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 <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-11-24 12:03:01 +02:00 committed by Jouni Malinen
parent e91ac53d53
commit 65c8633d90
4 changed files with 28 additions and 8 deletions

View file

@ -837,6 +837,14 @@ struct wpa_ssid {
*/ */
struct os_reltime disabled_until; 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 * parent_cred - Pointer to parent wpa_cred entry
* *

View file

@ -2845,7 +2845,7 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
if (!ssid->psk_set) { if (!ssid->psk_set) {
wpa_dbg(wpa_s, MSG_INFO, wpa_dbg(wpa_s, MSG_INFO,
"No PSK available for association"); "No PSK available for association");
wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE"); wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
return -1; return -1;
} }
@ -3895,7 +3895,7 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
"pre-shared key may be incorrect"); "pre-shared key may be incorrect");
if (wpas_p2p_4way_hs_failed(wpa_s) > 0) if (wpas_p2p_4way_hs_failed(wpa_s) > 0)
return; /* P2P group removed */ return; /* P2P group removed */
wpas_auth_failed(wpa_s, "WRONG_KEY"); wpas_auth_failed(wpa_s, "WRONG_KEY", prev_pending_bssid);
#ifdef CONFIG_DPP2 #ifdef CONFIG_DPP2
wpas_dpp_send_conn_status_result(wpa_s, wpas_dpp_send_conn_status_result(wpa_s,
DPP_STATUS_AUTH_FAILURE); 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)) && (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) &&
eapol_sm_failed(wpa_s->eapol))) && eapol_sm_failed(wpa_s->eapol))) &&
!wpa_s->eap_expected_failure)) !wpa_s->eap_expected_failure))
wpas_auth_failed(wpa_s, "AUTH_FAILED"); wpas_auth_failed(wpa_s, "AUTH_FAILED", addr);
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
if (deauth && reason_code > 0) { if (deauth && reason_code > 0) {

View file

@ -2011,7 +2011,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
if (!psk_set) { if (!psk_set) {
wpa_msg(wpa_s, MSG_INFO, wpa_msg(wpa_s, MSG_INFO,
"No PSK available for association"); "No PSK available for association");
wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE"); wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
return -1; return -1;
} }
#ifdef CONFIG_OWE #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) { if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
wpa_printf(MSG_DEBUG, "Continuous association failures - " wpa_printf(MSG_DEBUG, "Continuous association failures - "
"consider temporary network disabling"); "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 * 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; struct wpa_ssid *ssid = wpa_s->current_ssid;
int dur; 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", "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len), ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
ssid->auth_failures, dur, reason); 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.sec = 0;
ssid->disabled_until.usec = 0; ssid->disabled_until.usec = 0;
if (clear_failures) if (clear_failures) {
ssid->auth_failures = 0; 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);
}
} }

View file

@ -1629,7 +1629,8 @@ void fils_connection_failure(struct wpa_supplicant *wpa_s);
void fils_pmksa_cache_flush(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_driver_bss_selection(struct wpa_supplicant *wpa_s);
int wpas_is_p2p_prioritized(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, void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int clear_failures); struct wpa_ssid *ssid, int clear_failures);
int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid); int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid);