Merge branch 'vendor/ZLIB'
[dragonfly.git] / contrib / hostapd / src / wps / wps_attr_parse.c
1 /*
2  * Wi-Fi Protected Setup - attribute parsing
3  * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
4  *
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.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "wps_i.h"
19
20
21 static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
22                         const u8 *pos, u16 len)
23 {
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;
30                 }
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;
38                 }
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;
46                 }
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;
54                 }
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;
62                 }
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;
70                 }
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;
78                 }
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;
86                 }
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;
94                 }
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;
102                 }
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;
110                 }
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;
118                 }
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;
126                 }
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;
134                 }
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;
142                 }
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;
150                 }
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;
158                 }
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;
166                 }
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;
174                 }
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;
182                 }
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;
190                 }
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;
198                 }
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;
206                 }
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;
214                 }
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;
222                 }
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;
230                 }
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;
238                 }
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;
246                 }
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;
254                 }
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;
262                 }
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;
270                 }
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;
278                 }
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;
286                 }
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;
294                 }
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;
302                 }
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;
310                 }
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;
318                 }
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;
326                 }
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;
363                 }
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;
389                 }
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;
396         }
397
398         return 0;
399 }
400
401
402 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
403 {
404         const u8 *pos, *end;
405         u16 type, len;
406
407         os_memset(attr, 0, sizeof(*attr));
408         pos = wpabuf_head(msg);
409         end = pos + wpabuf_len(msg);
410
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;
417                 }
418
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;
428                 }
429
430                 if (wps_set_attr(attr, type, pos, len) < 0)
431                         return -1;
432
433                 pos += len;
434         }
435
436         return 0;
437 }