Browse Source

Interworking: Allow SSID-based network exclusion for credentials

The new excluded_ssid parameter within a cred block can be used to
excluded networks from matching with credentials.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 12 years ago
parent
commit
dbea8ac7ab

+ 5 - 0
wpa_supplicant/README-HS20

@@ -190,6 +190,11 @@ Credentials can be pre-configured for automatic network selection:
 # phase2: Pre-configure Phase 2 (inner authentication) parameters
 #	This optional field is used with like the 'eap' parameter.
 #
+# excluded_ssid: Excluded SSID
+#	This optional field can be used to excluded specific SSID(s) from
+#	matching with the network. Multiple entries can be used to specify more
+#	than one SSID.
+#
 # for example:
 #
 #cred={

+ 29 - 0
wpa_supplicant/config.c

@@ -1835,6 +1835,7 @@ void wpa_config_free_cred(struct wpa_cred *cred)
 	os_free(cred->eap_method);
 	os_free(cred->phase1);
 	os_free(cred->phase2);
+	os_free(cred->excluded_ssid);
 	os_free(cred);
 }
 
@@ -2411,6 +2412,34 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
 		return 0;
 	}
 
+	if (os_strcmp(var, "excluded_ssid") == 0) {
+		struct excluded_ssid *e;
+
+		if (len > MAX_SSID_LEN) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid "
+				   "excluded_ssid length %d", line, (int) len);
+			os_free(val);
+			return -1;
+		}
+
+		e = os_realloc_array(cred->excluded_ssid,
+				     cred->num_excluded_ssid + 1,
+				     sizeof(struct excluded_ssid));
+		if (e == NULL) {
+			os_free(val);
+			return -1;
+		}
+		cred->excluded_ssid = e;
+
+		e = &cred->excluded_ssid[cred->num_excluded_ssid++];
+		os_memcpy(e->ssid, val, len);
+		e->ssid_len = len;
+
+		os_free(val);
+
+		return 0;
+	}
+
 	if (line) {
 		wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.",
 			   line, var);

+ 6 - 0
wpa_supplicant/config.h

@@ -196,6 +196,12 @@ struct wpa_cred {
 	 * Pre-configured EAP parameters or %NULL.
 	 */
 	char *phase2;
+
+	struct excluded_ssid {
+		u8 ssid[MAX_SSID_LEN];
+		size_t ssid_len;
+	} *excluded_ssid;
+	size_t num_excluded_ssid;
 };
 
 

+ 10 - 0
wpa_supplicant/config_file.c

@@ -742,6 +742,16 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
 		fprintf(f, "\tphase1=\"%s\"\n", cred->phase1);
 	if (cred->phase2)
 		fprintf(f, "\tphase2=\"%s\"\n", cred->phase2);
+	if (cred->excluded_ssid) {
+		size_t i, j;
+		for (i = 0; i < cred->num_excluded_ssid; i++) {
+			struct excluded_ssid *e = &cred->excluded_ssid[i];
+			fprintf(f, "\texcluded_ssid=");
+			for (j = 0; j < e->ssid_len; j++)
+				fprintf(f, "%02x", e->ssid[j]);
+			fprintf(f, "\n");
+		}
+	}
 }
 
 

+ 25 - 0
wpa_supplicant/interworking.c

@@ -948,6 +948,24 @@ static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp,
 }
 
 
+static int cred_excluded_ssid(struct wpa_cred *cred, struct wpa_bss *bss)
+{
+	size_t i;
+
+	if (!cred->excluded_ssid)
+		return 0;
+
+	for (i = 0; i < cred->num_excluded_ssid; i++) {
+		struct excluded_ssid *e = &cred->excluded_ssid[i];
+		if (bss->ssid_len == e->ssid_len &&
+		    os_memcmp(bss->ssid, e->ssid, e->ssid_len) == 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+
 static struct wpa_cred * interworking_credentials_available_roaming_consortium(
 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
 {
@@ -975,6 +993,9 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium(
 					      cred->roaming_consortium_len))
 			continue;
 
+		if (cred_excluded_ssid(cred, bss))
+			continue;
+
 		if (selected == NULL ||
 		    selected->priority < cred->priority)
 			selected = cred;
@@ -1343,6 +1364,8 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
 		ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len);
 		wpa_printf(MSG_DEBUG, "PLMN match %sfound", ret ? "" : "not ");
 		if (ret) {
+			if (cred_excluded_ssid(cred, bss))
+				continue;
 			if (selected == NULL ||
 			    selected->priority < cred->priority)
 				selected = cred;
@@ -1383,6 +1406,8 @@ static struct wpa_cred * interworking_credentials_available_realm(
 			if (!nai_realm_match(&realm[i], cred->realm))
 				continue;
 			if (nai_realm_find_eap(cred, &realm[i])) {
+				if (cred_excluded_ssid(cred, bss))
+					continue;
 				if (selected == NULL ||
 				    selected->priority < cred->priority)
 					selected = cred;

+ 5 - 0
wpa_supplicant/wpa_supplicant.conf

@@ -389,6 +389,11 @@ fast_reauth=1
 # phase2: Pre-configure Phase 2 (inner authentication) parameters
 #	This optional field is used with like the 'eap' parameter.
 #
+# excluded_ssid: Excluded SSID
+#	This optional field can be used to excluded specific SSID(s) from
+#	matching with the network. Multiple entries can be used to specify more
+#	than one SSID.
+#
 # for example:
 #
 #cred={