From: Hu Wang Date: Fri, 30 May 2025 03:24:24 +0000 (-0700) Subject: Delete PMKID from driver when PMKSA entry is freed in Authenticator X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=849bce56e8b84b76e1582aac6852f2ef369d0796;p=thirdparty%2Fhostap.git Delete PMKID from driver when PMKSA entry is freed in Authenticator For SME-in-driver, external SAE authentication (i.e., the driver offloading SAE processing to hostapd) the PMKID is configured to the driver on successful completion, but this is not cleared when hostapd frees its PMKSA entry. This causes the driver and hostapd to get out of sync. This can result in the driver accepting an association with an unknown (to hostapd) PMKID, but hostapd ending up using Deauthentication frame due to that unknown PMKID. iPhone as a client seems to only clear its PMKSA entry based on with asssociation rejection and thus, it might retry again and again with the same unknown-to-hostapd PMKID. Remove the PMKID from the driver when the matching PMKSA is remove from hostapd to avoid this. Signed-off-by: Jouni Malinen --- diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 0bcc83d8b..aeae0af20 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -1392,3 +1392,25 @@ int hostapd_add_pmkid(struct hostapd_data *hapd, const u8 *bssid, const u8 *pmk, return hostapd_drv_add_pmkid(hapd, ¶ms); } + + +static int hostapd_drv_remove_pmkid(struct hostapd_data *hapd, + struct wpa_pmkid_params *params) +{ + if (!hapd->driver || !hapd->driver->remove_pmkid || !hapd->drv_priv) + return 0; + return hapd->driver->remove_pmkid(hapd->drv_priv, params); +} + + +int hostapd_remove_pmkid(struct hostapd_data *hapd, const u8 *sta_addr, + const u8 *pmkid) +{ + struct wpa_pmkid_params params; + + os_memset(¶ms, 0, sizeof(params)); + params.bssid = sta_addr; + params.pmkid = pmkid; + + return hostapd_drv_remove_pmkid(hapd, ¶ms); +} diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index b52763628..1468697ed 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -492,5 +492,7 @@ int hostapd_drv_add_pmkid(struct hostapd_data *hapd, struct wpa_pmkid_params *params); int hostapd_add_pmkid(struct hostapd_data *hapd, const u8 *bssid, const u8 *pmk, size_t pmk_len, const u8 *pmkid, int akmp); +int hostapd_remove_pmkid(struct hostapd_data *hapd, const u8 *sta_addr, + const u8 *pmkid); #endif /* AP_DRV_OPS */ diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index f2330bc9d..3f82bae7b 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -657,6 +657,12 @@ static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, { struct wpa_authenticator *wpa_auth = ctx; wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry); + + /* Remove matching PMKID from the driver, if it had been added, e.g., + * by external SAE authentication */ + if (wpa_auth->cb->remove_pmkid) + wpa_auth->cb->remove_pmkid(wpa_auth->cb_ctx, entry->spa, + entry->pmkid); } diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index c412633cd..a98a04487 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -431,6 +431,7 @@ struct wpa_auth_callbacks { struct wpa_authenticator * (*next_primary_auth)(void *ctx); #endif /* CONFIG_IEEE80211BE */ int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2); + int (*remove_pmkid)(void *ctx, const u8 *sta_addr, const u8 *pmkid); }; struct wpa_authenticator * wpa_init(const u8 *addr, diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index d30e9ef3b..519948a51 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1663,6 +1663,15 @@ static int hostapd_wpa_auth_get_drv_flags(void *ctx, } +static int hostapd_wpa_auth_remove_pmkid(void *ctx, const u8 *sta_addr, + const u8 *pmkid) +{ + struct hostapd_data *hapd = ctx; + + return hostapd_remove_pmkid(hapd, sta_addr, pmkid); +} + + int hostapd_setup_wpa(struct hostapd_data *hapd) { struct wpa_auth_config _conf; @@ -1718,6 +1727,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) .next_primary_auth = hostapd_next_primary_auth, #endif /* CONFIG_IEEE80211BE */ .get_drv_flags = hostapd_wpa_auth_get_drv_flags, + .remove_pmkid = hostapd_wpa_auth_remove_pmkid, }; const u8 *wpa_ie; size_t wpa_ie_len;