Accumulative patch from commit f5f37d3a4fc2df2a24676b4f95afca15ed793cba

Author: Jouni Malinen <j@w1.fi>
Date:   Sun Nov 25 22:05:32 2012 +0200

   Fix REAUTHENTICATE command after PMKSA caching

   The current PMKSA cache entry needs to be clear to allow EAPOL
   reauthentication to be started in case this association used PMKSA
   caching.

 - Remove old WPS_OOB NCF
 - WPS: Add preliminary NFC connection handover support for Enrollee
 - WPS: Reenable the networks disabled during wpa_wpas_reassoc
 - P2P: Avoid multi-channel scans when they are not needed
 - P2P: Allow discoverable interval for p2p_find to be configured
 - P2P: Allow all channels with multi-channel concurrency
 - Bonjour changes
 - Remove disassociate
 - HS 2.0 changes
 - Add preliminary support for using SQLite for eap_user database
 - Add SAE support
 - Add disallow_aps parameter to disallow BSSIDs/SSIDs

Change-Id: I85358a05b39d46b8db49acdad667e771c580b05c
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 22f709f..cfe56ea 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -717,9 +717,12 @@
 #endif /* INTERWORKING_3GPP */
 
 
-static int interworking_set_hs20_params(struct wpa_ssid *ssid)
+static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
+					struct wpa_ssid *ssid)
 {
-	if (wpa_config_set(ssid, "key_mgmt", "WPA-EAP", 0) < 0)
+	if (wpa_config_set(ssid, "key_mgmt",
+			   wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ?
+			   "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP", 0) < 0)
 		return -1;
 	if (wpa_config_set(ssid, "proto", "RSN", 0) < 0)
 		return -1;
@@ -786,6 +789,7 @@
 	ssid = wpa_config_add_network(wpa_s->conf);
 	if (ssid == NULL)
 		return -1;
+	ssid->parent_cred = cred;
 
 	wpas_notify_network_added(wpa_s, ssid);
 	wpa_config_set_network_defaults(ssid);
@@ -797,7 +801,7 @@
 	os_memcpy(ssid->ssid, ie + 2, ie[1]);
 	ssid->ssid_len = ie[1];
 
-	if (interworking_set_hs20_params(ssid) < 0)
+	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
 		goto fail;
 
 	eap_type = EAP_TYPE_SIM;
@@ -1046,6 +1050,17 @@
 	    wpa_config_set_quoted(ssid, "client_cert", cred->client_cert) < 0)
 		return -1;
 
+#ifdef ANDROID
+	if (cred->private_key &&
+	    os_strncmp(cred->private_key, "keystore://", 11) == 0) {
+		/* Use OpenSSL engine configuration for Android keystore */
+		if (wpa_config_set_quoted(ssid, "engine_id", "keystore") < 0 ||
+		    wpa_config_set_quoted(ssid, "key_id",
+					  cred->private_key + 11) < 0 ||
+		    wpa_config_set(ssid, "engine", "1", 0) < 0)
+			return -1;
+	} else
+#endif /* ANDROID */
 	if (cred->private_key && cred->private_key[0] &&
 	    wpa_config_set_quoted(ssid, "private_key", cred->private_key) < 0)
 		return -1;
@@ -1084,6 +1099,7 @@
 	ssid = wpa_config_add_network(wpa_s->conf);
 	if (ssid == NULL)
 		return -1;
+	ssid->parent_cred = cred;
 	wpas_notify_network_added(wpa_s, ssid);
 	wpa_config_set_network_defaults(ssid);
 	ssid->priority = cred->priority;
@@ -1094,7 +1110,7 @@
 	os_memcpy(ssid->ssid, ssid_ie + 2, ssid_ie[1]);
 	ssid->ssid_len = ssid_ie[1];
 
-	if (interworking_set_hs20_params(ssid) < 0)
+	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
 		goto fail;
 
 	if (cred->eap_method == NULL) {
@@ -1198,6 +1214,7 @@
 		nai_realm_free(realm, count);
 		return -1;
 	}
+	ssid->parent_cred = cred;
 	wpas_notify_network_added(wpa_s, ssid);
 	wpa_config_set_network_defaults(ssid);
 	ssid->priority = cred->priority;
@@ -1208,7 +1225,7 @@
 	os_memcpy(ssid->ssid, ie + 2, ie[1]);
 	ssid->ssid_len = ie[1];
 
-	if (interworking_set_hs20_params(ssid) < 0)
+	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
 		goto fail;
 
 	if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF,
@@ -1424,50 +1441,60 @@
 }
 
 
+int interworking_home_sp_cred(struct wpa_supplicant *wpa_s,
+			      struct wpa_cred *cred,
+			      struct wpabuf *domain_names)
+{
+#ifdef INTERWORKING_3GPP
+	char nai[100], *realm;
+
+	char *imsi = NULL;
+	int mnc_len = 0;
+	if (cred->imsi)
+		imsi = cred->imsi;
+#ifdef CONFIG_PCSC
+	else if (cred->pcsc && wpa_s->conf->pcsc_reader &&
+		 wpa_s->scard && wpa_s->imsi[0]) {
+		imsi = wpa_s->imsi;
+		mnc_len = wpa_s->mnc_len;
+	}
+#endif /* CONFIG_PCSC */
+	if (imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) {
+		realm = os_strchr(nai, '@');
+		if (realm)
+			realm++;
+		wpa_printf(MSG_DEBUG, "Interworking: Search for match "
+			   "with SIM/USIM domain %s", realm);
+		if (realm &&
+		    domain_name_list_contains(domain_names, realm))
+			return 1;
+	}
+#endif /* INTERWORKING_3GPP */
+
+	if (cred->domain == NULL)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "Interworking: Search for match with "
+		   "home SP FQDN %s", cred->domain);
+	if (domain_name_list_contains(domain_names, cred->domain))
+		return 1;
+
+	return 0;
+}
+
+
 static int interworking_home_sp(struct wpa_supplicant *wpa_s,
 				struct wpabuf *domain_names)
 {
 	struct wpa_cred *cred;
-#ifdef INTERWORKING_3GPP
-	char nai[100], *realm;
-#endif /* INTERWORKING_3GPP */
 
 	if (domain_names == NULL || wpa_s->conf->cred == NULL)
 		return -1;
 
 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
-#ifdef INTERWORKING_3GPP
-		char *imsi = NULL;
-		int mnc_len = 0;
-		if (cred->imsi)
-			imsi = cred->imsi;
-#ifdef CONFIG_PCSC
-		else if (cred->pcsc && wpa_s->conf->pcsc_reader &&
-			 wpa_s->scard && wpa_s->imsi[0]) {
-			imsi = wpa_s->imsi;
-			mnc_len = wpa_s->mnc_len;
-		}
-#endif /* CONFIG_PCSC */
-		if (imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0)
-		    == 0) {
-			realm = os_strchr(nai, '@');
-			if (realm)
-				realm++;
-			wpa_printf(MSG_DEBUG, "Interworking: Search for match "
-				   "with SIM/USIM domain %s", realm);
-			if (realm &&
-			    domain_name_list_contains(domain_names, realm))
-				return 1;
-		}
-#endif /* INTERWORKING_3GPP */
-
-		if (cred->domain == NULL)
-			continue;
-
-		wpa_printf(MSG_DEBUG, "Interworking: Search for match with "
-			   "home SP FQDN %s", cred->domain);
-		if (domain_name_list_contains(domain_names, cred->domain))
-			return 1;
+		int res = interworking_home_sp_cred(wpa_s, cred, domain_names);
+		if (res)
+			return res;
 	}
 
 	return 0;
@@ -1714,8 +1741,10 @@
 
 	freq = wpa_s->assoc_freq;
 	bss = wpa_bss_get_bssid(wpa_s, dst);
-	if (bss)
+	if (bss) {
+		wpa_bss_anqp_unshare_alloc(bss);
 		freq = bss->freq;
+	}
 	if (freq <= 0)
 		return -1;
 
@@ -1935,7 +1964,7 @@
 	wpa_printf(MSG_DEBUG, "Interworking: Start scan for network "
 		   "selection");
 	wpa_s->scan_res_handler = interworking_scan_res_handler;
-	wpa_s->scan_req = 2;
+	wpa_s->scan_req = MANUAL_SCAN_REQ;
 	wpa_supplicant_req_scan(wpa_s, 0, 0);
 
 	return 0;