Home | History | Annotate | Download | only in wps
      1 /*
      2  * Wi-Fi Protected Setup - attribute parsing
      3  * Copyright (c) 2008, Jouni Malinen <j (at) 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 }
    438