diff options
| author | Dmitry Shmidt <dimitrysh@google.com> | 2014-06-16 16:23:22 -0700 |
|---|---|---|
| committer | Dmitry Shmidt <dimitrysh@google.com> | 2014-06-16 16:23:22 -0700 |
| commit | 43cb578dfe2c492257636f6234a24178ed27789e (patch) | |
| tree | 23fb82e818c3cb838090e71b4c44e10314d79fab /src | |
| parent | 623d63a3a443027e50efdaaec027befcc3882527 (diff) | |
| download | android_external_wpa_supplicant_8-43cb578dfe2c492257636f6234a24178ed27789e.tar.gz android_external_wpa_supplicant_8-43cb578dfe2c492257636f6234a24178ed27789e.tar.bz2 android_external_wpa_supplicant_8-43cb578dfe2c492257636f6234a24178ed27789e.zip | |
Cumulative patch from commit 7efc7f66b1d63b3bbb99d9176f6f68c4d1fc6327
7efc7f6 TDLS: Fix TPK M1 error case (CID 68214)
d1bb7ae nl80211: Fix non-hostapd interface addition to not call add_ifidx()
38ddcca TDLS: Add ctrl_iface option for flushing all TDLS peers
342bce6 TDLS: Bail on STA add failure in tpk_m1 processing
947f900 TDLS: Handle unreachable link teardown for external setup
cf1600a hostapd: Configure driver ACL even if MAC address list is empty
fa21e6c Fix CONFIG_MODULE_TESTS=y build without CONFIG_P2P=y
bd10d93 P2P: Clean up by moving ifdef CONFIG_P2P to p2p_suppplicant.h
e3bd6e9 P2P: Use another interface operating channel as listen channel
28812a8 P2P: Try using one of the social channels for GO
751b00b P2P: Modify p2p_get_pref_freq
0a816e8 P2P: Remove duplicated code from get_shared_radio_freqs_data()
504df28 Remove unused dump_freq_array()
a0c90bb P2P: Collect and use extended data on used frequencies
b278f32 P2P: Remove unused code from get_shared_radio_freqs_data()
e627012 Clean up EAPOL-Key Key Data processing
d56d7e5 Clean up EAPOL-Key processing
8605eab EAP-EKE: Fix typos in debug message
25be28a dbus: Check return value more consistently (CID 62841)
ac79fcf wext: Verify set_ssid results consistently (CID 62842)
f62415d Note chmod() failure in debug log even in ignore case (CID 62843)
305000e WPS: Check wps_build_wfa_ext() return value consistently (CID 68104)
2485835 EAP-MSCHAPv2: Check hash function results more consistently (CID 68105)
b7c61c9 Fix validation of EAPOL-Key length with AES key wrap (CID 62859)
Change-Id: I4da11c59a54467301c38c3bec52629b9db19647d
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/ap/hostapd.c | 39 | ||||
| -rw-r--r-- | src/drivers/driver_nl80211.c | 10 | ||||
| -rw-r--r-- | src/drivers/driver_wext.c | 6 | ||||
| -rw-r--r-- | src/eap_peer/eap_eke.c | 6 | ||||
| -rw-r--r-- | src/eap_peer/eap_mschapv2.c | 33 | ||||
| -rw-r--r-- | src/p2p/p2p.c | 37 | ||||
| -rw-r--r-- | src/p2p/p2p.h | 11 | ||||
| -rw-r--r-- | src/p2p/p2p_i.h | 4 | ||||
| -rw-r--r-- | src/p2p/p2p_utils.c | 12 | ||||
| -rw-r--r-- | src/rsn_supp/tdls.c | 30 | ||||
| -rw-r--r-- | src/rsn_supp/wpa.c | 173 | ||||
| -rw-r--r-- | src/rsn_supp/wpa.h | 2 | ||||
| -rw-r--r-- | src/wps/wps_upnp.c | 5 |
13 files changed, 221 insertions, 147 deletions
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index ed733019..4e09fa3a 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -946,35 +946,24 @@ static void hostapd_set_acl(struct hostapd_data *hapd) if (hapd->iface->drv_max_acl_mac_addrs == 0) return; - if (!(conf->bss[0]->num_accept_mac || conf->bss[0]->num_deny_mac)) - return; if (conf->bss[0]->macaddr_acl == DENY_UNLESS_ACCEPTED) { - if (conf->bss[0]->num_accept_mac) { - accept_acl = 1; - err = hostapd_set_acl_list(hapd, - conf->bss[0]->accept_mac, - conf->bss[0]->num_accept_mac, - accept_acl); - if (err) { - wpa_printf(MSG_DEBUG, "Failed to set accept acl"); - return; - } - } else { - wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file"); + accept_acl = 1; + err = hostapd_set_acl_list(hapd, conf->bss[0]->accept_mac, + conf->bss[0]->num_accept_mac, + accept_acl); + if (err) { + wpa_printf(MSG_DEBUG, "Failed to set accept acl"); + return; } } else if (conf->bss[0]->macaddr_acl == ACCEPT_UNLESS_DENIED) { - if (conf->bss[0]->num_deny_mac) { - accept_acl = 0; - err = hostapd_set_acl_list(hapd, conf->bss[0]->deny_mac, - conf->bss[0]->num_deny_mac, - accept_acl); - if (err) { - wpa_printf(MSG_DEBUG, "Failed to set deny acl"); - return; - } - } else { - wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file"); + accept_acl = 0; + err = hostapd_set_acl_list(hapd, conf->bss[0]->deny_mac, + conf->bss[0]->num_deny_mac, + accept_acl); + if (err) { + wpa_printf(MSG_DEBUG, "Failed to set deny acl"); + return; } } } diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 75686538..aa2cd04a 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -10177,7 +10177,15 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, if (drv->global) drv->global->if_add_ifindex = ifidx; - if (ifidx > 0) + /* + * Some virtual interfaces need to process EAPOL packets and events on + * the parent interface. This is used mainly with hostapd. + */ + if (ifidx > 0 && + (drv->hostapd || + nlmode == NL80211_IFTYPE_AP_VLAN || + nlmode == NL80211_IFTYPE_WDS || + nlmode == NL80211_IFTYPE_MONITOR)) add_ifidx(drv, ifidx); return 0; diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index e5734bdd..a4f9cec7 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -2027,7 +2027,11 @@ int wpa_driver_wext_associate(void *priv, * Stop cfg80211 from trying to associate before we are done * with all parameters. */ - wpa_driver_wext_set_ssid(drv, (u8 *) "", 0); + if (wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) { + wpa_printf(MSG_DEBUG, + "WEXT: Failed to clear SSID to stop pending cfg80211 association attempts (if any)"); + /* continue anyway */ + } } if (wpa_driver_wext_set_drop_unencrypted(drv, params->drop_unencrypted) diff --git a/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c index 864ea1d9..6818b08f 100644 --- a/src/eap_peer/eap_eke.c +++ b/src/eap_peer/eap_eke.c @@ -451,7 +451,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, /* DHComponent_P = Encr(key, y_p) */ rpos = wpabuf_put(resp, data->sess.dhcomp_len); if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) { - wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_S"); + wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P"); os_memset(key, 0, sizeof(key)); return eap_eke_build_fail(data, ret, reqData, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); @@ -523,7 +523,7 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, end = payload + payload_len; if (pos + data->sess.pnonce_ps_len + data->sess.prf_len > end) { - wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit"); + wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm"); return eap_eke_build_fail(data, ret, reqData, EAP_EKE_FAIL_PROTO_ERROR); } @@ -543,7 +543,7 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_P | Nonce_S", nonces, 2 * data->sess.nonce_len); if (os_memcmp(data->nonce_p, nonces, data->sess.nonce_len) != 0) { - wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match trnsmitted Nonce_P"); + wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match transmitted Nonce_P"); return eap_eke_build_fail(data, ret, reqData, EAP_EKE_FAIL_AUTHENTICATION_FAIL); } diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c index f9aa7425..f2fcc371 100644 --- a/src/eap_peer/eap_mschapv2.c +++ b/src/eap_peer/eap_mschapv2.c @@ -309,10 +309,13 @@ static void eap_mschapv2_password_changed(struct eap_sm *sm, } else if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) { config->password = os_malloc(16); config->password_len = 16; - if (config->password) { - nt_password_hash(config->new_password, - config->new_password_len, - config->password); + if (config->password && + nt_password_hash(config->new_password, + config->new_password_len, + config->password)) { + os_free(config->password); + config->password = NULL; + config->password_len = 0; } os_free(config->new_password); } else { @@ -549,15 +552,17 @@ static struct wpabuf * eap_mschapv2_change_password( /* Encrypted-Hash */ if (pwhash) { u8 new_password_hash[16]; - nt_password_hash(new_password, new_password_len, - new_password_hash); + if (nt_password_hash(new_password, new_password_len, + new_password_hash)) + goto fail; nt_password_hash_encrypted_with_block(password, new_password_hash, cp->encr_hash); } else { - old_nt_password_hash_encrypted_with_new_nt_password_hash( - new_password, new_password_len, - password, password_len, cp->encr_hash); + if (old_nt_password_hash_encrypted_with_new_nt_password_hash( + new_password, new_password_len, + password, password_len, cp->encr_hash)) + goto fail; } /* Peer-Challenge */ @@ -594,9 +599,13 @@ static struct wpabuf * eap_mschapv2_change_password( /* Likewise, generate master_key here since we have the needed data * available. */ - nt_password_hash(new_password, new_password_len, password_hash); - hash_nt_password_hash(password_hash, password_hash_hash); - get_master_key(password_hash_hash, cp->nt_response, data->master_key); + if (nt_password_hash(new_password, new_password_len, password_hash) || + hash_nt_password_hash(password_hash, password_hash_hash) || + get_master_key(password_hash_hash, cp->nt_response, + data->master_key)) { + data->auth_response_valid = 0; + goto fail; + } data->master_key_valid = 1; /* Flags */ diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 1875ca4d..104f77ba 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -183,6 +183,14 @@ void p2p_set_state(struct p2p_data *p2p, int new_state) p2p_dbg(p2p, "State %s -> %s", p2p_state_txt(p2p->state), p2p_state_txt(new_state)); p2p->state = new_state; + + if (new_state == P2P_IDLE && p2p->pending_channel) { + p2p_dbg(p2p, "Apply change in listen channel"); + p2p->cfg->reg_class = p2p->pending_reg_class; + p2p->cfg->channel = p2p->pending_channel; + p2p->pending_reg_class = 0; + p2p->pending_channel = 0; + } } @@ -3991,20 +3999,43 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled) } -int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel) +int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel, + u8 forced) { if (p2p_channel_to_freq(reg_class, channel) < 0) return -1; p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u", reg_class, channel); - p2p->cfg->reg_class = reg_class; - p2p->cfg->channel = channel; + + /* + * Listen channel was set in configuration or set by control interface; + * cannot override it. + */ + if (p2p->cfg->channel_forced && forced == 0) + return -1; + + if (p2p->state == P2P_IDLE) { + p2p->cfg->reg_class = reg_class; + p2p->cfg->channel = channel; + p2p->cfg->channel_forced = forced; + } else { + p2p_dbg(p2p, "Defer setting listen channel"); + p2p->pending_reg_class = reg_class; + p2p->pending_channel = channel; + p2p->pending_channel_forced = forced; + } return 0; } +u8 p2p_get_listen_channel(struct p2p_data *p2p) +{ + return p2p->cfg->channel; +} + + int p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len) { p2p_dbg(p2p, "New SSID postfix: %s", wpa_ssid_txt(postfix, len)); diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index fa8031d0..9cf100fa 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -267,6 +267,12 @@ struct p2p_config { u8 channel; /** + * channel_forced - the listen channel was forced by configuration + * or by control interface and cannot be overridden + */ + u8 channel_forced; + + /** * Regulatory class for own operational channel */ u8 op_reg_class; @@ -1669,7 +1675,10 @@ void p2p_set_client_discoverability(struct p2p_data *p2p, int enabled); */ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled); -int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel); +int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel, + u8 forced); + +u8 p2p_get_listen_channel(struct p2p_data *p2p); int p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len); diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 65ff9ef4..39a927a3 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -480,6 +480,10 @@ struct p2p_data { unsigned int search_delay; int in_search_delay; + u8 pending_reg_class; + u8 pending_channel; + u8 pending_channel_forced; + #ifdef CONFIG_WIFI_DISPLAY struct wpabuf *wfd_ie_beacon; struct wpabuf *wfd_ie_probe_req; diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c index ac190644..189300ad 100644 --- a/src/p2p/p2p_utils.c +++ b/src/p2p/p2p_utils.c @@ -388,17 +388,19 @@ unsigned int p2p_get_pref_freq(struct p2p_data *p2p, const struct p2p_channels *channels) { unsigned int i; - int freq; + int freq = 0; + const struct p2p_channels *tmpc = channels ? + channels : &p2p->cfg->channels; + + if (tmpc == NULL) + return 0; for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) { freq = p2p_channel_to_freq(p2p->cfg->pref_chan[i].op_class, p2p->cfg->pref_chan[i].chan); - if (freq <= 0) - continue; - if (!channels || p2p_channels_includes_freq(channels, freq)) + if (p2p_channels_includes_freq(tmpc, freq)) return freq; } - return 0; } diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 84b7c1be..59ed2c92 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -802,7 +802,7 @@ static void wpa_tdls_disable_peer_link(struct wpa_sm *sm, } -void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr) +void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr) { struct wpa_tdls_peer *peer; @@ -811,8 +811,25 @@ void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr) break; } - if (peer) + if (!peer || !peer->tpk_success) { + wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR + " not connected - cannot teardown unreachable link", + MAC2STR(addr)); + return; + } + + if (wpa_tdls_is_external_setup(sm)) { + /* + * Disable the link, send a teardown packet through the + * AP, and then reset link data. + */ + wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr); + wpa_tdls_send_teardown(sm, addr, + WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE); + wpa_tdls_peer_free(sm, peer); + } else { wpa_tdls_disable_peer_link(sm, peer); + } } @@ -1831,7 +1848,6 @@ skip_rsn: if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) { wpa_msg(sm->ctx->ctx, MSG_WARNING, "TDLS: Failed to get random data for responder nonce"); - wpa_tdls_peer_free(sm, peer); goto error; } } @@ -1887,8 +1903,10 @@ skip_rsn: skip_rsn_check: /* add the peer to the driver as a "setup in progress" peer */ - wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, NULL, 0, NULL, 0); + if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, + NULL, 0, NULL, 0, NULL, 0, NULL, 0)) + goto error; + peer->tpk_in_progress = 1; wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2"); @@ -1902,6 +1920,8 @@ skip_rsn_check: error: wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, status); + if (peer) + wpa_tdls_peer_free(sm, peer); return -1; } diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index ba2a8c87..40fb92a2 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -379,7 +379,8 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, - u16 ver) + u16 ver, const u8 *key_data, + size_t key_data_len) { struct wpa_eapol_ie_parse ie; struct wpa_ptk *ptk; @@ -401,10 +402,9 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) { /* RSN: msg 1/4 should contain PMKID for the selected PMK */ - const u8 *_buf = (const u8 *) (key + 1); - size_t len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len); - if (wpa_supplicant_parse_ies(_buf, len, &ie) < 0) + wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", + key_data, key_data_len); + if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) goto failed; if (ie.pmkid) { wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " @@ -1068,10 +1068,10 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, const struct wpa_eapol_key *key, - u16 ver) + u16 ver, const u8 *key_data, + size_t key_data_len) { - u16 key_info, keylen, len; - const u8 *pos; + u16 key_info, keylen; struct wpa_eapol_ie_parse ie; wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); @@ -1080,10 +1080,8 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, key_info = WPA_GET_BE16(key->key_info); - pos = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); - if (wpa_supplicant_parse_ies(pos, len, &ie) < 0) + wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len); + if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) goto failed; if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, @@ -1238,21 +1236,14 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, const struct wpa_eapol_key *key, - size_t keydatalen, int key_info, - size_t extra_len, u16 ver, - struct wpa_gtk_data *gd) + const u8 *key_data, + size_t key_data_len, u16 key_info, + u16 ver, struct wpa_gtk_data *gd) { size_t maxkeylen; gd->gtk_len = WPA_GET_BE16(key->key_length); - maxkeylen = keydatalen; - if (keydatalen > extra_len) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: Truncated EAPOL-Key packet: " - "key_data_length=%lu > extra_len=%lu", - (unsigned long) keydatalen, (unsigned long) extra_len); - return -1; - } + maxkeylen = key_data_len; if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { if (maxkeylen < 8) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, @@ -1272,16 +1263,16 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, WPA_KEY_INFO_KEY_INDEX_SHIFT; if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { u8 ek[32]; - if (keydatalen > sizeof(gd->gtk)) { + if (key_data_len > sizeof(gd->gtk)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: RC4 key data too long (%lu)", - (unsigned long) keydatalen); + (unsigned long) key_data_len); return -1; } os_memcpy(ek, key->key_iv, 16); os_memcpy(ek + 16, sm->ptk.kek, 16); - os_memcpy(gd->gtk, key + 1, keydatalen); - if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) { + os_memcpy(gd->gtk, key_data, key_data_len); + if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) { os_memset(ek, 0, sizeof(ek)); wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, "WPA: RC4 failed"); @@ -1289,22 +1280,21 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, } os_memset(ek, 0, sizeof(ek)); } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - if (keydatalen % 8) { + if (maxkeylen % 8) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Unsupported AES-WRAP len %lu", - (unsigned long) keydatalen); + (unsigned long) maxkeylen); return -1; } if (maxkeylen > sizeof(gd->gtk)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: AES-WRAP key data " "too long (keydatalen=%lu maxkeylen=%lu)", - (unsigned long) keydatalen, + (unsigned long) key_data_len, (unsigned long) maxkeylen); return -1; } - if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, - (const u8 *) (key + 1), gd->gtk)) { + if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, key_data, gd->gtk)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: AES unwrap failed - could not decrypt " "GTK"); @@ -1360,9 +1350,10 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, - int extra_len, u16 ver) + const u8 *key_data, + size_t key_data_len, u16 ver) { - u16 key_info, keydatalen; + u16 key_info; int rekey, ret; struct wpa_gtk_data gd; @@ -1373,17 +1364,15 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); key_info = WPA_GET_BE16(key->key_info); - keydatalen = WPA_GET_BE16(key->key_data_length); if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) { - ret = wpa_supplicant_process_1_of_2_rsn(sm, - (const u8 *) (key + 1), - keydatalen, key_info, + ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data, + key_data_len, key_info, &gd); } else { - ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen, - key_info, extra_len, - ver, &gd); + ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data, + key_data_len, + key_info, ver, &gd); } wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); @@ -1471,12 +1460,11 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, /* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, - struct wpa_eapol_key *key, u16 ver) + struct wpa_eapol_key *key, u16 ver, + u8 *key_data, size_t *key_data_len) { - u16 keydatalen = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", - (u8 *) (key + 1), keydatalen); + key_data, *key_data_len); if (!sm->ptk_set) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: PTK not available, cannot decrypt EAPOL-Key Key " @@ -1490,7 +1478,7 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, u8 ek[32]; os_memcpy(ek, key->key_iv, 16); os_memcpy(ek + 16, sm->ptk.kek, 16); - if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) { + if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) { os_memset(ek, 0, sizeof(ek)); wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, "WPA: RC4 failed"); @@ -1501,37 +1489,37 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, ver == WPA_KEY_INFO_TYPE_AES_128_CMAC || sm->key_mgmt == WPA_KEY_MGMT_OSEN) { u8 *buf; - if (keydatalen % 8) { + if (*key_data_len < 8 || *key_data_len % 8) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Unsupported AES-WRAP len %d", - keydatalen); + "WPA: Unsupported AES-WRAP len %u", + (unsigned int) *key_data_len); return -1; } - keydatalen -= 8; /* AES-WRAP adds 8 bytes */ - buf = os_malloc(keydatalen); + *key_data_len -= 8; /* AES-WRAP adds 8 bytes */ + buf = os_malloc(*key_data_len); if (buf == NULL) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No memory for AES-UNWRAP buffer"); return -1; } - if (aes_unwrap(sm->ptk.kek, keydatalen / 8, - (u8 *) (key + 1), buf)) { + if (aes_unwrap(sm->ptk.kek, *key_data_len / 8, + key_data, buf)) { os_free(buf); wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: AES unwrap failed - " "could not decrypt EAPOL-Key key data"); return -1; } - os_memcpy(key + 1, buf, keydatalen); + os_memcpy(key_data, buf, *key_data_len); os_free(buf); - WPA_PUT_BE16(key->key_data_length, keydatalen); + WPA_PUT_BE16(key->key_data_length, *key_data_len); } else { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Unsupported key_info type %d", ver); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", - (u8 *) (key + 1), keydatalen); + key_data, *key_data_len); return 0; } @@ -1605,13 +1593,14 @@ static void wpa_eapol_key_dump(struct wpa_sm *sm, int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, const u8 *buf, size_t len) { - size_t plen, data_len, extra_len; - struct ieee802_1x_hdr *hdr; + size_t plen, data_len, key_data_len; + const struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; u16 key_info, ver; - u8 *tmp; + u8 *tmp = NULL; int ret = -1; struct wpa_peerkey *peerkey = NULL; + u8 *key_data; #ifdef CONFIG_IEEE80211R sm->ft_completed = 0; @@ -1626,13 +1615,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, return 0; } - tmp = os_malloc(len); - if (tmp == NULL) - return -1; - os_memcpy(tmp, buf, len); - - hdr = (struct ieee802_1x_hdr *) tmp; - key = (struct wpa_eapol_key *) (hdr + 1); + hdr = (const struct ieee802_1x_hdr *) buf; plen = be_to_host16(hdr->length); data_len = plen + sizeof(*hdr); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, @@ -1649,6 +1632,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, ret = 0; goto out; } + wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len); if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: EAPOL frame payload size %lu " @@ -1657,6 +1641,22 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, ret = 0; goto out; } + if (data_len < len) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: ignoring %lu bytes after the IEEE 802.1X data", + (unsigned long) len - data_len); + } + + /* + * Make a copy of the frame since we need to modify the buffer during + * MAC validation and Key Data decryption. + */ + tmp = os_malloc(data_len); + if (tmp == NULL) + goto out; + os_memcpy(tmp, buf, data_len); + key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr)); + key_data = (u8 *) (key + 1); if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) { @@ -1668,13 +1668,16 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, } wpa_eapol_key_dump(sm, key); - eapol_sm_notify_lower_layer_success(sm->eapol, 0); - wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len); - if (data_len < len) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: ignoring %lu bytes after the IEEE 802.1X data", - (unsigned long) len - data_len); + key_data_len = WPA_GET_BE16(key->key_data_length); + if (key_data_len > plen - sizeof(struct wpa_eapol_key)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " + "frame - key_data overflow (%u > %u)", + (unsigned int) key_data_len, + (unsigned int) (plen - sizeof(struct wpa_eapol_key))); + goto out; } + + eapol_sm_notify_lower_layer_success(sm->eapol, 0); key_info = WPA_GET_BE16(key->key_info); ver = key_info & WPA_KEY_INFO_TYPE_MASK; if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && @@ -1814,22 +1817,11 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, goto out; #endif /* CONFIG_PEERKEY */ - extra_len = data_len - sizeof(*hdr) - sizeof(*key); - - if (WPA_GET_BE16(key->key_data_length) > extra_len) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " - "frame - key_data overflow (%d > %lu)", - WPA_GET_BE16(key->key_data_length), - (unsigned long) extra_len); - goto out; - } - extra_len = WPA_GET_BE16(key->key_data_length); - if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - if (wpa_supplicant_decrypt_key_data(sm, key, ver)) + if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data, + &key_data_len)) goto out; - extra_len = WPA_GET_BE16(key->key_data_length); } if (key_info & WPA_KEY_INFO_KEY_TYPE) { @@ -1844,21 +1836,24 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver); } else if (key_info & WPA_KEY_INFO_MIC) { /* 3/4 4-Way Handshake */ - wpa_supplicant_process_3_of_4(sm, key, ver); + wpa_supplicant_process_3_of_4(sm, key, ver, key_data, + key_data_len); } else { /* 1/4 4-Way Handshake */ wpa_supplicant_process_1_of_4(sm, src_addr, key, - ver); + ver, key_data, + key_data_len); } } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { /* PeerKey SMK Handshake */ - peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info, + peerkey_rx_eapol_smk(sm, src_addr, key, key_data_len, key_info, ver); } else { if (key_info & WPA_KEY_INFO_MIC) { /* 1/2 Group Key Handshake */ wpa_supplicant_process_1_of_2(sm, src_addr, key, - extra_len, ver); + key_data, key_data_len, + ver); } else { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: EAPOL-Key (Group) without Mic bit - " diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index e98967c9..07a7bf90 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -385,7 +385,7 @@ int wpa_tdls_init(struct wpa_sm *sm); void wpa_tdls_teardown_peers(struct wpa_sm *sm); void wpa_tdls_deinit(struct wpa_sm *sm); void wpa_tdls_enable(struct wpa_sm *sm, int enabled); -void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr); +void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr); const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr); int wpa_tdls_is_external_setup(struct wpa_sm *sm); diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index f62b49e6..ae94a9f6 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -596,7 +596,10 @@ static struct wpabuf * build_fake_wsc_ack(void) wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put(msg, WPS_NONCE_LEN); - wps_build_wfa_ext(msg, 0, NULL, 0); + if (wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } return msg; } |
