LCOV - code coverage report
Current view: top level - wpa_supplicant - wps_supplicant.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1426431149 Lines: 1237 1479 83.6 %
Date: 2015-03-15 Functions: 74 78 94.9 %

          Line data    Source code
       1             : /*
       2             :  * wpa_supplicant / WPS integration
       3             :  * Copyright (c) 2008-2014, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "eloop.h"
      13             : #include "uuid.h"
      14             : #include "crypto/random.h"
      15             : #include "crypto/dh_group5.h"
      16             : #include "common/ieee802_11_defs.h"
      17             : #include "common/ieee802_11_common.h"
      18             : #include "common/wpa_common.h"
      19             : #include "common/wpa_ctrl.h"
      20             : #include "eap_common/eap_wsc_common.h"
      21             : #include "eap_peer/eap.h"
      22             : #include "eapol_supp/eapol_supp_sm.h"
      23             : #include "rsn_supp/wpa.h"
      24             : #include "wps/wps_attr_parse.h"
      25             : #include "config.h"
      26             : #include "wpa_supplicant_i.h"
      27             : #include "driver_i.h"
      28             : #include "notify.h"
      29             : #include "blacklist.h"
      30             : #include "bss.h"
      31             : #include "scan.h"
      32             : #include "ap.h"
      33             : #include "p2p/p2p.h"
      34             : #include "p2p_supplicant.h"
      35             : #include "wps_supplicant.h"
      36             : 
      37             : 
      38             : #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
      39             : #define WPS_PIN_SCAN_IGNORE_SEL_REG 3
      40             : #endif /* WPS_PIN_SCAN_IGNORE_SEL_REG */
      41             : 
      42             : static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx);
      43             : static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
      44             : 
      45             : 
      46        6028 : static void wpas_wps_clear_ap_info(struct wpa_supplicant *wpa_s)
      47             : {
      48        6028 :         os_free(wpa_s->wps_ap);
      49        6028 :         wpa_s->wps_ap = NULL;
      50        6028 :         wpa_s->num_wps_ap = 0;
      51        6028 :         wpa_s->wps_ap_iter = 0;
      52        6028 : }
      53             : 
      54             : 
      55         246 : static void wpas_wps_assoc_with_cred(void *eloop_ctx, void *timeout_ctx)
      56             : {
      57         246 :         struct wpa_supplicant *wpa_s = eloop_ctx;
      58         246 :         int use_fast_assoc = timeout_ctx != NULL;
      59             : 
      60         246 :         wpa_printf(MSG_DEBUG, "WPS: Continuing association after eapol_cb");
      61         480 :         if (!use_fast_assoc ||
      62         234 :             wpa_supplicant_fast_associate(wpa_s) != 1)
      63          12 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
      64         246 : }
      65             : 
      66             : 
      67         534 : static void wpas_wps_assoc_with_cred_cancel(struct wpa_supplicant *wpa_s)
      68             : {
      69         534 :         eloop_cancel_timeout(wpas_wps_assoc_with_cred, wpa_s, (void *) 0);
      70         534 :         eloop_cancel_timeout(wpas_wps_assoc_with_cred, wpa_s, (void *) 1);
      71         534 : }
      72             : 
      73             : 
      74        2068 : int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
      75             : {
      76        2068 :         if (wpas_p2p_wps_eapol_cb(wpa_s) > 0)
      77           3 :                 return 1;
      78             : 
      79        2785 :         if (!wpa_s->wps_success &&
      80        1440 :             wpa_s->current_ssid &&
      81         720 :             eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
      82          11 :                 const u8 *bssid = wpa_s->bssid;
      83          11 :                 if (is_zero_ether_addr(bssid))
      84           0 :                         bssid = wpa_s->pending_bssid;
      85             : 
      86          66 :                 wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR
      87             :                            " did not succeed - continue trying to find "
      88          66 :                            "suitable AP", MAC2STR(bssid));
      89          11 :                 wpa_blacklist_add(wpa_s, bssid);
      90             : 
      91          11 :                 wpa_supplicant_deauthenticate(wpa_s,
      92             :                                               WLAN_REASON_DEAUTH_LEAVING);
      93          11 :                 wpa_s->reassociate = 1;
      94          11 :                 wpa_supplicant_req_scan(wpa_s,
      95          11 :                                         wpa_s->blacklist_cleared ? 5 : 0, 0);
      96          11 :                 wpa_s->blacklist_cleared = 0;
      97          11 :                 return 1;
      98             :         }
      99             : 
     100        2054 :         wpas_wps_clear_ap_info(wpa_s);
     101        2054 :         eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
     102        2054 :         if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && !wpa_s->wps_success)
     103          43 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL);
     104             : 
     105        2324 :         if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid &&
     106         270 :             !(wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
     107         246 :                 int disabled = wpa_s->current_ssid->disabled;
     108         246 :                 unsigned int freq = wpa_s->assoc_freq;
     109             :                 struct wpa_bss *bss;
     110         246 :                 struct wpa_ssid *ssid = NULL;
     111         246 :                 int use_fast_assoc = 0;
     112             : 
     113         246 :                 wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - "
     114             :                            "try to associate with the received credential "
     115             :                            "(freq=%u)", freq);
     116         246 :                 wpa_s->own_disconnect_req = 1;
     117         246 :                 wpa_supplicant_deauthenticate(wpa_s,
     118             :                                               WLAN_REASON_DEAUTH_LEAVING);
     119         246 :                 if (disabled) {
     120           0 :                         wpa_printf(MSG_DEBUG, "WPS: Current network is "
     121             :                                    "disabled - wait for user to enable");
     122           0 :                         return 1;
     123             :                 }
     124         246 :                 wpa_s->after_wps = 5;
     125         246 :                 wpa_s->wps_freq = freq;
     126         246 :                 wpa_s->normal_scans = 0;
     127         246 :                 wpa_s->reassociate = 1;
     128             : 
     129         246 :                 wpa_printf(MSG_DEBUG, "WPS: Checking whether fast association "
     130             :                            "without a new scan can be used");
     131         246 :                 bss = wpa_supplicant_pick_network(wpa_s, &ssid);
     132         246 :                 if (bss) {
     133             :                         struct wpabuf *wps;
     134             :                         struct wps_parse_attr attr;
     135             : 
     136         234 :                         wps = wpa_bss_get_vendor_ie_multi(bss,
     137             :                                                           WPS_IE_VENDOR_TYPE);
     138         468 :                         if (wps && wps_parse_msg(wps, &attr) == 0 &&
     139         468 :                             attr.wps_state &&
     140         234 :                             *attr.wps_state == WPS_STATE_CONFIGURED)
     141         234 :                                 use_fast_assoc = 1;
     142         234 :                         wpabuf_free(wps);
     143             :                 }
     144             : 
     145             :                 /*
     146             :                  * Complete the next step from an eloop timeout to allow pending
     147             :                  * driver events related to the disconnection to be processed
     148             :                  * first. This makes it less likely for disconnection event to
     149             :                  * cause problems with the following connection.
     150             :                  */
     151         246 :                 wpa_printf(MSG_DEBUG, "WPS: Continue association from timeout");
     152         246 :                 wpas_wps_assoc_with_cred_cancel(wpa_s);
     153         246 :                 eloop_register_timeout(0, 10000,
     154             :                                        wpas_wps_assoc_with_cred, wpa_s,
     155             :                                        use_fast_assoc ? (void *) 1 :
     156             :                                        (void *) 0);
     157         246 :                 return 1;
     158             :         }
     159             : 
     160        1808 :         if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) {
     161          24 :                 wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting "
     162             :                            "for external credential processing");
     163          24 :                 wpas_clear_wps(wpa_s);
     164          24 :                 wpa_s->own_disconnect_req = 1;
     165          24 :                 wpa_supplicant_deauthenticate(wpa_s,
     166             :                                               WLAN_REASON_DEAUTH_LEAVING);
     167          24 :                 return 1;
     168             :         }
     169             : 
     170        1784 :         return 0;
     171             : }
     172             : 
     173             : 
     174         254 : static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s,
     175             :                                          struct wpa_ssid *ssid,
     176             :                                          const struct wps_credential *cred)
     177             : {
     178             :         struct wpa_driver_capa capa;
     179             :         struct wpa_bss *bss;
     180             :         const u8 *ie;
     181             :         struct wpa_ie_data adv;
     182         254 :         int wpa2 = 0, ccmp = 0;
     183             : 
     184             :         /*
     185             :          * Many existing WPS APs do not know how to negotiate WPA2 or CCMP in
     186             :          * case they are configured for mixed mode operation (WPA+WPA2 and
     187             :          * TKIP+CCMP). Try to use scan results to figure out whether the AP
     188             :          * actually supports stronger security and select that if the client
     189             :          * has support for it, too.
     190             :          */
     191             : 
     192         254 :         if (wpa_drv_get_capa(wpa_s, &capa))
     193         233 :                 return; /* Unknown what driver supports */
     194             : 
     195         254 :         if (ssid->ssid == NULL)
     196           0 :                 return;
     197         254 :         bss = wpa_bss_get(wpa_s, cred->mac_addr, ssid->ssid, ssid->ssid_len);
     198         254 :         if (bss == NULL) {
     199         233 :                 wpa_printf(MSG_DEBUG, "WPS: The AP was not found from BSS "
     200             :                            "table - use credential as-is");
     201         233 :                 return;
     202             :         }
     203             : 
     204          21 :         wpa_printf(MSG_DEBUG, "WPS: AP found from BSS table");
     205             : 
     206          21 :         ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
     207          21 :         if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0) {
     208          20 :                 wpa2 = 1;
     209          40 :                 if (adv.pairwise_cipher & WPA_CIPHER_CCMP)
     210          20 :                         ccmp = 1;
     211             :         } else {
     212           1 :                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
     213           1 :                 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0 &&
     214           0 :                     adv.pairwise_cipher & WPA_CIPHER_CCMP)
     215           0 :                         ccmp = 1;
     216             :         }
     217             : 
     218          21 :         if (ie == NULL && (ssid->proto & WPA_PROTO_WPA) &&
     219           0 :             (ssid->pairwise_cipher & WPA_CIPHER_TKIP)) {
     220             :                 /*
     221             :                  * TODO: This could be the initial AP configuration and the
     222             :                  * Beacon contents could change shortly. Should request a new
     223             :                  * scan and delay addition of the network until the updated
     224             :                  * scan results are available.
     225             :                  */
     226           0 :                 wpa_printf(MSG_DEBUG, "WPS: The AP did not yet advertise WPA "
     227             :                            "support - use credential as-is");
     228           0 :                 return;
     229             :         }
     230             : 
     231          21 :         if (ccmp && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
     232           0 :             (ssid->pairwise_cipher & WPA_CIPHER_TKIP) &&
     233           0 :             (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
     234           0 :                 wpa_printf(MSG_DEBUG, "WPS: Add CCMP into the credential "
     235             :                            "based on scan results");
     236           0 :                 if (wpa_s->conf->ap_scan == 1)
     237           0 :                         ssid->pairwise_cipher |= WPA_CIPHER_CCMP;
     238             :                 else
     239           0 :                         ssid->pairwise_cipher = WPA_CIPHER_CCMP;
     240             :         }
     241             : 
     242          21 :         if (wpa2 && !(ssid->proto & WPA_PROTO_RSN) &&
     243           0 :             (ssid->proto & WPA_PROTO_WPA) &&
     244           0 :             (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP)) {
     245           0 :                 wpa_printf(MSG_DEBUG, "WPS: Add WPA2 into the credential "
     246             :                            "based on scan results");
     247           0 :                 if (wpa_s->conf->ap_scan == 1)
     248           0 :                         ssid->proto |= WPA_PROTO_RSN;
     249             :                 else
     250           0 :                         ssid->proto = WPA_PROTO_RSN;
     251             :         }
     252             : }
     253             : 
     254             : 
     255         254 : static void wpas_wps_remove_dup_network(struct wpa_supplicant *wpa_s,
     256             :                                         struct wpa_ssid *new_ssid)
     257             : {
     258             :         struct wpa_ssid *ssid, *next;
     259             : 
     260         771 :         for (ssid = wpa_s->conf->ssid, next = ssid ? ssid->next : NULL; ssid;
     261         263 :              ssid = next, next = ssid ? ssid->next : NULL) {
     262             :                 /*
     263             :                  * new_ssid has already been added to the list in
     264             :                  * wpas_wps_add_network(), so skip it.
     265             :                  */
     266         263 :                 if (ssid == new_ssid)
     267         254 :                         continue;
     268             : 
     269           9 :                 if (ssid->bssid_set || new_ssid->bssid_set) {
     270           3 :                         if (ssid->bssid_set != new_ssid->bssid_set)
     271           2 :                                 continue;
     272           1 :                         if (os_memcmp(ssid->bssid, new_ssid->bssid, ETH_ALEN) !=
     273             :                             0)
     274           0 :                                 continue;
     275             :                 }
     276             : 
     277             :                 /* compare SSID */
     278           7 :                 if (ssid->ssid_len == 0 || ssid->ssid_len != new_ssid->ssid_len)
     279           3 :                         continue;
     280             : 
     281           4 :                 if (ssid->ssid && new_ssid->ssid) {
     282           8 :                         if (os_memcmp(ssid->ssid, new_ssid->ssid,
     283             :                                       ssid->ssid_len) != 0)
     284           0 :                                 continue;
     285           0 :                 } else if (ssid->ssid || new_ssid->ssid)
     286           0 :                         continue;
     287             : 
     288             :                 /* compare security parameters */
     289           7 :                 if (ssid->auth_alg != new_ssid->auth_alg ||
     290           6 :                     ssid->key_mgmt != new_ssid->key_mgmt ||
     291           5 :                     (ssid->group_cipher != new_ssid->group_cipher &&
     292           2 :                      !(ssid->group_cipher & new_ssid->group_cipher &
     293             :                        WPA_CIPHER_CCMP)))
     294           1 :                         continue;
     295             : 
     296             :                 /*
     297             :                  * Some existing WPS APs will send two creds in case they are
     298             :                  * configured for mixed mode operation (WPA+WPA2 and TKIP+CCMP).
     299             :                  * Try to merge these two creds if they are received in the same
     300             :                  * M8 message.
     301             :                  */
     302           4 :                 if (ssid->wps_run && ssid->wps_run == new_ssid->wps_run &&
     303           1 :                     wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
     304           2 :                         if (new_ssid->passphrase && ssid->passphrase &&
     305           1 :                             os_strcmp(new_ssid->passphrase, ssid->passphrase) !=
     306             :                             0) {
     307           0 :                                 wpa_printf(MSG_DEBUG,
     308             :                                            "WPS: M8 Creds with different passphrase - do not merge");
     309           0 :                                 continue;
     310             :                         }
     311             : 
     312           2 :                         if (new_ssid->psk_set &&
     313           2 :                             (!ssid->psk_set ||
     314           1 :                              os_memcmp(new_ssid->psk, ssid->psk, 32) != 0)) {
     315           0 :                                 wpa_printf(MSG_DEBUG,
     316             :                                            "WPS: M8 Creds with different PSK - do not merge");
     317           0 :                                 continue;
     318             :                         }
     319             : 
     320           2 :                         if ((new_ssid->passphrase && !ssid->passphrase) ||
     321           1 :                             (!new_ssid->passphrase && ssid->passphrase)) {
     322           0 :                                 wpa_printf(MSG_DEBUG,
     323             :                                            "WPS: M8 Creds with different passphrase/PSK type - do not merge");
     324           0 :                                 continue;
     325             :                         }
     326             : 
     327           1 :                         wpa_printf(MSG_DEBUG,
     328             :                                    "WPS: Workaround - merge likely WPA/WPA2-mixed mode creds in same M8 message");
     329           1 :                         new_ssid->proto |= ssid->proto;
     330           1 :                         new_ssid->pairwise_cipher |= ssid->pairwise_cipher;
     331             :                 } else {
     332             :                         /*
     333             :                          * proto and pairwise_cipher difference matter for
     334             :                          * non-mixed-mode creds.
     335             :                          */
     336           4 :                         if (ssid->proto != new_ssid->proto ||
     337           2 :                             ssid->pairwise_cipher != new_ssid->pairwise_cipher)
     338           1 :                                 continue;
     339             :                 }
     340             : 
     341             :                 /* Remove the duplicated older network entry. */
     342           2 :                 wpa_printf(MSG_DEBUG, "Remove duplicate network %d", ssid->id);
     343           2 :                 wpas_notify_network_removed(wpa_s, ssid);
     344           2 :                 if (wpa_s->current_ssid == ssid)
     345           1 :                         wpa_s->current_ssid = NULL;
     346           2 :                 wpa_config_remove_network(wpa_s->conf, ssid->id);
     347             :         }
     348         254 : }
     349             : 
     350             : 
     351         254 : static int wpa_supplicant_wps_cred(void *ctx,
     352             :                                    const struct wps_credential *cred)
     353             : {
     354         254 :         struct wpa_supplicant *wpa_s = ctx;
     355         254 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
     356             :         u16 auth_type;
     357             : #ifdef CONFIG_WPS_REG_DISABLE_OPEN
     358             :         int registrar = 0;
     359             : #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
     360             : 
     361         508 :         if ((wpa_s->conf->wps_cred_processing == 1 ||
     362         276 :              wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
     363          11 :                 size_t blen = cred->cred_attr_len * 2 + 1;
     364          11 :                 char *buf = os_malloc(blen);
     365          11 :                 if (buf) {
     366          11 :                         wpa_snprintf_hex(buf, blen,
     367             :                                          cred->cred_attr, cred->cred_attr_len);
     368          11 :                         wpa_msg(wpa_s, MSG_INFO, "%s%s",
     369             :                                 WPS_EVENT_CRED_RECEIVED, buf);
     370          11 :                         os_free(buf);
     371             :                 }
     372             : 
     373          11 :                 wpas_notify_wps_credential(wpa_s, cred);
     374             :         } else
     375         243 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
     376             : 
     377         508 :         wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
     378         254 :                         cred->cred_attr, cred->cred_attr_len);
     379             : 
     380         254 :         if (wpa_s->conf->wps_cred_processing == 1)
     381           0 :                 return 0;
     382             : 
     383         254 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len);
     384         254 :         wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x",
     385         254 :                    cred->auth_type);
     386         254 :         wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type);
     387         254 :         wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx);
     388         508 :         wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key",
     389         254 :                         cred->key, cred->key_len);
     390        1524 :         wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR,
     391        1524 :                    MAC2STR(cred->mac_addr));
     392             : 
     393         254 :         auth_type = cred->auth_type;
     394         254 :         if (auth_type == (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
     395           0 :                 wpa_printf(MSG_DEBUG, "WPS: Workaround - convert mixed-mode "
     396             :                            "auth_type into WPA2PSK");
     397           0 :                 auth_type = WPS_AUTH_WPA2PSK;
     398             :         }
     399             : 
     400         254 :         if (auth_type != WPS_AUTH_OPEN &&
     401         251 :             auth_type != WPS_AUTH_WPAPSK &&
     402             :             auth_type != WPS_AUTH_WPA2PSK) {
     403           0 :                 wpa_printf(MSG_DEBUG, "WPS: Ignored credentials for "
     404             :                            "unsupported authentication type 0x%x",
     405             :                            auth_type);
     406           0 :                 return 0;
     407             :         }
     408             : 
     409         254 :         if (auth_type == WPS_AUTH_WPAPSK || auth_type == WPS_AUTH_WPA2PSK) {
     410         253 :                 if (cred->key_len < 8 || cred->key_len > 2 * PMK_LEN) {
     411           0 :                         wpa_printf(MSG_ERROR, "WPS: Reject PSK credential with "
     412             :                                    "invalid Network Key length %lu",
     413             :                                    (unsigned long) cred->key_len);
     414           0 :                         return -1;
     415             :                 }
     416             :         }
     417             : 
     418         254 :         if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
     419         247 :                 wpa_printf(MSG_DEBUG, "WPS: Replace WPS network block based "
     420             :                            "on the received credential");
     421             : #ifdef CONFIG_WPS_REG_DISABLE_OPEN
     422             :                 if (ssid->eap.identity &&
     423             :                     ssid->eap.identity_len == WSC_ID_REGISTRAR_LEN &&
     424             :                     os_memcmp(ssid->eap.identity, WSC_ID_REGISTRAR,
     425             :                               WSC_ID_REGISTRAR_LEN) == 0)
     426             :                         registrar = 1;
     427             : #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
     428         247 :                 os_free(ssid->eap.identity);
     429         247 :                 ssid->eap.identity = NULL;
     430         247 :                 ssid->eap.identity_len = 0;
     431         247 :                 os_free(ssid->eap.phase1);
     432         247 :                 ssid->eap.phase1 = NULL;
     433         247 :                 os_free(ssid->eap.eap_methods);
     434         247 :                 ssid->eap.eap_methods = NULL;
     435         247 :                 if (!ssid->p2p_group) {
     436          85 :                         ssid->temporary = 0;
     437          85 :                         ssid->bssid_set = 0;
     438             :                 }
     439         247 :                 ssid->disabled_until.sec = 0;
     440         247 :                 ssid->disabled_until.usec = 0;
     441         247 :                 ssid->auth_failures = 0;
     442             :         } else {
     443           7 :                 wpa_printf(MSG_DEBUG, "WPS: Create a new network based on the "
     444             :                            "received credential");
     445           7 :                 ssid = wpa_config_add_network(wpa_s->conf);
     446           7 :                 if (ssid == NULL)
     447           0 :                         return -1;
     448           7 :                 if (wpa_s->current_ssid) {
     449             :                         /*
     450             :                          * Should the GO issue multiple credentials for some
     451             :                          * reason, each credential should be marked as a
     452             :                          * temporary P2P group similarly to the one that gets
     453             :                          * marked as such based on the pre-configured values
     454             :                          * used for the WPS network block.
     455             :                          */
     456           3 :                         ssid->p2p_group = wpa_s->current_ssid->p2p_group;
     457           3 :                         ssid->temporary = wpa_s->current_ssid->temporary;
     458             :                 }
     459           7 :                 wpas_notify_network_added(wpa_s, ssid);
     460             :         }
     461             : 
     462         254 :         wpa_config_set_network_defaults(ssid);
     463         254 :         ssid->wps_run = wpa_s->wps_run;
     464             : 
     465         254 :         os_free(ssid->ssid);
     466         254 :         ssid->ssid = os_malloc(cred->ssid_len);
     467         254 :         if (ssid->ssid) {
     468         254 :                 os_memcpy(ssid->ssid, cred->ssid, cred->ssid_len);
     469         254 :                 ssid->ssid_len = cred->ssid_len;
     470             :         }
     471             : 
     472         254 :         switch (cred->encr_type) {
     473             :         case WPS_ENCR_NONE:
     474           1 :                 break;
     475             :         case WPS_ENCR_TKIP:
     476           2 :                 ssid->pairwise_cipher = WPA_CIPHER_TKIP;
     477           2 :                 break;
     478             :         case WPS_ENCR_AES:
     479         251 :                 ssid->pairwise_cipher = WPA_CIPHER_CCMP;
     480         502 :                 if (wpa_s->drv_capa_known &&
     481         251 :                     (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP)) {
     482         251 :                         ssid->pairwise_cipher |= WPA_CIPHER_GCMP;
     483         251 :                         ssid->group_cipher |= WPA_CIPHER_GCMP;
     484             :                 }
     485         251 :                 break;
     486             :         }
     487             : 
     488         254 :         switch (auth_type) {
     489             :         case WPS_AUTH_OPEN:
     490           1 :                 ssid->auth_alg = WPA_AUTH_ALG_OPEN;
     491           1 :                 ssid->key_mgmt = WPA_KEY_MGMT_NONE;
     492           1 :                 ssid->proto = 0;
     493             : #ifdef CONFIG_WPS_REG_DISABLE_OPEN
     494             :                 if (registrar) {
     495             :                         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OPEN_NETWORK
     496             :                                 "id=%d - Credentials for an open "
     497             :                                 "network disabled by default - use "
     498             :                                 "'select_network %d' to enable",
     499             :                                 ssid->id, ssid->id);
     500             :                         ssid->disabled = 1;
     501             :                 }
     502             : #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
     503           1 :                 break;
     504             :         case WPS_AUTH_WPAPSK:
     505           2 :                 ssid->auth_alg = WPA_AUTH_ALG_OPEN;
     506           2 :                 ssid->key_mgmt = WPA_KEY_MGMT_PSK;
     507           2 :                 ssid->proto = WPA_PROTO_WPA;
     508           2 :                 break;
     509             :         case WPS_AUTH_WPA2PSK:
     510         251 :                 ssid->auth_alg = WPA_AUTH_ALG_OPEN;
     511         251 :                 ssid->key_mgmt = WPA_KEY_MGMT_PSK;
     512         251 :                 ssid->proto = WPA_PROTO_RSN;
     513         251 :                 break;
     514             :         }
     515             : 
     516         254 :         if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) {
     517         253 :                 if (cred->key_len == 2 * PMK_LEN) {
     518         179 :                         if (hexstr2bin((const char *) cred->key, ssid->psk,
     519             :                                        PMK_LEN)) {
     520           0 :                                 wpa_printf(MSG_ERROR, "WPS: Invalid Network "
     521             :                                            "Key");
     522           0 :                                 return -1;
     523             :                         }
     524         179 :                         ssid->psk_set = 1;
     525         179 :                         ssid->export_keys = 1;
     526          74 :                 } else if (cred->key_len >= 8 && cred->key_len < 2 * PMK_LEN) {
     527          74 :                         os_free(ssid->passphrase);
     528          74 :                         ssid->passphrase = os_malloc(cred->key_len + 1);
     529          74 :                         if (ssid->passphrase == NULL)
     530           0 :                                 return -1;
     531          74 :                         os_memcpy(ssid->passphrase, cred->key, cred->key_len);
     532          74 :                         ssid->passphrase[cred->key_len] = '\0';
     533          74 :                         wpa_config_update_psk(ssid);
     534          74 :                         ssid->export_keys = 1;
     535             :                 } else {
     536           0 :                         wpa_printf(MSG_ERROR, "WPS: Invalid Network Key "
     537             :                                    "length %lu",
     538             :                                    (unsigned long) cred->key_len);
     539           0 :                         return -1;
     540             :                 }
     541             :         }
     542             : 
     543         254 :         wpas_wps_security_workaround(wpa_s, ssid, cred);
     544             : 
     545         254 :         wpas_wps_remove_dup_network(wpa_s, ssid);
     546             : 
     547             : #ifndef CONFIG_NO_CONFIG_WRITE
     548         254 :         if (wpa_s->conf->update_config &&
     549           0 :             wpa_config_write(wpa_s->confname, wpa_s->conf)) {
     550           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to update configuration");
     551           0 :                 return -1;
     552             :         }
     553             : #endif /* CONFIG_NO_CONFIG_WRITE */
     554             : 
     555             :         /*
     556             :          * Optimize the post-WPS scan based on the channel used during
     557             :          * the provisioning in case EAP-Failure is not received.
     558             :          */
     559         254 :         wpa_s->after_wps = 5;
     560         254 :         wpa_s->wps_freq = wpa_s->assoc_freq;
     561             : 
     562         254 :         return 0;
     563             : }
     564             : 
     565             : 
     566          25 : static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s,
     567             :                                          struct wps_event_m2d *m2d)
     568             : {
     569          50 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_M2D
     570             :                 "dev_password_id=%d config_error=%d",
     571          50 :                 m2d->dev_password_id, m2d->config_error);
     572          25 :         wpas_notify_wps_event_m2d(wpa_s, m2d);
     573             : #ifdef CONFIG_P2P
     574          25 :         if (wpa_s->parent && wpa_s->parent != wpa_s) {
     575           4 :                 wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_M2D
     576             :                         "dev_password_id=%d config_error=%d",
     577           4 :                         m2d->dev_password_id, m2d->config_error);
     578             :         }
     579          25 :         if (m2d->config_error == WPS_CFG_MULTIPLE_PBC_DETECTED) {
     580             :                 /*
     581             :                  * Notify P2P from eloop timeout to avoid issues with the
     582             :                  * interface getting removed while processing a message.
     583             :                  */
     584           5 :                 eloop_register_timeout(0, 0, wpas_p2p_pbc_overlap_cb, wpa_s,
     585             :                                        NULL);
     586             :         }
     587             : #endif /* CONFIG_P2P */
     588          25 : }
     589             : 
     590             : 
     591          19 : static void wpas_wps_clear_timeout(void *eloop_ctx, void *timeout_ctx)
     592             : {
     593          19 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     594          19 :         wpa_printf(MSG_DEBUG, "WPS: Clear WPS network from timeout");
     595          19 :         wpas_clear_wps(wpa_s);
     596          19 : }
     597             : 
     598             : 
     599          43 : static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
     600             :                                           struct wps_event_fail *fail)
     601             : {
     602          44 :         if (fail->error_indication > 0 &&
     603           1 :             fail->error_indication < NUM_WPS_EI_VALUES) {
     604           3 :                 wpa_msg(wpa_s, MSG_INFO,
     605             :                         WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
     606           2 :                         fail->msg, fail->config_error, fail->error_indication,
     607           1 :                         wps_ei_str(fail->error_indication));
     608           2 :                 if (wpa_s->parent && wpa_s->parent != wpa_s)
     609           0 :                         wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
     610             :                                 "msg=%d config_error=%d reason=%d (%s)",
     611           0 :                                 fail->msg, fail->config_error,
     612           0 :                                 fail->error_indication,
     613           0 :                                 wps_ei_str(fail->error_indication));
     614             :         } else {
     615          42 :                 wpa_msg(wpa_s, MSG_INFO,
     616             :                         WPS_EVENT_FAIL "msg=%d config_error=%d",
     617          42 :                         fail->msg, fail->config_error);
     618          42 :                 if (wpa_s->parent && wpa_s->parent != wpa_s)
     619           1 :                         wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
     620             :                                 "msg=%d config_error=%d",
     621           1 :                                 fail->msg, fail->config_error);
     622             :         }
     623             : 
     624             :         /*
     625             :          * Need to allow WPS processing to complete, e.g., by sending WSC_NACK.
     626             :          */
     627          43 :         wpa_printf(MSG_DEBUG, "WPS: Register timeout to clear WPS network");
     628          43 :         eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL);
     629          43 :         eloop_register_timeout(0, 100000, wpas_wps_clear_timeout, wpa_s, NULL);
     630             : 
     631          43 :         wpas_notify_wps_event_fail(wpa_s, fail);
     632          43 :         wpas_p2p_wps_failed(wpa_s, fail);
     633          43 : }
     634             : 
     635             : 
     636             : static void wpas_wps_reenable_networks_cb(void *eloop_ctx, void *timeout_ctx);
     637             : 
     638        3689 : static void wpas_wps_reenable_networks(struct wpa_supplicant *wpa_s)
     639             : {
     640             :         struct wpa_ssid *ssid;
     641        3689 :         int changed = 0;
     642             : 
     643        3689 :         eloop_cancel_timeout(wpas_wps_reenable_networks_cb, wpa_s, NULL);
     644             : 
     645        4696 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
     646        1007 :                 if (ssid->disabled_for_connect && ssid->disabled) {
     647           4 :                         ssid->disabled_for_connect = 0;
     648           4 :                         ssid->disabled = 0;
     649           4 :                         wpas_notify_network_enabled_changed(wpa_s, ssid);
     650           4 :                         changed++;
     651             :                 }
     652             :         }
     653             : 
     654        3689 :         if (changed) {
     655             : #ifndef CONFIG_NO_CONFIG_WRITE
     656           3 :                 if (wpa_s->conf->update_config &&
     657           0 :                     wpa_config_write(wpa_s->confname, wpa_s->conf)) {
     658           0 :                         wpa_printf(MSG_DEBUG, "WPS: Failed to update "
     659             :                                    "configuration");
     660             :                 }
     661             : #endif /* CONFIG_NO_CONFIG_WRITE */
     662             :         }
     663        3689 : }
     664             : 
     665             : 
     666           3 : static void wpas_wps_reenable_networks_cb(void *eloop_ctx, void *timeout_ctx)
     667             : {
     668           3 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     669             :         /* Enable the networks disabled during wpas_wps_reassoc */
     670           3 :         wpas_wps_reenable_networks(wpa_s);
     671           3 : }
     672             : 
     673             : 
     674         235 : static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s)
     675             : {
     676         235 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
     677         235 :         wpa_s->wps_success = 1;
     678         235 :         wpas_notify_wps_event_success(wpa_s);
     679         235 :         if (wpa_s->current_ssid)
     680         234 :                 wpas_clear_temp_disabled(wpa_s, wpa_s->current_ssid, 1);
     681         235 :         wpa_s->extra_blacklist_count = 0;
     682             : 
     683             :         /*
     684             :          * Enable the networks disabled during wpas_wps_reassoc after 10
     685             :          * seconds. The 10 seconds timer is to allow the data connection to be
     686             :          * formed before allowing other networks to be selected.
     687             :          */
     688         235 :         eloop_register_timeout(10, 0, wpas_wps_reenable_networks_cb, wpa_s,
     689             :                                NULL);
     690             : 
     691         235 :         wpas_p2p_wps_success(wpa_s, wpa_s->bssid, 0);
     692         235 : }
     693             : 
     694             : 
     695          11 : static void wpa_supplicant_wps_event_er_ap_add(struct wpa_supplicant *wpa_s,
     696             :                                                struct wps_event_er_ap *ap)
     697             : {
     698             :         char uuid_str[100];
     699             :         char dev_type[WPS_DEV_TYPE_BUFSIZE];
     700             : 
     701          11 :         uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str));
     702          11 :         if (ap->pri_dev_type)
     703          11 :                 wps_dev_type_bin2str(ap->pri_dev_type, dev_type,
     704             :                                      sizeof(dev_type));
     705             :         else
     706           0 :                 dev_type[0] = '\0';
     707             : 
     708         143 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_ADD "%s " MACSTR
     709             :                 " pri_dev_type=%s wps_state=%d |%s|%s|%s|%s|%s|%s|",
     710          77 :                 uuid_str, MAC2STR(ap->mac_addr), dev_type, ap->wps_state,
     711          11 :                 ap->friendly_name ? ap->friendly_name : "",
     712          11 :                 ap->manufacturer ? ap->manufacturer : "",
     713          11 :                 ap->model_description ? ap->model_description : "",
     714          11 :                 ap->model_name ? ap->model_name : "",
     715          11 :                 ap->manufacturer_url ? ap->manufacturer_url : "",
     716          11 :                 ap->model_url ? ap->model_url : "");
     717          11 : }
     718             : 
     719             : 
     720          10 : static void wpa_supplicant_wps_event_er_ap_remove(struct wpa_supplicant *wpa_s,
     721             :                                                   struct wps_event_er_ap *ap)
     722             : {
     723             :         char uuid_str[100];
     724          10 :         uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str));
     725          10 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_REMOVE "%s", uuid_str);
     726          10 : }
     727             : 
     728             : 
     729          30 : static void wpa_supplicant_wps_event_er_enrollee_add(
     730             :         struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee)
     731             : {
     732             :         char uuid_str[100];
     733             :         char dev_type[WPS_DEV_TYPE_BUFSIZE];
     734             : 
     735          30 :         uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str));
     736          30 :         if (enrollee->pri_dev_type)
     737          30 :                 wps_dev_type_bin2str(enrollee->pri_dev_type, dev_type,
     738             :                                      sizeof(dev_type));
     739             :         else
     740           0 :                 dev_type[0] = '\0';
     741             : 
     742         390 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_ADD "%s " MACSTR
     743             :                 " M1=%d config_methods=0x%x dev_passwd_id=%d pri_dev_type=%s "
     744             :                 "|%s|%s|%s|%s|%s|",
     745         180 :                 uuid_str, MAC2STR(enrollee->mac_addr), enrollee->m1_received,
     746          60 :                 enrollee->config_methods, enrollee->dev_passwd_id, dev_type,
     747          30 :                 enrollee->dev_name ? enrollee->dev_name : "",
     748          30 :                 enrollee->manufacturer ? enrollee->manufacturer : "",
     749          30 :                 enrollee->model_name ? enrollee->model_name : "",
     750          30 :                 enrollee->model_number ? enrollee->model_number : "",
     751          30 :                 enrollee->serial_number ? enrollee->serial_number : "");
     752          30 : }
     753             : 
     754             : 
     755          21 : static void wpa_supplicant_wps_event_er_enrollee_remove(
     756             :         struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee)
     757             : {
     758             :         char uuid_str[100];
     759          21 :         uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str));
     760         126 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_REMOVE "%s " MACSTR,
     761         126 :                 uuid_str, MAC2STR(enrollee->mac_addr));
     762          21 : }
     763             : 
     764             : 
     765           1 : static void wpa_supplicant_wps_event_er_ap_settings(
     766             :         struct wpa_supplicant *wpa_s,
     767             :         struct wps_event_er_ap_settings *ap_settings)
     768             : {
     769             :         char uuid_str[100];
     770             :         char key_str[65];
     771           1 :         const struct wps_credential *cred = ap_settings->cred;
     772             : 
     773           1 :         key_str[0] = '\0';
     774           1 :         if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
     775           1 :                 if (cred->key_len >= 8 && cred->key_len <= 64) {
     776           1 :                         os_memcpy(key_str, cred->key, cred->key_len);
     777           1 :                         key_str[cred->key_len] = '\0';
     778             :                 }
     779             :         }
     780             : 
     781           1 :         uuid_bin2str(ap_settings->uuid, uuid_str, sizeof(uuid_str));
     782             :         /* Use wpa_msg_ctrl to avoid showing the key in debug log */
     783           3 :         wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_SETTINGS
     784             :                      "uuid=%s ssid=%s auth_type=0x%04x encr_type=0x%04x "
     785             :                      "key=%s",
     786           1 :                      uuid_str, wpa_ssid_txt(cred->ssid, cred->ssid_len),
     787           2 :                      cred->auth_type, cred->encr_type, key_str);
     788           1 : }
     789             : 
     790             : 
     791          44 : static void wpa_supplicant_wps_event_er_set_sel_reg(
     792             :         struct wpa_supplicant *wpa_s,
     793             :         struct wps_event_er_set_selected_registrar *ev)
     794             : {
     795             :         char uuid_str[100];
     796             : 
     797          44 :         uuid_bin2str(ev->uuid, uuid_str, sizeof(uuid_str));
     798          44 :         switch (ev->state) {
     799             :         case WPS_ER_SET_SEL_REG_START:
     800          52 :                 wpa_msg(wpa_s, MSG_DEBUG, WPS_EVENT_ER_SET_SEL_REG
     801             :                         "uuid=%s state=START sel_reg=%d dev_passwd_id=%u "
     802             :                         "sel_reg_config_methods=0x%x",
     803          26 :                         uuid_str, ev->sel_reg, ev->dev_passwd_id,
     804          26 :                         ev->sel_reg_config_methods);
     805          26 :                 break;
     806             :         case WPS_ER_SET_SEL_REG_DONE:
     807          18 :                 wpa_msg(wpa_s, MSG_DEBUG, WPS_EVENT_ER_SET_SEL_REG
     808             :                         "uuid=%s state=DONE", uuid_str);
     809          18 :                 break;
     810             :         case WPS_ER_SET_SEL_REG_FAILED:
     811           0 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_SET_SEL_REG
     812             :                         "uuid=%s state=FAILED", uuid_str);
     813           0 :                 break;
     814             :         }
     815          44 : }
     816             : 
     817             : 
     818         428 : static void wpa_supplicant_wps_event(void *ctx, enum wps_event event,
     819             :                                      union wps_event_data *data)
     820             : {
     821         428 :         struct wpa_supplicant *wpa_s = ctx;
     822         428 :         switch (event) {
     823             :         case WPS_EV_M2D:
     824          25 :                 wpa_supplicant_wps_event_m2d(wpa_s, &data->m2d);
     825          25 :                 break;
     826             :         case WPS_EV_FAIL:
     827          43 :                 wpa_supplicant_wps_event_fail(wpa_s, &data->fail);
     828          43 :                 break;
     829             :         case WPS_EV_SUCCESS:
     830         235 :                 wpa_supplicant_wps_event_success(wpa_s);
     831         235 :                 break;
     832             :         case WPS_EV_PWD_AUTH_FAIL:
     833             : #ifdef CONFIG_AP
     834           5 :                 if (wpa_s->ap_iface && data->pwd_auth_fail.enrollee)
     835           0 :                         wpa_supplicant_ap_pwd_auth_fail(wpa_s);
     836             : #endif /* CONFIG_AP */
     837           5 :                 break;
     838             :         case WPS_EV_PBC_OVERLAP:
     839           1 :                 break;
     840             :         case WPS_EV_PBC_TIMEOUT:
     841           0 :                 break;
     842             :         case WPS_EV_PBC_ACTIVE:
     843           1 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ACTIVE);
     844           1 :                 break;
     845             :         case WPS_EV_PBC_DISABLE:
     846           1 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_DISABLE);
     847           1 :                 break;
     848             :         case WPS_EV_ER_AP_ADD:
     849          11 :                 wpa_supplicant_wps_event_er_ap_add(wpa_s, &data->ap);
     850          11 :                 break;
     851             :         case WPS_EV_ER_AP_REMOVE:
     852          10 :                 wpa_supplicant_wps_event_er_ap_remove(wpa_s, &data->ap);
     853          10 :                 break;
     854             :         case WPS_EV_ER_ENROLLEE_ADD:
     855          30 :                 wpa_supplicant_wps_event_er_enrollee_add(wpa_s,
     856             :                                                          &data->enrollee);
     857          30 :                 break;
     858             :         case WPS_EV_ER_ENROLLEE_REMOVE:
     859          21 :                 wpa_supplicant_wps_event_er_enrollee_remove(wpa_s,
     860             :                                                             &data->enrollee);
     861          21 :                 break;
     862             :         case WPS_EV_ER_AP_SETTINGS:
     863           1 :                 wpa_supplicant_wps_event_er_ap_settings(wpa_s,
     864             :                                                         &data->ap_settings);
     865           1 :                 break;
     866             :         case WPS_EV_ER_SET_SELECTED_REGISTRAR:
     867          44 :                 wpa_supplicant_wps_event_er_set_sel_reg(wpa_s,
     868             :                                                         &data->set_sel_reg);
     869          44 :                 break;
     870             :         case WPS_EV_AP_PIN_SUCCESS:
     871           0 :                 break;
     872             :         }
     873         428 : }
     874             : 
     875             : 
     876         300 : static int wpa_supplicant_wps_rf_band(void *ctx)
     877             : {
     878         300 :         struct wpa_supplicant *wpa_s = ctx;
     879             : 
     880         300 :         if (!wpa_s->current_ssid || !wpa_s->assoc_freq)
     881           0 :                 return 0;
     882             : 
     883         300 :         return (wpa_s->assoc_freq > 2484) ? WPS_RF_50GHZ : WPS_RF_24GHZ;
     884             : }
     885             : 
     886             : 
     887         702 : enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid)
     888             : {
     889        1241 :         if (eap_is_wps_pbc_enrollee(&ssid->eap) ||
     890         539 :             eap_is_wps_pin_enrollee(&ssid->eap))
     891         583 :                 return WPS_REQ_ENROLLEE;
     892             :         else
     893         119 :                 return WPS_REQ_REGISTRAR;
     894             : }
     895             : 
     896             : 
     897        2602 : static void wpas_clear_wps(struct wpa_supplicant *wpa_s)
     898             : {
     899             :         int id;
     900        2602 :         struct wpa_ssid *ssid, *remove_ssid = NULL, *prev_current;
     901             : 
     902        2602 :         wpa_s->after_wps = 0;
     903        2602 :         wpa_s->known_wps_freq = 0;
     904             : 
     905        2602 :         prev_current = wpa_s->current_ssid;
     906             : 
     907             :         /* Enable the networks disabled during wpas_wps_reassoc */
     908        2602 :         wpas_wps_reenable_networks(wpa_s);
     909             : 
     910        2602 :         eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
     911        2602 :         eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL);
     912             : 
     913             :         /* Remove any existing WPS network from configuration */
     914        2602 :         ssid = wpa_s->conf->ssid;
     915        6187 :         while (ssid) {
     916         983 :                 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
     917          35 :                         if (ssid == wpa_s->current_ssid) {
     918          25 :                                 wpa_s->own_disconnect_req = 1;
     919          25 :                                 wpa_supplicant_deauthenticate(
     920             :                                         wpa_s, WLAN_REASON_DEAUTH_LEAVING);
     921             :                         }
     922          35 :                         id = ssid->id;
     923          35 :                         remove_ssid = ssid;
     924             :                 } else
     925         948 :                         id = -1;
     926         983 :                 ssid = ssid->next;
     927         983 :                 if (id >= 0) {
     928          35 :                         if (prev_current == remove_ssid) {
     929          25 :                                 wpa_sm_set_config(wpa_s->wpa, NULL);
     930          25 :                                 eapol_sm_notify_config(wpa_s->eapol, NULL,
     931             :                                                        NULL);
     932             :                         }
     933          35 :                         wpas_notify_network_removed(wpa_s, remove_ssid);
     934          35 :                         wpa_config_remove_network(wpa_s->conf, id);
     935             :                 }
     936             :         }
     937             : 
     938        2602 :         wpas_wps_clear_ap_info(wpa_s);
     939        2602 : }
     940             : 
     941             : 
     942           1 : static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx)
     943             : {
     944           1 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     945           1 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_TIMEOUT "Requested operation timed "
     946             :                 "out");
     947           1 :         wpas_clear_wps(wpa_s);
     948           1 : }
     949             : 
     950             : 
     951         295 : static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
     952             :                                               int registrar, const u8 *dev_addr,
     953             :                                               const u8 *bssid)
     954             : {
     955             :         struct wpa_ssid *ssid;
     956             : 
     957         295 :         ssid = wpa_config_add_network(wpa_s->conf);
     958         295 :         if (ssid == NULL)
     959           4 :                 return NULL;
     960         291 :         wpas_notify_network_added(wpa_s, ssid);
     961         291 :         wpa_config_set_network_defaults(ssid);
     962         291 :         ssid->temporary = 1;
     963         582 :         if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 ||
     964         582 :             wpa_config_set(ssid, "eap", "WSC", 0) < 0 ||
     965         291 :             wpa_config_set(ssid, "identity", registrar ?
     966             :                            "\"" WSC_ID_REGISTRAR "\"" :
     967             :                            "\"" WSC_ID_ENROLLEE "\"", 0) < 0) {
     968           0 :                 wpas_notify_network_removed(wpa_s, ssid);
     969           0 :                 wpa_config_remove_network(wpa_s->conf, ssid->id);
     970           0 :                 return NULL;
     971             :         }
     972             : 
     973             : #ifdef CONFIG_P2P
     974         291 :         if (dev_addr)
     975          15 :                 os_memcpy(ssid->go_p2p_dev_addr, dev_addr, ETH_ALEN);
     976             : #endif /* CONFIG_P2P */
     977             : 
     978         291 :         if (bssid) {
     979             : #ifndef CONFIG_P2P
     980             :                 struct wpa_bss *bss;
     981             :                 int count = 0;
     982             : #endif /* CONFIG_P2P */
     983             : 
     984         266 :                 os_memcpy(ssid->bssid, bssid, ETH_ALEN);
     985         266 :                 ssid->bssid_set = 1;
     986             : 
     987             :                 /*
     988             :                  * Note: With P2P, the SSID may change at the time the WPS
     989             :                  * provisioning is started, so better not filter the AP based
     990             :                  * on the current SSID in the scan results.
     991             :                  */
     992             : #ifndef CONFIG_P2P
     993             :                 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
     994             :                         if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0)
     995             :                                 continue;
     996             : 
     997             :                         os_free(ssid->ssid);
     998             :                         ssid->ssid = os_malloc(bss->ssid_len);
     999             :                         if (ssid->ssid == NULL)
    1000             :                                 break;
    1001             :                         os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
    1002             :                         ssid->ssid_len = bss->ssid_len;
    1003             :                         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from "
    1004             :                                           "scan results",
    1005             :                                           ssid->ssid, ssid->ssid_len);
    1006             :                         count++;
    1007             :                 }
    1008             : 
    1009             :                 if (count > 1) {
    1010             :                         wpa_printf(MSG_DEBUG, "WPS: More than one SSID found "
    1011             :                                    "for the AP; use wildcard");
    1012             :                         os_free(ssid->ssid);
    1013             :                         ssid->ssid = NULL;
    1014             :                         ssid->ssid_len = 0;
    1015             :                 }
    1016             : #endif /* CONFIG_P2P */
    1017             :         }
    1018             : 
    1019         291 :         return ssid;
    1020             : }
    1021             : 
    1022             : 
    1023         299 : static void wpas_wps_temp_disable(struct wpa_supplicant *wpa_s,
    1024             :                                   struct wpa_ssid *selected)
    1025             : {
    1026             :         struct wpa_ssid *ssid;
    1027             : 
    1028         299 :         if (wpa_s->current_ssid) {
    1029           2 :                 wpa_s->own_disconnect_req = 1;
    1030           2 :                 wpa_supplicant_deauthenticate(
    1031             :                         wpa_s, WLAN_REASON_DEAUTH_LEAVING);
    1032             :         }
    1033             : 
    1034             :         /* Mark all other networks disabled and trigger reassociation */
    1035         299 :         ssid = wpa_s->conf->ssid;
    1036         895 :         while (ssid) {
    1037         297 :                 int was_disabled = ssid->disabled;
    1038         297 :                 ssid->disabled_for_connect = 0;
    1039             :                 /*
    1040             :                  * In case the network object corresponds to a persistent group
    1041             :                  * then do not send out network disabled signal. In addition,
    1042             :                  * do not change disabled status of persistent network objects
    1043             :                  * from 2 to 1 should we connect to another network.
    1044             :                  */
    1045         297 :                 if (was_disabled != 2) {
    1046         296 :                         ssid->disabled = ssid != selected;
    1047         296 :                         if (was_disabled != ssid->disabled) {
    1048           5 :                                 if (ssid->disabled)
    1049           5 :                                         ssid->disabled_for_connect = 1;
    1050           5 :                                 wpas_notify_network_enabled_changed(wpa_s,
    1051             :                                                                     ssid);
    1052             :                         }
    1053             :                 }
    1054         297 :                 ssid = ssid->next;
    1055             :         }
    1056         299 : }
    1057             : 
    1058             : 
    1059         291 : static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
    1060             :                              struct wpa_ssid *selected, const u8 *bssid,
    1061             :                              int freq)
    1062             : {
    1063             :         struct wpa_bss *bss;
    1064             : 
    1065         291 :         wpa_s->wps_run++;
    1066         291 :         if (wpa_s->wps_run == 0)
    1067           0 :                 wpa_s->wps_run++;
    1068         291 :         wpa_s->after_wps = 0;
    1069         291 :         wpa_s->known_wps_freq = 0;
    1070         291 :         if (freq) {
    1071           8 :                 wpa_s->after_wps = 5;
    1072           8 :                 wpa_s->wps_freq = freq;
    1073         283 :         } else if (bssid) {
    1074         258 :                 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
    1075         258 :                 if (bss && bss->freq > 0) {
    1076         165 :                         wpa_s->known_wps_freq = 1;
    1077         165 :                         wpa_s->wps_freq = bss->freq;
    1078             :                 }
    1079             :         }
    1080             : 
    1081         291 :         wpas_wps_temp_disable(wpa_s, selected);
    1082             : 
    1083         291 :         wpa_s->disconnected = 0;
    1084         291 :         wpa_s->reassociate = 1;
    1085         291 :         wpa_s->scan_runs = 0;
    1086         291 :         wpa_s->normal_scans = 0;
    1087         291 :         wpa_s->wps_success = 0;
    1088         291 :         wpa_s->blacklist_cleared = 0;
    1089             : 
    1090         291 :         wpa_supplicant_cancel_sched_scan(wpa_s);
    1091         291 :         wpa_supplicant_req_scan(wpa_s, 0, 0);
    1092         291 : }
    1093             : 
    1094             : 
    1095          65 : int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
    1096             :                        int p2p_group)
    1097             : {
    1098             :         struct wpa_ssid *ssid;
    1099             : 
    1100             : #ifdef CONFIG_AP
    1101          65 :         if (wpa_s->ap_iface) {
    1102           0 :                 wpa_printf(MSG_DEBUG,
    1103             :                            "WPS: Reject request to start Registrar(as station) operation while AP mode is enabled");
    1104           0 :                 return -1;
    1105             :         }
    1106             : #endif /* CONFIG_AP */
    1107          65 :         wpas_clear_wps(wpa_s);
    1108          65 :         ssid = wpas_wps_add_network(wpa_s, 0, NULL, bssid);
    1109          65 :         if (ssid == NULL)
    1110           1 :                 return -1;
    1111          64 :         ssid->temporary = 1;
    1112          64 :         ssid->p2p_group = p2p_group;
    1113             : #ifdef CONFIG_P2P
    1114          64 :         if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
    1115          27 :                 ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
    1116          27 :                 if (ssid->ssid) {
    1117          27 :                         ssid->ssid_len = wpa_s->go_params->ssid_len;
    1118          27 :                         os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
    1119             :                                   ssid->ssid_len);
    1120          54 :                         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
    1121          27 :                                           "SSID", ssid->ssid, ssid->ssid_len);
    1122             :                 }
    1123             :         }
    1124             : #endif /* CONFIG_P2P */
    1125          64 :         if (wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0) < 0)
    1126           0 :                 return -1;
    1127          64 :         if (wpa_s->wps_fragment_size)
    1128           1 :                 ssid->eap.fragment_size = wpa_s->wps_fragment_size;
    1129          64 :         eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
    1130             :                                wpa_s, NULL);
    1131          64 :         wpas_wps_reassoc(wpa_s, ssid, bssid, 0);
    1132          64 :         return 0;
    1133             : }
    1134             : 
    1135             : 
    1136         187 : static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s,
    1137             :                                  const u8 *dev_addr, const u8 *bssid,
    1138             :                                  const char *pin, int p2p_group, u16 dev_pw_id,
    1139             :                                  const u8 *peer_pubkey_hash,
    1140             :                                  const u8 *ssid_val, size_t ssid_len, int freq)
    1141             : {
    1142             :         struct wpa_ssid *ssid;
    1143             :         char val[128 + 2 * WPS_OOB_PUBKEY_HASH_LEN];
    1144         187 :         unsigned int rpin = 0;
    1145             :         char hash[2 * WPS_OOB_PUBKEY_HASH_LEN + 10];
    1146             : 
    1147             : #ifdef CONFIG_AP
    1148         187 :         if (wpa_s->ap_iface) {
    1149           0 :                 wpa_printf(MSG_DEBUG,
    1150             :                            "WPS: Reject request to start Registrar(as station) operation while AP mode is enabled");
    1151           0 :                 return -1;
    1152             :         }
    1153             : #endif /* CONFIG_AP */
    1154         187 :         wpas_clear_wps(wpa_s);
    1155         187 :         if (bssid && is_zero_ether_addr(bssid))
    1156           4 :                 bssid = NULL;
    1157         187 :         ssid = wpas_wps_add_network(wpa_s, 0, dev_addr, bssid);
    1158         187 :         if (ssid == NULL) {
    1159           2 :                 wpa_printf(MSG_DEBUG, "WPS: Could not add network");
    1160           2 :                 return -1;
    1161             :         }
    1162         185 :         ssid->temporary = 1;
    1163         185 :         ssid->p2p_group = p2p_group;
    1164         185 :         if (ssid_val) {
    1165          11 :                 ssid->ssid = os_malloc(ssid_len);
    1166          11 :                 if (ssid->ssid) {
    1167          11 :                         os_memcpy(ssid->ssid, ssid_val, ssid_len);
    1168          11 :                         ssid->ssid_len = ssid_len;
    1169             :                 }
    1170             :         }
    1171         185 :         if (peer_pubkey_hash) {
    1172          17 :                 os_memcpy(hash, " pkhash=", 8);
    1173          17 :                 wpa_snprintf_hex_uppercase(hash + 8, sizeof(hash) - 8,
    1174             :                                            peer_pubkey_hash,
    1175             :                                            WPS_OOB_PUBKEY_HASH_LEN);
    1176             :         } else {
    1177         168 :                 hash[0] = '\0';
    1178             :         }
    1179             : #ifdef CONFIG_P2P
    1180         185 :         if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
    1181         144 :                 ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
    1182         144 :                 if (ssid->ssid) {
    1183         144 :                         ssid->ssid_len = wpa_s->go_params->ssid_len;
    1184         144 :                         os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
    1185             :                                   ssid->ssid_len);
    1186         288 :                         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
    1187         144 :                                           "SSID", ssid->ssid, ssid->ssid_len);
    1188             :                 }
    1189             :         }
    1190             : #endif /* CONFIG_P2P */
    1191         185 :         if (pin)
    1192         164 :                 os_snprintf(val, sizeof(val), "\"pin=%s dev_pw_id=%u%s\"",
    1193             :                             pin, dev_pw_id, hash);
    1194          21 :         else if (pin == NULL && dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) {
    1195          17 :                 os_snprintf(val, sizeof(val), "\"dev_pw_id=%u%s\"",
    1196             :                             dev_pw_id, hash);
    1197             :         } else {
    1198           4 :                 rpin = wps_generate_pin();
    1199           4 :                 os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u%s\"",
    1200             :                             rpin, dev_pw_id, hash);
    1201             :         }
    1202         185 :         if (wpa_config_set(ssid, "phase1", val, 0) < 0) {
    1203           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to set phase1 '%s'", val);
    1204           0 :                 return -1;
    1205             :         }
    1206         185 :         if (wpa_s->wps_fragment_size)
    1207           1 :                 ssid->eap.fragment_size = wpa_s->wps_fragment_size;
    1208         185 :         eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
    1209             :                                wpa_s, NULL);
    1210         185 :         wpa_s->wps_ap_iter = 1;
    1211         185 :         wpas_wps_reassoc(wpa_s, ssid, bssid, freq);
    1212         185 :         return rpin;
    1213             : }
    1214             : 
    1215             : 
    1216         158 : int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
    1217             :                        const char *pin, int p2p_group, u16 dev_pw_id)
    1218             : {
    1219         158 :         return wpas_wps_start_dev_pw(wpa_s, NULL, bssid, pin, p2p_group,
    1220             :                                      dev_pw_id, NULL, NULL, 0, 0);
    1221             : }
    1222             : 
    1223             : 
    1224             : /* Cancel the wps pbc/pin requests */
    1225        3356 : int wpas_wps_cancel(struct wpa_supplicant *wpa_s)
    1226             : {
    1227             : #ifdef CONFIG_AP
    1228        3356 :         if (wpa_s->ap_iface) {
    1229           9 :                 wpa_printf(MSG_DEBUG, "WPS: Cancelling in AP mode");
    1230           9 :                 return wpa_supplicant_ap_wps_cancel(wpa_s);
    1231             :         }
    1232             : #endif /* CONFIG_AP */
    1233             : 
    1234        6586 :         if (wpa_s->wpa_state == WPA_SCANNING ||
    1235        3239 :             wpa_s->wpa_state == WPA_DISCONNECTED) {
    1236        1686 :                 wpa_printf(MSG_DEBUG, "WPS: Cancel operation - cancel scan");
    1237        1686 :                 wpa_supplicant_cancel_scan(wpa_s);
    1238        1686 :                 wpas_clear_wps(wpa_s);
    1239        1661 :         } else if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
    1240         577 :                 wpa_printf(MSG_DEBUG, "WPS: Cancel operation - "
    1241             :                            "deauthenticate");
    1242         577 :                 wpa_s->own_disconnect_req = 1;
    1243         577 :                 wpa_supplicant_deauthenticate(wpa_s,
    1244             :                                               WLAN_REASON_DEAUTH_LEAVING);
    1245         577 :                 wpas_clear_wps(wpa_s);
    1246             :         } else {
    1247        1084 :                 wpas_wps_reenable_networks(wpa_s);
    1248        1084 :                 wpas_wps_clear_ap_info(wpa_s);
    1249        1084 :                 if (eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL) >
    1250             :                     0)
    1251           0 :                         wpas_clear_wps(wpa_s);
    1252             :         }
    1253             : 
    1254        3347 :         wpa_s->after_wps = 0;
    1255             : 
    1256        3347 :         return 0;
    1257             : }
    1258             : 
    1259             : 
    1260          43 : int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
    1261             :                        const char *pin, struct wps_new_ap_settings *settings)
    1262             : {
    1263             :         struct wpa_ssid *ssid;
    1264             :         char val[200];
    1265             :         char *pos, *end;
    1266             :         int res;
    1267             : 
    1268             : #ifdef CONFIG_AP
    1269          43 :         if (wpa_s->ap_iface) {
    1270           0 :                 wpa_printf(MSG_DEBUG,
    1271             :                            "WPS: Reject request to start Registrar(as station) operation while AP mode is enabled");
    1272           0 :                 return -1;
    1273             :         }
    1274             : #endif /* CONFIG_AP */
    1275          43 :         if (!pin)
    1276           0 :                 return -1;
    1277          43 :         wpas_clear_wps(wpa_s);
    1278          43 :         ssid = wpas_wps_add_network(wpa_s, 1, NULL, bssid);
    1279          43 :         if (ssid == NULL)
    1280           1 :                 return -1;
    1281          42 :         ssid->temporary = 1;
    1282          42 :         pos = val;
    1283          42 :         end = pos + sizeof(val);
    1284          42 :         res = os_snprintf(pos, end - pos, "\"pin=%s", pin);
    1285          42 :         if (os_snprintf_error(end - pos, res))
    1286           0 :                 return -1;
    1287          42 :         pos += res;
    1288          42 :         if (settings) {
    1289          16 :                 res = os_snprintf(pos, end - pos, " new_ssid=%s new_auth=%s "
    1290             :                                   "new_encr=%s new_key=%s",
    1291             :                                   settings->ssid_hex, settings->auth,
    1292             :                                   settings->encr, settings->key_hex);
    1293          16 :                 if (os_snprintf_error(end - pos, res))
    1294           0 :                         return -1;
    1295          16 :                 pos += res;
    1296             :         }
    1297          42 :         res = os_snprintf(pos, end - pos, "\"");
    1298          42 :         if (os_snprintf_error(end - pos, res))
    1299           0 :                 return -1;
    1300          42 :         if (wpa_config_set(ssid, "phase1", val, 0) < 0)
    1301           0 :                 return -1;
    1302          42 :         if (wpa_s->wps_fragment_size)
    1303           1 :                 ssid->eap.fragment_size = wpa_s->wps_fragment_size;
    1304          42 :         eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
    1305             :                                wpa_s, NULL);
    1306          42 :         wpas_wps_reassoc(wpa_s, ssid, bssid, 0);
    1307          42 :         return 0;
    1308             : }
    1309             : 
    1310             : 
    1311           0 : static int wpas_wps_new_psk_cb(void *ctx, const u8 *mac_addr,
    1312             :                                const u8 *p2p_dev_addr, const u8 *psk,
    1313             :                                size_t psk_len)
    1314             : {
    1315           0 :         if (is_zero_ether_addr(p2p_dev_addr)) {
    1316           0 :                 wpa_printf(MSG_DEBUG,
    1317             :                            "Received new WPA/WPA2-PSK from WPS for STA " MACSTR,
    1318           0 :                            MAC2STR(mac_addr));
    1319             :         } else {
    1320           0 :                 wpa_printf(MSG_DEBUG,
    1321             :                            "Received new WPA/WPA2-PSK from WPS for STA " MACSTR
    1322             :                            " P2P Device Addr " MACSTR,
    1323           0 :                            MAC2STR(mac_addr), MAC2STR(p2p_dev_addr));
    1324             :         }
    1325           0 :         wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len);
    1326             : 
    1327             :         /* TODO */
    1328             : 
    1329           0 :         return 0;
    1330             : }
    1331             : 
    1332             : 
    1333           0 : static void wpas_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
    1334             :                                    const struct wps_device_data *dev)
    1335             : {
    1336             :         char uuid[40], txt[400];
    1337             :         int len;
    1338             :         char devtype[WPS_DEV_TYPE_BUFSIZE];
    1339           0 :         if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
    1340           0 :                 return;
    1341           0 :         wpa_printf(MSG_DEBUG, "WPS: PIN needed for UUID-E %s", uuid);
    1342           0 :         len = os_snprintf(txt, sizeof(txt), "WPS-EVENT-PIN-NEEDED %s " MACSTR
    1343             :                           " [%s|%s|%s|%s|%s|%s]",
    1344           0 :                           uuid, MAC2STR(dev->mac_addr), dev->device_name,
    1345             :                           dev->manufacturer, dev->model_name,
    1346             :                           dev->model_number, dev->serial_number,
    1347           0 :                           wps_dev_type_bin2str(dev->pri_dev_type, devtype,
    1348             :                                                sizeof(devtype)));
    1349           0 :         if (!os_snprintf_error(sizeof(txt), len))
    1350           0 :                 wpa_printf(MSG_INFO, "%s", txt);
    1351             : }
    1352             : 
    1353             : 
    1354         130 : static void wpas_wps_set_sel_reg_cb(void *ctx, int sel_reg, u16 dev_passwd_id,
    1355             :                                     u16 sel_reg_config_methods)
    1356             : {
    1357             : #ifdef CONFIG_WPS_ER
    1358         130 :         struct wpa_supplicant *wpa_s = ctx;
    1359             : 
    1360         130 :         if (wpa_s->wps_er == NULL)
    1361         232 :                 return;
    1362          28 :         wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar - sel_reg=%d "
    1363             :                    "dev_password_id=%u sel_reg_config_methods=0x%x",
    1364             :                    sel_reg, dev_passwd_id, sel_reg_config_methods);
    1365          28 :         wps_er_set_sel_reg(wpa_s->wps_er, sel_reg, dev_passwd_id,
    1366             :                            sel_reg_config_methods);
    1367             : #endif /* CONFIG_WPS_ER */
    1368             : }
    1369             : 
    1370             : 
    1371       20866 : static u16 wps_fix_config_methods(u16 config_methods)
    1372             : {
    1373       20866 :         if ((config_methods &
    1374             :              (WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY |
    1375             :               WPS_CONFIG_PHY_DISPLAY)) == WPS_CONFIG_DISPLAY) {
    1376           1 :                 wpa_printf(MSG_INFO, "WPS: Converting display to "
    1377             :                            "virtual_display for WPS 2.0 compliance");
    1378           1 :                 config_methods |= WPS_CONFIG_VIRT_DISPLAY;
    1379             :         }
    1380       20866 :         if ((config_methods &
    1381             :              (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON |
    1382             :               WPS_CONFIG_PHY_PUSHBUTTON)) == WPS_CONFIG_PUSHBUTTON) {
    1383           1 :                 wpa_printf(MSG_INFO, "WPS: Converting push_button to "
    1384             :                            "virtual_push_button for WPS 2.0 compliance");
    1385           1 :                 config_methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
    1386             :         }
    1387             : 
    1388       20866 :         return config_methods;
    1389             : }
    1390             : 
    1391             : 
    1392         269 : static void wpas_wps_set_uuid(struct wpa_supplicant *wpa_s,
    1393             :                               struct wps_context *wps)
    1394             : {
    1395             :         char buf[50];
    1396             :         const char *src;
    1397             : 
    1398         269 :         if (is_nil_uuid(wpa_s->conf->uuid)) {
    1399             :                 struct wpa_supplicant *first;
    1400         268 :                 first = wpa_s->global->ifaces;
    1401        2497 :                 while (first && first->next)
    1402        1961 :                         first = first->next;
    1403         268 :                 if (first && first != wpa_s) {
    1404         173 :                         if (wps != wpa_s->global->ifaces->wps)
    1405         173 :                                 os_memcpy(wps->uuid,
    1406             :                                           wpa_s->global->ifaces->wps->uuid,
    1407             :                                           WPS_UUID_LEN);
    1408         173 :                         src = "from the first interface";
    1409             :                 } else {
    1410          95 :                         uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid);
    1411          95 :                         src = "based on MAC address";
    1412             :                 }
    1413             :         } else {
    1414           1 :                 os_memcpy(wps->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
    1415           1 :                 src = "based on configuration";
    1416             :         }
    1417             : 
    1418         269 :         uuid_bin2str(wps->uuid, buf, sizeof(buf));
    1419         269 :         wpa_dbg(wpa_s, MSG_DEBUG, "WPS: UUID %s: %s", src, buf);
    1420         269 : }
    1421             : 
    1422             : 
    1423         271 : static void wpas_wps_set_vendor_ext_m1(struct wpa_supplicant *wpa_s,
    1424             :                                        struct wps_context *wps)
    1425             : {
    1426         271 :         wpabuf_free(wps->dev.vendor_ext_m1);
    1427         271 :         wps->dev.vendor_ext_m1 = NULL;
    1428             : 
    1429         271 :         if (wpa_s->conf->wps_vendor_ext_m1) {
    1430           1 :                 wps->dev.vendor_ext_m1 =
    1431           1 :                         wpabuf_dup(wpa_s->conf->wps_vendor_ext_m1);
    1432           1 :                 if (!wps->dev.vendor_ext_m1) {
    1433           0 :                         wpa_printf(MSG_ERROR, "WPS: Cannot "
    1434             :                                    "allocate memory for vendor_ext_m1");
    1435             :                 }
    1436             :         }
    1437         271 : }
    1438             : 
    1439             : 
    1440         268 : int wpas_wps_init(struct wpa_supplicant *wpa_s)
    1441             : {
    1442             :         struct wps_context *wps;
    1443             :         struct wps_registrar_config rcfg;
    1444             :         struct hostapd_hw_modes *modes;
    1445             :         u16 m;
    1446             : 
    1447         268 :         wps = os_zalloc(sizeof(*wps));
    1448         268 :         if (wps == NULL)
    1449           1 :                 return -1;
    1450             : 
    1451         267 :         wps->cred_cb = wpa_supplicant_wps_cred;
    1452         267 :         wps->event_cb = wpa_supplicant_wps_event;
    1453         267 :         wps->rf_band_cb = wpa_supplicant_wps_rf_band;
    1454         267 :         wps->cb_ctx = wpa_s;
    1455             : 
    1456         267 :         wps->dev.device_name = wpa_s->conf->device_name;
    1457         267 :         wps->dev.manufacturer = wpa_s->conf->manufacturer;
    1458         267 :         wps->dev.model_name = wpa_s->conf->model_name;
    1459         267 :         wps->dev.model_number = wpa_s->conf->model_number;
    1460         267 :         wps->dev.serial_number = wpa_s->conf->serial_number;
    1461         267 :         wps->config_methods =
    1462         267 :                 wps_config_methods_str2bin(wpa_s->conf->config_methods);
    1463         267 :         if ((wps->config_methods & (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) ==
    1464             :             (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) {
    1465           0 :                 wpa_printf(MSG_ERROR, "WPS: Both Label and Display config "
    1466             :                            "methods are not allowed at the same time");
    1467           0 :                 os_free(wps);
    1468           0 :                 return -1;
    1469             :         }
    1470         267 :         wps->config_methods = wps_fix_config_methods(wps->config_methods);
    1471         267 :         wps->dev.config_methods = wps->config_methods;
    1472         267 :         os_memcpy(wps->dev.pri_dev_type, wpa_s->conf->device_type,
    1473             :                   WPS_DEV_TYPE_LEN);
    1474             : 
    1475         267 :         wps->dev.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
    1476         267 :         os_memcpy(wps->dev.sec_dev_type, wpa_s->conf->sec_device_type,
    1477             :                   WPS_DEV_TYPE_LEN * wps->dev.num_sec_dev_types);
    1478             : 
    1479         267 :         wpas_wps_set_vendor_ext_m1(wpa_s, wps);
    1480             : 
    1481         267 :         wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
    1482         267 :         modes = wpa_s->hw.modes;
    1483         267 :         if (modes) {
    1484         912 :                 for (m = 0; m < wpa_s->hw.num_modes; m++) {
    1485        1140 :                         if (modes[m].mode == HOSTAPD_MODE_IEEE80211B ||
    1486         456 :                             modes[m].mode == HOSTAPD_MODE_IEEE80211G)
    1487         456 :                                 wps->dev.rf_bands |= WPS_RF_24GHZ;
    1488         228 :                         else if (modes[m].mode == HOSTAPD_MODE_IEEE80211A)
    1489         228 :                                 wps->dev.rf_bands |= WPS_RF_50GHZ;
    1490             :                 }
    1491             :         }
    1492         267 :         if (wps->dev.rf_bands == 0) {
    1493             :                 /*
    1494             :                  * Default to claiming support for both bands if the driver
    1495             :                  * does not provide support for fetching supported bands.
    1496             :                  */
    1497          39 :                 wps->dev.rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
    1498             :         }
    1499         267 :         os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN);
    1500         267 :         wpas_wps_set_uuid(wpa_s, wps);
    1501             : 
    1502         267 :         wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
    1503         267 :         wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
    1504             : 
    1505         267 :         os_memset(&rcfg, 0, sizeof(rcfg));
    1506         267 :         rcfg.new_psk_cb = wpas_wps_new_psk_cb;
    1507         267 :         rcfg.pin_needed_cb = wpas_wps_pin_needed_cb;
    1508         267 :         rcfg.set_sel_reg_cb = wpas_wps_set_sel_reg_cb;
    1509         267 :         rcfg.cb_ctx = wpa_s;
    1510             : 
    1511         267 :         wps->registrar = wps_registrar_init(wps, &rcfg);
    1512         267 :         if (wps->registrar == NULL) {
    1513           1 :                 wpa_printf(MSG_DEBUG, "Failed to initialize WPS Registrar");
    1514           1 :                 os_free(wps);
    1515           1 :                 return -1;
    1516             :         }
    1517             : 
    1518         266 :         wpa_s->wps = wps;
    1519             : 
    1520         266 :         return 0;
    1521             : }
    1522             : 
    1523             : 
    1524             : #ifdef CONFIG_WPS_ER
    1525         269 : static void wpas_wps_nfc_clear(struct wps_context *wps)
    1526             : {
    1527         269 :         wps->ap_nfc_dev_pw_id = 0;
    1528         269 :         wpabuf_free(wps->ap_nfc_dh_pubkey);
    1529         269 :         wps->ap_nfc_dh_pubkey = NULL;
    1530         269 :         wpabuf_free(wps->ap_nfc_dh_privkey);
    1531         269 :         wps->ap_nfc_dh_privkey = NULL;
    1532         269 :         wpabuf_free(wps->ap_nfc_dev_pw);
    1533         269 :         wps->ap_nfc_dev_pw = NULL;
    1534         269 : }
    1535             : #endif /* CONFIG_WPS_ER */
    1536             : 
    1537             : 
    1538         288 : void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
    1539             : {
    1540         288 :         wpas_wps_assoc_with_cred_cancel(wpa_s);
    1541         288 :         eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
    1542         288 :         eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL);
    1543         288 :         eloop_cancel_timeout(wpas_wps_reenable_networks_cb, wpa_s, NULL);
    1544         288 :         wpas_wps_clear_ap_info(wpa_s);
    1545             : 
    1546             : #ifdef CONFIG_P2P
    1547         288 :         eloop_cancel_timeout(wpas_p2p_pbc_overlap_cb, wpa_s, NULL);
    1548             : #endif /* CONFIG_P2P */
    1549             : 
    1550         288 :         if (wpa_s->wps == NULL)
    1551         310 :                 return;
    1552             : 
    1553             : #ifdef CONFIG_WPS_ER
    1554         266 :         wps_er_deinit(wpa_s->wps_er, NULL, NULL);
    1555         266 :         wpa_s->wps_er = NULL;
    1556         266 :         wpas_wps_nfc_clear(wpa_s->wps);
    1557             : #endif /* CONFIG_WPS_ER */
    1558             : 
    1559         266 :         wps_registrar_deinit(wpa_s->wps->registrar);
    1560         266 :         wpabuf_free(wpa_s->wps->dh_pubkey);
    1561         266 :         wpabuf_free(wpa_s->wps->dh_privkey);
    1562         266 :         wpabuf_free(wpa_s->wps->dev.vendor_ext_m1);
    1563         266 :         os_free(wpa_s->wps->network_key);
    1564         266 :         os_free(wpa_s->wps);
    1565         266 :         wpa_s->wps = NULL;
    1566             : }
    1567             : 
    1568             : 
    1569        2737 : int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
    1570             :                             struct wpa_ssid *ssid, struct wpa_bss *bss)
    1571             : {
    1572             :         struct wpabuf *wps_ie;
    1573             : 
    1574        2737 :         if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
    1575        2413 :                 return -1;
    1576             : 
    1577         324 :         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1578         324 :         if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
    1579          69 :                 if (!wps_ie) {
    1580           0 :                         wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
    1581           0 :                         return 0;
    1582             :                 }
    1583             : 
    1584          69 :                 if (!wps_is_selected_pbc_registrar(wps_ie)) {
    1585           9 :                         wpa_printf(MSG_DEBUG, "   skip - WPS AP "
    1586             :                                    "without active PBC Registrar");
    1587           9 :                         wpabuf_free(wps_ie);
    1588           9 :                         return 0;
    1589             :                 }
    1590             : 
    1591             :                 /* TODO: overlap detection */
    1592          60 :                 wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
    1593             :                            "(Active PBC)");
    1594          60 :                 wpabuf_free(wps_ie);
    1595          60 :                 return 1;
    1596             :         }
    1597             : 
    1598         255 :         if (eap_is_wps_pin_enrollee(&ssid->eap)) {
    1599         196 :                 if (!wps_ie) {
    1600           0 :                         wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
    1601           0 :                         return 0;
    1602             :                 }
    1603             : 
    1604             :                 /*
    1605             :                  * Start with WPS APs that advertise our address as an
    1606             :                  * authorized MAC (v2.0) or active PIN Registrar (v1.0) and
    1607             :                  * allow any WPS AP after couple of scans since some APs do not
    1608             :                  * set Selected Registrar attribute properly when using
    1609             :                  * external Registrar.
    1610             :                  */
    1611         196 :                 if (!wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1)) {
    1612          35 :                         if (wpa_s->scan_runs < WPS_PIN_SCAN_IGNORE_SEL_REG) {
    1613          21 :                                 wpa_printf(MSG_DEBUG, "   skip - WPS AP "
    1614             :                                            "without active PIN Registrar");
    1615          21 :                                 wpabuf_free(wps_ie);
    1616          21 :                                 return 0;
    1617             :                         }
    1618          14 :                         wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
    1619             :                 } else {
    1620         161 :                         wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
    1621             :                                    "(Authorized MAC or Active PIN)");
    1622             :                 }
    1623         175 :                 wpabuf_free(wps_ie);
    1624         175 :                 return 1;
    1625             :         }
    1626             : 
    1627          59 :         if (wps_ie) {
    1628          59 :                 wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
    1629          59 :                 wpabuf_free(wps_ie);
    1630          59 :                 return 1;
    1631             :         }
    1632             : 
    1633           0 :         return -1;
    1634             : }
    1635             : 
    1636             : 
    1637         155 : int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
    1638             :                               struct wpa_ssid *ssid,
    1639             :                               struct wpa_bss *bss)
    1640             : {
    1641         155 :         struct wpabuf *wps_ie = NULL;
    1642         155 :         int ret = 0;
    1643             : 
    1644         155 :         if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
    1645          66 :                 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1646          66 :                 if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) {
    1647             :                         /* allow wildcard SSID for WPS PBC */
    1648          34 :                         ret = 1;
    1649             :                 }
    1650          89 :         } else if (eap_is_wps_pin_enrollee(&ssid->eap)) {
    1651          45 :                 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1652          90 :                 if (wps_ie &&
    1653          61 :                     (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1) ||
    1654          16 :                      wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) {
    1655             :                         /* allow wildcard SSID for WPS PIN */
    1656          34 :                         ret = 1;
    1657             :                 }
    1658             :         }
    1659             : 
    1660         209 :         if (!ret && ssid->bssid_set &&
    1661          54 :             os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) {
    1662             :                 /* allow wildcard SSID due to hardcoded BSSID match */
    1663          54 :                 ret = 1;
    1664             :         }
    1665             : 
    1666             : #ifdef CONFIG_WPS_STRICT
    1667             :         if (wps_ie) {
    1668             :                 if (wps_validate_beacon_probe_resp(wps_ie, bss->beacon_ie_len >
    1669             :                                                    0, bss->bssid) < 0)
    1670             :                         ret = 0;
    1671             :                 if (bss->beacon_ie_len) {
    1672             :                         struct wpabuf *bcn_wps;
    1673             :                         bcn_wps = wpa_bss_get_vendor_ie_multi_beacon(
    1674             :                                 bss, WPS_IE_VENDOR_TYPE);
    1675             :                         if (bcn_wps == NULL) {
    1676             :                                 wpa_printf(MSG_DEBUG, "WPS: Mandatory WPS IE "
    1677             :                                            "missing from AP Beacon");
    1678             :                                 ret = 0;
    1679             :                         } else {
    1680             :                                 if (wps_validate_beacon(wps_ie) < 0)
    1681             :                                         ret = 0;
    1682             :                                 wpabuf_free(bcn_wps);
    1683             :                         }
    1684             :                 }
    1685             :         }
    1686             : #endif /* CONFIG_WPS_STRICT */
    1687             : 
    1688         155 :         wpabuf_free(wps_ie);
    1689             : 
    1690         155 :         return ret;
    1691             : }
    1692             : 
    1693             : 
    1694        2506 : int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s,
    1695             :                               struct wpa_bss *selected, struct wpa_ssid *ssid)
    1696             : {
    1697             :         const u8 *sel_uuid, *uuid;
    1698             :         struct wpabuf *wps_ie;
    1699        2506 :         int ret = 0;
    1700             :         struct wpa_bss *bss;
    1701             : 
    1702        2506 :         if (!eap_is_wps_pbc_enrollee(&ssid->eap))
    1703        2446 :                 return 0;
    1704             : 
    1705         360 :         wpa_printf(MSG_DEBUG, "WPS: Check whether PBC session overlap is "
    1706             :                    "present in scan results; selected BSSID " MACSTR,
    1707         360 :                    MAC2STR(selected->bssid));
    1708             : 
    1709             :         /* Make sure that only one AP is in active PBC mode */
    1710          60 :         wps_ie = wpa_bss_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE);
    1711          60 :         if (wps_ie) {
    1712          60 :                 sel_uuid = wps_get_uuid_e(wps_ie);
    1713          60 :                 wpa_hexdump(MSG_DEBUG, "WPS: UUID of the selected BSS",
    1714             :                             sel_uuid, UUID_LEN);
    1715             :         } else {
    1716           0 :                 wpa_printf(MSG_DEBUG, "WPS: Selected BSS does not include "
    1717             :                            "WPS IE?!");
    1718           0 :                 sel_uuid = NULL;
    1719             :         }
    1720             : 
    1721         145 :         dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    1722             :                 struct wpabuf *ie;
    1723          88 :                 if (bss == selected)
    1724          58 :                         continue;
    1725          30 :                 ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1726          30 :                 if (!ie)
    1727           7 :                         continue;
    1728          23 :                 if (!wps_is_selected_pbc_registrar(ie)) {
    1729           8 :                         wpabuf_free(ie);
    1730           8 :                         continue;
    1731             :                 }
    1732          90 :                 wpa_printf(MSG_DEBUG, "WPS: Another BSS in active PBC mode: "
    1733          90 :                            MACSTR, MAC2STR(bss->bssid));
    1734          15 :                 uuid = wps_get_uuid_e(ie);
    1735          15 :                 wpa_hexdump(MSG_DEBUG, "WPS: UUID of the other BSS",
    1736             :                             uuid, UUID_LEN);
    1737          15 :                 if (os_memcmp(selected->bssid, bss->bssid, ETH_ALEN) == 0) {
    1738          11 :                         wpabuf_free(ie);
    1739          11 :                         continue;
    1740             :                 }
    1741           8 :                 if (sel_uuid == NULL || uuid == NULL ||
    1742           4 :                     os_memcmp(sel_uuid, uuid, UUID_LEN) != 0) {
    1743           3 :                         ret = 1; /* PBC overlap */
    1744          36 :                         wpa_msg(wpa_s, MSG_INFO, "WPS: PBC overlap detected: "
    1745             :                                 MACSTR " and " MACSTR,
    1746          18 :                                 MAC2STR(selected->bssid),
    1747          18 :                                 MAC2STR(bss->bssid));
    1748           3 :                         wpabuf_free(ie);
    1749           3 :                         break;
    1750             :                 }
    1751             : 
    1752             :                 /* TODO: verify that this is reasonable dual-band situation */
    1753             : 
    1754           1 :                 wpabuf_free(ie);
    1755             :         }
    1756             : 
    1757          60 :         wpabuf_free(wps_ie);
    1758             : 
    1759          60 :         return ret;
    1760             : }
    1761             : 
    1762             : 
    1763        1916 : void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s)
    1764             : {
    1765             :         struct wpa_bss *bss;
    1766        1916 :         unsigned int pbc = 0, auth = 0, pin = 0, wps = 0;
    1767             : 
    1768        1916 :         if (wpa_s->disconnected || wpa_s->wpa_state >= WPA_ASSOCIATED)
    1769        2087 :                 return;
    1770             : 
    1771        3795 :         dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    1772             :                 struct wpabuf *ie;
    1773        2050 :                 ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1774        2050 :                 if (!ie)
    1775        1372 :                         continue;
    1776         678 :                 if (wps_is_selected_pbc_registrar(ie))
    1777         117 :                         pbc++;
    1778         561 :                 else if (wps_is_addr_authorized(ie, wpa_s->own_addr, 0))
    1779         283 :                         auth++;
    1780         278 :                 else if (wps_is_selected_pin_registrar(ie))
    1781          21 :                         pin++;
    1782             :                 else
    1783         257 :                         wps++;
    1784         678 :                 wpabuf_free(ie);
    1785             :         }
    1786             : 
    1787        1745 :         if (pbc)
    1788          99 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PBC);
    1789        1646 :         else if (auth)
    1790         224 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_AUTH);
    1791        1422 :         else if (pin)
    1792          11 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PIN);
    1793        1411 :         else if (wps)
    1794         217 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE);
    1795             : }
    1796             : 
    1797             : 
    1798        4937 : int wpas_wps_searching(struct wpa_supplicant *wpa_s)
    1799             : {
    1800             :         struct wpa_ssid *ssid;
    1801             : 
    1802        8157 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
    1803        3712 :                 if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !ssid->disabled)
    1804         492 :                         return 1;
    1805             :         }
    1806             : 
    1807        4445 :         return 0;
    1808             : }
    1809             : 
    1810             : 
    1811         423 : int wpas_wps_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
    1812             :                               char *end)
    1813             : {
    1814             :         struct wpabuf *wps_ie;
    1815             :         int ret;
    1816             : 
    1817         423 :         wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, WPS_DEV_OUI_WFA);
    1818         423 :         if (wps_ie == NULL)
    1819         317 :                 return 0;
    1820             : 
    1821         106 :         ret = wps_attr_text(wps_ie, buf, end);
    1822         106 :         wpabuf_free(wps_ie);
    1823         106 :         return ret;
    1824             : }
    1825             : 
    1826             : 
    1827          11 : int wpas_wps_er_start(struct wpa_supplicant *wpa_s, const char *filter)
    1828             : {
    1829             : #ifdef CONFIG_WPS_ER
    1830          11 :         if (wpa_s->wps_er) {
    1831           1 :                 wps_er_refresh(wpa_s->wps_er);
    1832           1 :                 return 0;
    1833             :         }
    1834          10 :         wpa_s->wps_er = wps_er_init(wpa_s->wps, wpa_s->ifname, filter);
    1835          10 :         if (wpa_s->wps_er == NULL)
    1836           0 :                 return -1;
    1837          10 :         return 0;
    1838             : #else /* CONFIG_WPS_ER */
    1839             :         return 0;
    1840             : #endif /* CONFIG_WPS_ER */
    1841             : }
    1842             : 
    1843             : 
    1844          18 : void wpas_wps_er_stop(struct wpa_supplicant *wpa_s)
    1845             : {
    1846             : #ifdef CONFIG_WPS_ER
    1847          18 :         wps_er_deinit(wpa_s->wps_er, NULL, NULL);
    1848          18 :         wpa_s->wps_er = NULL;
    1849             : #endif /* CONFIG_WPS_ER */
    1850          18 : }
    1851             : 
    1852             : 
    1853             : #ifdef CONFIG_WPS_ER
    1854           4 : int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const u8 *addr,
    1855             :                         const char *uuid, const char *pin)
    1856             : {
    1857             :         u8 u[UUID_LEN];
    1858           4 :         const u8 *use_uuid = NULL;
    1859             :         u8 addr_buf[ETH_ALEN];
    1860             : 
    1861           4 :         if (os_strcmp(uuid, "any") == 0) {
    1862           1 :         } else if (uuid_str2bin(uuid, u) == 0) {
    1863           0 :                 use_uuid = u;
    1864           1 :         } else if (hwaddr_aton(uuid, addr_buf) == 0) {
    1865           1 :                 use_uuid = wps_er_get_sta_uuid(wpa_s->wps_er, addr_buf);
    1866           1 :                 if (use_uuid == NULL)
    1867           0 :                         return -1;
    1868             :         } else
    1869           0 :                 return -1;
    1870           4 :         return wps_registrar_add_pin(wpa_s->wps->registrar, addr,
    1871             :                                      use_uuid,
    1872             :                                      (const u8 *) pin, os_strlen(pin), 300);
    1873             : }
    1874             : 
    1875             : 
    1876           5 : int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid)
    1877             : {
    1878           5 :         u8 u[UUID_LEN], *use_uuid = NULL;
    1879           5 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    1880             : 
    1881           5 :         if (uuid_str2bin(uuid, u) == 0)
    1882           1 :                 use_uuid = u;
    1883           4 :         else if (hwaddr_aton(uuid, addr) == 0)
    1884           3 :                 use_addr = addr;
    1885             :         else
    1886           1 :                 return -1;
    1887           4 :         return wps_er_pbc(wpa_s->wps_er, use_uuid, use_addr);
    1888             : }
    1889             : 
    1890             : 
    1891           1 : int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
    1892             :                       const char *pin)
    1893             : {
    1894           1 :         u8 u[UUID_LEN], *use_uuid = NULL;
    1895           1 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    1896             : 
    1897           1 :         if (uuid_str2bin(uuid, u) == 0)
    1898           1 :                 use_uuid = u;
    1899           0 :         else if (hwaddr_aton(uuid, addr) == 0)
    1900           0 :                 use_addr = addr;
    1901             :         else
    1902           0 :                 return -1;
    1903             : 
    1904           1 :         return wps_er_learn(wpa_s->wps_er, use_uuid, use_addr, (const u8 *) pin,
    1905             :                             os_strlen(pin));
    1906             : }
    1907             : 
    1908             : 
    1909           8 : static int wpas_wps_network_to_cred(struct wpa_ssid *ssid,
    1910             :                                     struct wps_credential *cred)
    1911             : {
    1912           8 :         os_memset(cred, 0, sizeof(*cred));
    1913           8 :         if (ssid->ssid_len > 32)
    1914           0 :                 return -1;
    1915           8 :         os_memcpy(cred->ssid, ssid->ssid, ssid->ssid_len);
    1916           8 :         cred->ssid_len = ssid->ssid_len;
    1917           8 :         if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
    1918           8 :                 cred->auth_type = (ssid->proto & WPA_PROTO_RSN) ?
    1919             :                         WPS_AUTH_WPA2PSK : WPS_AUTH_WPAPSK;
    1920           8 :                 if (ssid->pairwise_cipher & WPA_CIPHER_CCMP)
    1921           8 :                         cred->encr_type = WPS_ENCR_AES;
    1922             :                 else
    1923           0 :                         cred->encr_type = WPS_ENCR_TKIP;
    1924           8 :                 if (ssid->passphrase) {
    1925           8 :                         cred->key_len = os_strlen(ssid->passphrase);
    1926           8 :                         if (cred->key_len >= 64)
    1927           0 :                                 return -1;
    1928           8 :                         os_memcpy(cred->key, ssid->passphrase, cred->key_len);
    1929           0 :                 } else if (ssid->psk_set) {
    1930           0 :                         cred->key_len = 32;
    1931           0 :                         os_memcpy(cred->key, ssid->psk, 32);
    1932             :                 } else
    1933           0 :                         return -1;
    1934             :         } else {
    1935           0 :                 cred->auth_type = WPS_AUTH_OPEN;
    1936           0 :                 cred->encr_type = WPS_ENCR_NONE;
    1937             :         }
    1938             : 
    1939           8 :         return 0;
    1940             : }
    1941             : 
    1942             : 
    1943           8 : int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid,
    1944             :                            int id)
    1945             : {
    1946           8 :         u8 u[UUID_LEN], *use_uuid = NULL;
    1947           8 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    1948             :         struct wpa_ssid *ssid;
    1949             :         struct wps_credential cred;
    1950             :         int ret;
    1951             : 
    1952           8 :         if (uuid_str2bin(uuid, u) == 0)
    1953           7 :                 use_uuid = u;
    1954           1 :         else if (hwaddr_aton(uuid, addr) == 0)
    1955           1 :                 use_addr = addr;
    1956             :         else
    1957           0 :                 return -1;
    1958           8 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    1959           8 :         if (ssid == NULL || ssid->ssid == NULL)
    1960           0 :                 return -1;
    1961             : 
    1962           8 :         if (wpas_wps_network_to_cred(ssid, &cred) < 0)
    1963           0 :                 return -1;
    1964           8 :         ret = wps_er_set_config(wpa_s->wps_er, use_uuid, use_addr, &cred);
    1965           8 :         os_memset(&cred, 0, sizeof(cred));
    1966           8 :         return ret;
    1967             : }
    1968             : 
    1969             : 
    1970           1 : int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid,
    1971             :                        const char *pin, struct wps_new_ap_settings *settings)
    1972             : {
    1973           1 :         u8 u[UUID_LEN], *use_uuid = NULL;
    1974           1 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    1975             :         struct wps_credential cred;
    1976             :         size_t len;
    1977             : 
    1978           1 :         if (uuid_str2bin(uuid, u) == 0)
    1979           0 :                 use_uuid = u;
    1980           1 :         else if (hwaddr_aton(uuid, addr) == 0)
    1981           1 :                 use_addr = addr;
    1982             :         else
    1983           0 :                 return -1;
    1984           2 :         if (settings->ssid_hex == NULL || settings->auth == NULL ||
    1985           2 :             settings->encr == NULL || settings->key_hex == NULL)
    1986           0 :                 return -1;
    1987             : 
    1988           1 :         os_memset(&cred, 0, sizeof(cred));
    1989           1 :         len = os_strlen(settings->ssid_hex);
    1990           2 :         if ((len & 1) || len > 2 * sizeof(cred.ssid) ||
    1991           1 :             hexstr2bin(settings->ssid_hex, cred.ssid, len / 2))
    1992           0 :                 return -1;
    1993           1 :         cred.ssid_len = len / 2;
    1994             : 
    1995           1 :         len = os_strlen(settings->key_hex);
    1996           2 :         if ((len & 1) || len > 2 * sizeof(cred.key) ||
    1997           1 :             hexstr2bin(settings->key_hex, cred.key, len / 2))
    1998           0 :                 return -1;
    1999           1 :         cred.key_len = len / 2;
    2000             : 
    2001           1 :         if (os_strcmp(settings->auth, "OPEN") == 0)
    2002           0 :                 cred.auth_type = WPS_AUTH_OPEN;
    2003           1 :         else if (os_strcmp(settings->auth, "WPAPSK") == 0)
    2004           0 :                 cred.auth_type = WPS_AUTH_WPAPSK;
    2005           1 :         else if (os_strcmp(settings->auth, "WPA2PSK") == 0)
    2006           1 :                 cred.auth_type = WPS_AUTH_WPA2PSK;
    2007             :         else
    2008           0 :                 return -1;
    2009             : 
    2010           1 :         if (os_strcmp(settings->encr, "NONE") == 0)
    2011           0 :                 cred.encr_type = WPS_ENCR_NONE;
    2012             : #ifdef CONFIG_TESTING_OPTIONS
    2013           1 :         else if (os_strcmp(settings->encr, "WEP") == 0)
    2014           0 :                 cred.encr_type = WPS_ENCR_WEP;
    2015             : #endif /* CONFIG_TESTING_OPTIONS */
    2016           1 :         else if (os_strcmp(settings->encr, "TKIP") == 0)
    2017           0 :                 cred.encr_type = WPS_ENCR_TKIP;
    2018           1 :         else if (os_strcmp(settings->encr, "CCMP") == 0)
    2019           1 :                 cred.encr_type = WPS_ENCR_AES;
    2020             :         else
    2021           0 :                 return -1;
    2022             : 
    2023           1 :         return wps_er_config(wpa_s->wps_er, use_uuid, use_addr,
    2024             :                              (const u8 *) pin, os_strlen(pin), &cred);
    2025             : }
    2026             : 
    2027             : 
    2028             : #ifdef CONFIG_WPS_NFC
    2029           3 : struct wpabuf * wpas_wps_er_nfc_config_token(struct wpa_supplicant *wpa_s,
    2030             :                                              int ndef, const char *uuid)
    2031             : {
    2032             :         struct wpabuf *ret;
    2033           3 :         u8 u[UUID_LEN], *use_uuid = NULL;
    2034           3 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    2035             : 
    2036           3 :         if (!wpa_s->wps_er)
    2037           1 :                 return NULL;
    2038             : 
    2039           2 :         if (uuid_str2bin(uuid, u) == 0)
    2040           0 :                 use_uuid = u;
    2041           2 :         else if (hwaddr_aton(uuid, addr) == 0)
    2042           2 :                 use_addr = addr;
    2043             :         else
    2044           0 :                 return NULL;
    2045             : 
    2046           2 :         ret = wps_er_nfc_config_token(wpa_s->wps_er, use_uuid, use_addr);
    2047           2 :         if (ndef && ret) {
    2048             :                 struct wpabuf *tmp;
    2049           1 :                 tmp = ndef_build_wifi(ret);
    2050           1 :                 wpabuf_free(ret);
    2051           1 :                 if (tmp == NULL)
    2052           0 :                         return NULL;
    2053           1 :                 ret = tmp;
    2054             :         }
    2055             : 
    2056           2 :         return ret;
    2057             : }
    2058             : #endif /* CONFIG_WPS_NFC */
    2059             : 
    2060             : 
    2061             : static int callbacks_pending = 0;
    2062             : 
    2063           0 : static void wpas_wps_terminate_cb(void *ctx)
    2064             : {
    2065           0 :         wpa_printf(MSG_DEBUG, "WPS ER: Terminated");
    2066           0 :         if (--callbacks_pending <= 0)
    2067           0 :                 eloop_terminate();
    2068           0 : }
    2069             : #endif /* CONFIG_WPS_ER */
    2070             : 
    2071             : 
    2072          15 : int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s)
    2073             : {
    2074             : #ifdef CONFIG_WPS_ER
    2075          15 :         if (wpa_s->wps_er) {
    2076           0 :                 callbacks_pending++;
    2077           0 :                 wps_er_deinit(wpa_s->wps_er, wpas_wps_terminate_cb, wpa_s);
    2078           0 :                 wpa_s->wps_er = NULL;
    2079           0 :                 return 1;
    2080             :         }
    2081             : #endif /* CONFIG_WPS_ER */
    2082          15 :         return 0;
    2083             : }
    2084             : 
    2085             : 
    2086       20599 : void wpas_wps_update_config(struct wpa_supplicant *wpa_s)
    2087             : {
    2088       20599 :         struct wps_context *wps = wpa_s->wps;
    2089             : 
    2090       20599 :         if (wps == NULL)
    2091       20599 :                 return;
    2092             : 
    2093       20599 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_CONFIG_METHODS) {
    2094           6 :                 wps->config_methods = wps_config_methods_str2bin(
    2095           6 :                         wpa_s->conf->config_methods);
    2096           6 :                 if ((wps->config_methods &
    2097             :                      (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) ==
    2098             :                     (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) {
    2099           1 :                         wpa_printf(MSG_ERROR, "WPS: Both Label and Display "
    2100             :                                    "config methods are not allowed at the "
    2101             :                                    "same time");
    2102           1 :                         wps->config_methods &= ~WPS_CONFIG_LABEL;
    2103             :                 }
    2104             :         }
    2105       20599 :         wps->config_methods = wps_fix_config_methods(wps->config_methods);
    2106       20599 :         wps->dev.config_methods = wps->config_methods;
    2107             : 
    2108       20599 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_TYPE)
    2109           3 :                 os_memcpy(wps->dev.pri_dev_type, wpa_s->conf->device_type,
    2110             :                           WPS_DEV_TYPE_LEN);
    2111             : 
    2112       20599 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_SEC_DEVICE_TYPE) {
    2113          11 :                 wps->dev.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
    2114          11 :                 os_memcpy(wps->dev.sec_dev_type, wpa_s->conf->sec_device_type,
    2115             :                           wps->dev.num_sec_dev_types * WPS_DEV_TYPE_LEN);
    2116             :         }
    2117             : 
    2118       20599 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_VENDOR_EXTENSION)
    2119           4 :                 wpas_wps_set_vendor_ext_m1(wpa_s, wps);
    2120             : 
    2121       20599 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_OS_VERSION)
    2122           2 :                 wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
    2123             : 
    2124       20599 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_UUID)
    2125           2 :                 wpas_wps_set_uuid(wpa_s, wps);
    2126             : 
    2127       20599 :         if (wpa_s->conf->changed_parameters &
    2128             :             (CFG_CHANGED_DEVICE_NAME | CFG_CHANGED_WPS_STRING)) {
    2129             :                 /* Update pointers to make sure they refer current values */
    2130          26 :                 wps->dev.device_name = wpa_s->conf->device_name;
    2131          26 :                 wps->dev.manufacturer = wpa_s->conf->manufacturer;
    2132          26 :                 wps->dev.model_name = wpa_s->conf->model_name;
    2133          26 :                 wps->dev.model_number = wpa_s->conf->model_number;
    2134          26 :                 wps->dev.serial_number = wpa_s->conf->serial_number;
    2135             :         }
    2136             : }
    2137             : 
    2138             : 
    2139             : #ifdef CONFIG_WPS_NFC
    2140             : 
    2141             : #ifdef CONFIG_WPS_ER
    2142             : static struct wpabuf *
    2143           0 : wpas_wps_network_config_token(struct wpa_supplicant *wpa_s, int ndef,
    2144             :                               struct wpa_ssid *ssid)
    2145             : {
    2146             :         struct wpabuf *ret;
    2147             :         struct wps_credential cred;
    2148             : 
    2149           0 :         if (wpas_wps_network_to_cred(ssid, &cred) < 0)
    2150           0 :                 return NULL;
    2151             : 
    2152           0 :         ret = wps_er_config_token_from_cred(wpa_s->wps, &cred);
    2153             : 
    2154           0 :         if (ndef && ret) {
    2155             :                 struct wpabuf *tmp;
    2156           0 :                 tmp = ndef_build_wifi(ret);
    2157           0 :                 wpabuf_free(ret);
    2158           0 :                 if (tmp == NULL)
    2159           0 :                         return NULL;
    2160           0 :                 ret = tmp;
    2161             :         }
    2162             : 
    2163           0 :         return ret;
    2164             : }
    2165             : #endif /* CONFIG_WPS_ER */
    2166             : 
    2167             : 
    2168           2 : struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
    2169             :                                           int ndef, const char *id_str)
    2170             : {
    2171             : #ifdef CONFIG_WPS_ER
    2172           2 :         if (id_str) {
    2173             :                 int id;
    2174           1 :                 char *end = NULL;
    2175             :                 struct wpa_ssid *ssid;
    2176             : 
    2177           1 :                 id = strtol(id_str, &end, 10);
    2178           1 :                 if (end && *end)
    2179           1 :                         return NULL;
    2180             : 
    2181           0 :                 ssid = wpa_config_get_network(wpa_s->conf, id);
    2182           0 :                 if (ssid == NULL)
    2183           0 :                         return NULL;
    2184           0 :                 return wpas_wps_network_config_token(wpa_s, ndef, ssid);
    2185             :         }
    2186             : #endif /* CONFIG_WPS_ER */
    2187             : #ifdef CONFIG_AP
    2188           1 :         if (wpa_s->ap_iface)
    2189           1 :                 return wpas_ap_wps_nfc_config_token(wpa_s, ndef);
    2190             : #endif /* CONFIG_AP */
    2191           0 :         return NULL;
    2192             : }
    2193             : 
    2194             : 
    2195          13 : struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef)
    2196             : {
    2197          13 :         if (wpa_s->conf->wps_nfc_pw_from_config) {
    2198           0 :                 return wps_nfc_token_build(ndef,
    2199           0 :                                            wpa_s->conf->wps_nfc_dev_pw_id,
    2200           0 :                                            wpa_s->conf->wps_nfc_dh_pubkey,
    2201           0 :                                            wpa_s->conf->wps_nfc_dev_pw);
    2202             :         }
    2203             : 
    2204          39 :         return wps_nfc_token_gen(ndef, &wpa_s->conf->wps_nfc_dev_pw_id,
    2205          13 :                                  &wpa_s->conf->wps_nfc_dh_pubkey,
    2206          13 :                                  &wpa_s->conf->wps_nfc_dh_privkey,
    2207          13 :                                  &wpa_s->conf->wps_nfc_dev_pw);
    2208             : }
    2209             : 
    2210             : 
    2211          29 : int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *go_dev_addr,
    2212             :                        const u8 *bssid,
    2213             :                        const struct wpabuf *dev_pw, u16 dev_pw_id,
    2214             :                        int p2p_group, const u8 *peer_pubkey_hash,
    2215             :                        const u8 *ssid, size_t ssid_len, int freq)
    2216             : {
    2217          29 :         struct wps_context *wps = wpa_s->wps;
    2218             :         char pw[32 * 2 + 1];
    2219             : 
    2220          29 :         if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && dev_pw == NULL) {
    2221           3 :                 dev_pw = wpa_s->conf->wps_nfc_dev_pw;
    2222           3 :                 dev_pw_id = wpa_s->conf->wps_nfc_dev_pw_id;
    2223             :         }
    2224             : 
    2225          58 :         if (wpa_s->conf->wps_nfc_dh_pubkey == NULL ||
    2226          29 :             wpa_s->conf->wps_nfc_dh_privkey == NULL) {
    2227           0 :                 wpa_printf(MSG_DEBUG, "WPS: Missing DH params - "
    2228             :                            "cannot start NFC-triggered connection");
    2229           0 :                 return -1;
    2230             :         }
    2231             : 
    2232          29 :         if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && dev_pw == NULL) {
    2233           0 :                 wpa_printf(MSG_DEBUG, "WPS: Missing Device Password (id=%u) - "
    2234             :                            "cannot start NFC-triggered connection", dev_pw_id);
    2235           0 :                 return -1;
    2236             :         }
    2237             : 
    2238          29 :         dh5_free(wps->dh_ctx);
    2239          29 :         wpabuf_free(wps->dh_pubkey);
    2240          29 :         wpabuf_free(wps->dh_privkey);
    2241          29 :         wps->dh_privkey = wpabuf_dup(wpa_s->conf->wps_nfc_dh_privkey);
    2242          29 :         wps->dh_pubkey = wpabuf_dup(wpa_s->conf->wps_nfc_dh_pubkey);
    2243          29 :         if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) {
    2244           0 :                 wps->dh_ctx = NULL;
    2245           0 :                 wpabuf_free(wps->dh_pubkey);
    2246           0 :                 wps->dh_pubkey = NULL;
    2247           0 :                 wpabuf_free(wps->dh_privkey);
    2248           0 :                 wps->dh_privkey = NULL;
    2249           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to get DH priv/pub key");
    2250           0 :                 return -1;
    2251             :         }
    2252          29 :         wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey);
    2253          29 :         if (wps->dh_ctx == NULL) {
    2254           0 :                 wpabuf_free(wps->dh_pubkey);
    2255           0 :                 wps->dh_pubkey = NULL;
    2256           0 :                 wpabuf_free(wps->dh_privkey);
    2257           0 :                 wps->dh_privkey = NULL;
    2258           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to initialize DH context");
    2259           0 :                 return -1;
    2260             :         }
    2261             : 
    2262          29 :         if (dev_pw) {
    2263          24 :                 wpa_snprintf_hex_uppercase(pw, sizeof(pw),
    2264          12 :                                            wpabuf_head(dev_pw),
    2265             :                                            wpabuf_len(dev_pw));
    2266             :         }
    2267          29 :         return wpas_wps_start_dev_pw(wpa_s, go_dev_addr, bssid,
    2268             :                                      dev_pw ? pw : NULL,
    2269             :                                      p2p_group, dev_pw_id, peer_pubkey_hash,
    2270             :                                      ssid, ssid_len, freq);
    2271             : }
    2272             : 
    2273             : 
    2274           8 : static int wpas_wps_use_cred(struct wpa_supplicant *wpa_s,
    2275             :                              struct wps_parse_attr *attr)
    2276             : {
    2277             :         /*
    2278             :          * Disable existing networks temporarily to allow the newly learned
    2279             :          * credential to be preferred. Enable the temporarily disabled networks
    2280             :          * after 10 seconds.
    2281             :          */
    2282           8 :         wpas_wps_temp_disable(wpa_s, NULL);
    2283           8 :         eloop_register_timeout(10, 0, wpas_wps_reenable_networks_cb, wpa_s,
    2284             :                                NULL);
    2285             : 
    2286           8 :         if (wps_oob_use_cred(wpa_s->wps, attr) < 0)
    2287           4 :                 return -1;
    2288             : 
    2289           4 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
    2290           0 :                 return 0;
    2291             : 
    2292           4 :         if (attr->ap_channel) {
    2293           3 :                 u16 chan = WPA_GET_BE16(attr->ap_channel);
    2294           3 :                 int freq = 0;
    2295             : 
    2296           3 :                 if (chan >= 1 && chan <= 13)
    2297           3 :                         freq = 2407 + 5 * chan;
    2298           0 :                 else if (chan == 14)
    2299           0 :                         freq = 2484;
    2300           0 :                 else if (chan >= 30)
    2301           0 :                         freq = 5000 + 5 * chan;
    2302             : 
    2303           3 :                 if (freq) {
    2304           3 :                         wpa_printf(MSG_DEBUG, "WPS: Credential container indicated AP channel %u -> %u MHz",
    2305             :                                    chan, freq);
    2306           3 :                         wpa_s->after_wps = 5;
    2307           3 :                         wpa_s->wps_freq = freq;
    2308             :                 }
    2309             :         }
    2310             : 
    2311           4 :         wpa_printf(MSG_DEBUG, "WPS: Request reconnection with new network "
    2312             :                    "based on the received credential added");
    2313           4 :         wpa_s->normal_scans = 0;
    2314           4 :         wpa_supplicant_reinit_autoscan(wpa_s);
    2315           4 :         wpa_s->disconnected = 0;
    2316           4 :         wpa_s->reassociate = 1;
    2317             : 
    2318           4 :         wpa_supplicant_cancel_sched_scan(wpa_s);
    2319           4 :         wpa_supplicant_req_scan(wpa_s, 0, 0);
    2320             : 
    2321           4 :         return 0;
    2322             : }
    2323             : 
    2324             : 
    2325             : #ifdef CONFIG_WPS_ER
    2326           2 : static int wpas_wps_add_nfc_password_token(struct wpa_supplicant *wpa_s,
    2327             :                                            struct wps_parse_attr *attr)
    2328             : {
    2329           4 :         return wps_registrar_add_nfc_password_token(
    2330           2 :                 wpa_s->wps->registrar, attr->oob_dev_password,
    2331             :                 attr->oob_dev_password_len);
    2332             : }
    2333             : #endif /* CONFIG_WPS_ER */
    2334             : 
    2335             : 
    2336          12 : static int wpas_wps_nfc_tag_process(struct wpa_supplicant *wpa_s,
    2337             :                                     const struct wpabuf *wps)
    2338             : {
    2339             :         struct wps_parse_attr attr;
    2340             : 
    2341          12 :         wpa_hexdump_buf(MSG_DEBUG, "WPS: Received NFC tag payload", wps);
    2342             : 
    2343          12 :         if (wps_parse_msg(wps, &attr)) {
    2344           1 :                 wpa_printf(MSG_DEBUG, "WPS: Ignore invalid data from NFC tag");
    2345           1 :                 return -1;
    2346             :         }
    2347             : 
    2348          11 :         if (attr.num_cred)
    2349           8 :                 return wpas_wps_use_cred(wpa_s, &attr);
    2350             : 
    2351             : #ifdef CONFIG_WPS_ER
    2352           3 :         if (attr.oob_dev_password)
    2353           2 :                 return wpas_wps_add_nfc_password_token(wpa_s, &attr);
    2354             : #endif /* CONFIG_WPS_ER */
    2355             : 
    2356           1 :         wpa_printf(MSG_DEBUG, "WPS: Ignore unrecognized NFC tag");
    2357           1 :         return -1;
    2358             : }
    2359             : 
    2360             : 
    2361          35 : int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
    2362             :                           const struct wpabuf *data, int forced_freq)
    2363             : {
    2364          35 :         const struct wpabuf *wps = data;
    2365          35 :         struct wpabuf *tmp = NULL;
    2366             :         int ret;
    2367             : 
    2368          35 :         if (wpabuf_len(data) < 4)
    2369           2 :                 return -1;
    2370             : 
    2371          33 :         if (*wpabuf_head_u8(data) != 0x10) {
    2372             :                 /* Assume this contains full NDEF record */
    2373          27 :                 tmp = ndef_parse_wifi(data);
    2374          27 :                 if (tmp == NULL) {
    2375             : #ifdef CONFIG_P2P
    2376          21 :                         tmp = ndef_parse_p2p(data);
    2377          21 :                         if (tmp) {
    2378           9 :                                 ret = wpas_p2p_nfc_tag_process(wpa_s, tmp,
    2379             :                                                                forced_freq);
    2380           9 :                                 wpabuf_free(tmp);
    2381           9 :                                 return ret;
    2382             :                         }
    2383             : #endif /* CONFIG_P2P */
    2384          12 :                         wpa_printf(MSG_DEBUG, "WPS: Could not parse NDEF");
    2385          12 :                         return -1;
    2386             :                 }
    2387           6 :                 wps = tmp;
    2388             :         }
    2389             : 
    2390          12 :         ret = wpas_wps_nfc_tag_process(wpa_s, wps);
    2391          12 :         wpabuf_free(tmp);
    2392          12 :         return ret;
    2393             : }
    2394             : 
    2395             : 
    2396          12 : struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s,
    2397             :                                           int ndef)
    2398             : {
    2399             :         struct wpabuf *ret;
    2400             : 
    2401          13 :         if (wpa_s->conf->wps_nfc_dh_pubkey == NULL &&
    2402           1 :             wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
    2403           1 :                            &wpa_s->conf->wps_nfc_dh_privkey) < 0)
    2404           0 :                 return NULL;
    2405             : 
    2406          12 :         ret = wps_build_nfc_handover_req(wpa_s->wps,
    2407          12 :                                          wpa_s->conf->wps_nfc_dh_pubkey);
    2408             : 
    2409          12 :         if (ndef && ret) {
    2410             :                 struct wpabuf *tmp;
    2411          12 :                 tmp = ndef_build_wifi(ret);
    2412          12 :                 wpabuf_free(ret);
    2413          12 :                 if (tmp == NULL)
    2414           0 :                         return NULL;
    2415          12 :                 ret = tmp;
    2416             :         }
    2417             : 
    2418          12 :         return ret;
    2419             : }
    2420             : 
    2421             : 
    2422             : #ifdef CONFIG_WPS_NFC
    2423             : 
    2424             : static struct wpabuf *
    2425           3 : wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s, int ndef,
    2426             :                              const char *uuid)
    2427             : {
    2428             : #ifdef CONFIG_WPS_ER
    2429             :         struct wpabuf *ret;
    2430           3 :         u8 u[UUID_LEN], *use_uuid = NULL;
    2431           3 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    2432           3 :         struct wps_context *wps = wpa_s->wps;
    2433             : 
    2434           3 :         if (wps == NULL)
    2435           0 :                 return NULL;
    2436             : 
    2437           3 :         if (uuid == NULL)
    2438           0 :                 return NULL;
    2439           3 :         if (uuid_str2bin(uuid, u) == 0)
    2440           0 :                 use_uuid = u;
    2441           3 :         else if (hwaddr_aton(uuid, addr) == 0)
    2442           3 :                 use_addr = addr;
    2443             :         else
    2444           0 :                 return NULL;
    2445             : 
    2446           3 :         if (wpa_s->conf->wps_nfc_dh_pubkey == NULL) {
    2447           1 :                 if (wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
    2448           1 :                                    &wpa_s->conf->wps_nfc_dh_privkey) < 0)
    2449           0 :                         return NULL;
    2450             :         }
    2451             : 
    2452           3 :         wpas_wps_nfc_clear(wps);
    2453           3 :         wps->ap_nfc_dev_pw_id = DEV_PW_NFC_CONNECTION_HANDOVER;
    2454           3 :         wps->ap_nfc_dh_pubkey = wpabuf_dup(wpa_s->conf->wps_nfc_dh_pubkey);
    2455           3 :         wps->ap_nfc_dh_privkey = wpabuf_dup(wpa_s->conf->wps_nfc_dh_privkey);
    2456           3 :         if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey) {
    2457           0 :                 wpas_wps_nfc_clear(wps);
    2458           0 :                 return NULL;
    2459             :         }
    2460             : 
    2461           3 :         ret = wps_er_nfc_handover_sel(wpa_s->wps_er, wpa_s->wps, use_uuid,
    2462           3 :                                       use_addr, wpa_s->conf->wps_nfc_dh_pubkey);
    2463           3 :         if (ndef && ret) {
    2464             :                 struct wpabuf *tmp;
    2465           3 :                 tmp = ndef_build_wifi(ret);
    2466           3 :                 wpabuf_free(ret);
    2467           3 :                 if (tmp == NULL)
    2468           0 :                         return NULL;
    2469           3 :                 ret = tmp;
    2470             :         }
    2471             : 
    2472           3 :         return ret;
    2473             : #else /* CONFIG_WPS_ER */
    2474             :         return NULL;
    2475             : #endif /* CONFIG_WPS_ER */
    2476             : }
    2477             : #endif /* CONFIG_WPS_NFC */
    2478             : 
    2479             : 
    2480           6 : struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
    2481             :                                           int ndef, int cr, const char *uuid)
    2482             : {
    2483             :         struct wpabuf *ret;
    2484           6 :         if (!cr)
    2485           2 :                 return NULL;
    2486           4 :         ret = wpas_ap_wps_nfc_handover_sel(wpa_s, ndef);
    2487           4 :         if (ret)
    2488           1 :                 return ret;
    2489           3 :         return wpas_wps_er_nfc_handover_sel(wpa_s, ndef, uuid);
    2490             : }
    2491             : 
    2492             : 
    2493          11 : static int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
    2494             :                                         const struct wpabuf *data)
    2495             : {
    2496             :         struct wpabuf *wps;
    2497          11 :         int ret = -1;
    2498             :         u16 wsc_len;
    2499             :         const u8 *pos;
    2500             :         struct wpabuf msg;
    2501             :         struct wps_parse_attr attr;
    2502             :         u16 dev_pw_id;
    2503          11 :         const u8 *bssid = NULL;
    2504          11 :         int freq = 0;
    2505             : 
    2506          11 :         wps = ndef_parse_wifi(data);
    2507          11 :         if (wps == NULL)
    2508           0 :                 return -1;
    2509          11 :         wpa_printf(MSG_DEBUG, "WPS: Received application/vnd.wfa.wsc "
    2510             :                    "payload from NFC connection handover");
    2511          11 :         wpa_hexdump_buf(MSG_DEBUG, "WPS: NFC payload", wps);
    2512          11 :         if (wpabuf_len(wps) < 2) {
    2513           0 :                 wpa_printf(MSG_DEBUG, "WPS: Too short Wi-Fi Handover Select "
    2514             :                            "Message");
    2515           0 :                 goto out;
    2516             :         }
    2517          11 :         pos = wpabuf_head(wps);
    2518          11 :         wsc_len = WPA_GET_BE16(pos);
    2519          11 :         if (wsc_len > wpabuf_len(wps) - 2) {
    2520           0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid WSC attribute length (%u) "
    2521             :                            "in Wi-Fi Handover Select Message", wsc_len);
    2522           0 :                 goto out;
    2523             :         }
    2524          11 :         pos += 2;
    2525             : 
    2526          11 :         wpa_hexdump(MSG_DEBUG,
    2527             :                     "WPS: WSC attributes in Wi-Fi Handover Select Message",
    2528             :                     pos, wsc_len);
    2529          11 :         if (wsc_len < wpabuf_len(wps) - 2) {
    2530           0 :                 wpa_hexdump(MSG_DEBUG,
    2531             :                             "WPS: Ignore extra data after WSC attributes",
    2532           0 :                             pos + wsc_len, wpabuf_len(wps) - 2 - wsc_len);
    2533             :         }
    2534             : 
    2535          11 :         wpabuf_set(&msg, pos, wsc_len);
    2536          11 :         ret = wps_parse_msg(&msg, &attr);
    2537          11 :         if (ret < 0) {
    2538           0 :                 wpa_printf(MSG_DEBUG, "WPS: Could not parse WSC attributes in "
    2539             :                            "Wi-Fi Handover Select Message");
    2540           0 :                 goto out;
    2541             :         }
    2542             : 
    2543          22 :         if (attr.oob_dev_password == NULL ||
    2544          11 :             attr.oob_dev_password_len < WPS_OOB_PUBKEY_HASH_LEN + 2) {
    2545           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Out-of-Band Device Password "
    2546             :                            "included in Wi-Fi Handover Select Message");
    2547           0 :                 ret = -1;
    2548           0 :                 goto out;
    2549             :         }
    2550             : 
    2551          11 :         if (attr.ssid == NULL) {
    2552           0 :                 wpa_printf(MSG_DEBUG, "WPS: No SSID included in Wi-Fi Handover "
    2553             :                            "Select Message");
    2554           0 :                 ret = -1;
    2555           0 :                 goto out;
    2556             :         }
    2557             : 
    2558          11 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", attr.ssid, attr.ssid_len);
    2559             : 
    2560          11 :         if (attr.mac_addr) {
    2561          11 :                 bssid = attr.mac_addr;
    2562          66 :                 wpa_printf(MSG_DEBUG, "WPS: MAC Address (BSSID): " MACSTR,
    2563          66 :                            MAC2STR(bssid));
    2564             :         }
    2565             : 
    2566          11 :         if (attr.rf_bands)
    2567           8 :                 wpa_printf(MSG_DEBUG, "WPS: RF Bands: %d", *attr.rf_bands);
    2568             : 
    2569          11 :         if (attr.ap_channel) {
    2570           8 :                 u16 chan = WPA_GET_BE16(attr.ap_channel);
    2571             : 
    2572           8 :                 wpa_printf(MSG_DEBUG, "WPS: AP Channel: %d", chan);
    2573             : 
    2574          14 :                 if (chan >= 1 && chan <= 13 &&
    2575          12 :                     (attr.rf_bands == NULL || *attr.rf_bands & WPS_RF_24GHZ))
    2576           6 :                         freq = 2407 + 5 * chan;
    2577           3 :                 else if (chan == 14 &&
    2578           2 :                          (attr.rf_bands == NULL ||
    2579           1 :                           *attr.rf_bands & WPS_RF_24GHZ))
    2580           1 :                         freq = 2484;
    2581           2 :                 else if (chan >= 30 &&
    2582           2 :                          (attr.rf_bands == NULL ||
    2583           1 :                           *attr.rf_bands & WPS_RF_50GHZ))
    2584           1 :                         freq = 5000 + 5 * chan;
    2585             : 
    2586           8 :                 if (freq) {
    2587           8 :                         wpa_printf(MSG_DEBUG,
    2588             :                                    "WPS: AP indicated channel %u -> %u MHz",
    2589             :                                    chan, freq);
    2590             :                 }
    2591             :         }
    2592             : 
    2593          22 :         wpa_hexdump(MSG_DEBUG, "WPS: Out-of-Band Device Password",
    2594          11 :                     attr.oob_dev_password, attr.oob_dev_password_len);
    2595          11 :         dev_pw_id = WPA_GET_BE16(attr.oob_dev_password +
    2596             :                                  WPS_OOB_PUBKEY_HASH_LEN);
    2597          11 :         if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER) {
    2598           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected OOB Device Password ID "
    2599             :                            "%u in Wi-Fi Handover Select Message", dev_pw_id);
    2600           0 :                 ret = -1;
    2601           0 :                 goto out;
    2602             :         }
    2603          11 :         wpa_hexdump(MSG_DEBUG, "WPS: AP Public Key hash",
    2604          11 :                     attr.oob_dev_password, WPS_OOB_PUBKEY_HASH_LEN);
    2605             : 
    2606          11 :         ret = wpas_wps_start_nfc(wpa_s, NULL, bssid, NULL, dev_pw_id, 0,
    2607             :                                  attr.oob_dev_password,
    2608             :                                  attr.ssid, attr.ssid_len, freq);
    2609             : 
    2610             : out:
    2611          11 :         wpabuf_free(wps);
    2612          11 :         return ret;
    2613             : }
    2614             : 
    2615             : 
    2616          11 : int wpas_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
    2617             :                                  const struct wpabuf *req,
    2618             :                                  const struct wpabuf *sel)
    2619             : {
    2620          11 :         wpa_printf(MSG_DEBUG, "NFC: WPS connection handover reported");
    2621          11 :         wpa_hexdump_buf_key(MSG_DEBUG, "WPS: Carrier record in request", req);
    2622          11 :         wpa_hexdump_buf_key(MSG_DEBUG, "WPS: Carrier record in select", sel);
    2623          11 :         return wpas_wps_nfc_rx_handover_sel(wpa_s, sel);
    2624             : }
    2625             : 
    2626             : 
    2627           3 : int wpas_er_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
    2628             :                                     const struct wpabuf *req,
    2629             :                                     const struct wpabuf *sel)
    2630             : {
    2631             :         struct wpabuf *wps;
    2632           3 :         int ret = -1;
    2633             :         u16 wsc_len;
    2634             :         const u8 *pos;
    2635             :         struct wpabuf msg;
    2636             :         struct wps_parse_attr attr;
    2637             :         u16 dev_pw_id;
    2638             : 
    2639             :         /*
    2640             :          * Enrollee/station is always initiator of the NFC connection handover,
    2641             :          * so use the request message here to find Enrollee public key hash.
    2642             :          */
    2643           3 :         wps = ndef_parse_wifi(req);
    2644           3 :         if (wps == NULL)
    2645           0 :                 return -1;
    2646           3 :         wpa_printf(MSG_DEBUG, "WPS: Received application/vnd.wfa.wsc "
    2647             :                    "payload from NFC connection handover");
    2648           3 :         wpa_hexdump_buf(MSG_DEBUG, "WPS: NFC payload", wps);
    2649           3 :         if (wpabuf_len(wps) < 2) {
    2650           0 :                 wpa_printf(MSG_DEBUG, "WPS: Too short Wi-Fi Handover Request "
    2651             :                            "Message");
    2652           0 :                 goto out;
    2653             :         }
    2654           3 :         pos = wpabuf_head(wps);
    2655           3 :         wsc_len = WPA_GET_BE16(pos);
    2656           3 :         if (wsc_len > wpabuf_len(wps) - 2) {
    2657           0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid WSC attribute length (%u) "
    2658             :                            "in rt Wi-Fi Handover Request Message", wsc_len);
    2659           0 :                 goto out;
    2660             :         }
    2661           3 :         pos += 2;
    2662             : 
    2663           3 :         wpa_hexdump(MSG_DEBUG,
    2664             :                     "WPS: WSC attributes in Wi-Fi Handover Request Message",
    2665             :                     pos, wsc_len);
    2666           3 :         if (wsc_len < wpabuf_len(wps) - 2) {
    2667           0 :                 wpa_hexdump(MSG_DEBUG,
    2668             :                             "WPS: Ignore extra data after WSC attributes",
    2669           0 :                             pos + wsc_len, wpabuf_len(wps) - 2 - wsc_len);
    2670             :         }
    2671             : 
    2672           3 :         wpabuf_set(&msg, pos, wsc_len);
    2673           3 :         ret = wps_parse_msg(&msg, &attr);
    2674           3 :         if (ret < 0) {
    2675           0 :                 wpa_printf(MSG_DEBUG, "WPS: Could not parse WSC attributes in "
    2676             :                            "Wi-Fi Handover Request Message");
    2677           0 :                 goto out;
    2678             :         }
    2679             : 
    2680           6 :         if (attr.oob_dev_password == NULL ||
    2681           3 :             attr.oob_dev_password_len < WPS_OOB_PUBKEY_HASH_LEN + 2) {
    2682           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Out-of-Band Device Password "
    2683             :                            "included in Wi-Fi Handover Request Message");
    2684           0 :                 ret = -1;
    2685           0 :                 goto out;
    2686             :         }
    2687             : 
    2688           3 :         if (attr.uuid_e == NULL) {
    2689           0 :                 wpa_printf(MSG_DEBUG, "WPS: No UUID-E included in Wi-Fi "
    2690             :                            "Handover Request Message");
    2691           0 :                 ret = -1;
    2692           0 :                 goto out;
    2693             :         }
    2694             : 
    2695           3 :         wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", attr.uuid_e, WPS_UUID_LEN);
    2696             : 
    2697           6 :         wpa_hexdump(MSG_DEBUG, "WPS: Out-of-Band Device Password",
    2698           3 :                     attr.oob_dev_password, attr.oob_dev_password_len);
    2699           3 :         dev_pw_id = WPA_GET_BE16(attr.oob_dev_password +
    2700             :                                  WPS_OOB_PUBKEY_HASH_LEN);
    2701           3 :         if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER) {
    2702           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected OOB Device Password ID "
    2703             :                            "%u in Wi-Fi Handover Request Message", dev_pw_id);
    2704           0 :                 ret = -1;
    2705           0 :                 goto out;
    2706             :         }
    2707           3 :         wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Public Key hash",
    2708           3 :                     attr.oob_dev_password, WPS_OOB_PUBKEY_HASH_LEN);
    2709             : 
    2710           3 :         ret = wps_registrar_add_nfc_pw_token(wpa_s->wps->registrar,
    2711             :                                              attr.oob_dev_password,
    2712             :                                              DEV_PW_NFC_CONNECTION_HANDOVER,
    2713             :                                              NULL, 0, 1);
    2714             : 
    2715             : out:
    2716           3 :         wpabuf_free(wps);
    2717           3 :         return ret;
    2718             : }
    2719             : 
    2720             : #endif /* CONFIG_WPS_NFC */
    2721             : 
    2722             : 
    2723        1546 : static void wpas_wps_dump_ap_info(struct wpa_supplicant *wpa_s)
    2724             : {
    2725             :         size_t i;
    2726             :         struct os_reltime now;
    2727             : 
    2728        1546 :         if (wpa_debug_level > MSG_DEBUG)
    2729        1088 :                 return;
    2730             : 
    2731        1546 :         if (wpa_s->wps_ap == NULL)
    2732        1088 :                 return;
    2733             : 
    2734         458 :         os_get_reltime(&now);
    2735             : 
    2736         956 :         for (i = 0; i < wpa_s->num_wps_ap; i++) {
    2737         498 :                 struct wps_ap_info *ap = &wpa_s->wps_ap[i];
    2738         498 :                 struct wpa_blacklist *e = wpa_blacklist_get(wpa_s, ap->bssid);
    2739             : 
    2740        3992 :                 wpa_printf(MSG_DEBUG, "WPS: AP[%d] " MACSTR " type=%d "
    2741             :                            "tries=%d last_attempt=%d sec ago blacklist=%d",
    2742        2988 :                            (int) i, MAC2STR(ap->bssid), ap->type, ap->tries,
    2743         498 :                            ap->last_attempt.sec > 0 ?
    2744           8 :                            (int) now.sec - (int) ap->last_attempt.sec : -1,
    2745             :                            e ? e->count : 0);
    2746             :         }
    2747             : }
    2748             : 
    2749             : 
    2750         737 : static struct wps_ap_info * wpas_wps_get_ap_info(struct wpa_supplicant *wpa_s,
    2751             :                                                  const u8 *bssid)
    2752             : {
    2753             :         size_t i;
    2754             : 
    2755         737 :         if (wpa_s->wps_ap == NULL)
    2756         354 :                 return NULL;
    2757             : 
    2758         429 :         for (i = 0; i < wpa_s->num_wps_ap; i++) {
    2759         407 :                 struct wps_ap_info *ap = &wpa_s->wps_ap[i];
    2760         407 :                 if (os_memcmp(ap->bssid, bssid, ETH_ALEN) == 0)
    2761         361 :                         return ap;
    2762             :         }
    2763             : 
    2764          22 :         return NULL;
    2765             : }
    2766             : 
    2767             : 
    2768        1674 : static void wpas_wps_update_ap_info_bss(struct wpa_supplicant *wpa_s,
    2769             :                                         struct wpa_scan_res *res)
    2770             : {
    2771             :         struct wpabuf *wps;
    2772             :         enum wps_ap_info_type type;
    2773             :         struct wps_ap_info *ap;
    2774             :         int r;
    2775             : 
    2776        1674 :         if (wpa_scan_get_vendor_ie(res, WPS_IE_VENDOR_TYPE) == NULL)
    2777        1129 :                 return;
    2778             : 
    2779         545 :         wps = wpa_scan_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
    2780         545 :         if (wps == NULL)
    2781           0 :                 return;
    2782             : 
    2783         545 :         r = wps_is_addr_authorized(wps, wpa_s->own_addr, 1);
    2784         545 :         if (r == 2)
    2785          95 :                 type = WPS_AP_SEL_REG_OUR;
    2786         450 :         else if (r == 1)
    2787         194 :                 type = WPS_AP_SEL_REG;
    2788             :         else
    2789         256 :                 type = WPS_AP_NOT_SEL_REG;
    2790             : 
    2791         545 :         wpabuf_free(wps);
    2792             : 
    2793         545 :         ap = wpas_wps_get_ap_info(wpa_s, res->bssid);
    2794         545 :         if (ap) {
    2795         169 :                 if (ap->type != type) {
    2796         252 :                         wpa_printf(MSG_DEBUG, "WPS: AP " MACSTR
    2797             :                                    " changed type %d -> %d",
    2798         252 :                                    MAC2STR(res->bssid), ap->type, type);
    2799          42 :                         ap->type = type;
    2800          42 :                         if (type != WPS_AP_NOT_SEL_REG)
    2801          15 :                                 wpa_blacklist_del(wpa_s, ap->bssid);
    2802             :                 }
    2803         169 :                 return;
    2804             :         }
    2805             : 
    2806         376 :         ap = os_realloc_array(wpa_s->wps_ap, wpa_s->num_wps_ap + 1,
    2807             :                               sizeof(struct wps_ap_info));
    2808         376 :         if (ap == NULL)
    2809           0 :                 return;
    2810             : 
    2811         376 :         wpa_s->wps_ap = ap;
    2812         376 :         ap = &wpa_s->wps_ap[wpa_s->num_wps_ap];
    2813         376 :         wpa_s->num_wps_ap++;
    2814             : 
    2815         376 :         os_memset(ap, 0, sizeof(*ap));
    2816         376 :         os_memcpy(ap->bssid, res->bssid, ETH_ALEN);
    2817         376 :         ap->type = type;
    2818        2256 :         wpa_printf(MSG_DEBUG, "WPS: AP " MACSTR " type %d added",
    2819        2256 :                    MAC2STR(ap->bssid), ap->type);
    2820             : }
    2821             : 
    2822             : 
    2823        1546 : void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s,
    2824             :                              struct wpa_scan_results *scan_res)
    2825             : {
    2826             :         size_t i;
    2827             : 
    2828        3220 :         for (i = 0; i < scan_res->num; i++)
    2829        1674 :                 wpas_wps_update_ap_info_bss(wpa_s, scan_res->res[i]);
    2830             : 
    2831        1546 :         wpas_wps_dump_ap_info(wpa_s);
    2832        1546 : }
    2833             : 
    2834             : 
    2835        2568 : void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid)
    2836             : {
    2837             :         struct wps_ap_info *ap;
    2838             : 
    2839        2568 :         wpa_s->after_wps = 0;
    2840             : 
    2841        2568 :         if (!wpa_s->wps_ap_iter)
    2842        2376 :                 return;
    2843         192 :         ap = wpas_wps_get_ap_info(wpa_s, bssid);
    2844         192 :         if (ap == NULL)
    2845           0 :                 return;
    2846         192 :         ap->tries++;
    2847         192 :         os_get_reltime(&ap->last_attempt);
    2848             : }

Generated by: LCOV version 1.10