From: Rameshkumar Sundaram Date: Thu, 3 Apr 2025 06:54:10 +0000 (+0530) Subject: AP MLD: Avoid reusing ML wpa state machine for non-ML STA X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9603a83a1e3f07c4c0705b64e0b5bac27449749d;p=thirdparty%2Fhostap.git AP MLD: Avoid reusing ML wpa state machine for non-ML STA When a STA tries to associate as an MLD initially but doesn't complete EAPOL due to some reason and reassociates (with the same MAC address) as a non-ML STA, EAPOL 2/4 fails during MIC verification. This is because the wpa_state_machine(sta->wpa_sm) is created when the STA first associates as an ML STA and sm->mld_assoc_link_id is set. Now when the STA reassociates in non-ML mode (sends Authentication and Association Request frames without an MLE) the previous STA instance as well as its previously created wpa_sm will be reused and hence AP MLD's MLD MAC address is used as AA to derive PTK. To fix this, reset the sta->wpa_sm if a non MFP or non authorized STA tries to reassociate. Also since now sm object is freed directly (without ap_free_sta()), reset valid flag and release group references for all links. Signed-off-by: Rameshkumar Sundaram --- diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index ccc82d046..7d207fcde 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3377,6 +3377,12 @@ static void handle_auth(struct hostapd_data *hapd, if (!sta->added_unassoc && auth_transaction == 1) { ap_sta_free_sta_profile(&sta->mld_info); os_memset(&sta->mld_info, 0, sizeof(sta->mld_info)); + if ((!(sta->flags & WLAN_STA_MFP) || + !ap_sta_is_authorized(sta)) && sta->wpa_sm) { + wpa_auth_sta_deinit(sta->wpa_sm); + sta->wpa_sm = NULL; + clear_wpa_sm_for_each_partner_link(hapd, sta); + } if (mld_sta) { u8 link_id = hapd->mld_link_id; diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index cfc2082b6..f78820813 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -202,8 +202,8 @@ static void __ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) #ifdef CONFIG_IEEE80211BE -static void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd, - struct sta_info *psta) +void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd, + struct sta_info *psta) { struct sta_info *lsta; struct hostapd_data *lhapd; diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 1730742a9..9a8f4068a 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -431,5 +431,7 @@ static inline void ap_sta_set_mld(struct sta_info *sta, bool mld) void ap_sta_free_sta_profile(struct mld_info *info); void hostapd_free_link_stas(struct hostapd_data *hapd); +void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd, + struct sta_info *psta); #endif /* STA_INFO_H */ diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index d337020d6..a27a66a07 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1115,8 +1115,14 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) os_free(sm->rsnxe); os_free(sm->rsn_selection); #ifdef CONFIG_IEEE80211BE - for_each_sm_auth(sm, link_id) + for_each_sm_auth(sm, link_id) { + struct wpa_authenticator *wpa_auth; + + wpa_auth = sm->mld_links[link_id].wpa_auth; sm->mld_links[link_id].wpa_auth = NULL; + sm->mld_links[link_id].valid = false; + wpa_group_put(wpa_auth, wpa_auth->group); + } #endif /* CONFIG_IEEE80211BE */ wpa_group_put(sm->wpa_auth, sm->group); #ifdef CONFIG_DPP2