]> git.ipfire.org Git - thirdparty/hostap.git/blob - src/ap/wps_hostapd.c
Rename some src/ap files to avoid duplicate file names
[thirdparty/hostap.git] / src / ap / wps_hostapd.c
1 /*
2 * hostapd / WPS integration
3 * Copyright (c) 2008-2009, 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 "utils/includes.h"
16
17 #include "utils/common.h"
18 #include "utils/eloop.h"
19 #include "utils/uuid.h"
20 #include "crypto/dh_groups.h"
21 #include "common/wpa_ctrl.h"
22 #include "common/ieee802_11_defs.h"
23 #include "common/ieee802_11_common.h"
24 #include "eapol_auth/eapol_auth_sm.h"
25 #include "eapol_auth/eapol_auth_sm_i.h"
26 #include "wps/wps.h"
27 #include "wps/wps_defs.h"
28 #include "wps/wps_dev_attr.h"
29 #include "hostapd.h"
30 #include "ap_config.h"
31 #include "sta_info.h"
32 #include "wps_hostapd.h"
33
34
35 #ifdef CONFIG_WPS_UPNP
36 #include "wps/wps_upnp.h"
37 static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
38 struct wps_context *wps);
39 static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd);
40 #endif /* CONFIG_WPS_UPNP */
41
42 static void hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
43 const u8 *ie, size_t ie_len);
44
45
46 static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk,
47 size_t psk_len)
48 {
49 struct hostapd_data *hapd = ctx;
50 struct hostapd_wpa_psk *p;
51 struct hostapd_ssid *ssid = &hapd->conf->ssid;
52
53 wpa_printf(MSG_DEBUG, "Received new WPA/WPA2-PSK from WPS for STA "
54 MACSTR, MAC2STR(mac_addr));
55 wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len);
56
57 if (psk_len != PMK_LEN) {
58 wpa_printf(MSG_DEBUG, "Unexpected PSK length %lu",
59 (unsigned long) psk_len);
60 return -1;
61 }
62
63 /* Add the new PSK to runtime PSK list */
64 p = os_zalloc(sizeof(*p));
65 if (p == NULL)
66 return -1;
67 os_memcpy(p->addr, mac_addr, ETH_ALEN);
68 os_memcpy(p->psk, psk, PMK_LEN);
69
70 p->next = ssid->wpa_psk;
71 ssid->wpa_psk = p;
72
73 if (ssid->wpa_psk_file) {
74 FILE *f;
75 char hex[PMK_LEN * 2 + 1];
76 /* Add the new PSK to PSK list file */
77 f = fopen(ssid->wpa_psk_file, "a");
78 if (f == NULL) {
79 wpa_printf(MSG_DEBUG, "Failed to add the PSK to "
80 "'%s'", ssid->wpa_psk_file);
81 return -1;
82 }
83
84 wpa_snprintf_hex(hex, sizeof(hex), psk, psk_len);
85 fprintf(f, MACSTR " %s\n", MAC2STR(mac_addr), hex);
86 fclose(f);
87 }
88
89 return 0;
90 }
91
92
93 static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie,
94 struct wpabuf *probe_resp_ie)
95 {
96 struct hostapd_data *hapd = ctx;
97 wpabuf_free(hapd->wps_beacon_ie);
98 hapd->wps_beacon_ie = beacon_ie;
99 wpabuf_free(hapd->wps_probe_resp_ie);
100 hapd->wps_probe_resp_ie = probe_resp_ie;
101 return hapd->drv.set_ap_wps_ie(hapd, hapd->wps_beacon_ie,
102 hapd->wps_probe_resp_ie);
103 }
104
105
106 static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
107 const struct wps_device_data *dev)
108 {
109 struct hostapd_data *hapd = ctx;
110 char uuid[40], txt[400];
111 int len;
112 char devtype[WPS_DEV_TYPE_BUFSIZE];
113 if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
114 return;
115 wpa_printf(MSG_DEBUG, "WPS: PIN needed for E-UUID %s", uuid);
116 len = os_snprintf(txt, sizeof(txt), WPS_EVENT_PIN_NEEDED
117 "%s " MACSTR " [%s|%s|%s|%s|%s|%s]",
118 uuid, MAC2STR(dev->mac_addr), dev->device_name,
119 dev->manufacturer, dev->model_name,
120 dev->model_number, dev->serial_number,
121 wps_dev_type_bin2str(dev->pri_dev_type, devtype,
122 sizeof(devtype)));
123 if (len > 0 && len < (int) sizeof(txt))
124 wpa_msg(hapd->msg_ctx, MSG_INFO, "%s", txt);
125
126 if (hapd->conf->wps_pin_requests) {
127 FILE *f;
128 struct os_time t;
129 f = fopen(hapd->conf->wps_pin_requests, "a");
130 if (f == NULL)
131 return;
132 os_get_time(&t);
133 fprintf(f, "%ld\t%s\t" MACSTR "\t%s\t%s\t%s\t%s\t%s"
134 "\t%s\n",
135 t.sec, uuid, MAC2STR(dev->mac_addr), dev->device_name,
136 dev->manufacturer, dev->model_name, dev->model_number,
137 dev->serial_number,
138 wps_dev_type_bin2str(dev->pri_dev_type, devtype,
139 sizeof(devtype)));
140 fclose(f);
141 }
142 }
143
144
145 static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
146 const u8 *uuid_e)
147 {
148 struct hostapd_data *hapd = ctx;
149 char uuid[40];
150 if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
151 return;
152 wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s",
153 MAC2STR(mac_addr), uuid);
154 }
155
156
157 static int str_starts(const char *str, const char *start)
158 {
159 return os_strncmp(str, start, os_strlen(start)) == 0;
160 }
161
162
163 static void wps_reload_config(void *eloop_data, void *user_ctx)
164 {
165 struct hostapd_iface *iface = eloop_data;
166
167 wpa_printf(MSG_DEBUG, "WPS: Reload configuration data");
168 if (iface->reload_config(iface) < 0) {
169 wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated "
170 "configuration");
171 }
172 }
173
174
175 static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
176 {
177 struct hostapd_data *hapd = ctx;
178 FILE *oconf, *nconf;
179 size_t len, i;
180 char *tmp_fname;
181 char buf[1024];
182 int multi_bss;
183 int wpa;
184
185 wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
186 cred->cred_attr, cred->cred_attr_len);
187
188 wpa_printf(MSG_DEBUG, "WPS: Received new AP Settings");
189 wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len);
190 wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x",
191 cred->auth_type);
192 wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type);
193 wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx);
194 wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key",
195 cred->key, cred->key_len);
196 wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR,
197 MAC2STR(cred->mac_addr));
198
199 if ((hapd->conf->wps_cred_processing == 1 ||
200 hapd->conf->wps_cred_processing == 2) && cred->cred_attr) {
201 size_t blen = cred->cred_attr_len * 2 + 1;
202 char *_buf = os_malloc(blen);
203 if (_buf) {
204 wpa_snprintf_hex(_buf, blen,
205 cred->cred_attr, cred->cred_attr_len);
206 wpa_msg(hapd->msg_ctx, MSG_INFO, "%s%s",
207 WPS_EVENT_NEW_AP_SETTINGS, _buf);
208 os_free(_buf);
209 }
210 } else
211 wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS);
212
213 if (hapd->conf->wps_cred_processing == 1)
214 return 0;
215
216 os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len);
217 hapd->wps->ssid_len = cred->ssid_len;
218 hapd->wps->encr_types = cred->encr_type;
219 hapd->wps->auth_types = cred->auth_type;
220 if (cred->key_len == 0) {
221 os_free(hapd->wps->network_key);
222 hapd->wps->network_key = NULL;
223 hapd->wps->network_key_len = 0;
224 } else {
225 if (hapd->wps->network_key == NULL ||
226 hapd->wps->network_key_len < cred->key_len) {
227 hapd->wps->network_key_len = 0;
228 os_free(hapd->wps->network_key);
229 hapd->wps->network_key = os_malloc(cred->key_len);
230 if (hapd->wps->network_key == NULL)
231 return -1;
232 }
233 hapd->wps->network_key_len = cred->key_len;
234 os_memcpy(hapd->wps->network_key, cred->key, cred->key_len);
235 }
236 hapd->wps->wps_state = WPS_STATE_CONFIGURED;
237
238 len = os_strlen(hapd->iface->config_fname) + 5;
239 tmp_fname = os_malloc(len);
240 if (tmp_fname == NULL)
241 return -1;
242 os_snprintf(tmp_fname, len, "%s-new", hapd->iface->config_fname);
243
244 oconf = fopen(hapd->iface->config_fname, "r");
245 if (oconf == NULL) {
246 wpa_printf(MSG_WARNING, "WPS: Could not open current "
247 "configuration file");
248 os_free(tmp_fname);
249 return -1;
250 }
251
252 nconf = fopen(tmp_fname, "w");
253 if (nconf == NULL) {
254 wpa_printf(MSG_WARNING, "WPS: Could not write updated "
255 "configuration file");
256 os_free(tmp_fname);
257 fclose(oconf);
258 return -1;
259 }
260
261 fprintf(nconf, "# WPS configuration - START\n");
262
263 fprintf(nconf, "wps_state=2\n");
264
265 fprintf(nconf, "ssid=");
266 for (i = 0; i < cred->ssid_len; i++)
267 fputc(cred->ssid[i], nconf);
268 fprintf(nconf, "\n");
269
270 if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
271 (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
272 wpa = 3;
273 else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK))
274 wpa = 2;
275 else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))
276 wpa = 1;
277 else
278 wpa = 0;
279
280 if (wpa) {
281 char *prefix;
282 fprintf(nconf, "wpa=%d\n", wpa);
283
284 fprintf(nconf, "wpa_key_mgmt=");
285 prefix = "";
286 if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) {
287 fprintf(nconf, "WPA-EAP");
288 prefix = " ";
289 }
290 if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK))
291 fprintf(nconf, "%sWPA-PSK", prefix);
292 fprintf(nconf, "\n");
293
294 fprintf(nconf, "wpa_pairwise=");
295 prefix = "";
296 if (cred->encr_type & WPS_ENCR_AES) {
297 fprintf(nconf, "CCMP");
298 prefix = " ";
299 }
300 if (cred->encr_type & WPS_ENCR_TKIP) {
301 fprintf(nconf, "%sTKIP", prefix);
302 }
303 fprintf(nconf, "\n");
304
305 if (cred->key_len >= 8 && cred->key_len < 64) {
306 fprintf(nconf, "wpa_passphrase=");
307 for (i = 0; i < cred->key_len; i++)
308 fputc(cred->key[i], nconf);
309 fprintf(nconf, "\n");
310 } else if (cred->key_len == 64) {
311 fprintf(nconf, "wpa_psk=");
312 for (i = 0; i < cred->key_len; i++)
313 fputc(cred->key[i], nconf);
314 fprintf(nconf, "\n");
315 } else {
316 wpa_printf(MSG_WARNING, "WPS: Invalid key length %lu "
317 "for WPA/WPA2",
318 (unsigned long) cred->key_len);
319 }
320
321 fprintf(nconf, "auth_algs=1\n");
322 } else {
323 if ((cred->auth_type & WPS_AUTH_OPEN) &&
324 (cred->auth_type & WPS_AUTH_SHARED))
325 fprintf(nconf, "auth_algs=3\n");
326 else if (cred->auth_type & WPS_AUTH_SHARED)
327 fprintf(nconf, "auth_algs=2\n");
328 else
329 fprintf(nconf, "auth_algs=1\n");
330
331 if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx <= 4) {
332 int key_idx = cred->key_idx;
333 if (key_idx)
334 key_idx--;
335 fprintf(nconf, "wep_default_key=%d\n", key_idx);
336 fprintf(nconf, "wep_key%d=", key_idx);
337 if (cred->key_len == 10 || cred->key_len == 26) {
338 /* WEP key as a hex string */
339 for (i = 0; i < cred->key_len; i++)
340 fputc(cred->key[i], nconf);
341 } else {
342 /* Raw WEP key; convert to hex */
343 for (i = 0; i < cred->key_len; i++)
344 fprintf(nconf, "%02x", cred->key[i]);
345 }
346 fprintf(nconf, "\n");
347 }
348 }
349
350 fprintf(nconf, "# WPS configuration - END\n");
351
352 multi_bss = 0;
353 while (fgets(buf, sizeof(buf), oconf)) {
354 if (os_strncmp(buf, "bss=", 4) == 0)
355 multi_bss = 1;
356 if (!multi_bss &&
357 (str_starts(buf, "ssid=") ||
358 str_starts(buf, "auth_algs=") ||
359 str_starts(buf, "wps_state=") ||
360 str_starts(buf, "wpa=") ||
361 str_starts(buf, "wpa_psk=") ||
362 str_starts(buf, "wpa_pairwise=") ||
363 str_starts(buf, "rsn_pairwise=") ||
364 str_starts(buf, "wpa_key_mgmt=") ||
365 str_starts(buf, "wpa_passphrase="))) {
366 fprintf(nconf, "#WPS# %s", buf);
367 } else
368 fprintf(nconf, "%s", buf);
369 }
370
371 fclose(nconf);
372 fclose(oconf);
373
374 if (rename(tmp_fname, hapd->iface->config_fname) < 0) {
375 wpa_printf(MSG_WARNING, "WPS: Failed to rename the updated "
376 "configuration file: %s", strerror(errno));
377 os_free(tmp_fname);
378 return -1;
379 }
380
381 os_free(tmp_fname);
382
383 /* Schedule configuration reload after short period of time to allow
384 * EAP-WSC to be finished.
385 */
386 eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface,
387 NULL);
388
389 /* TODO: dualband AP may need to update multiple configuration files */
390
391 wpa_printf(MSG_DEBUG, "WPS: AP configuration updated");
392
393 return 0;
394 }
395
396
397 static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
398 struct wps_event_pwd_auth_fail *data)
399 {
400 FILE *f;
401
402 if (!data->enrollee)
403 return;
404
405 /*
406 * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
407 * if this happens multiple times.
408 */
409 hapd->ap_pin_failures++;
410 if (hapd->ap_pin_failures < 4)
411 return;
412
413 wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
414 hapd->wps->ap_setup_locked = 1;
415
416 wps_registrar_update_ie(hapd->wps->registrar);
417
418 if (hapd->conf->wps_cred_processing == 1)
419 return;
420
421 f = fopen(hapd->iface->config_fname, "a");
422 if (f == NULL) {
423 wpa_printf(MSG_WARNING, "WPS: Could not append to the current "
424 "configuration file");
425 return;
426 }
427
428 fprintf(f, "# WPS AP Setup Locked based on possible attack\n");
429 fprintf(f, "ap_setup_locked=1\n");
430 fclose(f);
431
432 /* TODO: dualband AP may need to update multiple configuration files */
433
434 wpa_printf(MSG_DEBUG, "WPS: AP configuration updated");
435 }
436
437
438 static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
439 union wps_event_data *data)
440 {
441 struct hostapd_data *hapd = ctx;
442
443 if (event == WPS_EV_PWD_AUTH_FAIL)
444 hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail);
445 }
446
447
448 static void hostapd_wps_clear_ies(struct hostapd_data *hapd)
449 {
450 wpabuf_free(hapd->wps_beacon_ie);
451 hapd->wps_beacon_ie = NULL;
452
453 wpabuf_free(hapd->wps_probe_resp_ie);
454 hapd->wps_probe_resp_ie = NULL;
455
456 hapd->drv.set_ap_wps_ie(hapd, NULL, NULL);
457 }
458
459
460 int hostapd_init_wps(struct hostapd_data *hapd,
461 struct hostapd_bss_config *conf)
462 {
463 struct wps_context *wps;
464 struct wps_registrar_config cfg;
465
466 if (conf->wps_state == 0) {
467 hostapd_wps_clear_ies(hapd);
468 return 0;
469 }
470
471 wps = os_zalloc(sizeof(*wps));
472 if (wps == NULL)
473 return -1;
474
475 wps->cred_cb = hostapd_wps_cred_cb;
476 wps->event_cb = hostapd_wps_event_cb;
477 wps->cb_ctx = hapd;
478
479 os_memset(&cfg, 0, sizeof(cfg));
480 wps->wps_state = hapd->conf->wps_state;
481 wps->ap_setup_locked = hapd->conf->ap_setup_locked;
482 if (is_nil_uuid(hapd->conf->uuid)) {
483 uuid_gen_mac_addr(hapd->own_addr, wps->uuid);
484 wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC address",
485 wps->uuid, UUID_LEN);
486 } else
487 os_memcpy(wps->uuid, hapd->conf->uuid, UUID_LEN);
488 wps->ssid_len = hapd->conf->ssid.ssid_len;
489 os_memcpy(wps->ssid, hapd->conf->ssid.ssid, wps->ssid_len);
490 wps->ap = 1;
491 os_memcpy(wps->dev.mac_addr, hapd->own_addr, ETH_ALEN);
492 wps->dev.device_name = hapd->conf->device_name ?
493 os_strdup(hapd->conf->device_name) : NULL;
494 wps->dev.manufacturer = hapd->conf->manufacturer ?
495 os_strdup(hapd->conf->manufacturer) : NULL;
496 wps->dev.model_name = hapd->conf->model_name ?
497 os_strdup(hapd->conf->model_name) : NULL;
498 wps->dev.model_number = hapd->conf->model_number ?
499 os_strdup(hapd->conf->model_number) : NULL;
500 wps->dev.serial_number = hapd->conf->serial_number ?
501 os_strdup(hapd->conf->serial_number) : NULL;
502 wps->config_methods =
503 wps_config_methods_str2bin(hapd->conf->config_methods);
504 if (hapd->conf->device_type &&
505 wps_dev_type_str2bin(hapd->conf->device_type,
506 wps->dev.pri_dev_type) < 0) {
507 wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
508 os_free(wps);
509 return -1;
510 }
511 wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version);
512 wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
513 WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
514
515 if (conf->wpa & WPA_PROTO_RSN) {
516 if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
517 wps->auth_types |= WPS_AUTH_WPA2PSK;
518 if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
519 wps->auth_types |= WPS_AUTH_WPA2;
520
521 if (conf->rsn_pairwise & WPA_CIPHER_CCMP)
522 wps->encr_types |= WPS_ENCR_AES;
523 if (conf->rsn_pairwise & WPA_CIPHER_TKIP)
524 wps->encr_types |= WPS_ENCR_TKIP;
525 }
526
527 if (conf->wpa & WPA_PROTO_WPA) {
528 if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
529 wps->auth_types |= WPS_AUTH_WPAPSK;
530 if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
531 wps->auth_types |= WPS_AUTH_WPA;
532
533 if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
534 wps->encr_types |= WPS_ENCR_AES;
535 if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
536 wps->encr_types |= WPS_ENCR_TKIP;
537 }
538
539 if (conf->ssid.security_policy == SECURITY_PLAINTEXT) {
540 wps->encr_types |= WPS_ENCR_NONE;
541 wps->auth_types |= WPS_AUTH_OPEN;
542 } else if (conf->ssid.security_policy == SECURITY_STATIC_WEP) {
543 wps->encr_types |= WPS_ENCR_WEP;
544 if (conf->auth_algs & WPA_AUTH_ALG_OPEN)
545 wps->auth_types |= WPS_AUTH_OPEN;
546 if (conf->auth_algs & WPA_AUTH_ALG_SHARED)
547 wps->auth_types |= WPS_AUTH_SHARED;
548 } else if (conf->ssid.security_policy == SECURITY_IEEE_802_1X) {
549 wps->auth_types |= WPS_AUTH_OPEN;
550 if (conf->default_wep_key_len)
551 wps->encr_types |= WPS_ENCR_WEP;
552 else
553 wps->encr_types |= WPS_ENCR_NONE;
554 }
555
556 if (conf->ssid.wpa_psk_file) {
557 /* Use per-device PSKs */
558 } else if (conf->ssid.wpa_passphrase) {
559 wps->network_key = (u8 *) os_strdup(conf->ssid.wpa_passphrase);
560 wps->network_key_len = os_strlen(conf->ssid.wpa_passphrase);
561 } else if (conf->ssid.wpa_psk) {
562 wps->network_key = os_malloc(2 * PMK_LEN + 1);
563 if (wps->network_key == NULL) {
564 os_free(wps);
565 return -1;
566 }
567 wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1,
568 conf->ssid.wpa_psk->psk, PMK_LEN);
569 wps->network_key_len = 2 * PMK_LEN;
570 } else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) {
571 wps->network_key = os_malloc(conf->ssid.wep.len[0]);
572 if (wps->network_key == NULL) {
573 os_free(wps);
574 return -1;
575 }
576 os_memcpy(wps->network_key, conf->ssid.wep.key[0],
577 conf->ssid.wep.len[0]);
578 wps->network_key_len = conf->ssid.wep.len[0];
579 }
580
581 if (conf->ssid.wpa_psk) {
582 os_memcpy(wps->psk, conf->ssid.wpa_psk->psk, PMK_LEN);
583 wps->psk_set = 1;
584 }
585
586 if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) {
587 /* Override parameters to enable security by default */
588 wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
589 wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
590 }
591
592 wps->ap_settings = conf->ap_settings;
593 wps->ap_settings_len = conf->ap_settings_len;
594
595 cfg.new_psk_cb = hostapd_wps_new_psk_cb;
596 cfg.set_ie_cb = hostapd_wps_set_ie_cb;
597 cfg.pin_needed_cb = hostapd_wps_pin_needed_cb;
598 cfg.reg_success_cb = hostapd_wps_reg_success_cb;
599 cfg.cb_ctx = hapd;
600 cfg.skip_cred_build = conf->skip_cred_build;
601 cfg.extra_cred = conf->extra_cred;
602 cfg.extra_cred_len = conf->extra_cred_len;
603 cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) &&
604 conf->skip_cred_build;
605 if (conf->ssid.security_policy == SECURITY_STATIC_WEP)
606 cfg.static_wep_only = 1;
607
608 wps->registrar = wps_registrar_init(wps, &cfg);
609 if (wps->registrar == NULL) {
610 printf("Failed to initialize WPS Registrar\n");
611 os_free(wps->network_key);
612 os_free(wps);
613 return -1;
614 }
615
616 #ifdef CONFIG_WPS_UPNP
617 wps->friendly_name = hapd->conf->friendly_name;
618 wps->manufacturer_url = hapd->conf->manufacturer_url;
619 wps->model_description = hapd->conf->model_description;
620 wps->model_url = hapd->conf->model_url;
621 wps->upc = hapd->conf->upc;
622
623 if (hostapd_wps_upnp_init(hapd, wps) < 0) {
624 wpa_printf(MSG_ERROR, "Failed to initialize WPS UPnP");
625 wps_registrar_deinit(wps->registrar);
626 os_free(wps->network_key);
627 os_free(wps);
628 return -1;
629 }
630 #endif /* CONFIG_WPS_UPNP */
631
632 hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd);
633
634 hapd->wps = wps;
635
636 return 0;
637 }
638
639
640 void hostapd_deinit_wps(struct hostapd_data *hapd)
641 {
642 if (hapd->wps == NULL)
643 return;
644 #ifdef CONFIG_WPS_UPNP
645 hostapd_wps_upnp_deinit(hapd);
646 #endif /* CONFIG_WPS_UPNP */
647 wps_registrar_deinit(hapd->wps->registrar);
648 os_free(hapd->wps->network_key);
649 wps_device_data_free(&hapd->wps->dev);
650 wpabuf_free(hapd->wps->dh_pubkey);
651 wpabuf_free(hapd->wps->dh_privkey);
652 wpabuf_free(hapd->wps->oob_conf.pubkey_hash);
653 wpabuf_free(hapd->wps->oob_conf.dev_password);
654 wps_free_pending_msgs(hapd->wps->upnp_msgs);
655 os_free(hapd->wps);
656 hapd->wps = NULL;
657 hostapd_wps_clear_ies(hapd);
658 }
659
660
661 int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
662 const char *pin, int timeout)
663 {
664 u8 u[UUID_LEN];
665 int any = 0;
666
667 if (hapd->wps == NULL)
668 return -1;
669 if (os_strcmp(uuid, "any") == 0)
670 any = 1;
671 else if (uuid_str2bin(uuid, u))
672 return -1;
673 return wps_registrar_add_pin(hapd->wps->registrar, any ? NULL : u,
674 (const u8 *) pin, os_strlen(pin),
675 timeout);
676 }
677
678
679 int hostapd_wps_button_pushed(struct hostapd_data *hapd)
680 {
681 if (hapd->wps == NULL)
682 return -1;
683 return wps_registrar_button_pushed(hapd->wps->registrar);
684 }
685
686
687 #ifdef CONFIG_WPS_OOB
688 int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
689 char *path, char *method, char *name)
690 {
691 struct wps_context *wps = hapd->wps;
692 struct oob_device_data *oob_dev;
693
694 oob_dev = wps_get_oob_device(device_type);
695 if (oob_dev == NULL)
696 return -1;
697 oob_dev->device_path = path;
698 oob_dev->device_name = name;
699 wps->oob_conf.oob_method = wps_get_oob_method(method);
700
701 if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) {
702 /*
703 * Use pre-configured DH keys in order to be able to write the
704 * key hash into the OOB file.
705 */
706 wpabuf_free(wps->dh_pubkey);
707 wpabuf_free(wps->dh_privkey);
708 wps->dh_privkey = NULL;
709 wps->dh_pubkey = dh_init(dh_groups_get(WPS_DH_GROUP),
710 &wps->dh_privkey);
711 wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192);
712 if (wps->dh_pubkey == NULL) {
713 wpa_printf(MSG_ERROR, "WPS: Failed to initialize "
714 "Diffie-Hellman handshake");
715 return -1;
716 }
717 }
718
719 if (wps_process_oob(wps, oob_dev, 1) < 0)
720 goto error;
721
722 if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ||
723 wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) &&
724 hostapd_wps_add_pin(hapd, "any",
725 wpabuf_head(wps->oob_conf.dev_password), 0) <
726 0)
727 goto error;
728
729 return 0;
730
731 error:
732 wpabuf_free(wps->dh_pubkey);
733 wps->dh_pubkey = NULL;
734 wpabuf_free(wps->dh_privkey);
735 wps->dh_privkey = NULL;
736 return -1;
737 }
738 #endif /* CONFIG_WPS_OOB */
739
740
741 static void hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
742 const u8 *ie, size_t ie_len)
743 {
744 struct hostapd_data *hapd = ctx;
745 struct wpabuf *wps_ie;
746
747 if (hapd->wps == NULL)
748 return;
749
750 wps_ie = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
751 if (wps_ie == NULL)
752 return;
753
754 if (wpabuf_len(wps_ie) > 0) {
755 wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie);
756 #ifdef CONFIG_WPS_UPNP
757 /* FIX: what exactly should be included in the WLANEvent?
758 * WPS attributes? Full ProbeReq frame? */
759 upnp_wps_device_send_wlan_event(hapd->wps_upnp, addr,
760 UPNP_WPS_WLANEVENT_TYPE_PROBE,
761 wps_ie);
762 #endif /* CONFIG_WPS_UPNP */
763 }
764
765 wpabuf_free(wps_ie);
766 }
767
768
769 #ifdef CONFIG_WPS_UPNP
770
771 static int hostapd_rx_req_put_wlan_response(
772 void *priv, enum upnp_wps_wlanevent_type ev_type,
773 const u8 *mac_addr, const struct wpabuf *msg,
774 enum wps_msg_type msg_type)
775 {
776 struct hostapd_data *hapd = priv;
777 struct sta_info *sta;
778 struct upnp_pending_message *p;
779
780 wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr="
781 MACSTR, ev_type, MAC2STR(mac_addr));
782 wpa_hexdump(MSG_MSGDUMP, "WPS UPnP: PutWLANResponse NewMessage",
783 wpabuf_head(msg), wpabuf_len(msg));
784 if (ev_type != UPNP_WPS_WLANEVENT_TYPE_EAP) {
785 wpa_printf(MSG_DEBUG, "WPS UPnP: Ignored unexpected "
786 "PutWLANResponse WLANEventType %d", ev_type);
787 return -1;
788 }
789
790 /*
791 * EAP response to ongoing to WPS Registration. Send it to EAP-WSC
792 * server implementation for delivery to the peer.
793 */
794
795 sta = ap_get_sta(hapd, mac_addr);
796 if (!sta) {
797 /*
798 * Workaround - Intel wsccmd uses bogus NewWLANEventMAC:
799 * Pick STA that is in an ongoing WPS registration without
800 * checking the MAC address.
801 */
802 wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found based "
803 "on NewWLANEventMAC; try wildcard match");
804 for (sta = hapd->sta_list; sta; sta = sta->next) {
805 if (sta->eapol_sm && (sta->flags & WLAN_STA_WPS))
806 break;
807 }
808 }
809
810 if (!sta) {
811 wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found");
812 return 0;
813 }
814
815 p = os_zalloc(sizeof(*p));
816 if (p == NULL)
817 return -1;
818 os_memcpy(p->addr, sta->addr, ETH_ALEN);
819 p->msg = wpabuf_dup(msg);
820 p->type = msg_type;
821 p->next = hapd->wps->upnp_msgs;
822 hapd->wps->upnp_msgs = p;
823
824 return eapol_auth_eap_pending_cb(sta->eapol_sm, sta->eapol_sm->eap);
825 }
826
827
828 static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
829 struct wps_context *wps)
830 {
831 struct upnp_wps_device_ctx *ctx;
832
833 if (!hapd->conf->upnp_iface)
834 return 0;
835 ctx = os_zalloc(sizeof(*ctx));
836 if (ctx == NULL)
837 return -1;
838
839 ctx->rx_req_put_wlan_response = hostapd_rx_req_put_wlan_response;
840 if (hapd->conf->ap_pin)
841 ctx->ap_pin = os_strdup(hapd->conf->ap_pin);
842
843 hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd);
844 if (hapd->wps_upnp == NULL) {
845 os_free(ctx);
846 return -1;
847 }
848 wps->wps_upnp = hapd->wps_upnp;
849
850 if (upnp_wps_device_start(hapd->wps_upnp, hapd->conf->upnp_iface)) {
851 upnp_wps_device_deinit(hapd->wps_upnp);
852 hapd->wps_upnp = NULL;
853 return -1;
854 }
855
856 return 0;
857 }
858
859
860 static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd)
861 {
862 upnp_wps_device_deinit(hapd->wps_upnp);
863 }
864
865 #endif /* CONFIG_WPS_UPNP */
866
867
868 int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
869 char *buf, size_t buflen)
870 {
871 return wps_registrar_get_info(hapd->wps->registrar, addr, buf, buflen);
872 }