From d7c3347f595f2b75b4e5a93c7219539779b6d1e1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 31 Dec 2015 21:46:08 +0200 Subject: [PATCH] HS 2.0: Postpone WNM-Notification sending by 100 ms This makes it somewhat easier for the station to be able to receive and process the encrypted WNM-Notification frames that the AP previously sentt immediately after receiving EAPOL-Key msg 4/4. While the station is supposed to have the TK configured for receive before sending out EAPOL-Key msg 4/4, not many actual implementations do that. As such, there is a race condition in being able to configure the key at the station and the AP sending out the first encrypted frame after EAPOL-Key 4/4. The extra 100 ms time here makes it more likely for the station to have managed to configure the key in time. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 2 +- src/ap/ieee802_1x.c | 67 +++++++++++++++++++++++++++++---------------- src/ap/ieee802_1x.h | 2 +- src/ap/sta_info.c | 8 +++--- 4 files changed, 50 insertions(+), 29 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 01b514eee..54cd698aa 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -2010,7 +2010,7 @@ static void handle_disassoc(struct hostapd_data *hapd, /* Stop Accounting and IEEE 802.1X sessions, but leave the STA * authenticated. */ accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); + ieee802_1x_free_station(hapd, sta); if (sta->ipaddr) hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); ap_sta_ip6addr_del(hapd, sta); diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index e3b3d94e5..607f94187 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -34,6 +34,9 @@ #include "ieee802_1x.h" +#ifdef CONFIG_HS20 +static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx); +#endif /* CONFIG_HS20 */ static void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta, int success, int remediation); @@ -1048,7 +1051,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) * Clear any possible EAPOL authenticator state to support * reassociation change from WPS to PSK. */ - ieee802_1x_free_station(sta); + ieee802_1x_free_station(hapd, sta); return; } @@ -1059,7 +1062,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) * Clear any possible EAPOL authenticator state to support * reassociation change from WPA-EAP to PSK. */ - ieee802_1x_free_station(sta); + ieee802_1x_free_station(hapd, sta); return; } @@ -1146,10 +1149,14 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) } -void ieee802_1x_free_station(struct sta_info *sta) +void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta) { struct eapol_state_machine *sm = sta->eapol_sm; +#ifdef CONFIG_HS20 + eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta); +#endif /* CONFIG_HS20 */ + if (sm == NULL) return; @@ -2528,6 +2535,34 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, } +#ifdef CONFIG_HS20 +static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + + if (sta->remediation) { + wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " + MACSTR " to indicate Subscription Remediation", + MAC2STR(sta->addr)); + hs20_send_wnm_notification(hapd, sta->addr, + sta->remediation_method, + sta->remediation_url); + os_free(sta->remediation_url); + sta->remediation_url = NULL; + } + + if (sta->hs20_deauth_req) { + wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " + MACSTR " to indicate imminent deauthentication", + MAC2STR(sta->addr)); + hs20_send_wnm_notification_deauth_req(hapd, sta->addr, + sta->hs20_deauth_req); + } +} +#endif /* CONFIG_HS20 */ + + static void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta, int success, int remediation) @@ -2547,26 +2582,12 @@ static void ieee802_1x_finished(struct hostapd_data *hapd, sta->remediation_method = 1; /* SOAP-XML SPP */ } - if (success) { - if (sta->remediation) { - wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification " - "to " MACSTR " to indicate Subscription " - "Remediation", - MAC2STR(sta->addr)); - hs20_send_wnm_notification(hapd, sta->addr, - sta->remediation_method, - sta->remediation_url); - os_free(sta->remediation_url); - sta->remediation_url = NULL; - } - - if (sta->hs20_deauth_req) { - wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification " - "to " MACSTR " to indicate imminent " - "deauthentication", MAC2STR(sta->addr)); - hs20_send_wnm_notification_deauth_req( - hapd, sta->addr, sta->hs20_deauth_req); - } + if (success && (sta->remediation || sta->hs20_deauth_req)) { + wpa_printf(MSG_DEBUG, "HS 2.0: Schedule WNM-Notification to " + MACSTR " in 100 ms", MAC2STR(sta->addr)); + eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta); + eloop_register_timeout(0, 100000, ieee802_1x_wnm_notif_send, + hapd, sta); } #endif /* CONFIG_HS20 */ diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h index 14d695569..ec8019900 100644 --- a/src/ap/ieee802_1x.h +++ b/src/ap/ieee802_1x.h @@ -21,7 +21,7 @@ struct radius_msg; void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, size_t len); void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta); -void ieee802_1x_free_station(struct sta_info *sta); +void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta); void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta); void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 500beff31..68fff4cf9 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -253,7 +253,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); sae_clear_retransmit_timer(hapd, sta); - ieee802_1x_free_station(sta); + ieee802_1x_free_station(hapd, sta); wpa_auth_sta_deinit(sta->wpa_sm); rsn_preauth_free_station(hapd, sta); #ifndef CONFIG_NO_RADIUS @@ -487,7 +487,7 @@ skip_poll: sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); + ieee802_1x_free_station(hapd, sta); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated due to " "inactivity"); @@ -722,7 +722,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, ap_handle_timer, hapd, sta); accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); + ieee802_1x_free_station(hapd, sta); sta->disassoc_reason = reason; sta->flags |= WLAN_STA_PENDING_DISASSOC_CB; @@ -761,7 +761,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, ap_handle_timer, hapd, sta); accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); + ieee802_1x_free_station(hapd, sta); sta->deauth_reason = reason; sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;