Cumulative patch from commit 8b3b803ab9fe69650da7e3b2ee9e44f0f054ee0a

8b3b803 Include Extended Capabilities element based on scan results
6903ee6 P2P Extend postponing of concurrent scans for persistent GO
77e3094 hlr_auc_gw: Fix max_chal value validation
3e6547b hlr_auc_gw: Add support for processing command line operations
2b5b875 EAP-AKA server: Fix AUTS processing
9a50ee6 hlr_auc_gw: Update file comments to mention Milenage
5388dc9 Document use of Linux capabilities instead of privileged process
a771c07 Add driver status information to control interface
739faee nl80211: Add some more debug prints for mgmt frame TX
f78f278 nl80211: Fix off-channel Action frame TX from GO with use_monitor
298f518 Get rid of compiler warning in no-CONFIG_CTRL_IFACE builds
ea61aa1 Add no_ctrl_interface config param to clear ctrl_interface
25b65a1 Make sure updated BSS entry does not get added twice to the list
bbc6c72 P2P: Use group formation timeout on persistent group GO
41f8532 P2P: Extend group formation timeout on GO to first data connection
20625e9 P2P: Remove P2P groups on process termination
76fe79e Register wpa_msg callback even if only global ctrl_iface is used
af96448 nl80211: Add more debug prints for send_mlme operations
5d4c78f nl80211: Reset nlmode to station on leaving IBSS
0249c12 Avoid compiler warning with CONFIG_NO_STDOUT_DEBUG=y
ed1bf01 Allow hostapd config file for dynamically added interface
97bacf7 Do not clear hostapd configuration parameters on disable-iface
66f4dd1 hostapd: Fix couple of deinit path cases to clear pointers
f18b781 nl80211: Print more debug info on management frame RX information
89286e9 Re-open ctrl_iface socket on some failure cases as a workaround
3ca96df atheros: Compile fix for driver code not defining IEEE80211_APPIE_FRAME_WNM
762c92a OpenSSL: Split OCSP peer_cert/peer_issuer debug output into parts
f224cf0 HS 2.0: Allow printf format parsing with language:name strings
913c19c Fix wpa_config_parse_string() to null terminate printf decoded values
04e533e Fix language string length validation in parse_lang_string()
742e715 Simplify ctrl_iface sendto() use
6668efd Clear frequency list on empty value
1a9f247 Make scan_freq field to be saved by save_config
aa78cd3 Drop EAP packet with code 10 before EAPOL state machine processing
3cc247a Use configured sched_scan interval for the PNO scan
d047ae6 WPS: Ignore PBC-to-PIN change from M1 to M2 as a workaround
79986bf Print ctrl_iface sendto() failures into debug log
eab2b50 P2P: Cancel group formation timeout on client connection
00eb299 P2P: Fix operation channel configuration update

Change-Id: I9269e23bc8019b951c2a2d3c707562b2e006148b
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 0b4fd77..dc68fc8 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1289,26 +1289,34 @@
 static int parse_lang_string(struct hostapd_lang_string **array,
 			     unsigned int *count, char *pos)
 {
-	char *sep;
-	size_t clen, nlen;
+	char *sep, *str = NULL;
+	size_t clen, nlen, slen;
 	struct hostapd_lang_string *ls;
+	int ret = -1;
+
+	if (*pos == '"' || (*pos == 'P' && pos[1] == '"')) {
+		str = wpa_config_parse_string(pos, &slen);
+		if (!str)
+			return -1;
+		pos = str;
+	}
 
 	sep = os_strchr(pos, ':');
 	if (sep == NULL)
-		return -1;
+		goto fail;
 	*sep++ = '\0';
 
 	clen = os_strlen(pos);
-	if (clen < 2)
-		return -1;
+	if (clen < 2 || clen > sizeof(ls->lang))
+		goto fail;
 	nlen = os_strlen(sep);
 	if (nlen > 252)
-		return -1;
+		goto fail;
 
 	ls = os_realloc_array(*array, *count + 1,
 			      sizeof(struct hostapd_lang_string));
 	if (ls == NULL)
-		return -1;
+		goto fail;
 
 	*array = ls;
 	ls = &(*array)[*count];
@@ -1319,7 +1327,10 @@
 	ls->name_len = nlen;
 	os_memcpy(ls->name, sep, nlen);
 
-	return 0;
+	ret = 0;
+fail:
+	os_free(str);
+	return ret;
 }
 
 
diff --git a/hostapd/hlr_auc_gw.c b/hostapd/hlr_auc_gw.c
index e04e2e9..2e61ac3 100644
--- a/hostapd/hlr_auc_gw.c
+++ b/hostapd/hlr_auc_gw.c
@@ -1,6 +1,6 @@
 /*
  * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
- * Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2005-2007, 2012-2013, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -30,12 +30,16 @@
  * IMSI and max_chal are sent as an ASCII string,
  * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings.
  *
- * The example implementation here reads GSM authentication triplets from a
+ * An example implementation here reads GSM authentication triplets from a
  * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
  * strings. This is used to simulate an HLR/AuC. As such, it is not very useful
  * for real life authentication, but it is useful both as an example
  * implementation and for EAP-SIM/AKA/AKA' testing.
  *
+ * For a stronger example design, Milenage and GSM-Milenage algorithms can be
+ * used to dynamically generate authenticatipn information for EAP-AKA/AKA' and
+ * EAP-SIM, respectively, if Ki is known.
+ *
  * SQN generation follows the not time-based Profile 2 described in
  * 3GPP TS 33.102 Annex C.3.2. The length of IND is 5 bits by default, but this
  * can be changed with a command line options if needed.
@@ -58,6 +62,7 @@
 static int update_milenage = 0;
 static int sqn_changes = 0;
 static int ind_len = 5;
+static int stdout_debug = 1;
 
 /* GSM triplets */
 struct gsm_triplet {
@@ -214,6 +219,9 @@
 {
 	char cmd[128], val[13], *pos;
 
+	if (sqlite_db == NULL)
+		return 0;
+
 	pos = val;
 	pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6);
 	*pos = '\0';
@@ -611,31 +619,30 @@
 }
 
 
-static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
-			 char *imsi)
+static int sim_req_auth(char *imsi, char *resp, size_t resp_len)
 {
 	int count, max_chal, ret;
 	char *pos;
-	char reply[1000], *rpos, *rend;
+	char *rpos, *rend;
 	struct milenage_parameters *m;
 	struct gsm_triplet *g;
 
-	reply[0] = '\0';
+	resp[0] = '\0';
 
 	pos = strchr(imsi, ' ');
 	if (pos) {
 		*pos++ = '\0';
 		max_chal = atoi(pos);
-		if (max_chal < 1 || max_chal < EAP_SIM_MAX_CHAL)
+		if (max_chal < 1 || max_chal > EAP_SIM_MAX_CHAL)
 			max_chal = EAP_SIM_MAX_CHAL;
 	} else
 		max_chal = EAP_SIM_MAX_CHAL;
 
-	rend = &reply[sizeof(reply)];
-	rpos = reply;
+	rend = resp + resp_len;
+	rpos = resp;
 	ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
 	if (ret < 0 || ret >= rend - rpos)
-		return;
+		return -1;
 	rpos += ret;
 
 	m = get_milenage(imsi);
@@ -643,7 +650,7 @@
 		u8 _rand[16], sres[4], kc[8];
 		for (count = 0; count < max_chal; count++) {
 			if (random_get_bytes(_rand, 16) < 0)
-				return;
+				return -1;
 			gsm_milenage(m->opc, m->ki, _rand, sres, kc);
 			*rpos++ = ' ';
 			rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
@@ -653,7 +660,7 @@
 			rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16);
 		}
 		*rpos = '\0';
-		goto send;
+		return 0;
 	}
 
 	count = 0;
@@ -677,15 +684,11 @@
 		printf("No GSM triplets found for %s\n", imsi);
 		ret = snprintf(rpos, rend - rpos, " FAILURE");
 		if (ret < 0 || ret >= rend - rpos)
-			return;
+			return -1;
 		rpos += ret;
 	}
 
-send:
-	printf("Send: %s\n", reply);
-	if (sendto(s, reply, rpos - reply, 0,
-		   (struct sockaddr *) from, fromlen) < 0)
-		perror("send");
+	return 0;
 }
 
 
@@ -711,11 +714,10 @@
 }
 
 
-static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
-			 char *imsi)
+static int aka_req_auth(char *imsi, char *resp, size_t resp_len)
 {
 	/* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
-	char reply[1000], *pos, *end;
+	char *pos, *end;
 	u8 _rand[EAP_AKA_RAND_LEN];
 	u8 autn[EAP_AKA_AUTN_LEN];
 	u8 ik[EAP_AKA_IK_LEN];
@@ -729,16 +731,18 @@
 	m = get_milenage(imsi);
 	if (m) {
 		if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
-			return;
+			return -1;
 		res_len = EAP_AKA_RES_MAX_LEN;
 		inc_sqn(m->sqn);
 #ifdef CONFIG_SQLITE
 		db_update_milenage_sqn(m);
 #endif /* CONFIG_SQLITE */
 		sqn_changes = 1;
-		printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
-		       m->sqn[0], m->sqn[1], m->sqn[2],
-		       m->sqn[3], m->sqn[4], m->sqn[5]);
+		if (stdout_debug) {
+			printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
+			       m->sqn[0], m->sqn[1], m->sqn[2],
+			       m->sqn[3], m->sqn[4], m->sqn[5]);
+		}
 		milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
 				  autn, ik, ck, res, &res_len);
 	} else {
@@ -756,18 +760,18 @@
 #endif /* AKA_USE_FIXED_TEST_VALUES */
 	}
 
-	pos = reply;
-	end = &reply[sizeof(reply)];
+	pos = resp;
+	end = resp + resp_len;
 	ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
 	if (ret < 0 || ret >= end - pos)
-		return;
+		return -1;
 	pos += ret;
 	if (failed) {
 		ret = snprintf(pos, end - pos, "FAILURE");
 		if (ret < 0 || ret >= end - pos)
-			return;
+			return -1;
 		pos += ret;
-		goto done;
+		return 0;
 	}
 	pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
 	*pos++ = ' ';
@@ -779,65 +783,84 @@
 	*pos++ = ' ';
 	pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
 
-done:
-	printf("Send: %s\n", reply);
-
-	if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
-		   fromlen) < 0)
-		perror("send");
+	return 0;
 }
 
 
-static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
-		     char *imsi)
+static int aka_auts(char *imsi, char *resp, size_t resp_len)
 {
 	char *auts, *__rand;
 	u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
 	struct milenage_parameters *m;
 
+	resp[0] = '\0';
+
 	/* AKA-AUTS <IMSI> <AUTS> <RAND> */
 
 	auts = strchr(imsi, ' ');
 	if (auts == NULL)
-		return;
+		return -1;
 	*auts++ = '\0';
 
 	__rand = strchr(auts, ' ');
 	if (__rand == NULL)
-		return;
+		return -1;
 	*__rand++ = '\0';
 
-	printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", imsi, auts, __rand);
+	if (stdout_debug) {
+		printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n",
+		       imsi, auts, __rand);
+	}
 	if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) ||
 	    hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) {
 		printf("Could not parse AUTS/RAND\n");
-		return;
+		return -1;
 	}
 
 	m = get_milenage(imsi);
 	if (m == NULL) {
 		printf("Unknown IMSI: %s\n", imsi);
-		return;
+		return -1;
 	}
 
 	if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
 		printf("AKA-AUTS: Incorrect MAC-S\n");
 	} else {
 		memcpy(m->sqn, sqn, 6);
-		printf("AKA-AUTS: Re-synchronized: "
-		       "SQN=%02x%02x%02x%02x%02x%02x\n",
-		       sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
+		if (stdout_debug) {
+			printf("AKA-AUTS: Re-synchronized: "
+			       "SQN=%02x%02x%02x%02x%02x%02x\n",
+			       sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
+		}
 #ifdef CONFIG_SQLITE
 		db_update_milenage_sqn(m);
 #endif /* CONFIG_SQLITE */
 		sqn_changes = 1;
 	}
+
+	return 0;
+}
+
+
+static int process_cmd(char *cmd, char *resp, size_t resp_len)
+{
+	if (os_strncmp(cmd, "SIM-REQ-AUTH ", 13) == 0)
+		return sim_req_auth(cmd + 13, resp, resp_len);
+
+	if (os_strncmp(cmd, "AKA-REQ-AUTH ", 13) == 0)
+		return aka_req_auth(cmd + 13, resp, resp_len);
+
+	if (os_strncmp(cmd, "AKA-AUTS ", 9) == 0)
+		return aka_auts(cmd + 9, resp, resp_len);
+
+	printf("Unknown request: %s\n", cmd);
+	return -1;
 }
 
 
 static int process(int s)
 {
-	char buf[1000];
+	char buf[1000], resp[1000];
 	struct sockaddr_un from;
 	socklen_t fromlen;
 	ssize_t res;
@@ -859,14 +882,21 @@
 
 	printf("Received: %s\n", buf);
 
-	if (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0)
-		sim_req_auth(s, &from, fromlen, buf + 13);
-	else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0)
-		aka_req_auth(s, &from, fromlen, buf + 13);
-	else if (strncmp(buf, "AKA-AUTS ", 9) == 0)
-		aka_auts(s, &from, fromlen, buf + 9);
-	else
-		printf("Unknown request: %s\n", buf);
+	if (process_cmd(buf, resp, sizeof(resp)) < 0) {
+		printf("Failed to process request\n");
+		return -1;
+	}
+
+	if (resp[0] == '\0') {
+		printf("No response\n");
+		return 0;
+	}
+
+	printf("Send: %s\n", resp);
+
+	if (sendto(s, resp, os_strlen(resp), 0, (struct sockaddr *) &from,
+		   fromlen) < 0)
+		perror("send");
 
 	return 0;
 }
@@ -894,8 +924,10 @@
 		os_free(prev);
 	}
 
-	close(serv_sock);
-	unlink(socket_path);
+	if (serv_sock >= 0)
+		close(serv_sock);
+	if (socket_path)
+		unlink(socket_path);
 
 #ifdef CONFIG_SQLITE
 	if (sqlite_db) {
@@ -917,12 +949,12 @@
 {
 	printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
 	       "database/authenticator\n"
-	       "Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>\n"
+	       "Copyright (c) 2005-2007, 2012-2013, Jouni Malinen <j@w1.fi>\n"
 	       "\n"
 	       "usage:\n"
 	       "hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
 	       "[-m<milenage file>] \\\n"
-	       "        [-D<DB file>] [-i<IND len in bits>]\n"
+	       "        [-D<DB file>] [-i<IND len in bits>] [command]\n"
 	       "\n"
 	       "options:\n"
 	       "  -h = show this usage help\n"
@@ -932,7 +964,15 @@
 	       "  -g<triplet file> = path for GSM authentication triplets\n"
 	       "  -m<milenage file> = path for Milenage keys\n"
 	       "  -D<DB file> = path to SQLite database\n"
-	       "  -i<IND len in bits> = IND length for SQN (default: 5)\n",
+	       "  -i<IND len in bits> = IND length for SQN (default: 5)\n"
+	       "\n"
+	       "If the optional command argument, like "
+	       "\"AKA-REQ-AUTH <IMSI>\" is used, a single\n"
+	       "command is processed with response sent to stdout. Otherwise, "
+	       "hlr_auc_gw opens\n"
+	       "a control interface and processes commands sent through it "
+	       "(e.g., by EAP server\n"
+	       "in hostapd).\n",
 	       default_socket_path);
 }
 
@@ -942,6 +982,7 @@
 	int c;
 	char *gsm_triplet_file = NULL;
 	char *sqlite_db_file = NULL;
+	int ret = 0;
 
 	if (os_program_init())
 		return -1;
@@ -1005,18 +1046,31 @@
 	if (milenage_file && read_milenage(milenage_file) < 0)
 		return -1;
 
-	serv_sock = open_socket(socket_path);
-	if (serv_sock < 0)
-		return -1;
+	if (optind == argc) {
+		serv_sock = open_socket(socket_path);
+		if (serv_sock < 0)
+			return -1;
 
-	printf("Listening for requests on %s\n", socket_path);
+		printf("Listening for requests on %s\n", socket_path);
 
-	atexit(cleanup);
-	signal(SIGTERM, handle_term);
-	signal(SIGINT, handle_term);
+		atexit(cleanup);
+		signal(SIGTERM, handle_term);
+		signal(SIGINT, handle_term);
 
-	for (;;)
-		process(serv_sock);
+		for (;;)
+			process(serv_sock);
+	} else {
+		char buf[1000];
+		socket_path = NULL;
+		stdout_debug = 0;
+		if (process_cmd(argv[optind], buf, sizeof(buf)) < 0) {
+			printf("FAIL\n");
+			ret = -1;
+		} else {
+			printf("%s\n", buf);
+		}
+		cleanup();
+	}
 
 #ifdef CONFIG_SQLITE
 	if (sqlite_db) {
@@ -1027,5 +1081,5 @@
 
 	os_program_deinit();
 
-	return 0;
+	return ret;
 }
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 45897ed..de1bf75 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1457,6 +1457,9 @@
 # information to be complete.
 #venue_name=eng:Example venue
 #venue_name=fin:Esimerkkipaikka
+# Alternative format for language:value strings:
+# (double quoted string, printf-escaped string)
+#venue_name=P"eng:Example\nvenue"
 
 # Network Authentication Type
 # This parameter indicates what type of network authentication is used in the