1 /*
2  * wpa_supplicant / WPS integration
3  * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 #include "common.h"
18 #include "ieee802_11_defs.h"
19 #include "wpa_common.h"
20 #include "config.h"
21 #include "eap_peer/eap.h"
22 #include "wpa_supplicant_i.h"
23 #include "eloop.h"
24 #include "uuid.h"
25 #include "wpa_ctrl.h"
26 #include "ctrl_iface_dbus.h"
27 #include "eap_common/eap_wsc_common.h"
28 #include "blacklist.h"
29 #include "wps_supplicant.h"
30 
31 #define WPS_PIN_SCAN_IGNORE_SEL_REG 3
32 
33 static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx);
34 static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
35 
36 
37 int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
38 {
39 	if (!wpa_s->wps_success &&
40 	    wpa_s->current_ssid &&
41 	    eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
42 		const u8 *bssid = wpa_s->bssid;
43 		if (is_zero_ether_addr(bssid))
44 			bssid = wpa_s->pending_bssid;
45 
46 		wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR
47 			   " did not succeed - continue trying to find "
48 			   "suitable AP", MAC2STR(bssid));
49 		wpa_blacklist_add(wpa_s, bssid);
50 
51 		wpa_supplicant_deauthenticate(wpa_s,
52 					      WLAN_REASON_DEAUTH_LEAVING);
53 		wpa_s->reassociate = 1;
54 		wpa_supplicant_req_scan(wpa_s,
55 					wpa_s->blacklist_cleared ? 5 : 0, 0);
56 		wpa_s->blacklist_cleared = 0;
57 		return 1;
58 	}
59 
60 	eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
61 
62 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid &&
63 	    !(wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
64 		wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - "
65 			   "try to associate with the received credential");
66 		wpa_supplicant_deauthenticate(wpa_s,
67 					      WLAN_REASON_DEAUTH_LEAVING);
68 		wpa_s->reassociate = 1;
69 		wpa_supplicant_req_scan(wpa_s, 0, 0);
70 		return 1;
71 	}
72 
73 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) {
74 		wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting "
75 			   "for external credential processing");
76 		wpas_clear_wps(wpa_s);
77 		wpa_supplicant_deauthenticate(wpa_s,
78 					      WLAN_REASON_DEAUTH_LEAVING);
79 		return 1;
80 	}
81 
82 	return 0;
83 }
84 
85 
86 static int wpa_supplicant_wps_cred(void *ctx,
87 				   const struct wps_credential *cred)
88 {
89 	struct wpa_supplicant *wpa_s = ctx;
90 	struct wpa_ssid *ssid = wpa_s->current_ssid;
91 
92 	if ((wpa_s->conf->wps_cred_processing == 1 ||
93 	     wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
94 		size_t blen = cred->cred_attr_len * 2 + 1;
95 		char *buf = os_malloc(blen);
96 		if (buf) {
97 			wpa_snprintf_hex(buf, blen,
98 					 cred->cred_attr, cred->cred_attr_len);
99 			wpa_msg(wpa_s, MSG_INFO, "%s%s",
100 				WPS_EVENT_CRED_RECEIVED, buf);
101 			os_free(buf);
102 		}
103 		wpa_supplicant_dbus_notify_wps_cred(wpa_s, cred);
104 	} else
105 		wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
106 
107 	wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
108 			cred->cred_attr, cred->cred_attr_len);
109 
110 	if (wpa_s->conf->wps_cred_processing == 1)
111 		return 0;
112 
113 	if (cred->auth_type != WPS_AUTH_OPEN &&
114 	    cred->auth_type != WPS_AUTH_SHARED &&
115 	    cred->auth_type != WPS_AUTH_WPAPSK &&
116 	    cred->auth_type != WPS_AUTH_WPA2PSK) {
117 		wpa_printf(MSG_DEBUG, "WPS: Ignored credentials for "
118 			   "unsupported authentication type %d",
119 			   cred->auth_type);
120 		return 0;
121 	}
122 
123 	if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
124 		wpa_printf(MSG_DEBUG, "WPS: Replace WPS network block based "
125 			   "on the received credential");
126 		os_free(ssid->eap.identity);
127 		ssid->eap.identity = NULL;
128 		ssid->eap.identity_len = 0;
129 		os_free(ssid->eap.phase1);
130 		ssid->eap.phase1 = NULL;
131 		os_free(ssid->eap.eap_methods);
132 		ssid->eap.eap_methods = NULL;
133 	} else {
134 		wpa_printf(MSG_DEBUG, "WPS: Create a new network based on the "
135 			   "received credential");
136 		ssid = wpa_config_add_network(wpa_s->conf);
137 		if (ssid == NULL)
138 			return -1;
139 	}
140 
141 	wpa_config_set_network_defaults(ssid);
142 
143 	os_free(ssid->ssid);
144 	ssid->ssid = os_malloc(cred->ssid_len);
145 	if (ssid->ssid) {
146 		os_memcpy(ssid->ssid, cred->ssid, cred->ssid_len);
147 		ssid->ssid_len = cred->ssid_len;
148 	}
149 
150 	switch (cred->encr_type) {
151 	case WPS_ENCR_NONE:
152 		break;
153 	case WPS_ENCR_WEP:
154 		if (cred->key_len > 0 && cred->key_len <= MAX_WEP_KEY_LEN &&
155 		    cred->key_idx < NUM_WEP_KEYS) {
156 			os_memcpy(ssid->wep_key[cred->key_idx], cred->key,
157 				  cred->key_len);
158 			ssid->wep_key_len[cred->key_idx] = cred->key_len;
159 			ssid->wep_tx_keyidx = cred->key_idx;
160 		}
161 		break;
162 	case WPS_ENCR_TKIP:
163 		ssid->pairwise_cipher = WPA_CIPHER_TKIP;
164 		break;
165 	case WPS_ENCR_AES:
166 		ssid->pairwise_cipher = WPA_CIPHER_CCMP;
167 		break;
168 	}
169 
170 	switch (cred->auth_type) {
171 	case WPS_AUTH_OPEN:
172 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
173 		ssid->key_mgmt = WPA_KEY_MGMT_NONE;
174 		ssid->proto = 0;
175 		break;
176 	case WPS_AUTH_SHARED:
177 		ssid->auth_alg = WPA_AUTH_ALG_SHARED;
178 		ssid->key_mgmt = WPA_KEY_MGMT_NONE;
179 		ssid->proto = 0;
180 		break;
181 	case WPS_AUTH_WPAPSK:
182 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
183 		ssid->key_mgmt = WPA_KEY_MGMT_PSK;
184 		ssid->proto = WPA_PROTO_WPA;
185 		break;
186 	case WPS_AUTH_WPA:
187 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
188 		ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
189 		ssid->proto = WPA_PROTO_WPA;
190 		break;
191 	case WPS_AUTH_WPA2:
192 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
193 		ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
194 		ssid->proto = WPA_PROTO_RSN;
195 		break;
196 	case WPS_AUTH_WPA2PSK:
197 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
198 		ssid->key_mgmt = WPA_KEY_MGMT_PSK;
199 		ssid->proto = WPA_PROTO_RSN;
200 		break;
201 	}
202 
203 	if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) {
204 		if (cred->key_len == 2 * PMK_LEN) {
205 			if (hexstr2bin((const char *) cred->key, ssid->psk,
206 				       PMK_LEN)) {
207 				wpa_printf(MSG_ERROR, "WPS: Invalid Network "
208 					   "Key");
209 				return -1;
210 			}
211 			ssid->psk_set = 1;
212 		} else if (cred->key_len >= 8 && cred->key_len < 2 * PMK_LEN) {
213 			os_free(ssid->passphrase);
214 			ssid->passphrase = os_malloc(cred->key_len + 1);
215 			if (ssid->passphrase == NULL)
216 				return -1;
217 			os_memcpy(ssid->passphrase, cred->key, cred->key_len);
218 			ssid->passphrase[cred->key_len] = '\0';
219 			wpa_config_update_psk(ssid);
220 		} else {
221 			wpa_printf(MSG_ERROR, "WPS: Invalid Network Key "
222 				   "length %lu",
223 				   (unsigned long) cred->key_len);
224 			return -1;
225 		}
226 	}
227 
228 #ifndef CONFIG_NO_CONFIG_WRITE
229 	if (wpa_s->conf->update_config &&
230 	    wpa_config_write(wpa_s->confname, wpa_s->conf)) {
231 		wpa_printf(MSG_DEBUG, "WPS: Failed to update configuration");
232 		return -1;
233 	}
234 #endif /* CONFIG_NO_CONFIG_WRITE */
235 
236 	return 0;
237 }
238 
239 
240 static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s,
241 					 struct wps_event_m2d *m2d)
242 {
243 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_M2D
244 		"dev_password_id=%d config_error=%d",
245 		m2d->dev_password_id, m2d->config_error);
246 }
247 
248 
249 static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
250 					  struct wps_event_fail *fail)
251 {
252 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL "msg=%d", fail->msg);
253 	wpas_clear_wps(wpa_s);
254 }
255 
256 
257 static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s)
258 {
259 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
260 	wpa_s->wps_success = 1;
261 }
262 
263 
264 static void wpa_supplicant_wps_event(void *ctx, enum wps_event event,
265 				     union wps_event_data *data)
266 {
267 	struct wpa_supplicant *wpa_s = ctx;
268 	switch (event) {
269 	case WPS_EV_M2D:
270 		wpa_supplicant_wps_event_m2d(wpa_s, &data->m2d);
271 		break;
272 	case WPS_EV_FAIL:
273 		wpa_supplicant_wps_event_fail(wpa_s, &data->fail);
274 		break;
275 	case WPS_EV_SUCCESS:
276 		wpa_supplicant_wps_event_success(wpa_s);
277 		break;
278 	case WPS_EV_PWD_AUTH_FAIL:
279 		break;
280 	}
281 }
282 
283 
284 enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid)
285 {
286 	if (eap_is_wps_pbc_enrollee(&ssid->eap) ||
287 	    eap_is_wps_pin_enrollee(&ssid->eap))
288 		return WPS_REQ_ENROLLEE;
289 	else
290 		return WPS_REQ_REGISTRAR;
291 }
292 
293 
294 static void wpas_clear_wps(struct wpa_supplicant *wpa_s)
295 {
296 	int id;
297 	struct wpa_ssid *ssid;
298 
299 	eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
300 
301 	/* Remove any existing WPS network from configuration */
302 	ssid = wpa_s->conf->ssid;
303 	while (ssid) {
304 		if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
305 			if (ssid == wpa_s->current_ssid)
306 				wpa_s->current_ssid = NULL;
307 			id = ssid->id;
308 		} else
309 			id = -1;
310 		ssid = ssid->next;
311 		if (id >= 0)
312 			wpa_config_remove_network(wpa_s->conf, id);
313 	}
314 }
315 
316 
317 static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx)
318 {
319 	struct wpa_supplicant *wpa_s = eloop_ctx;
320 	wpa_printf(MSG_INFO, WPS_EVENT_TIMEOUT "Requested operation timed "
321 		   "out");
322 	wpas_clear_wps(wpa_s);
323 }
324 
325 
326 static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
327 					      int registrar, const u8 *bssid)
328 {
329 	struct wpa_ssid *ssid;
330 
331 	ssid = wpa_config_add_network(wpa_s->conf);
332 	if (ssid == NULL)
333 		return NULL;
334 	wpa_config_set_network_defaults(ssid);
335 	if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 ||
336 	    wpa_config_set(ssid, "eap", "WSC", 0) < 0 ||
337 	    wpa_config_set(ssid, "identity", registrar ?
338 			   "\"" WSC_ID_REGISTRAR "\"" :
339 			   "\"" WSC_ID_ENROLLEE "\"", 0) < 0) {
340 		wpa_config_remove_network(wpa_s->conf, ssid->id);
341 		return NULL;
342 	}
343 
344 	if (bssid) {
345 		size_t i;
346 		struct wpa_scan_res *res;
347 
348 		os_memcpy(ssid->bssid, bssid, ETH_ALEN);
349 		ssid->bssid_set = 1;
350 
351 		/* Try to get SSID from scan results */
352 		if (wpa_s->scan_res == NULL &&
353 		    wpa_supplicant_get_scan_results(wpa_s) < 0)
354 			return ssid; /* Could not find any scan results */
355 
356 		for (i = 0; i < wpa_s->scan_res->num; i++) {
357 			const u8 *ie;
358 
359 			res = wpa_s->scan_res->res[i];
360 			if (os_memcmp(bssid, res->bssid, ETH_ALEN) != 0)
361 				continue;
362 
363 			ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
364 			if (ie == NULL)
365 				break;
366 			os_free(ssid->ssid);
367 			ssid->ssid = os_malloc(ie[1]);
368 			if (ssid->ssid == NULL)
369 				break;
370 			os_memcpy(ssid->ssid, ie + 2, ie[1]);
371 			ssid->ssid_len = ie[1];
372 			break;
373 		}
374 	}
375 
376 	return ssid;
377 }
378 
379 
380 static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
381 			     struct wpa_ssid *selected)
382 {
383 	struct wpa_ssid *ssid;
384 
385 	/* Mark all other networks disabled and trigger reassociation */
386 	ssid = wpa_s->conf->ssid;
387 	while (ssid) {
388 		ssid->disabled = ssid != selected;
389 		ssid = ssid->next;
390 	}
391 	wpa_s->disconnected = 0;
392 	wpa_s->reassociate = 1;
393 	wpa_s->scan_runs = 0;
394 	wpa_s->wps_success = 0;
395 	wpa_s->blacklist_cleared = 0;
396 	wpa_supplicant_req_scan(wpa_s, 0, 0);
397 }
398 
399 
400 int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid)
401 {
402 	struct wpa_ssid *ssid;
403 	wpas_clear_wps(wpa_s);
404 	ssid = wpas_wps_add_network(wpa_s, 0, bssid);
405 	if (ssid == NULL)
406 		return -1;
407 	wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0);
408 	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
409 			       wpa_s, NULL);
410 	wpas_wps_reassoc(wpa_s, ssid);
411 	return 0;
412 }
413 
414 
415 int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
416 		       const char *pin)
417 {
418 	struct wpa_ssid *ssid;
419 	char val[30];
420 	unsigned int rpin = 0;
421 
422 	wpas_clear_wps(wpa_s);
423 	ssid = wpas_wps_add_network(wpa_s, 0, bssid);
424 	if (ssid == NULL)
425 		return -1;
426 	if (pin)
427 		os_snprintf(val, sizeof(val), "\"pin=%s\"", pin);
428 	else {
429 		rpin = wps_generate_pin();
430 		os_snprintf(val, sizeof(val), "\"pin=%08d\"", rpin);
431 	}
432 	wpa_config_set(ssid, "phase1", val, 0);
433 	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
434 			       wpa_s, NULL);
435 	wpas_wps_reassoc(wpa_s, ssid);
436 	return rpin;
437 }
438 
439 
440 int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
441 		       const char *pin)
442 {
443 	struct wpa_ssid *ssid;
444 	char val[30];
445 
446 	if (!pin)
447 		return -1;
448 	wpas_clear_wps(wpa_s);
449 	ssid = wpas_wps_add_network(wpa_s, 1, bssid);
450 	if (ssid == NULL)
451 		return -1;
452 	os_snprintf(val, sizeof(val), "\"pin=%s\"", pin);
453 	wpa_config_set(ssid, "phase1", val, 0);
454 	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
455 			       wpa_s, NULL);
456 	wpas_wps_reassoc(wpa_s, ssid);
457 	return 0;
458 }
459 
460 
461 static int wpas_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk,
462 			       size_t psk_len)
463 {
464 	wpa_printf(MSG_DEBUG, "WPS: Received new WPA/WPA2-PSK from WPS for "
465 		   "STA " MACSTR, MAC2STR(mac_addr));
466 	wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len);
467 
468 	/* TODO */
469 
470 	return 0;
471 }
472 
473 
474 static void wpas_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
475 				   const struct wps_device_data *dev)
476 {
477 	char uuid[40], txt[400];
478 	int len;
479 	if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
480 		return;
481 	wpa_printf(MSG_DEBUG, "WPS: PIN needed for UUID-E %s", uuid);
482 	len = os_snprintf(txt, sizeof(txt), "WPS-EVENT-PIN-NEEDED %s " MACSTR
483 			  " [%s|%s|%s|%s|%s|%d-%08X-%d]",
484 			  uuid, MAC2STR(dev->mac_addr), dev->device_name,
485 			  dev->manufacturer, dev->model_name,
486 			  dev->model_number, dev->serial_number,
487 			  dev->categ, dev->oui, dev->sub_categ);
488 	if (len > 0 && len < (int) sizeof(txt))
489 		wpa_printf(MSG_INFO, "%s", txt);
490 }
491 
492 
493 int wpas_wps_init(struct wpa_supplicant *wpa_s)
494 {
495 	struct wps_context *wps;
496 	struct wps_registrar_config rcfg;
497 
498 	wps = os_zalloc(sizeof(*wps));
499 	if (wps == NULL)
500 		return -1;
501 
502 	wps->cred_cb = wpa_supplicant_wps_cred;
503 	wps->event_cb = wpa_supplicant_wps_event;
504 	wps->cb_ctx = wpa_s;
505 
506 	wps->dev.device_name = wpa_s->conf->device_name;
507 	wps->dev.manufacturer = wpa_s->conf->manufacturer;
508 	wps->dev.model_name = wpa_s->conf->model_name;
509 	wps->dev.model_number = wpa_s->conf->model_number;
510 	wps->dev.serial_number = wpa_s->conf->serial_number;
511 	if (wpa_s->conf->device_type) {
512 		char *pos;
513 		u8 oui[4];
514 		/* <categ>-<OUI>-<subcateg> */
515 		wps->dev.categ = atoi(wpa_s->conf->device_type);
516 		pos = os_strchr(wpa_s->conf->device_type, '-');
517 		if (pos == NULL) {
518 			wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
519 			os_free(wps);
520 			return -1;
521 		}
522 		pos++;
523 		if (hexstr2bin(pos, oui, 4)) {
524 			wpa_printf(MSG_ERROR, "WPS: Invalid device_type OUI");
525 			os_free(wps);
526 			return -1;
527 		}
528 		wps->dev.oui = WPA_GET_BE32(oui);
529 		pos = os_strchr(pos, '-');
530 		if (pos == NULL) {
531 			wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
532 			os_free(wps);
533 			return -1;
534 		}
535 		pos++;
536 		wps->dev.sub_categ = atoi(pos);
537 	}
538 	wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
539 	wps->dev.rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ; /* TODO: config */
540 	os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN);
541 	if (is_nil_uuid(wpa_s->conf->uuid)) {
542 		uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid);
543 		wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC address",
544 			    wps->uuid, WPS_UUID_LEN);
545 	} else
546 		os_memcpy(wps->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
547 
548 	wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
549 	wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
550 
551 	os_memset(&rcfg, 0, sizeof(rcfg));
552 	rcfg.new_psk_cb = wpas_wps_new_psk_cb;
553 	rcfg.pin_needed_cb = wpas_wps_pin_needed_cb;
554 	rcfg.cb_ctx = wpa_s;
555 
556 	wps->registrar = wps_registrar_init(wps, &rcfg);
557 	if (wps->registrar == NULL) {
558 		wpa_printf(MSG_DEBUG, "Failed to initialize WPS Registrar");
559 		os_free(wps);
560 		return -1;
561 	}
562 
563 	wpa_s->wps = wps;
564 
565 	return 0;
566 }
567 
568 
569 void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
570 {
571 	eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
572 
573 	if (wpa_s->wps == NULL)
574 		return;
575 
576 	wps_registrar_deinit(wpa_s->wps->registrar);
577 	os_free(wpa_s->wps->network_key);
578 	os_free(wpa_s->wps);
579 	wpa_s->wps = NULL;
580 }
581 
582 
583 int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
584 			    struct wpa_ssid *ssid, struct wpa_scan_res *bss)
585 {
586 	struct wpabuf *wps_ie;
587 
588 	if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
589 		return -1;
590 
591 	wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
592 	if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
593 		if (!wps_ie) {
594 			wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
595 			return 0;
596 		}
597 
598 		if (!wps_is_selected_pbc_registrar(wps_ie)) {
599 			wpa_printf(MSG_DEBUG, "   skip - WPS AP "
600 				   "without active PBC Registrar");
601 			wpabuf_free(wps_ie);
602 			return 0;
603 		}
604 
605 		/* TODO: overlap detection */
606 		wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
607 			   "(Active PBC)");
608 		wpabuf_free(wps_ie);
609 		return 1;
610 	}
611 
612 	if (eap_is_wps_pin_enrollee(&ssid->eap)) {
613 		if (!wps_ie) {
614 			wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
615 			return 0;
616 		}
617 
618 		/*
619 		 * Start with WPS APs that advertise active PIN Registrar and
620 		 * allow any WPS AP after third scan since some APs do not set
621 		 * Selected Registrar attribute properly when using external
622 		 * Registrar.
623 		 */
624 		if (!wps_is_selected_pin_registrar(wps_ie)) {
625 			if (wpa_s->scan_runs < WPS_PIN_SCAN_IGNORE_SEL_REG) {
626 				wpa_printf(MSG_DEBUG, "   skip - WPS AP "
627 					   "without active PIN Registrar");
628 				wpabuf_free(wps_ie);
629 				return 0;
630 			}
631 			wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
632 		} else {
633 			wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
634 				   "(Active PIN)");
635 		}
636 		wpabuf_free(wps_ie);
637 		return 1;
638 	}
639 
640 	if (wps_ie) {
641 		wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
642 		wpabuf_free(wps_ie);
643 		return 1;
644 	}
645 
646 	return -1;
647 }
648 
649 
650 int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
651 			      struct wpa_ssid *ssid,
652 			      struct wpa_scan_res *bss)
653 {
654 	struct wpabuf *wps_ie = NULL;
655 	int ret = 0;
656 
657 	if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
658 		wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
659 		if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) {
660 			/* allow wildcard SSID for WPS PBC */
661 			ret = 1;
662 		}
663 	} else if (eap_is_wps_pin_enrollee(&ssid->eap)) {
664 		wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
665 		if (wps_ie &&
666 		    (wps_is_selected_pin_registrar(wps_ie) ||
667 		     wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) {
668 			/* allow wildcard SSID for WPS PIN */
669 			ret = 1;
670 		}
671 	}
672 
673 	if (!ret && ssid->bssid_set &&
674 	    os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) {
675 		/* allow wildcard SSID due to hardcoded BSSID match */
676 		ret = 1;
677 	}
678 
679 	wpabuf_free(wps_ie);
680 
681 	return ret;
682 }
683 
684 
685 int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s,
686 			      struct wpa_scan_res *selected,
687 			      struct wpa_ssid *ssid)
688 {
689 	const u8 *sel_uuid, *uuid;
690 	size_t i;
691 	struct wpabuf *wps_ie;
692 	int ret = 0;
693 
694 	if (!eap_is_wps_pbc_enrollee(&ssid->eap))
695 		return 0;
696 
697 	/* Make sure that only one AP is in active PBC mode */
698 	wps_ie = wpa_scan_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE);
699 	if (wps_ie)
700 		sel_uuid = wps_get_uuid_e(wps_ie);
701 	else
702 		sel_uuid = NULL;
703 
704 	for (i = 0; i < wpa_s->scan_res->num; i++) {
705 		struct wpa_scan_res *bss = wpa_s->scan_res->res[i];
706 		struct wpabuf *ie;
707 		if (bss == selected)
708 			continue;
709 		ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
710 		if (!ie)
711 			continue;
712 		if (!wps_is_selected_pbc_registrar(ie)) {
713 			wpabuf_free(ie);
714 			continue;
715 		}
716 		uuid = wps_get_uuid_e(ie);
717 		if (sel_uuid == NULL || uuid == NULL ||
718 		    os_memcmp(sel_uuid, uuid, 16) != 0) {
719 			ret = 1; /* PBC overlap */
720 			wpabuf_free(ie);
721 			break;
722 		}
723 
724 		/* TODO: verify that this is reasonable dual-band situation */
725 
726 		wpabuf_free(ie);
727 	}
728 
729 	wpabuf_free(wps_ie);
730 
731 	return ret;
732 }
733 
734 
735 void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s)
736 {
737 	size_t i;
738 
739 	if (wpa_s->disconnected || wpa_s->wpa_state >= WPA_ASSOCIATED)
740 		return;
741 
742 	for (i = 0; i < wpa_s->scan_res->num; i++) {
743 		struct wpa_scan_res *bss = wpa_s->scan_res->res[i];
744 		struct wpabuf *ie;
745 		ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
746 		if (!ie)
747 			continue;
748 		if (wps_is_selected_pbc_registrar(ie))
749 			wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PBC);
750 		else if (wps_is_selected_pin_registrar(ie))
751 			wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PIN);
752 		else
753 			wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE);
754 		wpabuf_free(ie);
755 		break;
756 	}
757 }
758 
759 
760 int wpas_wps_searching(struct wpa_supplicant *wpa_s)
761 {
762 	struct wpa_ssid *ssid;
763 
764 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
765 		if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !ssid->disabled)
766 			return 1;
767 	}
768 
769 	return 0;
770 }
771