Allow WPS APs for PIN enrollment even without Selected Registrar
Some WPS APs do not set Selected Registrar attribute to 1 properly when using an external Registrar. Allow such an AP to be selected for PIN registration after couple of scan runs that do not find APs marked with Selected Registrar = 1. This allows wpa_supplicant to iterate through all APs that advertise WPS support without delaying connection with implementations that set Selected Registrar = 1 properly.
This commit is contained in:
parent
401e039633
commit
a609915233
6 changed files with 75 additions and 20 deletions
|
@ -66,6 +66,8 @@ extern "C" {
|
|||
#define WPS_EVENT_FAIL "WPS-FAIL "
|
||||
/** WPS registration completed successfully */
|
||||
#define WPS_EVENT_SUCCESS "WPS-SUCCESS "
|
||||
/** WPS enrollment attempt timed out and was terminated */
|
||||
#define WPS_EVENT_TIMEOUT "WPS-TIMEOUT "
|
||||
|
||||
/* hostapd control interface - fixed message prefixes */
|
||||
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
|
||||
|
|
|
@ -271,7 +271,8 @@ static int wpa_supplicant_match_privacy(struct wpa_scan_res *bss,
|
|||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_ssid_bss_match(struct wpa_ssid *ssid,
|
||||
static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
struct wpa_scan_res *bss)
|
||||
{
|
||||
struct wpa_ie_data ie;
|
||||
|
@ -279,7 +280,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_ssid *ssid,
|
|||
const u8 *rsn_ie, *wpa_ie;
|
||||
int ret;
|
||||
|
||||
ret = wpas_wps_ssid_bss_match(ssid, bss);
|
||||
ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
|
||||
|
@ -425,7 +426,7 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
|
|||
|
||||
#ifdef CONFIG_WPS
|
||||
if (ssid->ssid_len == 0 &&
|
||||
wpas_wps_ssid_wildcard_ok(ssid, bss))
|
||||
wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss))
|
||||
check_ssid = 0;
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
@ -445,7 +446,7 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!wpa_supplicant_ssid_bss_match(ssid, bss))
|
||||
if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss))
|
||||
continue;
|
||||
|
||||
wpa_printf(MSG_DEBUG, " selected WPA AP "
|
||||
|
@ -515,7 +516,8 @@ wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
|
|||
* with our mode. */
|
||||
check_ssid = 1;
|
||||
if (ssid->ssid_len == 0 &&
|
||||
wpas_wps_ssid_wildcard_ok(ssid, bss))
|
||||
wpas_wps_ssid_wildcard_ok(wpa_s, ssid,
|
||||
bss))
|
||||
check_ssid = 0;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
@ -646,6 +648,7 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
|
|||
wpa_printf(MSG_DEBUG, "No APs found - clear blacklist "
|
||||
"and try again");
|
||||
wpa_blacklist_clear(wpa_s);
|
||||
wpa_s->blacklist_cleared++;
|
||||
} else if (selected == NULL) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -204,7 +204,8 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
if (ret) {
|
||||
wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
|
||||
wpa_supplicant_req_scan(wpa_s, 10, 0);
|
||||
}
|
||||
} else
|
||||
wpa_s->scan_runs++;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -346,6 +346,7 @@ struct wpa_supplicant {
|
|||
* results without a new scan request; this is used
|
||||
* to speed up the first association if the driver
|
||||
* has already available scan results. */
|
||||
int scan_runs; /* number of scan runs since WPS was started */
|
||||
|
||||
struct wpa_client_mlme mlme;
|
||||
int use_client_mlme;
|
||||
|
@ -356,6 +357,8 @@ struct wpa_supplicant {
|
|||
int mic_errors_seen; /* Michael MIC errors with the current PTK */
|
||||
|
||||
struct wps_context *wps;
|
||||
int wps_success; /* WPS success event received */
|
||||
int blacklist_cleared;
|
||||
|
||||
struct ibss_rsn *ibss_rsn;
|
||||
};
|
||||
|
|
|
@ -25,8 +25,10 @@
|
|||
#include "wpa_ctrl.h"
|
||||
#include "ctrl_iface_dbus.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "blacklist.h"
|
||||
#include "wps_supplicant.h"
|
||||
|
||||
#define WPS_PIN_SCAN_IGNORE_SEL_REG 3
|
||||
|
||||
static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
|
||||
|
@ -34,6 +36,27 @@ static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
|
|||
|
||||
int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (!wpa_s->wps_success &&
|
||||
wpa_s->current_ssid &&
|
||||
eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
|
||||
const u8 *bssid = wpa_s->bssid;
|
||||
if (is_zero_ether_addr(bssid))
|
||||
bssid = wpa_s->pending_bssid;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR
|
||||
" did not succeed - continue trying to find "
|
||||
"suitable AP", MAC2STR(bssid));
|
||||
wpa_blacklist_add(wpa_s, bssid);
|
||||
|
||||
wpa_supplicant_deauthenticate(wpa_s,
|
||||
WLAN_REASON_DEAUTH_LEAVING);
|
||||
wpa_s->reassociate = 1;
|
||||
wpa_supplicant_req_scan(wpa_s,
|
||||
wpa_s->blacklist_cleared ? 5 : 0, 0);
|
||||
wpa_s->blacklist_cleared = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
|
||||
|
||||
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid &&
|
||||
|
@ -234,6 +257,7 @@ static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
|
|||
static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
|
||||
wpa_s->wps_success = 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -291,7 +315,8 @@ static void wpas_clear_wps(struct wpa_supplicant *wpa_s)
|
|||
static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||
wpa_printf(MSG_DEBUG, "WPS: Requested operation timed out");
|
||||
wpa_printf(MSG_INFO, WPS_EVENT_TIMEOUT "Requested operation timed "
|
||||
"out");
|
||||
wpas_clear_wps(wpa_s);
|
||||
}
|
||||
|
||||
|
@ -363,6 +388,9 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
wpa_s->disconnected = 0;
|
||||
wpa_s->reassociate = 1;
|
||||
wpa_s->scan_runs = 0;
|
||||
wpa_s->wps_success = 0;
|
||||
wpa_s->blacklist_cleared = 0;
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -550,7 +578,8 @@ void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
|
|||
}
|
||||
|
||||
|
||||
int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid, struct wpa_scan_res *bss)
|
||||
int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid, struct wpa_scan_res *bss)
|
||||
{
|
||||
struct wpabuf *wps_ie;
|
||||
|
||||
|
@ -584,14 +613,24 @@ int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid, struct wpa_scan_res *bss)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start with WPS APs that advertise active PIN Registrar and
|
||||
* allow any WPS AP after third scan since some APs do not set
|
||||
* Selected Registrar attribute properly when using external
|
||||
* Registrar.
|
||||
*/
|
||||
if (!wps_is_selected_pin_registrar(wps_ie)) {
|
||||
wpa_printf(MSG_DEBUG, " skip - WPS AP "
|
||||
"without active PIN Registrar");
|
||||
wpabuf_free(wps_ie);
|
||||
return 0;
|
||||
if (wpa_s->scan_runs < WPS_PIN_SCAN_IGNORE_SEL_REG) {
|
||||
wpa_printf(MSG_DEBUG, " skip - WPS AP "
|
||||
"without active PIN Registrar");
|
||||
wpabuf_free(wps_ie);
|
||||
return 0;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, " selected based on WPS IE");
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, " selected based on WPS IE "
|
||||
"(Active PIN)");
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, " selected based on WPS IE "
|
||||
"(Active PIN)");
|
||||
wpabuf_free(wps_ie);
|
||||
return 1;
|
||||
}
|
||||
|
@ -606,7 +645,8 @@ int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid, struct wpa_scan_res *bss)
|
|||
}
|
||||
|
||||
|
||||
int wpas_wps_ssid_wildcard_ok(struct wpa_ssid *ssid,
|
||||
int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
struct wpa_scan_res *bss)
|
||||
{
|
||||
struct wpabuf *wps_ie = NULL;
|
||||
|
@ -620,7 +660,9 @@ int wpas_wps_ssid_wildcard_ok(struct wpa_ssid *ssid,
|
|||
}
|
||||
} else if (eap_is_wps_pin_enrollee(&ssid->eap)) {
|
||||
wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
|
||||
if (wps_ie && wps_is_selected_pin_registrar(wps_ie)) {
|
||||
if (wps_ie &&
|
||||
(wps_is_selected_pin_registrar(wps_ie) ||
|
||||
wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) {
|
||||
/* allow wildcard SSID for WPS PIN */
|
||||
ret = 1;
|
||||
}
|
||||
|
|
|
@ -29,8 +29,10 @@ int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||
const char *pin);
|
||||
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
const char *pin);
|
||||
int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid, struct wpa_scan_res *bss);
|
||||
int wpas_wps_ssid_wildcard_ok(struct wpa_ssid *ssid, struct wpa_scan_res *bss);
|
||||
int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid, struct wpa_scan_res *bss);
|
||||
int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid, struct wpa_scan_res *bss);
|
||||
int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_res *selected,
|
||||
struct wpa_ssid *ssid);
|
||||
|
@ -58,13 +60,15 @@ static inline u8 wpas_wps_get_req_type(struct wpa_ssid *ssid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int wpas_wps_ssid_bss_match(struct wpa_ssid *ssid,
|
||||
static inline int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
struct wpa_scan_res *bss)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int wpas_wps_ssid_wildcard_ok(struct wpa_ssid *ssid,
|
||||
static inline int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
struct wpa_scan_res *bss)
|
||||
{
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue