diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 905bb4aa9..f7b1fb72c 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -459,7 +459,7 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt)) { /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(sm); + wpa_ft_prepare_auth_request(sm, NULL); } #endif /* CONFIG_IEEE80211R */ } @@ -1936,7 +1936,7 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) wpa_supplicant_key_neg_complete(sm, sm->bssid, 1); /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(sm); + wpa_ft_prepare_auth_request(sm, NULL); clear_ptk = 0; } diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 5ff69062d..0d4405b53 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -281,14 +281,15 @@ static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *r1kh_id); -int wpa_ft_prepare_auth_request(struct wpa_sm *sm); +int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie); int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, int ft_action, const u8 *target_ap, const u8 *ric_ies, size_t ric_ies_len); int wpa_ft_is_completed(struct wpa_sm *sm); int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len, const u8 *src_addr); -int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap); +int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap, + const u8 *mdie); #else /* CONFIG_IEEE80211R */ @@ -299,7 +300,8 @@ wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, return 0; } -static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm) +static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm, + const u8 *mdie) { return 0; } diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index eb68e262b..7c89e9b78 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -115,6 +115,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, * @target_ap: Target AP address * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL * @ric_ies_len: Length of ric_ies buffer in octets + * @ap_mdie: Mobility Domain IE from the target AP * Returns: Pointer to buffer with IEs or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(); @@ -122,7 +123,8 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, const u8 *anonce, const u8 *pmk_name, const u8 *kck, const u8 *target_ap, - const u8 *ric_ies, size_t ric_ies_len) + const u8 *ric_ies, size_t ric_ies_len, + const u8 *ap_mdie) { size_t buf_len; u8 *buf, *pos, *ftie_len, *ftie_pos; @@ -227,7 +229,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, pos += sizeof(*mdie); os_memcpy(mdie->mobility_domain, sm->mobility_domain, MOBILITY_DOMAIN_ID_LEN); - mdie->ft_capab = 0; /* FIX: copy from the target AP's MDIE */ + mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] : 0; /* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */ ftie_pos = pos; @@ -497,9 +499,10 @@ static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid) /** * wpa_ft_prepare_auth_request - Generate over-the-air auth request * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @mdie: Target AP MDIE * Returns: 0 on success, -1 on failure */ -int wpa_ft_prepare_auth_request(struct wpa_sm *sm) +int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie) { u8 *ft_ies; size_t ft_ies_len; @@ -511,7 +514,7 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm) } ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, sm->bssid, NULL, 0); + NULL, sm->bssid, NULL, 0, mdie); if (ft_ies) { wpa_sm_update_ft_ies(sm, sm->mobility_domain, ft_ies, ft_ies_len); @@ -628,7 +631,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce, sm->pmk_r1_name, sm->ptk.kck, bssid, - ric_ies, ric_ies_len); + ric_ies, ric_ies_len, + parse.mdie ? parse.mdie - 2 : NULL); if (ft_ies) { wpa_sm_update_ft_ies(sm, sm->mobility_domain, ft_ies, ft_ies_len); @@ -936,9 +940,12 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, /** * wpa_ft_start_over_ds - Generate over-the-DS auth request * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @target_ap: Target AP Address + * @mdie: Mobility Domain IE from the target AP * Returns: 0 on success, -1 on failure */ -int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap) +int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap, + const u8 *mdie) { u8 *ft_ies; size_t ft_ies_len; @@ -953,7 +960,7 @@ int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap) } ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, target_ap, NULL, 0); + NULL, target_ap, NULL, 0, mdie); if (ft_ies) { sm->over_the_ds_in_progress = 1; os_memcpy(sm->target_ap, target_ap, ETH_ALEN); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index c7d342762..969cc8a08 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -136,6 +136,8 @@ static int wpa_supplicant_ctrl_iface_ft_ds( struct wpa_supplicant *wpa_s, char *addr) { u8 target_ap[ETH_ALEN]; + struct wpa_bss *bss; + const u8 *mdie; if (hwaddr_aton(addr, target_ap)) { wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " @@ -145,7 +147,13 @@ static int wpa_supplicant_ctrl_iface_ft_ds( wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); - return wpa_ft_start_over_ds(wpa_s->wpa, target_ap); + bss = wpa_bss_get_bssid(wpa_s, target_ap); + if (bss) + mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); + else + mdie = NULL; + + return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie); } #endif /* CONFIG_IEEE80211R */ diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index f04295a71..814837549 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -163,7 +163,7 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL); if (md) { /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(wpa_s->wpa); + wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && ssid->key_mgmt & (WPA_KEY_MGMT_FT_PSK | diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 6748735c0..c5387bfd6 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1040,7 +1040,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL); if (md) { /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(wpa_s->wpa); + wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_WPS