Listtree.mcc: make creation of tree node symmetrical to other proxied operations
[AROS.git] / workbench / network / WirelessManager / src / wps / wps_attr_parse.c
blob30b0e79211ae1274b9bf4aa92ea36daf1ccb465f
1 /*
2 * Wi-Fi Protected Setup - attribute parsing
3 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #include "common.h"
18 #include "wps_i.h"
20 #define WPS_WORKAROUNDS
23 static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
24 const u8 *pos, u16 len)
26 switch (type) {
27 case ATTR_VERSION:
28 if (len != 1) {
29 wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
30 len);
31 return -1;
33 attr->version = pos;
34 break;
35 case ATTR_MSG_TYPE:
36 if (len != 1) {
37 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
38 "length %u", len);
39 return -1;
41 attr->msg_type = pos;
42 break;
43 case ATTR_ENROLLEE_NONCE:
44 if (len != WPS_NONCE_LEN) {
45 wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
46 "length %u", len);
47 return -1;
49 attr->enrollee_nonce = pos;
50 break;
51 case ATTR_REGISTRAR_NONCE:
52 if (len != WPS_NONCE_LEN) {
53 wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
54 "length %u", len);
55 return -1;
57 attr->registrar_nonce = pos;
58 break;
59 case ATTR_UUID_E:
60 if (len != WPS_UUID_LEN) {
61 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
62 len);
63 return -1;
65 attr->uuid_e = pos;
66 break;
67 case ATTR_UUID_R:
68 if (len != WPS_UUID_LEN) {
69 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
70 len);
71 return -1;
73 attr->uuid_r = pos;
74 break;
75 case ATTR_AUTH_TYPE_FLAGS:
76 if (len != 2) {
77 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
78 "Type Flags length %u", len);
79 return -1;
81 attr->auth_type_flags = pos;
82 break;
83 case ATTR_ENCR_TYPE_FLAGS:
84 if (len != 2) {
85 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
86 "Flags length %u", len);
87 return -1;
89 attr->encr_type_flags = pos;
90 break;
91 case ATTR_CONN_TYPE_FLAGS:
92 if (len != 1) {
93 wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
94 "Flags length %u", len);
95 return -1;
97 attr->conn_type_flags = pos;
98 break;
99 case ATTR_CONFIG_METHODS:
100 if (len != 2) {
101 wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
102 "length %u", len);
103 return -1;
105 attr->config_methods = pos;
106 break;
107 case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
108 if (len != 2) {
109 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
110 "Registrar Config Methods length %u", len);
111 return -1;
113 attr->sel_reg_config_methods = pos;
114 break;
115 case ATTR_PRIMARY_DEV_TYPE:
116 if (len != WPS_DEV_TYPE_LEN) {
117 wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
118 "Type length %u", len);
119 return -1;
121 attr->primary_dev_type = pos;
122 break;
123 case ATTR_RF_BANDS:
124 if (len != 1) {
125 wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
126 "%u", len);
127 return -1;
129 attr->rf_bands = pos;
130 break;
131 case ATTR_ASSOC_STATE:
132 if (len != 2) {
133 wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
134 "length %u", len);
135 return -1;
137 attr->assoc_state = pos;
138 break;
139 case ATTR_CONFIG_ERROR:
140 if (len != 2) {
141 wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
142 "Error length %u", len);
143 return -1;
145 attr->config_error = pos;
146 break;
147 case ATTR_DEV_PASSWORD_ID:
148 if (len != 2) {
149 wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
150 "ID length %u", len);
151 return -1;
153 attr->dev_password_id = pos;
154 break;
155 case ATTR_OOB_DEVICE_PASSWORD:
156 if (len != WPS_OOB_DEVICE_PASSWORD_ATTR_LEN) {
157 wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
158 "Password length %u", len);
159 return -1;
161 attr->oob_dev_password = pos;
162 break;
163 case ATTR_OS_VERSION:
164 if (len != 4) {
165 wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
166 "%u", len);
167 return -1;
169 attr->os_version = pos;
170 break;
171 case ATTR_WPS_STATE:
172 if (len != 1) {
173 wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
174 "Setup State length %u", len);
175 return -1;
177 attr->wps_state = pos;
178 break;
179 case ATTR_AUTHENTICATOR:
180 if (len != WPS_AUTHENTICATOR_LEN) {
181 wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
182 "length %u", len);
183 return -1;
185 attr->authenticator = pos;
186 break;
187 case ATTR_R_HASH1:
188 if (len != WPS_HASH_LEN) {
189 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
190 len);
191 return -1;
193 attr->r_hash1 = pos;
194 break;
195 case ATTR_R_HASH2:
196 if (len != WPS_HASH_LEN) {
197 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
198 len);
199 return -1;
201 attr->r_hash2 = pos;
202 break;
203 case ATTR_E_HASH1:
204 if (len != WPS_HASH_LEN) {
205 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
206 len);
207 return -1;
209 attr->e_hash1 = pos;
210 break;
211 case ATTR_E_HASH2:
212 if (len != WPS_HASH_LEN) {
213 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
214 len);
215 return -1;
217 attr->e_hash2 = pos;
218 break;
219 case ATTR_R_SNONCE1:
220 if (len != WPS_SECRET_NONCE_LEN) {
221 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
222 "%u", len);
223 return -1;
225 attr->r_snonce1 = pos;
226 break;
227 case ATTR_R_SNONCE2:
228 if (len != WPS_SECRET_NONCE_LEN) {
229 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
230 "%u", len);
231 return -1;
233 attr->r_snonce2 = pos;
234 break;
235 case ATTR_E_SNONCE1:
236 if (len != WPS_SECRET_NONCE_LEN) {
237 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
238 "%u", len);
239 return -1;
241 attr->e_snonce1 = pos;
242 break;
243 case ATTR_E_SNONCE2:
244 if (len != WPS_SECRET_NONCE_LEN) {
245 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
246 "%u", len);
247 return -1;
249 attr->e_snonce2 = pos;
250 break;
251 case ATTR_KEY_WRAP_AUTH:
252 if (len != WPS_KWA_LEN) {
253 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
254 "Authenticator length %u", len);
255 return -1;
257 attr->key_wrap_auth = pos;
258 break;
259 case ATTR_AUTH_TYPE:
260 if (len != 2) {
261 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
262 "Type length %u", len);
263 return -1;
265 attr->auth_type = pos;
266 break;
267 case ATTR_ENCR_TYPE:
268 if (len != 2) {
269 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
270 "Type length %u", len);
271 return -1;
273 attr->encr_type = pos;
274 break;
275 case ATTR_NETWORK_INDEX:
276 if (len != 1) {
277 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
278 "length %u", len);
279 return -1;
281 attr->network_idx = pos;
282 break;
283 case ATTR_NETWORK_KEY_INDEX:
284 if (len != 1) {
285 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
286 "length %u", len);
287 return -1;
289 attr->network_key_idx = pos;
290 break;
291 case ATTR_MAC_ADDR:
292 if (len != ETH_ALEN) {
293 wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
294 "length %u", len);
295 return -1;
297 attr->mac_addr = pos;
298 break;
299 case ATTR_KEY_PROVIDED_AUTO:
300 if (len != 1) {
301 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided "
302 "Automatically length %u", len);
303 return -1;
305 attr->key_prov_auto = pos;
306 break;
307 case ATTR_802_1X_ENABLED:
308 if (len != 1) {
309 wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled "
310 "length %u", len);
311 return -1;
313 attr->dot1x_enabled = pos;
314 break;
315 case ATTR_SELECTED_REGISTRAR:
316 if (len != 1) {
317 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
318 " length %u", len);
319 return -1;
321 attr->selected_registrar = pos;
322 break;
323 case ATTR_REQUEST_TYPE:
324 if (len != 1) {
325 wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
326 "length %u", len);
327 return -1;
329 attr->request_type = pos;
330 break;
331 case ATTR_RESPONSE_TYPE:
332 if (len != 1) {
333 wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
334 "length %u", len);
335 return -1;
337 attr->response_type = pos;
338 break;
339 case ATTR_MANUFACTURER:
340 attr->manufacturer = pos;
341 attr->manufacturer_len = len;
342 break;
343 case ATTR_MODEL_NAME:
344 attr->model_name = pos;
345 attr->model_name_len = len;
346 break;
347 case ATTR_MODEL_NUMBER:
348 attr->model_number = pos;
349 attr->model_number_len = len;
350 break;
351 case ATTR_SERIAL_NUMBER:
352 attr->serial_number = pos;
353 attr->serial_number_len = len;
354 break;
355 case ATTR_DEV_NAME:
356 attr->dev_name = pos;
357 attr->dev_name_len = len;
358 break;
359 case ATTR_PUBLIC_KEY:
360 attr->public_key = pos;
361 attr->public_key_len = len;
362 break;
363 case ATTR_ENCR_SETTINGS:
364 attr->encr_settings = pos;
365 attr->encr_settings_len = len;
366 break;
367 case ATTR_CRED:
368 if (attr->num_cred >= MAX_CRED_COUNT) {
369 wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
370 "attribute (max %d credentials)",
371 MAX_CRED_COUNT);
372 break;
374 attr->cred[attr->num_cred] = pos;
375 attr->cred_len[attr->num_cred] = len;
376 attr->num_cred++;
377 break;
378 case ATTR_SSID:
379 attr->ssid = pos;
380 attr->ssid_len = len;
381 break;
382 case ATTR_NETWORK_KEY:
383 attr->network_key = pos;
384 attr->network_key_len = len;
385 break;
386 case ATTR_EAP_TYPE:
387 attr->eap_type = pos;
388 attr->eap_type_len = len;
389 break;
390 case ATTR_EAP_IDENTITY:
391 attr->eap_identity = pos;
392 attr->eap_identity_len = len;
393 break;
394 case ATTR_AP_SETUP_LOCKED:
395 if (len != 1) {
396 wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
397 "length %u", len);
398 return -1;
400 attr->ap_setup_locked = pos;
401 break;
402 default:
403 wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
404 "len=%u", type, len);
405 break;
408 return 0;
412 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
414 const u8 *pos, *end;
415 u16 type, len;
417 os_memset(attr, 0, sizeof(*attr));
418 pos = wpabuf_head(msg);
419 end = pos + wpabuf_len(msg);
421 while (pos < end) {
422 if (end - pos < 4) {
423 wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
424 "%lu bytes remaining",
425 (unsigned long) (end - pos));
426 return -1;
429 type = WPA_GET_BE16(pos);
430 pos += 2;
431 len = WPA_GET_BE16(pos);
432 pos += 2;
433 wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u",
434 type, len);
435 if (len > end - pos) {
436 wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
437 return -1;
440 #ifdef WPS_WORKAROUNDS
441 if (type == 0 && len == 0) {
443 * Mac OS X 10.6 seems to be adding 0x00 padding to the
444 * end of M1. Skip those to avoid interop issues.
446 int i;
447 for (i = 0; i < end - pos; i++) {
448 if (pos[i])
449 break;
451 if (i == end - pos) {
452 wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
453 "unexpected message padding");
454 break;
457 #endif /* WPS_WORKAROUNDS */
459 if (wps_set_attr(attr, type, pos, len) < 0)
460 return -1;
462 pos += len;
465 return 0;