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