139beb93cSSam Leffler /* 239beb93cSSam Leffler * Wi-Fi Protected Setup - attribute parsing 339beb93cSSam Leffler * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 539beb93cSSam Leffler * This program is free software; you can redistribute it and/or modify 639beb93cSSam Leffler * it under the terms of the GNU General Public License version 2 as 739beb93cSSam Leffler * published by the Free Software Foundation. 839beb93cSSam Leffler * 939beb93cSSam Leffler * Alternatively, this software may be distributed under the terms of BSD 1039beb93cSSam Leffler * license. 1139beb93cSSam Leffler * 1239beb93cSSam Leffler * See README and COPYING for more details. 1339beb93cSSam Leffler */ 1439beb93cSSam Leffler 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler 1739beb93cSSam Leffler #include "common.h" 1839beb93cSSam Leffler #include "wps_i.h" 1939beb93cSSam Leffler 20*e28a4053SRui Paulo #define WPS_WORKAROUNDS 21*e28a4053SRui Paulo 2239beb93cSSam Leffler 2339beb93cSSam Leffler static int wps_set_attr(struct wps_parse_attr *attr, u16 type, 2439beb93cSSam Leffler const u8 *pos, u16 len) 2539beb93cSSam Leffler { 2639beb93cSSam Leffler switch (type) { 2739beb93cSSam Leffler case ATTR_VERSION: 2839beb93cSSam Leffler if (len != 1) { 2939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", 3039beb93cSSam Leffler len); 3139beb93cSSam Leffler return -1; 3239beb93cSSam Leffler } 3339beb93cSSam Leffler attr->version = pos; 3439beb93cSSam Leffler break; 3539beb93cSSam Leffler case ATTR_MSG_TYPE: 3639beb93cSSam Leffler if (len != 1) { 3739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " 3839beb93cSSam Leffler "length %u", len); 3939beb93cSSam Leffler return -1; 4039beb93cSSam Leffler } 4139beb93cSSam Leffler attr->msg_type = pos; 4239beb93cSSam Leffler break; 4339beb93cSSam Leffler case ATTR_ENROLLEE_NONCE: 4439beb93cSSam Leffler if (len != WPS_NONCE_LEN) { 4539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " 4639beb93cSSam Leffler "length %u", len); 4739beb93cSSam Leffler return -1; 4839beb93cSSam Leffler } 4939beb93cSSam Leffler attr->enrollee_nonce = pos; 5039beb93cSSam Leffler break; 5139beb93cSSam Leffler case ATTR_REGISTRAR_NONCE: 5239beb93cSSam Leffler if (len != WPS_NONCE_LEN) { 5339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " 5439beb93cSSam Leffler "length %u", len); 5539beb93cSSam Leffler return -1; 5639beb93cSSam Leffler } 5739beb93cSSam Leffler attr->registrar_nonce = pos; 5839beb93cSSam Leffler break; 5939beb93cSSam Leffler case ATTR_UUID_E: 6039beb93cSSam Leffler if (len != WPS_UUID_LEN) { 6139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", 6239beb93cSSam Leffler len); 6339beb93cSSam Leffler return -1; 6439beb93cSSam Leffler } 6539beb93cSSam Leffler attr->uuid_e = pos; 6639beb93cSSam Leffler break; 6739beb93cSSam Leffler case ATTR_UUID_R: 6839beb93cSSam Leffler if (len != WPS_UUID_LEN) { 6939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", 7039beb93cSSam Leffler len); 7139beb93cSSam Leffler return -1; 7239beb93cSSam Leffler } 7339beb93cSSam Leffler attr->uuid_r = pos; 7439beb93cSSam Leffler break; 7539beb93cSSam Leffler case ATTR_AUTH_TYPE_FLAGS: 7639beb93cSSam Leffler if (len != 2) { 7739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " 7839beb93cSSam Leffler "Type Flags length %u", len); 7939beb93cSSam Leffler return -1; 8039beb93cSSam Leffler } 8139beb93cSSam Leffler attr->auth_type_flags = pos; 8239beb93cSSam Leffler break; 8339beb93cSSam Leffler case ATTR_ENCR_TYPE_FLAGS: 8439beb93cSSam Leffler if (len != 2) { 8539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " 8639beb93cSSam Leffler "Flags length %u", len); 8739beb93cSSam Leffler return -1; 8839beb93cSSam Leffler } 8939beb93cSSam Leffler attr->encr_type_flags = pos; 9039beb93cSSam Leffler break; 9139beb93cSSam Leffler case ATTR_CONN_TYPE_FLAGS: 9239beb93cSSam Leffler if (len != 1) { 9339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " 9439beb93cSSam Leffler "Flags length %u", len); 9539beb93cSSam Leffler return -1; 9639beb93cSSam Leffler } 9739beb93cSSam Leffler attr->conn_type_flags = pos; 9839beb93cSSam Leffler break; 9939beb93cSSam Leffler case ATTR_CONFIG_METHODS: 10039beb93cSSam Leffler if (len != 2) { 10139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " 10239beb93cSSam Leffler "length %u", len); 10339beb93cSSam Leffler return -1; 10439beb93cSSam Leffler } 10539beb93cSSam Leffler attr->config_methods = pos; 10639beb93cSSam Leffler break; 10739beb93cSSam Leffler case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: 10839beb93cSSam Leffler if (len != 2) { 10939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " 11039beb93cSSam Leffler "Registrar Config Methods length %u", len); 11139beb93cSSam Leffler return -1; 11239beb93cSSam Leffler } 11339beb93cSSam Leffler attr->sel_reg_config_methods = pos; 11439beb93cSSam Leffler break; 11539beb93cSSam Leffler case ATTR_PRIMARY_DEV_TYPE: 116*e28a4053SRui Paulo if (len != WPS_DEV_TYPE_LEN) { 11739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " 11839beb93cSSam Leffler "Type length %u", len); 11939beb93cSSam Leffler return -1; 12039beb93cSSam Leffler } 12139beb93cSSam Leffler attr->primary_dev_type = pos; 12239beb93cSSam Leffler break; 12339beb93cSSam Leffler case ATTR_RF_BANDS: 12439beb93cSSam Leffler if (len != 1) { 12539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " 12639beb93cSSam Leffler "%u", len); 12739beb93cSSam Leffler return -1; 12839beb93cSSam Leffler } 12939beb93cSSam Leffler attr->rf_bands = pos; 13039beb93cSSam Leffler break; 13139beb93cSSam Leffler case ATTR_ASSOC_STATE: 13239beb93cSSam Leffler if (len != 2) { 13339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " 13439beb93cSSam Leffler "length %u", len); 13539beb93cSSam Leffler return -1; 13639beb93cSSam Leffler } 13739beb93cSSam Leffler attr->assoc_state = pos; 13839beb93cSSam Leffler break; 13939beb93cSSam Leffler case ATTR_CONFIG_ERROR: 14039beb93cSSam Leffler if (len != 2) { 14139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " 14239beb93cSSam Leffler "Error length %u", len); 14339beb93cSSam Leffler return -1; 14439beb93cSSam Leffler } 14539beb93cSSam Leffler attr->config_error = pos; 14639beb93cSSam Leffler break; 14739beb93cSSam Leffler case ATTR_DEV_PASSWORD_ID: 14839beb93cSSam Leffler if (len != 2) { 14939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " 15039beb93cSSam Leffler "ID length %u", len); 15139beb93cSSam Leffler return -1; 15239beb93cSSam Leffler } 15339beb93cSSam Leffler attr->dev_password_id = pos; 15439beb93cSSam Leffler break; 155*e28a4053SRui Paulo case ATTR_OOB_DEVICE_PASSWORD: 156*e28a4053SRui Paulo if (len != WPS_OOB_DEVICE_PASSWORD_ATTR_LEN) { 157*e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device " 158*e28a4053SRui Paulo "Password length %u", len); 159*e28a4053SRui Paulo return -1; 160*e28a4053SRui Paulo } 161*e28a4053SRui Paulo attr->oob_dev_password = pos; 162*e28a4053SRui Paulo break; 16339beb93cSSam Leffler case ATTR_OS_VERSION: 16439beb93cSSam Leffler if (len != 4) { 16539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " 16639beb93cSSam Leffler "%u", len); 16739beb93cSSam Leffler return -1; 16839beb93cSSam Leffler } 16939beb93cSSam Leffler attr->os_version = pos; 17039beb93cSSam Leffler break; 17139beb93cSSam Leffler case ATTR_WPS_STATE: 17239beb93cSSam Leffler if (len != 1) { 17339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " 17439beb93cSSam Leffler "Setup State length %u", len); 17539beb93cSSam Leffler return -1; 17639beb93cSSam Leffler } 17739beb93cSSam Leffler attr->wps_state = pos; 17839beb93cSSam Leffler break; 17939beb93cSSam Leffler case ATTR_AUTHENTICATOR: 18039beb93cSSam Leffler if (len != WPS_AUTHENTICATOR_LEN) { 18139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " 18239beb93cSSam Leffler "length %u", len); 18339beb93cSSam Leffler return -1; 18439beb93cSSam Leffler } 18539beb93cSSam Leffler attr->authenticator = pos; 18639beb93cSSam Leffler break; 18739beb93cSSam Leffler case ATTR_R_HASH1: 18839beb93cSSam Leffler if (len != WPS_HASH_LEN) { 18939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", 19039beb93cSSam Leffler len); 19139beb93cSSam Leffler return -1; 19239beb93cSSam Leffler } 19339beb93cSSam Leffler attr->r_hash1 = pos; 19439beb93cSSam Leffler break; 19539beb93cSSam Leffler case ATTR_R_HASH2: 19639beb93cSSam Leffler if (len != WPS_HASH_LEN) { 19739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", 19839beb93cSSam Leffler len); 19939beb93cSSam Leffler return -1; 20039beb93cSSam Leffler } 20139beb93cSSam Leffler attr->r_hash2 = pos; 20239beb93cSSam Leffler break; 20339beb93cSSam Leffler case ATTR_E_HASH1: 20439beb93cSSam Leffler if (len != WPS_HASH_LEN) { 20539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", 20639beb93cSSam Leffler len); 20739beb93cSSam Leffler return -1; 20839beb93cSSam Leffler } 20939beb93cSSam Leffler attr->e_hash1 = pos; 21039beb93cSSam Leffler break; 21139beb93cSSam Leffler case ATTR_E_HASH2: 21239beb93cSSam Leffler if (len != WPS_HASH_LEN) { 21339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", 21439beb93cSSam Leffler len); 21539beb93cSSam Leffler return -1; 21639beb93cSSam Leffler } 21739beb93cSSam Leffler attr->e_hash2 = pos; 21839beb93cSSam Leffler break; 21939beb93cSSam Leffler case ATTR_R_SNONCE1: 22039beb93cSSam Leffler if (len != WPS_SECRET_NONCE_LEN) { 22139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " 22239beb93cSSam Leffler "%u", len); 22339beb93cSSam Leffler return -1; 22439beb93cSSam Leffler } 22539beb93cSSam Leffler attr->r_snonce1 = pos; 22639beb93cSSam Leffler break; 22739beb93cSSam Leffler case ATTR_R_SNONCE2: 22839beb93cSSam Leffler if (len != WPS_SECRET_NONCE_LEN) { 22939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " 23039beb93cSSam Leffler "%u", len); 23139beb93cSSam Leffler return -1; 23239beb93cSSam Leffler } 23339beb93cSSam Leffler attr->r_snonce2 = pos; 23439beb93cSSam Leffler break; 23539beb93cSSam Leffler case ATTR_E_SNONCE1: 23639beb93cSSam Leffler if (len != WPS_SECRET_NONCE_LEN) { 23739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " 23839beb93cSSam Leffler "%u", len); 23939beb93cSSam Leffler return -1; 24039beb93cSSam Leffler } 24139beb93cSSam Leffler attr->e_snonce1 = pos; 24239beb93cSSam Leffler break; 24339beb93cSSam Leffler case ATTR_E_SNONCE2: 24439beb93cSSam Leffler if (len != WPS_SECRET_NONCE_LEN) { 24539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " 24639beb93cSSam Leffler "%u", len); 24739beb93cSSam Leffler return -1; 24839beb93cSSam Leffler } 24939beb93cSSam Leffler attr->e_snonce2 = pos; 25039beb93cSSam Leffler break; 25139beb93cSSam Leffler case ATTR_KEY_WRAP_AUTH: 25239beb93cSSam Leffler if (len != WPS_KWA_LEN) { 25339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " 25439beb93cSSam Leffler "Authenticator length %u", len); 25539beb93cSSam Leffler return -1; 25639beb93cSSam Leffler } 25739beb93cSSam Leffler attr->key_wrap_auth = pos; 25839beb93cSSam Leffler break; 25939beb93cSSam Leffler case ATTR_AUTH_TYPE: 26039beb93cSSam Leffler if (len != 2) { 26139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " 26239beb93cSSam Leffler "Type length %u", len); 26339beb93cSSam Leffler return -1; 26439beb93cSSam Leffler } 26539beb93cSSam Leffler attr->auth_type = pos; 26639beb93cSSam Leffler break; 26739beb93cSSam Leffler case ATTR_ENCR_TYPE: 26839beb93cSSam Leffler if (len != 2) { 26939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " 27039beb93cSSam Leffler "Type length %u", len); 27139beb93cSSam Leffler return -1; 27239beb93cSSam Leffler } 27339beb93cSSam Leffler attr->encr_type = pos; 27439beb93cSSam Leffler break; 27539beb93cSSam Leffler case ATTR_NETWORK_INDEX: 27639beb93cSSam Leffler if (len != 1) { 27739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " 27839beb93cSSam Leffler "length %u", len); 27939beb93cSSam Leffler return -1; 28039beb93cSSam Leffler } 28139beb93cSSam Leffler attr->network_idx = pos; 28239beb93cSSam Leffler break; 28339beb93cSSam Leffler case ATTR_NETWORK_KEY_INDEX: 28439beb93cSSam Leffler if (len != 1) { 28539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " 28639beb93cSSam Leffler "length %u", len); 28739beb93cSSam Leffler return -1; 28839beb93cSSam Leffler } 28939beb93cSSam Leffler attr->network_key_idx = pos; 29039beb93cSSam Leffler break; 29139beb93cSSam Leffler case ATTR_MAC_ADDR: 29239beb93cSSam Leffler if (len != ETH_ALEN) { 29339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " 29439beb93cSSam Leffler "length %u", len); 29539beb93cSSam Leffler return -1; 29639beb93cSSam Leffler } 29739beb93cSSam Leffler attr->mac_addr = pos; 29839beb93cSSam Leffler break; 29939beb93cSSam Leffler case ATTR_KEY_PROVIDED_AUTO: 30039beb93cSSam Leffler if (len != 1) { 30139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided " 30239beb93cSSam Leffler "Automatically length %u", len); 30339beb93cSSam Leffler return -1; 30439beb93cSSam Leffler } 30539beb93cSSam Leffler attr->key_prov_auto = pos; 30639beb93cSSam Leffler break; 30739beb93cSSam Leffler case ATTR_802_1X_ENABLED: 30839beb93cSSam Leffler if (len != 1) { 30939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled " 31039beb93cSSam Leffler "length %u", len); 31139beb93cSSam Leffler return -1; 31239beb93cSSam Leffler } 31339beb93cSSam Leffler attr->dot1x_enabled = pos; 31439beb93cSSam Leffler break; 31539beb93cSSam Leffler case ATTR_SELECTED_REGISTRAR: 31639beb93cSSam Leffler if (len != 1) { 31739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" 31839beb93cSSam Leffler " length %u", len); 31939beb93cSSam Leffler return -1; 32039beb93cSSam Leffler } 32139beb93cSSam Leffler attr->selected_registrar = pos; 32239beb93cSSam Leffler break; 32339beb93cSSam Leffler case ATTR_REQUEST_TYPE: 32439beb93cSSam Leffler if (len != 1) { 32539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " 32639beb93cSSam Leffler "length %u", len); 32739beb93cSSam Leffler return -1; 32839beb93cSSam Leffler } 32939beb93cSSam Leffler attr->request_type = pos; 33039beb93cSSam Leffler break; 33139beb93cSSam Leffler case ATTR_RESPONSE_TYPE: 33239beb93cSSam Leffler if (len != 1) { 33339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " 33439beb93cSSam Leffler "length %u", len); 33539beb93cSSam Leffler return -1; 33639beb93cSSam Leffler } 337*e28a4053SRui Paulo attr->response_type = pos; 33839beb93cSSam Leffler break; 33939beb93cSSam Leffler case ATTR_MANUFACTURER: 34039beb93cSSam Leffler attr->manufacturer = pos; 34139beb93cSSam Leffler attr->manufacturer_len = len; 34239beb93cSSam Leffler break; 34339beb93cSSam Leffler case ATTR_MODEL_NAME: 34439beb93cSSam Leffler attr->model_name = pos; 34539beb93cSSam Leffler attr->model_name_len = len; 34639beb93cSSam Leffler break; 34739beb93cSSam Leffler case ATTR_MODEL_NUMBER: 34839beb93cSSam Leffler attr->model_number = pos; 34939beb93cSSam Leffler attr->model_number_len = len; 35039beb93cSSam Leffler break; 35139beb93cSSam Leffler case ATTR_SERIAL_NUMBER: 35239beb93cSSam Leffler attr->serial_number = pos; 35339beb93cSSam Leffler attr->serial_number_len = len; 35439beb93cSSam Leffler break; 35539beb93cSSam Leffler case ATTR_DEV_NAME: 35639beb93cSSam Leffler attr->dev_name = pos; 35739beb93cSSam Leffler attr->dev_name_len = len; 35839beb93cSSam Leffler break; 35939beb93cSSam Leffler case ATTR_PUBLIC_KEY: 36039beb93cSSam Leffler attr->public_key = pos; 36139beb93cSSam Leffler attr->public_key_len = len; 36239beb93cSSam Leffler break; 36339beb93cSSam Leffler case ATTR_ENCR_SETTINGS: 36439beb93cSSam Leffler attr->encr_settings = pos; 36539beb93cSSam Leffler attr->encr_settings_len = len; 36639beb93cSSam Leffler break; 36739beb93cSSam Leffler case ATTR_CRED: 36839beb93cSSam Leffler if (attr->num_cred >= MAX_CRED_COUNT) { 36939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " 37039beb93cSSam Leffler "attribute (max %d credentials)", 37139beb93cSSam Leffler MAX_CRED_COUNT); 37239beb93cSSam Leffler break; 37339beb93cSSam Leffler } 37439beb93cSSam Leffler attr->cred[attr->num_cred] = pos; 37539beb93cSSam Leffler attr->cred_len[attr->num_cred] = len; 37639beb93cSSam Leffler attr->num_cred++; 37739beb93cSSam Leffler break; 37839beb93cSSam Leffler case ATTR_SSID: 37939beb93cSSam Leffler attr->ssid = pos; 38039beb93cSSam Leffler attr->ssid_len = len; 38139beb93cSSam Leffler break; 38239beb93cSSam Leffler case ATTR_NETWORK_KEY: 38339beb93cSSam Leffler attr->network_key = pos; 38439beb93cSSam Leffler attr->network_key_len = len; 38539beb93cSSam Leffler break; 38639beb93cSSam Leffler case ATTR_EAP_TYPE: 38739beb93cSSam Leffler attr->eap_type = pos; 38839beb93cSSam Leffler attr->eap_type_len = len; 38939beb93cSSam Leffler break; 39039beb93cSSam Leffler case ATTR_EAP_IDENTITY: 39139beb93cSSam Leffler attr->eap_identity = pos; 39239beb93cSSam Leffler attr->eap_identity_len = len; 39339beb93cSSam Leffler break; 3943157ba21SRui Paulo case ATTR_AP_SETUP_LOCKED: 3953157ba21SRui Paulo if (len != 1) { 3963157ba21SRui Paulo wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked " 3973157ba21SRui Paulo "length %u", len); 3983157ba21SRui Paulo return -1; 3993157ba21SRui Paulo } 4003157ba21SRui Paulo attr->ap_setup_locked = pos; 4013157ba21SRui Paulo break; 40239beb93cSSam Leffler default: 40339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " 40439beb93cSSam Leffler "len=%u", type, len); 40539beb93cSSam Leffler break; 40639beb93cSSam Leffler } 40739beb93cSSam Leffler 40839beb93cSSam Leffler return 0; 40939beb93cSSam Leffler } 41039beb93cSSam Leffler 41139beb93cSSam Leffler 41239beb93cSSam Leffler int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) 41339beb93cSSam Leffler { 41439beb93cSSam Leffler const u8 *pos, *end; 41539beb93cSSam Leffler u16 type, len; 41639beb93cSSam Leffler 41739beb93cSSam Leffler os_memset(attr, 0, sizeof(*attr)); 41839beb93cSSam Leffler pos = wpabuf_head(msg); 41939beb93cSSam Leffler end = pos + wpabuf_len(msg); 42039beb93cSSam Leffler 42139beb93cSSam Leffler while (pos < end) { 42239beb93cSSam Leffler if (end - pos < 4) { 42339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid message - " 42439beb93cSSam Leffler "%lu bytes remaining", 42539beb93cSSam Leffler (unsigned long) (end - pos)); 42639beb93cSSam Leffler return -1; 42739beb93cSSam Leffler } 42839beb93cSSam Leffler 42939beb93cSSam Leffler type = WPA_GET_BE16(pos); 43039beb93cSSam Leffler pos += 2; 43139beb93cSSam Leffler len = WPA_GET_BE16(pos); 43239beb93cSSam Leffler pos += 2; 43339beb93cSSam Leffler wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u", 43439beb93cSSam Leffler type, len); 43539beb93cSSam Leffler if (len > end - pos) { 43639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); 43739beb93cSSam Leffler return -1; 43839beb93cSSam Leffler } 43939beb93cSSam Leffler 440*e28a4053SRui Paulo #ifdef WPS_WORKAROUNDS 441*e28a4053SRui Paulo if (type == 0 && len == 0) { 442*e28a4053SRui Paulo /* 443*e28a4053SRui Paulo * Mac OS X 10.6 seems to be adding 0x00 padding to the 444*e28a4053SRui Paulo * end of M1. Skip those to avoid interop issues. 445*e28a4053SRui Paulo */ 446*e28a4053SRui Paulo int i; 447*e28a4053SRui Paulo for (i = 0; i < end - pos; i++) { 448*e28a4053SRui Paulo if (pos[i]) 449*e28a4053SRui Paulo break; 450*e28a4053SRui Paulo } 451*e28a4053SRui Paulo if (i == end - pos) { 452*e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "WPS: Workaround - skip " 453*e28a4053SRui Paulo "unexpected message padding"); 454*e28a4053SRui Paulo break; 455*e28a4053SRui Paulo } 456*e28a4053SRui Paulo } 457*e28a4053SRui Paulo #endif /* WPS_WORKAROUNDS */ 458*e28a4053SRui Paulo 45939beb93cSSam Leffler if (wps_set_attr(attr, type, pos, len) < 0) 46039beb93cSSam Leffler return -1; 46139beb93cSSam Leffler 46239beb93cSSam Leffler pos += len; 46339beb93cSSam Leffler } 46439beb93cSSam Leffler 46539beb93cSSam Leffler return 0; 46639beb93cSSam Leffler } 467