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