FT: Copy FT Capability and Policy to MDIE from target AP

This sets the FT Capability and Policy field in the MDIE to the values
received from the target AP (if available). This fixes the MDIE contents
during FT Protocol, but the correct value may not yet be used in initial
mobility domain association.
This commit is contained in:
Jouni Malinen 2010-04-09 16:26:20 +03:00 committed by Jouni Malinen
parent 3db6531436
commit 76b7981d07
6 changed files with 32 additions and 15 deletions

View file

@ -459,7 +459,7 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->key_mgmt)) { if (wpa_key_mgmt_ft(sm->key_mgmt)) {
/* Prepare for the next transition */ /* Prepare for the next transition */
wpa_ft_prepare_auth_request(sm); wpa_ft_prepare_auth_request(sm, NULL);
} }
#endif /* CONFIG_IEEE80211R */ #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); wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
/* Prepare for the next transition */ /* Prepare for the next transition */
wpa_ft_prepare_auth_request(sm); wpa_ft_prepare_auth_request(sm, NULL);
clear_ptk = 0; clear_ptk = 0;
} }

View file

@ -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, 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 *r0kh_id, size_t r0kh_id_len,
const u8 *r1kh_id); 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 wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
int ft_action, const u8 *target_ap, int ft_action, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len); const u8 *ric_ies, size_t ric_ies_len);
int wpa_ft_is_completed(struct wpa_sm *sm); int wpa_ft_is_completed(struct wpa_sm *sm);
int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
size_t ies_len, const u8 *src_addr); 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 */ #else /* CONFIG_IEEE80211R */
@ -299,7 +300,8 @@ wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
return 0; 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; return 0;
} }

View file

@ -115,6 +115,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
* @target_ap: Target AP address * @target_ap: Target AP address
* @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL * @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 * @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 * Returns: Pointer to buffer with IEs or %NULL on failure
* *
* Caller is responsible for freeing the returned buffer with os_free(); * 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, static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
const u8 *anonce, const u8 *pmk_name, const u8 *anonce, const u8 *pmk_name,
const u8 *kck, const u8 *target_ap, 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; size_t buf_len;
u8 *buf, *pos, *ftie_len, *ftie_pos; 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); pos += sizeof(*mdie);
os_memcpy(mdie->mobility_domain, sm->mobility_domain, os_memcpy(mdie->mobility_domain, sm->mobility_domain,
MOBILITY_DOMAIN_ID_LEN); 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[SNonce, [R1KH-ID,] R0KH-ID ] */
ftie_pos = pos; 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 * wpa_ft_prepare_auth_request - Generate over-the-air auth request
* @sm: Pointer to WPA state machine data from wpa_sm_init() * @sm: Pointer to WPA state machine data from wpa_sm_init()
* @mdie: Target AP MDIE
* Returns: 0 on success, -1 on failure * 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; u8 *ft_ies;
size_t ft_ies_len; 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, 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) { if (ft_ies) {
wpa_sm_update_ft_ies(sm, sm->mobility_domain, wpa_sm_update_ft_ies(sm, sm->mobility_domain,
ft_ies, ft_ies_len); 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, ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
sm->pmk_r1_name, sm->ptk.kck, bssid, 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) { if (ft_ies) {
wpa_sm_update_ft_ies(sm, sm->mobility_domain, wpa_sm_update_ft_ies(sm, sm->mobility_domain,
ft_ies, ft_ies_len); 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 * wpa_ft_start_over_ds - Generate over-the-DS auth request
* @sm: Pointer to WPA state machine data from wpa_sm_init() * @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 * 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; u8 *ft_ies;
size_t ft_ies_len; 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, 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) { if (ft_ies) {
sm->over_the_ds_in_progress = 1; sm->over_the_ds_in_progress = 1;
os_memcpy(sm->target_ap, target_ap, ETH_ALEN); os_memcpy(sm->target_ap, target_ap, ETH_ALEN);

View file

@ -136,6 +136,8 @@ static int wpa_supplicant_ctrl_iface_ft_ds(
struct wpa_supplicant *wpa_s, char *addr) struct wpa_supplicant *wpa_s, char *addr)
{ {
u8 target_ap[ETH_ALEN]; u8 target_ap[ETH_ALEN];
struct wpa_bss *bss;
const u8 *mdie;
if (hwaddr_aton(addr, target_ap)) { if (hwaddr_aton(addr, target_ap)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 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)); 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 */ #endif /* CONFIG_IEEE80211R */

View file

@ -163,7 +163,7 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL); wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL);
if (md) { if (md) {
/* Prepare for the next transition */ /* 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 | if (md && ssid->key_mgmt & (WPA_KEY_MGMT_FT_PSK |

View file

@ -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); wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL);
if (md) { if (md) {
/* Prepare for the next transition */ /* 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 */ #endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_WPS #ifdef CONFIG_WPS