RSN: Verify RSNXE match between Beacon/ProbeResp and EAPOL-Key msg 3/4
If the AP advertises RSN Extension element, it has to be advertised consistently in the unprotected (Beacon and Probe Response) and protected (EAPOL-Key msg 3/4) frames. Verify that this is the case. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
3134bb13a8
commit
146889e3ca
9 changed files with 85 additions and 9 deletions
|
@ -1365,6 +1365,16 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((sm->ap_rsnxe && !ie->rsnxe) ||
|
||||||
|
(!sm->ap_rsnxe && ie->rsnxe) ||
|
||||||
|
(sm->ap_rsnxe && ie->rsnxe &&
|
||||||
|
(sm->ap_rsnxe_len != ie->rsnxe_len ||
|
||||||
|
os_memcmp(sm->ap_rsnxe, ie->rsnxe, sm->ap_rsnxe_len) != 0))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"WPA: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
if (wpa_key_mgmt_ft(sm->key_mgmt) &&
|
if (wpa_key_mgmt_ft(sm->key_mgmt) &&
|
||||||
wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
|
wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
|
||||||
|
@ -2664,6 +2674,7 @@ void wpa_sm_deinit(struct wpa_sm *sm)
|
||||||
os_free(sm->assoc_wpa_ie);
|
os_free(sm->assoc_wpa_ie);
|
||||||
os_free(sm->ap_wpa_ie);
|
os_free(sm->ap_wpa_ie);
|
||||||
os_free(sm->ap_rsn_ie);
|
os_free(sm->ap_rsn_ie);
|
||||||
|
os_free(sm->ap_rsnxe);
|
||||||
wpa_sm_drop_sa(sm);
|
wpa_sm_drop_sa(sm);
|
||||||
os_free(sm->ctx);
|
os_free(sm->ctx);
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
|
@ -3283,6 +3294,39 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_sm_set_ap_rsnxe - Set AP RSNXE from Beacon/ProbeResp
|
||||||
|
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||||
|
* @ie: Pointer to IE data (starting from id)
|
||||||
|
* @len: IE length
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* Inform WPA state machine about the RSNXE used in Beacon / Probe Response
|
||||||
|
* frame.
|
||||||
|
*/
|
||||||
|
int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
|
{
|
||||||
|
if (!sm)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_free(sm->ap_rsnxe);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE");
|
||||||
|
sm->ap_rsnxe = NULL;
|
||||||
|
sm->ap_rsnxe_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
|
||||||
|
sm->ap_rsnxe = os_memdup(ie, len);
|
||||||
|
if (!sm->ap_rsnxe)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sm->ap_rsnxe_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
|
* wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
|
||||||
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||||
|
|
|
@ -136,6 +136,7 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
|
||||||
size_t *wpa_ie_len);
|
size_t *wpa_ie_len);
|
||||||
int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
|
int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
|
int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
|
int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen);
|
int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen);
|
||||||
|
|
||||||
int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
|
int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
|
||||||
|
@ -260,6 +261,12 @@ static inline int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
|
static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -88,8 +88,8 @@ struct wpa_sm {
|
||||||
|
|
||||||
u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
|
u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
|
||||||
size_t assoc_wpa_ie_len;
|
size_t assoc_wpa_ie_len;
|
||||||
u8 *ap_wpa_ie, *ap_rsn_ie;
|
u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
|
||||||
size_t ap_wpa_ie_len, ap_rsn_ie_len;
|
size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
|
||||||
|
|
||||||
#ifdef CONFIG_TDLS
|
#ifdef CONFIG_TDLS
|
||||||
struct wpa_tdls_peer *tdls;
|
struct wpa_tdls_peer *tdls;
|
||||||
|
|
|
@ -506,6 +506,11 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
|
||||||
ie->rsn_ie_len = pos[1] + 2;
|
ie->rsn_ie_len = pos[1] + 2;
|
||||||
wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
|
wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
|
||||||
ie->rsn_ie, ie->rsn_ie_len);
|
ie->rsn_ie, ie->rsn_ie_len);
|
||||||
|
} else if (*pos == WLAN_EID_RSNX) {
|
||||||
|
ie->rsnxe = pos;
|
||||||
|
ie->rsnxe_len = pos[1] + 2;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key",
|
||||||
|
ie->rsnxe, ie->rsnxe_len);
|
||||||
} else if (*pos == WLAN_EID_MOBILITY_DOMAIN &&
|
} else if (*pos == WLAN_EID_MOBILITY_DOMAIN &&
|
||||||
pos[1] >= sizeof(struct rsn_mdie)) {
|
pos[1] >= sizeof(struct rsn_mdie)) {
|
||||||
ie->mdie = pos;
|
ie->mdie = pos;
|
||||||
|
|
|
@ -23,6 +23,8 @@ struct wpa_eapol_ie_parse {
|
||||||
size_t mac_addr_len;
|
size_t mac_addr_len;
|
||||||
const u8 *igtk;
|
const u8 *igtk;
|
||||||
size_t igtk_len;
|
size_t igtk_len;
|
||||||
|
const u8 *rsnxe;
|
||||||
|
size_t rsnxe_len;
|
||||||
const u8 *mdie;
|
const u8 *mdie;
|
||||||
size_t mdie_len;
|
size_t mdie_len;
|
||||||
const u8 *ftie;
|
const u8 *ftie;
|
||||||
|
|
|
@ -2647,14 +2647,19 @@ no_pfs:
|
||||||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
|
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p[0] == WLAN_EID_RSNX && p[1] >= 1)
|
||||||
|
wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
|
||||||
|
|
||||||
l -= len;
|
l -= len;
|
||||||
p += len;
|
p += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wpa_found && data->assoc_info.beacon_ies)
|
if (!wpa_found && data->assoc_info.beacon_ies)
|
||||||
wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
|
wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
|
||||||
if (!rsn_found && data->assoc_info.beacon_ies)
|
if (!rsn_found && data->assoc_info.beacon_ies) {
|
||||||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
|
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
|
||||||
|
wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
|
||||||
|
}
|
||||||
if (wpa_found || rsn_found)
|
if (wpa_found || rsn_found)
|
||||||
wpa_s->ap_ies_from_associnfo = 1;
|
wpa_s->ap_ies_from_associnfo = 1;
|
||||||
|
|
||||||
|
@ -2674,7 +2679,7 @@ no_pfs:
|
||||||
|
|
||||||
static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
|
static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
const u8 *bss_wpa = NULL, *bss_rsn = NULL;
|
const u8 *bss_wpa = NULL, *bss_rsn = NULL, *bss_rsnx = NULL;
|
||||||
|
|
||||||
if (!wpa_s->current_bss || !wpa_s->current_ssid)
|
if (!wpa_s->current_bss || !wpa_s->current_ssid)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2685,11 +2690,14 @@ static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
|
||||||
bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss,
|
bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss,
|
||||||
WPA_IE_VENDOR_TYPE);
|
WPA_IE_VENDOR_TYPE);
|
||||||
bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN);
|
bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN);
|
||||||
|
bss_rsnx = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSNX);
|
||||||
|
|
||||||
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
|
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
|
||||||
bss_wpa ? 2 + bss_wpa[1] : 0) ||
|
bss_wpa ? 2 + bss_wpa[1] : 0) ||
|
||||||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
|
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
|
||||||
bss_rsn ? 2 + bss_rsn[1] : 0))
|
bss_rsn ? 2 + bss_rsn[1] : 0) ||
|
||||||
|
wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
|
||||||
|
bss_rsnx ? 2 + bss_rsnx[1] : 0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -111,6 +111,7 @@ static int supp_get_beacon_ie(void *ctx)
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
|
wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
|
||||||
/* TODO: get correct RSN IE */
|
/* TODO: get correct RSN IE */
|
||||||
|
wpa_sm_set_ap_rsnxe(peer->supp, NULL, 0);
|
||||||
return wpa_sm_set_ap_rsn_ie(peer->supp,
|
return wpa_sm_set_ap_rsn_ie(peer->supp,
|
||||||
(u8 *) "\x30\x14\x01\x00"
|
(u8 *) "\x30\x14\x01\x00"
|
||||||
"\x00\x0f\xac\x04"
|
"\x00\x0f\xac\x04"
|
||||||
|
|
|
@ -402,6 +402,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
|
||||||
wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
|
wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
|
||||||
wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
|
wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
|
||||||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
|
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
|
||||||
|
wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
|
||||||
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
|
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
|
||||||
wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
|
wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
|
||||||
wpa_s->group_cipher = WPA_CIPHER_NONE;
|
wpa_s->group_cipher = WPA_CIPHER_NONE;
|
||||||
|
@ -1233,14 +1234,16 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
||||||
{
|
{
|
||||||
struct wpa_ie_data ie;
|
struct wpa_ie_data ie;
|
||||||
int sel, proto;
|
int sel, proto;
|
||||||
const u8 *bss_wpa, *bss_rsn, *bss_osen;
|
const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
|
||||||
|
|
||||||
if (bss) {
|
if (bss) {
|
||||||
bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
|
bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
|
||||||
bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
|
bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
|
||||||
|
bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
|
||||||
bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
|
bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
|
||||||
} else
|
} else {
|
||||||
bss_wpa = bss_rsn = bss_osen = NULL;
|
bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
|
if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
|
||||||
wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
|
wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
|
||||||
|
@ -1371,7 +1374,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
||||||
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
|
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
|
||||||
bss_wpa ? 2 + bss_wpa[1] : 0) ||
|
bss_wpa ? 2 + bss_wpa[1] : 0) ||
|
||||||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
|
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
|
||||||
bss_rsn ? 2 + bss_rsn[1] : 0))
|
bss_rsn ? 2 + bss_rsn[1] : 0) ||
|
||||||
|
wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
|
||||||
|
bss_rsnx ? 2 + bss_rsnx[1] : 0))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -396,6 +396,10 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
|
||||||
ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
|
ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
|
||||||
if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
|
if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
|
ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX);
|
||||||
|
if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
|
||||||
|
ret = -1;
|
||||||
} else {
|
} else {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue