wpa_ie = wpa_ie + wpa_ie[1] + 2;
wpa_ie_len = wpa_ie[1] + 2;
}
- if ((sm->rsn_override &&
- get_vendor_ie(wpa_ie, wpa_ie_len, RSNE_OVERRIDE_IE_VENDOR_TYPE)) ||
- (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) {
+ if ((conf->rsn_override_key_mgmt || conf->rsn_override_key_mgmt_2) &&
+ !rsn_is_snonce_cookie(sm->SNonce)) {
u8 *ie;
size_t ie_len;
u32 ids[] = {
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
if (wpa_key_mgmt_ft(sm->key_mgmt) &&
wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
os_free(sm->ap_wpa_ie);
os_free(sm->ap_rsn_ie);
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++) {
os_free(sm->mlo.links[i].ap_rsne);
os_free(sm->mlo.links[i].ap_rsnxe);
}
+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
* @sm: Pointer to WPA state machine data from wpa_sm_init()
{
char *pos = buf, *end = buf + buflen;
int ret;
+ const u8 *rsne;
+ size_t rsne_len;
+
+ rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
ret = os_snprintf(pos, end - pos,
"pairwise_cipher=%s\n"
}
#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;
- 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)) {
ret = os_snprintf(pos, end - pos, "pmf=%d\n"
int wpa_sm_pmf_enabled(struct wpa_sm *sm)
{
struct wpa_ie_data rsn;
+ const u8 *rsne;
+ size_t rsne_len;
+
+ rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
- if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
+ if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !rsne)
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))
return 1;
int wpa_sm_ocv_enabled(struct wpa_sm *sm)
{
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 wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len,
- &rsn) >= 0 &&
+ return wpa_parse_wpa_ie_rsn(rsne, rsne_len, &rsn) >= 0 &&
(rsn.capabilities & WPA_CAPABILITY_OCVC);
}
sm->ap_rsn_ie_len = 0;
} else {
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_malloc(len - 4);
- if (!sm->ap_rsn_ie)
- 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 = 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;
sm->ap_rsnxe_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
- if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
- sm->ap_rsnxe = os_malloc(len - 4);
- if (!sm->ap_rsnxe)
- 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 = 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;
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_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_rsnxe(wpa_s->wpa, NULL, 0);
wpa_s->rsnxe_len = 0;
!!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
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,
bss_wpa ? 2 + bss_wpa[1] : 0) ||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
bss_rsn ? 2 + bss_rsn[1] : 0) ||
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;
}