139beb93cSSam Leffler /* 239beb93cSSam Leffler * wpa_supplicant / WPS integration 339beb93cSSam Leffler * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 539beb93cSSam Leffler * This program is free software; you can redistribute it and/or modify 639beb93cSSam Leffler * it under the terms of the GNU General Public License version 2 as 739beb93cSSam Leffler * published by the Free Software Foundation. 839beb93cSSam Leffler * 939beb93cSSam Leffler * Alternatively, this software may be distributed under the terms of BSD 1039beb93cSSam Leffler * license. 1139beb93cSSam Leffler * 1239beb93cSSam Leffler * See README and COPYING for more details. 1339beb93cSSam Leffler */ 1439beb93cSSam Leffler 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler 1739beb93cSSam Leffler #include "common.h" 1839beb93cSSam Leffler #include "ieee802_11_defs.h" 1939beb93cSSam Leffler #include "wpa_common.h" 2039beb93cSSam Leffler #include "config.h" 2139beb93cSSam Leffler #include "eap_peer/eap.h" 2239beb93cSSam Leffler #include "wpa_supplicant_i.h" 2339beb93cSSam Leffler #include "eloop.h" 2439beb93cSSam Leffler #include "uuid.h" 2539beb93cSSam Leffler #include "wpa_ctrl.h" 2639beb93cSSam Leffler #include "ctrl_iface_dbus.h" 2739beb93cSSam Leffler #include "eap_common/eap_wsc_common.h" 2839beb93cSSam Leffler #include "blacklist.h" 2939beb93cSSam Leffler #include "wps_supplicant.h" 3039beb93cSSam Leffler 3139beb93cSSam Leffler #define WPS_PIN_SCAN_IGNORE_SEL_REG 3 3239beb93cSSam Leffler 3339beb93cSSam Leffler static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx); 3439beb93cSSam Leffler static void wpas_clear_wps(struct wpa_supplicant *wpa_s); 3539beb93cSSam Leffler 3639beb93cSSam Leffler 3739beb93cSSam Leffler int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) 3839beb93cSSam Leffler { 3939beb93cSSam Leffler if (!wpa_s->wps_success && 4039beb93cSSam Leffler wpa_s->current_ssid && 4139beb93cSSam Leffler eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) { 4239beb93cSSam Leffler const u8 *bssid = wpa_s->bssid; 4339beb93cSSam Leffler if (is_zero_ether_addr(bssid)) 4439beb93cSSam Leffler bssid = wpa_s->pending_bssid; 4539beb93cSSam Leffler 4639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR 4739beb93cSSam Leffler " did not succeed - continue trying to find " 4839beb93cSSam Leffler "suitable AP", MAC2STR(bssid)); 4939beb93cSSam Leffler wpa_blacklist_add(wpa_s, bssid); 5039beb93cSSam Leffler 5139beb93cSSam Leffler wpa_supplicant_deauthenticate(wpa_s, 5239beb93cSSam Leffler WLAN_REASON_DEAUTH_LEAVING); 5339beb93cSSam Leffler wpa_s->reassociate = 1; 5439beb93cSSam Leffler wpa_supplicant_req_scan(wpa_s, 5539beb93cSSam Leffler wpa_s->blacklist_cleared ? 5 : 0, 0); 5639beb93cSSam Leffler wpa_s->blacklist_cleared = 0; 5739beb93cSSam Leffler return 1; 5839beb93cSSam Leffler } 5939beb93cSSam Leffler 6039beb93cSSam Leffler eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL); 6139beb93cSSam Leffler 6239beb93cSSam Leffler if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid && 6339beb93cSSam Leffler !(wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { 6439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - " 6539beb93cSSam Leffler "try to associate with the received credential"); 6639beb93cSSam Leffler wpa_supplicant_deauthenticate(wpa_s, 6739beb93cSSam Leffler WLAN_REASON_DEAUTH_LEAVING); 6839beb93cSSam Leffler wpa_s->reassociate = 1; 6939beb93cSSam Leffler wpa_supplicant_req_scan(wpa_s, 0, 0); 7039beb93cSSam Leffler return 1; 7139beb93cSSam Leffler } 7239beb93cSSam Leffler 7339beb93cSSam Leffler if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) { 7439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting " 7539beb93cSSam Leffler "for external credential processing"); 7639beb93cSSam Leffler wpas_clear_wps(wpa_s); 7739beb93cSSam Leffler wpa_supplicant_deauthenticate(wpa_s, 7839beb93cSSam Leffler WLAN_REASON_DEAUTH_LEAVING); 7939beb93cSSam Leffler return 1; 8039beb93cSSam Leffler } 8139beb93cSSam Leffler 8239beb93cSSam Leffler return 0; 8339beb93cSSam Leffler } 8439beb93cSSam Leffler 8539beb93cSSam Leffler 8639beb93cSSam Leffler static int wpa_supplicant_wps_cred(void *ctx, 8739beb93cSSam Leffler const struct wps_credential *cred) 8839beb93cSSam Leffler { 8939beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 9039beb93cSSam Leffler struct wpa_ssid *ssid = wpa_s->current_ssid; 9139beb93cSSam Leffler 9239beb93cSSam Leffler if ((wpa_s->conf->wps_cred_processing == 1 || 9339beb93cSSam Leffler wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) { 9439beb93cSSam Leffler size_t blen = cred->cred_attr_len * 2 + 1; 9539beb93cSSam Leffler char *buf = os_malloc(blen); 9639beb93cSSam Leffler if (buf) { 9739beb93cSSam Leffler wpa_snprintf_hex(buf, blen, 9839beb93cSSam Leffler cred->cred_attr, cred->cred_attr_len); 9939beb93cSSam Leffler wpa_msg(wpa_s, MSG_INFO, "%s%s", 10039beb93cSSam Leffler WPS_EVENT_CRED_RECEIVED, buf); 10139beb93cSSam Leffler os_free(buf); 10239beb93cSSam Leffler } 10339beb93cSSam Leffler wpa_supplicant_dbus_notify_wps_cred(wpa_s, cred); 10439beb93cSSam Leffler } else 10539beb93cSSam Leffler wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED); 10639beb93cSSam Leffler 10739beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", 10839beb93cSSam Leffler cred->cred_attr, cred->cred_attr_len); 10939beb93cSSam Leffler 11039beb93cSSam Leffler if (wpa_s->conf->wps_cred_processing == 1) 11139beb93cSSam Leffler return 0; 11239beb93cSSam Leffler 11339beb93cSSam Leffler if (cred->auth_type != WPS_AUTH_OPEN && 11439beb93cSSam Leffler cred->auth_type != WPS_AUTH_SHARED && 11539beb93cSSam Leffler cred->auth_type != WPS_AUTH_WPAPSK && 11639beb93cSSam Leffler cred->auth_type != WPS_AUTH_WPA2PSK) { 11739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Ignored credentials for " 11839beb93cSSam Leffler "unsupported authentication type %d", 11939beb93cSSam Leffler cred->auth_type); 12039beb93cSSam Leffler return 0; 12139beb93cSSam Leffler } 12239beb93cSSam Leffler 12339beb93cSSam Leffler if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { 12439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Replace WPS network block based " 12539beb93cSSam Leffler "on the received credential"); 12639beb93cSSam Leffler os_free(ssid->eap.identity); 12739beb93cSSam Leffler ssid->eap.identity = NULL; 12839beb93cSSam Leffler ssid->eap.identity_len = 0; 12939beb93cSSam Leffler os_free(ssid->eap.phase1); 13039beb93cSSam Leffler ssid->eap.phase1 = NULL; 13139beb93cSSam Leffler os_free(ssid->eap.eap_methods); 13239beb93cSSam Leffler ssid->eap.eap_methods = NULL; 13339beb93cSSam Leffler } else { 13439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Create a new network based on the " 13539beb93cSSam Leffler "received credential"); 13639beb93cSSam Leffler ssid = wpa_config_add_network(wpa_s->conf); 13739beb93cSSam Leffler if (ssid == NULL) 13839beb93cSSam Leffler return -1; 13939beb93cSSam Leffler } 14039beb93cSSam Leffler 14139beb93cSSam Leffler wpa_config_set_network_defaults(ssid); 14239beb93cSSam Leffler 14339beb93cSSam Leffler os_free(ssid->ssid); 14439beb93cSSam Leffler ssid->ssid = os_malloc(cred->ssid_len); 14539beb93cSSam Leffler if (ssid->ssid) { 14639beb93cSSam Leffler os_memcpy(ssid->ssid, cred->ssid, cred->ssid_len); 14739beb93cSSam Leffler ssid->ssid_len = cred->ssid_len; 14839beb93cSSam Leffler } 14939beb93cSSam Leffler 15039beb93cSSam Leffler switch (cred->encr_type) { 15139beb93cSSam Leffler case WPS_ENCR_NONE: 15239beb93cSSam Leffler break; 15339beb93cSSam Leffler case WPS_ENCR_WEP: 15439beb93cSSam Leffler if (cred->key_len > 0 && cred->key_len <= MAX_WEP_KEY_LEN && 15539beb93cSSam Leffler cred->key_idx < NUM_WEP_KEYS) { 15639beb93cSSam Leffler os_memcpy(ssid->wep_key[cred->key_idx], cred->key, 15739beb93cSSam Leffler cred->key_len); 15839beb93cSSam Leffler ssid->wep_key_len[cred->key_idx] = cred->key_len; 15939beb93cSSam Leffler ssid->wep_tx_keyidx = cred->key_idx; 16039beb93cSSam Leffler } 16139beb93cSSam Leffler break; 16239beb93cSSam Leffler case WPS_ENCR_TKIP: 16339beb93cSSam Leffler ssid->pairwise_cipher = WPA_CIPHER_TKIP; 16439beb93cSSam Leffler break; 16539beb93cSSam Leffler case WPS_ENCR_AES: 16639beb93cSSam Leffler ssid->pairwise_cipher = WPA_CIPHER_CCMP; 16739beb93cSSam Leffler break; 16839beb93cSSam Leffler } 16939beb93cSSam Leffler 17039beb93cSSam Leffler switch (cred->auth_type) { 17139beb93cSSam Leffler case WPS_AUTH_OPEN: 17239beb93cSSam Leffler ssid->auth_alg = WPA_AUTH_ALG_OPEN; 17339beb93cSSam Leffler ssid->key_mgmt = WPA_KEY_MGMT_NONE; 17439beb93cSSam Leffler ssid->proto = 0; 17539beb93cSSam Leffler break; 17639beb93cSSam Leffler case WPS_AUTH_SHARED: 17739beb93cSSam Leffler ssid->auth_alg = WPA_AUTH_ALG_SHARED; 17839beb93cSSam Leffler ssid->key_mgmt = WPA_KEY_MGMT_NONE; 17939beb93cSSam Leffler ssid->proto = 0; 18039beb93cSSam Leffler break; 18139beb93cSSam Leffler case WPS_AUTH_WPAPSK: 18239beb93cSSam Leffler ssid->auth_alg = WPA_AUTH_ALG_OPEN; 18339beb93cSSam Leffler ssid->key_mgmt = WPA_KEY_MGMT_PSK; 18439beb93cSSam Leffler ssid->proto = WPA_PROTO_WPA; 18539beb93cSSam Leffler break; 18639beb93cSSam Leffler case WPS_AUTH_WPA: 18739beb93cSSam Leffler ssid->auth_alg = WPA_AUTH_ALG_OPEN; 18839beb93cSSam Leffler ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 18939beb93cSSam Leffler ssid->proto = WPA_PROTO_WPA; 19039beb93cSSam Leffler break; 19139beb93cSSam Leffler case WPS_AUTH_WPA2: 19239beb93cSSam Leffler ssid->auth_alg = WPA_AUTH_ALG_OPEN; 19339beb93cSSam Leffler ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 19439beb93cSSam Leffler ssid->proto = WPA_PROTO_RSN; 19539beb93cSSam Leffler break; 19639beb93cSSam Leffler case WPS_AUTH_WPA2PSK: 19739beb93cSSam Leffler ssid->auth_alg = WPA_AUTH_ALG_OPEN; 19839beb93cSSam Leffler ssid->key_mgmt = WPA_KEY_MGMT_PSK; 19939beb93cSSam Leffler ssid->proto = WPA_PROTO_RSN; 20039beb93cSSam Leffler break; 20139beb93cSSam Leffler } 20239beb93cSSam Leffler 20339beb93cSSam Leffler if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) { 20439beb93cSSam Leffler if (cred->key_len == 2 * PMK_LEN) { 20539beb93cSSam Leffler if (hexstr2bin((const char *) cred->key, ssid->psk, 20639beb93cSSam Leffler PMK_LEN)) { 20739beb93cSSam Leffler wpa_printf(MSG_ERROR, "WPS: Invalid Network " 20839beb93cSSam Leffler "Key"); 20939beb93cSSam Leffler return -1; 21039beb93cSSam Leffler } 21139beb93cSSam Leffler ssid->psk_set = 1; 21239beb93cSSam Leffler } else if (cred->key_len >= 8 && cred->key_len < 2 * PMK_LEN) { 21339beb93cSSam Leffler os_free(ssid->passphrase); 21439beb93cSSam Leffler ssid->passphrase = os_malloc(cred->key_len + 1); 21539beb93cSSam Leffler if (ssid->passphrase == NULL) 21639beb93cSSam Leffler return -1; 21739beb93cSSam Leffler os_memcpy(ssid->passphrase, cred->key, cred->key_len); 21839beb93cSSam Leffler ssid->passphrase[cred->key_len] = '\0'; 21939beb93cSSam Leffler wpa_config_update_psk(ssid); 22039beb93cSSam Leffler } else { 22139beb93cSSam Leffler wpa_printf(MSG_ERROR, "WPS: Invalid Network Key " 22239beb93cSSam Leffler "length %lu", 22339beb93cSSam Leffler (unsigned long) cred->key_len); 22439beb93cSSam Leffler return -1; 22539beb93cSSam Leffler } 22639beb93cSSam Leffler } 22739beb93cSSam Leffler 22839beb93cSSam Leffler #ifndef CONFIG_NO_CONFIG_WRITE 22939beb93cSSam Leffler if (wpa_s->conf->update_config && 23039beb93cSSam Leffler wpa_config_write(wpa_s->confname, wpa_s->conf)) { 23139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Failed to update configuration"); 23239beb93cSSam Leffler return -1; 23339beb93cSSam Leffler } 23439beb93cSSam Leffler #endif /* CONFIG_NO_CONFIG_WRITE */ 23539beb93cSSam Leffler 23639beb93cSSam Leffler return 0; 23739beb93cSSam Leffler } 23839beb93cSSam Leffler 23939beb93cSSam Leffler 24039beb93cSSam Leffler static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s, 24139beb93cSSam Leffler struct wps_event_m2d *m2d) 24239beb93cSSam Leffler { 24339beb93cSSam Leffler wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_M2D 24439beb93cSSam Leffler "dev_password_id=%d config_error=%d", 24539beb93cSSam Leffler m2d->dev_password_id, m2d->config_error); 24639beb93cSSam Leffler } 24739beb93cSSam Leffler 24839beb93cSSam Leffler 24939beb93cSSam Leffler static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s, 25039beb93cSSam Leffler struct wps_event_fail *fail) 25139beb93cSSam Leffler { 25239beb93cSSam Leffler wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL "msg=%d", fail->msg); 25339beb93cSSam Leffler wpas_clear_wps(wpa_s); 25439beb93cSSam Leffler } 25539beb93cSSam Leffler 25639beb93cSSam Leffler 25739beb93cSSam Leffler static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s) 25839beb93cSSam Leffler { 25939beb93cSSam Leffler wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS); 26039beb93cSSam Leffler wpa_s->wps_success = 1; 26139beb93cSSam Leffler } 26239beb93cSSam Leffler 26339beb93cSSam Leffler 26439beb93cSSam Leffler static void wpa_supplicant_wps_event(void *ctx, enum wps_event event, 26539beb93cSSam Leffler union wps_event_data *data) 26639beb93cSSam Leffler { 26739beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 26839beb93cSSam Leffler switch (event) { 26939beb93cSSam Leffler case WPS_EV_M2D: 27039beb93cSSam Leffler wpa_supplicant_wps_event_m2d(wpa_s, &data->m2d); 27139beb93cSSam Leffler break; 27239beb93cSSam Leffler case WPS_EV_FAIL: 27339beb93cSSam Leffler wpa_supplicant_wps_event_fail(wpa_s, &data->fail); 27439beb93cSSam Leffler break; 27539beb93cSSam Leffler case WPS_EV_SUCCESS: 27639beb93cSSam Leffler wpa_supplicant_wps_event_success(wpa_s); 27739beb93cSSam Leffler break; 27839beb93cSSam Leffler case WPS_EV_PWD_AUTH_FAIL: 27939beb93cSSam Leffler break; 28039beb93cSSam Leffler } 28139beb93cSSam Leffler } 28239beb93cSSam Leffler 28339beb93cSSam Leffler 28439beb93cSSam Leffler enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid) 28539beb93cSSam Leffler { 28639beb93cSSam Leffler if (eap_is_wps_pbc_enrollee(&ssid->eap) || 28739beb93cSSam Leffler eap_is_wps_pin_enrollee(&ssid->eap)) 28839beb93cSSam Leffler return WPS_REQ_ENROLLEE; 28939beb93cSSam Leffler else 29039beb93cSSam Leffler return WPS_REQ_REGISTRAR; 29139beb93cSSam Leffler } 29239beb93cSSam Leffler 29339beb93cSSam Leffler 29439beb93cSSam Leffler static void wpas_clear_wps(struct wpa_supplicant *wpa_s) 29539beb93cSSam Leffler { 29639beb93cSSam Leffler int id; 29739beb93cSSam Leffler struct wpa_ssid *ssid; 29839beb93cSSam Leffler 29939beb93cSSam Leffler eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL); 30039beb93cSSam Leffler 30139beb93cSSam Leffler /* Remove any existing WPS network from configuration */ 30239beb93cSSam Leffler ssid = wpa_s->conf->ssid; 30339beb93cSSam Leffler while (ssid) { 30439beb93cSSam Leffler if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { 30539beb93cSSam Leffler if (ssid == wpa_s->current_ssid) 30639beb93cSSam Leffler wpa_s->current_ssid = NULL; 30739beb93cSSam Leffler id = ssid->id; 30839beb93cSSam Leffler } else 30939beb93cSSam Leffler id = -1; 31039beb93cSSam Leffler ssid = ssid->next; 31139beb93cSSam Leffler if (id >= 0) 31239beb93cSSam Leffler wpa_config_remove_network(wpa_s->conf, id); 31339beb93cSSam Leffler } 31439beb93cSSam Leffler } 31539beb93cSSam Leffler 31639beb93cSSam Leffler 31739beb93cSSam Leffler static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx) 31839beb93cSSam Leffler { 31939beb93cSSam Leffler struct wpa_supplicant *wpa_s = eloop_ctx; 32039beb93cSSam Leffler wpa_printf(MSG_INFO, WPS_EVENT_TIMEOUT "Requested operation timed " 32139beb93cSSam Leffler "out"); 32239beb93cSSam Leffler wpas_clear_wps(wpa_s); 32339beb93cSSam Leffler } 32439beb93cSSam Leffler 32539beb93cSSam Leffler 32639beb93cSSam Leffler static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s, 32739beb93cSSam Leffler int registrar, const u8 *bssid) 32839beb93cSSam Leffler { 32939beb93cSSam Leffler struct wpa_ssid *ssid; 33039beb93cSSam Leffler 33139beb93cSSam Leffler ssid = wpa_config_add_network(wpa_s->conf); 33239beb93cSSam Leffler if (ssid == NULL) 33339beb93cSSam Leffler return NULL; 33439beb93cSSam Leffler wpa_config_set_network_defaults(ssid); 33539beb93cSSam Leffler if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 || 33639beb93cSSam Leffler wpa_config_set(ssid, "eap", "WSC", 0) < 0 || 33739beb93cSSam Leffler wpa_config_set(ssid, "identity", registrar ? 33839beb93cSSam Leffler "\"" WSC_ID_REGISTRAR "\"" : 33939beb93cSSam Leffler "\"" WSC_ID_ENROLLEE "\"", 0) < 0) { 34039beb93cSSam Leffler wpa_config_remove_network(wpa_s->conf, ssid->id); 34139beb93cSSam Leffler return NULL; 34239beb93cSSam Leffler } 34339beb93cSSam Leffler 34439beb93cSSam Leffler if (bssid) { 34539beb93cSSam Leffler size_t i; 34639beb93cSSam Leffler struct wpa_scan_res *res; 34739beb93cSSam Leffler 34839beb93cSSam Leffler os_memcpy(ssid->bssid, bssid, ETH_ALEN); 34939beb93cSSam Leffler ssid->bssid_set = 1; 35039beb93cSSam Leffler 35139beb93cSSam Leffler /* Try to get SSID from scan results */ 35239beb93cSSam Leffler if (wpa_s->scan_res == NULL && 35339beb93cSSam Leffler wpa_supplicant_get_scan_results(wpa_s) < 0) 35439beb93cSSam Leffler return ssid; /* Could not find any scan results */ 35539beb93cSSam Leffler 35639beb93cSSam Leffler for (i = 0; i < wpa_s->scan_res->num; i++) { 35739beb93cSSam Leffler const u8 *ie; 35839beb93cSSam Leffler 35939beb93cSSam Leffler res = wpa_s->scan_res->res[i]; 36039beb93cSSam Leffler if (os_memcmp(bssid, res->bssid, ETH_ALEN) != 0) 36139beb93cSSam Leffler continue; 36239beb93cSSam Leffler 36339beb93cSSam Leffler ie = wpa_scan_get_ie(res, WLAN_EID_SSID); 36439beb93cSSam Leffler if (ie == NULL) 36539beb93cSSam Leffler break; 36639beb93cSSam Leffler os_free(ssid->ssid); 36739beb93cSSam Leffler ssid->ssid = os_malloc(ie[1]); 36839beb93cSSam Leffler if (ssid->ssid == NULL) 36939beb93cSSam Leffler break; 37039beb93cSSam Leffler os_memcpy(ssid->ssid, ie + 2, ie[1]); 37139beb93cSSam Leffler ssid->ssid_len = ie[1]; 37239beb93cSSam Leffler break; 37339beb93cSSam Leffler } 37439beb93cSSam Leffler } 37539beb93cSSam Leffler 37639beb93cSSam Leffler return ssid; 37739beb93cSSam Leffler } 37839beb93cSSam Leffler 37939beb93cSSam Leffler 38039beb93cSSam Leffler static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s, 38139beb93cSSam Leffler struct wpa_ssid *selected) 38239beb93cSSam Leffler { 38339beb93cSSam Leffler struct wpa_ssid *ssid; 38439beb93cSSam Leffler 38539beb93cSSam Leffler /* Mark all other networks disabled and trigger reassociation */ 38639beb93cSSam Leffler ssid = wpa_s->conf->ssid; 38739beb93cSSam Leffler while (ssid) { 38839beb93cSSam Leffler ssid->disabled = ssid != selected; 38939beb93cSSam Leffler ssid = ssid->next; 39039beb93cSSam Leffler } 39139beb93cSSam Leffler wpa_s->disconnected = 0; 39239beb93cSSam Leffler wpa_s->reassociate = 1; 39339beb93cSSam Leffler wpa_s->scan_runs = 0; 39439beb93cSSam Leffler wpa_s->wps_success = 0; 39539beb93cSSam Leffler wpa_s->blacklist_cleared = 0; 39639beb93cSSam Leffler wpa_supplicant_req_scan(wpa_s, 0, 0); 39739beb93cSSam Leffler } 39839beb93cSSam Leffler 39939beb93cSSam Leffler 40039beb93cSSam Leffler int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid) 40139beb93cSSam Leffler { 40239beb93cSSam Leffler struct wpa_ssid *ssid; 40339beb93cSSam Leffler wpas_clear_wps(wpa_s); 40439beb93cSSam Leffler ssid = wpas_wps_add_network(wpa_s, 0, bssid); 40539beb93cSSam Leffler if (ssid == NULL) 40639beb93cSSam Leffler return -1; 40739beb93cSSam Leffler wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0); 40839beb93cSSam Leffler eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, 40939beb93cSSam Leffler wpa_s, NULL); 41039beb93cSSam Leffler wpas_wps_reassoc(wpa_s, ssid); 41139beb93cSSam Leffler return 0; 41239beb93cSSam Leffler } 41339beb93cSSam Leffler 41439beb93cSSam Leffler 41539beb93cSSam Leffler int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, 41639beb93cSSam Leffler const char *pin) 41739beb93cSSam Leffler { 41839beb93cSSam Leffler struct wpa_ssid *ssid; 41939beb93cSSam Leffler char val[30]; 42039beb93cSSam Leffler unsigned int rpin = 0; 42139beb93cSSam Leffler 42239beb93cSSam Leffler wpas_clear_wps(wpa_s); 42339beb93cSSam Leffler ssid = wpas_wps_add_network(wpa_s, 0, bssid); 42439beb93cSSam Leffler if (ssid == NULL) 42539beb93cSSam Leffler return -1; 42639beb93cSSam Leffler if (pin) 42739beb93cSSam Leffler os_snprintf(val, sizeof(val), "\"pin=%s\"", pin); 42839beb93cSSam Leffler else { 42939beb93cSSam Leffler rpin = wps_generate_pin(); 43039beb93cSSam Leffler os_snprintf(val, sizeof(val), "\"pin=%08d\"", rpin); 43139beb93cSSam Leffler } 43239beb93cSSam Leffler wpa_config_set(ssid, "phase1", val, 0); 43339beb93cSSam Leffler eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, 43439beb93cSSam Leffler wpa_s, NULL); 43539beb93cSSam Leffler wpas_wps_reassoc(wpa_s, ssid); 43639beb93cSSam Leffler return rpin; 43739beb93cSSam Leffler } 43839beb93cSSam Leffler 43939beb93cSSam Leffler 44039beb93cSSam Leffler int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid, 44139beb93cSSam Leffler const char *pin) 44239beb93cSSam Leffler { 44339beb93cSSam Leffler struct wpa_ssid *ssid; 44439beb93cSSam Leffler char val[30]; 44539beb93cSSam Leffler 44639beb93cSSam Leffler if (!pin) 44739beb93cSSam Leffler return -1; 44839beb93cSSam Leffler wpas_clear_wps(wpa_s); 44939beb93cSSam Leffler ssid = wpas_wps_add_network(wpa_s, 1, bssid); 45039beb93cSSam Leffler if (ssid == NULL) 45139beb93cSSam Leffler return -1; 45239beb93cSSam Leffler os_snprintf(val, sizeof(val), "\"pin=%s\"", pin); 45339beb93cSSam Leffler wpa_config_set(ssid, "phase1", val, 0); 45439beb93cSSam Leffler eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, 45539beb93cSSam Leffler wpa_s, NULL); 45639beb93cSSam Leffler wpas_wps_reassoc(wpa_s, ssid); 45739beb93cSSam Leffler return 0; 45839beb93cSSam Leffler } 45939beb93cSSam Leffler 46039beb93cSSam Leffler 46139beb93cSSam Leffler static int wpas_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk, 46239beb93cSSam Leffler size_t psk_len) 46339beb93cSSam Leffler { 46439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received new WPA/WPA2-PSK from WPS for " 46539beb93cSSam Leffler "STA " MACSTR, MAC2STR(mac_addr)); 46639beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len); 46739beb93cSSam Leffler 46839beb93cSSam Leffler /* TODO */ 46939beb93cSSam Leffler 47039beb93cSSam Leffler return 0; 47139beb93cSSam Leffler } 47239beb93cSSam Leffler 47339beb93cSSam Leffler 47439beb93cSSam Leffler static void wpas_wps_pin_needed_cb(void *ctx, const u8 *uuid_e, 47539beb93cSSam Leffler const struct wps_device_data *dev) 47639beb93cSSam Leffler { 47739beb93cSSam Leffler char uuid[40], txt[400]; 47839beb93cSSam Leffler int len; 47939beb93cSSam Leffler if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) 48039beb93cSSam Leffler return; 48139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: PIN needed for UUID-E %s", uuid); 48239beb93cSSam Leffler len = os_snprintf(txt, sizeof(txt), "WPS-EVENT-PIN-NEEDED %s " MACSTR 48339beb93cSSam Leffler " [%s|%s|%s|%s|%s|%d-%08X-%d]", 48439beb93cSSam Leffler uuid, MAC2STR(dev->mac_addr), dev->device_name, 48539beb93cSSam Leffler dev->manufacturer, dev->model_name, 48639beb93cSSam Leffler dev->model_number, dev->serial_number, 48739beb93cSSam Leffler dev->categ, dev->oui, dev->sub_categ); 48839beb93cSSam Leffler if (len > 0 && len < (int) sizeof(txt)) 48939beb93cSSam Leffler wpa_printf(MSG_INFO, "%s", txt); 49039beb93cSSam Leffler } 49139beb93cSSam Leffler 49239beb93cSSam Leffler 49339beb93cSSam Leffler int wpas_wps_init(struct wpa_supplicant *wpa_s) 49439beb93cSSam Leffler { 49539beb93cSSam Leffler struct wps_context *wps; 49639beb93cSSam Leffler struct wps_registrar_config rcfg; 49739beb93cSSam Leffler 49839beb93cSSam Leffler wps = os_zalloc(sizeof(*wps)); 49939beb93cSSam Leffler if (wps == NULL) 50039beb93cSSam Leffler return -1; 50139beb93cSSam Leffler 50239beb93cSSam Leffler wps->cred_cb = wpa_supplicant_wps_cred; 50339beb93cSSam Leffler wps->event_cb = wpa_supplicant_wps_event; 50439beb93cSSam Leffler wps->cb_ctx = wpa_s; 50539beb93cSSam Leffler 50639beb93cSSam Leffler wps->dev.device_name = wpa_s->conf->device_name; 50739beb93cSSam Leffler wps->dev.manufacturer = wpa_s->conf->manufacturer; 50839beb93cSSam Leffler wps->dev.model_name = wpa_s->conf->model_name; 50939beb93cSSam Leffler wps->dev.model_number = wpa_s->conf->model_number; 51039beb93cSSam Leffler wps->dev.serial_number = wpa_s->conf->serial_number; 51139beb93cSSam Leffler if (wpa_s->conf->device_type) { 51239beb93cSSam Leffler char *pos; 51339beb93cSSam Leffler u8 oui[4]; 51439beb93cSSam Leffler /* <categ>-<OUI>-<subcateg> */ 51539beb93cSSam Leffler wps->dev.categ = atoi(wpa_s->conf->device_type); 51639beb93cSSam Leffler pos = os_strchr(wpa_s->conf->device_type, '-'); 51739beb93cSSam Leffler if (pos == NULL) { 51839beb93cSSam Leffler wpa_printf(MSG_ERROR, "WPS: Invalid device_type"); 51939beb93cSSam Leffler os_free(wps); 52039beb93cSSam Leffler return -1; 52139beb93cSSam Leffler } 52239beb93cSSam Leffler pos++; 52339beb93cSSam Leffler if (hexstr2bin(pos, oui, 4)) { 52439beb93cSSam Leffler wpa_printf(MSG_ERROR, "WPS: Invalid device_type OUI"); 52539beb93cSSam Leffler os_free(wps); 52639beb93cSSam Leffler return -1; 52739beb93cSSam Leffler } 52839beb93cSSam Leffler wps->dev.oui = WPA_GET_BE32(oui); 52939beb93cSSam Leffler pos = os_strchr(pos, '-'); 53039beb93cSSam Leffler if (pos == NULL) { 53139beb93cSSam Leffler wpa_printf(MSG_ERROR, "WPS: Invalid device_type"); 53239beb93cSSam Leffler os_free(wps); 53339beb93cSSam Leffler return -1; 53439beb93cSSam Leffler } 53539beb93cSSam Leffler pos++; 53639beb93cSSam Leffler wps->dev.sub_categ = atoi(pos); 53739beb93cSSam Leffler } 53839beb93cSSam Leffler wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version); 53939beb93cSSam Leffler wps->dev.rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ; /* TODO: config */ 54039beb93cSSam Leffler os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN); 54139beb93cSSam Leffler if (is_nil_uuid(wpa_s->conf->uuid)) { 54239beb93cSSam Leffler uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid); 54339beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC address", 54439beb93cSSam Leffler wps->uuid, WPS_UUID_LEN); 54539beb93cSSam Leffler } else 54639beb93cSSam Leffler os_memcpy(wps->uuid, wpa_s->conf->uuid, WPS_UUID_LEN); 54739beb93cSSam Leffler 54839beb93cSSam Leffler wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; 54939beb93cSSam Leffler wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; 55039beb93cSSam Leffler 55139beb93cSSam Leffler os_memset(&rcfg, 0, sizeof(rcfg)); 55239beb93cSSam Leffler rcfg.new_psk_cb = wpas_wps_new_psk_cb; 55339beb93cSSam Leffler rcfg.pin_needed_cb = wpas_wps_pin_needed_cb; 55439beb93cSSam Leffler rcfg.cb_ctx = wpa_s; 55539beb93cSSam Leffler 55639beb93cSSam Leffler wps->registrar = wps_registrar_init(wps, &rcfg); 55739beb93cSSam Leffler if (wps->registrar == NULL) { 55839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Failed to initialize WPS Registrar"); 55939beb93cSSam Leffler os_free(wps); 56039beb93cSSam Leffler return -1; 56139beb93cSSam Leffler } 56239beb93cSSam Leffler 56339beb93cSSam Leffler wpa_s->wps = wps; 56439beb93cSSam Leffler 56539beb93cSSam Leffler return 0; 56639beb93cSSam Leffler } 56739beb93cSSam Leffler 56839beb93cSSam Leffler 56939beb93cSSam Leffler void wpas_wps_deinit(struct wpa_supplicant *wpa_s) 57039beb93cSSam Leffler { 57139beb93cSSam Leffler eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL); 57239beb93cSSam Leffler 57339beb93cSSam Leffler if (wpa_s->wps == NULL) 57439beb93cSSam Leffler return; 57539beb93cSSam Leffler 57639beb93cSSam Leffler wps_registrar_deinit(wpa_s->wps->registrar); 57739beb93cSSam Leffler os_free(wpa_s->wps->network_key); 57839beb93cSSam Leffler os_free(wpa_s->wps); 57939beb93cSSam Leffler wpa_s->wps = NULL; 58039beb93cSSam Leffler } 58139beb93cSSam Leffler 58239beb93cSSam Leffler 58339beb93cSSam Leffler int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s, 58439beb93cSSam Leffler struct wpa_ssid *ssid, struct wpa_scan_res *bss) 58539beb93cSSam Leffler { 58639beb93cSSam Leffler struct wpabuf *wps_ie; 58739beb93cSSam Leffler 58839beb93cSSam Leffler if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS)) 58939beb93cSSam Leffler return -1; 59039beb93cSSam Leffler 59139beb93cSSam Leffler wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 59239beb93cSSam Leffler if (eap_is_wps_pbc_enrollee(&ssid->eap)) { 59339beb93cSSam Leffler if (!wps_ie) { 59439beb93cSSam Leffler wpa_printf(MSG_DEBUG, " skip - non-WPS AP"); 59539beb93cSSam Leffler return 0; 59639beb93cSSam Leffler } 59739beb93cSSam Leffler 59839beb93cSSam Leffler if (!wps_is_selected_pbc_registrar(wps_ie)) { 59939beb93cSSam Leffler wpa_printf(MSG_DEBUG, " skip - WPS AP " 60039beb93cSSam Leffler "without active PBC Registrar"); 60139beb93cSSam Leffler wpabuf_free(wps_ie); 60239beb93cSSam Leffler return 0; 60339beb93cSSam Leffler } 60439beb93cSSam Leffler 60539beb93cSSam Leffler /* TODO: overlap detection */ 60639beb93cSSam Leffler wpa_printf(MSG_DEBUG, " selected based on WPS IE " 60739beb93cSSam Leffler "(Active PBC)"); 60839beb93cSSam Leffler wpabuf_free(wps_ie); 60939beb93cSSam Leffler return 1; 61039beb93cSSam Leffler } 61139beb93cSSam Leffler 61239beb93cSSam Leffler if (eap_is_wps_pin_enrollee(&ssid->eap)) { 61339beb93cSSam Leffler if (!wps_ie) { 61439beb93cSSam Leffler wpa_printf(MSG_DEBUG, " skip - non-WPS AP"); 61539beb93cSSam Leffler return 0; 61639beb93cSSam Leffler } 61739beb93cSSam Leffler 61839beb93cSSam Leffler /* 61939beb93cSSam Leffler * Start with WPS APs that advertise active PIN Registrar and 62039beb93cSSam Leffler * allow any WPS AP after third scan since some APs do not set 62139beb93cSSam Leffler * Selected Registrar attribute properly when using external 62239beb93cSSam Leffler * Registrar. 62339beb93cSSam Leffler */ 62439beb93cSSam Leffler if (!wps_is_selected_pin_registrar(wps_ie)) { 62539beb93cSSam Leffler if (wpa_s->scan_runs < WPS_PIN_SCAN_IGNORE_SEL_REG) { 62639beb93cSSam Leffler wpa_printf(MSG_DEBUG, " skip - WPS AP " 62739beb93cSSam Leffler "without active PIN Registrar"); 62839beb93cSSam Leffler wpabuf_free(wps_ie); 62939beb93cSSam Leffler return 0; 63039beb93cSSam Leffler } 63139beb93cSSam Leffler wpa_printf(MSG_DEBUG, " selected based on WPS IE"); 63239beb93cSSam Leffler } else { 63339beb93cSSam Leffler wpa_printf(MSG_DEBUG, " selected based on WPS IE " 63439beb93cSSam Leffler "(Active PIN)"); 63539beb93cSSam Leffler } 63639beb93cSSam Leffler wpabuf_free(wps_ie); 63739beb93cSSam Leffler return 1; 63839beb93cSSam Leffler } 63939beb93cSSam Leffler 64039beb93cSSam Leffler if (wps_ie) { 64139beb93cSSam Leffler wpa_printf(MSG_DEBUG, " selected based on WPS IE"); 64239beb93cSSam Leffler wpabuf_free(wps_ie); 64339beb93cSSam Leffler return 1; 64439beb93cSSam Leffler } 64539beb93cSSam Leffler 64639beb93cSSam Leffler return -1; 64739beb93cSSam Leffler } 64839beb93cSSam Leffler 64939beb93cSSam Leffler 65039beb93cSSam Leffler int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s, 65139beb93cSSam Leffler struct wpa_ssid *ssid, 65239beb93cSSam Leffler struct wpa_scan_res *bss) 65339beb93cSSam Leffler { 65439beb93cSSam Leffler struct wpabuf *wps_ie = NULL; 65539beb93cSSam Leffler int ret = 0; 65639beb93cSSam Leffler 65739beb93cSSam Leffler if (eap_is_wps_pbc_enrollee(&ssid->eap)) { 65839beb93cSSam Leffler wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 65939beb93cSSam Leffler if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) { 66039beb93cSSam Leffler /* allow wildcard SSID for WPS PBC */ 66139beb93cSSam Leffler ret = 1; 66239beb93cSSam Leffler } 66339beb93cSSam Leffler } else if (eap_is_wps_pin_enrollee(&ssid->eap)) { 66439beb93cSSam Leffler wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 66539beb93cSSam Leffler if (wps_ie && 66639beb93cSSam Leffler (wps_is_selected_pin_registrar(wps_ie) || 66739beb93cSSam Leffler wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) { 66839beb93cSSam Leffler /* allow wildcard SSID for WPS PIN */ 66939beb93cSSam Leffler ret = 1; 67039beb93cSSam Leffler } 67139beb93cSSam Leffler } 67239beb93cSSam Leffler 67339beb93cSSam Leffler if (!ret && ssid->bssid_set && 67439beb93cSSam Leffler os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) { 67539beb93cSSam Leffler /* allow wildcard SSID due to hardcoded BSSID match */ 67639beb93cSSam Leffler ret = 1; 67739beb93cSSam Leffler } 67839beb93cSSam Leffler 67939beb93cSSam Leffler wpabuf_free(wps_ie); 68039beb93cSSam Leffler 68139beb93cSSam Leffler return ret; 68239beb93cSSam Leffler } 68339beb93cSSam Leffler 68439beb93cSSam Leffler 68539beb93cSSam Leffler int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, 68639beb93cSSam Leffler struct wpa_scan_res *selected, 68739beb93cSSam Leffler struct wpa_ssid *ssid) 68839beb93cSSam Leffler { 68939beb93cSSam Leffler const u8 *sel_uuid, *uuid; 69039beb93cSSam Leffler size_t i; 69139beb93cSSam Leffler struct wpabuf *wps_ie; 69239beb93cSSam Leffler int ret = 0; 69339beb93cSSam Leffler 69439beb93cSSam Leffler if (!eap_is_wps_pbc_enrollee(&ssid->eap)) 69539beb93cSSam Leffler return 0; 69639beb93cSSam Leffler 69739beb93cSSam Leffler /* Make sure that only one AP is in active PBC mode */ 69839beb93cSSam Leffler wps_ie = wpa_scan_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE); 69939beb93cSSam Leffler if (wps_ie) 70039beb93cSSam Leffler sel_uuid = wps_get_uuid_e(wps_ie); 70139beb93cSSam Leffler else 70239beb93cSSam Leffler sel_uuid = NULL; 70339beb93cSSam Leffler 70439beb93cSSam Leffler for (i = 0; i < wpa_s->scan_res->num; i++) { 70539beb93cSSam Leffler struct wpa_scan_res *bss = wpa_s->scan_res->res[i]; 70639beb93cSSam Leffler struct wpabuf *ie; 70739beb93cSSam Leffler if (bss == selected) 70839beb93cSSam Leffler continue; 70939beb93cSSam Leffler ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 71039beb93cSSam Leffler if (!ie) 71139beb93cSSam Leffler continue; 71239beb93cSSam Leffler if (!wps_is_selected_pbc_registrar(ie)) { 71339beb93cSSam Leffler wpabuf_free(ie); 71439beb93cSSam Leffler continue; 71539beb93cSSam Leffler } 71639beb93cSSam Leffler uuid = wps_get_uuid_e(ie); 71739beb93cSSam Leffler if (sel_uuid == NULL || uuid == NULL || 71839beb93cSSam Leffler os_memcmp(sel_uuid, uuid, 16) != 0) { 71939beb93cSSam Leffler ret = 1; /* PBC overlap */ 72039beb93cSSam Leffler wpabuf_free(ie); 72139beb93cSSam Leffler break; 72239beb93cSSam Leffler } 72339beb93cSSam Leffler 72439beb93cSSam Leffler /* TODO: verify that this is reasonable dual-band situation */ 72539beb93cSSam Leffler 72639beb93cSSam Leffler wpabuf_free(ie); 72739beb93cSSam Leffler } 72839beb93cSSam Leffler 72939beb93cSSam Leffler wpabuf_free(wps_ie); 73039beb93cSSam Leffler 73139beb93cSSam Leffler return ret; 73239beb93cSSam Leffler } 73339beb93cSSam Leffler 73439beb93cSSam Leffler 73539beb93cSSam Leffler void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s) 73639beb93cSSam Leffler { 73739beb93cSSam Leffler size_t i; 73839beb93cSSam Leffler 73939beb93cSSam Leffler if (wpa_s->disconnected || wpa_s->wpa_state >= WPA_ASSOCIATED) 74039beb93cSSam Leffler return; 74139beb93cSSam Leffler 74239beb93cSSam Leffler for (i = 0; i < wpa_s->scan_res->num; i++) { 74339beb93cSSam Leffler struct wpa_scan_res *bss = wpa_s->scan_res->res[i]; 74439beb93cSSam Leffler struct wpabuf *ie; 74539beb93cSSam Leffler ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 74639beb93cSSam Leffler if (!ie) 74739beb93cSSam Leffler continue; 74839beb93cSSam Leffler if (wps_is_selected_pbc_registrar(ie)) 74939beb93cSSam Leffler wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PBC); 75039beb93cSSam Leffler else if (wps_is_selected_pin_registrar(ie)) 75139beb93cSSam Leffler wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PIN); 75239beb93cSSam Leffler else 75339beb93cSSam Leffler wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE); 75439beb93cSSam Leffler wpabuf_free(ie); 75539beb93cSSam Leffler break; 75639beb93cSSam Leffler } 75739beb93cSSam Leffler } 75839beb93cSSam Leffler 75939beb93cSSam Leffler 76039beb93cSSam Leffler int wpas_wps_searching(struct wpa_supplicant *wpa_s) 76139beb93cSSam Leffler { 76239beb93cSSam Leffler struct wpa_ssid *ssid; 76339beb93cSSam Leffler 76439beb93cSSam Leffler for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 76539beb93cSSam Leffler if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !ssid->disabled) 76639beb93cSSam Leffler return 1; 76739beb93cSSam Leffler } 76839beb93cSSam Leffler 76939beb93cSSam Leffler return 0; 77039beb93cSSam Leffler } 771