wpa_supplicant: Fix auth failure when the MAC is updated externally
When connecting to a WPA-EAP network and the MAC address is changed just before the association (for example by NetworkManager, which sets a random MAC during scans), the authentication sometimes fails in the following way ('####' logs added by me): wpa_supplicant logs: wlan0: WPA: RX message 1 of 4-Way Handshake from 02:00:00:00:01:00 (ver=1) 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 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 RSN: PMKID from Authenticator - hexdump(len=16): d8 21 9d a5 73 98 88 26 ef 03 d2 ce f7 04 7d 23 wlan0: RSN: no matching PMKID found EAPOL: Successfully fetched key (len=32) WPA: PMK from EAPOL state machines - hexdump(len=32): [REMOVED] #### WPA: rsn_pmkid(): #### WPA: aa - hexdump(len=6): 02 00 00 00 01 00 #### WPA: spa - hexdump(len=6): 66 20 cf ab 8c dc #### 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 #### WPA: computed PMKID - hexdump(len=16): ea 73 67 b1 8e 5f 18 43 58 24 e8 1c 47 23 87 71 RSN: Replace PMKSA entry for the current AP and any PMKSA cache entry that was based on the old PMK nl80211: Delete PMKID for 02:00:00:00:01:00 wlan0: RSN: PMKSA cache entry free_cb: 02:00:00:00:01:00 reason=1 RSN: Added PMKSA cache entry for 02:00:00:00:01:00 network_ctx=0x5630bf85a270 nl80211: Add PMKID for 02:00:00:00:01:00 wlan0: RSN: PMKID mismatch - authentication server may have derived different MSK?! hostapd logs: WPA: PMK from EAPOL state machine (MSK len=64 PMK len=32) WPA: 02:00:00:00:00:00 WPA_PTK entering state PTKSTART wlan1: STA 02:00:00:00:00:00 WPA: sending 1/4 msg of 4-Way Handshake #### WPA: rsn_pmkid(): #### WPA: aa - hexdump(len=6): 02 00 00 00 01 00 #### WPA: spa - hexdump(len=6): 02 00 00 00 00 00 #### 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 #### WPA: computed PMKID - hexdump(len=16): d8 21 9d a5 73 98 88 26 ef 03 d2 ce f7 04 7d 23 WPA: Send EAPOL(version=1 secure=0 mic=0 ack=1 install=0 pairwise=1 kde_len=22 keyidx=0 encr=0) That's because wpa_supplicant computed the PMKID using the wrong (old) MAC address used during the scan. wpa_supplicant updates own_addr when the interface goes up, as the MAC can only change while the interface is down. However, drivers don't report all interface state changes: for example the nl80211 driver may ignore a down-up cycle if the down message is processed later, when the interface is already up. In such cases, wpa_supplicant (and in particular, the EAP state machine) would continue to use the old MAC. Add a new driver event that notifies of MAC address changes while the interface is active. Signed-off-by: Beniamino Galvani <bgalvani@redhat.com>
This commit is contained in:
parent
2ff9696d3b
commit
77a020a118
4 changed files with 20 additions and 4 deletions
|
@ -4585,6 +4585,15 @@ enum wpa_event_type {
|
||||||
* change event.
|
* change event.
|
||||||
*/
|
*/
|
||||||
EVENT_STATION_OPMODE_CHANGED,
|
EVENT_STATION_OPMODE_CHANGED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVENT_INTERFACE_MAC_CHANGED - Notify that interface MAC changed
|
||||||
|
*
|
||||||
|
* This event is emitted when the MAC changes while the interface is
|
||||||
|
* enabled. When an interface was disabled and becomes enabled, it
|
||||||
|
* must be always assumed that the MAC possibly changed.
|
||||||
|
*/
|
||||||
|
EVENT_INTERFACE_MAC_CHANGED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,7 @@ const char * event_to_string(enum wpa_event_type event)
|
||||||
E2S(EXTERNAL_AUTH);
|
E2S(EXTERNAL_AUTH);
|
||||||
E2S(PORT_AUTHORIZED);
|
E2S(PORT_AUTHORIZED);
|
||||||
E2S(STATION_OPMODE_CHANGED);
|
E2S(STATION_OPMODE_CHANGED);
|
||||||
|
E2S(INTERFACE_MAC_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
|
|
|
@ -951,7 +951,7 @@ nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len,
|
||||||
|
|
||||||
|
|
||||||
static void nl80211_refresh_mac(struct wpa_driver_nl80211_data *drv,
|
static void nl80211_refresh_mac(struct wpa_driver_nl80211_data *drv,
|
||||||
int ifindex)
|
int ifindex, int notify)
|
||||||
{
|
{
|
||||||
struct i802_bss *bss;
|
struct i802_bss *bss;
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
|
@ -970,6 +970,9 @@ static void nl80211_refresh_mac(struct wpa_driver_nl80211_data *drv,
|
||||||
ifindex, bss->ifname,
|
ifindex, bss->ifname,
|
||||||
MAC2STR(bss->addr), MAC2STR(addr));
|
MAC2STR(bss->addr), MAC2STR(addr));
|
||||||
os_memcpy(bss->addr, addr, ETH_ALEN);
|
os_memcpy(bss->addr, addr, ETH_ALEN);
|
||||||
|
if (notify)
|
||||||
|
wpa_supplicant_event(drv->ctx,
|
||||||
|
EVENT_INTERFACE_MAC_CHANGED, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1041,11 +1044,11 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
||||||
namebuf[0] = '\0';
|
namebuf[0] = '\0';
|
||||||
if (if_indextoname(ifi->ifi_index, namebuf) &&
|
if (if_indextoname(ifi->ifi_index, namebuf) &&
|
||||||
linux_iface_up(drv->global->ioctl_sock, namebuf) > 0) {
|
linux_iface_up(drv->global->ioctl_sock, namebuf) > 0) {
|
||||||
/* Re-read MAC address as it may have changed */
|
|
||||||
nl80211_refresh_mac(drv, ifi->ifi_index);
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
|
wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
|
||||||
"event since interface %s is up", namebuf);
|
"event since interface %s is up", namebuf);
|
||||||
drv->ignore_if_down_event = 0;
|
drv->ignore_if_down_event = 0;
|
||||||
|
/* Re-read MAC address as it may have changed */
|
||||||
|
nl80211_refresh_mac(drv, ifi->ifi_index, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
|
wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
|
||||||
|
@ -1091,7 +1094,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
||||||
"removed", drv->first_bss->ifname);
|
"removed", drv->first_bss->ifname);
|
||||||
} else {
|
} else {
|
||||||
/* Re-read MAC address as it may have changed */
|
/* Re-read MAC address as it may have changed */
|
||||||
nl80211_refresh_mac(drv, ifi->ifi_index);
|
nl80211_refresh_mac(drv, ifi->ifi_index, 0);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Interface up");
|
wpa_printf(MSG_DEBUG, "nl80211: Interface up");
|
||||||
drv->if_disabled = 0;
|
drv->if_disabled = 0;
|
||||||
|
|
|
@ -4374,6 +4374,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
data->signal_change.current_noise,
|
data->signal_change.current_noise,
|
||||||
data->signal_change.current_txrate);
|
data->signal_change.current_txrate);
|
||||||
break;
|
break;
|
||||||
|
case EVENT_INTERFACE_MAC_CHANGED:
|
||||||
|
wpa_supplicant_update_mac_addr(wpa_s);
|
||||||
|
break;
|
||||||
case EVENT_INTERFACE_ENABLED:
|
case EVENT_INTERFACE_ENABLED:
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
|
wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
|
||||||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
|
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
|
||||||
|
|
Loading…
Reference in a new issue