Use the existing RSNE parsing and checks also for OSEN. Signed-off-by: Alexander Wetzel <alexander@xxxxxxxxxxxxxx> --- src/rsn_supp/wpa.c | 32 ++++++++++---- wpa_supplicant/events.c | 86 ++++++++++++++++++++++---------------- wpa_supplicant/wpas_glue.c | 13 +++++- 3 files changed, 87 insertions(+), 44 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 504feaf2a..99cdab298 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -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; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 9d808c55d..6fe4cdd2a 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -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 && diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 503163d5d..cbaff4ff3 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -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; -- 2.24.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap