Branch data Line data Source code
1 : : /*
2 : : * Wi-Fi Protected Setup
3 : : * Copyright (c) 2007-2009, 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 "includes.h"
10 : :
11 : : #include "common.h"
12 : : #include "crypto/dh_group5.h"
13 : : #include "common/ieee802_11_defs.h"
14 : : #include "wps_i.h"
15 : : #include "wps_dev_attr.h"
16 : :
17 : :
18 : : #ifdef CONFIG_WPS_TESTING
19 : : int wps_version_number = 0x20;
20 : : int wps_testing_dummy_cred = 0;
21 : : #endif /* CONFIG_WPS_TESTING */
22 : :
23 : :
24 : : /**
25 : : * wps_init - Initialize WPS Registration protocol data
26 : : * @cfg: WPS configuration
27 : : * Returns: Pointer to allocated data or %NULL on failure
28 : : *
29 : : * This function is used to initialize WPS data for a registration protocol
30 : : * instance (i.e., each run of registration protocol as a Registrar of
31 : : * Enrollee. The caller is responsible for freeing this data after the
32 : : * registration run has been completed by calling wps_deinit().
33 : : */
34 : 124 : struct wps_data * wps_init(const struct wps_config *cfg)
35 : : {
36 : 124 : struct wps_data *data = os_zalloc(sizeof(*data));
37 [ - + ]: 124 : if (data == NULL)
38 : 0 : return NULL;
39 : 124 : data->wps = cfg->wps;
40 : 124 : data->registrar = cfg->registrar;
41 [ + + ]: 124 : if (cfg->registrar) {
42 : 60 : os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN);
43 : : } else {
44 : 64 : os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN);
45 : 64 : os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN);
46 : : }
47 [ + + ]: 124 : if (cfg->pin) {
48 : 56 : data->dev_pw_id = cfg->dev_pw_id;
49 : 56 : data->dev_password = os_malloc(cfg->pin_len);
50 [ - + ]: 56 : if (data->dev_password == NULL) {
51 : 0 : os_free(data);
52 : 0 : return NULL;
53 : : }
54 : 56 : os_memcpy(data->dev_password, cfg->pin, cfg->pin_len);
55 : 56 : data->dev_password_len = cfg->pin_len;
56 : 56 : wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password",
57 : 56 : data->dev_password, data->dev_password_len);
58 : : }
59 : :
60 : : #ifdef CONFIG_WPS_NFC
61 [ + + ][ - + ]: 124 : if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) {
[ # # ]
62 : : /* Keep AP PIN as alternative Device Password */
63 : 0 : data->alt_dev_pw_id = data->dev_pw_id;
64 : 0 : data->alt_dev_password = data->dev_password;
65 : 0 : data->alt_dev_password_len = data->dev_password_len;
66 : :
67 : 0 : data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id;
68 : 0 : data->dev_password =
69 : 0 : os_malloc(wpabuf_len(cfg->wps->ap_nfc_dev_pw));
70 [ # # ]: 0 : if (data->dev_password == NULL) {
71 : 0 : os_free(data);
72 : 0 : return NULL;
73 : : }
74 : 0 : os_memcpy(data->dev_password,
75 : : wpabuf_head(cfg->wps->ap_nfc_dev_pw),
76 : : wpabuf_len(cfg->wps->ap_nfc_dev_pw));
77 : 0 : data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw);
78 : 0 : wpa_hexdump_key(MSG_DEBUG, "WPS: NFC dev_password",
79 : 0 : data->dev_password, data->dev_password_len);
80 : : }
81 : : #endif /* CONFIG_WPS_NFC */
82 : :
83 : 124 : data->pbc = cfg->pbc;
84 [ + + ]: 124 : if (cfg->pbc) {
85 : : /* Use special PIN '00000000' for PBC */
86 : 12 : data->dev_pw_id = DEV_PW_PUSHBUTTON;
87 : 12 : os_free(data->dev_password);
88 : 12 : data->dev_password = (u8 *) os_strdup("00000000");
89 [ - + ]: 12 : if (data->dev_password == NULL) {
90 : 0 : os_free(data);
91 : 0 : return NULL;
92 : : }
93 : 12 : data->dev_password_len = 8;
94 : : }
95 : :
96 [ + + ]: 124 : data->state = data->registrar ? RECV_M1 : SEND_M1;
97 : :
98 [ + + ]: 124 : if (cfg->assoc_wps_ie) {
99 : : struct wps_parse_attr attr;
100 : 52 : wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq",
101 : : cfg->assoc_wps_ie);
102 [ - + ]: 52 : if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) {
103 : 0 : wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE "
104 : : "from (Re)AssocReq");
105 [ - + ]: 52 : } else if (attr.request_type == NULL) {
106 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute "
107 : : "in (Re)AssocReq WPS IE");
108 : : } else {
109 : 52 : wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE "
110 : : "in (Re)AssocReq WPS IE): %d",
111 : 52 : *attr.request_type);
112 : 52 : data->request_type = *attr.request_type;
113 : : }
114 : : }
115 : :
116 [ + + ]: 124 : if (cfg->new_ap_settings) {
117 : 3 : data->new_ap_settings =
118 : 3 : os_malloc(sizeof(*data->new_ap_settings));
119 [ - + ]: 3 : if (data->new_ap_settings == NULL) {
120 : 0 : os_free(data->dev_password);
121 : 0 : os_free(data);
122 : 0 : return NULL;
123 : : }
124 : 3 : os_memcpy(data->new_ap_settings, cfg->new_ap_settings,
125 : : sizeof(*data->new_ap_settings));
126 : : }
127 : :
128 [ + + ]: 124 : if (cfg->peer_addr)
129 : 54 : os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN);
130 [ + + ]: 124 : if (cfg->p2p_dev_addr)
131 : 50 : os_memcpy(data->p2p_dev_addr, cfg->p2p_dev_addr, ETH_ALEN);
132 : :
133 : 124 : data->use_psk_key = cfg->use_psk_key;
134 : 124 : data->pbc_in_m1 = cfg->pbc_in_m1;
135 : :
136 : 124 : return data;
137 : : }
138 : :
139 : :
140 : : /**
141 : : * wps_deinit - Deinitialize WPS Registration protocol data
142 : : * @data: WPS Registration protocol data from wps_init()
143 : : */
144 : 124 : void wps_deinit(struct wps_data *data)
145 : : {
146 : : #ifdef CONFIG_WPS_NFC
147 [ + + ][ + + ]: 124 : if (data->registrar && data->nfc_pw_token)
148 : 1 : wps_registrar_remove_nfc_pw_token(data->wps->registrar,
149 : : data->nfc_pw_token);
150 : : #endif /* CONFIG_WPS_NFC */
151 : :
152 [ - + ]: 124 : if (data->wps_pin_revealed) {
153 : 0 : wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and "
154 : : "negotiation failed");
155 [ # # ]: 0 : if (data->registrar)
156 : 0 : wps_registrar_invalidate_pin(data->wps->registrar,
157 : 0 : data->uuid_e);
158 [ + + ]: 124 : } else if (data->registrar)
159 : 60 : wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e);
160 : :
161 : 124 : wpabuf_free(data->dh_privkey);
162 : 124 : wpabuf_free(data->dh_pubkey_e);
163 : 124 : wpabuf_free(data->dh_pubkey_r);
164 : 124 : wpabuf_free(data->last_msg);
165 : 124 : os_free(data->dev_password);
166 : 124 : os_free(data->alt_dev_password);
167 : 124 : os_free(data->new_psk);
168 : 124 : wps_device_data_free(&data->peer_dev);
169 : 124 : os_free(data->new_ap_settings);
170 : 124 : dh5_free(data->dh_ctx);
171 : 124 : os_free(data->nfc_pw_token);
172 : 124 : os_free(data);
173 : 124 : }
174 : :
175 : :
176 : : /**
177 : : * wps_process_msg - Process a WPS message
178 : : * @wps: WPS Registration protocol data from wps_init()
179 : : * @op_code: Message OP Code
180 : : * @msg: Message data
181 : : * Returns: Processing result
182 : : *
183 : : * This function is used to process WPS messages with OP Codes WSC_ACK,
184 : : * WSC_NACK, WSC_MSG, and WSC_Done. The caller (e.g., EAP server/peer) is
185 : : * responsible for reassembling the messages before calling this function.
186 : : * Response to this message is built by calling wps_get_msg().
187 : : */
188 : 549 : enum wps_process_res wps_process_msg(struct wps_data *wps,
189 : : enum wsc_op_code op_code,
190 : : const struct wpabuf *msg)
191 : : {
192 [ + + ]: 549 : if (wps->registrar)
193 : 297 : return wps_registrar_process_msg(wps, op_code, msg);
194 : : else
195 : 549 : return wps_enrollee_process_msg(wps, op_code, msg);
196 : : }
197 : :
198 : :
199 : : /**
200 : : * wps_get_msg - Build a WPS message
201 : : * @wps: WPS Registration protocol data from wps_init()
202 : : * @op_code: Buffer for returning message OP Code
203 : : * Returns: The generated WPS message or %NULL on failure
204 : : *
205 : : * This function is used to build a response to a message processed by calling
206 : : * wps_process_msg(). The caller is responsible for freeing the buffer.
207 : : */
208 : 559 : struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code)
209 : : {
210 [ + + ]: 559 : if (wps->registrar)
211 : 243 : return wps_registrar_get_msg(wps, op_code);
212 : : else
213 : 559 : return wps_enrollee_get_msg(wps, op_code);
214 : : }
215 : :
216 : :
217 : : /**
218 : : * wps_is_selected_pbc_registrar - Check whether WPS IE indicates active PBC
219 : : * @msg: WPS IE contents from Beacon or Probe Response frame
220 : : * Returns: 1 if PBC Registrar is active, 0 if not
221 : : */
222 : 350 : int wps_is_selected_pbc_registrar(const struct wpabuf *msg)
223 : : {
224 : : struct wps_parse_attr attr;
225 : :
226 : : /*
227 : : * In theory, this could also verify that attr.sel_reg_config_methods
228 : : * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations
229 : : * do not set Selected Registrar Config Methods attribute properly, so
230 : : * it is safer to just use Device Password ID here.
231 : : */
232 : :
233 [ + - ][ + + ]: 350 : if (wps_parse_msg(msg, &attr) < 0 ||
234 [ + - ][ + - ]: 272 : !attr.selected_registrar || *attr.selected_registrar == 0 ||
235 [ + + ]: 272 : !attr.dev_password_id ||
236 : 272 : WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON)
237 : 289 : return 0;
238 : :
239 : : #ifdef CONFIG_WPS_STRICT
240 [ + - - + ]: 122 : if (!attr.sel_reg_config_methods ||
241 : 61 : !(WPA_GET_BE16(attr.sel_reg_config_methods) &
242 : : WPS_CONFIG_PUSHBUTTON))
243 : 0 : return 0;
244 : : #endif /* CONFIG_WPS_STRICT */
245 : :
246 : 350 : return 1;
247 : : }
248 : :
249 : :
250 : 96 : static int is_selected_pin_registrar(struct wps_parse_attr *attr)
251 : : {
252 : : /*
253 : : * In theory, this could also verify that attr.sel_reg_config_methods
254 : : * includes WPS_CONFIG_LABEL, WPS_CONFIG_DISPLAY, or WPS_CONFIG_KEYPAD,
255 : : * but some deployed AP implementations do not set Selected Registrar
256 : : * Config Methods attribute properly, so it is safer to just use
257 : : * Device Password ID here.
258 : : */
259 : :
260 [ + + ][ - + ]: 96 : if (!attr->selected_registrar || *attr->selected_registrar == 0)
261 : 74 : return 0;
262 : :
263 [ + - - + ]: 44 : if (attr->dev_password_id != NULL &&
264 : 22 : WPA_GET_BE16(attr->dev_password_id) == DEV_PW_PUSHBUTTON)
265 : 0 : return 0;
266 : :
267 : : #ifdef CONFIG_WPS_STRICT
268 [ + - - + ]: 44 : if (!attr->sel_reg_config_methods ||
269 : 22 : !(WPA_GET_BE16(attr->sel_reg_config_methods) &
270 : : (WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD)))
271 : 0 : return 0;
272 : : #endif /* CONFIG_WPS_STRICT */
273 : :
274 : 96 : return 1;
275 : : }
276 : :
277 : :
278 : : /**
279 : : * wps_is_selected_pin_registrar - Check whether WPS IE indicates active PIN
280 : : * @msg: WPS IE contents from Beacon or Probe Response frame
281 : : * Returns: 1 if PIN Registrar is active, 0 if not
282 : : */
283 : 96 : int wps_is_selected_pin_registrar(const struct wpabuf *msg)
284 : : {
285 : : struct wps_parse_attr attr;
286 : :
287 [ - + ]: 96 : if (wps_parse_msg(msg, &attr) < 0)
288 : 0 : return 0;
289 : :
290 : 96 : return is_selected_pin_registrar(&attr);
291 : : }
292 : :
293 : :
294 : : /**
295 : : * wps_is_addr_authorized - Check whether WPS IE authorizes MAC address
296 : : * @msg: WPS IE contents from Beacon or Probe Response frame
297 : : * @addr: MAC address to search for
298 : : * @ver1_compat: Whether to use version 1 compatibility mode
299 : : * Returns: 2 if the specified address is explicit authorized, 1 if address is
300 : : * authorized (broadcast), 0 if not
301 : : */
302 : 977 : int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
303 : : int ver1_compat)
304 : : {
305 : : struct wps_parse_attr attr;
306 : : unsigned int i;
307 : : const u8 *pos;
308 : 977 : const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
309 : :
310 [ - + ]: 977 : if (wps_parse_msg(msg, &attr) < 0)
311 : 0 : return 0;
312 : :
313 [ - + ][ # # ]: 977 : if (!attr.version2 && ver1_compat) {
314 : : /*
315 : : * Version 1.0 AP - AuthorizedMACs not used, so revert back to
316 : : * old mechanism of using SelectedRegistrar.
317 : : */
318 : 0 : return is_selected_pin_registrar(&attr);
319 : : }
320 : :
321 [ + + ]: 977 : if (!attr.authorized_macs)
322 : 341 : return 0;
323 : :
324 : 636 : pos = attr.authorized_macs;
325 [ + + ]: 676 : for (i = 0; i < attr.authorized_macs_len / ETH_ALEN; i++) {
326 [ + + ]: 636 : if (os_memcmp(pos, addr, ETH_ALEN) == 0)
327 : 286 : return 2;
328 [ + + ]: 350 : if (os_memcmp(pos, bcast, ETH_ALEN) == 0)
329 : 310 : return 1;
330 : 40 : pos += ETH_ALEN;
331 : : }
332 : :
333 : 977 : return 0;
334 : : }
335 : :
336 : :
337 : : /**
338 : : * wps_ap_priority_compar - Prioritize WPS IE from two APs
339 : : * @wps_a: WPS IE contents from Beacon or Probe Response frame
340 : : * @wps_b: WPS IE contents from Beacon or Probe Response frame
341 : : * Returns: 1 if wps_b is considered more likely selection for WPS
342 : : * provisioning, -1 if wps_a is considered more like, or 0 if no preference
343 : : */
344 : 360 : int wps_ap_priority_compar(const struct wpabuf *wps_a,
345 : : const struct wpabuf *wps_b)
346 : : {
347 : : struct wps_parse_attr attr_a, attr_b;
348 : : int sel_a, sel_b;
349 : :
350 [ + - ][ - + ]: 360 : if (wps_a == NULL || wps_parse_msg(wps_a, &attr_a) < 0)
351 : 0 : return 1;
352 [ + - ][ - + ]: 360 : if (wps_b == NULL || wps_parse_msg(wps_b, &attr_b) < 0)
353 : 0 : return -1;
354 : :
355 [ + + ][ + - ]: 360 : sel_a = attr_a.selected_registrar && *attr_a.selected_registrar != 0;
356 [ + + ][ + - ]: 360 : sel_b = attr_b.selected_registrar && *attr_b.selected_registrar != 0;
357 : :
358 [ + + ][ + + ]: 360 : if (sel_a && !sel_b)
359 : 12 : return -1;
360 [ + + ][ + + ]: 348 : if (!sel_a && sel_b)
361 : 166 : return 1;
362 : :
363 : 360 : return 0;
364 : : }
365 : :
366 : :
367 : : /**
368 : : * wps_get_uuid_e - Get UUID-E from WPS IE
369 : : * @msg: WPS IE contents from Beacon or Probe Response frame
370 : : * Returns: Pointer to UUID-E or %NULL if not included
371 : : *
372 : : * The returned pointer is to the msg contents and it remains valid only as
373 : : * long as the msg buffer is valid.
374 : : */
375 : 18 : const u8 * wps_get_uuid_e(const struct wpabuf *msg)
376 : : {
377 : : struct wps_parse_attr attr;
378 : :
379 [ - + ]: 18 : if (wps_parse_msg(msg, &attr) < 0)
380 : 0 : return NULL;
381 : 18 : return attr.uuid_e;
382 : : }
383 : :
384 : :
385 : : /**
386 : : * wps_is_20 - Check whether WPS attributes claim support for WPS 2.0
387 : : */
388 : 52 : int wps_is_20(const struct wpabuf *msg)
389 : : {
390 : : struct wps_parse_attr attr;
391 : :
392 [ + - ][ - + ]: 52 : if (msg == NULL || wps_parse_msg(msg, &attr) < 0)
393 : 0 : return 0;
394 : 52 : return attr.version2 != NULL;
395 : : }
396 : :
397 : :
398 : : /**
399 : : * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request
400 : : * @req_type: Value for Request Type attribute
401 : : * Returns: WPS IE or %NULL on failure
402 : : *
403 : : * The caller is responsible for freeing the buffer.
404 : : */
405 : 70 : struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type)
406 : : {
407 : : struct wpabuf *ie;
408 : : u8 *len;
409 : :
410 : 70 : wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association "
411 : : "Request");
412 : 70 : ie = wpabuf_alloc(100);
413 [ - + ]: 70 : if (ie == NULL)
414 : 0 : return NULL;
415 : :
416 : 70 : wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
417 : 70 : len = wpabuf_put(ie, 1);
418 : 70 : wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
419 : :
420 [ + - + - ]: 140 : if (wps_build_version(ie) ||
421 [ - + ]: 140 : wps_build_req_type(ie, req_type) ||
422 : 70 : wps_build_wfa_ext(ie, 0, NULL, 0)) {
423 : 0 : wpabuf_free(ie);
424 : 0 : return NULL;
425 : : }
426 : :
427 : 70 : *len = wpabuf_len(ie) - 2;
428 : :
429 : 70 : return ie;
430 : : }
431 : :
432 : :
433 : : /**
434 : : * wps_build_assoc_resp_ie - Build WPS IE for (Re)Association Response
435 : : * Returns: WPS IE or %NULL on failure
436 : : *
437 : : * The caller is responsible for freeing the buffer.
438 : : */
439 : 478 : struct wpabuf * wps_build_assoc_resp_ie(void)
440 : : {
441 : : struct wpabuf *ie;
442 : : u8 *len;
443 : :
444 : 478 : wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association "
445 : : "Response");
446 : 478 : ie = wpabuf_alloc(100);
447 [ - + ]: 478 : if (ie == NULL)
448 : 0 : return NULL;
449 : :
450 : 478 : wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
451 : 478 : len = wpabuf_put(ie, 1);
452 : 478 : wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
453 : :
454 [ + - + - ]: 956 : if (wps_build_version(ie) ||
455 [ - + ]: 956 : wps_build_resp_type(ie, WPS_RESP_AP) ||
456 : 478 : wps_build_wfa_ext(ie, 0, NULL, 0)) {
457 : 0 : wpabuf_free(ie);
458 : 0 : return NULL;
459 : : }
460 : :
461 : 478 : *len = wpabuf_len(ie) - 2;
462 : :
463 : 478 : return ie;
464 : : }
465 : :
466 : :
467 : : /**
468 : : * wps_build_probe_req_ie - Build WPS IE for Probe Request
469 : : * @pw_id: Password ID (DEV_PW_PUSHBUTTON for active PBC and DEV_PW_DEFAULT for
470 : : * most other use cases)
471 : : * @dev: Device attributes
472 : : * @uuid: Own UUID
473 : : * @req_type: Value for Request Type attribute
474 : : * @num_req_dev_types: Number of requested device types
475 : : * @req_dev_types: Requested device types (8 * num_req_dev_types octets) or
476 : : * %NULL if none
477 : : * Returns: WPS IE or %NULL on failure
478 : : *
479 : : * The caller is responsible for freeing the buffer.
480 : : */
481 : 896 : struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev,
482 : : const u8 *uuid,
483 : : enum wps_request_type req_type,
484 : : unsigned int num_req_dev_types,
485 : : const u8 *req_dev_types)
486 : : {
487 : : struct wpabuf *ie;
488 : :
489 : 896 : wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request");
490 : :
491 : 896 : ie = wpabuf_alloc(500);
492 [ - + ]: 896 : if (ie == NULL)
493 : 0 : return NULL;
494 : :
495 [ + - + - ]: 1792 : if (wps_build_version(ie) ||
496 [ + - ]: 1792 : wps_build_req_type(ie, req_type) ||
497 [ + - ]: 1792 : wps_build_config_methods(ie, dev->config_methods) ||
498 [ + - ]: 1792 : wps_build_uuid_e(ie, uuid) ||
499 [ + - ]: 1792 : wps_build_primary_dev_type(dev, ie) ||
500 [ + - ]: 1792 : wps_build_rf_bands(dev, ie, 0) ||
501 [ + - ]: 1792 : wps_build_assoc_state(NULL, ie) ||
502 [ + - ]: 1792 : wps_build_config_error(ie, WPS_CFG_NO_ERROR) ||
503 [ + - ]: 1792 : wps_build_dev_password_id(ie, pw_id) ||
504 : : #ifdef CONFIG_WPS2
505 [ + - ]: 1792 : wps_build_manufacturer(dev, ie) ||
506 [ + - ]: 1792 : wps_build_model_name(dev, ie) ||
507 [ + - ]: 1792 : wps_build_model_number(dev, ie) ||
508 [ + - ]: 1792 : wps_build_dev_name(dev, ie) ||
509 [ + - ]: 1792 : wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) ||
510 : : #endif /* CONFIG_WPS2 */
511 : 896 : wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types)
512 [ - + ]: 896 : ||
513 : 896 : wps_build_secondary_dev_type(dev, ie)
514 : : ) {
515 : 0 : wpabuf_free(ie);
516 : 0 : return NULL;
517 : : }
518 : :
519 : : #ifndef CONFIG_WPS2
520 : : if (dev->p2p && wps_build_dev_name(dev, ie)) {
521 : : wpabuf_free(ie);
522 : : return NULL;
523 : : }
524 : : #endif /* CONFIG_WPS2 */
525 : :
526 : 896 : return wps_ie_encapsulate(ie);
527 : : }
528 : :
529 : :
530 : 55 : void wps_free_pending_msgs(struct upnp_pending_message *msgs)
531 : : {
532 : : struct upnp_pending_message *p, *prev;
533 : 55 : p = msgs;
534 [ - + ]: 55 : while (p) {
535 : 0 : prev = p;
536 : 0 : p = p->next;
537 : 0 : wpabuf_free(prev->msg);
538 : 0 : os_free(prev);
539 : : }
540 : 55 : }
541 : :
542 : :
543 : 4 : int wps_attr_text(struct wpabuf *data, char *buf, char *end)
544 : : {
545 : : struct wps_parse_attr attr;
546 : 4 : char *pos = buf;
547 : : int ret;
548 : :
549 [ - + ]: 4 : if (wps_parse_msg(data, &attr) < 0)
550 : 0 : return -1;
551 : :
552 [ + - ]: 4 : if (attr.wps_state) {
553 [ - + ]: 4 : if (*attr.wps_state == WPS_STATE_NOT_CONFIGURED)
554 : 0 : ret = os_snprintf(pos, end - pos,
555 : : "wps_state=unconfigured\n");
556 [ + - ]: 4 : else if (*attr.wps_state == WPS_STATE_CONFIGURED)
557 : 4 : ret = os_snprintf(pos, end - pos,
558 : : "wps_state=configured\n");
559 : : else
560 : 0 : ret = 0;
561 [ + - ][ - + ]: 4 : if (ret < 0 || ret >= end - pos)
562 : 0 : return pos - buf;
563 : 4 : pos += ret;
564 : : }
565 : :
566 [ - + ][ # # ]: 4 : if (attr.ap_setup_locked && *attr.ap_setup_locked) {
567 : 0 : ret = os_snprintf(pos, end - pos,
568 : : "wps_ap_setup_locked=1\n");
569 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
570 : 0 : return pos - buf;
571 : 0 : pos += ret;
572 : : }
573 : :
574 [ + + ][ + - ]: 4 : if (attr.selected_registrar && *attr.selected_registrar) {
575 : 3 : ret = os_snprintf(pos, end - pos,
576 : : "wps_selected_registrar=1\n");
577 [ + - ][ - + ]: 3 : if (ret < 0 || ret >= end - pos)
578 : 0 : return pos - buf;
579 : 3 : pos += ret;
580 : : }
581 : :
582 [ + + ]: 4 : if (attr.dev_password_id) {
583 : 3 : ret = os_snprintf(pos, end - pos,
584 : : "wps_device_password_id=%u\n",
585 : 3 : WPA_GET_BE16(attr.dev_password_id));
586 [ + - ][ - + ]: 3 : if (ret < 0 || ret >= end - pos)
587 : 0 : return pos - buf;
588 : 3 : pos += ret;
589 : : }
590 : :
591 [ + + ]: 4 : if (attr.sel_reg_config_methods) {
592 : 3 : ret = os_snprintf(pos, end - pos,
593 : : "wps_selected_registrar_config_methods="
594 : : "0x%04x\n",
595 : 3 : WPA_GET_BE16(attr.sel_reg_config_methods));
596 [ + - ][ - + ]: 3 : if (ret < 0 || ret >= end - pos)
597 : 0 : return pos - buf;
598 : 3 : pos += ret;
599 : : }
600 : :
601 [ + - ]: 4 : if (attr.primary_dev_type) {
602 : : char devtype[WPS_DEV_TYPE_BUFSIZE];
603 : 4 : ret = os_snprintf(pos, end - pos,
604 : : "wps_primary_device_type=%s\n",
605 : : wps_dev_type_bin2str(attr.primary_dev_type,
606 : : devtype,
607 : : sizeof(devtype)));
608 [ + - ][ - + ]: 4 : if (ret < 0 || ret >= end - pos)
609 : 0 : return pos - buf;
610 : 4 : pos += ret;
611 : : }
612 : :
613 [ + - ]: 4 : if (attr.dev_name) {
614 : 4 : char *str = os_malloc(attr.dev_name_len + 1);
615 : : size_t i;
616 [ - + ]: 4 : if (str == NULL)
617 : 0 : return pos - buf;
618 [ + + ]: 36 : for (i = 0; i < attr.dev_name_len; i++) {
619 [ - + ]: 32 : if (attr.dev_name[i] < 32)
620 : 0 : str[i] = '_';
621 : : else
622 : 32 : str[i] = attr.dev_name[i];
623 : : }
624 : 4 : str[i] = '\0';
625 : 4 : ret = os_snprintf(pos, end - pos, "wps_device_name=%s\n", str);
626 : 4 : os_free(str);
627 [ + - ][ - + ]: 4 : if (ret < 0 || ret >= end - pos)
628 : 0 : return pos - buf;
629 : 4 : pos += ret;
630 : : }
631 : :
632 [ + - ]: 4 : if (attr.config_methods) {
633 : 4 : ret = os_snprintf(pos, end - pos,
634 : : "wps_config_methods=0x%04x\n",
635 : 4 : WPA_GET_BE16(attr.config_methods));
636 [ + - ][ - + ]: 4 : if (ret < 0 || ret >= end - pos)
637 : 0 : return pos - buf;
638 : 4 : pos += ret;
639 : : }
640 : :
641 : 4 : return pos - buf;
642 : : }
643 : :
644 : :
645 : 0 : const char * wps_ei_str(enum wps_error_indication ei)
646 : : {
647 [ # # # # : 0 : switch (ei) {
# ]
648 : : case WPS_EI_NO_ERROR:
649 : 0 : return "No Error";
650 : : case WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED:
651 : 0 : return "TKIP Only Prohibited";
652 : : case WPS_EI_SECURITY_WEP_PROHIBITED:
653 : 0 : return "WEP Prohibited";
654 : : case WPS_EI_AUTH_FAILURE:
655 : 0 : return "Authentication Failure";
656 : : default:
657 : 0 : return "Unknown";
658 : : }
659 : : }
|