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

Generated by: LCOV version 1.10