RSNO: Include all RSNE/RSNXE variants in EAPOL-Key message 3/4
This allows all variants to be verified based on a protected frame to achieve robust downgrade protection. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
6f522baa1b
commit
521374b978
8 changed files with 275 additions and 121 deletions
|
@ -4665,82 +4665,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
||||||
wpa_ie = wpa_ie + wpa_ie[1] + 2;
|
wpa_ie = wpa_ie + wpa_ie[1] + 2;
|
||||||
wpa_ie_len = wpa_ie[1] + 2;
|
wpa_ie_len = wpa_ie[1] + 2;
|
||||||
}
|
}
|
||||||
if ((sm->rsn_override &&
|
if ((conf->rsn_override_key_mgmt || conf->rsn_override_key_mgmt_2) &&
|
||||||
get_vendor_ie(wpa_ie, wpa_ie_len, RSNE_OVERRIDE_IE_VENDOR_TYPE)) ||
|
!rsn_is_snonce_cookie(sm->SNonce)) {
|
||||||
(sm->rsn_override_2 &&
|
|
||||||
get_vendor_ie(wpa_ie, wpa_ie_len,
|
|
||||||
RSNE_OVERRIDE_2_IE_VENDOR_TYPE))) {
|
|
||||||
const u8 *mde, *fte, *tie, *tie2 = NULL;
|
|
||||||
const u8 *override_rsne = NULL, *override_rsnxe = NULL;
|
|
||||||
const struct element *elem;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"RSN: Use RSNE/RSNXE override element contents");
|
|
||||||
mde = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_MOBILITY_DOMAIN);
|
|
||||||
fte = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_FAST_BSS_TRANSITION);
|
|
||||||
tie = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_TIMEOUT_INTERVAL);
|
|
||||||
if (tie) {
|
|
||||||
const u8 *next = tie + 2 + tie[1];
|
|
||||||
|
|
||||||
tie2 = get_ie(next, wpa_ie + wpa_ie_len - next,
|
|
||||||
WLAN_EID_TIMEOUT_INTERVAL);
|
|
||||||
}
|
|
||||||
for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC,
|
|
||||||
wpa_ie, wpa_ie_len) {
|
|
||||||
if (elem->datalen >= 4) {
|
|
||||||
if (WPA_GET_BE32(elem->data) ==
|
|
||||||
(sm->rsn_override_2 ?
|
|
||||||
RSNE_OVERRIDE_2_IE_VENDOR_TYPE :
|
|
||||||
RSNE_OVERRIDE_IE_VENDOR_TYPE))
|
|
||||||
override_rsne = &elem->id;
|
|
||||||
if (WPA_GET_BE32(elem->data) ==
|
|
||||||
RSNXE_OVERRIDE_IE_VENDOR_TYPE)
|
|
||||||
override_rsnxe = &elem->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs before edits",
|
|
||||||
wpa_ie, wpa_ie_len);
|
|
||||||
wpa_ie_buf3 = os_malloc(wpa_ie_len);
|
|
||||||
if (!wpa_ie_buf3)
|
|
||||||
goto done;
|
|
||||||
pos = wpa_ie_buf3;
|
|
||||||
if (override_rsne) {
|
|
||||||
*pos++ = WLAN_EID_RSN;
|
|
||||||
*pos++ = override_rsne[1] - 4;
|
|
||||||
os_memcpy(pos, &override_rsne[2 + 4],
|
|
||||||
override_rsne[1] - 4);
|
|
||||||
pos += override_rsne[1] - 4;
|
|
||||||
}
|
|
||||||
if (mde) {
|
|
||||||
os_memcpy(pos, mde, 2 + mde[1]);
|
|
||||||
pos += 2 + mde[1];
|
|
||||||
}
|
|
||||||
if (fte) {
|
|
||||||
os_memcpy(pos, fte, 2 + fte[1]);
|
|
||||||
pos += 2 + fte[1];
|
|
||||||
}
|
|
||||||
if (tie) {
|
|
||||||
os_memcpy(pos, tie, 2 + tie[1]);
|
|
||||||
pos += 2 + tie[1];
|
|
||||||
}
|
|
||||||
if (tie2) {
|
|
||||||
os_memcpy(pos, tie2, 2 + tie2[1]);
|
|
||||||
pos += 2 + tie2[1];
|
|
||||||
}
|
|
||||||
if (override_rsnxe) {
|
|
||||||
*pos++ = WLAN_EID_RSNX;
|
|
||||||
*pos++ = override_rsnxe[1] - 4;
|
|
||||||
os_memcpy(pos, &override_rsnxe[2 + 4],
|
|
||||||
override_rsnxe[1] - 4);
|
|
||||||
pos += override_rsnxe[1] - 4;
|
|
||||||
}
|
|
||||||
wpa_ie = wpa_ie_buf3;
|
|
||||||
wpa_ie_len = pos - wpa_ie_buf3;
|
|
||||||
wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits",
|
|
||||||
wpa_ie, wpa_ie_len);
|
|
||||||
} else if ((conf->rsn_override_key_mgmt ||
|
|
||||||
conf->rsn_override_key_mgmt_2) &&
|
|
||||||
!sm->rsn_override && !sm->rsn_override_2) {
|
|
||||||
u8 *ie;
|
u8 *ie;
|
||||||
size_t ie_len;
|
size_t ie_len;
|
||||||
u32 ids[] = {
|
u32 ids[] = {
|
||||||
|
|
|
@ -3629,6 +3629,24 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selector == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
|
||||||
|
ie->rsne_override = pos;
|
||||||
|
ie->rsne_override_len = dlen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selector == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
|
||||||
|
ie->rsne_override_2 = pos;
|
||||||
|
ie->rsne_override_2_len = dlen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selector == RSNXE_OVERRIDE_IE_VENDOR_TYPE) {
|
||||||
|
ie->rsnxe_override = pos;
|
||||||
|
ie->rsnxe_override_len = dlen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (selector == RSN_SELECTION_IE_VENDOR_TYPE) {
|
if (selector == RSN_SELECTION_IE_VENDOR_TYPE) {
|
||||||
ie->rsn_selection = p;
|
ie->rsn_selection = p;
|
||||||
ie->rsn_selection_len = left;
|
ie->rsn_selection_len = left;
|
||||||
|
|
|
@ -714,6 +714,12 @@ struct wpa_eapol_ie_parse {
|
||||||
size_t wmm_len;
|
size_t wmm_len;
|
||||||
const u8 *rsn_selection;
|
const u8 *rsn_selection;
|
||||||
size_t rsn_selection_len;
|
size_t rsn_selection_len;
|
||||||
|
const u8 *rsne_override;
|
||||||
|
size_t rsne_override_len;
|
||||||
|
const u8 *rsne_override_2;
|
||||||
|
size_t rsne_override_2_len;
|
||||||
|
const u8 *rsnxe_override;
|
||||||
|
size_t rsnxe_override_len;
|
||||||
u16 valid_mlo_gtks; /* bitmap of valid link GTK KDEs */
|
u16 valid_mlo_gtks; /* bitmap of valid link GTK KDEs */
|
||||||
const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
|
const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
|
||||||
size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
|
size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
|
||||||
|
|
|
@ -2228,6 +2228,69 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sm->proto == WPA_PROTO_RSN &&
|
||||||
|
sm->rsn_override != RSN_OVERRIDE_NOT_USED) {
|
||||||
|
if ((sm->ap_rsne_override && !ie->rsne_override) ||
|
||||||
|
(!sm->ap_rsne_override && ie->rsne_override) ||
|
||||||
|
(sm->ap_rsne_override && ie->rsne_override &&
|
||||||
|
(sm->ap_rsne_override_len != ie->rsne_override_len ||
|
||||||
|
os_memcmp(sm->ap_rsne_override, ie->rsne_override,
|
||||||
|
sm->ap_rsne_override_len) != 0))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN: RSNE Override element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNE Override element in Beacon/ProbeResp",
|
||||||
|
sm->ap_rsne_override,
|
||||||
|
sm->ap_rsne_override_len);
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNE Override element in EAPOL-Key msg 3/4",
|
||||||
|
ie->rsne_override, ie->rsne_override_len);
|
||||||
|
wpa_sm_deauthenticate(sm,
|
||||||
|
WLAN_REASON_IE_IN_4WAY_DIFFERS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sm->ap_rsne_override_2 && !ie->rsne_override_2) ||
|
||||||
|
(!sm->ap_rsne_override_2 && ie->rsne_override_2) ||
|
||||||
|
(sm->ap_rsne_override_2 && ie->rsne_override_2 &&
|
||||||
|
(sm->ap_rsne_override_2_len != ie->rsne_override_2_len ||
|
||||||
|
os_memcmp(sm->ap_rsne_override_2, ie->rsne_override_2,
|
||||||
|
sm->ap_rsne_override_2_len) != 0))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN: RSNE Override 2 element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNE Override 2 element in Beacon/ProbeResp",
|
||||||
|
sm->ap_rsne_override_2,
|
||||||
|
sm->ap_rsne_override_2_len);
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNE Override 2 element in EAPOL-Key msg 3/4",
|
||||||
|
ie->rsne_override_2, ie->rsne_override_2_len);
|
||||||
|
wpa_sm_deauthenticate(sm,
|
||||||
|
WLAN_REASON_IE_IN_4WAY_DIFFERS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sm->ap_rsnxe_override && !ie->rsnxe_override) ||
|
||||||
|
(!sm->ap_rsnxe_override && ie->rsnxe_override) ||
|
||||||
|
(sm->ap_rsnxe_override && ie->rsnxe_override &&
|
||||||
|
(sm->ap_rsnxe_override_len != ie->rsnxe_override_len ||
|
||||||
|
os_memcmp(sm->ap_rsnxe_override, ie->rsnxe_override,
|
||||||
|
sm->ap_rsnxe_override_len) != 0))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN: RSNXE Override element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNXE Override element in Beacon/ProbeResp",
|
||||||
|
sm->ap_rsnxe_override,
|
||||||
|
sm->ap_rsnxe_override_len);
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNXE Override element in EAPOL-Key msg 3/4",
|
||||||
|
ie->rsnxe_override, ie->rsnxe_override_len);
|
||||||
|
wpa_sm_deauthenticate(sm,
|
||||||
|
WLAN_REASON_IE_IN_4WAY_DIFFERS);
|
||||||
|
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)
|
||||||
|
@ -4208,6 +4271,9 @@ void wpa_sm_deinit(struct wpa_sm *sm)
|
||||||
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);
|
os_free(sm->ap_rsnxe);
|
||||||
|
os_free(sm->ap_rsne_override);
|
||||||
|
os_free(sm->ap_rsne_override_2);
|
||||||
|
os_free(sm->ap_rsnxe_override);
|
||||||
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
||||||
os_free(sm->mlo.links[i].ap_rsne);
|
os_free(sm->mlo.links[i].ap_rsne);
|
||||||
os_free(sm->mlo.links[i].ap_rsnxe);
|
os_free(sm->mlo.links[i].ap_rsnxe);
|
||||||
|
@ -4813,6 +4879,23 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const u8 * wpa_sm_get_ap_rsne(struct wpa_sm *sm, size_t *len)
|
||||||
|
{
|
||||||
|
if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE) {
|
||||||
|
*len = sm->ap_rsne_override_len;
|
||||||
|
return sm->ap_rsne_override;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE_2) {
|
||||||
|
*len = sm->ap_rsne_override_2_len;
|
||||||
|
return sm->ap_rsne_override_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = sm->ap_rsn_ie_len;
|
||||||
|
return sm->ap_rsn_ie;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_sm_get_status - Get WPA state machine
|
* wpa_sm_get_status - Get WPA state machine
|
||||||
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||||
|
@ -4830,6 +4913,10 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
|
||||||
{
|
{
|
||||||
char *pos = buf, *end = buf + buflen;
|
char *pos = buf, *end = buf + buflen;
|
||||||
int ret;
|
int ret;
|
||||||
|
const u8 *rsne;
|
||||||
|
size_t rsne_len;
|
||||||
|
|
||||||
|
rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
|
||||||
|
|
||||||
ret = os_snprintf(pos, end - pos,
|
ret = os_snprintf(pos, end - pos,
|
||||||
"pairwise_cipher=%s\n"
|
"pairwise_cipher=%s\n"
|
||||||
|
@ -4851,10 +4938,10 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) {
|
if (sm->mfp != NO_MGMT_FRAME_PROTECTION && rsne) {
|
||||||
struct wpa_ie_data rsn;
|
struct wpa_ie_data rsn;
|
||||||
if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn)
|
|
||||||
>= 0 &&
|
if (wpa_parse_wpa_ie_rsn(rsne, rsne_len, &rsn) >= 0 &&
|
||||||
rsn.capabilities & (WPA_CAPABILITY_MFPR |
|
rsn.capabilities & (WPA_CAPABILITY_MFPR |
|
||||||
WPA_CAPABILITY_MFPC)) {
|
WPA_CAPABILITY_MFPC)) {
|
||||||
ret = os_snprintf(pos, end - pos, "pmf=%d\n"
|
ret = os_snprintf(pos, end - pos, "pmf=%d\n"
|
||||||
|
@ -4876,11 +4963,15 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
|
||||||
int wpa_sm_pmf_enabled(struct wpa_sm *sm)
|
int wpa_sm_pmf_enabled(struct wpa_sm *sm)
|
||||||
{
|
{
|
||||||
struct wpa_ie_data rsn;
|
struct wpa_ie_data rsn;
|
||||||
|
const u8 *rsne;
|
||||||
|
size_t rsne_len;
|
||||||
|
|
||||||
if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
|
rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
|
||||||
|
|
||||||
|
if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !rsne)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 &&
|
if (wpa_parse_wpa_ie_rsn(rsne, rsne_len, &rsn) >= 0 &&
|
||||||
rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
|
rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -4903,12 +4994,14 @@ int wpa_sm_ext_key_id_active(struct wpa_sm *sm)
|
||||||
int wpa_sm_ocv_enabled(struct wpa_sm *sm)
|
int wpa_sm_ocv_enabled(struct wpa_sm *sm)
|
||||||
{
|
{
|
||||||
struct wpa_ie_data rsn;
|
struct wpa_ie_data rsn;
|
||||||
|
const u8 *rsne;
|
||||||
|
size_t rsne_len;
|
||||||
|
|
||||||
if (!sm->ocv || !sm->ap_rsn_ie)
|
rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
|
||||||
|
if (!sm->ocv || !rsne)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len,
|
return wpa_parse_wpa_ie_rsn(rsne, rsne_len, &rsn) >= 0 &&
|
||||||
&rsn) >= 0 &&
|
|
||||||
(rsn.capabilities & WPA_CAPABILITY_OCVC);
|
(rsn.capabilities & WPA_CAPABILITY_OCVC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5145,24 +5238,11 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
sm->ap_rsn_ie_len = 0;
|
sm->ap_rsn_ie_len = 0;
|
||||||
} else {
|
} else {
|
||||||
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
|
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
|
||||||
if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
|
sm->ap_rsn_ie = os_memdup(ie, len);
|
||||||
sm->ap_rsn_ie = os_malloc(len - 4);
|
if (sm->ap_rsn_ie == NULL)
|
||||||
if (!sm->ap_rsn_ie)
|
return -1;
|
||||||
return -1;
|
|
||||||
sm->ap_rsn_ie[0] = WLAN_EID_RSN;
|
|
||||||
sm->ap_rsn_ie[1] = len - 2 - 4;
|
|
||||||
os_memcpy(&sm->ap_rsn_ie[2], ie + 2 + 4, len - 2 - 4);
|
|
||||||
sm->ap_rsn_ie_len = len - 4;
|
|
||||||
wpa_hexdump(MSG_DEBUG,
|
|
||||||
"RSN: Converted RSNE override to RSNE",
|
|
||||||
sm->ap_rsn_ie, sm->ap_rsn_ie_len);
|
|
||||||
} else {
|
|
||||||
sm->ap_rsn_ie = os_memdup(ie, len);
|
|
||||||
if (sm->ap_rsn_ie == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
sm->ap_rsn_ie_len = len;
|
sm->ap_rsn_ie_len = len;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -5191,24 +5271,86 @@ int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
sm->ap_rsnxe_len = 0;
|
sm->ap_rsnxe_len = 0;
|
||||||
} else {
|
} else {
|
||||||
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
|
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
|
||||||
if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
|
sm->ap_rsnxe = os_memdup(ie, len);
|
||||||
sm->ap_rsnxe = os_malloc(len - 4);
|
if (!sm->ap_rsnxe)
|
||||||
if (!sm->ap_rsnxe)
|
return -1;
|
||||||
return -1;
|
|
||||||
sm->ap_rsnxe[0] = WLAN_EID_RSNX;
|
|
||||||
sm->ap_rsnxe[1] = len - 2 - 4;
|
|
||||||
os_memcpy(&sm->ap_rsnxe[2], ie + 2 + 4, len - 2 - 4);
|
|
||||||
sm->ap_rsnxe_len = len - 4;
|
|
||||||
wpa_hexdump(MSG_DEBUG,
|
|
||||||
"RSN: Converted RSNXE override to RSNXE",
|
|
||||||
sm->ap_rsnxe, sm->ap_rsnxe_len);
|
|
||||||
} else {
|
|
||||||
sm->ap_rsnxe = os_memdup(ie, len);
|
|
||||||
if (!sm->ap_rsnxe)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
sm->ap_rsnxe_len = len;
|
sm->ap_rsnxe_len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
|
{
|
||||||
|
if (!sm)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_free(sm->ap_rsne_override);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
"RSN: Clearing AP RSNE Override element");
|
||||||
|
sm->ap_rsne_override = NULL;
|
||||||
|
sm->ap_rsne_override_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNE Override element",
|
||||||
|
ie, len);
|
||||||
|
sm->ap_rsne_override = os_memdup(ie, len);
|
||||||
|
if (!sm->ap_rsne_override)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sm->ap_rsne_override_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_sm_set_ap_rsne_override_2(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
|
{
|
||||||
|
if (!sm)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_free(sm->ap_rsne_override_2);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
"RSN: Clearing AP RSNE Override 2 element");
|
||||||
|
sm->ap_rsne_override_2 = NULL;
|
||||||
|
sm->ap_rsne_override_2_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNE Override 2 element",
|
||||||
|
ie, len);
|
||||||
|
sm->ap_rsne_override_2 = os_memdup(ie, len);
|
||||||
|
if (!sm->ap_rsne_override_2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sm->ap_rsne_override_2_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
|
{
|
||||||
|
if (!sm)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_free(sm->ap_rsnxe_override);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
"RSN: Clearing AP RSNXE Override element");
|
||||||
|
sm->ap_rsnxe_override = NULL;
|
||||||
|
sm->ap_rsnxe_override_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNXE Override element",
|
||||||
|
ie, len);
|
||||||
|
sm->ap_rsnxe_override = os_memdup(ie, len);
|
||||||
|
if (!sm->ap_rsnxe_override)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sm->ap_rsnxe_override_len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -212,6 +212,9 @@ int wpa_sm_set_assoc_rsnxe(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_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_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
|
int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
|
int wpa_sm_set_ap_rsne_override_2(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
|
int wpa_sm_set_ap_rsnxe_override(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,
|
||||||
|
@ -356,6 +359,24 @@ static inline int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_sm_set_ap_rsne_override_2(struct wpa_sm *sm, const u8 *ie,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_sm_set_ap_rsnxe_override(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;
|
||||||
|
|
|
@ -120,6 +120,9 @@ struct wpa_sm {
|
||||||
size_t assoc_rsnxe_len;
|
size_t assoc_rsnxe_len;
|
||||||
u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
|
u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
|
||||||
size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
|
size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
|
||||||
|
u8 *ap_rsne_override, *ap_rsne_override_2, *ap_rsnxe_override;
|
||||||
|
size_t ap_rsne_override_len, ap_rsne_override_2_len,
|
||||||
|
ap_rsnxe_override_len;
|
||||||
|
|
||||||
#ifdef CONFIG_TDLS
|
#ifdef CONFIG_TDLS
|
||||||
struct wpa_tdls_peer *tdls;
|
struct wpa_tdls_peer *tdls;
|
||||||
|
|
|
@ -416,6 +416,9 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
|
||||||
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_ap_rsnxe(wpa_s->wpa, NULL, 0);
|
||||||
|
wpa_sm_set_ap_rsne_override(wpa_s->wpa, NULL, 0);
|
||||||
|
wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, NULL, 0);
|
||||||
|
wpa_sm_set_ap_rsnxe_override(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_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
|
wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
|
||||||
wpa_s->rsnxe_len = 0;
|
wpa_s->rsnxe_len = 0;
|
||||||
|
@ -1833,12 +1836,31 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
||||||
!!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
|
!!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
|
||||||
|
|
||||||
if (bss || !wpa_s->ap_ies_from_associnfo) {
|
if (bss || !wpa_s->ap_ies_from_associnfo) {
|
||||||
|
const u8 *rsnoe = NULL, *rsno2e = NULL, *rsnxoe = NULL;
|
||||||
|
|
||||||
|
if (bss) {
|
||||||
|
bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
|
||||||
|
bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
|
||||||
|
rsnoe = wpa_bss_get_vendor_ie(
|
||||||
|
bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
rsno2e = wpa_bss_get_vendor_ie(
|
||||||
|
bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
rsnxoe = wpa_bss_get_vendor_ie(
|
||||||
|
bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
|
||||||
bss_rsnx ? 2 + bss_rsnx[1] : 0))
|
bss_rsnx ? 2 + bss_rsnx[1] : 0) ||
|
||||||
|
wpa_sm_set_ap_rsne_override(wpa_s->wpa, rsnoe,
|
||||||
|
rsnoe ? 2 + rsnoe[1] : 0) ||
|
||||||
|
wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, rsno2e,
|
||||||
|
rsno2e ? 2 + rsno2e[1] : 0) ||
|
||||||
|
wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, rsnxoe,
|
||||||
|
rsnxoe ? 2 + rsnxoe[1] : 0))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -425,13 +425,29 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
|
||||||
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
|
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
ie = wpa_bss_get_rsne(wpa_s, curr, ssid, false);
|
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_rsnxe(wpa_s, curr, ssid, false);
|
ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX);
|
||||||
if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
|
if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
|
ie = wpa_bss_get_vendor_ie(curr, RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (wpa_sm_set_ap_rsne_override(wpa_s->wpa, ie,
|
||||||
|
ie ? 2 + ie[1] : 0))
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
ie = wpa_bss_get_vendor_ie(curr,
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
if (wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, ie,
|
||||||
|
ie ? 2 + ie[1] : 0))
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
ie = wpa_bss_get_vendor_ie(curr, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, ie,
|
||||||
|
ie ? 2 + ie[1] : 0))
|
||||||
|
ret = -1;
|
||||||
} else {
|
} else {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue