hostapd: Update vendor branch to 0.6.10
[dragonfly.git] / contrib / hostapd / src / wps / wps_attr_parse.c
blobf50ae397492980c9fb898b5f0d9d6f8c263f78ab
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"
21 static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
22 const u8 *pos, u16 len)
24 switch (type) {
25 case ATTR_VERSION:
26 if (len != 1) {
27 wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
28 len);
29 return -1;
31 attr->version = pos;
32 break;
33 case ATTR_MSG_TYPE:
34 if (len != 1) {
35 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
36 "length %u", len);
37 return -1;
39 attr->msg_type = pos;
40 break;
41 case ATTR_ENROLLEE_NONCE:
42 if (len != WPS_NONCE_LEN) {
43 wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
44 "length %u", len);
45 return -1;
47 attr->enrollee_nonce = pos;
48 break;
49 case ATTR_REGISTRAR_NONCE:
50 if (len != WPS_NONCE_LEN) {
51 wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
52 "length %u", len);
53 return -1;
55 attr->registrar_nonce = pos;
56 break;
57 case ATTR_UUID_E:
58 if (len != WPS_UUID_LEN) {
59 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
60 len);
61 return -1;
63 attr->uuid_e = pos;
64 break;
65 case ATTR_UUID_R:
66 if (len != WPS_UUID_LEN) {
67 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
68 len);
69 return -1;
71 attr->uuid_r = pos;
72 break;
73 case ATTR_AUTH_TYPE_FLAGS:
74 if (len != 2) {
75 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
76 "Type Flags length %u", len);
77 return -1;
79 attr->auth_type_flags = pos;
80 break;
81 case ATTR_ENCR_TYPE_FLAGS:
82 if (len != 2) {
83 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
84 "Flags length %u", len);
85 return -1;
87 attr->encr_type_flags = pos;
88 break;
89 case ATTR_CONN_TYPE_FLAGS:
90 if (len != 1) {
91 wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
92 "Flags length %u", len);
93 return -1;
95 attr->conn_type_flags = pos;
96 break;
97 case ATTR_CONFIG_METHODS:
98 if (len != 2) {
99 wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
100 "length %u", len);
101 return -1;
103 attr->config_methods = pos;
104 break;
105 case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
106 if (len != 2) {
107 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
108 "Registrar Config Methods length %u", len);
109 return -1;
111 attr->sel_reg_config_methods = pos;
112 break;
113 case ATTR_PRIMARY_DEV_TYPE:
114 if (len != sizeof(struct wps_dev_type)) {
115 wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
116 "Type length %u", len);
117 return -1;
119 attr->primary_dev_type = pos;
120 break;
121 case ATTR_RF_BANDS:
122 if (len != 1) {
123 wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
124 "%u", len);
125 return -1;
127 attr->rf_bands = pos;
128 break;
129 case ATTR_ASSOC_STATE:
130 if (len != 2) {
131 wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
132 "length %u", len);
133 return -1;
135 attr->assoc_state = pos;
136 break;
137 case ATTR_CONFIG_ERROR:
138 if (len != 2) {
139 wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
140 "Error length %u", len);
141 return -1;
143 attr->config_error = pos;
144 break;
145 case ATTR_DEV_PASSWORD_ID:
146 if (len != 2) {
147 wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
148 "ID length %u", len);
149 return -1;
151 attr->dev_password_id = pos;
152 break;
153 case ATTR_OS_VERSION:
154 if (len != 4) {
155 wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
156 "%u", len);
157 return -1;
159 attr->os_version = pos;
160 break;
161 case ATTR_WPS_STATE:
162 if (len != 1) {
163 wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
164 "Setup State length %u", len);
165 return -1;
167 attr->wps_state = pos;
168 break;
169 case ATTR_AUTHENTICATOR:
170 if (len != WPS_AUTHENTICATOR_LEN) {
171 wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
172 "length %u", len);
173 return -1;
175 attr->authenticator = pos;
176 break;
177 case ATTR_R_HASH1:
178 if (len != WPS_HASH_LEN) {
179 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
180 len);
181 return -1;
183 attr->r_hash1 = pos;
184 break;
185 case ATTR_R_HASH2:
186 if (len != WPS_HASH_LEN) {
187 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
188 len);
189 return -1;
191 attr->r_hash2 = pos;
192 break;
193 case ATTR_E_HASH1:
194 if (len != WPS_HASH_LEN) {
195 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
196 len);
197 return -1;
199 attr->e_hash1 = pos;
200 break;
201 case ATTR_E_HASH2:
202 if (len != WPS_HASH_LEN) {
203 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
204 len);
205 return -1;
207 attr->e_hash2 = pos;
208 break;
209 case ATTR_R_SNONCE1:
210 if (len != WPS_SECRET_NONCE_LEN) {
211 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
212 "%u", len);
213 return -1;
215 attr->r_snonce1 = pos;
216 break;
217 case ATTR_R_SNONCE2:
218 if (len != WPS_SECRET_NONCE_LEN) {
219 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
220 "%u", len);
221 return -1;
223 attr->r_snonce2 = pos;
224 break;
225 case ATTR_E_SNONCE1:
226 if (len != WPS_SECRET_NONCE_LEN) {
227 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
228 "%u", len);
229 return -1;
231 attr->e_snonce1 = pos;
232 break;
233 case ATTR_E_SNONCE2:
234 if (len != WPS_SECRET_NONCE_LEN) {
235 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
236 "%u", len);
237 return -1;
239 attr->e_snonce2 = pos;
240 break;
241 case ATTR_KEY_WRAP_AUTH:
242 if (len != WPS_KWA_LEN) {
243 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
244 "Authenticator length %u", len);
245 return -1;
247 attr->key_wrap_auth = pos;
248 break;
249 case ATTR_AUTH_TYPE:
250 if (len != 2) {
251 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
252 "Type length %u", len);
253 return -1;
255 attr->auth_type = pos;
256 break;
257 case ATTR_ENCR_TYPE:
258 if (len != 2) {
259 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
260 "Type length %u", len);
261 return -1;
263 attr->encr_type = pos;
264 break;
265 case ATTR_NETWORK_INDEX:
266 if (len != 1) {
267 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
268 "length %u", len);
269 return -1;
271 attr->network_idx = pos;
272 break;
273 case ATTR_NETWORK_KEY_INDEX:
274 if (len != 1) {
275 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
276 "length %u", len);
277 return -1;
279 attr->network_key_idx = pos;
280 break;
281 case ATTR_MAC_ADDR:
282 if (len != ETH_ALEN) {
283 wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
284 "length %u", len);
285 return -1;
287 attr->mac_addr = pos;
288 break;
289 case ATTR_KEY_PROVIDED_AUTO:
290 if (len != 1) {
291 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided "
292 "Automatically length %u", len);
293 return -1;
295 attr->key_prov_auto = pos;
296 break;
297 case ATTR_802_1X_ENABLED:
298 if (len != 1) {
299 wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled "
300 "length %u", len);
301 return -1;
303 attr->dot1x_enabled = pos;
304 break;
305 case ATTR_SELECTED_REGISTRAR:
306 if (len != 1) {
307 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
308 " length %u", len);
309 return -1;
311 attr->selected_registrar = pos;
312 break;
313 case ATTR_REQUEST_TYPE:
314 if (len != 1) {
315 wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
316 "length %u", len);
317 return -1;
319 attr->request_type = pos;
320 break;
321 case ATTR_RESPONSE_TYPE:
322 if (len != 1) {
323 wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
324 "length %u", len);
325 return -1;
327 attr->request_type = pos;
328 break;
329 case ATTR_MANUFACTURER:
330 attr->manufacturer = pos;
331 attr->manufacturer_len = len;
332 break;
333 case ATTR_MODEL_NAME:
334 attr->model_name = pos;
335 attr->model_name_len = len;
336 break;
337 case ATTR_MODEL_NUMBER:
338 attr->model_number = pos;
339 attr->model_number_len = len;
340 break;
341 case ATTR_SERIAL_NUMBER:
342 attr->serial_number = pos;
343 attr->serial_number_len = len;
344 break;
345 case ATTR_DEV_NAME:
346 attr->dev_name = pos;
347 attr->dev_name_len = len;
348 break;
349 case ATTR_PUBLIC_KEY:
350 attr->public_key = pos;
351 attr->public_key_len = len;
352 break;
353 case ATTR_ENCR_SETTINGS:
354 attr->encr_settings = pos;
355 attr->encr_settings_len = len;
356 break;
357 case ATTR_CRED:
358 if (attr->num_cred >= MAX_CRED_COUNT) {
359 wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
360 "attribute (max %d credentials)",
361 MAX_CRED_COUNT);
362 break;
364 attr->cred[attr->num_cred] = pos;
365 attr->cred_len[attr->num_cred] = len;
366 attr->num_cred++;
367 break;
368 case ATTR_SSID:
369 attr->ssid = pos;
370 attr->ssid_len = len;
371 break;
372 case ATTR_NETWORK_KEY:
373 attr->network_key = pos;
374 attr->network_key_len = len;
375 break;
376 case ATTR_EAP_TYPE:
377 attr->eap_type = pos;
378 attr->eap_type_len = len;
379 break;
380 case ATTR_EAP_IDENTITY:
381 attr->eap_identity = pos;
382 attr->eap_identity_len = len;
383 break;
384 case ATTR_AP_SETUP_LOCKED:
385 if (len != 1) {
386 wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
387 "length %u", len);
388 return -1;
390 attr->ap_setup_locked = pos;
391 break;
392 default:
393 wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
394 "len=%u", type, len);
395 break;
398 return 0;
402 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
404 const u8 *pos, *end;
405 u16 type, len;
407 os_memset(attr, 0, sizeof(*attr));
408 pos = wpabuf_head(msg);
409 end = pos + wpabuf_len(msg);
411 while (pos < end) {
412 if (end - pos < 4) {
413 wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
414 "%lu bytes remaining",
415 (unsigned long) (end - pos));
416 return -1;
419 type = WPA_GET_BE16(pos);
420 pos += 2;
421 len = WPA_GET_BE16(pos);
422 pos += 2;
423 wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u",
424 type, len);
425 if (len > end - pos) {
426 wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
427 return -1;
430 if (wps_set_attr(attr, type, pos, len) < 0)
431 return -1;
433 pos += len;
436 return 0;