Blame SOURCES/rh1490885-fix-auth-failure-when-the-mac-is-updated-externally.patch

8f4474
From 175c8ec5f46fbe544eb71b80d83ed517a3c81ba4 Mon Sep 17 00:00:00 2001
8f4474
From: Beniamino Galvani <bgalvani@redhat.com>
8f4474
Date: Thu, 15 Feb 2018 11:50:01 +0100
8f4474
Subject: [PATCH] wpa_supplicant: Fix auth failure when the MAC is updated
8f4474
 externally
8f4474
8f4474
When connecting to a WPA-EAP network and the MAC address is changed
8f4474
just before the association (for example by NetworkManager, which sets
8f4474
a random MAC during scans), the authentication sometimes fails in the
8f4474
following way ('####' logs added by me):
8f4474
8f4474
wpa_supplicant logs:
8f4474
 wlan0: WPA: RX message 1 of 4-Way Handshake from 02:00:00:00:01:00 (ver=1)
8f4474
 RSN: msg 1/4 key data - hexdump(len=22): dd 14 00 0f ac 04 d8 21 9d a5 73 98 88 26 ef 03 d2 ce f7 04 7d 23
8f4474
 WPA: PMKID in EAPOL-Key - hexdump(len=22): dd 14 00 0f ac 04 d8 21 9d a5 73 98 88 26 ef 03 d2 ce f7 04 7d 23
8f4474
 RSN: PMKID from Authenticator - hexdump(len=16): d8 21 9d a5 73 98 88 26 ef 03 d2 ce f7 04 7d 23
8f4474
 wlan0: RSN: no matching PMKID found
8f4474
 EAPOL: Successfully fetched key (len=32)
8f4474
 WPA: PMK from EAPOL state machines - hexdump(len=32): [REMOVED]
8f4474
 #### WPA: rsn_pmkid():
8f4474
 #### WPA: aa              - hexdump(len=6): 02 00 00 00 01 00
8f4474
 #### WPA: spa             - hexdump(len=6): 66 20 cf ab 8c dc
8f4474
 #### WPA: PMK             - hexdump(len=32): b5 24 76 4f 6f 50 8c f6 a1 2e 24 b8 07 4e 9a 13 1b 94 c4 a8 1f 7e 22 d6 ed fc 7d 43 c7 77 b6 f7
8f4474
 #### WPA: computed PMKID  - hexdump(len=16): ea 73 67 b1 8e 5f 18 43 58 24 e8 1c 47 23 87 71
8f4474
 RSN: Replace PMKSA entry for the current AP and any PMKSA cache entry that was based on the old PMK
8f4474
 nl80211: Delete PMKID for 02:00:00:00:01:00
8f4474
 wlan0: RSN: PMKSA cache entry free_cb: 02:00:00:00:01:00 reason=1
8f4474
 RSN: Added PMKSA cache entry for 02:00:00:00:01:00 network_ctx=0x5630bf85a270
8f4474
 nl80211: Add PMKID for 02:00:00:00:01:00
8f4474
 wlan0: RSN: PMKID mismatch - authentication server may have derived different MSK?!
8f4474
8f4474
hostapd logs:
8f4474
 WPA: PMK from EAPOL state machine (MSK len=64 PMK len=32)
8f4474
 WPA: 02:00:00:00:00:00 WPA_PTK entering state PTKSTART
8f4474
 wlan1: STA 02:00:00:00:00:00 WPA: sending 1/4 msg of 4-Way Handshake
8f4474
 #### WPA: rsn_pmkid():
8f4474
 #### WPA: aa              - hexdump(len=6): 02 00 00 00 01 00
8f4474
 #### WPA: spa             - hexdump(len=6): 02 00 00 00 00 00
8f4474
 #### WPA: PMK             - hexdump(len=32): b5 24 76 4f 6f 50 8c f6 a1 2e 24 b8 07 4e 9a 13 1b 94 c4 a8 1f 7e 22 d6 ed fc 7d 43 c7 77 b6 f7
8f4474
 #### WPA: computed PMKID  - hexdump(len=16): d8 21 9d a5 73 98 88 26 ef 03 d2 ce f7 04 7d 23
8f4474
 WPA: Send EAPOL(version=1 secure=0 mic=0 ack=1 install=0 pairwise=1 kde_len=22 keyidx=0 encr=0)
8f4474
8f4474
That's because wpa_supplicant computed the PMKID using the wrong (old)
8f4474
MAC address used during the scan. wpa_supplicant updates own_addr when
8f4474
the interface goes up, as the MAC can only change while the interface
8f4474
is down. However, drivers don't report all interface state changes:
8f4474
for example the nl80211 driver may ignore a down-up cycle if the down
8f4474
message is processed later, when the interface is already up. In such
8f4474
cases, wpa_supplicant (and in particular, the EAP state machine) would
8f4474
continue to use the old MAC.
8f4474
8f4474
Add a new driver event that notifies of MAC address changes while the
8f4474
interface is active.
8f4474
8f4474
Signed-off-by: Beniamino Galvani <bgalvani@redhat.com>
8f4474
(cherry picked from commit 77a020a118168e05e7cc0d28a7bf661772e531af)
8f4474
---
8f4474
 src/drivers/driver.h         |  9 +++++++++
8f4474
 src/drivers/driver_common.c  |  1 +
8f4474
 src/drivers/driver_nl80211.c | 11 +++++++----
8f4474
 wpa_supplicant/events.c      |  3 +++
8f4474
 4 files changed, 20 insertions(+), 4 deletions(-)
8f4474
8f4474
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
8f4474
index df996dc21..f8d556133 100644
8f4474
--- a/src/drivers/driver.h
8f4474
+++ b/src/drivers/driver.h
8f4474
@@ -4106,6 +4106,15 @@ enum wpa_event_type {
8f4474
 	 * EVENT_P2P_LO_STOP - Notify that P2P listen offload is stopped
8f4474
 	 */
8f4474
 	EVENT_P2P_LO_STOP,
8f4474
+
8f4474
+	/**
8f4474
+	 * EVENT_INTERFACE_MAC_CHANGED - Notify that interface MAC changed
8f4474
+	 *
8f4474
+	 * This event is emitted when the MAC changes while the interface is
8f4474
+	 * enabled. When an interface was disabled and becomes enabled, it
8f4474
+	 * must be always assumed that the MAC possibly changed.
8f4474
+	 */
8f4474
+	EVENT_INTERFACE_MAC_CHANGED,
8f4474
 };
8f4474
 
8f4474
 
8f4474
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
8f4474
index c7107ba89..bdddc0a48 100644
8f4474
--- a/src/drivers/driver_common.c
8f4474
+++ b/src/drivers/driver_common.c
8f4474
@@ -81,6 +81,7 @@ const char * event_to_string(enum wpa_event_type event)
8f4474
 	E2S(ACS_CHANNEL_SELECTED);
8f4474
 	E2S(DFS_CAC_STARTED);
8f4474
 	E2S(P2P_LO_STOP);
8f4474
+	E2S(INTERFACE_MAC_CHANGED);
8f4474
 	}
8f4474
 
8f4474
 	return "UNKNOWN";
8f4474
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
8f4474
index f7f3cfebc..d4a879836 100644
8f4474
--- a/src/drivers/driver_nl80211.c
8f4474
+++ b/src/drivers/driver_nl80211.c
8f4474
@@ -923,7 +923,7 @@ nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
8f4474
 
8f4474
 
8f4474
 static void nl80211_refresh_mac(struct wpa_driver_nl80211_data *drv,
8f4474
-				int ifindex)
8f4474
+				int ifindex, int notify)
8f4474
 {
8f4474
 	struct i802_bss *bss;
8f4474
 	u8 addr[ETH_ALEN];
8f4474
@@ -942,6 +942,9 @@ static void nl80211_refresh_mac(struct wpa_driver_nl80211_data *drv,
8f4474
 			   ifindex, bss->ifname,
8f4474
 			   MAC2STR(bss->addr), MAC2STR(addr));
8f4474
 		os_memcpy(bss->addr, addr, ETH_ALEN);
8f4474
+		if (notify)
8f4474
+			wpa_supplicant_event(drv->ctx,
8f4474
+					     EVENT_INTERFACE_MAC_CHANGED, NULL);
8f4474
 	}
8f4474
 }
8f4474
 
8f4474
@@ -1010,11 +1013,11 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
8f4474
 		namebuf[0] = '\0';
8f4474
 		if (if_indextoname(ifi->ifi_index, namebuf) &&
8f4474
 		    linux_iface_up(drv->global->ioctl_sock, namebuf) > 0) {
8f4474
-			/* Re-read MAC address as it may have changed */
8f4474
-			nl80211_refresh_mac(drv, ifi->ifi_index);
8f4474
 			wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
8f4474
 				   "event since interface %s is up", namebuf);
8f4474
 			drv->ignore_if_down_event = 0;
8f4474
+			/* Re-read MAC address as it may have changed */
8f4474
+			nl80211_refresh_mac(drv, ifi->ifi_index, 1);
8f4474
 			return;
8f4474
 		}
8f4474
 		wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
8f4474
@@ -1060,7 +1063,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
8f4474
 				   "removed", drv->first_bss->ifname);
8f4474
 		} else {
8f4474
 			/* Re-read MAC address as it may have changed */
8f4474
-			nl80211_refresh_mac(drv, ifi->ifi_index);
8f4474
+			nl80211_refresh_mac(drv, ifi->ifi_index, 0);
8f4474
 
8f4474
 			wpa_printf(MSG_DEBUG, "nl80211: Interface up");
8f4474
 			drv->if_disabled = 0;
8f4474
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
8f4474
index 4dc044c2b..6eb35104c 100644
8f4474
--- a/wpa_supplicant/events.c
8f4474
+++ b/wpa_supplicant/events.c
8f4474
@@ -3927,6 +3927,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
8f4474
 			data->signal_change.current_noise,
8f4474
 			data->signal_change.current_txrate);
8f4474
 		break;
8f4474
+	case EVENT_INTERFACE_MAC_CHANGED:
8f4474
+		wpa_supplicant_update_mac_addr(wpa_s);
8f4474
+		break;
8f4474
 	case EVENT_INTERFACE_ENABLED:
8f4474
 		wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
8f4474
 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
8f4474
-- 
8f4474
2.14.3
8f4474