Line data Source code
1 : /*
2 : * hostapd / WPS integration
3 : * Copyright (c) 2008-2012, 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 "utils/includes.h"
10 :
11 : #include "utils/common.h"
12 : #include "utils/eloop.h"
13 : #include "utils/uuid.h"
14 : #include "common/wpa_ctrl.h"
15 : #include "common/ieee802_11_defs.h"
16 : #include "common/ieee802_11_common.h"
17 : #include "eapol_auth/eapol_auth_sm.h"
18 : #include "eapol_auth/eapol_auth_sm_i.h"
19 : #include "wps/wps.h"
20 : #include "wps/wps_defs.h"
21 : #include "wps/wps_dev_attr.h"
22 : #include "wps/wps_attr_parse.h"
23 : #include "hostapd.h"
24 : #include "ap_config.h"
25 : #include "ap_drv_ops.h"
26 : #include "beacon.h"
27 : #include "sta_info.h"
28 : #include "wps_hostapd.h"
29 :
30 :
31 : #ifdef CONFIG_WPS_UPNP
32 : #include "wps/wps_upnp.h"
33 : static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
34 : struct wps_context *wps);
35 : static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd);
36 : #endif /* CONFIG_WPS_UPNP */
37 :
38 : static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
39 : const u8 *bssid,
40 : const u8 *ie, size_t ie_len,
41 : int ssi_signal);
42 : static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
43 : static void hostapd_wps_nfc_clear(struct wps_context *wps);
44 :
45 :
46 : struct wps_for_each_data {
47 : int (*func)(struct hostapd_data *h, void *ctx);
48 : void *ctx;
49 : struct hostapd_data *calling_hapd;
50 : };
51 :
52 :
53 521 : static int wps_for_each(struct hostapd_iface *iface, void *ctx)
54 : {
55 521 : struct wps_for_each_data *data = ctx;
56 : size_t j;
57 :
58 521 : if (iface == NULL)
59 0 : return 0;
60 1035 : for (j = 0; j < iface->num_bss; j++) {
61 521 : struct hostapd_data *hapd = iface->bss[j];
62 : int ret;
63 :
64 535 : if (hapd != data->calling_hapd &&
65 26 : (hapd->conf->wps_independent ||
66 12 : data->calling_hapd->conf->wps_independent))
67 2 : continue;
68 :
69 519 : ret = data->func(hapd, data->ctx);
70 519 : if (ret)
71 7 : return ret;
72 : }
73 :
74 514 : return 0;
75 : }
76 :
77 :
78 507 : static int hostapd_wps_for_each(struct hostapd_data *hapd,
79 : int (*func)(struct hostapd_data *h, void *ctx),
80 : void *ctx)
81 : {
82 507 : struct hostapd_iface *iface = hapd->iface;
83 : struct wps_for_each_data data;
84 507 : data.func = func;
85 507 : data.ctx = ctx;
86 507 : data.calling_hapd = hapd;
87 677 : if (iface->interfaces == NULL ||
88 170 : iface->interfaces->for_each_interface == NULL)
89 337 : return wps_for_each(iface, &data);
90 170 : return iface->interfaces->for_each_interface(iface->interfaces,
91 : wps_for_each, &data);
92 : }
93 :
94 :
95 15 : static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr,
96 : const u8 *p2p_dev_addr, const u8 *psk,
97 : size_t psk_len)
98 : {
99 15 : struct hostapd_data *hapd = ctx;
100 : struct hostapd_wpa_psk *p;
101 15 : struct hostapd_ssid *ssid = &hapd->conf->ssid;
102 :
103 15 : if (is_zero_ether_addr(p2p_dev_addr)) {
104 48 : wpa_printf(MSG_DEBUG,
105 : "Received new WPA/WPA2-PSK from WPS for STA " MACSTR,
106 48 : MAC2STR(mac_addr));
107 : } else {
108 84 : wpa_printf(MSG_DEBUG,
109 : "Received new WPA/WPA2-PSK from WPS for STA " MACSTR
110 : " P2P Device Addr " MACSTR,
111 84 : MAC2STR(mac_addr), MAC2STR(p2p_dev_addr));
112 : }
113 15 : wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len);
114 :
115 15 : if (psk_len != PMK_LEN) {
116 0 : wpa_printf(MSG_DEBUG, "Unexpected PSK length %lu",
117 : (unsigned long) psk_len);
118 0 : return -1;
119 : }
120 :
121 : /* Add the new PSK to runtime PSK list */
122 15 : p = os_zalloc(sizeof(*p));
123 15 : if (p == NULL)
124 0 : return -1;
125 15 : os_memcpy(p->addr, mac_addr, ETH_ALEN);
126 15 : os_memcpy(p->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
127 15 : os_memcpy(p->psk, psk, PMK_LEN);
128 :
129 15 : if (hapd->new_psk_cb) {
130 8 : hapd->new_psk_cb(hapd->new_psk_cb_ctx, mac_addr, p2p_dev_addr,
131 : psk, psk_len);
132 : }
133 :
134 15 : p->next = ssid->wpa_psk;
135 15 : ssid->wpa_psk = p;
136 :
137 15 : if (ssid->wpa_psk_file) {
138 : FILE *f;
139 : char hex[PMK_LEN * 2 + 1];
140 : /* Add the new PSK to PSK list file */
141 7 : f = fopen(ssid->wpa_psk_file, "a");
142 7 : if (f == NULL) {
143 3 : wpa_printf(MSG_DEBUG, "Failed to add the PSK to "
144 : "'%s'", ssid->wpa_psk_file);
145 3 : return -1;
146 : }
147 :
148 4 : wpa_snprintf_hex(hex, sizeof(hex), psk, psk_len);
149 4 : fprintf(f, MACSTR " %s\n", MAC2STR(mac_addr), hex);
150 4 : fclose(f);
151 : }
152 :
153 12 : return 0;
154 : }
155 :
156 :
157 1091 : static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie,
158 : struct wpabuf *probe_resp_ie)
159 : {
160 1091 : struct hostapd_data *hapd = ctx;
161 1091 : wpabuf_free(hapd->wps_beacon_ie);
162 1091 : hapd->wps_beacon_ie = beacon_ie;
163 1091 : wpabuf_free(hapd->wps_probe_resp_ie);
164 1091 : hapd->wps_probe_resp_ie = probe_resp_ie;
165 1091 : if (hapd->beacon_set_done)
166 694 : ieee802_11_set_beacon(hapd);
167 1091 : return hostapd_set_ap_wps_ie(hapd);
168 : }
169 :
170 :
171 18 : static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
172 : const struct wps_device_data *dev)
173 : {
174 18 : struct hostapd_data *hapd = ctx;
175 : char uuid[40], txt[400];
176 : int len;
177 : char devtype[WPS_DEV_TYPE_BUFSIZE];
178 18 : if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
179 0 : return;
180 18 : wpa_printf(MSG_DEBUG, "WPS: PIN needed for E-UUID %s", uuid);
181 126 : len = os_snprintf(txt, sizeof(txt), WPS_EVENT_PIN_NEEDED
182 : "%s " MACSTR " [%s|%s|%s|%s|%s|%s]",
183 108 : uuid, MAC2STR(dev->mac_addr), dev->device_name,
184 : dev->manufacturer, dev->model_name,
185 : dev->model_number, dev->serial_number,
186 18 : wps_dev_type_bin2str(dev->pri_dev_type, devtype,
187 : sizeof(devtype)));
188 18 : if (!os_snprintf_error(sizeof(txt), len))
189 18 : wpa_msg(hapd->msg_ctx, MSG_INFO, "%s", txt);
190 :
191 18 : if (hapd->conf->wps_pin_requests) {
192 : FILE *f;
193 : struct os_time t;
194 1 : f = fopen(hapd->conf->wps_pin_requests, "a");
195 1 : if (f == NULL)
196 0 : return;
197 1 : os_get_time(&t);
198 7 : fprintf(f, "%ld\t%s\t" MACSTR "\t%s\t%s\t%s\t%s\t%s"
199 : "\t%s\n",
200 6 : t.sec, uuid, MAC2STR(dev->mac_addr), dev->device_name,
201 : dev->manufacturer, dev->model_name, dev->model_number,
202 : dev->serial_number,
203 1 : wps_dev_type_bin2str(dev->pri_dev_type, devtype,
204 : sizeof(devtype)));
205 1 : fclose(f);
206 : }
207 : }
208 :
209 :
210 : struct wps_stop_reg_data {
211 : struct hostapd_data *current_hapd;
212 : const u8 *uuid_e;
213 : const u8 *dev_pw;
214 : size_t dev_pw_len;
215 : };
216 :
217 219 : static int wps_stop_registrar(struct hostapd_data *hapd, void *ctx)
218 : {
219 219 : struct wps_stop_reg_data *data = ctx;
220 219 : if (hapd != data->current_hapd && hapd->wps != NULL)
221 3 : wps_registrar_complete(hapd->wps->registrar, data->uuid_e,
222 : data->dev_pw, data->dev_pw_len);
223 219 : return 0;
224 : }
225 :
226 :
227 214 : static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
228 : const u8 *uuid_e, const u8 *dev_pw,
229 : size_t dev_pw_len)
230 : {
231 214 : struct hostapd_data *hapd = ctx;
232 : char uuid[40];
233 : struct wps_stop_reg_data data;
234 214 : if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
235 214 : return;
236 1284 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s",
237 1284 : MAC2STR(mac_addr), uuid);
238 214 : if (hapd->wps_reg_success_cb)
239 168 : hapd->wps_reg_success_cb(hapd->wps_reg_success_cb_ctx,
240 : mac_addr, uuid_e);
241 214 : data.current_hapd = hapd;
242 214 : data.uuid_e = uuid_e;
243 214 : data.dev_pw = dev_pw;
244 214 : data.dev_pw_len = dev_pw_len;
245 214 : hostapd_wps_for_each(hapd, wps_stop_registrar, &data);
246 : }
247 :
248 :
249 511 : static void hostapd_wps_enrollee_seen_cb(void *ctx, const u8 *addr,
250 : const u8 *uuid_e,
251 : const u8 *pri_dev_type,
252 : u16 config_methods,
253 : u16 dev_password_id, u8 request_type,
254 : const char *dev_name)
255 : {
256 511 : struct hostapd_data *hapd = ctx;
257 : char uuid[40];
258 : char devtype[WPS_DEV_TYPE_BUFSIZE];
259 511 : if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
260 511 : return;
261 511 : if (dev_name == NULL)
262 0 : dev_name = "";
263 3577 : wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ENROLLEE_SEEN MACSTR
264 : " %s %s 0x%x %u %u [%s]",
265 3066 : MAC2STR(addr), uuid,
266 : wps_dev_type_bin2str(pri_dev_type, devtype,
267 : sizeof(devtype)),
268 : config_methods, dev_password_id, request_type, dev_name);
269 : }
270 :
271 :
272 91 : static int str_starts(const char *str, const char *start)
273 : {
274 91 : return os_strncmp(str, start, os_strlen(start)) == 0;
275 : }
276 :
277 :
278 17 : static void wps_reload_config(void *eloop_data, void *user_ctx)
279 : {
280 17 : struct hostapd_iface *iface = eloop_data;
281 :
282 17 : wpa_printf(MSG_DEBUG, "WPS: Reload configuration data");
283 34 : if (iface->interfaces == NULL ||
284 17 : iface->interfaces->reload_config(iface) < 0) {
285 0 : wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated "
286 : "configuration");
287 : }
288 17 : }
289 :
290 :
291 393 : void hostapd_wps_eap_completed(struct hostapd_data *hapd)
292 : {
293 : /*
294 : * Reduce race condition of the station trying to reconnect immediately
295 : * after AP reconfiguration through WPS by rescheduling the reload
296 : * timeout to happen after EAP completion rather than the originally
297 : * scheduled 100 ms after new configuration became known.
298 : */
299 393 : if (eloop_deplete_timeout(0, 0, wps_reload_config, hapd->iface, NULL) ==
300 : 1)
301 12 : wpa_printf(MSG_DEBUG, "WPS: Reschedule immediate configuration reload");
302 393 : }
303 :
304 :
305 1 : static void hapd_new_ap_event(struct hostapd_data *hapd, const u8 *attr,
306 : size_t attr_len)
307 : {
308 1 : size_t blen = attr_len * 2 + 1;
309 1 : char *buf = os_malloc(blen);
310 1 : if (buf) {
311 1 : wpa_snprintf_hex(buf, blen, attr, attr_len);
312 1 : wpa_msg(hapd->msg_ctx, MSG_INFO,
313 : WPS_EVENT_NEW_AP_SETTINGS "%s", buf);
314 1 : os_free(buf);
315 : }
316 1 : }
317 :
318 :
319 16 : static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd,
320 : const struct wps_credential *cred)
321 : {
322 16 : struct hostapd_bss_config *bss = hapd->conf;
323 :
324 16 : wpa_printf(MSG_DEBUG, "WPS: Updating in-memory configuration");
325 :
326 16 : bss->wps_state = 2;
327 16 : if (cred->ssid_len <= HOSTAPD_MAX_SSID_LEN) {
328 16 : os_memcpy(bss->ssid.ssid, cred->ssid, cred->ssid_len);
329 16 : bss->ssid.ssid_len = cred->ssid_len;
330 16 : bss->ssid.ssid_set = 1;
331 : }
332 :
333 31 : if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
334 15 : (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
335 9 : bss->wpa = 3;
336 7 : else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK))
337 6 : bss->wpa = 2;
338 1 : else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))
339 0 : bss->wpa = 1;
340 : else
341 1 : bss->wpa = 0;
342 :
343 16 : if (bss->wpa) {
344 15 : if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA))
345 0 : bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
346 15 : if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK))
347 15 : bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
348 :
349 15 : bss->wpa_pairwise = 0;
350 15 : if (cred->encr_type & WPS_ENCR_AES)
351 15 : bss->wpa_pairwise |= WPA_CIPHER_CCMP;
352 15 : if (cred->encr_type & WPS_ENCR_TKIP)
353 9 : bss->wpa_pairwise |= WPA_CIPHER_TKIP;
354 15 : bss->rsn_pairwise = bss->wpa_pairwise;
355 15 : bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa,
356 : bss->wpa_pairwise,
357 : bss->rsn_pairwise);
358 :
359 15 : if (cred->key_len >= 8 && cred->key_len < 64) {
360 15 : os_free(bss->ssid.wpa_passphrase);
361 15 : bss->ssid.wpa_passphrase = os_zalloc(cred->key_len + 1);
362 15 : if (bss->ssid.wpa_passphrase)
363 15 : os_memcpy(bss->ssid.wpa_passphrase, cred->key,
364 : cred->key_len);
365 15 : hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
366 0 : } else if (cred->key_len == 64) {
367 0 : hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
368 0 : bss->ssid.wpa_psk =
369 0 : os_zalloc(sizeof(struct hostapd_wpa_psk));
370 0 : if (bss->ssid.wpa_psk &&
371 0 : hexstr2bin((const char *) cred->key,
372 0 : bss->ssid.wpa_psk->psk, PMK_LEN) == 0) {
373 0 : bss->ssid.wpa_psk->group = 1;
374 0 : os_free(bss->ssid.wpa_passphrase);
375 0 : bss->ssid.wpa_passphrase = NULL;
376 : }
377 : }
378 15 : bss->auth_algs = 1;
379 : } else {
380 : /*
381 : * WPS 2.0 does not allow WEP to be configured, so no need to
382 : * process that option here either.
383 : */
384 1 : bss->auth_algs = 1;
385 : }
386 :
387 : /* Schedule configuration reload after short period of time to allow
388 : * EAP-WSC to be finished.
389 : */
390 16 : eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface,
391 : NULL);
392 :
393 16 : return 0;
394 : }
395 :
396 :
397 18 : static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
398 : {
399 18 : const struct wps_credential *cred = ctx;
400 : FILE *oconf, *nconf;
401 : size_t len, i;
402 : char *tmp_fname;
403 : char buf[1024];
404 : int multi_bss;
405 : int wpa;
406 :
407 18 : if (hapd->wps == NULL)
408 0 : return 0;
409 :
410 36 : wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
411 18 : cred->cred_attr, cred->cred_attr_len);
412 :
413 18 : wpa_printf(MSG_DEBUG, "WPS: Received new AP Settings");
414 18 : wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len);
415 18 : wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x",
416 18 : cred->auth_type);
417 18 : wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type);
418 18 : wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx);
419 36 : wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key",
420 18 : cred->key, cred->key_len);
421 108 : wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR,
422 108 : MAC2STR(cred->mac_addr));
423 :
424 35 : if ((hapd->conf->wps_cred_processing == 1 ||
425 18 : hapd->conf->wps_cred_processing == 2) && cred->cred_attr) {
426 1 : hapd_new_ap_event(hapd, cred->cred_attr, cred->cred_attr_len);
427 34 : } else if (hapd->conf->wps_cred_processing == 1 ||
428 17 : hapd->conf->wps_cred_processing == 2) {
429 : struct wpabuf *attr;
430 0 : attr = wpabuf_alloc(200);
431 0 : if (attr && wps_build_credential_wrap(attr, cred) == 0)
432 0 : hapd_new_ap_event(hapd, wpabuf_head_u8(attr),
433 : wpabuf_len(attr));
434 0 : wpabuf_free(attr);
435 : } else
436 17 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS);
437 :
438 18 : if (hapd->conf->wps_cred_processing == 1)
439 1 : return 0;
440 :
441 17 : os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len);
442 17 : hapd->wps->ssid_len = cred->ssid_len;
443 17 : hapd->wps->encr_types = cred->encr_type;
444 17 : hapd->wps->auth_types = cred->auth_type;
445 17 : hapd->wps->ap_encr_type = cred->encr_type;
446 17 : hapd->wps->ap_auth_type = cred->auth_type;
447 17 : if (cred->key_len == 0) {
448 1 : os_free(hapd->wps->network_key);
449 1 : hapd->wps->network_key = NULL;
450 1 : hapd->wps->network_key_len = 0;
451 : } else {
452 17 : if (hapd->wps->network_key == NULL ||
453 1 : hapd->wps->network_key_len < cred->key_len) {
454 16 : hapd->wps->network_key_len = 0;
455 16 : os_free(hapd->wps->network_key);
456 16 : hapd->wps->network_key = os_malloc(cred->key_len);
457 16 : if (hapd->wps->network_key == NULL)
458 0 : return -1;
459 : }
460 16 : hapd->wps->network_key_len = cred->key_len;
461 16 : os_memcpy(hapd->wps->network_key, cred->key, cred->key_len);
462 : }
463 17 : hapd->wps->wps_state = WPS_STATE_CONFIGURED;
464 :
465 17 : if (hapd->iface->config_fname == NULL)
466 16 : return hapd_wps_reconfig_in_memory(hapd, cred);
467 1 : len = os_strlen(hapd->iface->config_fname) + 5;
468 1 : tmp_fname = os_malloc(len);
469 1 : if (tmp_fname == NULL)
470 0 : return -1;
471 1 : os_snprintf(tmp_fname, len, "%s-new", hapd->iface->config_fname);
472 :
473 1 : oconf = fopen(hapd->iface->config_fname, "r");
474 1 : if (oconf == NULL) {
475 0 : wpa_printf(MSG_WARNING, "WPS: Could not open current "
476 : "configuration file");
477 0 : os_free(tmp_fname);
478 0 : return -1;
479 : }
480 :
481 1 : nconf = fopen(tmp_fname, "w");
482 1 : if (nconf == NULL) {
483 0 : wpa_printf(MSG_WARNING, "WPS: Could not write updated "
484 : "configuration file");
485 0 : os_free(tmp_fname);
486 0 : fclose(oconf);
487 0 : return -1;
488 : }
489 :
490 1 : fprintf(nconf, "# WPS configuration - START\n");
491 :
492 1 : fprintf(nconf, "wps_state=2\n");
493 :
494 1 : if (is_hex(cred->ssid, cred->ssid_len)) {
495 0 : fprintf(nconf, "ssid2=");
496 0 : for (i = 0; i < cred->ssid_len; i++)
497 0 : fprintf(nconf, "%02x", cred->ssid[i]);
498 0 : fprintf(nconf, "\n");
499 : } else {
500 1 : fprintf(nconf, "ssid=");
501 4 : for (i = 0; i < cred->ssid_len; i++)
502 3 : fputc(cred->ssid[i], nconf);
503 1 : fprintf(nconf, "\n");
504 : }
505 :
506 2 : if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
507 1 : (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
508 1 : wpa = 3;
509 0 : else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK))
510 0 : wpa = 2;
511 0 : else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))
512 0 : wpa = 1;
513 : else
514 0 : wpa = 0;
515 :
516 1 : if (wpa) {
517 : char *prefix;
518 1 : fprintf(nconf, "wpa=%d\n", wpa);
519 :
520 1 : fprintf(nconf, "wpa_key_mgmt=");
521 1 : prefix = "";
522 1 : if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) {
523 0 : fprintf(nconf, "WPA-EAP");
524 0 : prefix = " ";
525 : }
526 1 : if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK))
527 1 : fprintf(nconf, "%sWPA-PSK", prefix);
528 1 : fprintf(nconf, "\n");
529 :
530 1 : fprintf(nconf, "wpa_pairwise=");
531 1 : prefix = "";
532 1 : if (cred->encr_type & WPS_ENCR_AES) {
533 1 : fprintf(nconf, "CCMP");
534 1 : prefix = " ";
535 : }
536 1 : if (cred->encr_type & WPS_ENCR_TKIP) {
537 1 : fprintf(nconf, "%sTKIP", prefix);
538 : }
539 1 : fprintf(nconf, "\n");
540 :
541 1 : if (cred->key_len >= 8 && cred->key_len < 64) {
542 1 : fprintf(nconf, "wpa_passphrase=");
543 23 : for (i = 0; i < cred->key_len; i++)
544 22 : fputc(cred->key[i], nconf);
545 1 : fprintf(nconf, "\n");
546 0 : } else if (cred->key_len == 64) {
547 0 : fprintf(nconf, "wpa_psk=");
548 0 : for (i = 0; i < cred->key_len; i++)
549 0 : fputc(cred->key[i], nconf);
550 0 : fprintf(nconf, "\n");
551 : } else {
552 0 : wpa_printf(MSG_WARNING, "WPS: Invalid key length %lu "
553 : "for WPA/WPA2",
554 : (unsigned long) cred->key_len);
555 : }
556 :
557 1 : fprintf(nconf, "auth_algs=1\n");
558 : } else {
559 : /*
560 : * WPS 2.0 does not allow WEP to be configured, so no need to
561 : * process that option here either.
562 : */
563 0 : fprintf(nconf, "auth_algs=1\n");
564 : }
565 :
566 1 : fprintf(nconf, "# WPS configuration - END\n");
567 :
568 1 : multi_bss = 0;
569 11 : while (fgets(buf, sizeof(buf), oconf)) {
570 9 : if (os_strncmp(buf, "bss=", 4) == 0)
571 0 : multi_bss = 1;
572 18 : if (!multi_bss &&
573 17 : (str_starts(buf, "ssid=") ||
574 16 : str_starts(buf, "ssid2=") ||
575 16 : str_starts(buf, "auth_algs=") ||
576 16 : str_starts(buf, "wep_default_key=") ||
577 16 : str_starts(buf, "wep_key") ||
578 15 : str_starts(buf, "wps_state=") ||
579 14 : str_starts(buf, "wpa=") ||
580 14 : str_starts(buf, "wpa_psk=") ||
581 14 : str_starts(buf, "wpa_pairwise=") ||
582 14 : str_starts(buf, "rsn_pairwise=") ||
583 14 : str_starts(buf, "wpa_key_mgmt=") ||
584 7 : str_starts(buf, "wpa_passphrase="))) {
585 2 : fprintf(nconf, "#WPS# %s", buf);
586 : } else
587 7 : fprintf(nconf, "%s", buf);
588 : }
589 :
590 1 : fclose(nconf);
591 1 : fclose(oconf);
592 :
593 1 : if (rename(tmp_fname, hapd->iface->config_fname) < 0) {
594 0 : wpa_printf(MSG_WARNING, "WPS: Failed to rename the updated "
595 0 : "configuration file: %s", strerror(errno));
596 0 : os_free(tmp_fname);
597 0 : return -1;
598 : }
599 :
600 1 : os_free(tmp_fname);
601 :
602 : /* Schedule configuration reload after short period of time to allow
603 : * EAP-WSC to be finished.
604 : */
605 1 : eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface,
606 : NULL);
607 :
608 1 : wpa_printf(MSG_DEBUG, "WPS: AP configuration updated");
609 :
610 1 : return 0;
611 : }
612 :
613 :
614 16 : static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
615 : {
616 16 : struct hostapd_data *hapd = ctx;
617 16 : return hostapd_wps_for_each(hapd, hapd_wps_cred_cb, (void *) cred);
618 : }
619 :
620 :
621 1 : static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
622 : {
623 1 : struct hostapd_data *hapd = eloop_data;
624 :
625 1 : if (hapd->conf->ap_setup_locked)
626 0 : return;
627 1 : if (hapd->ap_pin_failures_consecutive >= 10)
628 0 : return;
629 :
630 1 : wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN");
631 1 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
632 1 : hapd->wps->ap_setup_locked = 0;
633 1 : wps_registrar_update_ie(hapd->wps->registrar);
634 : }
635 :
636 :
637 9 : static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx)
638 : {
639 9 : struct wps_event_pwd_auth_fail *data = ctx;
640 :
641 9 : if (!data->enrollee || hapd->conf->ap_pin == NULL || hapd->wps == NULL)
642 0 : return 0;
643 :
644 : /*
645 : * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
646 : * for some time if this happens multiple times to slow down brute
647 : * force attacks.
648 : */
649 9 : hapd->ap_pin_failures++;
650 9 : hapd->ap_pin_failures_consecutive++;
651 9 : wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u "
652 : "(%u consecutive)",
653 : hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
654 9 : if (hapd->ap_pin_failures < 3)
655 6 : return 0;
656 :
657 3 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
658 3 : hapd->wps->ap_setup_locked = 1;
659 :
660 3 : wps_registrar_update_ie(hapd->wps->registrar);
661 :
662 5 : if (!hapd->conf->ap_setup_locked &&
663 2 : hapd->ap_pin_failures_consecutive >= 10) {
664 : /*
665 : * In indefinite lockdown - disable automatic AP PIN
666 : * reenablement.
667 : */
668 0 : eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
669 0 : wpa_printf(MSG_DEBUG, "WPS: AP PIN disabled indefinitely");
670 3 : } else if (!hapd->conf->ap_setup_locked) {
671 2 : if (hapd->ap_pin_lockout_time == 0)
672 2 : hapd->ap_pin_lockout_time = 60;
673 0 : else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 &&
674 0 : (hapd->ap_pin_failures % 3) == 0)
675 0 : hapd->ap_pin_lockout_time *= 2;
676 :
677 2 : wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN for %u seconds",
678 : hapd->ap_pin_lockout_time);
679 2 : eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
680 2 : eloop_register_timeout(hapd->ap_pin_lockout_time, 0,
681 : hostapd_wps_reenable_ap_pin, hapd,
682 : NULL);
683 : }
684 :
685 3 : return 0;
686 : }
687 :
688 :
689 9 : static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
690 : struct wps_event_pwd_auth_fail *data)
691 : {
692 : /* Update WPS Status - Authentication Failure */
693 9 : wpa_printf(MSG_DEBUG, "WPS: Authentication failure update");
694 9 : hapd->wps_stats.status = WPS_STATUS_FAILURE;
695 9 : hapd->wps_stats.failure_reason = WPS_EI_AUTH_FAILURE;
696 9 : os_memcpy(hapd->wps_stats.peer_addr, data->peer_macaddr, ETH_ALEN);
697 :
698 9 : hostapd_wps_for_each(hapd, wps_pwd_auth_fail, data);
699 9 : }
700 :
701 :
702 28 : static int wps_ap_pin_success(struct hostapd_data *hapd, void *ctx)
703 : {
704 28 : if (hapd->conf->ap_pin == NULL || hapd->wps == NULL)
705 1 : return 0;
706 :
707 27 : if (hapd->ap_pin_failures_consecutive == 0)
708 27 : return 0;
709 :
710 0 : wpa_printf(MSG_DEBUG, "WPS: Clear consecutive AP PIN failure counter "
711 : "- total validation failures %u (%u consecutive)",
712 : hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
713 0 : hapd->ap_pin_failures_consecutive = 0;
714 :
715 0 : return 0;
716 : }
717 :
718 :
719 28 : static void hostapd_wps_ap_pin_success(struct hostapd_data *hapd)
720 : {
721 28 : hostapd_wps_for_each(hapd, wps_ap_pin_success, NULL);
722 28 : }
723 :
724 :
725 12 : static void hostapd_wps_event_pbc_overlap(struct hostapd_data *hapd)
726 : {
727 : /* Update WPS Status - PBC Overlap */
728 12 : hapd->wps_stats.pbc_status = WPS_PBC_STATUS_OVERLAP;
729 12 : }
730 :
731 :
732 4 : static void hostapd_wps_event_pbc_timeout(struct hostapd_data *hapd)
733 : {
734 : /* Update WPS PBC Status:PBC Timeout */
735 4 : hapd->wps_stats.pbc_status = WPS_PBC_STATUS_TIMEOUT;
736 4 : }
737 :
738 :
739 63 : static void hostapd_wps_event_pbc_active(struct hostapd_data *hapd)
740 : {
741 : /* Update WPS PBC status - Active */
742 63 : hapd->wps_stats.pbc_status = WPS_PBC_STATUS_ACTIVE;
743 63 : }
744 :
745 :
746 50 : static void hostapd_wps_event_pbc_disable(struct hostapd_data *hapd)
747 : {
748 : /* Update WPS PBC status - Active */
749 50 : hapd->wps_stats.pbc_status = WPS_PBC_STATUS_DISABLE;
750 50 : }
751 :
752 :
753 220 : static void hostapd_wps_event_success(struct hostapd_data *hapd,
754 : struct wps_event_success *success)
755 : {
756 : /* Update WPS status - Success */
757 220 : hapd->wps_stats.pbc_status = WPS_PBC_STATUS_DISABLE;
758 220 : hapd->wps_stats.status = WPS_STATUS_SUCCESS;
759 220 : os_memcpy(hapd->wps_stats.peer_addr, success->peer_macaddr, ETH_ALEN);
760 220 : }
761 :
762 :
763 42 : static void hostapd_wps_event_fail(struct hostapd_data *hapd,
764 : struct wps_event_fail *fail)
765 : {
766 : /* Update WPS status - Failure */
767 42 : hapd->wps_stats.status = WPS_STATUS_FAILURE;
768 42 : os_memcpy(hapd->wps_stats.peer_addr, fail->peer_macaddr, ETH_ALEN);
769 :
770 42 : hapd->wps_stats.failure_reason = fail->error_indication;
771 :
772 43 : if (fail->error_indication > 0 &&
773 1 : fail->error_indication < NUM_WPS_EI_VALUES) {
774 3 : wpa_msg(hapd->msg_ctx, MSG_INFO,
775 : WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
776 2 : fail->msg, fail->config_error, fail->error_indication,
777 1 : wps_ei_str(fail->error_indication));
778 : } else {
779 41 : wpa_msg(hapd->msg_ctx, MSG_INFO,
780 : WPS_EVENT_FAIL "msg=%d config_error=%d",
781 41 : fail->msg, fail->config_error);
782 : }
783 42 : }
784 :
785 :
786 428 : static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
787 : union wps_event_data *data)
788 : {
789 428 : struct hostapd_data *hapd = ctx;
790 :
791 428 : switch (event) {
792 : case WPS_EV_M2D:
793 0 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_M2D);
794 0 : break;
795 : case WPS_EV_FAIL:
796 42 : hostapd_wps_event_fail(hapd, &data->fail);
797 42 : break;
798 : case WPS_EV_SUCCESS:
799 220 : hostapd_wps_event_success(hapd, &data->success);
800 220 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_SUCCESS);
801 220 : break;
802 : case WPS_EV_PWD_AUTH_FAIL:
803 9 : hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail);
804 9 : break;
805 : case WPS_EV_PBC_OVERLAP:
806 12 : hostapd_wps_event_pbc_overlap(hapd);
807 12 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_OVERLAP);
808 12 : break;
809 : case WPS_EV_PBC_TIMEOUT:
810 4 : hostapd_wps_event_pbc_timeout(hapd);
811 4 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_TIMEOUT);
812 4 : break;
813 : case WPS_EV_PBC_ACTIVE:
814 63 : hostapd_wps_event_pbc_active(hapd);
815 63 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ACTIVE);
816 63 : break;
817 : case WPS_EV_PBC_DISABLE:
818 50 : hostapd_wps_event_pbc_disable(hapd);
819 50 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_DISABLE);
820 50 : break;
821 : case WPS_EV_ER_AP_ADD:
822 0 : break;
823 : case WPS_EV_ER_AP_REMOVE:
824 0 : break;
825 : case WPS_EV_ER_ENROLLEE_ADD:
826 0 : break;
827 : case WPS_EV_ER_ENROLLEE_REMOVE:
828 0 : break;
829 : case WPS_EV_ER_AP_SETTINGS:
830 0 : break;
831 : case WPS_EV_ER_SET_SELECTED_REGISTRAR:
832 0 : break;
833 : case WPS_EV_AP_PIN_SUCCESS:
834 28 : hostapd_wps_ap_pin_success(hapd);
835 28 : break;
836 : }
837 428 : if (hapd->wps_event_cb)
838 245 : hapd->wps_event_cb(hapd->wps_event_cb_ctx, event, data);
839 428 : }
840 :
841 :
842 306 : static int hostapd_wps_rf_band_cb(void *ctx)
843 : {
844 306 : struct hostapd_data *hapd = ctx;
845 :
846 612 : return hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
847 306 : WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
848 : }
849 :
850 :
851 2375 : static void hostapd_wps_clear_ies(struct hostapd_data *hapd, int deinit_only)
852 : {
853 2375 : wpabuf_free(hapd->wps_beacon_ie);
854 2375 : hapd->wps_beacon_ie = NULL;
855 :
856 2375 : wpabuf_free(hapd->wps_probe_resp_ie);
857 2375 : hapd->wps_probe_resp_ie = NULL;
858 :
859 2375 : if (deinit_only)
860 3763 : return;
861 :
862 987 : hostapd_set_ap_wps_ie(hapd);
863 : }
864 :
865 :
866 72 : static int get_uuid_cb(struct hostapd_iface *iface, void *ctx)
867 : {
868 72 : const u8 **uuid = ctx;
869 : size_t j;
870 :
871 72 : if (iface == NULL)
872 0 : return 0;
873 141 : for (j = 0; j < iface->num_bss; j++) {
874 72 : struct hostapd_data *hapd = iface->bss[j];
875 75 : if (hapd->wps && !hapd->conf->wps_independent &&
876 3 : !is_nil_uuid(hapd->wps->uuid)) {
877 3 : *uuid = hapd->wps->uuid;
878 3 : return 1;
879 : }
880 : }
881 :
882 69 : return 0;
883 : }
884 :
885 :
886 71 : static const u8 * get_own_uuid(struct hostapd_iface *iface)
887 : {
888 : const u8 *uuid;
889 142 : if (iface->interfaces == NULL ||
890 71 : iface->interfaces->for_each_interface == NULL)
891 0 : return NULL;
892 71 : uuid = NULL;
893 71 : iface->interfaces->for_each_interface(iface->interfaces, get_uuid_cb,
894 : &uuid);
895 71 : return uuid;
896 : }
897 :
898 :
899 91 : static int count_interface_cb(struct hostapd_iface *iface, void *ctx)
900 : {
901 91 : int *count= ctx;
902 91 : (*count)++;
903 91 : return 0;
904 : }
905 :
906 :
907 397 : static int interface_count(struct hostapd_iface *iface)
908 : {
909 397 : int count = 0;
910 484 : if (iface->interfaces == NULL ||
911 87 : iface->interfaces->for_each_interface == NULL)
912 310 : return 0;
913 87 : iface->interfaces->for_each_interface(iface->interfaces,
914 : count_interface_cb, &count);
915 87 : return count;
916 : }
917 :
918 :
919 416 : static int hostapd_wps_set_vendor_ext(struct hostapd_data *hapd,
920 : struct wps_context *wps)
921 : {
922 : int i;
923 :
924 4576 : for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
925 4160 : wpabuf_free(wps->dev.vendor_ext[i]);
926 4160 : wps->dev.vendor_ext[i] = NULL;
927 :
928 4160 : if (hapd->conf->wps_vendor_ext[i] == NULL)
929 4157 : continue;
930 :
931 3 : wps->dev.vendor_ext[i] =
932 3 : wpabuf_dup(hapd->conf->wps_vendor_ext[i]);
933 3 : if (wps->dev.vendor_ext[i] == NULL) {
934 0 : while (--i >= 0)
935 0 : wpabuf_free(wps->dev.vendor_ext[i]);
936 0 : return -1;
937 : }
938 : }
939 :
940 416 : return 0;
941 : }
942 :
943 :
944 397 : static void hostapd_free_wps(struct wps_context *wps)
945 : {
946 : int i;
947 :
948 4367 : for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
949 3970 : wpabuf_free(wps->dev.vendor_ext[i]);
950 397 : wps_device_data_free(&wps->dev);
951 397 : os_free(wps->network_key);
952 397 : hostapd_wps_nfc_clear(wps);
953 397 : wpabuf_free(wps->dh_pubkey);
954 397 : wpabuf_free(wps->dh_privkey);
955 397 : os_free(wps);
956 397 : }
957 :
958 :
959 1384 : int hostapd_init_wps(struct hostapd_data *hapd,
960 : struct hostapd_bss_config *conf)
961 : {
962 : struct wps_context *wps;
963 : struct wps_registrar_config cfg;
964 :
965 1384 : if (conf->wps_state == 0) {
966 987 : hostapd_wps_clear_ies(hapd, 0);
967 987 : return 0;
968 : }
969 :
970 397 : wps = os_zalloc(sizeof(*wps));
971 397 : if (wps == NULL)
972 0 : return -1;
973 :
974 397 : wps->cred_cb = hostapd_wps_cred_cb;
975 397 : wps->event_cb = hostapd_wps_event_cb;
976 397 : wps->rf_band_cb = hostapd_wps_rf_band_cb;
977 397 : wps->cb_ctx = hapd;
978 :
979 397 : os_memset(&cfg, 0, sizeof(cfg));
980 397 : wps->wps_state = hapd->conf->wps_state;
981 397 : wps->ap_setup_locked = hapd->conf->ap_setup_locked;
982 397 : if (is_nil_uuid(hapd->conf->uuid)) {
983 : const u8 *uuid;
984 71 : uuid = get_own_uuid(hapd->iface);
985 71 : if (uuid && !conf->wps_independent) {
986 3 : os_memcpy(wps->uuid, uuid, UUID_LEN);
987 3 : wpa_hexdump(MSG_DEBUG, "WPS: Clone UUID from another "
988 3 : "interface", wps->uuid, UUID_LEN);
989 : } else {
990 68 : uuid_gen_mac_addr(hapd->own_addr, wps->uuid);
991 68 : wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC "
992 68 : "address", wps->uuid, UUID_LEN);
993 : }
994 : } else {
995 326 : os_memcpy(wps->uuid, hapd->conf->uuid, UUID_LEN);
996 326 : wpa_hexdump(MSG_DEBUG, "WPS: Use configured UUID",
997 326 : wps->uuid, UUID_LEN);
998 : }
999 397 : wps->ssid_len = hapd->conf->ssid.ssid_len;
1000 397 : os_memcpy(wps->ssid, hapd->conf->ssid.ssid, wps->ssid_len);
1001 397 : wps->ap = 1;
1002 397 : os_memcpy(wps->dev.mac_addr, hapd->own_addr, ETH_ALEN);
1003 794 : wps->dev.device_name = hapd->conf->device_name ?
1004 397 : os_strdup(hapd->conf->device_name) : NULL;
1005 794 : wps->dev.manufacturer = hapd->conf->manufacturer ?
1006 397 : os_strdup(hapd->conf->manufacturer) : NULL;
1007 794 : wps->dev.model_name = hapd->conf->model_name ?
1008 397 : os_strdup(hapd->conf->model_name) : NULL;
1009 794 : wps->dev.model_number = hapd->conf->model_number ?
1010 397 : os_strdup(hapd->conf->model_number) : NULL;
1011 794 : wps->dev.serial_number = hapd->conf->serial_number ?
1012 397 : os_strdup(hapd->conf->serial_number) : NULL;
1013 397 : wps->config_methods =
1014 397 : wps_config_methods_str2bin(hapd->conf->config_methods);
1015 397 : if ((wps->config_methods &
1016 : (WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY |
1017 : WPS_CONFIG_PHY_DISPLAY)) == WPS_CONFIG_DISPLAY) {
1018 0 : wpa_printf(MSG_INFO, "WPS: Converting display to "
1019 : "virtual_display for WPS 2.0 compliance");
1020 0 : wps->config_methods |= WPS_CONFIG_VIRT_DISPLAY;
1021 : }
1022 397 : if ((wps->config_methods &
1023 : (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON |
1024 : WPS_CONFIG_PHY_PUSHBUTTON)) == WPS_CONFIG_PUSHBUTTON) {
1025 16 : wpa_printf(MSG_INFO, "WPS: Converting push_button to "
1026 : "virtual_push_button for WPS 2.0 compliance");
1027 16 : wps->config_methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
1028 : }
1029 397 : os_memcpy(wps->dev.pri_dev_type, hapd->conf->device_type,
1030 : WPS_DEV_TYPE_LEN);
1031 :
1032 397 : if (hostapd_wps_set_vendor_ext(hapd, wps) < 0)
1033 0 : goto fail;
1034 :
1035 397 : wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version);
1036 :
1037 397 : if (conf->wps_rf_bands) {
1038 0 : wps->dev.rf_bands = conf->wps_rf_bands;
1039 : } else {
1040 397 : wps->dev.rf_bands =
1041 397 : hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
1042 : WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
1043 : }
1044 :
1045 397 : if (conf->wpa & WPA_PROTO_RSN) {
1046 367 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
1047 364 : wps->auth_types |= WPS_AUTH_WPA2PSK;
1048 367 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
1049 2 : wps->auth_types |= WPS_AUTH_WPA2;
1050 :
1051 367 : if (conf->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP))
1052 367 : wps->encr_types |= WPS_ENCR_AES;
1053 367 : if (conf->rsn_pairwise & WPA_CIPHER_TKIP)
1054 2 : wps->encr_types |= WPS_ENCR_TKIP;
1055 : }
1056 :
1057 397 : if (conf->wpa & WPA_PROTO_WPA) {
1058 4 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
1059 4 : wps->auth_types |= WPS_AUTH_WPAPSK;
1060 4 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
1061 2 : wps->auth_types |= WPS_AUTH_WPA;
1062 :
1063 4 : if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
1064 2 : wps->encr_types |= WPS_ENCR_AES;
1065 4 : if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
1066 4 : wps->encr_types |= WPS_ENCR_TKIP;
1067 : }
1068 :
1069 397 : if (conf->ssid.security_policy == SECURITY_PLAINTEXT) {
1070 30 : wps->encr_types |= WPS_ENCR_NONE;
1071 30 : wps->auth_types |= WPS_AUTH_OPEN;
1072 : }
1073 :
1074 397 : if (conf->ssid.wpa_psk_file) {
1075 : /* Use per-device PSKs */
1076 395 : } else if (conf->ssid.wpa_passphrase) {
1077 61 : wps->network_key = (u8 *) os_strdup(conf->ssid.wpa_passphrase);
1078 61 : wps->network_key_len = os_strlen(conf->ssid.wpa_passphrase);
1079 334 : } else if (conf->ssid.wpa_psk) {
1080 304 : wps->network_key = os_malloc(2 * PMK_LEN + 1);
1081 304 : if (wps->network_key == NULL)
1082 0 : goto fail;
1083 304 : wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1,
1084 304 : conf->ssid.wpa_psk->psk, PMK_LEN);
1085 304 : wps->network_key_len = 2 * PMK_LEN;
1086 30 : } else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) {
1087 0 : wps->network_key = os_malloc(conf->ssid.wep.len[0]);
1088 0 : if (wps->network_key == NULL)
1089 0 : goto fail;
1090 0 : os_memcpy(wps->network_key, conf->ssid.wep.key[0],
1091 : conf->ssid.wep.len[0]);
1092 0 : wps->network_key_len = conf->ssid.wep.len[0];
1093 : }
1094 :
1095 397 : if (conf->ssid.wpa_psk) {
1096 365 : os_memcpy(wps->psk, conf->ssid.wpa_psk->psk, PMK_LEN);
1097 365 : wps->psk_set = 1;
1098 : }
1099 :
1100 397 : wps->ap_auth_type = wps->auth_types;
1101 397 : wps->ap_encr_type = wps->encr_types;
1102 397 : if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) {
1103 : /* Override parameters to enable security by default */
1104 18 : wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
1105 18 : wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
1106 : }
1107 :
1108 397 : wps->ap_settings = conf->ap_settings;
1109 397 : wps->ap_settings_len = conf->ap_settings_len;
1110 :
1111 397 : cfg.new_psk_cb = hostapd_wps_new_psk_cb;
1112 397 : cfg.set_ie_cb = hostapd_wps_set_ie_cb;
1113 397 : cfg.pin_needed_cb = hostapd_wps_pin_needed_cb;
1114 397 : cfg.reg_success_cb = hostapd_wps_reg_success_cb;
1115 397 : cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb;
1116 397 : cfg.cb_ctx = hapd;
1117 397 : cfg.skip_cred_build = conf->skip_cred_build;
1118 397 : cfg.extra_cred = conf->extra_cred;
1119 397 : cfg.extra_cred_len = conf->extra_cred_len;
1120 398 : cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) &&
1121 1 : conf->skip_cred_build;
1122 397 : if (conf->ssid.security_policy == SECURITY_STATIC_WEP)
1123 0 : cfg.static_wep_only = 1;
1124 397 : cfg.dualband = interface_count(hapd->iface) > 1;
1125 397 : if ((wps->dev.rf_bands & (WPS_RF_50GHZ | WPS_RF_24GHZ)) ==
1126 : (WPS_RF_50GHZ | WPS_RF_24GHZ))
1127 0 : cfg.dualband = 1;
1128 397 : if (cfg.dualband)
1129 4 : wpa_printf(MSG_DEBUG, "WPS: Dualband AP");
1130 397 : cfg.force_per_enrollee_psk = conf->force_per_enrollee_psk;
1131 :
1132 397 : wps->registrar = wps_registrar_init(wps, &cfg);
1133 397 : if (wps->registrar == NULL) {
1134 0 : wpa_printf(MSG_ERROR, "Failed to initialize WPS Registrar");
1135 0 : goto fail;
1136 : }
1137 :
1138 : #ifdef CONFIG_WPS_UPNP
1139 397 : wps->friendly_name = hapd->conf->friendly_name;
1140 397 : wps->manufacturer_url = hapd->conf->manufacturer_url;
1141 397 : wps->model_description = hapd->conf->model_description;
1142 397 : wps->model_url = hapd->conf->model_url;
1143 397 : wps->upc = hapd->conf->upc;
1144 : #endif /* CONFIG_WPS_UPNP */
1145 :
1146 397 : hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd);
1147 :
1148 397 : hapd->wps = wps;
1149 :
1150 397 : return 0;
1151 :
1152 : fail:
1153 0 : hostapd_free_wps(wps);
1154 0 : return -1;
1155 : }
1156 :
1157 :
1158 1345 : int hostapd_init_wps_complete(struct hostapd_data *hapd)
1159 : {
1160 1345 : struct wps_context *wps = hapd->wps;
1161 :
1162 1345 : if (wps == NULL)
1163 948 : return 0;
1164 :
1165 : #ifdef CONFIG_WPS_UPNP
1166 397 : if (hostapd_wps_upnp_init(hapd, wps) < 0) {
1167 0 : wpa_printf(MSG_ERROR, "Failed to initialize WPS UPnP");
1168 0 : wps_registrar_deinit(wps->registrar);
1169 0 : hostapd_free_wps(wps);
1170 0 : hapd->wps = NULL;
1171 0 : return -1;
1172 : }
1173 : #endif /* CONFIG_WPS_UPNP */
1174 :
1175 397 : return 0;
1176 : }
1177 :
1178 :
1179 409 : static void hostapd_wps_nfc_clear(struct wps_context *wps)
1180 : {
1181 : #ifdef CONFIG_WPS_NFC
1182 409 : wpa_printf(MSG_DEBUG, "WPS: Clear NFC Tag context %p", wps);
1183 409 : wps->ap_nfc_dev_pw_id = 0;
1184 409 : wpabuf_free(wps->ap_nfc_dh_pubkey);
1185 409 : wps->ap_nfc_dh_pubkey = NULL;
1186 409 : wpabuf_free(wps->ap_nfc_dh_privkey);
1187 409 : wps->ap_nfc_dh_privkey = NULL;
1188 409 : wpabuf_free(wps->ap_nfc_dev_pw);
1189 409 : wps->ap_nfc_dev_pw = NULL;
1190 : #endif /* CONFIG_WPS_NFC */
1191 409 : }
1192 :
1193 :
1194 1388 : void hostapd_deinit_wps(struct hostapd_data *hapd)
1195 : {
1196 1388 : eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
1197 1388 : eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
1198 1388 : eloop_cancel_timeout(wps_reload_config, hapd->iface, NULL);
1199 1388 : if (hapd->wps == NULL) {
1200 991 : hostapd_wps_clear_ies(hapd, 1);
1201 2379 : return;
1202 : }
1203 : #ifdef CONFIG_WPS_UPNP
1204 397 : hostapd_wps_upnp_deinit(hapd);
1205 : #endif /* CONFIG_WPS_UPNP */
1206 397 : wps_registrar_deinit(hapd->wps->registrar);
1207 397 : wps_free_pending_msgs(hapd->wps->upnp_msgs);
1208 397 : hostapd_free_wps(hapd->wps);
1209 397 : hapd->wps = NULL;
1210 397 : hostapd_wps_clear_ies(hapd, 1);
1211 : }
1212 :
1213 :
1214 21 : void hostapd_update_wps(struct hostapd_data *hapd)
1215 : {
1216 21 : if (hapd->wps == NULL)
1217 23 : return;
1218 :
1219 : #ifdef CONFIG_WPS_UPNP
1220 19 : hapd->wps->friendly_name = hapd->conf->friendly_name;
1221 19 : hapd->wps->manufacturer_url = hapd->conf->manufacturer_url;
1222 19 : hapd->wps->model_description = hapd->conf->model_description;
1223 19 : hapd->wps->model_url = hapd->conf->model_url;
1224 19 : hapd->wps->upc = hapd->conf->upc;
1225 : #endif /* CONFIG_WPS_UPNP */
1226 :
1227 19 : hostapd_wps_set_vendor_ext(hapd, hapd->wps);
1228 :
1229 19 : if (hapd->conf->wps_state)
1230 19 : wps_registrar_update_ie(hapd->wps->registrar);
1231 : else
1232 0 : hostapd_deinit_wps(hapd);
1233 : }
1234 :
1235 :
1236 : struct wps_add_pin_data {
1237 : const u8 *addr;
1238 : const u8 *uuid;
1239 : const u8 *pin;
1240 : size_t pin_len;
1241 : int timeout;
1242 : int added;
1243 : };
1244 :
1245 :
1246 156 : static int wps_add_pin(struct hostapd_data *hapd, void *ctx)
1247 : {
1248 156 : struct wps_add_pin_data *data = ctx;
1249 : int ret;
1250 :
1251 156 : if (hapd->wps == NULL)
1252 0 : return 0;
1253 156 : ret = wps_registrar_add_pin(hapd->wps->registrar, data->addr,
1254 : data->uuid, data->pin, data->pin_len,
1255 : data->timeout);
1256 156 : if (ret == 0)
1257 156 : data->added++;
1258 156 : return ret;
1259 : }
1260 :
1261 :
1262 154 : int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
1263 : const char *uuid, const char *pin, int timeout)
1264 : {
1265 : u8 u[UUID_LEN];
1266 : struct wps_add_pin_data data;
1267 :
1268 154 : data.addr = addr;
1269 154 : data.uuid = u;
1270 154 : data.pin = (const u8 *) pin;
1271 154 : data.pin_len = os_strlen(pin);
1272 154 : data.timeout = timeout;
1273 154 : data.added = 0;
1274 :
1275 154 : if (os_strcmp(uuid, "any") == 0)
1276 152 : data.uuid = NULL;
1277 : else {
1278 2 : if (uuid_str2bin(uuid, u))
1279 0 : return -1;
1280 2 : data.uuid = u;
1281 : }
1282 154 : if (hostapd_wps_for_each(hapd, wps_add_pin, &data) < 0)
1283 0 : return -1;
1284 154 : return data.added ? 0 : -1;
1285 : }
1286 :
1287 :
1288 69 : static int wps_button_pushed(struct hostapd_data *hapd, void *ctx)
1289 : {
1290 69 : const u8 *p2p_dev_addr = ctx;
1291 69 : if (hapd->wps == NULL)
1292 3 : return -1;
1293 66 : return wps_registrar_button_pushed(hapd->wps->registrar, p2p_dev_addr);
1294 : }
1295 :
1296 :
1297 66 : int hostapd_wps_button_pushed(struct hostapd_data *hapd,
1298 : const u8 *p2p_dev_addr)
1299 : {
1300 66 : return hostapd_wps_for_each(hapd, wps_button_pushed,
1301 : (void *) p2p_dev_addr);
1302 : }
1303 :
1304 :
1305 4 : static int wps_cancel(struct hostapd_data *hapd, void *ctx)
1306 : {
1307 4 : if (hapd->wps == NULL)
1308 1 : return -1;
1309 :
1310 3 : wps_registrar_wps_cancel(hapd->wps->registrar);
1311 3 : ap_for_each_sta(hapd, ap_sta_wps_cancel, NULL);
1312 :
1313 3 : return 0;
1314 : }
1315 :
1316 :
1317 4 : int hostapd_wps_cancel(struct hostapd_data *hapd)
1318 : {
1319 4 : return hostapd_wps_for_each(hapd, wps_cancel, NULL);
1320 : }
1321 :
1322 :
1323 689 : static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
1324 : const u8 *bssid,
1325 : const u8 *ie, size_t ie_len,
1326 : int ssi_signal)
1327 : {
1328 689 : struct hostapd_data *hapd = ctx;
1329 : struct wpabuf *wps_ie;
1330 : struct ieee802_11_elems elems;
1331 :
1332 689 : if (hapd->wps == NULL)
1333 0 : return 0;
1334 :
1335 689 : if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
1336 0 : wpa_printf(MSG_DEBUG, "WPS: Could not parse ProbeReq from "
1337 0 : MACSTR, MAC2STR(addr));
1338 0 : return 0;
1339 : }
1340 :
1341 1053 : if (elems.ssid && elems.ssid_len > 0 &&
1342 581 : (elems.ssid_len != hapd->conf->ssid.ssid_len ||
1343 217 : os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) !=
1344 : 0))
1345 153 : return 0; /* Not for us */
1346 :
1347 536 : wps_ie = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
1348 536 : if (wps_ie == NULL)
1349 25 : return 0;
1350 511 : if (wps_validate_probe_req(wps_ie, addr) < 0) {
1351 0 : wpabuf_free(wps_ie);
1352 0 : return 0;
1353 : }
1354 :
1355 511 : if (wpabuf_len(wps_ie) > 0) {
1356 511 : int p2p_wildcard = 0;
1357 : #ifdef CONFIG_P2P
1358 232 : if (elems.ssid && elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
1359 0 : os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
1360 : P2P_WILDCARD_SSID_LEN) == 0)
1361 0 : p2p_wildcard = 1;
1362 : #endif /* CONFIG_P2P */
1363 511 : wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie,
1364 : p2p_wildcard);
1365 : #ifdef CONFIG_WPS_UPNP
1366 : /* FIX: what exactly should be included in the WLANEvent?
1367 : * WPS attributes? Full ProbeReq frame? */
1368 511 : if (!p2p_wildcard)
1369 511 : upnp_wps_device_send_wlan_event(
1370 : hapd->wps_upnp, addr,
1371 : UPNP_WPS_WLANEVENT_TYPE_PROBE, wps_ie);
1372 : #endif /* CONFIG_WPS_UPNP */
1373 : }
1374 :
1375 511 : wpabuf_free(wps_ie);
1376 :
1377 511 : return 0;
1378 : }
1379 :
1380 :
1381 : #ifdef CONFIG_WPS_UPNP
1382 :
1383 23 : static int hostapd_rx_req_put_wlan_response(
1384 : void *priv, enum upnp_wps_wlanevent_type ev_type,
1385 : const u8 *mac_addr, const struct wpabuf *msg,
1386 : enum wps_msg_type msg_type)
1387 : {
1388 23 : struct hostapd_data *hapd = priv;
1389 : struct sta_info *sta;
1390 : struct upnp_pending_message *p;
1391 :
1392 138 : wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr="
1393 138 : MACSTR, ev_type, MAC2STR(mac_addr));
1394 23 : wpa_hexdump(MSG_MSGDUMP, "WPS UPnP: PutWLANResponse NewMessage",
1395 : wpabuf_head(msg), wpabuf_len(msg));
1396 23 : if (ev_type != UPNP_WPS_WLANEVENT_TYPE_EAP) {
1397 0 : wpa_printf(MSG_DEBUG, "WPS UPnP: Ignored unexpected "
1398 : "PutWLANResponse WLANEventType %d", ev_type);
1399 0 : return -1;
1400 : }
1401 :
1402 : /*
1403 : * EAP response to ongoing to WPS Registration. Send it to EAP-WSC
1404 : * server implementation for delivery to the peer.
1405 : */
1406 :
1407 23 : sta = ap_get_sta(hapd, mac_addr);
1408 : #ifndef CONFIG_WPS_STRICT
1409 23 : if (!sta) {
1410 : /*
1411 : * Workaround - Intel wsccmd uses bogus NewWLANEventMAC:
1412 : * Pick STA that is in an ongoing WPS registration without
1413 : * checking the MAC address.
1414 : */
1415 0 : wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found based "
1416 : "on NewWLANEventMAC; try wildcard match");
1417 0 : for (sta = hapd->sta_list; sta; sta = sta->next) {
1418 0 : if (sta->eapol_sm && (sta->flags & WLAN_STA_WPS))
1419 0 : break;
1420 : }
1421 : }
1422 : #endif /* CONFIG_WPS_STRICT */
1423 :
1424 23 : if (!sta || !(sta->flags & WLAN_STA_WPS)) {
1425 0 : wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found");
1426 0 : return 0;
1427 : }
1428 :
1429 23 : if (!sta->eapol_sm) {
1430 : /*
1431 : * This can happen, e.g., if an ER sends an extra message after
1432 : * the station has disassociated (but not fully
1433 : * deauthenticated).
1434 : */
1435 0 : wpa_printf(MSG_DEBUG, "WPS UPnP: Matching STA did not have EAPOL state machine initialized");
1436 0 : return 0;
1437 : }
1438 :
1439 23 : p = os_zalloc(sizeof(*p));
1440 23 : if (p == NULL)
1441 0 : return -1;
1442 23 : os_memcpy(p->addr, sta->addr, ETH_ALEN);
1443 23 : p->msg = wpabuf_dup(msg);
1444 23 : p->type = msg_type;
1445 23 : p->next = hapd->wps->upnp_msgs;
1446 23 : hapd->wps->upnp_msgs = p;
1447 :
1448 23 : return eapol_auth_eap_pending_cb(sta->eapol_sm, sta->eapol_sm->eap);
1449 : }
1450 :
1451 :
1452 397 : static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
1453 : struct wps_context *wps)
1454 : {
1455 : struct upnp_wps_device_ctx *ctx;
1456 :
1457 397 : if (!hapd->conf->upnp_iface)
1458 381 : return 0;
1459 16 : ctx = os_zalloc(sizeof(*ctx));
1460 16 : if (ctx == NULL)
1461 0 : return -1;
1462 :
1463 16 : ctx->rx_req_put_wlan_response = hostapd_rx_req_put_wlan_response;
1464 16 : if (hapd->conf->ap_pin)
1465 15 : ctx->ap_pin = os_strdup(hapd->conf->ap_pin);
1466 :
1467 16 : hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd,
1468 16 : hapd->conf->upnp_iface);
1469 16 : if (hapd->wps_upnp == NULL)
1470 0 : return -1;
1471 16 : wps->wps_upnp = hapd->wps_upnp;
1472 :
1473 16 : return 0;
1474 : }
1475 :
1476 :
1477 397 : static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd)
1478 : {
1479 397 : upnp_wps_device_deinit(hapd->wps_upnp, hapd);
1480 397 : }
1481 :
1482 : #endif /* CONFIG_WPS_UPNP */
1483 :
1484 :
1485 81 : int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
1486 : char *buf, size_t buflen)
1487 : {
1488 81 : if (hapd->wps == NULL)
1489 75 : return 0;
1490 6 : return wps_registrar_get_info(hapd->wps->registrar, addr, buf, buflen);
1491 : }
1492 :
1493 :
1494 2 : static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
1495 : {
1496 2 : struct hostapd_data *hapd = eloop_data;
1497 2 : wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
1498 2 : hostapd_wps_ap_pin_disable(hapd);
1499 2 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_PIN_DISABLED);
1500 2 : }
1501 :
1502 :
1503 5 : static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout)
1504 : {
1505 5 : wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
1506 5 : hapd->ap_pin_failures = 0;
1507 5 : hapd->ap_pin_failures_consecutive = 0;
1508 5 : hapd->conf->ap_setup_locked = 0;
1509 5 : if (hapd->wps->ap_setup_locked) {
1510 1 : wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
1511 1 : hapd->wps->ap_setup_locked = 0;
1512 1 : wps_registrar_update_ie(hapd->wps->registrar);
1513 : }
1514 5 : eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
1515 5 : if (timeout > 0)
1516 5 : eloop_register_timeout(timeout, 0,
1517 : hostapd_wps_ap_pin_timeout, hapd, NULL);
1518 5 : }
1519 :
1520 :
1521 5 : static int wps_ap_pin_disable(struct hostapd_data *hapd, void *ctx)
1522 : {
1523 5 : os_free(hapd->conf->ap_pin);
1524 5 : hapd->conf->ap_pin = NULL;
1525 : #ifdef CONFIG_WPS_UPNP
1526 5 : upnp_wps_set_ap_pin(hapd->wps_upnp, NULL);
1527 : #endif /* CONFIG_WPS_UPNP */
1528 5 : eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
1529 5 : return 0;
1530 : }
1531 :
1532 :
1533 5 : void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd)
1534 : {
1535 5 : wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
1536 5 : hostapd_wps_for_each(hapd, wps_ap_pin_disable, NULL);
1537 5 : }
1538 :
1539 :
1540 : struct wps_ap_pin_data {
1541 : char pin_txt[9];
1542 : int timeout;
1543 : };
1544 :
1545 :
1546 5 : static int wps_ap_pin_set(struct hostapd_data *hapd, void *ctx)
1547 : {
1548 5 : struct wps_ap_pin_data *data = ctx;
1549 5 : os_free(hapd->conf->ap_pin);
1550 5 : hapd->conf->ap_pin = os_strdup(data->pin_txt);
1551 : #ifdef CONFIG_WPS_UPNP
1552 5 : upnp_wps_set_ap_pin(hapd->wps_upnp, data->pin_txt);
1553 : #endif /* CONFIG_WPS_UPNP */
1554 5 : hostapd_wps_ap_pin_enable(hapd, data->timeout);
1555 5 : return 0;
1556 : }
1557 :
1558 :
1559 3 : const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout)
1560 : {
1561 : unsigned int pin;
1562 : struct wps_ap_pin_data data;
1563 :
1564 3 : pin = wps_generate_pin();
1565 3 : os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%08u", pin);
1566 3 : data.timeout = timeout;
1567 3 : hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
1568 3 : return hapd->conf->ap_pin;
1569 : }
1570 :
1571 :
1572 3 : const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd)
1573 : {
1574 3 : return hapd->conf->ap_pin;
1575 : }
1576 :
1577 :
1578 2 : int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
1579 : int timeout)
1580 : {
1581 : struct wps_ap_pin_data data;
1582 : int ret;
1583 :
1584 2 : ret = os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%s", pin);
1585 2 : if (os_snprintf_error(sizeof(data.pin_txt), ret))
1586 0 : return -1;
1587 2 : data.timeout = timeout;
1588 2 : return hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
1589 : }
1590 :
1591 :
1592 4 : static int wps_update_ie(struct hostapd_data *hapd, void *ctx)
1593 : {
1594 4 : if (hapd->wps)
1595 4 : wps_registrar_update_ie(hapd->wps->registrar);
1596 4 : return 0;
1597 : }
1598 :
1599 :
1600 4 : void hostapd_wps_update_ie(struct hostapd_data *hapd)
1601 : {
1602 4 : hostapd_wps_for_each(hapd, wps_update_ie, NULL);
1603 4 : }
1604 :
1605 :
1606 2 : int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
1607 : const char *auth, const char *encr, const char *key)
1608 : {
1609 : struct wps_credential cred;
1610 : size_t len;
1611 :
1612 2 : os_memset(&cred, 0, sizeof(cred));
1613 :
1614 2 : len = os_strlen(ssid);
1615 4 : if ((len & 1) || len > 2 * sizeof(cred.ssid) ||
1616 2 : hexstr2bin(ssid, cred.ssid, len / 2))
1617 0 : return -1;
1618 2 : cred.ssid_len = len / 2;
1619 :
1620 2 : if (os_strncmp(auth, "OPEN", 4) == 0)
1621 0 : cred.auth_type = WPS_AUTH_OPEN;
1622 2 : else if (os_strncmp(auth, "WPAPSK", 6) == 0)
1623 0 : cred.auth_type = WPS_AUTH_WPAPSK;
1624 2 : else if (os_strncmp(auth, "WPA2PSK", 7) == 0)
1625 2 : cred.auth_type = WPS_AUTH_WPA2PSK;
1626 : else
1627 0 : return -1;
1628 :
1629 2 : if (encr) {
1630 2 : if (os_strncmp(encr, "NONE", 4) == 0)
1631 0 : cred.encr_type = WPS_ENCR_NONE;
1632 2 : else if (os_strncmp(encr, "TKIP", 4) == 0)
1633 0 : cred.encr_type = WPS_ENCR_TKIP;
1634 2 : else if (os_strncmp(encr, "CCMP", 4) == 0)
1635 2 : cred.encr_type = WPS_ENCR_AES;
1636 : else
1637 0 : return -1;
1638 : } else
1639 0 : cred.encr_type = WPS_ENCR_NONE;
1640 :
1641 2 : if (key) {
1642 2 : len = os_strlen(key);
1643 4 : if ((len & 1) || len > 2 * sizeof(cred.key) ||
1644 2 : hexstr2bin(key, cred.key, len / 2))
1645 0 : return -1;
1646 2 : cred.key_len = len / 2;
1647 : }
1648 :
1649 2 : return wps_registrar_config_ap(hapd->wps->registrar, &cred);
1650 : }
1651 :
1652 :
1653 : #ifdef CONFIG_WPS_NFC
1654 :
1655 : struct wps_nfc_password_token_data {
1656 : const u8 *oob_dev_pw;
1657 : size_t oob_dev_pw_len;
1658 : int added;
1659 : };
1660 :
1661 :
1662 2 : static int wps_add_nfc_password_token(struct hostapd_data *hapd, void *ctx)
1663 : {
1664 2 : struct wps_nfc_password_token_data *data = ctx;
1665 : int ret;
1666 :
1667 2 : if (hapd->wps == NULL)
1668 0 : return 0;
1669 2 : ret = wps_registrar_add_nfc_password_token(hapd->wps->registrar,
1670 : data->oob_dev_pw,
1671 : data->oob_dev_pw_len);
1672 2 : if (ret == 0)
1673 2 : data->added++;
1674 2 : return ret;
1675 : }
1676 :
1677 :
1678 2 : static int hostapd_wps_add_nfc_password_token(struct hostapd_data *hapd,
1679 : struct wps_parse_attr *attr)
1680 : {
1681 : struct wps_nfc_password_token_data data;
1682 :
1683 2 : data.oob_dev_pw = attr->oob_dev_password;
1684 2 : data.oob_dev_pw_len = attr->oob_dev_password_len;
1685 2 : data.added = 0;
1686 2 : if (hostapd_wps_for_each(hapd, wps_add_nfc_password_token, &data) < 0)
1687 0 : return -1;
1688 2 : return data.added ? 0 : -1;
1689 : }
1690 :
1691 :
1692 2 : static int hostapd_wps_nfc_tag_process(struct hostapd_data *hapd,
1693 : const struct wpabuf *wps)
1694 : {
1695 : struct wps_parse_attr attr;
1696 :
1697 2 : wpa_hexdump_buf(MSG_DEBUG, "WPS: Received NFC tag payload", wps);
1698 :
1699 2 : if (wps_parse_msg(wps, &attr)) {
1700 0 : wpa_printf(MSG_DEBUG, "WPS: Ignore invalid data from NFC tag");
1701 0 : return -1;
1702 : }
1703 :
1704 2 : if (attr.oob_dev_password)
1705 2 : return hostapd_wps_add_nfc_password_token(hapd, &attr);
1706 :
1707 0 : wpa_printf(MSG_DEBUG, "WPS: Ignore unrecognized NFC tag");
1708 0 : return -1;
1709 : }
1710 :
1711 :
1712 2 : int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
1713 : const struct wpabuf *data)
1714 : {
1715 2 : const struct wpabuf *wps = data;
1716 2 : struct wpabuf *tmp = NULL;
1717 : int ret;
1718 :
1719 2 : if (wpabuf_len(data) < 4)
1720 0 : return -1;
1721 :
1722 2 : if (*wpabuf_head_u8(data) != 0x10) {
1723 : /* Assume this contains full NDEF record */
1724 2 : tmp = ndef_parse_wifi(data);
1725 2 : if (tmp == NULL) {
1726 0 : wpa_printf(MSG_DEBUG, "WPS: Could not parse NDEF");
1727 0 : return -1;
1728 : }
1729 2 : wps = tmp;
1730 : }
1731 :
1732 2 : ret = hostapd_wps_nfc_tag_process(hapd, wps);
1733 2 : wpabuf_free(tmp);
1734 2 : return ret;
1735 : }
1736 :
1737 :
1738 3 : struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
1739 : int ndef)
1740 : {
1741 : struct wpabuf *ret;
1742 :
1743 3 : if (hapd->wps == NULL)
1744 0 : return NULL;
1745 :
1746 3 : ret = wps_get_oob_cred(hapd->wps, hostapd_wps_rf_band_cb(hapd),
1747 3 : hapd->iconf->channel);
1748 3 : if (ndef && ret) {
1749 : struct wpabuf *tmp;
1750 3 : tmp = ndef_build_wifi(ret);
1751 3 : wpabuf_free(ret);
1752 3 : if (tmp == NULL)
1753 0 : return NULL;
1754 3 : ret = tmp;
1755 : }
1756 :
1757 3 : return ret;
1758 : }
1759 :
1760 :
1761 9 : struct wpabuf * hostapd_wps_nfc_hs_cr(struct hostapd_data *hapd, int ndef)
1762 : {
1763 : struct wpabuf *ret;
1764 :
1765 9 : if (hapd->wps == NULL)
1766 0 : return NULL;
1767 :
1768 9 : if (hapd->conf->wps_nfc_dh_pubkey == NULL) {
1769 8 : struct wps_context *wps = hapd->wps;
1770 8 : if (wps_nfc_gen_dh(&hapd->conf->wps_nfc_dh_pubkey,
1771 8 : &hapd->conf->wps_nfc_dh_privkey) < 0)
1772 0 : return NULL;
1773 8 : hostapd_wps_nfc_clear(wps);
1774 8 : wps->ap_nfc_dev_pw_id = DEV_PW_NFC_CONNECTION_HANDOVER;
1775 8 : wps->ap_nfc_dh_pubkey =
1776 8 : wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey);
1777 8 : wps->ap_nfc_dh_privkey =
1778 8 : wpabuf_dup(hapd->conf->wps_nfc_dh_privkey);
1779 8 : if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey) {
1780 0 : hostapd_wps_nfc_clear(wps);
1781 0 : return NULL;
1782 : }
1783 : }
1784 :
1785 18 : ret = wps_build_nfc_handover_sel(hapd->wps,
1786 9 : hapd->conf->wps_nfc_dh_pubkey,
1787 18 : hapd->own_addr, hapd->iface->freq);
1788 :
1789 9 : if (ndef && ret) {
1790 : struct wpabuf *tmp;
1791 9 : tmp = ndef_build_wifi(ret);
1792 9 : wpabuf_free(ret);
1793 9 : if (tmp == NULL)
1794 0 : return NULL;
1795 9 : ret = tmp;
1796 : }
1797 :
1798 9 : return ret;
1799 : }
1800 :
1801 :
1802 9 : int hostapd_wps_nfc_report_handover(struct hostapd_data *hapd,
1803 : const struct wpabuf *req,
1804 : const struct wpabuf *sel)
1805 : {
1806 : struct wpabuf *wps;
1807 9 : int ret = -1;
1808 : u16 wsc_len;
1809 : const u8 *pos;
1810 : struct wpabuf msg;
1811 : struct wps_parse_attr attr;
1812 : u16 dev_pw_id;
1813 :
1814 : /*
1815 : * Enrollee/station is always initiator of the NFC connection handover,
1816 : * so use the request message here to find Enrollee public key hash.
1817 : */
1818 9 : wps = ndef_parse_wifi(req);
1819 9 : if (wps == NULL)
1820 1 : return -1;
1821 8 : wpa_printf(MSG_DEBUG, "WPS: Received application/vnd.wfa.wsc "
1822 : "payload from NFC connection handover");
1823 8 : wpa_hexdump_buf(MSG_DEBUG, "WPS: NFC payload", wps);
1824 8 : if (wpabuf_len(wps) < 2) {
1825 0 : wpa_printf(MSG_DEBUG, "WPS: Too short Wi-Fi Handover Request "
1826 : "Message");
1827 0 : goto out;
1828 : }
1829 8 : pos = wpabuf_head(wps);
1830 8 : wsc_len = WPA_GET_BE16(pos);
1831 8 : if (wsc_len > wpabuf_len(wps) - 2) {
1832 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid WSC attribute length (%u) "
1833 : "in rt Wi-Fi Handover Request Message", wsc_len);
1834 0 : goto out;
1835 : }
1836 8 : pos += 2;
1837 :
1838 8 : wpa_hexdump(MSG_DEBUG,
1839 : "WPS: WSC attributes in Wi-Fi Handover Request Message",
1840 : pos, wsc_len);
1841 8 : if (wsc_len < wpabuf_len(wps) - 2) {
1842 0 : wpa_hexdump(MSG_DEBUG,
1843 : "WPS: Ignore extra data after WSC attributes",
1844 0 : pos + wsc_len, wpabuf_len(wps) - 2 - wsc_len);
1845 : }
1846 :
1847 8 : wpabuf_set(&msg, pos, wsc_len);
1848 8 : ret = wps_parse_msg(&msg, &attr);
1849 8 : if (ret < 0) {
1850 0 : wpa_printf(MSG_DEBUG, "WPS: Could not parse WSC attributes in "
1851 : "Wi-Fi Handover Request Message");
1852 0 : goto out;
1853 : }
1854 :
1855 16 : if (attr.oob_dev_password == NULL ||
1856 8 : attr.oob_dev_password_len < WPS_OOB_PUBKEY_HASH_LEN + 2) {
1857 0 : wpa_printf(MSG_DEBUG, "WPS: No Out-of-Band Device Password "
1858 : "included in Wi-Fi Handover Request Message");
1859 0 : ret = -1;
1860 0 : goto out;
1861 : }
1862 :
1863 8 : if (attr.uuid_e == NULL) {
1864 0 : wpa_printf(MSG_DEBUG, "WPS: No UUID-E included in Wi-Fi "
1865 : "Handover Request Message");
1866 0 : ret = -1;
1867 0 : goto out;
1868 : }
1869 :
1870 8 : wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", attr.uuid_e, WPS_UUID_LEN);
1871 :
1872 16 : wpa_hexdump(MSG_DEBUG, "WPS: Out-of-Band Device Password",
1873 8 : attr.oob_dev_password, attr.oob_dev_password_len);
1874 8 : dev_pw_id = WPA_GET_BE16(attr.oob_dev_password +
1875 : WPS_OOB_PUBKEY_HASH_LEN);
1876 8 : if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER) {
1877 0 : wpa_printf(MSG_DEBUG, "WPS: Unexpected OOB Device Password ID "
1878 : "%u in Wi-Fi Handover Request Message", dev_pw_id);
1879 0 : ret = -1;
1880 0 : goto out;
1881 : }
1882 8 : wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Public Key hash",
1883 8 : attr.oob_dev_password, WPS_OOB_PUBKEY_HASH_LEN);
1884 :
1885 8 : ret = wps_registrar_add_nfc_pw_token(hapd->wps->registrar,
1886 : attr.oob_dev_password,
1887 : DEV_PW_NFC_CONNECTION_HANDOVER,
1888 : NULL, 0, 1);
1889 :
1890 : out:
1891 8 : wpabuf_free(wps);
1892 8 : return ret;
1893 : }
1894 :
1895 :
1896 3 : struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef)
1897 : {
1898 3 : if (hapd->conf->wps_nfc_pw_from_config) {
1899 0 : return wps_nfc_token_build(ndef,
1900 0 : hapd->conf->wps_nfc_dev_pw_id,
1901 0 : hapd->conf->wps_nfc_dh_pubkey,
1902 0 : hapd->conf->wps_nfc_dev_pw);
1903 : }
1904 :
1905 9 : return wps_nfc_token_gen(ndef, &hapd->conf->wps_nfc_dev_pw_id,
1906 3 : &hapd->conf->wps_nfc_dh_pubkey,
1907 3 : &hapd->conf->wps_nfc_dh_privkey,
1908 3 : &hapd->conf->wps_nfc_dev_pw);
1909 : }
1910 :
1911 :
1912 3 : int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd)
1913 : {
1914 3 : struct wps_context *wps = hapd->wps;
1915 : struct wpabuf *pw;
1916 :
1917 3 : if (wps == NULL)
1918 0 : return -1;
1919 :
1920 6 : if (!hapd->conf->wps_nfc_dh_pubkey ||
1921 6 : !hapd->conf->wps_nfc_dh_privkey ||
1922 6 : !hapd->conf->wps_nfc_dev_pw ||
1923 3 : !hapd->conf->wps_nfc_dev_pw_id)
1924 0 : return -1;
1925 :
1926 3 : hostapd_wps_nfc_clear(wps);
1927 3 : wpa_printf(MSG_DEBUG,
1928 : "WPS: Enable NFC Tag (Dev Pw Id %u) for AP interface %s (context %p)",
1929 3 : hapd->conf->wps_nfc_dev_pw_id, hapd->conf->iface, wps);
1930 3 : wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id;
1931 3 : wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey);
1932 3 : wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey);
1933 3 : pw = hapd->conf->wps_nfc_dev_pw;
1934 3 : wps->ap_nfc_dev_pw = wpabuf_alloc(
1935 3 : wpabuf_len(pw) * 2 + 1);
1936 3 : if (wps->ap_nfc_dev_pw) {
1937 9 : wpa_snprintf_hex_uppercase(
1938 3 : (char *) wpabuf_put(wps->ap_nfc_dev_pw,
1939 3 : wpabuf_len(pw) * 2),
1940 3 : wpabuf_len(pw) * 2 + 1,
1941 3 : wpabuf_head(pw), wpabuf_len(pw));
1942 : }
1943 :
1944 6 : if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey ||
1945 3 : !wps->ap_nfc_dev_pw) {
1946 0 : hostapd_wps_nfc_clear(wps);
1947 0 : return -1;
1948 : }
1949 :
1950 3 : return 0;
1951 : }
1952 :
1953 :
1954 1 : void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd)
1955 : {
1956 1 : wpa_printf(MSG_DEBUG, "WPS: Disable NFC token for AP interface %s",
1957 1 : hapd->conf->iface);
1958 1 : hostapd_wps_nfc_clear(hapd->wps);
1959 1 : }
1960 :
1961 : #endif /* CONFIG_WPS_NFC */
|