RSNE/RSNXE overriding for STA

Add support for RSNE/RSNXE Override elements. Use these elements to
determine AP's extended RSN parameters.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2023-10-11 12:50:05 +03:00 committed by Jouni Malinen
parent d0b55eb360
commit 765c48d5ad
11 changed files with 486 additions and 25 deletions

View file

@ -4550,12 +4550,27 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
} else { } else {
wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNE", wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNE",
ie, len); ie, len);
sm->mlo.links[i].ap_rsne = os_memdup(ie, len); if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
if (!sm->mlo.links[i].ap_rsne) { sm->mlo.links[i].ap_rsne = os_malloc(len - 4);
sm->mlo.links[i].ap_rsne_len = 0; if (!sm->mlo.links[i].ap_rsne)
return -1; return -1;
sm->mlo.links[i].ap_rsne[0] = WLAN_EID_RSN;
sm->mlo.links[i].ap_rsne[1] = len - 2 - 4;
os_memcpy(&sm->mlo.links[i].ap_rsne[2],
ie + 2 + 4, len - 2 - 4);
sm->mlo.links[i].ap_rsne_len = len - 4;
wpa_hexdump(MSG_DEBUG,
"RSN: Converted RSNE override to RSNE",
sm->mlo.links[i].ap_rsne,
sm->mlo.links[i].ap_rsne_len);
} else {
sm->mlo.links[i].ap_rsne = os_memdup(ie, len);
if (!sm->mlo.links[i].ap_rsne) {
sm->mlo.links[i].ap_rsne_len = 0;
return -1;
}
sm->mlo.links[i].ap_rsne_len = len;
} }
sm->mlo.links[i].ap_rsne_len = len;
} }
ie = mlo->links[i].ap_rsnxe; ie = mlo->links[i].ap_rsnxe;
@ -4571,12 +4586,27 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
} else { } else {
wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNXE", ie, wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNXE", ie,
len); len);
sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len); if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
if (!sm->mlo.links[i].ap_rsnxe) { sm->mlo.links[i].ap_rsnxe = os_malloc(len - 4);
sm->mlo.links[i].ap_rsnxe_len = 0; if (!sm->mlo.links[i].ap_rsnxe)
return -1; return -1;
sm->mlo.links[i].ap_rsnxe[0] = WLAN_EID_RSNX;
sm->mlo.links[i].ap_rsnxe[1] = len - 2 - 4;
os_memcpy(&sm->mlo.links[i].ap_rsnxe[2],
ie + 2 + 4, len - 2 - 4);
sm->mlo.links[i].ap_rsnxe_len = len - 4;
wpa_hexdump(MSG_DEBUG,
"RSN: Converted RSNXE override to RSNXE",
sm->mlo.links[i].ap_rsnxe,
sm->mlo.links[i].ap_rsnxe_len);
} else {
sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len);
if (!sm->mlo.links[i].ap_rsnxe) {
sm->mlo.links[i].ap_rsnxe_len = 0;
return -1;
}
sm->mlo.links[i].ap_rsnxe_len = len;
} }
sm->mlo.links[i].ap_rsnxe_len = len;
} }
} }
@ -5077,11 +5107,24 @@ 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);
sm->ap_rsn_ie = os_memdup(ie, len); if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
if (sm->ap_rsn_ie == NULL) sm->ap_rsn_ie = os_malloc(len - 4);
return -1; 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_len = len; sm->ap_rsn_ie_len = len;
}
} }
return 0; return 0;
@ -5110,11 +5153,24 @@ 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);
sm->ap_rsnxe = os_memdup(ie, len); if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
if (!sm->ap_rsnxe) sm->ap_rsnxe = os_malloc(len - 4);
return -1; 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_len = len; sm->ap_rsnxe_len = len;
}
} }
return 0; return 0;

View file

@ -33,8 +33,15 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC && if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE) wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE)
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data); return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
else if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); wpa_ie[1] >= 4 &&
WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE)
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
wpa_ie[1] >= 4 &&
WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_2_IE_VENDOR_TYPE)
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
} }

View file

@ -1657,10 +1657,22 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
if (ssid) { if (ssid) {
struct wpa_ie_data ie; struct wpa_ie_data ie;
const u8 *rsne;
size_t rsne_len;
if (!elems.rsn_ie || if (elems.rsne_override_2 && wpas_rsn_overriding(wpa_s)) {
wpa_parse_wpa_ie(elems.rsn_ie - 2, 2 + elems.rsn_ie_len, rsne = elems.rsne_override_2;
&ie)) { rsne_len = elems.rsne_override_2_len;
} else if (elems.rsne_override &&
wpas_rsn_overriding(wpa_s)) {
rsne = elems.rsne_override;
rsne_len = elems.rsne_override_len;
} else {
rsne = elems.rsn_ie;
rsne_len = elems.rsn_ie_len;
}
if (!rsne ||
wpa_parse_wpa_ie(rsne - 2, 2 + rsne_len, &ie)) {
wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element"); wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
goto out; goto out;
} }
@ -1868,10 +1880,163 @@ out:
} }
static bool wpa_bss_supported_cipher(struct wpa_supplicant *wpa_s,
int pairwise_cipher)
{
if (!wpa_s->drv_enc)
return true;
if ((pairwise_cipher & WPA_CIPHER_CCMP) &&
(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP))
return true;
if ((pairwise_cipher & WPA_CIPHER_GCMP) &&
(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP))
return true;
if ((pairwise_cipher & WPA_CIPHER_CCMP_256) &&
(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP_256))
return true;
if ((pairwise_cipher & WPA_CIPHER_GCMP_256) &&
(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP_256))
return true;
return false;
}
static bool wpa_bss_supported_key_mgmt(struct wpa_supplicant *wpa_s,
int key_mgmt)
{
if (!wpa_s->drv_key_mgmt)
return true;
if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2))
return true;
if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256))
return true;
if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT))
return true;
if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384))
return true;
if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B))
return true;
if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192))
return true;
if ((key_mgmt & WPA_KEY_MGMT_PSK) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK))
return true;
if ((key_mgmt & WPA_KEY_MGMT_FT_PSK) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK))
return true;
if ((key_mgmt & WPA_KEY_MGMT_PSK_SHA256) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256))
return true;
if ((key_mgmt & WPA_KEY_MGMT_SAE) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE))
return true;
if ((key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY))
return true;
if ((key_mgmt & WPA_KEY_MGMT_FT_SAE) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE))
return true;
if ((key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY))
return true;
if ((key_mgmt & WPA_KEY_MGMT_OWE) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE))
return true;
if ((key_mgmt & WPA_KEY_MGMT_DPP) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP))
return true;
if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA256) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256))
return true;
if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA384) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384))
return true;
if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256))
return true;
if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) &&
(wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384))
return true;
return false;
}
static bool wpa_bss_supported_rsne(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, const u8 *ie)
{
struct wpa_ie_data data;
if (wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) < 0)
return false;
/* Check that there is a supported AKM and pairwise cipher based on
* overall capabilities */
if (!data.pairwise_cipher || !data.key_mgmt)
return false;
if (wpa_s->drv_capa_known) {
if (!wpa_bss_supported_cipher(wpa_s, data.pairwise_cipher) ||
!wpa_bss_supported_key_mgmt(wpa_s, data.key_mgmt))
return false;
}
if (ssid) {
/* Check that there is a supported AKM and pairwise cipher
* based on the specific network profile. */
if ((ssid->pairwise_cipher & data.pairwise_cipher) == 0)
return false;
if ((ssid->key_mgmt & data.key_mgmt) == 0)
return false;
}
return true;
}
const u8 * wpa_bss_get_rsne(struct wpa_supplicant *wpa_s, const u8 * wpa_bss_get_rsne(struct wpa_supplicant *wpa_s,
const struct wpa_bss *bss, struct wpa_ssid *ssid, const struct wpa_bss *bss, struct wpa_ssid *ssid,
bool mlo) bool mlo)
{ {
const u8 *ie;
if (wpas_rsn_overriding(wpa_s)) {
if (!ssid)
ssid = wpa_s->current_ssid;
/* MLO cases for RSN overriding are required to use RSNE
* Override 2 element and RSNXE Override element together. */
ie = wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
if (mlo && ie &&
!wpa_bss_get_vendor_ie(bss,
RSNXE_OVERRIDE_IE_VENDOR_TYPE)) {
wpa_printf(MSG_DEBUG, "BSS " MACSTR
" advertises RSNE Override 2 element without RSNXE Override element - ignore RSNE Override 2 element for MLO",
MAC2STR(bss->bssid));
} else if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie)) {
return ie;
}
if (!mlo) {
ie = wpa_bss_get_vendor_ie(
bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie))
return ie;
}
}
return wpa_bss_get_ie(bss, WLAN_EID_RSN); return wpa_bss_get_ie(bss, WLAN_EID_RSN);
} }
@ -1880,5 +2045,33 @@ const u8 * wpa_bss_get_rsnxe(struct wpa_supplicant *wpa_s,
const struct wpa_bss *bss, struct wpa_ssid *ssid, const struct wpa_bss *bss, struct wpa_ssid *ssid,
bool mlo) bool mlo)
{ {
const u8 *ie;
if (wpas_rsn_overriding(wpa_s)) {
ie = wpa_bss_get_vendor_ie(bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
if (ie) {
const u8 *tmp;
tmp = wpa_bss_get_rsne(wpa_s, bss, ssid, mlo);
if (!tmp || tmp[0] == WLAN_EID_RSN) {
/* An acceptable RSNE override element was not
* found, so need to ignore RSNXE overriding. */
return NULL;
}
return ie;
}
/* MLO cases for RSN overriding are required to use RSNE
* Override 2 element and RSNXE Override element together. */
if (mlo && wpa_bss_get_vendor_ie(
bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE)) {
wpa_printf(MSG_DEBUG, "BSS " MACSTR
" advertises RSNXE Override element without RSNE Override 2 element - ignore RSNXE Override element for MLO",
MAC2STR(bss->bssid));
return NULL;
}
}
return wpa_bss_get_ie(bss, WLAN_EID_RSNX); return wpa_bss_get_ie(bss, WLAN_EID_RSNX);
} }

View file

@ -5579,6 +5579,7 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(extended_key_id, 0, 1), 0 }, { INT_RANGE(extended_key_id, 0, 1), 0 },
#endif /* CONFIG_WNM */ #endif /* CONFIG_WNM */
{ INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0}, { INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0},
{ INT_RANGE(rsn_overriding, 0, 2), 0},
#ifdef CONFIG_PASN #ifdef CONFIG_PASN
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
{ INT_RANGE(force_kdk_derivation, 0, 1), 0 }, { INT_RANGE(force_kdk_derivation, 0, 1), 0 },

View file

@ -1774,6 +1774,19 @@ struct wpa_config {
*/ */
int wowlan_disconnect_on_deinit; int wowlan_disconnect_on_deinit;
/**
* rsn_overriding - RSN overriding
*
* 0 = Disabled
* 1 = Enabled automatically if the driver indicates support
* 2 = Forced to be enabled even without driver capability indication
*/
enum rsn_overriding {
RSN_OVERRIDING_DISABLED = 0,
RSN_OVERRIDING_AUTO = 1,
RSN_OVERRIDING_ENABLED = 2,
} rsn_overriding;
#ifdef CONFIG_PASN #ifdef CONFIG_PASN
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
/* /*

View file

@ -1615,6 +1615,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->wowlan_disconnect_on_deinit) if (config->wowlan_disconnect_on_deinit)
fprintf(f, "wowlan_disconnect_on_deinit=%d\n", fprintf(f, "wowlan_disconnect_on_deinit=%d\n",
config->wowlan_disconnect_on_deinit); config->wowlan_disconnect_on_deinit);
if (config->rsn_overriding)
fprintf(f, "rsn_overriding=%d\n", config->rsn_overriding);
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
if (config->mld_force_single_link) if (config->mld_force_single_link)
fprintf(f, "mld_force_single_link=1\n"); fprintf(f, "mld_force_single_link=1\n");

View file

@ -1296,7 +1296,9 @@ static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
ie = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false); ie = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
if (ie && ie[1] >= 1) if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4 + 1)
rsnxe_capa = ie[4 + 2];
else if (ie && ie[1] >= 1)
rsnxe_capa = ie[2]; rsnxe_capa = ie[2];
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
@ -3665,9 +3667,29 @@ 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 (wpas_rsn_overriding(wpa_s) &&
p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
rsn_found = 1;
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
}
if (!rsn_found &&
wpas_rsn_overriding(wpa_s) &&
p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
rsn_found = 1;
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
}
if (p[0] == WLAN_EID_RSNX && p[1] >= 1) if (p[0] == WLAN_EID_RSNX && p[1] >= 1)
wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len); wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
if (wpas_rsn_overriding(wpa_s) &&
p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
WPA_GET_BE32(&p[2]) == RSNXE_OVERRIDE_IE_VENDOR_TYPE)
wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
l -= len; l -= len;
p += len; p += len;
} }

View file

@ -191,7 +191,10 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
const u8 *rsnxe; const u8 *rsnxe;
rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false); rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
if (rsnxe && rsnxe[1] >= 1) if (rsnxe && rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC &&
rsnxe[1] >= 1 + 4)
rsnxe_capa = rsnxe[2 + 4];
else if (rsnxe && rsnxe[1] >= 1)
rsnxe_capa = rsnxe[2]; rsnxe_capa = rsnxe[2];
} }
@ -2464,6 +2467,28 @@ mscs_fail:
wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len; wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
} }
if (wpas_rsn_overriding(wpa_s) &&
wpas_ap_supports_rsn_overriding(wpa_s, wpa_s->current_bss) &&
wpa_s->sme.assoc_req_ie_len + 2 + 4 <=
sizeof(wpa_s->sme.assoc_req_ie)) {
u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
u32 type = 0;
const u8 *ie;
ie = wpa_bss_get_rsne(wpa_s, wpa_s->current_bss, ssid,
wpa_s->valid_links);
if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
type = WPA_GET_BE32(&ie[2]);
if (type) {
/* Indicate support for RSN overriding */
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4;
WPA_PUT_BE32(pos, type);
wpa_s->sme.assoc_req_ie_len += 2 + 4;
}
}
params.bssid = bssid; params.bssid = bssid;
params.ssid = wpa_s->sme.ssid; params.ssid = wpa_s->sme.ssid;
params.ssid_len = wpa_s->sme.ssid_len; params.ssid_len = wpa_s->sme.ssid_len;

View file

@ -3943,6 +3943,57 @@ mscs_end:
wpa_ie_len += multi_ap_ie_len; wpa_ie_len += multi_ap_ie_len;
} }
if (!wpas_driver_bss_selection(wpa_s) &&
wpas_rsn_overriding(wpa_s) &&
wpas_ap_supports_rsn_overriding(wpa_s, bss) &&
wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
u8 *pos = wpa_ie + wpa_ie_len;
u32 type = 0;
const u8 *ie;
ie = wpa_bss_get_rsne(wpa_s, bss, ssid, wpa_s->valid_links);
if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
type = WPA_GET_BE32(&ie[2]);
if (type) {
/* Indicate support for RSN overriding */
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4;
WPA_PUT_BE32(pos, type);
pos += 4;
wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
pos - wpa_ie);
wpa_ie_len += 2 + 4;
}
}
if (wpas_driver_bss_selection(wpa_s) &&
wpas_rsn_overriding(wpa_s)) {
if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
u8 *pos = wpa_ie + wpa_ie_len;
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4;
WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
pos += 4;
wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
pos - wpa_ie);
wpa_ie_len += 2 + 4;
}
if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
u8 *pos = wpa_ie + wpa_ie_len;
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4;
WPA_PUT_BE32(pos, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
pos += 4;
wpa_hexdump(MSG_MSGDUMP, "RSNE Override 2",
wpa_ie, pos - wpa_ie);
wpa_ie_len += 2 + 4;
}
}
params->wpa_ie = wpa_ie; params->wpa_ie = wpa_ie;
params->wpa_ie_len = wpa_ie_len; params->wpa_ie_len = wpa_ie_len;
params->auth_alg = algs; params->auth_alg = algs;
@ -8557,6 +8608,28 @@ int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
} }
static bool wpas_driver_rsn_override(struct wpa_supplicant *wpa_s)
{
return !!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA);
}
bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s)
{
if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_DISABLED)
return false;
if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_ENABLED)
return true;
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
wpas_driver_bss_selection(wpa_s))
return wpas_driver_rsn_override(wpa_s);
return true;
}
#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) #if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s, int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, struct wpa_ssid *ssid,
@ -9531,3 +9604,58 @@ bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
return false; return false;
} }
bool wpas_ap_supports_rsn_overriding(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss)
{
int i;
if (!bss)
return false;
if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
return true;
if (!wpa_s->valid_links)
return false;
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
if (!(wpa_s->valid_links & BIT(i)))
continue;
if (wpa_s->links[i].bss &&
(wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
RSNE_OVERRIDE_2_IE_VENDOR_TYPE)))
return true;
}
return false;
}
bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss)
{
int i;
if (!bss)
return false;
if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
return true;
if (!wpa_s->valid_links)
return false;
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
if (!(wpa_s->valid_links & BIT(i)))
continue;
if (wpa_s->links[i].bss &&
wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
return true;
}
return false;
}

View file

@ -878,6 +878,15 @@ fast_reauth=1
# 1 = auto: Activate Extended Key ID support if the driver supports it # 1 = auto: Activate Extended Key ID support if the driver supports it
#extended_key_id=0 #extended_key_id=0
# RSN overriding
# NOTE: The protocol used for this mechanism is still subject to change and as
# such, this should not yet be enabled for production uses to avoid issues if
# something were to change.
# 0 = Disabled (default)
# 1 = Enabled automatically if the driver indicates support
# 2 = Forced to be enabled even without driver capability indication
#rsn_overriding=0
# network block # network block
# #
# Each network (usually AP's sharing the same SSID) is configured as a separate # Each network (usually AP's sharing the same SSID) is configured as a separate

View file

@ -1727,6 +1727,7 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
void fils_connection_failure(struct wpa_supplicant *wpa_s); void fils_connection_failure(struct wpa_supplicant *wpa_s);
void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s); void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s); int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);
bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s);
int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s); int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s);
void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason, void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
const u8 *bssid); const u8 *bssid);
@ -2011,5 +2012,9 @@ bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled);
bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss); bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss);
bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr); bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr);
bool wpas_ap_supports_rsn_overriding(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss);
bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss);
#endif /* WPA_SUPPLICANT_I_H */ #endif /* WPA_SUPPLICANT_I_H */