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:
parent
d0b55eb360
commit
765c48d5ad
11 changed files with 486 additions and 25 deletions
|
@ -4550,6 +4550,20 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
|
|||
} else {
|
||||
wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNE",
|
||||
ie, len);
|
||||
if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
|
||||
sm->mlo.links[i].ap_rsne = os_malloc(len - 4);
|
||||
if (!sm->mlo.links[i].ap_rsne)
|
||||
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;
|
||||
|
@ -4557,6 +4571,7 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
|
|||
}
|
||||
sm->mlo.links[i].ap_rsne_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
ie = mlo->links[i].ap_rsnxe;
|
||||
len = mlo->links[i].ap_rsnxe_len;
|
||||
|
@ -4571,6 +4586,20 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
|
|||
} else {
|
||||
wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNXE", ie,
|
||||
len);
|
||||
if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
|
||||
sm->mlo.links[i].ap_rsnxe = os_malloc(len - 4);
|
||||
if (!sm->mlo.links[i].ap_rsnxe)
|
||||
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;
|
||||
|
@ -4579,6 +4608,7 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
|
|||
sm->mlo.links[i].ap_rsnxe_len = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5077,12 +5107,25 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
|
|||
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_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5110,12 +5153,25 @@ int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
|
|||
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_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,14 @@ 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 &&
|
||||
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);
|
||||
else
|
||||
if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1657,10 +1657,22 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
|
|||
|
||||
if (ssid) {
|
||||
struct wpa_ie_data ie;
|
||||
const u8 *rsne;
|
||||
size_t rsne_len;
|
||||
|
||||
if (!elems.rsn_ie ||
|
||||
wpa_parse_wpa_ie(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
|
||||
&ie)) {
|
||||
if (elems.rsne_override_2 && wpas_rsn_overriding(wpa_s)) {
|
||||
rsne = elems.rsne_override_2;
|
||||
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");
|
||||
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 struct wpa_bss *bss, struct wpa_ssid *ssid,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1880,5 +2045,33 @@ const u8 * wpa_bss_get_rsnxe(struct wpa_supplicant *wpa_s,
|
|||
const struct wpa_bss *bss, struct wpa_ssid *ssid,
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -5579,6 +5579,7 @@ static const struct global_parse_data global_fields[] = {
|
|||
{ INT_RANGE(extended_key_id, 0, 1), 0 },
|
||||
#endif /* CONFIG_WNM */
|
||||
{ INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0},
|
||||
{ INT_RANGE(rsn_overriding, 0, 2), 0},
|
||||
#ifdef CONFIG_PASN
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
{ INT_RANGE(force_kdk_derivation, 0, 1), 0 },
|
||||
|
|
|
@ -1774,6 +1774,19 @@ struct wpa_config {
|
|||
*/
|
||||
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_TESTING_OPTIONS
|
||||
/*
|
||||
|
|
|
@ -1615,6 +1615,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
|
|||
if (config->wowlan_disconnect_on_deinit)
|
||||
fprintf(f, "wowlan_disconnect_on_deinit=%d\n",
|
||||
config->wowlan_disconnect_on_deinit);
|
||||
if (config->rsn_overriding)
|
||||
fprintf(f, "rsn_overriding=%d\n", config->rsn_overriding);
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (config->mld_force_single_link)
|
||||
fprintf(f, "mld_force_single_link=1\n");
|
||||
|
|
|
@ -1296,7 +1296,9 @@ static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
|||
|
||||
#ifdef CONFIG_SAE
|
||||
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];
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
|
@ -3665,9 +3667,29 @@ no_pfs:
|
|||
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)
|
||||
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;
|
||||
p += len;
|
||||
}
|
||||
|
|
|
@ -191,7 +191,10 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
|
|||
const u8 *rsnxe;
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
|
@ -2464,6 +2467,28 @@ mscs_fail:
|
|||
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.ssid = wpa_s->sme.ssid;
|
||||
params.ssid_len = wpa_s->sme.ssid_len;
|
||||
|
|
|
@ -3943,6 +3943,57 @@ mscs_end:
|
|||
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_len = wpa_ie_len;
|
||||
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)
|
||||
int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
|
@ -9531,3 +9604,58 @@ bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -878,6 +878,15 @@ fast_reauth=1
|
|||
# 1 = auto: Activate Extended Key ID support if the driver supports it
|
||||
#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
|
||||
#
|
||||
# Each network (usually AP's sharing the same SSID) is configured as a separate
|
||||
|
|
|
@ -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_pmksa_cache_flush(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);
|
||||
void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
|
||||
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 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 */
|
||||
|
|
Loading…
Reference in a new issue