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