Accumulative patch from commit dc013f1e37df3462085cf01a13f0c432f146ad7a

Author: Jouni Malinen <jouni@qca.qualcomm.com>
Date:   Tue Jan 15 12:03:29 2013 +0200
    eapol_test: Remove unnecessary header file inclusion

 - P2P: Send P2P-FIND-STOPPED event in the new continue-search states
 - P2P: Add some more details on Service Query TLV format
 - P2P: Use the same Dialog Token value for every GO Negotiation retry
 - P2P: Publish more connected clients info in Probe Response frames
 - P2P: Fix some memory leaks in p2p_add_device()
 - P2P: Use the same Dialog Token value for every PD retry
 - P2P: Document operating channel selection functions
 - P2P: Always re-select operating channel if not hard coded
 - P2P: Do not allow re-selection of GO channel if forced_freq in use
 - P2P: Set FORCE_FREQ flag as part of p2p_prepare_channel()
 - P2P: Share a single function for GO channel selection
 - P2P: Prefer operating channels where HT40 is possible
 - P2P: Be more careful with wpa_config_update_psk() call
 - P2P: Allow PSK to be used instead of passphrase for persistent GO
 - P2P: Consider age for the P2P scan results
 - Move some P2P offchannel operations to offchannel.c
 - P2P: Add more complete description of p2p_cancel
 - P2P: Allow p2p_cancel to be used to stop p2p_connect-join operation
 - Interworking changes
 - WNM changes
 - WPS changes
 - SAE changes

Change-Id: I38b847d3460066cc58aecbcf67266bfcff1d344e
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index cfe56ea..b8a8bb2 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -13,6 +13,7 @@
 #include "common/gas.h"
 #include "common/wpa_ctrl.h"
 #include "utils/pcsc_funcs.h"
+#include "utils/eloop.h"
 #include "drivers/driver.h"
 #include "eap_common/eap_defs.h"
 #include "eap_peer/eap.h"
@@ -170,6 +171,13 @@
 }
 
 
+static void interworking_continue_anqp(void *eloop_ctx, void *sock_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	interworking_next_anqp_fetch(wpa_s);
+}
+
+
 static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
 				      struct wpa_bss *bss)
 {
@@ -238,6 +246,8 @@
 	if (res < 0) {
 		wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
 		ret = -1;
+		eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s,
+				       NULL);
 	} else
 		wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
 			   "%u", res);
@@ -516,13 +526,18 @@
 		return 0;
 	}
 
-	if (eap->method == EAP_TYPE_PEAP &&
-	    eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL)
-		return 0;
+	if (eap->method == EAP_TYPE_PEAP) {
+		if (eap->inner_method &&
+		    eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL)
+			return 0;
+		if (!eap->inner_method &&
+		    eap_get_name(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2) == NULL)
+			return 0;
+	}
 
 	if (eap->method == EAP_TYPE_TTLS) {
 		if (eap->inner_method == 0 && eap->inner_non_eap == 0)
-			return 0;
+			return 1; /* Assume TTLS/MSCHAPv2 is used */
 		if (eap->inner_method &&
 		    eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL)
 			return 0;
@@ -948,6 +963,24 @@
 }
 
 
+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 +1008,9 @@
 					      cred->roaming_consortium_len))
 			continue;
 
+		if (cred_excluded_ssid(cred, bss))
+			continue;
+
 		if (selected == NULL ||
 		    selected->priority < cred->priority)
 			selected = cred;
@@ -1263,11 +1299,20 @@
 					   0) < 0)
 				goto fail;
 			break;
+		default:
+			/* EAP params were not set - assume TTLS/MSCHAPv2 */
+			if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"",
+					   0) < 0)
+				goto fail;
+			break;
 		}
 		break;
 	case EAP_TYPE_PEAP:
 		os_snprintf(buf, sizeof(buf), "\"auth=%s\"",
-			    eap_get_name(EAP_VENDOR_IETF, eap->inner_method));
+			    eap_get_name(EAP_VENDOR_IETF,
+					 eap->inner_method ?
+					 eap->inner_method :
+					 EAP_TYPE_MSCHAPV2));
 		if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
 			goto fail;
 		break;
@@ -1337,6 +1382,8 @@
 		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;
@@ -1377,6 +1424,8 @@
 			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;
@@ -1459,7 +1508,8 @@
 		mnc_len = wpa_s->mnc_len;
 	}
 #endif /* CONFIG_PCSC */
-	if (imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) {
+	if (domain_names &&
+	    imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) {
 		realm = os_strchr(nai, '@');
 		if (realm)
 			realm++;
@@ -1471,7 +1521,7 @@
 	}
 #endif /* INTERWORKING_3GPP */
 
-	if (cred->domain == NULL)
+	if (domain_names == NULL || cred->domain == NULL)
 		return 0;
 
 	wpa_printf(MSG_DEBUG, "Interworking: Search for match with "
@@ -1630,6 +1680,11 @@
 			continue;
 		if (other->anqp == NULL)
 			continue;
+		if (other->anqp->roaming_consortium == NULL &&
+		    other->anqp->nai_realm == NULL &&
+		    other->anqp->anqp_3gpp == NULL &&
+		    other->anqp->domain_name == NULL)
+			continue;
 		if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED))
 			continue;
 		if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0)
@@ -1655,7 +1710,7 @@
 	int found = 0;
 	const u8 *ie;
 
-	if (!wpa_s->fetch_anqp_in_progress)
+	if (eloop_terminated() || !wpa_s->fetch_anqp_in_progress)
 		return;
 
 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {