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