Branch data Line data Source code
1 : : /*
2 : : * Wi-Fi Protected Setup - attribute parsing
3 : : * Copyright (c) 2008, 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 "wps_defs.h"
13 : : #include "wps_attr_parse.h"
14 : :
15 : : #ifndef CONFIG_WPS_STRICT
16 : : #define WPS_WORKAROUNDS
17 : : #endif /* CONFIG_WPS_STRICT */
18 : :
19 : :
20 : 7681 : static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
21 : : u8 id, u8 len, const u8 *pos)
22 : : {
23 : 7681 : wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u",
24 : : id, len);
25 [ + + + + : 7681 : switch (id) {
+ + ]
26 : : case WFA_ELEM_VERSION2:
27 [ + + ]: 5336 : if (len != 1) {
28 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
29 : : "%u", len);
30 : 1 : return -1;
31 : : }
32 : 5335 : attr->version2 = pos;
33 : 5335 : break;
34 : : case WFA_ELEM_AUTHORIZEDMACS:
35 : 863 : attr->authorized_macs = pos;
36 : 863 : attr->authorized_macs_len = len;
37 : 863 : break;
38 : : case WFA_ELEM_NETWORK_KEY_SHAREABLE:
39 [ + + ]: 2 : if (len != 1) {
40 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
41 : : "Shareable length %u", len);
42 : 1 : return -1;
43 : : }
44 : 1 : attr->network_key_shareable = pos;
45 : 1 : break;
46 : : case WFA_ELEM_REQUEST_TO_ENROLL:
47 [ + + ]: 1476 : if (len != 1) {
48 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
49 : : "length %u", len);
50 : 1 : return -1;
51 : : }
52 : 1475 : attr->request_to_enroll = pos;
53 : 1475 : break;
54 : : case WFA_ELEM_SETTINGS_DELAY_TIME:
55 [ + + ]: 2 : if (len != 1) {
56 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
57 : : "Time length %u", len);
58 : 1 : return -1;
59 : : }
60 : 1 : attr->settings_delay_time = pos;
61 : 1 : break;
62 : : default:
63 : 2 : wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
64 : : "Extension subelement %u", id);
65 : 2 : break;
66 : : }
67 : :
68 : 7681 : return 0;
69 : : }
70 : :
71 : :
72 : 5342 : static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
73 : : u16 len)
74 : : {
75 : 5342 : const u8 *end = pos + len;
76 : : u8 id, elen;
77 : :
78 [ + + ]: 13019 : while (pos + 2 <= end) {
79 : 7682 : id = *pos++;
80 : 7682 : elen = *pos++;
81 [ + + ]: 7682 : if (pos + elen > end)
82 : 1 : break;
83 [ + + ]: 7681 : if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
84 : 4 : return -1;
85 : 7677 : pos += elen;
86 : : }
87 : :
88 : 5342 : return 0;
89 : : }
90 : :
91 : :
92 : 5373 : static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
93 : : u16 len)
94 : : {
95 : : u32 vendor_id;
96 : :
97 [ + + ]: 5373 : if (len < 3) {
98 : 3 : wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension");
99 : 3 : return 0;
100 : : }
101 : :
102 : 5370 : vendor_id = WPA_GET_BE24(pos);
103 [ + + ]: 5370 : switch (vendor_id) {
104 : : case WPS_VENDOR_ID_WFA:
105 : 5342 : return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3);
106 : : }
107 : :
108 : : /* Handle unknown vendor extensions */
109 : :
110 : 28 : wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)",
111 : : vendor_id);
112 : :
113 [ + + ]: 28 : if (len > WPS_MAX_VENDOR_EXT_LEN) {
114 : 1 : wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)",
115 : : len);
116 : 1 : return -1;
117 : : }
118 : :
119 [ + + ]: 27 : if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) {
120 : 1 : wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension "
121 : : "attribute (max %d vendor extensions)",
122 : : MAX_WPS_PARSE_VENDOR_EXT);
123 : 1 : return -1;
124 : : }
125 : 26 : attr->vendor_ext[attr->num_vendor_ext] = pos;
126 : 26 : attr->vendor_ext_len[attr->num_vendor_ext] = len;
127 : 26 : attr->num_vendor_ext++;
128 : :
129 : 5373 : return 0;
130 : : }
131 : :
132 : :
133 : 65955 : static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
134 : : const u8 *pos, u16 len)
135 : : {
136 [ + + + + : 65955 : switch (type) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + ]
137 : : case ATTR_VERSION:
138 [ + + ]: 5319 : if (len != 1) {
139 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
140 : : len);
141 : 1 : return -1;
142 : : }
143 : 5318 : attr->version = pos;
144 : 5318 : break;
145 : : case ATTR_MSG_TYPE:
146 [ + + ]: 1292 : if (len != 1) {
147 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
148 : : "length %u", len);
149 : 1 : return -1;
150 : : }
151 : 1291 : attr->msg_type = pos;
152 : 1291 : break;
153 : : case ATTR_ENROLLEE_NONCE:
154 [ + + ]: 900 : if (len != WPS_NONCE_LEN) {
155 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
156 : : "length %u", len);
157 : 1 : return -1;
158 : : }
159 : 899 : attr->enrollee_nonce = pos;
160 : 899 : break;
161 : : case ATTR_REGISTRAR_NONCE:
162 [ + + ]: 760 : if (len != WPS_NONCE_LEN) {
163 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
164 : : "length %u", len);
165 : 1 : return -1;
166 : : }
167 : 759 : attr->registrar_nonce = pos;
168 : 759 : break;
169 : : case ATTR_UUID_E:
170 [ + + ]: 3712 : if (len != WPS_UUID_LEN) {
171 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
172 : : len);
173 : 2 : return -1;
174 : : }
175 : 3710 : attr->uuid_e = pos;
176 : 3710 : break;
177 : : case ATTR_UUID_R:
178 [ + + ]: 185 : if (len != WPS_UUID_LEN) {
179 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
180 : : len);
181 : 2 : return -1;
182 : : }
183 : 183 : attr->uuid_r = pos;
184 : 183 : break;
185 : : case ATTR_AUTH_TYPE_FLAGS:
186 [ + + ]: 339 : if (len != 2) {
187 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
188 : : "Type Flags length %u", len);
189 : 1 : return -1;
190 : : }
191 : 338 : attr->auth_type_flags = pos;
192 : 338 : break;
193 : : case ATTR_ENCR_TYPE_FLAGS:
194 [ + + ]: 339 : if (len != 2) {
195 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
196 : : "Flags length %u", len);
197 : 1 : return -1;
198 : : }
199 : 338 : attr->encr_type_flags = pos;
200 : 338 : break;
201 : : case ATTR_CONN_TYPE_FLAGS:
202 [ + + ]: 339 : if (len != 1) {
203 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
204 : : "Flags length %u", len);
205 : 1 : return -1;
206 : : }
207 : 338 : attr->conn_type_flags = pos;
208 : 338 : break;
209 : : case ATTR_CONFIG_METHODS:
210 [ + + ]: 3934 : if (len != 2) {
211 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
212 : : "length %u", len);
213 : 1 : return -1;
214 : : }
215 : 3933 : attr->config_methods = pos;
216 : 3933 : break;
217 : : case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
218 [ + + ]: 871 : if (len != 2) {
219 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
220 : : "Registrar Config Methods length %u", len);
221 : 1 : return -1;
222 : : }
223 : 870 : attr->sel_reg_config_methods = pos;
224 : 870 : break;
225 : : case ATTR_PRIMARY_DEV_TYPE:
226 [ + + ]: 3850 : if (len != WPS_DEV_TYPE_LEN) {
227 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
228 : : "Type length %u", len);
229 : 1 : return -1;
230 : : }
231 : 3849 : attr->primary_dev_type = pos;
232 : 3849 : break;
233 : : case ATTR_RF_BANDS:
234 [ + + ]: 2098 : if (len != 1) {
235 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
236 : : "%u", len);
237 : 1 : return -1;
238 : : }
239 : 2097 : attr->rf_bands = pos;
240 : 2097 : break;
241 : : case ATTR_ASSOC_STATE:
242 [ + + ]: 2014 : if (len != 2) {
243 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
244 : : "length %u", len);
245 : 1 : return -1;
246 : : }
247 : 2013 : attr->assoc_state = pos;
248 : 2013 : break;
249 : : case ATTR_CONFIG_ERROR:
250 [ + + ]: 2061 : if (len != 2) {
251 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
252 : : "Error length %u", len);
253 : 1 : return -1;
254 : : }
255 : 2060 : attr->config_error = pos;
256 : 2060 : break;
257 : : case ATTR_DEV_PASSWORD_ID:
258 [ + + ]: 3018 : if (len != 2) {
259 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
260 : : "ID length %u", len);
261 : 1 : return -1;
262 : : }
263 : 3017 : attr->dev_password_id = pos;
264 : 3017 : break;
265 : : case ATTR_OOB_DEVICE_PASSWORD:
266 [ + + ][ + + ]: 48 : if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
267 : : len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
268 [ + + ]: 46 : WPS_OOB_DEVICE_PASSWORD_LEN ||
269 : : (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
270 [ + + ]: 35 : WPS_OOB_DEVICE_PASSWORD_MIN_LEN &&
271 : 35 : WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) !=
272 : : DEV_PW_NFC_CONNECTION_HANDOVER)) {
273 : 3 : wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
274 : : "Password length %u", len);
275 : 3 : return -1;
276 : : }
277 : 45 : attr->oob_dev_password = pos;
278 : 45 : attr->oob_dev_password_len = len;
279 : 45 : break;
280 : : case ATTR_OS_VERSION:
281 [ + + ]: 339 : if (len != 4) {
282 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
283 : : "%u", len);
284 : 1 : return -1;
285 : : }
286 : 338 : attr->os_version = pos;
287 : 338 : break;
288 : : case ATTR_WPS_STATE:
289 [ + + ]: 2011 : if (len != 1) {
290 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
291 : : "Setup State length %u", len);
292 : 1 : return -1;
293 : : }
294 : 2010 : attr->wps_state = pos;
295 : 2010 : break;
296 : : case ATTR_AUTHENTICATOR:
297 [ + + ]: 904 : if (len != WPS_AUTHENTICATOR_LEN) {
298 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
299 : : "length %u", len);
300 : 2 : return -1;
301 : : }
302 : 902 : attr->authenticator = pos;
303 : 902 : break;
304 : : case ATTR_R_HASH1:
305 [ + + ]: 132 : if (len != WPS_HASH_LEN) {
306 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
307 : : len);
308 : 2 : return -1;
309 : : }
310 : 130 : attr->r_hash1 = pos;
311 : 130 : break;
312 : : case ATTR_R_HASH2:
313 [ + + ]: 132 : if (len != WPS_HASH_LEN) {
314 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
315 : : len);
316 : 2 : return -1;
317 : : }
318 : 130 : attr->r_hash2 = pos;
319 : 130 : break;
320 : : case ATTR_E_HASH1:
321 [ + + ]: 142 : if (len != WPS_HASH_LEN) {
322 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
323 : : len);
324 : 2 : return -1;
325 : : }
326 : 140 : attr->e_hash1 = pos;
327 : 140 : break;
328 : : case ATTR_E_HASH2:
329 [ + + ]: 142 : if (len != WPS_HASH_LEN) {
330 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
331 : : len);
332 : 2 : return -1;
333 : : }
334 : 140 : attr->e_hash2 = pos;
335 : 140 : break;
336 : : case ATTR_R_SNONCE1:
337 [ + + ]: 125 : if (len != WPS_SECRET_NONCE_LEN) {
338 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
339 : : "%u", len);
340 : 2 : return -1;
341 : : }
342 : 123 : attr->r_snonce1 = pos;
343 : 123 : break;
344 : : case ATTR_R_SNONCE2:
345 [ + + ]: 119 : if (len != WPS_SECRET_NONCE_LEN) {
346 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
347 : : "%u", len);
348 : 2 : return -1;
349 : : }
350 : 117 : attr->r_snonce2 = pos;
351 : 117 : break;
352 : : case ATTR_E_SNONCE1:
353 [ + + ]: 119 : if (len != WPS_SECRET_NONCE_LEN) {
354 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
355 : : "%u", len);
356 : 2 : return -1;
357 : : }
358 : 117 : attr->e_snonce1 = pos;
359 : 117 : break;
360 : : case ATTR_E_SNONCE2:
361 [ + + ]: 116 : if (len != WPS_SECRET_NONCE_LEN) {
362 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
363 : : "%u", len);
364 : 2 : return -1;
365 : : }
366 : 114 : attr->e_snonce2 = pos;
367 : 114 : break;
368 : : case ATTR_KEY_WRAP_AUTH:
369 [ + + ]: 582 : if (len != WPS_KWA_LEN) {
370 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
371 : : "Authenticator length %u", len);
372 : 2 : return -1;
373 : : }
374 : 580 : attr->key_wrap_auth = pos;
375 : 580 : break;
376 : : case ATTR_AUTH_TYPE:
377 [ + + ]: 136 : if (len != 2) {
378 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
379 : : "Type length %u", len);
380 : 1 : return -1;
381 : : }
382 : 135 : attr->auth_type = pos;
383 : 135 : break;
384 : : case ATTR_ENCR_TYPE:
385 [ + + ]: 136 : if (len != 2) {
386 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
387 : : "Type length %u", len);
388 : 1 : return -1;
389 : : }
390 : 135 : attr->encr_type = pos;
391 : 135 : break;
392 : : case ATTR_NETWORK_INDEX:
393 [ + + ]: 118 : if (len != 1) {
394 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
395 : : "length %u", len);
396 : 1 : return -1;
397 : : }
398 : 117 : attr->network_idx = pos;
399 : 117 : break;
400 : : case ATTR_NETWORK_KEY_INDEX:
401 [ + + ]: 2 : if (len != 1) {
402 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
403 : : "length %u", len);
404 : 1 : return -1;
405 : : }
406 : 1 : attr->network_key_idx = pos;
407 : 1 : break;
408 : : case ATTR_MAC_ADDR:
409 [ + + ]: 322 : if (len != ETH_ALEN) {
410 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
411 : : "length %u", len);
412 : 2 : return -1;
413 : : }
414 : 320 : attr->mac_addr = pos;
415 : 320 : break;
416 : : case ATTR_SELECTED_REGISTRAR:
417 [ + + ]: 871 : if (len != 1) {
418 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
419 : : " length %u", len);
420 : 1 : return -1;
421 : : }
422 : 870 : attr->selected_registrar = pos;
423 : 870 : break;
424 : : case ATTR_REQUEST_TYPE:
425 [ + + ]: 2052 : if (len != 1) {
426 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
427 : : "length %u", len);
428 : 1 : return -1;
429 : : }
430 : 2051 : attr->request_type = pos;
431 : 2051 : break;
432 : : case ATTR_RESPONSE_TYPE:
433 [ + + ]: 1833 : if (len != 1) {
434 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
435 : : "length %u", len);
436 : 1 : return -1;
437 : : }
438 : 1832 : attr->response_type = pos;
439 : 1832 : break;
440 : : case ATTR_MANUFACTURER:
441 : 3865 : attr->manufacturer = pos;
442 : 3865 : attr->manufacturer_len = len;
443 : 3865 : break;
444 : : case ATTR_MODEL_NAME:
445 : 3866 : attr->model_name = pos;
446 : 3866 : attr->model_name_len = len;
447 : 3866 : break;
448 : : case ATTR_MODEL_NUMBER:
449 : 3865 : attr->model_number = pos;
450 : 3865 : attr->model_number_len = len;
451 : 3865 : break;
452 : : case ATTR_SERIAL_NUMBER:
453 : 2190 : attr->serial_number = pos;
454 : 2190 : attr->serial_number_len = len;
455 : 2190 : break;
456 : : case ATTR_DEV_NAME:
457 : 3849 : attr->dev_name = pos;
458 : 3849 : attr->dev_name_len = len;
459 : 3849 : break;
460 : : case ATTR_PUBLIC_KEY:
461 : 324 : attr->public_key = pos;
462 : 324 : attr->public_key_len = len;
463 : 324 : break;
464 : : case ATTR_ENCR_SETTINGS:
465 : 628 : attr->encr_settings = pos;
466 : 628 : attr->encr_settings_len = len;
467 : 628 : break;
468 : : case ATTR_CRED:
469 [ + + ]: 122 : if (attr->num_cred >= MAX_CRED_COUNT) {
470 : 2 : wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
471 : : "attribute (max %d credentials)",
472 : : MAX_CRED_COUNT);
473 : 2 : break;
474 : : }
475 : 120 : attr->cred[attr->num_cred] = pos;
476 : 120 : attr->cred_len[attr->num_cred] = len;
477 : 120 : attr->num_cred++;
478 : 120 : break;
479 : : case ATTR_SSID:
480 : 144 : attr->ssid = pos;
481 : 144 : attr->ssid_len = len;
482 : 144 : break;
483 : : case ATTR_NETWORK_KEY:
484 : 138 : attr->network_key = pos;
485 : 138 : attr->network_key_len = len;
486 : 138 : break;
487 : : case ATTR_AP_SETUP_LOCKED:
488 [ + + ]: 23 : if (len != 1) {
489 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
490 : : "length %u", len);
491 : 1 : return -1;
492 : : }
493 : 22 : attr->ap_setup_locked = pos;
494 : 22 : break;
495 : : case ATTR_REQUESTED_DEV_TYPE:
496 [ + + ]: 39 : if (len != WPS_DEV_TYPE_LEN) {
497 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
498 : : "Type length %u", len);
499 : 2 : return -1;
500 : : }
501 [ + + ]: 37 : if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
502 : 2 : wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
503 : : "Type attribute (max %u types)",
504 : : MAX_REQ_DEV_TYPE_COUNT);
505 : 2 : break;
506 : : }
507 : 35 : attr->req_dev_type[attr->num_req_dev_type] = pos;
508 : 35 : attr->num_req_dev_type++;
509 : 35 : break;
510 : : case ATTR_SECONDARY_DEV_TYPE_LIST:
511 [ + + ][ + + ]: 86 : if (len > WPS_SEC_DEV_TYPE_MAX_LEN ||
512 : 85 : (len % WPS_DEV_TYPE_LEN) > 0) {
513 : 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device "
514 : : "Type length %u", len);
515 : 2 : return -1;
516 : : }
517 : 84 : attr->sec_dev_type_list = pos;
518 : 84 : attr->sec_dev_type_list_len = len;
519 : 84 : break;
520 : : case ATTR_VENDOR_EXT:
521 [ + + ]: 5373 : if (wps_parse_vendor_ext(attr, pos, len) < 0)
522 : 6 : return -1;
523 : 5367 : break;
524 : : case ATTR_AP_CHANNEL:
525 [ + + ]: 11 : if (len != 2) {
526 : 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel "
527 : : "length %u", len);
528 : 1 : return -1;
529 : : }
530 : 10 : attr->ap_channel = pos;
531 : 10 : break;
532 : : default:
533 : 20 : wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
534 : : "len=%u", type, len);
535 : 20 : break;
536 : : }
537 : :
538 : 65955 : return 0;
539 : : }
540 : :
541 : :
542 : 6277 : int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
543 : : {
544 : : const u8 *pos, *end;
545 : : u16 type, len;
546 : : #ifdef WPS_WORKAROUNDS
547 : 6277 : u16 prev_type = 0;
548 : : #endif /* WPS_WORKAROUNDS */
549 : :
550 : 6277 : os_memset(attr, 0, sizeof(*attr));
551 : 6277 : pos = wpabuf_head(msg);
552 : 6277 : end = pos + wpabuf_len(msg);
553 : :
554 [ + + ]: 72169 : while (pos < end) {
555 [ + + ]: 65964 : if (end - pos < 4) {
556 : 4 : wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
557 : : "%lu bytes remaining",
558 : 4 : (unsigned long) (end - pos));
559 : 4 : return -1;
560 : : }
561 : :
562 : 65960 : type = WPA_GET_BE16(pos);
563 : 65960 : pos += 2;
564 : 65960 : len = WPA_GET_BE16(pos);
565 : 65960 : pos += 2;
566 : 65960 : wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u",
567 : : type, len);
568 [ + + ]: 65960 : if (len > end - pos) {
569 : 4 : wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
570 : 4 : wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg);
571 : : #ifdef WPS_WORKAROUNDS
572 : : /*
573 : : * Some deployed APs seem to have a bug in encoding of
574 : : * Network Key attribute in the Credential attribute
575 : : * where they add an extra octet after the Network Key
576 : : * attribute at least when open network is being
577 : : * provisioned.
578 : : */
579 [ + + ][ + + ]: 4 : if ((type & 0xff00) != 0x1000 &&
580 : : prev_type == ATTR_NETWORK_KEY) {
581 : 1 : wpa_printf(MSG_DEBUG, "WPS: Workaround - try "
582 : : "to skip unexpected octet after "
583 : : "Network Key");
584 : 1 : pos -= 3;
585 : 1 : continue;
586 : : }
587 : : #endif /* WPS_WORKAROUNDS */
588 : 3 : return -1;
589 : : }
590 : :
591 : : #ifdef WPS_WORKAROUNDS
592 [ + + ][ + + ]: 65956 : if (type == 0 && len == 0) {
593 : : /*
594 : : * Mac OS X 10.6 seems to be adding 0x00 padding to the
595 : : * end of M1. Skip those to avoid interop issues.
596 : : */
597 : : int i;
598 [ + + ]: 6 : for (i = 0; i < end - pos; i++) {
599 [ + + ]: 5 : if (pos[i])
600 : 1 : break;
601 : : }
602 [ + + ]: 2 : if (i == end - pos) {
603 : 1 : wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
604 : : "unexpected message padding");
605 : 1 : break;
606 : : }
607 : : }
608 : : #endif /* WPS_WORKAROUNDS */
609 : :
610 [ + + ]: 65955 : if (wps_set_attr(attr, type, pos, len) < 0)
611 : 64 : return -1;
612 : :
613 : : #ifdef WPS_WORKAROUNDS
614 : 65891 : prev_type = type;
615 : : #endif /* WPS_WORKAROUNDS */
616 : 65891 : pos += len;
617 : : }
618 : :
619 : 6277 : return 0;
620 : : }
|