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