[RFC PATCH] fix MAC address spoofing issues

Dan Williams dcbw at redhat.com
Fri Nov 19 16:52:22 EST 2010


This patch is from Jirka Klimes, developed to fix various issues when
spoofing MAC addresses.  Does this approach look workable?  If you have
specific questions about the issues he encountered I'm sure he could
elaborate.  But part of the problem was that if the MAC address gets
changed without removing and re-adding the interface to the supplicant,
it gets some upper-layer stuff wrong.  But removing and re-adding is a
pretty heavy operation that we don't want to do often.  In a more
dynamic environment you may want to spoof a MAC on one wifi network but
not on another, and in that case a managed like NM just switches the MAC
address of the interface (while the interface is in the disconnected
state) and then tells the supplicant to connect.

Thoughts?

Dan

---

--- ./src/l2_packet/l2_packet.h	2009-02-15 19:00:00.000000000 +0100
+++ /tmp/wpa_supplicant-0.6.8//src/l2_packet/l2_packet.h	2010-06-15 15:46:10.166287859 +0200
@@ -113,6 +113,17 @@
  */
 int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len);
 
+/**
+ * l2_packet_update_own_addr - Update own layer 2 address from the interface
+ * @l2: Pointer to internal l2_packet data from l2_packet_init()
+ * Returns: 0 on success, -1 on failure
+ 
+ * This function can be used to update the current MAC address in l2_packet_data
+ * structure from the interface bound to the l2_packet. This is mainly useful
+ * for updating MAC address before association to have valid address for use in
+ * key derivation for WPA.
+ */
+int l2_packet_update_own_addr(struct l2_packet_data *l2);
 
 /**
  * l2_packet_notify_auth_start - Notify l2_packet about start of authentication
--- ./src/l2_packet/l2_packet_freebsd.c	2009-02-15 19:00:00.000000000 +0100
+++ /tmp/wpa_supplicant-0.6.8//src/l2_packet/l2_packet_freebsd.c	2010-06-15 15:31:30.051410151 +0200
@@ -280,6 +280,18 @@
 }
 
 
+int l2_packet_update_own_addr(struct l2_packet_data *l2)
+{
+	if (eth_get(l2->ifname, l2->own_addr) < 0) {
+		fprintf(stderr, "Failed to get link-level address for "
+			"interface '%s'.\n", l2->ifname);
+		return -1;
+	}
+
+	return 0;
+}
+
+
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 }
--- ./src/l2_packet/l2_packet_linux.c	2009-02-15 19:00:00.000000000 +0100
+++ /tmp/wpa_supplicant-0.6.8//src/l2_packet/l2_packet_linux.c	2010-06-15 15:31:30.052410290 +0200
@@ -194,6 +194,33 @@
 }
 
 
+int l2_packet_update_own_addr(struct l2_packet_data *l2)
+{
+	struct ifreq ifr;
+
+	if (l2 == NULL) {
+		fprintf(stderr, "l2_packet_init() not called previously");
+		return -1;
+	}
+
+	if (l2->fd < 0) {
+		fprintf(stderr, "Socket not available");
+		return -1;
+	}
+
+	os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
+        if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) >= 0) {
+		os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+		wpa_printf(MSG_DEBUG, "Updated own MAC address: " MACSTR, MAC2STR(l2->own_addr));
+	} else {
+                perror("ioctl[SIOCGIFHWADDR]");
+		return -1;
+	}
+
+	return 0;
+}
+
+
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 }
--- ./src/l2_packet/l2_packet_ndis.c	2009-02-15 19:00:00.000000000 +0100
+++ /tmp/wpa_supplicant-0.6.8//src/l2_packet/l2_packet_ndis.c	2010-06-15 15:55:34.505743362 +0200
@@ -511,6 +511,12 @@
 }
 
 
+int l2_packet_update_own_addr(struct l2_packet_data *l2)
+{
+	return -1;
+}
+
+
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 }
--- ./src/l2_packet/l2_packet_none.c	2009-02-15 19:00:00.000000000 +0100
+++ /tmp/wpa_supplicant-0.6.8//src/l2_packet/l2_packet_none.c	2010-06-15 15:56:29.332896326 +0200
@@ -117,6 +117,12 @@
 }
 
 
+int l2_packet_update_own_addr(struct l2_packet_data *l2)
+{
+	return -1;
+}
+
+
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 	/* This function can be left empty */
--- ./src/l2_packet/l2_packet_pcap.c	2009-02-15 19:00:00.000000000 +0100
+++ /tmp/wpa_supplicant-0.6.8//src/l2_packet/l2_packet_pcap.c	2010-06-15 15:31:30.052410290 +0200
@@ -371,6 +371,29 @@
 }
 
 
+int l2_packet_update_own_addr(struct l2_packet_data *l2)
+{
+	eth_addr_t own_addr;
+
+#ifdef CONFIG_WINPCAP
+	return -1;
+#else /* CONFIG_WINPCAP */
+	if (!l2->eth) {
+		fprintf(stderr, "Interface not opened '%s'.\n", l2->ifname);
+		return -1;
+	}
+	if (eth_get(l2->eth, &own_addr) < 0) {
+		printf("Failed to get own hw address from interface '%s'.\n",
+		       l2->ifname);
+		perror("eth_get");
+		return -1;
+	}
+	os_memcpy(l2->own_addr, own_addr.data, ETH_ALEN);
+	return 0;
+#endif /* CONFIG_WINPCAP */
+}
+
+
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 #ifdef CONFIG_WINPCAP
--- ./src/l2_packet/l2_packet_privsep.c	2009-02-15 19:00:00.000000000 +0100
+++ /tmp/wpa_supplicant-0.6.8//src/l2_packet/l2_packet_privsep.c	2010-06-15 15:57:26.393498291 +0200
@@ -261,6 +261,13 @@
 }
 
 
+int l2_packet_update_own_addr(struct l2_packet_data *l2)
+{
+	/* TODO */
+	return -1;
+}
+
+
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 	wpa_priv_cmd(l2, PRIVSEP_CMD_L2_NOTIFY_AUTH_START, NULL, 0);
--- ./src/l2_packet/l2_packet_winpcap.c	2009-02-15 19:00:00.000000000 +0100
+++ /tmp/wpa_supplicant-0.6.8//src/l2_packet/l2_packet_winpcap.c	2010-06-15 15:31:30.051410151 +0200
@@ -334,6 +334,12 @@
 }
 
 
+int l2_packet_update_own_addr(struct l2_packet_data *l2, u8 *addr)
+{
+	return -1;
+}
+
+
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 	if (l2)
--- ./wpa_supplicant/wpa_supplicant.c	2010-06-15 15:35:19.840285762 +0200
+++ /tmp/wpa_supplicant-0.6.8//wpa_supplicant/wpa_supplicant.c	2010-06-15 16:46:50.213287240 +0200
@@ -949,6 +949,28 @@
 	struct wpa_driver_capa capa;
 	int assoc_failed = 0;
 
+	/* Update own MAC address before associating */
+	if (wpa_s->driver->send_eapol) {
+		const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
+		if (addr) {
+			os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
+			wpa_sm_set_own_addr(wpa_s->wpa, addr);
+		}
+	} else {
+		if (l2_packet_update_own_addr(wpa_s->l2) == 0) {
+			l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr);
+			wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
+		} else {
+			const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
+			if (addr) {
+				wpa_printf(MSG_DEBUG, "Updating own MAC failed; setting it according driver data structure: " MACSTR,
+				           MAC2STR(addr));
+				os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
+				wpa_sm_set_own_addr(wpa_s->wpa, addr);
+			}
+		}
+	}
+
 	wpa_s->reassociate = 0;
 	if (bss) {
 #ifdef CONFIG_IEEE80211R



More information about the HostAP mailing list