diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index a9ed6510f..68804bb08 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -916,6 +916,10 @@ enum { /* WNM-Notification WFA vendors specific subtypes */ #define HS20_WNM_SUB_REM_NEEDED 0 +#define HS20_WNM_DEAUTH_IMMINENT_NOTICE 1 + +#define HS20_DEAUTH_REASON_CODE_BSS 0 +#define HS20_DEAUTH_REASON_CODE_ESS 1 /* Wi-Fi Direct (P2P) */ diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 54f59b12e..7ba499568 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -169,6 +169,7 @@ extern "C" { #define GAS_QUERY_DONE "GAS-QUERY-DONE " #define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION " +#define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE " #define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START " #define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT " diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index d419ffb47..456ba61ff 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -14,10 +14,12 @@ #include "common/ieee802_11_defs.h" #include "common/gas.h" #include "common/wpa_ctrl.h" +#include "rsn_supp/wpa.h" #include "wpa_supplicant_i.h" #include "driver_i.h" #include "config.h" #include "bss.h" +#include "blacklist.h" #include "gas_query.h" #include "interworking.h" #include "hs20_supplicant.h" @@ -246,3 +248,33 @@ void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s, else wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION); } + + +void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code, + u16 reauth_delay, const char *url) +{ + if (!wpa_sm_pmf_enabled(wpa_s->wpa)) { + wpa_printf(MSG_DEBUG, "HS 2.0: Ignore deauthentication imminent notice since PMF was not enabled"); + return; + } + + wpa_msg(wpa_s, MSG_INFO, HS20_DEAUTH_IMMINENT_NOTICE "%u %u %s", + code, reauth_delay, url); + + if (code == HS20_DEAUTH_REASON_CODE_BSS) { + wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to blacklist"); + wpa_blacklist_add(wpa_s, wpa_s->bssid); + } + + if (code == HS20_DEAUTH_REASON_CODE_ESS && wpa_s->current_ssid) { + struct os_time now; + os_get_time(&now); + if (now.sec + reauth_delay <= + wpa_s->current_ssid->disabled_until.sec) + return; + wpa_printf(MSG_DEBUG, "HS 2.0: Disable network for %u seconds", + reauth_delay); + wpa_s->current_ssid->disabled_until.sec = + now.sec + reauth_delay; + } +} diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h index b19355bc1..eb24b7427 100644 --- a/wpa_supplicant/hs20_supplicant.h +++ b/wpa_supplicant/hs20_supplicant.h @@ -22,5 +22,7 @@ int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s, const char *url, u8 osu_method); +void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code, + u16 reauth_delay, const char *url); #endif /* HS20_SUPPLICANT_H */ diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index 9b7bfa704..0619f6db3 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -756,7 +756,7 @@ static void ieee802_11_rx_wnm_notif_req_wfa(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *data, int len) { - const u8 *pos, *end; + const u8 *pos, *end, *next; u8 ie, ie_len; pos = data; @@ -772,6 +772,13 @@ static void ieee802_11_rx_wnm_notif_req_wfa(struct wpa_supplicant *wpa_s, "subelement"); break; } + next = pos + ie_len; + if (ie_len < 4) { + pos = next; + continue; + } + wpa_printf(MSG_DEBUG, "WNM: Subelement OUI %06x type %u", + WPA_GET_BE24(pos), pos[3]); #ifdef CONFIG_HS20 if (ie == WLAN_EID_VENDOR_SPECIFIC && ie_len >= 5 && @@ -809,11 +816,45 @@ static void ieee802_11_rx_wnm_notif_req_wfa(struct wpa_supplicant *wpa_s, hs20_rx_subscription_remediation(wpa_s, url, osu_method); os_free(url); - break; + pos = next; + continue; + } + + if (ie == WLAN_EID_VENDOR_SPECIFIC && ie_len >= 8 && + WPA_GET_BE24(pos) == OUI_WFA && + pos[3] == HS20_WNM_DEAUTH_IMMINENT_NOTICE) { + const u8 *ie_end; + u8 url_len; + char *url; + u8 code; + u16 reauth_delay; + + ie_end = pos + ie_len; + pos += 4; + code = *pos++; + reauth_delay = WPA_GET_LE16(pos); + pos += 2; + url_len = *pos++; + wpa_printf(MSG_DEBUG, "WNM: HS 2.0 Deauthentication " + "Imminent - Reason Code %u " + "Re-Auth Delay %u URL Length %u", + code, reauth_delay, url_len); + if (pos + url_len > ie_end) + break; + url = os_malloc(url_len + 1); + if (url == NULL) + break; + os_memcpy(url, pos, url_len); + url[url_len] = '\0'; + hs20_rx_deauth_imminent_notice(wpa_s, code, + reauth_delay, url); + os_free(url); + pos = next; + continue; } #endif /* CONFIG_HS20 */ - pos += ie_len; + pos = next; } } diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 07a334a54..1871a2802 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -3183,6 +3183,8 @@ static void wpa_cli_action_process(const char *msg) wpa_cli_exec(action_file, ctrl_ifname, pos); } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) { wpa_cli_exec(action_file, ctrl_ifname, pos); + } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) { + wpa_cli_exec(action_file, ctrl_ifname, pos); } else if (str_match(pos, WPA_EVENT_TERMINATING)) { printf("wpa_supplicant is terminating - stop monitoring\n"); wpa_cli_quit = 1;