#include "eloop.h"
#include "uuid.h"
#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);
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 &&
return 1;
}
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) {
+ wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting "
+ "for external credential processing");
+ wpas_clear_wps(wpa_s);
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_DEAUTH_LEAVING);
+ return 1;
+ }
+
return 0;
}
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid = wpa_s->current_ssid;
- wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
+ if ((wpa_s->conf->wps_cred_processing == 1 ||
+ wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
+ size_t blen = cred->cred_attr_len * 2 + 1;
+ char *buf = os_malloc(blen);
+ if (buf) {
+ wpa_snprintf_hex(buf, blen,
+ cred->cred_attr, cred->cred_attr_len);
+ wpa_msg(wpa_s, MSG_INFO, "%s%s",
+ WPS_EVENT_CRED_RECEIVED, buf);
+ os_free(buf);
+ }
+ wpa_supplicant_dbus_notify_wps_cred(wpa_s, cred);
+ } else
+ wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
+
+ wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
+ cred->cred_attr, cred->cred_attr_len);
+
+ if (wpa_s->conf->wps_cred_processing == 1)
+ return 0;
+
+ if (cred->auth_type != WPS_AUTH_OPEN &&
+ cred->auth_type != WPS_AUTH_SHARED &&
+ cred->auth_type != WPS_AUTH_WPAPSK &&
+ cred->auth_type != WPS_AUTH_WPA2PSK) {
+ wpa_printf(MSG_DEBUG, "WPS: Ignored credentials for "
+ "unsupported authentication type %d",
+ cred->auth_type);
+ return 0;
+ }
if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
wpa_printf(MSG_DEBUG, "WPS: Replace WPS network block based "
switch (cred->encr_type) {
case WPS_ENCR_NONE:
- ssid->pairwise_cipher = ssid->group_cipher = WPA_CIPHER_NONE;
break;
case WPS_ENCR_WEP:
- ssid->pairwise_cipher = ssid->group_cipher =
- WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104;
if (cred->key_len > 0 && cred->key_len <= MAX_WEP_KEY_LEN &&
cred->key_idx < NUM_WEP_KEYS) {
os_memcpy(ssid->wep_key[cred->key_idx], cred->key,
break;
case WPS_ENCR_TKIP:
ssid->pairwise_cipher = WPA_CIPHER_TKIP;
- ssid->group_cipher = WPA_CIPHER_TKIP;
break;
case WPS_ENCR_AES:
ssid->pairwise_cipher = WPA_CIPHER_CCMP;
- ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP;
break;
}
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;
}
case WPS_EV_SUCCESS:
wpa_supplicant_wps_event_success(wpa_s);
break;
+ case WPS_EV_PWD_AUTH_FAIL:
+ break;
}
}
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);
}
}
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);
}
}
-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;
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;
}
}
-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;
}
} 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;
}