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