[PATCH] wpa_supplicant: Use RSNE parsing for OSEN

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux