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 38968 : static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
21 : u8 id, u8 len, const u8 *pos)
22 : {
23 38968 : wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u",
24 : id, len);
25 38968 : switch (id) {
26 : case WFA_ELEM_VERSION2:
27 24544 : if (len != 1) {
28 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
29 : "%u", len);
30 1 : return -1;
31 : }
32 24543 : attr->version2 = pos;
33 24543 : break;
34 : case WFA_ELEM_AUTHORIZEDMACS:
35 10675 : attr->authorized_macs = pos;
36 10675 : attr->authorized_macs_len = len;
37 10675 : 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 3741 : if (len != 1) {
48 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
49 : "length %u", len);
50 1 : return -1;
51 : }
52 3740 : attr->request_to_enroll = pos;
53 3740 : 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 : case WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS:
63 2 : if (len != 2) {
64 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Configuration Methods length %u",
65 : len);
66 1 : return -1;
67 : }
68 1 : attr->registrar_configuration_methods = pos;
69 1 : break;
70 : default:
71 2 : wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
72 : "Extension subelement %u", id);
73 2 : break;
74 : }
75 :
76 38963 : return 0;
77 : }
78 :
79 :
80 24551 : static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
81 : u16 len)
82 : {
83 24551 : const u8 *end = pos + len;
84 : u8 id, elen;
85 :
86 88065 : while (pos + 2 <= end) {
87 38969 : id = *pos++;
88 38969 : elen = *pos++;
89 38969 : if (pos + elen > end)
90 1 : break;
91 38968 : if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
92 5 : return -1;
93 38963 : pos += elen;
94 : }
95 :
96 24546 : return 0;
97 : }
98 :
99 :
100 24582 : static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
101 : u16 len)
102 : {
103 : u32 vendor_id;
104 :
105 24582 : if (len < 3) {
106 3 : wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension");
107 3 : return 0;
108 : }
109 :
110 24579 : vendor_id = WPA_GET_BE24(pos);
111 24579 : switch (vendor_id) {
112 : case WPS_VENDOR_ID_WFA:
113 24551 : return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3);
114 : }
115 :
116 : /* Handle unknown vendor extensions */
117 :
118 28 : wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)",
119 : vendor_id);
120 :
121 28 : if (len > WPS_MAX_VENDOR_EXT_LEN) {
122 1 : wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)",
123 : len);
124 1 : return -1;
125 : }
126 :
127 27 : if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) {
128 1 : wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension "
129 : "attribute (max %d vendor extensions)",
130 : MAX_WPS_PARSE_VENDOR_EXT);
131 1 : return -1;
132 : }
133 26 : attr->vendor_ext[attr->num_vendor_ext] = pos;
134 26 : attr->vendor_ext_len[attr->num_vendor_ext] = len;
135 26 : attr->num_vendor_ext++;
136 :
137 26 : return 0;
138 : }
139 :
140 :
141 328876 : static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
142 : const u8 *pos, u16 len)
143 : {
144 328876 : switch (type) {
145 : case ATTR_VERSION:
146 24802 : if (len != 1) {
147 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
148 : len);
149 1 : return -1;
150 : }
151 24801 : attr->version = pos;
152 24801 : break;
153 : case ATTR_MSG_TYPE:
154 3493 : if (len != 1) {
155 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
156 : "length %u", len);
157 1 : return -1;
158 : }
159 3492 : attr->msg_type = pos;
160 3492 : break;
161 : case ATTR_ENROLLEE_NONCE:
162 2457 : if (len != WPS_NONCE_LEN) {
163 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
164 : "length %u", len);
165 1 : return -1;
166 : }
167 2456 : attr->enrollee_nonce = pos;
168 2456 : break;
169 : case ATTR_REGISTRAR_NONCE:
170 1971 : if (len != WPS_NONCE_LEN) {
171 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
172 : "length %u", len);
173 1 : return -1;
174 : }
175 1970 : attr->registrar_nonce = pos;
176 1970 : break;
177 : case ATTR_UUID_E:
178 20362 : if (len != WPS_UUID_LEN) {
179 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
180 : len);
181 2 : return -1;
182 : }
183 20360 : attr->uuid_e = pos;
184 20360 : break;
185 : case ATTR_UUID_R:
186 495 : if (len != WPS_UUID_LEN) {
187 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
188 : len);
189 2 : return -1;
190 : }
191 493 : attr->uuid_r = pos;
192 493 : break;
193 : case ATTR_AUTH_TYPE_FLAGS:
194 1009 : if (len != 2) {
195 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
196 : "Type Flags length %u", len);
197 1 : return -1;
198 : }
199 1008 : attr->auth_type_flags = pos;
200 1008 : break;
201 : case ATTR_ENCR_TYPE_FLAGS:
202 1007 : if (len != 2) {
203 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
204 : "Flags length %u", len);
205 1 : return -1;
206 : }
207 1006 : attr->encr_type_flags = pos;
208 1006 : break;
209 : case ATTR_CONN_TYPE_FLAGS:
210 1005 : if (len != 1) {
211 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
212 : "Flags length %u", len);
213 1 : return -1;
214 : }
215 1004 : attr->conn_type_flags = pos;
216 1004 : break;
217 : case ATTR_CONFIG_METHODS:
218 21062 : if (len != 2) {
219 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
220 : "length %u", len);
221 1 : return -1;
222 : }
223 21061 : attr->config_methods = pos;
224 21061 : break;
225 : case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
226 10718 : if (len != 2) {
227 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
228 : "Registrar Config Methods length %u", len);
229 1 : return -1;
230 : }
231 10717 : attr->sel_reg_config_methods = pos;
232 10717 : break;
233 : case ATTR_PRIMARY_DEV_TYPE:
234 20883 : if (len != WPS_DEV_TYPE_LEN) {
235 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
236 : "Type length %u", len);
237 1 : return -1;
238 : }
239 20882 : attr->primary_dev_type = pos;
240 20882 : break;
241 : case ATTR_RF_BANDS:
242 6177 : if (len != 1) {
243 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
244 : "%u", len);
245 1 : return -1;
246 : }
247 6176 : attr->rf_bands = pos;
248 6176 : break;
249 : case ATTR_ASSOC_STATE:
250 5982 : if (len != 2) {
251 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
252 : "length %u", len);
253 1 : return -1;
254 : }
255 5981 : attr->assoc_state = pos;
256 5981 : break;
257 : case ATTR_CONFIG_ERROR:
258 6115 : if (len != 2) {
259 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
260 : "Error length %u", len);
261 1 : return -1;
262 : }
263 6114 : attr->config_error = pos;
264 6114 : break;
265 : case ATTR_DEV_PASSWORD_ID:
266 17230 : if (len != 2) {
267 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
268 : "ID length %u", len);
269 1 : return -1;
270 : }
271 17229 : attr->dev_password_id = pos;
272 17229 : break;
273 : case ATTR_OOB_DEVICE_PASSWORD:
274 60 : if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
275 : len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
276 58 : WPS_OOB_DEVICE_PASSWORD_LEN ||
277 : (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
278 41 : WPS_OOB_DEVICE_PASSWORD_MIN_LEN &&
279 41 : WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) !=
280 : DEV_PW_NFC_CONNECTION_HANDOVER)) {
281 3 : wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
282 : "Password length %u", len);
283 3 : return -1;
284 : }
285 57 : attr->oob_dev_password = pos;
286 57 : attr->oob_dev_password_len = len;
287 57 : break;
288 : case ATTR_OS_VERSION:
289 979 : if (len != 4) {
290 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
291 : "%u", len);
292 1 : return -1;
293 : }
294 978 : attr->os_version = pos;
295 978 : break;
296 : case ATTR_WPS_STATE:
297 15455 : if (len != 1) {
298 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
299 : "Setup State length %u", len);
300 1 : return -1;
301 : }
302 15454 : attr->wps_state = pos;
303 15454 : break;
304 : case ATTR_AUTHENTICATOR:
305 2421 : if (len != WPS_AUTHENTICATOR_LEN) {
306 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
307 : "length %u", len);
308 2 : return -1;
309 : }
310 2419 : attr->authenticator = pos;
311 2419 : break;
312 : case ATTR_R_HASH1:
313 363 : if (len != WPS_HASH_LEN) {
314 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
315 : len);
316 2 : return -1;
317 : }
318 361 : attr->r_hash1 = pos;
319 361 : break;
320 : case ATTR_R_HASH2:
321 363 : if (len != WPS_HASH_LEN) {
322 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
323 : len);
324 2 : return -1;
325 : }
326 361 : attr->r_hash2 = pos;
327 361 : break;
328 : case ATTR_E_HASH1:
329 371 : if (len != WPS_HASH_LEN) {
330 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
331 : len);
332 2 : return -1;
333 : }
334 369 : attr->e_hash1 = pos;
335 369 : break;
336 : case ATTR_E_HASH2:
337 371 : if (len != WPS_HASH_LEN) {
338 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
339 : len);
340 2 : return -1;
341 : }
342 369 : attr->e_hash2 = pos;
343 369 : break;
344 : case ATTR_R_SNONCE1:
345 336 : if (len != WPS_SECRET_NONCE_LEN) {
346 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
347 : "%u", len);
348 2 : return -1;
349 : }
350 334 : attr->r_snonce1 = pos;
351 334 : break;
352 : case ATTR_R_SNONCE2:
353 314 : if (len != WPS_SECRET_NONCE_LEN) {
354 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
355 : "%u", len);
356 2 : return -1;
357 : }
358 312 : attr->r_snonce2 = pos;
359 312 : break;
360 : case ATTR_E_SNONCE1:
361 306 : if (len != WPS_SECRET_NONCE_LEN) {
362 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
363 : "%u", len);
364 2 : return -1;
365 : }
366 304 : attr->e_snonce1 = pos;
367 304 : break;
368 : case ATTR_E_SNONCE2:
369 292 : if (len != WPS_SECRET_NONCE_LEN) {
370 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
371 : "%u", len);
372 2 : return -1;
373 : }
374 290 : attr->e_snonce2 = pos;
375 290 : break;
376 : case ATTR_KEY_WRAP_AUTH:
377 1511 : if (len != WPS_KWA_LEN) {
378 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
379 : "Authenticator length %u", len);
380 2 : return -1;
381 : }
382 1509 : attr->key_wrap_auth = pos;
383 1509 : break;
384 : case ATTR_AUTH_TYPE:
385 323 : if (len != 2) {
386 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
387 : "Type length %u", len);
388 1 : return -1;
389 : }
390 322 : attr->auth_type = pos;
391 322 : break;
392 : case ATTR_ENCR_TYPE:
393 323 : if (len != 2) {
394 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
395 : "Type length %u", len);
396 1 : return -1;
397 : }
398 322 : attr->encr_type = pos;
399 322 : break;
400 : case ATTR_NETWORK_INDEX:
401 277 : if (len != 1) {
402 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
403 : "length %u", len);
404 1 : return -1;
405 : }
406 276 : attr->network_idx = pos;
407 276 : break;
408 : case ATTR_NETWORK_KEY_INDEX:
409 5 : if (len != 1) {
410 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
411 : "length %u", len);
412 1 : return -1;
413 : }
414 4 : attr->network_key_idx = pos;
415 4 : break;
416 : case ATTR_MAC_ADDR:
417 889 : if (len != ETH_ALEN) {
418 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
419 : "length %u", len);
420 2 : return -1;
421 : }
422 887 : attr->mac_addr = pos;
423 887 : break;
424 : case ATTR_SELECTED_REGISTRAR:
425 10719 : if (len != 1) {
426 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
427 : " length %u", len);
428 1 : return -1;
429 : }
430 10718 : attr->selected_registrar = pos;
431 10718 : break;
432 : case ATTR_REQUEST_TYPE:
433 6119 : if (len != 1) {
434 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
435 : "length %u", len);
436 1 : return -1;
437 : }
438 6118 : attr->request_type = pos;
439 6118 : break;
440 : case ATTR_RESPONSE_TYPE:
441 14770 : if (len != 1) {
442 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
443 : "length %u", len);
444 1 : return -1;
445 : }
446 14769 : attr->response_type = pos;
447 14769 : break;
448 : case ATTR_MANUFACTURER:
449 20793 : attr->manufacturer = pos;
450 20793 : if (len > WPS_MANUFACTURER_MAX_LEN)
451 1 : attr->manufacturer_len = WPS_MANUFACTURER_MAX_LEN;
452 : else
453 20792 : attr->manufacturer_len = len;
454 20793 : break;
455 : case ATTR_MODEL_NAME:
456 20792 : attr->model_name = pos;
457 20792 : if (len > WPS_MODEL_NAME_MAX_LEN)
458 1 : attr->model_name_len = WPS_MODEL_NAME_MAX_LEN;
459 : else
460 20791 : attr->model_name_len = len;
461 20792 : break;
462 : case ATTR_MODEL_NUMBER:
463 20788 : attr->model_number = pos;
464 20788 : if (len > WPS_MODEL_NUMBER_MAX_LEN)
465 1 : attr->model_number_len = WPS_MODEL_NUMBER_MAX_LEN;
466 : else
467 20787 : attr->model_number_len = len;
468 20788 : break;
469 : case ATTR_SERIAL_NUMBER:
470 15790 : attr->serial_number = pos;
471 15790 : if (len > WPS_SERIAL_NUMBER_MAX_LEN)
472 1 : attr->serial_number_len = WPS_SERIAL_NUMBER_MAX_LEN;
473 : else
474 15789 : attr->serial_number_len = len;
475 15790 : break;
476 : case ATTR_DEV_NAME:
477 20898 : if (len > WPS_DEV_NAME_MAX_LEN) {
478 1 : wpa_printf(MSG_DEBUG,
479 : "WPS: Ignore too long Device Name (len=%u)",
480 : len);
481 1 : break;
482 : }
483 20897 : attr->dev_name = pos;
484 20897 : attr->dev_name_len = len;
485 20897 : break;
486 : case ATTR_PUBLIC_KEY:
487 : /*
488 : * The Public Key attribute is supposed to be exactly 192 bytes
489 : * in length. Allow couple of bytes shorter one to try to
490 : * interoperate with implementations that do not use proper
491 : * zero-padding.
492 : */
493 978 : if (len < 190 || len > 192) {
494 1 : wpa_printf(MSG_DEBUG,
495 : "WPS: Ignore Public Key with unexpected length %u",
496 : len);
497 1 : break;
498 : }
499 977 : attr->public_key = pos;
500 977 : attr->public_key_len = len;
501 977 : break;
502 : case ATTR_ENCR_SETTINGS:
503 1634 : attr->encr_settings = pos;
504 1634 : attr->encr_settings_len = len;
505 1634 : break;
506 : case ATTR_CRED:
507 278 : if (attr->num_cred >= MAX_CRED_COUNT) {
508 2 : wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
509 : "attribute (max %d credentials)",
510 : MAX_CRED_COUNT);
511 2 : break;
512 : }
513 276 : attr->cred[attr->num_cred] = pos;
514 276 : attr->cred_len[attr->num_cred] = len;
515 276 : attr->num_cred++;
516 276 : break;
517 : case ATTR_SSID:
518 334 : if (len > SSID_MAX_LEN) {
519 1 : wpa_printf(MSG_DEBUG,
520 : "WPS: Ignore too long SSID (len=%u)", len);
521 1 : break;
522 : }
523 333 : attr->ssid = pos;
524 333 : attr->ssid_len = len;
525 333 : break;
526 : case ATTR_NETWORK_KEY:
527 324 : attr->network_key = pos;
528 324 : attr->network_key_len = len;
529 324 : break;
530 : case ATTR_AP_SETUP_LOCKED:
531 66 : if (len != 1) {
532 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
533 : "length %u", len);
534 1 : return -1;
535 : }
536 65 : attr->ap_setup_locked = pos;
537 65 : break;
538 : case ATTR_REQUESTED_DEV_TYPE:
539 49 : if (len != WPS_DEV_TYPE_LEN) {
540 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
541 : "Type length %u", len);
542 2 : return -1;
543 : }
544 47 : if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
545 2 : wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
546 : "Type attribute (max %u types)",
547 : MAX_REQ_DEV_TYPE_COUNT);
548 2 : break;
549 : }
550 45 : attr->req_dev_type[attr->num_req_dev_type] = pos;
551 45 : attr->num_req_dev_type++;
552 45 : break;
553 : case ATTR_SECONDARY_DEV_TYPE_LIST:
554 385 : if (len > WPS_SEC_DEV_TYPE_MAX_LEN ||
555 192 : (len % WPS_DEV_TYPE_LEN) > 0) {
556 2 : wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device "
557 : "Type length %u", len);
558 2 : return -1;
559 : }
560 191 : attr->sec_dev_type_list = pos;
561 191 : attr->sec_dev_type_list_len = len;
562 191 : break;
563 : case ATTR_VENDOR_EXT:
564 24582 : if (wps_parse_vendor_ext(attr, pos, len) < 0)
565 7 : return -1;
566 24575 : break;
567 : case ATTR_AP_CHANNEL:
568 13 : if (len != 2) {
569 1 : wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel "
570 : "length %u", len);
571 1 : return -1;
572 : }
573 12 : attr->ap_channel = pos;
574 12 : break;
575 : default:
576 29 : wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
577 : "len=%u", type, len);
578 29 : break;
579 : }
580 :
581 328811 : return 0;
582 : }
583 :
584 :
585 27215 : int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
586 : {
587 : const u8 *pos, *end;
588 : u16 type, len;
589 : #ifdef WPS_WORKAROUNDS
590 27215 : u16 prev_type = 0;
591 : #endif /* WPS_WORKAROUNDS */
592 :
593 27215 : os_memset(attr, 0, sizeof(*attr));
594 27215 : pos = wpabuf_head(msg);
595 27215 : end = pos + wpabuf_len(msg);
596 :
597 383242 : while (pos < end) {
598 328961 : if (end - pos < 4) {
599 77 : wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
600 : "%lu bytes remaining",
601 77 : (unsigned long) (end - pos));
602 77 : return -1;
603 : }
604 :
605 328884 : type = WPA_GET_BE16(pos);
606 328884 : pos += 2;
607 328884 : len = WPA_GET_BE16(pos);
608 328884 : pos += 2;
609 328884 : wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u",
610 : type, len);
611 328884 : if (len > end - pos) {
612 7 : wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
613 7 : wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg);
614 : #ifdef WPS_WORKAROUNDS
615 : /*
616 : * Some deployed APs seem to have a bug in encoding of
617 : * Network Key attribute in the Credential attribute
618 : * where they add an extra octet after the Network Key
619 : * attribute at least when open network is being
620 : * provisioned.
621 : */
622 7 : if ((type & 0xff00) != 0x1000 &&
623 : prev_type == ATTR_NETWORK_KEY) {
624 1 : wpa_printf(MSG_DEBUG, "WPS: Workaround - try "
625 : "to skip unexpected octet after "
626 : "Network Key");
627 1 : pos -= 3;
628 1 : continue;
629 : }
630 : #endif /* WPS_WORKAROUNDS */
631 6 : return -1;
632 : }
633 :
634 : #ifdef WPS_WORKAROUNDS
635 328877 : if (type == 0 && len == 0) {
636 : /*
637 : * Mac OS X 10.6 seems to be adding 0x00 padding to the
638 : * end of M1. Skip those to avoid interop issues.
639 : */
640 : int i;
641 6 : for (i = 0; i < end - pos; i++) {
642 5 : if (pos[i])
643 1 : break;
644 : }
645 2 : if (i == end - pos) {
646 1 : wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
647 : "unexpected message padding");
648 1 : break;
649 : }
650 : }
651 : #endif /* WPS_WORKAROUNDS */
652 :
653 328876 : if (wps_set_attr(attr, type, pos, len) < 0)
654 65 : return -1;
655 :
656 : #ifdef WPS_WORKAROUNDS
657 328811 : prev_type = type;
658 : #endif /* WPS_WORKAROUNDS */
659 328811 : pos += len;
660 : }
661 :
662 27067 : return 0;
663 : }
|