]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Delete PMKID from driver when PMKSA entry is freed in Authenticator
authorHu Wang <huw@qti.qualcomm.com>
Fri, 30 May 2025 03:24:24 +0000 (20:24 -0700)
committerJouni Malinen <j@w1.fi>
Sat, 7 Jun 2025 13:34:05 +0000 (16:34 +0300)
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 <jouni.malinen@oss.qualcomm.com>
src/ap/ap_drv_ops.c
src/ap/ap_drv_ops.h
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_glue.c

index 0bcc83d8b72ff32fe491af09c9e3b7bd9b1fd257..aeae0af20abc46744559bb8514435411e00ab033 100644 (file)
@@ -1392,3 +1392,25 @@ int hostapd_add_pmkid(struct hostapd_data *hapd, const u8 *bssid, const u8 *pmk,
 
        return hostapd_drv_add_pmkid(hapd, &params);
 }
+
+
+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(&params, 0, sizeof(params));
+       params.bssid = sta_addr;
+       params.pmkid = pmkid;
+
+       return hostapd_drv_remove_pmkid(hapd, &params);
+}
index b52763628a7d1bd08a1a533bd9962b2bec6ba1f7..1468697eda32fa927101b25c3bb163e77367bf21 100644 (file)
@@ -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 */
index f2330bc9d4b47f5e7f58d16f0cd7c7e23f207d0c..3f82bae7bb378d77d9496c2a9cc7d941a7d7a9b9 100644 (file)
@@ -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);
 }
 
 
index c412633cd719e913e8f8b64a618a5fc09c8dea01..a98a0448721a8e86ae452a1e612ff26342f566bc 100644 (file)
@@ -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,
index d30e9ef3b0f0d92272593348690cc4815f38098d..519948a518c2c57c04162173c7118502eb8d52ba 100644 (file)
@@ -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;