@@ -1316,6 +1316,9 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
const unsigned char *src_addr,
struct wpa_eapol_ie_parse *ie)
{
+ const u8 *rsn_ie;
+ size_t rsn_ie_len;
+
if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"WPA: No WPA/RSN IE for this AP known. "
@@ -1329,39 +1332,54 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
"WPA: Found the current AP from "
"updated scan results");
}
+ } else {
+ wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: Using known WPA/RSN IE for this AP.");
+ }
+
+ if (ie->rsn_ie && ie->osen) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
+ "WPA: Error - RSN and OSEN IE used together");
+ return -1;
+ } else if (ie->osen) {
+ rsn_ie = ie->osen;
+ rsn_ie_len = ie->osen_len;
+ } else {
+ rsn_ie = ie->rsn_ie;
+ rsn_ie_len = ie->rsn_ie_len;
}
- if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&
+ if (ie->wpa_ie == NULL && rsn_ie == NULL &&
(sm->ap_wpa_ie || sm->ap_rsn_ie)) {
wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
"with IE in Beacon/ProbeResp (no IE?)",
src_addr, ie->wpa_ie, ie->wpa_ie_len,
- ie->rsn_ie, ie->rsn_ie_len);
+ rsn_ie, rsn_ie_len);
return -1;
}
if ((ie->wpa_ie && sm->ap_wpa_ie &&
(ie->wpa_ie_len != sm->ap_wpa_ie_len ||
os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
- (ie->rsn_ie && sm->ap_rsn_ie &&
+ (rsn_ie && sm->ap_rsn_ie &&
wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
sm->ap_rsn_ie, sm->ap_rsn_ie_len,
- ie->rsn_ie, ie->rsn_ie_len))) {
+ rsn_ie, rsn_ie_len))) {
wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
"with IE in Beacon/ProbeResp",
src_addr, ie->wpa_ie, ie->wpa_ie_len,
- ie->rsn_ie, ie->rsn_ie_len);
+ rsn_ie, rsn_ie_len);
return -1;
}
if (sm->proto == WPA_PROTO_WPA &&
- ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) {
+ rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) {
wpa_report_ie_mismatch(sm, "Possible downgrade attack "
"detected - RSN was enabled and RSN IE "
"was in msg 3/4, but not in "
"Beacon/ProbeResp",
src_addr, ie->wpa_ie, ie->wpa_ie_len,
- ie->rsn_ie, ie->rsn_ie_len);
+ rsn_ie, rsn_ie_len);
return -1;
}
@@ -538,7 +538,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
{
struct wpa_ie_data ie;
int proto_match = 0;
- const u8 *rsn_ie, *wpa_ie;
+ const u8 *rsn_ie, *wpa_ie, *osen;
int ret;
int wep_ok;
@@ -553,9 +553,21 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA));
rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
- while ((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) && rsn_ie) {
+ osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
+
+ while ((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) &&
+ (rsn_ie || osen)) {
proto_match++;
+ if (osen && (ssid->proto & WPA_PROTO_RSN || rsn_ie)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - invalid RSN/OSEN mix");
+ break;
+ } else if (osen) {
+ rsn_ie = osen;
+ }
+
if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
@@ -576,14 +588,6 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
return 1;
}
- if (!(ie.proto & ssid->proto) &&
- !(ssid->proto & WPA_PROTO_OSEN)) {
- if (debug_print)
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip RSN IE - proto mismatch");
- break;
- }
-
if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
@@ -729,21 +733,14 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_OWE */
- if ((ssid->proto & (WPA_PROTO_WPA | WPA_PROTO_RSN)) &&
+ if ((ssid->proto & (WPA_PROTO_WPA | WPA_PROTO_RSN | WPA_PROTO_OSEN)) &&
wpa_key_mgmt_wpa(ssid->key_mgmt) && proto_match == 0) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - no WPA/RSN proto match");
+ " skip - no WPA/RSN/OSEN proto match");
return 0;
}
- if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) &&
- wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE)) {
- if (debug_print)
- wpa_dbg(wpa_s, MSG_DEBUG, " allow in OSEN");
- return 1;
- }
-
if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2");
@@ -2418,7 +2415,7 @@ static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
- int l, len, found = 0, found_x = 0, wpa_found, rsn_found;
+ int l, len, found = 0, found_x = 0, wpa_found, rsn_found, osen_found;
const u8 *p;
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_OWE)
u8 bssid[ETH_ALEN];
@@ -2491,10 +2488,9 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
break;
}
if (!found &&
- ((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
- (os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
- (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 4 &&
- (os_memcmp(&p[2], "\x50\x6F\x9A\x12", 4) == 0)) ||
+ ((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 4 &&
+ (WPA_GET_BE32(&p[2]) == WPA_IE_VENDOR_TYPE ||
+ WPA_GET_BE32(&p[2]) == OSEN_IE_VENDOR_TYPE)) ||
(p[0] == WLAN_EID_RSN && p[1] >= 2))) {
if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len))
break;
@@ -2653,7 +2649,7 @@ no_pfs:
/* Go through the IEs and make a copy of the WPA/RSN IEs, if present.
*/
- wpa_found = rsn_found = 0;
+ wpa_found = rsn_found = osen_found = 0;
while (p && l >= 2) {
len = p[1] + 2;
if (len > l) {
@@ -2661,11 +2657,16 @@ no_pfs:
p, l);
break;
}
- if (!wpa_found &&
- p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
- os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) {
- wpa_found = 1;
- wpa_sm_set_ap_wpa_ie(wpa_s->wpa, p, len);
+ if (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 4) {
+ if (!wpa_found &&
+ WPA_GET_BE32(&p[2]) == WPA_IE_VENDOR_TYPE) {
+ wpa_found = 1;
+ wpa_sm_set_ap_wpa_ie(wpa_s->wpa, p, len);
+ } else if (!osen_found &&
+ WPA_GET_BE32(&p[2]) == OSEN_IE_VENDOR_TYPE) {
+ osen_found = 1;
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
+ }
}
if (!rsn_found &&
@@ -2673,6 +2674,11 @@ no_pfs:
rsn_found = 1;
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
}
+ if (!osen_found &&
+ p[0] == WLAN_EID_RSN && p[1] >= 2) {
+ osen_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);
@@ -2681,13 +2687,21 @@ no_pfs:
p += len;
}
- if (!wpa_found && data->assoc_info.beacon_ies)
- wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
- if (!rsn_found && data->assoc_info.beacon_ies) {
- wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
- wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
+ if (rsn_found && osen_found) {
+ wpa_msg(wpa_s, MSG_ERROR,
+ "Invalid combination: RSN and OSEN IE found");
+ return -1;
+ }
+
+ if (data->assoc_info.beacon_ies) {
+ if (!wpa_found)
+ wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
+ if (!rsn_found && !osen_found)
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
+ if (!rsn_found)
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
}
- if (wpa_found || rsn_found)
+ if (wpa_found || rsn_found || osen_found)
wpa_s->ap_ies_from_associnfo = 1;
if (wpa_s->assoc_freq && data->assoc_info.freq &&
@@ -377,7 +377,7 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
int ret = 0;
struct wpa_bss *curr = NULL, *bss;
struct wpa_ssid *ssid = wpa_s->current_ssid;
- const u8 *ie;
+ const u8 *ie, *osen;
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0)
@@ -396,7 +396,18 @@ 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))
ret = -1;
+ osen = wpa_bss_get_vendor_ie(curr, OSEN_IE_VENDOR_TYPE);
ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
+
+ /* RSN and OSEN Elements are mutually exclusive but
+ * have the same content and similar use cases.
+ * Therefore just store the OSEN Element in ap_rsn_ie
+ */
+ if (osen && ie)
+ ret = -1;
+ else if (osen)
+ ie = osen;
+
if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
ret = -1;
Use the existing RSNE parsing and checks also for OSEN. Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de> --- src/rsn_supp/wpa.c | 32 ++++++++++---- wpa_supplicant/events.c | 86 ++++++++++++++++++++++---------------- wpa_supplicant/wpas_glue.c | 13 +++++- 3 files changed, 87 insertions(+), 44 deletions(-)