From 65c8633d90551a745e72e194a6ca98bbf60d6d0f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 24 Nov 2022 12:03:01 +0200 Subject: [PATCH] Allow a lower priority BSS to be tried after network disabling If a higher priority BSS has invalid security parameters, e.g., an invalid SAE password, and a lower priority BSS is discovered only after the local network profile has been temporarily disabled, the BSSID ignoring mechanism is not sufficient to allow the lower priority BSS to be tried and all consecutive attempts will continue to use the higher priority BSS. This might prevent connection in some unexpected cases with invalid network configuration. Extend BSSID ignoring mechanism to work in this type of a case by ignoring the BSSID that resulted in disabling the SSID temporarily during the first connection attempt after having re-enabled the SSID. This allows a lower priority BSS, if any is available in scan results, to be tried next to see if it might have working security parameters. Signed-off-by: Jouni Malinen --- wpa_supplicant/config_ssid.h | 8 ++++++++ wpa_supplicant/events.c | 6 +++--- wpa_supplicant/wpa_supplicant.c | 19 +++++++++++++++---- wpa_supplicant/wpa_supplicant_i.h | 3 ++- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index a8a81d79b..c77ffa11a 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -837,6 +837,14 @@ struct wpa_ssid { */ struct os_reltime disabled_until; + /** + * disabled_due_to - BSSID of the disabling failure + * + * This identifies the BSS that failed the connection attempt that + * resulted in the network being temporarily disabled. + */ + u8 disabled_due_to[ETH_ALEN]; + /** * parent_cred - Pointer to parent wpa_cred entry * diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 5af3b6177..35f3694a0 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2845,7 +2845,7 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s, if (!ssid->psk_set) { wpa_dbg(wpa_s, MSG_INFO, "No PSK available for association"); - wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE"); + wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL); return -1; } @@ -3895,7 +3895,7 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s, "pre-shared key may be incorrect"); if (wpas_p2p_4way_hs_failed(wpa_s) > 0) return; /* P2P group removed */ - wpas_auth_failed(wpa_s, "WRONG_KEY"); + wpas_auth_failed(wpa_s, "WRONG_KEY", prev_pending_bssid); #ifdef CONFIG_DPP2 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_AUTH_FAILURE); @@ -4399,7 +4399,7 @@ static void wpas_event_disconnect(struct wpa_supplicant *wpa_s, const u8 *addr, (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) && eapol_sm_failed(wpa_s->eapol))) && !wpa_s->eap_expected_failure)) - wpas_auth_failed(wpa_s, "AUTH_FAILED"); + wpas_auth_failed(wpa_s, "AUTH_FAILED", addr); #ifdef CONFIG_P2P if (deauth && reason_code > 0) { diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index f9409f56a..ab2e70b5d 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2011,7 +2011,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, if (!psk_set) { wpa_msg(wpa_s, MSG_INFO, "No PSK available for association"); - wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE"); + wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL); return -1; } #ifdef CONFIG_OWE @@ -7919,7 +7919,7 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) { wpa_printf(MSG_DEBUG, "Continuous association failures - " "consider temporary network disabling"); - wpas_auth_failed(wpa_s, "CONN_FAILED"); + wpas_auth_failed(wpa_s, "CONN_FAILED", bssid); } /* * Multiple consecutive connection failures mean that other APs are @@ -8266,7 +8266,8 @@ int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s) } -void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason) +void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason, + const u8 *bssid) { struct wpa_ssid *ssid = wpa_s->current_ssid; int dur; @@ -8323,6 +8324,9 @@ void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason) "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s", ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len), ssid->auth_failures, dur, reason); + + if (bssid) + os_memcpy(ssid->disabled_due_to, bssid, ETH_ALEN); } @@ -8339,8 +8343,15 @@ void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s, } ssid->disabled_until.sec = 0; ssid->disabled_until.usec = 0; - if (clear_failures) + if (clear_failures) { ssid->auth_failures = 0; + } else if (!is_zero_ether_addr(ssid->disabled_due_to)) { + wpa_printf(MSG_DEBUG, "Mark BSSID " MACSTR + " ignored to allow a lower priority BSS, if any, to be tried next", + MAC2STR(ssid->disabled_due_to)); + wpa_bssid_ignore_add(wpa_s, ssid->disabled_due_to); + os_memset(ssid->disabled_due_to, 0, ETH_ALEN); + } } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 3e35b9ca8..add24f07d 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1629,7 +1629,8 @@ void fils_connection_failure(struct wpa_supplicant *wpa_s); void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s); int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s); int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s); -void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason); +void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason, + const u8 *bssid); void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int clear_failures); int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid);