/** * wpa_parse_wpa_ie_rsn - Parse RSN IE * @rsn_ie: Buffer containing RSN IE * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) * @data: Pointer to structure that will be filled in with parsed data * Returns: 0 on success, <0 on failure */ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data) { const struct rsn_ie_hdr *hdr; const u8 *pos; int left; int i, count; os_memset(data, 0, sizeof(*data)); data->proto = WPA_PROTO_RSN; data->pairwise_cipher = WPA_CIPHER_CCMP; data->group_cipher = WPA_CIPHER_CCMP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; data->capabilities = 0; data->pmkid = NULL; data->num_pmkid = 0; #ifdef CONFIG_IEEE80211W data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; #else /* CONFIG_IEEE80211W */ data->mgmt_group_cipher = 0; #endif /* CONFIG_IEEE80211W */ if (rsn_ie_len == 0) { /* No RSN IE - fail silently */ return -1; } if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) { wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", __func__, (unsigned long) rsn_ie_len); return -1; } hdr = (const struct rsn_ie_hdr *) rsn_ie; if (hdr->elem_id != WLAN_EID_RSN || hdr->len != rsn_ie_len - 2 || WPA_GET_LE16(hdr->version) != RSN_VERSION) { wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", __func__); return -2; } pos = (const u8 *) (hdr + 1); left = rsn_ie_len - sizeof(*hdr); if (left >= RSN_SELECTOR_LEN) { data->group_cipher = rsn_selector_to_bitfield(pos); #ifdef CONFIG_IEEE80211W if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) { wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group " "cipher", __func__); return -1; } #endif /* CONFIG_IEEE80211W */ pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } else if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", __func__, left); return -3; } if (left >= 2) { data->pairwise_cipher = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * RSN_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " "count %u left %u", __func__, count, left); return -4; } for (i = 0; i < count; i++) { data->pairwise_cipher |= rsn_selector_to_bitfield(pos); pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } #ifdef CONFIG_IEEE80211W if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) { wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as " "pairwise cipher", __func__); return -1; } #endif /* CONFIG_IEEE80211W */ } else if (left == 1) { wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", __func__); return -5; } if (left >= 2) { data->key_mgmt = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * RSN_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " "count %u left %u", __func__, count, left); return -6; } for (i = 0; i < count; i++) { data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos); pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } } else if (left == 1) { wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", __func__); return -7; } if (left >= 2) { data->capabilities = WPA_GET_LE16(pos); pos += 2; left -= 2; } if (left >= 2) { data->num_pmkid = WPA_GET_LE16(pos); pos += 2; left -= 2; if (left < (int) data->num_pmkid * PMKID_LEN) { wpa_printf(MSG_DEBUG, "%s: PMKID underflow " "(num_pmkid=%lu left=%d)", __func__, (unsigned long) data->num_pmkid, left); data->num_pmkid = 0; return -9; } else { data->pmkid = pos; pos += data->num_pmkid * PMKID_LEN; left -= data->num_pmkid * PMKID_LEN; } } #ifdef CONFIG_IEEE80211W if (left >= 4) { data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { wpa_printf(MSG_DEBUG, "%s: Unsupported management " "group cipher 0x%x", __func__, data->mgmt_group_cipher); return -10; } pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } #endif /* CONFIG_IEEE80211W */ if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", __func__, left); } return 0; }
static int eth_get(const char *device, u8 ea[ETH_ALEN]) { #ifdef __sun__ dlpi_handle_t dh; u32 physaddrlen = DLPI_PHYSADDR_MAX; u8 physaddr[DLPI_PHYSADDR_MAX]; int retval; retval = dlpi_open(device, &dh, 0); if (retval != DLPI_SUCCESS) { wpa_printf(MSG_ERROR, "dlpi_open error: %s", dlpi_strerror(retval)); return -1; } retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, physaddr, &physaddrlen); if (retval != DLPI_SUCCESS) { wpa_printf(MSG_ERROR, "dlpi_get_physaddr error: %s", dlpi_strerror(retval)); dlpi_close(dh); return -1; } os_memcpy(ea, physaddr, ETH_ALEN); dlpi_close(dh); #else /* __sun__ */ struct if_msghdr *ifm; struct sockaddr_dl *sdl; u_char *p, *buf; size_t len; int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) return -1; if ((buf = os_malloc(len)) == NULL) return -1; if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { os_free(buf); return -1; } for (p = buf; p < buf + len; p += ifm->ifm_msglen) { ifm = (struct if_msghdr *)p; sdl = (struct sockaddr_dl *)(ifm + 1); if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0) continue; if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 || os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0) continue; os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen); break; } os_free(buf); if (p >= buf + len) { errno = ESRCH; return -1; } #endif /* __sun__ */ return 0; }
/** * handle_term - SIGINT and SIGTERM handler to terminate hostapd process */ static void handle_term(int sig, void *signal_ctx) { wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig); eloop_terminate(); }
static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx) { struct wpa_supplicant *wpa_s = eloop_data; wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out"); wpas_wps_ap_pin_disable(wpa_s); }
static int wps_set_attr(struct wps_parse_attr *attr, u16 type, const u8 *pos, u16 len) { switch (type) { case ATTR_VERSION: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", len); return -1; } attr->version = pos; break; case ATTR_MSG_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " "length %u", len); return -1; } attr->msg_type = pos; break; case ATTR_ENROLLEE_NONCE: if (len != WPS_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " "length %u", len); return -1; } attr->enrollee_nonce = pos; break; case ATTR_REGISTRAR_NONCE: if (len != WPS_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " "length %u", len); return -1; } attr->registrar_nonce = pos; break; case ATTR_UUID_E: if (len != WPS_UUID_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", len); return -1; } attr->uuid_e = pos; break; case ATTR_UUID_R: if (len != WPS_UUID_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", len); return -1; } attr->uuid_r = pos; break; case ATTR_AUTH_TYPE_FLAGS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " "Type Flags length %u", len); return -1; } attr->auth_type_flags = pos; break; case ATTR_ENCR_TYPE_FLAGS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " "Flags length %u", len); return -1; } attr->encr_type_flags = pos; break; case ATTR_CONN_TYPE_FLAGS: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " "Flags length %u", len); return -1; } attr->conn_type_flags = pos; break; case ATTR_CONFIG_METHODS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " "length %u", len); return -1; } attr->config_methods = pos; break; case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " "Registrar Config Methods length %u", len); return -1; } attr->sel_reg_config_methods = pos; break; case ATTR_PRIMARY_DEV_TYPE: if (len != WPS_DEV_TYPE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " "Type length %u", len); return -1; } attr->primary_dev_type = pos; break; case ATTR_RF_BANDS: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " "%u", len); return -1; } attr->rf_bands = pos; break; case ATTR_ASSOC_STATE: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " "length %u", len); return -1; } attr->assoc_state = pos; break; case ATTR_CONFIG_ERROR: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " "Error length %u", len); return -1; } attr->config_error = pos; break; case ATTR_DEV_PASSWORD_ID: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " "ID length %u", len); return -1; } attr->dev_password_id = pos; break; case ATTR_OOB_DEVICE_PASSWORD: if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 + WPS_OOB_DEVICE_PASSWORD_MIN_LEN || len > WPS_OOB_PUBKEY_HASH_LEN + 2 + WPS_OOB_DEVICE_PASSWORD_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device " "Password length %u", len); return -1; } attr->oob_dev_password = pos; attr->oob_dev_password_len = len; break; case ATTR_OS_VERSION: if (len != 4) { wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " "%u", len); return -1; } attr->os_version = pos; break; case ATTR_WPS_STATE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " "Setup State length %u", len); return -1; } attr->wps_state = pos; break; case ATTR_AUTHENTICATOR: if (len != WPS_AUTHENTICATOR_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " "length %u", len); return -1; } attr->authenticator = pos; break; case ATTR_R_HASH1: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", len); return -1; } attr->r_hash1 = pos; break; case ATTR_R_HASH2: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", len); return -1; } attr->r_hash2 = pos; break; case ATTR_E_HASH1: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", len); return -1; } attr->e_hash1 = pos; break; case ATTR_E_HASH2: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", len); return -1; } attr->e_hash2 = pos; break; case ATTR_R_SNONCE1: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " "%u", len); return -1; } attr->r_snonce1 = pos; break; case ATTR_R_SNONCE2: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " "%u", len); return -1; } attr->r_snonce2 = pos; break; case ATTR_E_SNONCE1: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " "%u", len); return -1; } attr->e_snonce1 = pos; break; case ATTR_E_SNONCE2: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " "%u", len); return -1; } attr->e_snonce2 = pos; break; case ATTR_KEY_WRAP_AUTH: if (len != WPS_KWA_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " "Authenticator length %u", len); return -1; } attr->key_wrap_auth = pos; break; case ATTR_AUTH_TYPE: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " "Type length %u", len); return -1; } attr->auth_type = pos; break; case ATTR_ENCR_TYPE: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " "Type length %u", len); return -1; } attr->encr_type = pos; break; case ATTR_NETWORK_INDEX: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " "length %u", len); return -1; } attr->network_idx = pos; break; case ATTR_NETWORK_KEY_INDEX: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " "length %u", len); return -1; } attr->network_key_idx = pos; break; case ATTR_MAC_ADDR: if (len != ETH_ALEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " "length %u", len); return -1; } attr->mac_addr = pos; break; case ATTR_KEY_PROVIDED_AUTO: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided " "Automatically length %u", len); return -1; } attr->key_prov_auto = pos; break; case ATTR_802_1X_ENABLED: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled " "length %u", len); return -1; } attr->dot1x_enabled = pos; break; case ATTR_SELECTED_REGISTRAR: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" " length %u", len); return -1; } attr->selected_registrar = pos; break; case ATTR_REQUEST_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " "length %u", len); return -1; } attr->request_type = pos; break; case ATTR_RESPONSE_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " "length %u", len); return -1; } attr->response_type = pos; break; case ATTR_MANUFACTURER: attr->manufacturer = pos; attr->manufacturer_len = len; break; case ATTR_MODEL_NAME: attr->model_name = pos; attr->model_name_len = len; break; case ATTR_MODEL_NUMBER: attr->model_number = pos; attr->model_number_len = len; break; case ATTR_SERIAL_NUMBER: attr->serial_number = pos; attr->serial_number_len = len; break; case ATTR_DEV_NAME: attr->dev_name = pos; attr->dev_name_len = len; break; case ATTR_PUBLIC_KEY: attr->public_key = pos; attr->public_key_len = len; break; case ATTR_ENCR_SETTINGS: attr->encr_settings = pos; attr->encr_settings_len = len; break; case ATTR_CRED: if (attr->num_cred >= MAX_CRED_COUNT) { wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " "attribute (max %d credentials)", MAX_CRED_COUNT); break; } attr->cred[attr->num_cred] = pos; attr->cred_len[attr->num_cred] = len; attr->num_cred++; break; case ATTR_SSID: attr->ssid = pos; attr->ssid_len = len; break; case ATTR_NETWORK_KEY: attr->network_key = pos; attr->network_key_len = len; break; case ATTR_EAP_TYPE: attr->eap_type = pos; attr->eap_type_len = len; break; case ATTR_EAP_IDENTITY: attr->eap_identity = pos; attr->eap_identity_len = len; break; case ATTR_AP_SETUP_LOCKED: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked " "length %u", len); return -1; } attr->ap_setup_locked = pos; break; case ATTR_REQUESTED_DEV_TYPE: if (len != WPS_DEV_TYPE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device " "Type length %u", len); return -1; } if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) { wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device " "Type attribute (max %u types)", MAX_REQ_DEV_TYPE_COUNT); break; } attr->req_dev_type[attr->num_req_dev_type] = pos; attr->num_req_dev_type++; break; case ATTR_SECONDARY_DEV_TYPE_LIST: if (len > WPS_SEC_DEV_TYPE_MAX_LEN || (len % WPS_DEV_TYPE_LEN) > 0) { wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device " "Type length %u", len); return -1; } attr->sec_dev_type_list = pos; attr->sec_dev_type_list_len = len; break; case ATTR_VENDOR_EXT: if (wps_parse_vendor_ext(attr, pos, len) < 0) return -1; break; case ATTR_AP_CHANNEL: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel " "length %u", len); return -1; } attr->ap_channel = pos; break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " "len=%u", type, len); break; } return 0; }
static void eapol_sm_processKey(struct eapol_sm *sm) { struct ieee802_1x_hdr *hdr; struct ieee802_1x_eapol_key *key; struct eap_key_data keydata; u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32]; u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN]; int key_len, res, sign_key_len, encr_key_len; u16 rx_key_length; wpa_printf(MSG_DEBUG, "EAPOL: processKey"); if (sm->last_rx_key == NULL) return; if (!sm->conf.accept_802_1x_keys) { wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key" " even though this was not accepted - " "ignoring this packet"); return; } hdr = (struct ieee802_1x_hdr *) sm->last_rx_key; key = (struct ieee802_1x_eapol_key *) (hdr + 1); if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) { wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame"); return; } rx_key_length = WPA_GET_BE16(key->key_length); wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d " "EAPOL-Key: type=%d key_length=%d key_index=0x%x", hdr->version, hdr->type, be_to_host16(hdr->length), key->type, rx_key_length, key->key_index); eapol_sm_notify_lower_layer_success(sm); sign_key_len = IEEE8021X_SIGN_KEY_LEN; encr_key_len = IEEE8021X_ENCR_KEY_LEN; res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata)); if (res < 0) { wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for " "decrypting EAPOL-Key keys"); return; } if (res == 16) { /* LEAP derives only 16 bytes of keying material. */ res = eapol_sm_get_key(sm, (u8 *) &keydata, 16); if (res) { wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP " "master key for decrypting EAPOL-Key keys"); return; } sign_key_len = 16; encr_key_len = 16; memcpy(keydata.sign_key, keydata.encr_key, 16); } else if (res) { wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key " "data for decrypting EAPOL-Key keys (res=%d)", res); return; } /* The key replay_counter must increase when same master key */ if (sm->replay_counter_valid && memcmp(sm->last_replay_counter, key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN) >= 0) { wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did " "not increase - ignoring key"); wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter", sm->last_replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter", key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); return; } /* Verify key signature (HMAC-MD5) */ memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN); memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN); hmac_md5(keydata.sign_key, sign_key_len, sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length), key->key_signature); if (memcmp(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN) != 0) { wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in " "EAPOL-Key packet"); memcpy(key->key_signature, orig_key_sign, IEEE8021X_KEY_SIGN_LEN); return; } wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified"); key_len = be_to_host16(hdr->length) - sizeof(*key); if (key_len > 32 || rx_key_length > 32) { wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d", key_len ? key_len : rx_key_length); return; } if (key_len == rx_key_length) { memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN); memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key, encr_key_len); memcpy(datakey, key + 1, key_len); rc4(datakey, key_len, ekey, IEEE8021X_KEY_IV_LEN + encr_key_len); wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key", datakey, key_len); } else if (key_len == 0) { /* * IEEE 802.1X-2004 specifies that least significant Key Length * octets from MS-MPPE-Send-Key are used as the key if the key * data is not present. This seems to be meaning the beginning * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator. * Anyway, taking the beginning of the keying material from EAP * seems to interoperate with Authenticators. */ key_len = rx_key_length; memcpy(datakey, keydata.encr_key, key_len); wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying " "material data encryption key", datakey, key_len); } else { wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d " "(key_length=%d)", key_len, rx_key_length); return; } sm->replay_counter_valid = TRUE; memcpy(sm->last_replay_counter, key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d " "len %d", key->key_index & IEEE8021X_KEY_INDEX_FLAG ? "unicast" : "broadcast", key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len); if (sm->ctx->set_wep_key && sm->ctx->set_wep_key(sm->ctx->ctx, key->key_index & IEEE8021X_KEY_INDEX_FLAG, key->key_index & IEEE8021X_KEY_INDEX_MASK, datakey, key_len) < 0) { wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the " " driver."); } else { if (key->key_index & IEEE8021X_KEY_INDEX_FLAG) sm->unicast_key_received = TRUE; else sm->broadcast_key_received = TRUE; if ((sm->unicast_key_received || !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) && (sm->broadcast_key_received || !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST))) { wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key " "frames received"); sm->portValid = TRUE; if (sm->ctx->eapol_done_cb) sm->ctx->eapol_done_cb(sm->ctx->ctx); } } }
int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { struct wpa_driver_associate_params params; struct hostapd_iface *hapd_iface; struct hostapd_config *conf; size_t i; if (ssid->ssid == NULL || ssid->ssid_len == 0) { wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); return -1; } wpa_supplicant_ap_deinit(wpa_s); wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')", wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); os_memset(¶ms, 0, sizeof(params)); params.ssid = ssid->ssid; params.ssid_len = ssid->ssid_len; switch (ssid->mode) { case WPAS_MODE_INFRA: params.mode = IEEE80211_MODE_INFRA; break; case WPAS_MODE_IBSS: params.mode = IEEE80211_MODE_IBSS; break; case WPAS_MODE_AP: case WPAS_MODE_P2P_GO: case WPAS_MODE_P2P_GROUP_FORMATION: params.mode = IEEE80211_MODE_AP; break; } params.freq = ssid->frequency; if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; else wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt); if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; else if (ssid->pairwise_cipher & WPA_CIPHER_TKIP) wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; else if (ssid->pairwise_cipher & WPA_CIPHER_NONE) wpa_s->pairwise_cipher = WPA_CIPHER_NONE; else { wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " "cipher."); return -1; } params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher); params.group_suite = params.pairwise_suite; #ifdef CONFIG_P2P if (ssid->mode == WPAS_MODE_P2P_GO || ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) params.p2p = 1; wpa_drv_set_intra_bss(wpa_s, wpa_s->conf->p2p_intra_bss); #endif /* CONFIG_P2P */ if (wpa_s->parent->set_ap_uapsd) params.uapsd = wpa_s->parent->ap_uapsd; else params.uapsd = -1; if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); return -1; } wpa_s->ap_iface = hapd_iface = os_zalloc(sizeof(*wpa_s->ap_iface)); if (hapd_iface == NULL) return -1; hapd_iface->owner = wpa_s; wpa_s->ap_iface->conf = conf = hostapd_config_defaults(); if (conf == NULL) { wpa_supplicant_ap_deinit(wpa_s); return -1; } if (params.uapsd > 0) { conf->bss->wmm_enabled = 1; conf->bss->wmm_uapsd = 1; } if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) { wpa_printf(MSG_ERROR, "Failed to create AP configuration"); wpa_supplicant_ap_deinit(wpa_s); return -1; } #ifdef CONFIG_P2P if (ssid->mode == WPAS_MODE_P2P_GO) conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER; else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER | P2P_GROUP_FORMATION; #endif /* CONFIG_P2P */ hapd_iface->num_bss = conf->num_bss; hapd_iface->bss = os_zalloc(conf->num_bss * sizeof(struct hostapd_data *)); if (hapd_iface->bss == NULL) { wpa_supplicant_ap_deinit(wpa_s); return -1; } for (i = 0; i < conf->num_bss; i++) { hapd_iface->bss[i] = hostapd_alloc_bss_data(hapd_iface, conf, &conf->bss[i]); if (hapd_iface->bss[i] == NULL) { wpa_supplicant_ap_deinit(wpa_s); return -1; } hapd_iface->bss[i]->msg_ctx = wpa_s; #ifdef ANDROID_BRCM_P2P_PATCH /* Sending the event to parent is required as SSL listens on parent ctrl iface */ hapd_iface->bss[i]->msg_ctx_parent = wpa_s->parent; #endif hapd_iface->bss[i]->public_action_cb = ap_public_action_rx; hapd_iface->bss[i]->public_action_cb_ctx = wpa_s; hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx; hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s; hostapd_register_probereq_cb(hapd_iface->bss[i], ap_probe_req_rx, wpa_s); hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb; hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s; hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb; hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s; hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb; hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s; #ifdef CONFIG_P2P hapd_iface->bss[i]->p2p = wpa_s->global->p2p; hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init( wpa_s, ssid->p2p_persistent_group, ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION); #endif /* CONFIG_P2P */ hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb; hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s; } os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN); hapd_iface->bss[0]->driver = wpa_s->driver; hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv; wpa_s->current_ssid = ssid; os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN); wpa_s->assoc_freq = ssid->frequency; if (hostapd_setup_interface(wpa_s->ap_iface)) { wpa_printf(MSG_ERROR, "Failed to initialize AP interface"); wpa_supplicant_ap_deinit(wpa_s); return -1; } #ifdef ANDROID_BRCM_P2P_PATCH if (wpa_drv_probe_req_report(wpa_s, 1) < 0) { wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver to " "report received Probe Request frames"); return -1; } #endif return 0; }
struct wowlan_triggers * wpa_get_wowlan_triggers(const char *wowlan_triggers, const struct wpa_driver_capa *capa) { struct wowlan_triggers *triggers; char *start, *end, *buf; int last; if (!wowlan_triggers) return NULL; buf = os_strdup(wowlan_triggers); if (buf == NULL) return NULL; triggers = os_zalloc(sizeof(*triggers)); if (triggers == NULL) goto out; #define CHECK_TRIGGER(trigger) \ wpa_check_wowlan_trigger(start, #trigger, \ capa->wowlan_triggers.trigger, \ &triggers->trigger) start = buf; while (*start != '\0') { while (isblank((unsigned char) *start)) start++; if (*start == '\0') break; end = start; while (!isblank((unsigned char) *end) && *end != '\0') end++; last = *end == '\0'; *end = '\0'; if (!CHECK_TRIGGER(any) && !CHECK_TRIGGER(disconnect) && !CHECK_TRIGGER(magic_pkt) && !CHECK_TRIGGER(gtk_rekey_failure) && !CHECK_TRIGGER(eap_identity_req) && !CHECK_TRIGGER(four_way_handshake) && !CHECK_TRIGGER(rfkill_release)) { wpa_printf(MSG_DEBUG, "Unknown/unsupported wowlan trigger '%s'", start); os_free(triggers); triggers = NULL; goto out; } if (last) break; start = end + 1; } #undef CHECK_TRIGGER out: os_free(buf); return triggers; }
int main(int argc, char *argv[]) { int c, i; struct wpa_interface *ifaces, *iface; int iface_count, exitcode = -1; struct wpa_params params; struct wpa_global *global; if (os_program_init()) return -1; os_memset(¶ms, 0, sizeof(params)); params.wpa_debug_level = MSG_INFO; iface = ifaces = os_zalloc(sizeof(struct wpa_interface)); if (ifaces == NULL) return -1; iface_count = 1; wpa_supplicant_fd_workaround(1); for (;;) { c = getopt(argc, argv, "b:Bc:C:D:de:f:g:G:hi:I:KLm:No:O:p:P:qsTtuvW"); if (c < 0) break; switch (c) { case 'b': iface->bridge_ifname = optarg; break; case 'B': params.daemonize++; break; case 'c': iface->confname = optarg; break; case 'C': iface->ctrl_interface = optarg; break; case 'D': iface->driver = optarg; break; case 'd': #ifdef CONFIG_NO_STDOUT_DEBUG printf("Debugging disabled with " "CONFIG_NO_STDOUT_DEBUG=y build time " "option.\n"); goto out; #else /* CONFIG_NO_STDOUT_DEBUG */ params.wpa_debug_level--; break; #endif /* CONFIG_NO_STDOUT_DEBUG */ case 'e': params.entropy_file = optarg; break; #ifdef CONFIG_DEBUG_FILE case 'f': params.wpa_debug_file_path = optarg; break; #endif /* CONFIG_DEBUG_FILE */ case 'g': params.ctrl_interface = optarg; break; case 'G': params.ctrl_interface_group = optarg; break; case 'h': usage(); exitcode = 0; goto out; case 'i': iface->ifname = optarg; break; case 'I': iface->confanother = optarg; break; case 'K': params.wpa_debug_show_keys++; break; case 'L': license(); exitcode = 0; goto out; #ifdef CONFIG_P2P case 'm': iface->conf_p2p_dev = optarg; break; #endif /* CONFIG_P2P */ case 'o': params.override_driver = optarg; break; case 'O': params.override_ctrl_interface = optarg; break; case 'p': iface->driver_param = optarg; break; case 'P': os_free(params.pid_file); params.pid_file = os_rel2abs_path(optarg); break; case 'q': params.wpa_debug_level++; break; #ifdef CONFIG_DEBUG_SYSLOG case 's': params.wpa_debug_syslog++; break; #endif /* CONFIG_DEBUG_SYSLOG */ #ifdef CONFIG_DEBUG_LINUX_TRACING case 'T': params.wpa_debug_tracing++; break; #endif /* CONFIG_DEBUG_LINUX_TRACING */ case 't': params.wpa_debug_timestamp++; break; #ifdef CONFIG_DBUS case 'u': params.dbus_ctrl_interface = 1; break; #endif /* CONFIG_DBUS */ case 'v': printf("%s\n", wpa_supplicant_version); exitcode = 0; goto out; case 'W': params.wait_for_monitor++; break; case 'N': iface_count++; iface = os_realloc_array(ifaces, iface_count, sizeof(struct wpa_interface)); if (iface == NULL) goto out; ifaces = iface; iface = &ifaces[iface_count - 1]; os_memset(iface, 0, sizeof(*iface)); break; default: usage(); exitcode = 0; goto out; } } exitcode = 0; global = wpa_supplicant_init(¶ms); if (global == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant"); exitcode = -1; goto out; } else { wpa_printf(MSG_INFO, "Successfully initialized " "wpa_supplicant"); } for (i = 0; exitcode == 0 && i < iface_count; i++) { struct wpa_supplicant *wpa_s; if ((ifaces[i].confname == NULL && ifaces[i].ctrl_interface == NULL) || ifaces[i].ifname == NULL) { if (iface_count == 1 && (params.ctrl_interface || params.dbus_ctrl_interface)) break; usage(); exitcode = -1; break; } wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL); if (wpa_s == NULL) { exitcode = -1; break; } } if (exitcode == 0) exitcode = wpa_supplicant_run(global); wpa_supplicant_deinit(global); out: wpa_supplicant_fd_workaround(0); os_free(ifaces); os_free(params.pid_file); os_program_deinit(); return exitcode; }
struct ctrl_iface_global_priv * wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) { struct ctrl_iface_global_priv *priv; struct sockaddr_un addr; priv = os_zalloc(sizeof(*priv)); if (priv == NULL) return NULL; priv->global = global; priv->sock = -1; if (global->params.ctrl_interface == NULL) return priv; #ifdef ANDROID priv->sock = android_get_control_socket(global->params.ctrl_interface); if (priv->sock >= 0) goto havesock; #endif wpa_printf(MSG_DEBUG, "Global control interface '%s'", global->params.ctrl_interface); priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); if (priv->sock < 0) { perror("socket(PF_UNIX)"); goto fail; } os_memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; os_strncpy(addr.sun_path, global->params.ctrl_interface, sizeof(addr.sun_path)); if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(PF_UNIX)"); if (connect(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" " allow connections - assuming it was left" "over from forced program termination"); if (unlink(global->params.ctrl_interface) < 0) { perror("unlink[ctrl_iface]"); wpa_printf(MSG_ERROR, "Could not unlink " "existing ctrl_iface socket '%s'", global->params.ctrl_interface); goto fail; } if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(PF_UNIX)"); goto fail; } wpa_printf(MSG_DEBUG, "Successfully replaced leftover " "ctrl_iface socket '%s'", global->params.ctrl_interface); } else { wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " "be in use - cannot override it"); wpa_printf(MSG_INFO, "Delete '%s' manually if it is " "not used anymore", global->params.ctrl_interface); goto fail; } } havesock: eloop_register_read_sock(priv->sock, wpa_supplicant_global_ctrl_iface_receive, global, NULL); return priv; fail: if (priv->sock >= 0) close(priv->sock); os_free(priv); return NULL; }
int wpas_wfd_parse_config(struct wpa_config *conf, struct wfd_config *wfd) { if (conf->wfd_enable && wpas_wfd_y_n_str2bin(conf->wfd_enable, &wfd->enabled) < 0) { wpa_printf(MSG_ERROR, "WFD: Invalid wfd_enable value"); return -1; } if (conf->wfd_device_type && wpas_wfd_device_type_str2bin(conf->wfd_device_type, &wfd->device_type)) { wpa_printf(MSG_ERROR, "WFD: Invalid wfd_device_type value"); return -1; } if (conf->wfd_coupled_sink_supported_by_source && wpas_wfd_y_n_str2bin(conf->wfd_coupled_sink_supported_by_source, &wfd->coupled_sink_supported_by_source)) { wpa_printf(MSG_ERROR, "WFD: Invalid wfd_coupled_sink_supported_by_source value"); return -1; } if (conf->wfd_coupled_sink_supported_by_sink && wpas_wfd_y_n_str2bin(conf->wfd_coupled_sink_supported_by_sink, &wfd->coupled_sink_supported_by_sink)) { wpa_printf(MSG_ERROR, "WFD: Invalid wfd_coupled_sink_supported_by_sink value"); return -1; } if (conf->wfd_available_for_session && wpas_wfd_y_n_str2bin(conf->wfd_available_for_session, &wfd->available_for_session)) { wpa_printf(MSG_ERROR, "WFD: Invalid wfd_available_for_session value"); return -1; } if (conf->wfd_service_discovery_supported && wpas_wfd_y_n_str2bin(conf->wfd_service_discovery_supported, &wfd->service_discovery_supported)) { wpa_printf(MSG_ERROR, "WFD: Invalid wfd_service_discovery_supported value"); return -1; } if (conf->wfd_preferred_connectivity && wpas_wfd_preferred_connectivity_str2bin( conf->wfd_preferred_connectivity, &wfd->preferred_connectivity)) { wpa_printf(MSG_ERROR, "WFD: Invalid wfd_preferred_connectivity value"); return -1; } if (conf->wfd_content_protection_supported && wpas_wfd_y_n_str2bin(conf->wfd_content_protection_supported, &wfd->content_protection_supported)) { wpa_printf(MSG_ERROR, "WFD: Invalid wfd_content_protection_supported value"); return -1; } if (conf->wfd_time_sync_supported && wpas_wfd_y_n_str2bin(conf->wfd_time_sync_supported, &wfd->time_sync_supported)) { wpa_printf(MSG_ERROR, "WFD: Invalid wfd_time_sync_supported value"); return -1; } if (conf->primarysink_audio_notsupported && wpas_wfd_y_n_str2bin(conf->primarysink_audio_notsupported, &wfd->primarysink_audio_notsupported)) { wpa_printf(MSG_ERROR, "WFD: Invalid primarysink_audio_notsupported value"); return -1; } if (conf->source_audio_only_supported && wpas_wfd_y_n_str2bin(conf->source_audio_only_supported, &wfd->source_audio_only_supported)) { wpa_printf(MSG_ERROR, "WFD: Invalid source_audio_only_supported value"); return -1; } if (conf->tdls_persistent_group_intended && wpas_wfd_y_n_str2bin(conf->tdls_persistent_group_intended, &wfd->tdls_persistent_group_intended)) { wpa_printf(MSG_ERROR, "WFD: Invalid tdls_persistent_group_intended value"); return -1; } if (conf->tdls_persistent_group_reinvoke && wpas_wfd_y_n_str2bin(conf->tdls_persistent_group_reinvoke, &wfd->tdls_persistent_group_reinvoke)) { wpa_printf(MSG_ERROR, "WFD: Invalid tdls_persistent_group_reinvoke value"); return -1; } wfd->session_mgmt_ctrl_port = conf->wfd_session_mgmt_ctrl_port; wfd->device_max_throughput = conf->wfd_device_max_throughput; return 0; }
struct ctrl_iface_priv * wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) { struct ctrl_iface_priv *priv; struct sockaddr_un addr; char *fname = NULL; gid_t gid = 0; int gid_set = 0; char *buf, *dir = NULL, *gid_str = NULL; struct group *grp; char *endp; priv = os_zalloc(sizeof(*priv)); if (priv == NULL) return NULL; priv->wpa_s = wpa_s; priv->sock = -1; if (wpa_s->conf->ctrl_interface == NULL) return priv; buf = os_strdup(wpa_s->conf->ctrl_interface); if (buf == NULL) goto fail; #ifdef ANDROID os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", wpa_s->conf->ctrl_interface); priv->sock = android_get_control_socket(addr.sun_path); if (priv->sock >= 0) goto havesock; #endif if (os_strncmp(buf, "DIR=", 4) == 0) { dir = buf + 4; gid_str = os_strstr(dir, " GROUP="); if (gid_str) { *gid_str = '\0'; gid_str += 7; } } else { dir = buf; gid_str = wpa_s->conf->ctrl_interface_group; } if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) { if (errno == EEXIST) { wpa_printf(MSG_DEBUG, "Using existing control " "interface directory."); } else { perror("mkdir[ctrl_interface]"); goto fail; } } if (gid_str) { grp = getgrnam(gid_str); if (grp) { gid = grp->gr_gid; gid_set = 1; wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" " (from group name '%s')", (int) gid, gid_str); } else { /* Group name not found - try to parse this as gid */ gid = strtol(gid_str, &endp, 10); if (*gid_str == '\0' || *endp != '\0') { wpa_printf(MSG_ERROR, "CTRL: Invalid group " "'%s'", gid_str); goto fail; } gid_set = 1; wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", (int) gid); } } if (gid_set && chown(dir, -1, gid) < 0) { perror("chown[ctrl_interface]"); goto fail; } if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >= sizeof(addr.sun_path)) goto fail; priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); if (priv->sock < 0) { perror("socket(PF_UNIX)"); goto fail; } os_memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; fname = wpa_supplicant_ctrl_iface_path(wpa_s); if (fname == NULL) goto fail; os_strncpy(addr.sun_path, fname, sizeof(addr.sun_path)); if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", strerror(errno)); if (connect(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" " allow connections - assuming it was left" "over from forced program termination"); if (unlink(fname) < 0) { perror("unlink[ctrl_iface]"); wpa_printf(MSG_ERROR, "Could not unlink " "existing ctrl_iface socket '%s'", fname); goto fail; } if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(PF_UNIX)"); goto fail; } wpa_printf(MSG_DEBUG, "Successfully replaced leftover " "ctrl_iface socket '%s'", fname); } else { wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " "be in use - cannot override it"); wpa_printf(MSG_INFO, "Delete '%s' manually if it is " "not used anymore", fname); os_free(fname); fname = NULL; goto fail; } } if (gid_set && chown(fname, -1, gid) < 0) { perror("chown[ctrl_interface/ifname]"); goto fail; } if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { perror("chmod[ctrl_interface/ifname]"); goto fail; } os_free(fname); havesock: eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv); wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); os_free(buf); return priv; fail: if (priv->sock >= 0) close(priv->sock); os_free(priv); if (fname) { unlink(fname); os_free(fname); } os_free(buf); return NULL; }
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) { u8 *start, *end, *rpos, *rend; int added = 0; start = ies; end = ies + ies_len; while (start < end) { if (*start == WLAN_EID_RSN) break; start += 2 + start[1]; } if (start >= end) { wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in " "IEs data"); return -1; } wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification", start, 2 + start[1]); /* Find start of PMKID-Count */ rpos = start + 2; rend = rpos + start[1]; /* Skip Version and Group Data Cipher Suite */ rpos += 2 + 4; /* Skip Pairwise Cipher Suite Count and List */ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; /* Skip AKM Suite Count and List */ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; if (rpos == rend) { /* Add RSN Capabilities */ os_memmove(rpos + 2, rpos, end - rpos); *rpos++ = 0; *rpos++ = 0; } else { /* Skip RSN Capabilities */ rpos += 2; if (rpos > rend) { wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in " "IEs data"); return -1; } } if (rpos == rend) { /* No PMKID-Count field included; add it */ os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos); WPA_PUT_LE16(rpos, 1); rpos += 2; os_memcpy(rpos, pmkid, PMKID_LEN); added += 2 + PMKID_LEN; start[1] += 2 + PMKID_LEN; } else { /* PMKID-Count was included; use it */ if (WPA_GET_LE16(rpos) != 0) { wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " "in RSN IE in EAPOL-Key data"); return -1; } WPA_PUT_LE16(rpos, 1); rpos += 2; os_memmove(rpos + PMKID_LEN, rpos, end - rpos); os_memcpy(rpos, pmkid, PMKID_LEN); added += PMKID_LEN; start[1] += PMKID_LEN; } wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " "(PMKID inserted)", start, 2 + start[1]); return added; }
int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data) { const struct wpa_ie_hdr *hdr; const u8 *pos; int left; int i, count; os_memset(data, 0, sizeof(*data)); data->proto = WPA_PROTO_WPA; data->pairwise_cipher = WPA_CIPHER_TKIP; data->group_cipher = WPA_CIPHER_TKIP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; data->capabilities = 0; data->pmkid = NULL; data->num_pmkid = 0; data->mgmt_group_cipher = 0; if (wpa_ie_len == 0) { /* No WPA IE - fail silently */ return -1; } if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", __func__, (unsigned long) wpa_ie_len); return -1; } hdr = (const struct wpa_ie_hdr *) wpa_ie; if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || hdr->len != wpa_ie_len - 2 || RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || WPA_GET_LE16(hdr->version) != WPA_VERSION) { wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", __func__); return -2; } pos = (const u8 *) (hdr + 1); left = wpa_ie_len - sizeof(*hdr); if (left >= WPA_SELECTOR_LEN) { data->group_cipher = wpa_selector_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } else if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", __func__, left); return -3; } if (left >= 2) { data->pairwise_cipher = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " "count %u left %u", __func__, count, left); return -4; } for (i = 0; i < count; i++) { data->pairwise_cipher |= wpa_selector_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } } else if (left == 1) { wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", __func__); return -5; } if (left >= 2) { data->key_mgmt = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " "count %u left %u", __func__, count, left); return -6; } for (i = 0; i < count; i++) { data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } } else if (left == 1) { wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", __func__); return -7; } if (left >= 2) { data->capabilities = WPA_GET_LE16(pos); pos += 2; left -= 2; } if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", __func__, left); } return 0; }
static int p2p_parse_attribute(u8 id, const u8 *data, u16 len, struct p2p_message *msg) { const u8 *pos; size_t i, nlen; char devtype[WPS_DEV_TYPE_BUFSIZE]; switch (id) { case P2P_ATTR_CAPABILITY: if (len < 2) { wpa_printf(MSG_DEBUG, "P2P: Too short Capability " "attribute (length %d)", len); return -1; } msg->capability = data; wpa_printf(MSG_DEBUG, "P2P: * Device Capability %02x " "Group Capability %02x", data[0], data[1]); break; case P2P_ATTR_DEVICE_ID: if (len < ETH_ALEN) { wpa_printf(MSG_DEBUG, "P2P: Too short Device ID " "attribute (length %d)", len); return -1; } msg->device_id = data; wpa_printf(MSG_DEBUG, "P2P: * Device ID " MACSTR, MAC2STR(msg->device_id)); break; case P2P_ATTR_GROUP_OWNER_INTENT: if (len < 1) { wpa_printf(MSG_DEBUG, "P2P: Too short GO Intent " "attribute (length %d)", len); return -1; } msg->go_intent = data; wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u " "Tie breaker %u", data[0] >> 1, data[0] & 0x01); break; case P2P_ATTR_STATUS: if (len < 1) { wpa_printf(MSG_DEBUG, "P2P: Too short Status " "attribute (length %d)", len); return -1; } msg->status = data; wpa_printf(MSG_DEBUG, "P2P: * Status: %d", data[0]); break; case P2P_ATTR_LISTEN_CHANNEL: if (len == 0) { wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Ignore " "null channel"); break; } if (len < 5) { wpa_printf(MSG_DEBUG, "P2P: Too short Listen Channel " "attribute (length %d)", len); return -1; } msg->listen_channel = data; wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: " "Country %c%c(0x%02x) Regulatory " "Class %d Channel Number %d", data[0], data[1], data[2], data[3], data[4]); break; case P2P_ATTR_OPERATING_CHANNEL: if (len == 0) { wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: " "Ignore null channel"); break; } if (len < 5) { wpa_printf(MSG_DEBUG, "P2P: Too short Operating " "Channel attribute (length %d)", len); return -1; } msg->operating_channel = data; wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: " "Country %c%c(0x%02x) Regulatory " "Class %d Channel Number %d", data[0], data[1], data[2], data[3], data[4]); break; case P2P_ATTR_CHANNEL_LIST: if (len < 3) { wpa_printf(MSG_DEBUG, "P2P: Too short Channel List " "attribute (length %d)", len); return -1; } msg->channel_list = data; msg->channel_list_len = len; wpa_printf(MSG_DEBUG, "P2P: * Channel List: Country String " "'%c%c(0x%02x)'", data[0], data[1], data[2]); wpa_hexdump(MSG_MSGDUMP, "P2P: Channel List", msg->channel_list, msg->channel_list_len); break; case P2P_ATTR_GROUP_INFO: msg->group_info = data; msg->group_info_len = len; wpa_printf(MSG_DEBUG, "P2P: * Group Info"); break; case P2P_ATTR_DEVICE_INFO: if (len < ETH_ALEN + 2 + 8 + 1) { wpa_printf(MSG_DEBUG, "P2P: Too short Device Info " "attribute (length %d)", len); return -1; } msg->p2p_device_info = data; msg->p2p_device_info_len = len; pos = data; msg->p2p_device_addr = pos; pos += ETH_ALEN; msg->config_methods = WPA_GET_BE16(pos); pos += 2; msg->pri_dev_type = pos; pos += 8; msg->num_sec_dev_types = *pos++; if (msg->num_sec_dev_types * 8 > data + len - pos) { wpa_printf(MSG_DEBUG, "P2P: Device Info underflow"); return -1; } pos += msg->num_sec_dev_types * 8; if (data + len - pos < 4) { wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name " "length %d", (int) (data + len - pos)); return -1; } if (WPA_GET_BE16(pos) != ATTR_DEV_NAME) { wpa_hexdump(MSG_DEBUG, "P2P: Unexpected Device Name " "header", pos, 4); return -1; } pos += 2; nlen = WPA_GET_BE16(pos); pos += 2; if (data + len - pos < (int) nlen || nlen > 32) { wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name " "length %d (buf len %d)", (int) nlen, (int) (data + len - pos)); return -1; } os_memcpy(msg->device_name, pos, nlen); msg->device_name[nlen] = '\0'; for (i = 0; i < nlen; i++) { if (msg->device_name[i] == '\0') break; if (msg->device_name[i] > 0 && msg->device_name[i] < 32) msg->device_name[i] = '_'; } wpa_printf(MSG_DEBUG, "P2P: * Device Info: addr " MACSTR " primary device type %s device name '%s' " "config methods 0x%x", MAC2STR(msg->p2p_device_addr), wps_dev_type_bin2str(msg->pri_dev_type, devtype, sizeof(devtype)), msg->device_name, msg->config_methods); break; case P2P_ATTR_CONFIGURATION_TIMEOUT: if (len < 2) { wpa_printf(MSG_DEBUG, "P2P: Too short Configuration " "Timeout attribute (length %d)", len); return -1; } msg->config_timeout = data; wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout"); break; case P2P_ATTR_INTENDED_INTERFACE_ADDR: if (len < ETH_ALEN) { wpa_printf(MSG_DEBUG, "P2P: Too short Intended P2P " "Interface Address attribute (length %d)", len); return -1; } msg->intended_addr = data; wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address: " MACSTR, MAC2STR(msg->intended_addr)); break; case P2P_ATTR_GROUP_BSSID: if (len < ETH_ALEN) { wpa_printf(MSG_DEBUG, "P2P: Too short P2P Group BSSID " "attribute (length %d)", len); return -1; } msg->group_bssid = data; wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID: " MACSTR, MAC2STR(msg->group_bssid)); break; case P2P_ATTR_GROUP_ID: if (len < ETH_ALEN || len > ETH_ALEN + 32) { wpa_printf(MSG_DEBUG, "P2P: Invalid P2P Group ID " "attribute length %d", len); return -1; } msg->group_id = data; msg->group_id_len = len; wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID: Device Address " MACSTR, MAC2STR(msg->group_id)); wpa_hexdump_ascii(MSG_DEBUG, "P2P: * P2P Group ID: SSID", msg->group_id + ETH_ALEN, msg->group_id_len - ETH_ALEN); break; case P2P_ATTR_INVITATION_FLAGS: if (len < 1) { wpa_printf(MSG_DEBUG, "P2P: Too short Invitation " "Flag attribute (length %d)", len); return -1; } msg->invitation_flags = data; wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x", data[0]); break; case P2P_ATTR_MANAGEABILITY: if (len < 1) { wpa_printf(MSG_DEBUG, "P2P: Too short Manageability " "attribute (length %d)", len); return -1; } msg->manageability = data; wpa_printf(MSG_DEBUG, "P2P: * Manageability: bitmap 0x%x", data[0]); break; case P2P_ATTR_NOTICE_OF_ABSENCE: if (len < 2) { wpa_printf(MSG_DEBUG, "P2P: Too short Notice of " "Absence attribute (length %d)", len); return -1; } msg->noa = data; msg->noa_len = len; wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence"); break; case P2P_ATTR_EXT_LISTEN_TIMING: if (len < 4) { wpa_printf(MSG_DEBUG, "P2P: Too short Extended Listen " "Timing attribute (length %d)", len); return -1; } msg->ext_listen_timing = data; wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing " "(period %u msec interval %u msec)", WPA_GET_LE16(msg->ext_listen_timing), WPA_GET_LE16(msg->ext_listen_timing + 2)); break; case P2P_ATTR_MINOR_REASON_CODE: if (len < 1) { wpa_printf(MSG_DEBUG, "P2P: Too short Minor Reason " "Code attribute (length %d)", len); return -1; } msg->minor_reason_code = data; wpa_printf(MSG_DEBUG, "P2P: * Minor Reason Code: %u", *msg->minor_reason_code); break; default: wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d " "(length %d)", id, len); break; } return 0; }
void ap_list_process_beacon(struct hostapd_iface *iface, const struct ieee80211_mgmt *mgmt, struct ieee802_11_elems *elems, struct hostapd_frame_info *fi) { struct ap_info *ap; struct os_time now; int new_ap = 0; size_t len; int set_beacon = 0; if (iface->conf->ap_table_max_size < 1) return; ap = ap_get_ap(iface, mgmt->bssid); if (!ap) { ap = ap_ap_add(iface, mgmt->bssid); if (!ap) { printf("Failed to allocate AP information entry\n"); return; } new_ap = 1; } ap->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int); ap->capability = le_to_host16(mgmt->u.beacon.capab_info); if (elems->ssid) { len = elems->ssid_len; if (len >= sizeof(ap->ssid)) len = sizeof(ap->ssid) - 1; os_memcpy(ap->ssid, elems->ssid, len); ap->ssid[len] = '\0'; ap->ssid_len = len; } os_memset(ap->supported_rates, 0, WLAN_SUPP_RATES_MAX); len = 0; if (elems->supp_rates) { len = elems->supp_rates_len; if (len > WLAN_SUPP_RATES_MAX) len = WLAN_SUPP_RATES_MAX; os_memcpy(ap->supported_rates, elems->supp_rates, len); } if (elems->ext_supp_rates) { int len2; if (len + elems->ext_supp_rates_len > WLAN_SUPP_RATES_MAX) len2 = WLAN_SUPP_RATES_MAX - len; else len2 = elems->ext_supp_rates_len; os_memcpy(ap->supported_rates + len, elems->ext_supp_rates, len2); } ap->wpa = elems->wpa_ie != NULL; if (elems->erp_info && elems->erp_info_len == 1) ap->erp = elems->erp_info[0]; else ap->erp = -1; if (elems->ds_params && elems->ds_params_len == 1) ap->channel = elems->ds_params[0]; else if (fi) ap->channel = fi->channel; if (elems->ht_capabilities) ap->ht_support = 1; else ap->ht_support = 0; ap->num_beacons++; os_get_time(&now); ap->last_beacon = now.sec; if (fi) { ap->ssi_signal = fi->ssi_signal; ap->datarate = fi->datarate; } if (!new_ap && ap != iface->ap_list) { /* move AP entry into the beginning of the list so that the * oldest entry is always in the end of the list */ ap_ap_list_del(iface, ap); ap_ap_list_add(iface, ap); } if (!iface->olbc && ap_list_beacon_olbc(iface, ap)) { iface->olbc = 1; wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR " - enable " "protection", MAC2STR(ap->addr)); set_beacon++; } #ifdef CONFIG_IEEE80211N if (!iface->olbc_ht && !ap->ht_support) { iface->olbc_ht = 1; hostapd_ht_operation_update(iface); wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR " - enable protection", MAC2STR(ap->addr)); set_beacon++; } #endif /* CONFIG_IEEE80211N */ if (set_beacon) ieee802_11_set_beacons(iface); }
/** * eapol_sm_rx_eapol - Process received EAPOL frames * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @src: Source MAC address of the EAPOL packet * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) * @len: Length of the EAPOL frame * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine, * -1 failure */ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, size_t len) { const struct ieee802_1x_hdr *hdr; const struct ieee802_1x_eapol_key *key; int plen, data_len; int res = 1; if (sm == NULL) return 0; sm->dot1xSuppEapolFramesRx++; if (len < sizeof(*hdr)) { sm->dot1xSuppInvalidEapolFramesRx++; return 0; } hdr = (const struct ieee802_1x_hdr *) buf; sm->dot1xSuppLastEapolFrameVersion = hdr->version; memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN); if (hdr->version < EAPOL_VERSION) { /* TODO: backwards compatibility */ } plen = be_to_host16(hdr->length); if (plen > len - sizeof(*hdr)) { sm->dot1xSuppEapLengthErrorFramesRx++; return 0; } data_len = plen + sizeof(*hdr); switch (hdr->type) { case IEEE802_1X_TYPE_EAP_PACKET: if (sm->cached_pmk) { /* Trying to use PMKSA caching, but Authenticator did * not seem to have a matching entry. Need to restart * EAPOL state machines. */ eapol_sm_abort_cached(sm); } free(sm->eapReqData); sm->eapReqDataLen = plen; sm->eapReqData = malloc(sm->eapReqDataLen); if (sm->eapReqData) { wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " "frame"); memcpy(sm->eapReqData, (u8 *) (hdr + 1), sm->eapReqDataLen); sm->eapolEap = TRUE; eapol_sm_step(sm); } break; case IEEE802_1X_TYPE_EAPOL_KEY: if (plen < sizeof(*key)) { wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key " "frame received"); break; } key = (const struct ieee802_1x_eapol_key *) (hdr + 1); if (key->type == EAPOL_KEY_TYPE_WPA || key->type == EAPOL_KEY_TYPE_RSN) { /* WPA Supplicant takes care of this frame. */ wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key " "frame in EAPOL state machines"); res = 0; break; } if (key->type != EAPOL_KEY_TYPE_RC4) { wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown " "EAPOL-Key type %d", key->type); break; } free(sm->last_rx_key); sm->last_rx_key = malloc(data_len); if (sm->last_rx_key) { wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key " "frame"); memcpy(sm->last_rx_key, buf, data_len); sm->last_rx_key_len = data_len; sm->rxKey = TRUE; eapol_sm_step(sm); } break; default: wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d", hdr->type); sm->dot1xSuppInvalidEapolFramesRx++; break; } return res; }
/* MLME-SLEEPMODE.response */ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 action_type, u16 intval) { struct ieee80211_mgmt *mgmt; int res; size_t len; size_t gtk_elem_len = 0; size_t igtk_elem_len = 0; struct wnm_sleep_element wnmsleep_ie; u8 *wnmtfs_ie; u8 wnmsleep_ie_len; u16 wnmtfs_ie_len; u8 *pos; struct sta_info *sta; enum wnm_oper tfs_oper = action_type == WNM_SLEEP_MODE_ENTER ? WNM_SLEEP_TFS_RESP_IE_ADD : WNM_SLEEP_TFS_RESP_IE_NONE; sta = ap_get_sta(hapd, addr); if (sta == NULL) { wpa_printf(MSG_DEBUG, "%s: station not found", __func__); return -EINVAL; } /* WNM-Sleep Mode IE */ os_memset(&wnmsleep_ie, 0, sizeof(struct wnm_sleep_element)); wnmsleep_ie_len = sizeof(struct wnm_sleep_element); wnmsleep_ie.eid = WLAN_EID_WNMSLEEP; wnmsleep_ie.len = wnmsleep_ie_len - 2; wnmsleep_ie.action_type = action_type; wnmsleep_ie.status = WNM_STATUS_SLEEP_ACCEPT; wnmsleep_ie.intval = host_to_le16(intval); /* TFS IE(s) */ wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN); if (wnmtfs_ie == NULL) return -1; if (ieee80211_11_get_tfs_ie(hapd, addr, wnmtfs_ie, &wnmtfs_ie_len, tfs_oper)) { wnmtfs_ie_len = 0; os_free(wnmtfs_ie); wnmtfs_ie = NULL; } #define MAX_GTK_SUBELEM_LEN 45 #define MAX_IGTK_SUBELEM_LEN 26 mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN); if (mgmt == NULL) { wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for " "WNM-Sleep Response action frame"); return -1; } os_memcpy(mgmt->da, addr, ETH_ALEN); os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); mgmt->u.action.category = WLAN_ACTION_WNM; mgmt->u.action.u.wnm_sleep_resp.action = WNM_SLEEP_MODE_RESP; mgmt->u.action.u.wnm_sleep_resp.dialogtoken = dialog_token; pos = (u8 *)mgmt->u.action.u.wnm_sleep_resp.variable; /* add key data if MFP is enabled */ if (!wpa_auth_uses_mfp(sta->wpa_sm) || action_type != WNM_SLEEP_MODE_EXIT) { mgmt->u.action.u.wnm_sleep_resp.keydata_len = 0; } else { gtk_elem_len = wpa_wnmsleep_gtk_subelem(sta->wpa_sm, pos); pos += gtk_elem_len; wpa_printf(MSG_DEBUG, "Pass 4, gtk_len = %d", (int) gtk_elem_len); #ifdef CONFIG_IEEE80211W res = wpa_wnmsleep_igtk_subelem(sta->wpa_sm, pos); if (res < 0) { os_free(wnmtfs_ie); os_free(mgmt); return -1; } igtk_elem_len = res; pos += igtk_elem_len; wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d", (int) igtk_elem_len); #endif /* CONFIG_IEEE80211W */ WPA_PUT_LE16((u8 *) &mgmt->u.action.u.wnm_sleep_resp.keydata_len, gtk_elem_len + igtk_elem_len); } os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len); /* copy TFS IE here */ pos += wnmsleep_ie_len; if (wnmtfs_ie) os_memcpy(pos, wnmtfs_ie, wnmtfs_ie_len); len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len + igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len; /* In driver, response frame should be forced to sent when STA is in * PS mode */ res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, mgmt->da, &mgmt->u.action.category, len); if (!res) { wpa_printf(MSG_DEBUG, "Successfully send WNM-Sleep Response " "frame"); /* when entering wnmsleep * 1. pause the node in driver * 2. mark the node so that AP won't update GTK/IGTK during * WNM Sleep */ if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT && wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) { sta->flags |= WLAN_STA_WNM_SLEEP_MODE; hostapd_drv_wnm_oper(hapd, WNM_SLEEP_ENTER_CONFIRM, addr, NULL, NULL); wpa_set_wnmsleep(sta->wpa_sm, 1); } /* when exiting wnmsleep * 1. unmark the node * 2. start GTK/IGTK update if MFP is not used * 3. unpause the node in driver */ if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT || wnmsleep_ie.status == WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) && wnmsleep_ie.action_type == WNM_SLEEP_MODE_EXIT) { sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; wpa_set_wnmsleep(sta->wpa_sm, 0); hostapd_drv_wnm_oper(hapd, WNM_SLEEP_EXIT_CONFIRM, addr, NULL, NULL); if (!wpa_auth_uses_mfp(sta->wpa_sm)) wpa_wnmsleep_rekey_gtk(sta->wpa_sm); } } else wpa_printf(MSG_DEBUG, "Fail to send WNM-Sleep Response frame"); #undef MAX_GTK_SUBELEM_LEN #undef MAX_IGTK_SUBELEM_LEN os_free(wnmtfs_ie); os_free(mgmt); return res; }
void _wpa_hexdump(int level, const char *title, const u8 *buf, size_t len, int show) { size_t i; #ifdef CONFIG_DEBUG_LINUX_TRACING if (wpa_debug_tracing_file != NULL) { fprintf(wpa_debug_tracing_file, WPAS_TRACE_PFX "%s - hexdump(len=%lu):", level, title, (unsigned long) len); if (buf == NULL) { fprintf(wpa_debug_tracing_file, " [NULL]\n"); } else if (!show) { fprintf(wpa_debug_tracing_file, " [REMOVED]\n"); } else { for (i = 0; i < len; i++) fprintf(wpa_debug_tracing_file, " %02x", buf[i]); } fflush(wpa_debug_tracing_file); } #endif /* CONFIG_DEBUG_LINUX_TRACING */ if (level < wpa_debug_level) return; #ifdef CONFIG_ANDROID_LOG { const char *display; char *strbuf = NULL; size_t slen = len; if (buf == NULL) { display = " [NULL]"; } else if (len == 0) { display = ""; } else if (show && len) { /* Limit debug message length for Android log */ if (slen > 32) slen = 32; strbuf = os_malloc(1 + 3 * slen); if (strbuf == NULL) { wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " "allocate message buffer"); return; } for (i = 0; i < slen; i++) os_snprintf(&strbuf[i * 3], 4, " %02x", buf[i]); display = strbuf; } else { display = " [REMOVED]"; } __android_log_print(wpa_to_android_level(level), ANDROID_LOG_NAME, "%s - hexdump(len=%lu):%s%s", title, (long unsigned int) len, display, len > slen ? " ..." : ""); os_free(strbuf); return; } #else /* CONFIG_ANDROID_LOG */ #ifdef CONFIG_DEBUG_SYSLOG if (wpa_debug_syslog) { const char *display; char *strbuf = NULL; if (buf == NULL) { display = " [NULL]"; } else if (len == 0) { display = ""; } else if (show && len) { strbuf = os_malloc(1 + 3 * len); if (strbuf == NULL) { wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " "allocate message buffer"); return; } for (i = 0; i < len; i++) os_snprintf(&strbuf[i * 3], 4, " %02x", buf[i]); display = strbuf; } else { display = " [REMOVED]"; } syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s", title, (unsigned long) len, display); os_free(strbuf); return; } #endif /* CONFIG_DEBUG_SYSLOG */ wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { fprintf(out_file, "%s - hexdump(len=%lu):", title, (unsigned long) len); if (buf == NULL) { fprintf(out_file, " [NULL]"); } else if (show) { for (i = 0; i < len; i++) fprintf(out_file, " %02x", buf[i]); } else { fprintf(out_file, " [REMOVED]"); } fprintf(out_file, "\n"); } else { #endif /* CONFIG_DEBUG_FILE */ printf("%s - hexdump(len=%lu):", title, (unsigned long) len); if (buf == NULL) { printf(" [NULL]"); } else if (show) { for (i = 0; i < len; i++) printf(" %02x", buf[i]); } else { printf(" [REMOVED]"); } printf("\n"); #ifdef CONFIG_DEBUG_FILE } #endif /* CONFIG_DEBUG_FILE */ #endif /* CONFIG_ANDROID_LOG */ }
int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta, u8 req_mode, int disassoc_timer, u8 valid_int, const u8 *bss_term_dur, const char *url, const u8 *nei_rep, size_t nei_rep_len) { u8 *buf, *pos; struct ieee80211_mgmt *mgmt; size_t url_len; wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to " MACSTR " req_mode=0x%x disassoc_timer=%d valid_int=0x%x", MAC2STR(sta->addr), req_mode, disassoc_timer, valid_int); buf = os_zalloc(1000 + nei_rep_len); if (buf == NULL) return -1; mgmt = (struct ieee80211_mgmt *) buf; mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); os_memcpy(mgmt->da, sta->addr, ETH_ALEN); os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); mgmt->u.action.category = WLAN_ACTION_WNM; mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; mgmt->u.action.u.bss_tm_req.dialog_token = 1; mgmt->u.action.u.bss_tm_req.req_mode = req_mode; mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(disassoc_timer); mgmt->u.action.u.bss_tm_req.validity_interval = valid_int; pos = mgmt->u.action.u.bss_tm_req.variable; if ((req_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) && bss_term_dur) { os_memcpy(pos, bss_term_dur, 12); pos += 12; } if (url) { /* Session Information URL */ url_len = os_strlen(url); if (url_len > 255) { os_free(buf); return -1; } *pos++ = url_len; os_memcpy(pos, url, url_len); pos += url_len; } if (nei_rep) { os_memcpy(pos, nei_rep, nei_rep_len); pos += nei_rep_len; } if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0) < 0) { wpa_printf(MSG_DEBUG, "Failed to send BSS Transition Management Request frame"); os_free(buf); return -1; } os_free(buf); if (disassoc_timer) { /* send disassociation frame after time-out */ set_disassoc_timer(hapd, sta, disassoc_timer); } return 0; }
static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_config *conf) { struct hostapd_bss_config *bss = &conf->bss[0]; int pairwise; #ifdef CONFIG_IEEE80211N struct hostapd_hw_modes *modes; u16 num_modes, flags; #endif /* CONFIG_IEEE80211N */ conf->driver = wpa_s->driver; os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface)); if (ssid->frequency == 0) { /* default channel 11 */ conf->hw_mode = HOSTAPD_MODE_IEEE80211G; conf->channel = 11; } else if (ssid->frequency >= 2412 && ssid->frequency <= 2472) { conf->hw_mode = HOSTAPD_MODE_IEEE80211G; conf->channel = (ssid->frequency - 2407) / 5; } else if ((ssid->frequency >= 5180 && ssid->frequency <= 5240) || (ssid->frequency >= 5745 && ssid->frequency <= 5825)) { conf->hw_mode = HOSTAPD_MODE_IEEE80211A; conf->channel = (ssid->frequency - 5000) / 5; } else { wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz", ssid->frequency); return -1; } /* TODO: enable HT40 if driver supports it; * drop to 11b if driver does not support 11g */ #ifdef CONFIG_IEEE80211N /* * Enable HT20 if the driver supports it, by setting conf->ieee80211n * and conf->ht_capab. * Using default config settings for: conf->ht_op_mode_fixed, * conf->secondary_channel, conf->require_ht */ modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes, &flags); if (modes) { struct hostapd_hw_modes *mode = NULL; int i; for (i = 0; i < num_modes; i++) { if (modes[i].mode == conf->hw_mode) { mode = &modes[i]; break; } } if (mode && mode->ht_capab) { bss->wmm_enabled = 1; conf->ieee80211n = 1; conf->ht_capab = mode->ht_capab; } ieee80211_sta_free_hw_features(modes, num_modes); modes = NULL; } #endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_P2P if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) { /* Remove 802.11b rates from supported and basic rate sets */ int *list = os_malloc(4 * sizeof(int)); if (list) { list[0] = 60; list[1] = 120; list[2] = 240; list[3] = -1; } conf->basic_rates = list; list = os_malloc(9 * sizeof(int)); if (list) { list[0] = 60; list[1] = 90; list[2] = 120; list[3] = 180; list[4] = 240; list[5] = 360; list[6] = 480; list[7] = 540; list[8] = -1; } conf->supported_rates = list; } #endif /* CONFIG_P2P */ if (ssid->ssid_len == 0) { wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); return -1; } os_memcpy(bss->ssid.ssid, ssid->ssid, ssid->ssid_len); bss->ssid.ssid[ssid->ssid_len] = '\0'; bss->ssid.ssid_len = ssid->ssid_len; bss->ssid.ssid_set = 1; if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) bss->wpa = ssid->proto; bss->wpa_key_mgmt = ssid->key_mgmt; bss->wpa_pairwise = ssid->pairwise_cipher; if (ssid->passphrase) { bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase); } else if (ssid->psk_set) { os_free(bss->ssid.wpa_psk); bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); if (bss->ssid.wpa_psk == NULL) return -1; os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN); bss->ssid.wpa_psk->group = 1; } /* Select group cipher based on the enabled pairwise cipher suites */ pairwise = 0; if (bss->wpa & 1) pairwise |= bss->wpa_pairwise; if (bss->wpa & 2) { if (bss->rsn_pairwise == 0) bss->rsn_pairwise = bss->wpa_pairwise; pairwise |= bss->rsn_pairwise; } if (pairwise & WPA_CIPHER_TKIP) bss->wpa_group = WPA_CIPHER_TKIP; else bss->wpa_group = WPA_CIPHER_CCMP; if (bss->wpa && bss->ieee802_1x) bss->ssid.security_policy = SECURITY_WPA; else if (bss->wpa) bss->ssid.security_policy = SECURITY_WPA_PSK; else if (bss->ieee802_1x) { bss->ssid.security_policy = SECURITY_IEEE_802_1X; bss->ssid.wep.default_len = bss->default_wep_key_len; } else if (bss->ssid.wep.keys_set) bss->ssid.security_policy = SECURITY_STATIC_WEP; else bss->ssid.security_policy = SECURITY_PLAINTEXT; #ifdef CONFIG_WPS /* * Enable WPS by default, but require user interaction to actually use * it. Only the internal Registrar is supported. */ bss->eap_server = 1; bss->wps_state = 2; bss->ap_setup_locked = 2; if (wpa_s->conf->config_methods) bss->config_methods = os_strdup(wpa_s->conf->config_methods); os_memcpy(bss->device_type, wpa_s->conf->device_type, WPS_DEV_TYPE_LEN); if (wpa_s->conf->device_name) { bss->device_name = os_strdup(wpa_s->conf->device_name); bss->friendly_name = os_strdup(wpa_s->conf->device_name); } if (wpa_s->conf->manufacturer) bss->manufacturer = os_strdup(wpa_s->conf->manufacturer); if (wpa_s->conf->model_name) bss->model_name = os_strdup(wpa_s->conf->model_name); if (wpa_s->conf->model_number) bss->model_number = os_strdup(wpa_s->conf->model_number); if (wpa_s->conf->serial_number) bss->serial_number = os_strdup(wpa_s->conf->serial_number); if (is_nil_uuid(wpa_s->conf->uuid)) os_memcpy(bss->uuid, wpa_s->wps->uuid, WPS_UUID_LEN); else os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN); os_memcpy(bss->os_version, wpa_s->conf->os_version, 4); #endif /* CONFIG_WPS */ if (wpa_s->max_stations && wpa_s->max_stations < wpa_s->conf->max_num_sta) bss->max_num_sta = wpa_s->max_stations; else bss->max_num_sta = wpa_s->conf->max_num_sta; bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack; return 0; }
int authsrv_init(struct hostapd_data *hapd) { #ifdef EAP_TLS_FUNCS if (hapd->conf->eap_server && (hapd->conf->ca_cert || hapd->conf->server_cert || hapd->conf->private_key || hapd->conf->dh_file)) { struct tls_connection_params params; hapd->ssl_ctx = tls_init(NULL); if (hapd->ssl_ctx == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize TLS"); authsrv_deinit(hapd); return -1; } os_memset(¶ms, 0, sizeof(params)); params.ca_cert = hapd->conf->ca_cert; params.client_cert = hapd->conf->server_cert; params.private_key = hapd->conf->private_key; params.private_key_passwd = hapd->conf->private_key_passwd; params.dh_file = hapd->conf->dh_file; params.openssl_ciphers = hapd->conf->openssl_ciphers; params.ocsp_stapling_response = hapd->conf->ocsp_stapling_response; if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) { wpa_printf(MSG_ERROR, "Failed to set TLS parameters"); authsrv_deinit(hapd); return -1; } if (tls_global_set_verify(hapd->ssl_ctx, hapd->conf->check_crl)) { wpa_printf(MSG_ERROR, "Failed to enable check_crl"); authsrv_deinit(hapd); return -1; } } #endif /* EAP_TLS_FUNCS */ #ifdef EAP_SIM_DB if (hapd->conf->eap_sim_db) { hapd->eap_sim_db_priv = eap_sim_db_init(hapd->conf->eap_sim_db, hostapd_sim_db_cb, hapd); if (hapd->eap_sim_db_priv == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM " "database interface"); authsrv_deinit(hapd); return -1; } } #endif /* EAP_SIM_DB */ #ifdef RADIUS_SERVER if (hapd->conf->radius_server_clients && hostapd_setup_radius_srv(hapd)) return -1; #endif /* RADIUS_SERVER */ return 0; }
/** * wps_init - Initialize WPS Registration protocol data * @cfg: WPS configuration * Returns: Pointer to allocated data or %NULL on failure * * This function is used to initialize WPS data for a registration protocol * instance (i.e., each run of registration protocol as a Registrar of * Enrollee. The caller is responsible for freeing this data after the * registration run has been completed by calling wps_deinit(). */ struct wps_data * wps_init(const struct wps_config *cfg) { struct wps_data *data = os_zalloc(sizeof (*data)); if (data == NULL) return NULL; data->wps = cfg->wps; data->registrar = cfg->registrar; if (cfg->registrar) { os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN); } else { os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN); os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN); } if (cfg->pin) { data->dev_pw_id = data->wps->oob_dev_pw_id == 0 ? DEV_PW_DEFAULT : data->wps->oob_dev_pw_id; data->dev_password = os_malloc(cfg->pin_len); if (data->dev_password == NULL) { os_free(data); return NULL; } os_memcpy(data->dev_password, cfg->pin, cfg->pin_len); data->dev_password_len = cfg->pin_len; } data->pbc = cfg->pbc; if (cfg->pbc) { /* Use special PIN '00000000' for PBC */ data->dev_pw_id = DEV_PW_PUSHBUTTON; os_free(data->dev_password); data->dev_password = os_malloc(8); if (data->dev_password == NULL) { os_free(data); return NULL; } os_memset(data->dev_password, '0', 8); data->dev_password_len = 8; } data->state = data->registrar ? RECV_M1 : SEND_M1; if (cfg->assoc_wps_ie) { struct wps_parse_attr attr; wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq", cfg->assoc_wps_ie); if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) { wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE " "from (Re)AssocReq"); } else if (attr.request_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute " "in (Re)AssocReq WPS IE"); } else { wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE " "in (Re)AssocReq WPS IE): %d", *attr.request_type); data->request_type = *attr.request_type; } } if (cfg->new_ap_settings) { data->new_ap_settings = os_malloc(sizeof (*data->new_ap_settings)); if (data->new_ap_settings == NULL) { os_free(data); return NULL; } os_memcpy(data->new_ap_settings, cfg->new_ap_settings, sizeof (*data->new_ap_settings)); } if (cfg->peer_addr) os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN); data->use_psk_key = cfg->use_psk_key; return data; }
static int test_driver_send_mgmt_frame(void *priv, const void *buf, size_t len, int flags) { struct test_driver_data *drv = priv; struct msghdr msg; struct iovec io[2]; const u8 *dest; int ret = 0, broadcast = 0; char desttxt[30]; struct sockaddr_un addr; struct dirent *dent; DIR *dir; struct ieee80211_hdr *hdr; u16 fc; if (drv->test_socket < 0 || len < 10 || drv->socket_dir == NULL) { wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d len=%lu" " socket_dir=%p)", __func__, drv->test_socket, (unsigned long) len, drv->socket_dir); return -1; } dest = buf; dest += 4; broadcast = memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0; snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dest)); io[0].iov_base = "MLME "; io[0].iov_len = 5; io[1].iov_base = (void *) buf; io[1].iov_len = len; memset(&msg, 0, sizeof(msg)); msg.msg_iov = io; msg.msg_iovlen = 2; dir = opendir(drv->socket_dir); if (dir == NULL) { perror("test_driver: opendir"); return -1; } while ((dent = readdir(dir))) { #ifdef _DIRENT_HAVE_D_TYPE /* Skip the file if it is not a socket. Also accept * DT_UNKNOWN (0) in case the C library or underlying file * system does not support d_type. */ if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) continue; #endif /* _DIRENT_HAVE_D_TYPE */ if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", drv->socket_dir, dent->d_name); if (strcmp(addr.sun_path, drv->own_socket_path) == 0) continue; if (!broadcast && strstr(dent->d_name, desttxt) == NULL) continue; wpa_printf(MSG_DEBUG, "%s: Send management frame to %s", __func__, dent->d_name); msg.msg_name = &addr; msg.msg_namelen = sizeof(addr); ret = sendmsg(drv->test_socket, &msg, 0); if (ret < 0) perror("driver_test: sendmsg"); } closedir(dir); hdr = (struct ieee80211_hdr *) buf; fc = le_to_host16(hdr->frame_control); ieee802_11_mgmt_cb(drv->hapd, (u8 *) buf, len, WLAN_FC_GET_STYPE(fc), ret >= 0); return ret; }
int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) { const u8 *pos, *end; u16 type, len; #ifdef WPS_WORKAROUNDS u16 prev_type = 0; #endif /* WPS_WORKAROUNDS */ os_memset(attr, 0, sizeof(*attr)); pos = wpabuf_head(msg); end = pos + wpabuf_len(msg); while (pos < end) { if (end - pos < 4) { wpa_printf(MSG_DEBUG, "WPS: Invalid message - " "%lu bytes remaining", (unsigned long) (end - pos)); return -1; } type = WPA_GET_BE16(pos); pos += 2; len = WPA_GET_BE16(pos); pos += 2; wpa_printf(MSG_DEBUG, "WPS: attr type=0x%x len=%u", type, len); if (len > end - pos) { wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg); #ifdef WPS_WORKAROUNDS /* * Some deployed APs seem to have a bug in encoding of * Network Key attribute in the Credential attribute * where they add an extra octet after the Network Key * attribute at least when open network is being * provisioned. */ if ((type & 0xff00) != 0x1000 && prev_type == ATTR_NETWORK_KEY) { wpa_printf(MSG_DEBUG, "WPS: Workaround - try " "to skip unexpected octet after " "Network Key"); pos -= 3; continue; } #endif /* WPS_WORKAROUNDS */ return -1; } #ifdef WPS_WORKAROUNDS if (type == 0 && len == 0) { /* * Mac OS X 10.6 seems to be adding 0x00 padding to the * end of M1. Skip those to avoid interop issues. */ int i; for (i = 0; i < end - pos; i++) { if (pos[i]) break; } if (i == end - pos) { wpa_printf(MSG_DEBUG, "WPS: Workaround - skip " "unexpected message padding"); break; } } #endif /* WPS_WORKAROUNDS */ if (wps_set_attr(attr, type, pos, len) < 0) return -1; #ifdef WPS_WORKAROUNDS prev_type = type; #endif /* WPS_WORKAROUNDS */ pos += len; } return 0; }
static void test_driver_assoc(struct test_driver_data *drv, struct sockaddr_un *from, socklen_t fromlen, char *data) { struct test_client_socket *cli; u8 ie[256], ssid[32]; size_t ielen, ssid_len = 0; char *pos, *pos2, cmd[50]; struct test_driver_bss *bss; /* data: STA-addr SSID(hex) IEs(hex) */ cli = wpa_zalloc(sizeof(*cli)); if (cli == NULL) return; if (hwaddr_aton(data, cli->addr)) { printf("test_socket: Invalid MAC address '%s' in ASSOC\n", data); free(cli); return; } pos = data + 17; while (*pos == ' ') pos++; pos2 = strchr(pos, ' '); ielen = 0; if (pos2) { ssid_len = (pos2 - pos) / 2; if (hexstr2bin(pos, ssid, ssid_len) < 0) { wpa_printf(MSG_DEBUG, "%s: Invalid SSID", __func__); free(cli); return; } wpa_hexdump_ascii(MSG_DEBUG, "test_driver_assoc: SSID", ssid, ssid_len); pos = pos2 + 1; ielen = strlen(pos) / 2; if (ielen > sizeof(ie)) ielen = sizeof(ie); if (hexstr2bin(pos, ie, ielen) < 0) ielen = 0; } for (bss = drv->bss; bss; bss = bss->next) { if (bss->ssid_len == ssid_len && memcmp(bss->ssid, ssid, ssid_len) == 0) break; } if (bss == NULL) { wpa_printf(MSG_DEBUG, "%s: No matching SSID found from " "configured BSSes", __func__); free(cli); return; } cli->bss = bss; memcpy(&cli->un, from, sizeof(cli->un)); cli->unlen = fromlen; cli->next = drv->cli; drv->cli = cli; wpa_hexdump_ascii(MSG_DEBUG, "test_socket: ASSOC sun_path", (const u8 *) cli->un.sun_path, cli->unlen - sizeof(cli->un.sun_family)); snprintf(cmd, sizeof(cmd), "ASSOCRESP " MACSTR " 0", MAC2STR(bss->bssid)); sendto(drv->test_socket, cmd, strlen(cmd), 0, (struct sockaddr *) from, fromlen); if (test_driver_new_sta(drv, bss, cli->addr, ie, ielen) < 0) { wpa_printf(MSG_DEBUG, "test_driver: failed to add new STA"); } }
/** * hostapd_driver_init - Preparate driver interface */ static int hostapd_driver_init(struct hostapd_iface *iface) { struct wpa_init_params params; size_t i; struct hostapd_data *hapd = iface->bss[0]; struct hostapd_bss_config *conf = hapd->conf; u8 *b = conf->bssid; struct wpa_driver_capa capa; if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); return -1; } /* Initialize the driver interface */ if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) b = NULL; os_memset(¶ms, 0, sizeof(params)); for (i = 0; wpa_drivers[i]; i++) { if (wpa_drivers[i] != hapd->driver) continue; if (global.drv_priv[i] == NULL && wpa_drivers[i]->global_init) { global.drv_priv[i] = wpa_drivers[i]->global_init(); if (global.drv_priv[i] == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize " "driver '%s'", wpa_drivers[i]->name); return -1; } } params.global_priv = global.drv_priv[i]; break; } params.bssid = b; params.ifname = hapd->conf->iface; params.driver_params = hapd->iconf->driver_params; params.use_pae_group_addr = hapd->conf->use_pae_group_addr; params.num_bridge = hapd->iface->num_bss; params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *)); if (params.bridge == NULL) return -1; for (i = 0; i < hapd->iface->num_bss; i++) { struct hostapd_data *bss = hapd->iface->bss[i]; if (bss->conf->bridge[0]) params.bridge[i] = bss->conf->bridge; } params.own_addr = hapd->own_addr; hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); os_free(params.bridge); if (hapd->drv_priv == NULL) { wpa_printf(MSG_ERROR, "%s driver initialization failed.", hapd->driver->name); hapd->driver = NULL; return -1; } if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { struct wowlan_triggers *triggs; iface->drv_flags = capa.flags; iface->smps_modes = capa.smps_modes; iface->probe_resp_offloads = capa.probe_resp_offloads; iface->extended_capa = capa.extended_capa; iface->extended_capa_mask = capa.extended_capa_mask; iface->extended_capa_len = capa.extended_capa_len; iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa); if (triggs && hapd->driver->set_wowlan) { if (hapd->driver->set_wowlan(hapd->drv_priv, triggs)) wpa_printf(MSG_ERROR, "set_wowlan failed"); } os_free(triggs); } return 0; }
static int test_driver_if_remove(void *priv, enum hostapd_driver_if_type type, const char *ifname, const u8 *addr) { wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname); return 0; }
static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, int level, const char *txt, size_t len) { struct hostapd_data *hapd = ctx; char *format, *module_str; int maxlen; int conf_syslog_level, conf_stdout_level; unsigned int conf_syslog, conf_stdout; maxlen = len + 100; format = os_malloc(maxlen); if (!format) return; if (hapd && hapd->conf) { conf_syslog_level = hapd->conf->logger_syslog_level; conf_stdout_level = hapd->conf->logger_stdout_level; conf_syslog = hapd->conf->logger_syslog; conf_stdout = hapd->conf->logger_stdout; } else { conf_syslog_level = conf_stdout_level = 0; conf_syslog = conf_stdout = (unsigned int) -1; } switch (module) { case HOSTAPD_MODULE_IEEE80211: module_str = "IEEE 802.11"; break; case HOSTAPD_MODULE_IEEE8021X: module_str = "IEEE 802.1X"; break; case HOSTAPD_MODULE_RADIUS: module_str = "RADIUS"; break; case HOSTAPD_MODULE_WPA: module_str = "WPA"; break; case HOSTAPD_MODULE_DRIVER: module_str = "DRIVER"; break; case HOSTAPD_MODULE_IAPP: module_str = "IAPP"; break; case HOSTAPD_MODULE_MLME: module_str = "MLME"; break; default: module_str = NULL; break; } if (hapd && hapd->conf && addr) os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", hapd->conf->iface, MAC2STR(addr), module_str ? " " : "", module_str ? module_str : "", txt); else if (hapd && hapd->conf) os_snprintf(format, maxlen, "%s:%s%s %s", hapd->conf->iface, module_str ? " " : "", module_str ? module_str : "", txt); else if (addr) os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", MAC2STR(addr), module_str ? " " : "", module_str ? module_str : "", txt); else os_snprintf(format, maxlen, "%s%s%s", module_str ? module_str : "", module_str ? ": " : "", txt); if ((conf_stdout & module) && level >= conf_stdout_level) { wpa_debug_print_timestamp(); wpa_printf(MSG_INFO, "%s", format); } #ifndef CONFIG_NATIVE_WINDOWS if ((conf_syslog & module) && level >= conf_syslog_level) { int priority; switch (level) { case HOSTAPD_LEVEL_DEBUG_VERBOSE: case HOSTAPD_LEVEL_DEBUG: priority = LOG_DEBUG; break; case HOSTAPD_LEVEL_INFO: priority = LOG_INFO; break; case HOSTAPD_LEVEL_NOTICE: priority = LOG_NOTICE; break; case HOSTAPD_LEVEL_WARNING: priority = LOG_WARNING; break; default: priority = LOG_INFO; break; } syslog(priority, "%s", format); } #endif /* CONFIG_NATIVE_WINDOWS */ os_free(format); }
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse) { const u8 *end, *pos; struct wpa_ie_data data; int ret; const struct rsn_ftie *ftie; int prot_ie_count = 0; os_memset(parse, 0, sizeof(*parse)); if (ies == NULL) return 0; pos = ies; end = ies + ies_len; while (pos + 2 <= end && pos + 2 + pos[1] <= end) { switch (pos[0]) { case WLAN_EID_RSN: parse->rsn = pos + 2; parse->rsn_len = pos[1]; ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, parse->rsn_len + 2, &data); if (ret < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse " "RSN IE: %d", ret); return -1; } if (data.num_pmkid == 1 && data.pmkid) parse->rsn_pmkid = data.pmkid; break; case WLAN_EID_MOBILITY_DOMAIN: parse->mdie = pos + 2; parse->mdie_len = pos[1]; break; case WLAN_EID_FAST_BSS_TRANSITION: if (pos[1] < sizeof(*ftie)) return -1; ftie = (const struct rsn_ftie *) (pos + 2); prot_ie_count = ftie->mic_control[1]; if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) return -1; break; case WLAN_EID_TIMEOUT_INTERVAL: parse->tie = pos + 2; parse->tie_len = pos[1]; break; case WLAN_EID_RIC_DATA: if (parse->ric == NULL) parse->ric = pos; break; } pos += 2 + pos[1]; } if (prot_ie_count == 0) return 0; /* no MIC */ /* * Check that the protected IE count matches with IEs included in the * frame. */ if (parse->rsn) prot_ie_count--; if (parse->mdie) prot_ie_count--; if (parse->ftie) prot_ie_count--; if (prot_ie_count < 0) { wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " "the protected IE count"); return -1; } if (prot_ie_count == 0 && parse->ric) { wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not " "included in protected IE count"); return -1; } /* Determine the end of the RIC IE(s) */ pos = parse->ric; while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end && prot_ie_count) { prot_ie_count--; pos += 2 + pos[1]; } parse->ric_len = pos - parse->ric; if (prot_ie_count) { wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " "frame", (int) prot_ie_count); return -1; } return 0; }