1/*
2 * WPA Supplicant / Configuration parser and common functions
3 * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "utils/uuid.h"
13#include "crypto/sha1.h"
14#include "rsn_supp/wpa.h"
15#include "eap_peer/eap.h"
16#include "config.h"
17
18
19#if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE)
20#define NO_CONFIG_WRITE
21#endif
22
23/*
24 * Structure for network configuration parsing. This data is used to implement
25 * a generic parser for each network block variable. The table of configuration
26 * variables is defined below in this file (ssid_fields[]).
27 */
28struct parse_data {
29	/* Configuration variable name */
30	char *name;
31
32	/* Parser function for this variable */
33	int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
34		      int line, const char *value);
35
36#ifndef NO_CONFIG_WRITE
37	/* Writer function (i.e., to get the variable in text format from
38	 * internal presentation). */
39	char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
40#endif /* NO_CONFIG_WRITE */
41
42	/* Variable specific parameters for the parser. */
43	void *param1, *param2, *param3, *param4;
44
45	/* 0 = this variable can be included in debug output and ctrl_iface
46	 * 1 = this variable contains key/private data and it must not be
47	 *     included in debug output unless explicitly requested. In
48	 *     addition, this variable will not be readable through the
49	 *     ctrl_iface.
50	 */
51	int key_data;
52};
53
54
55static char * wpa_config_parse_string(const char *value, size_t *len)
56{
57	if (*value == '"') {
58		const char *pos;
59		char *str;
60		value++;
61		pos = os_strrchr(value, '"');
62		if (pos == NULL || pos[1] != '\0')
63			return NULL;
64		*len = pos - value;
65		str = os_malloc(*len + 1);
66		if (str == NULL)
67			return NULL;
68		os_memcpy(str, value, *len);
69		str[*len] = '\0';
70		return str;
71	} else {
72		u8 *str;
73		size_t tlen, hlen = os_strlen(value);
74		if (hlen & 1)
75			return NULL;
76		tlen = hlen / 2;
77		str = os_malloc(tlen + 1);
78		if (str == NULL)
79			return NULL;
80		if (hexstr2bin(value, str, tlen)) {
81			os_free(str);
82			return NULL;
83		}
84		str[tlen] = '\0';
85		*len = tlen;
86		return (char *) str;
87	}
88}
89
90
91static int wpa_config_parse_str(const struct parse_data *data,
92				struct wpa_ssid *ssid,
93				int line, const char *value)
94{
95	size_t res_len, *dst_len;
96	char **dst, *tmp;
97
98	if (os_strcmp(value, "NULL") == 0) {
99		wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
100			   data->name);
101		tmp = NULL;
102		res_len = 0;
103		goto set;
104	}
105
106	tmp = wpa_config_parse_string(value, &res_len);
107	if (tmp == NULL) {
108		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
109			   line, data->name,
110			   data->key_data ? "[KEY DATA REMOVED]" : value);
111		return -1;
112	}
113
114	if (data->key_data) {
115		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
116				      (u8 *) tmp, res_len);
117	} else {
118		wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
119				  (u8 *) tmp, res_len);
120	}
121
122	if (data->param3 && res_len < (size_t) data->param3) {
123		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
124			   "min_len=%ld)", line, data->name,
125			   (unsigned long) res_len, (long) data->param3);
126		os_free(tmp);
127		return -1;
128	}
129
130	if (data->param4 && res_len > (size_t) data->param4) {
131		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
132			   "max_len=%ld)", line, data->name,
133			   (unsigned long) res_len, (long) data->param4);
134		os_free(tmp);
135		return -1;
136	}
137
138set:
139	dst = (char **) (((u8 *) ssid) + (long) data->param1);
140	dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
141	os_free(*dst);
142	*dst = tmp;
143	if (data->param2)
144		*dst_len = res_len;
145
146	return 0;
147}
148
149
150#ifndef NO_CONFIG_WRITE
151static int is_hex(const u8 *data, size_t len)
152{
153	size_t i;
154
155	for (i = 0; i < len; i++) {
156		if (data[i] < 32 || data[i] >= 127)
157			return 1;
158	}
159	return 0;
160}
161
162
163static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
164{
165	char *buf;
166
167	buf = os_malloc(len + 3);
168	if (buf == NULL)
169		return NULL;
170	buf[0] = '"';
171	os_memcpy(buf + 1, value, len);
172	buf[len + 1] = '"';
173	buf[len + 2] = '\0';
174
175	return buf;
176}
177
178
179static char * wpa_config_write_string_hex(const u8 *value, size_t len)
180{
181	char *buf;
182
183	buf = os_zalloc(2 * len + 1);
184	if (buf == NULL)
185		return NULL;
186	wpa_snprintf_hex(buf, 2 * len + 1, value, len);
187
188	return buf;
189}
190
191
192static char * wpa_config_write_string(const u8 *value, size_t len)
193{
194	if (value == NULL)
195		return NULL;
196
197	if (is_hex(value, len))
198		return wpa_config_write_string_hex(value, len);
199	else
200		return wpa_config_write_string_ascii(value, len);
201}
202
203
204static char * wpa_config_write_str(const struct parse_data *data,
205				   struct wpa_ssid *ssid)
206{
207	size_t len;
208	char **src;
209
210	src = (char **) (((u8 *) ssid) + (long) data->param1);
211	if (*src == NULL)
212		return NULL;
213
214	if (data->param2)
215		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
216	else
217		len = os_strlen(*src);
218
219	return wpa_config_write_string((const u8 *) *src, len);
220}
221
222#ifdef WPA_UNICODE_SSID
223static char * wpa_config_write_str_unicode(const struct parse_data *data,
224						struct wpa_ssid *ssid)
225{
226	size_t len;
227	char **src;
228
229	src = (char **) (((u8 *) ssid) + (long) data->param1);
230	if (*src == NULL)
231		return NULL;
232
233	if (data->param2)
234		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
235	else
236		len = os_strlen(*src);
237
238	return wpa_config_write_string_ascii((const u8 *) *src, len);
239}
240#endif
241#endif /* NO_CONFIG_WRITE */
242
243
244static int wpa_config_parse_int(const struct parse_data *data,
245				struct wpa_ssid *ssid,
246				int line, const char *value)
247{
248	int *dst;
249
250	dst = (int *) (((u8 *) ssid) + (long) data->param1);
251	*dst = atoi(value);
252	wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
253
254	if (data->param3 && *dst < (long) data->param3) {
255		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
256			   "min_value=%ld)", line, data->name, *dst,
257			   (long) data->param3);
258		*dst = (long) data->param3;
259		return -1;
260	}
261
262	if (data->param4 && *dst > (long) data->param4) {
263		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
264			   "max_value=%ld)", line, data->name, *dst,
265			   (long) data->param4);
266		*dst = (long) data->param4;
267		return -1;
268	}
269
270	return 0;
271}
272
273
274#ifndef NO_CONFIG_WRITE
275static char * wpa_config_write_int(const struct parse_data *data,
276				   struct wpa_ssid *ssid)
277{
278	int *src, res;
279	char *value;
280
281	src = (int *) (((u8 *) ssid) + (long) data->param1);
282
283	value = os_malloc(20);
284	if (value == NULL)
285		return NULL;
286	res = os_snprintf(value, 20, "%d", *src);
287	if (res < 0 || res >= 20) {
288		os_free(value);
289		return NULL;
290	}
291	value[20 - 1] = '\0';
292	return value;
293}
294#endif /* NO_CONFIG_WRITE */
295
296
297static int wpa_config_parse_bssid(const struct parse_data *data,
298				  struct wpa_ssid *ssid, int line,
299				  const char *value)
300{
301	if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
302	    os_strcmp(value, "any") == 0) {
303		ssid->bssid_set = 0;
304		wpa_printf(MSG_MSGDUMP, "BSSID any");
305		return 0;
306	}
307	if (hwaddr_aton(value, ssid->bssid)) {
308		wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
309			   line, value);
310		return -1;
311	}
312	ssid->bssid_set = 1;
313	wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
314	return 0;
315}
316
317
318#ifndef NO_CONFIG_WRITE
319static char * wpa_config_write_bssid(const struct parse_data *data,
320				     struct wpa_ssid *ssid)
321{
322	char *value;
323	int res;
324
325	if (!ssid->bssid_set)
326		return NULL;
327
328	value = os_malloc(20);
329	if (value == NULL)
330		return NULL;
331	res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
332	if (res < 0 || res >= 20) {
333		os_free(value);
334		return NULL;
335	}
336	value[20 - 1] = '\0';
337	return value;
338}
339#endif /* NO_CONFIG_WRITE */
340
341
342static int wpa_config_parse_psk(const struct parse_data *data,
343				struct wpa_ssid *ssid, int line,
344				const char *value)
345{
346	if (*value == '"') {
347#ifndef CONFIG_NO_PBKDF2
348		const char *pos;
349		size_t len;
350
351		value++;
352		pos = os_strrchr(value, '"');
353		if (pos)
354			len = pos - value;
355		else
356			len = os_strlen(value);
357		if (len < 8 || len > 63) {
358			wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
359				   "length %lu (expected: 8..63) '%s'.",
360				   line, (unsigned long) len, value);
361			return -1;
362		}
363		wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
364				      (u8 *) value, len);
365		if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
366		    os_memcmp(ssid->passphrase, value, len) == 0)
367			return 0;
368		ssid->psk_set = 0;
369		os_free(ssid->passphrase);
370		ssid->passphrase = os_malloc(len + 1);
371		if (ssid->passphrase == NULL)
372			return -1;
373		os_memcpy(ssid->passphrase, value, len);
374		ssid->passphrase[len] = '\0';
375		return 0;
376#else /* CONFIG_NO_PBKDF2 */
377		wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
378			   "supported.", line);
379		return -1;
380#endif /* CONFIG_NO_PBKDF2 */
381	}
382
383	if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
384	    value[PMK_LEN * 2] != '\0') {
385		wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
386			   line, value);
387		return -1;
388	}
389
390	os_free(ssid->passphrase);
391	ssid->passphrase = NULL;
392
393	ssid->psk_set = 1;
394	wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
395	return 0;
396}
397
398
399#ifndef NO_CONFIG_WRITE
400static char * wpa_config_write_psk(const struct parse_data *data,
401				   struct wpa_ssid *ssid)
402{
403	if (ssid->passphrase)
404		return wpa_config_write_string_ascii(
405			(const u8 *) ssid->passphrase,
406			os_strlen(ssid->passphrase));
407
408	if (ssid->psk_set)
409		return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
410
411	return NULL;
412}
413#endif /* NO_CONFIG_WRITE */
414
415
416static int wpa_config_parse_proto(const struct parse_data *data,
417				  struct wpa_ssid *ssid, int line,
418				  const char *value)
419{
420	int val = 0, last, errors = 0;
421	char *start, *end, *buf;
422
423	buf = os_strdup(value);
424	if (buf == NULL)
425		return -1;
426	start = buf;
427
428	while (*start != '\0') {
429		while (*start == ' ' || *start == '\t')
430			start++;
431		if (*start == '\0')
432			break;
433		end = start;
434		while (*end != ' ' && *end != '\t' && *end != '\0')
435			end++;
436		last = *end == '\0';
437		*end = '\0';
438		if (os_strcmp(start, "WPA") == 0)
439			val |= WPA_PROTO_WPA;
440		else if (os_strcmp(start, "RSN") == 0 ||
441			 os_strcmp(start, "WPA2") == 0)
442			val |= WPA_PROTO_RSN;
443		else {
444			wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
445				   line, start);
446			errors++;
447		}
448
449		if (last)
450			break;
451		start = end + 1;
452	}
453	os_free(buf);
454
455	if (val == 0) {
456		wpa_printf(MSG_ERROR,
457			   "Line %d: no proto values configured.", line);
458		errors++;
459	}
460
461	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
462	ssid->proto = val;
463	return errors ? -1 : 0;
464}
465
466
467#ifndef NO_CONFIG_WRITE
468static char * wpa_config_write_proto(const struct parse_data *data,
469				     struct wpa_ssid *ssid)
470{
471	int first = 1, ret;
472	char *buf, *pos, *end;
473
474	pos = buf = os_zalloc(10);
475	if (buf == NULL)
476		return NULL;
477	end = buf + 10;
478
479	if (ssid->proto & WPA_PROTO_WPA) {
480		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
481		if (ret < 0 || ret >= end - pos)
482			return buf;
483		pos += ret;
484		first = 0;
485	}
486
487	if (ssid->proto & WPA_PROTO_RSN) {
488		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
489		if (ret < 0 || ret >= end - pos)
490			return buf;
491		pos += ret;
492		first = 0;
493	}
494
495	return buf;
496}
497#endif /* NO_CONFIG_WRITE */
498
499
500static int wpa_config_parse_key_mgmt(const struct parse_data *data,
501				     struct wpa_ssid *ssid, int line,
502				     const char *value)
503{
504	int val = 0, last, errors = 0;
505	char *start, *end, *buf;
506
507	buf = os_strdup(value);
508	if (buf == NULL)
509		return -1;
510	start = buf;
511
512	while (*start != '\0') {
513		while (*start == ' ' || *start == '\t')
514			start++;
515		if (*start == '\0')
516			break;
517		end = start;
518		while (*end != ' ' && *end != '\t' && *end != '\0')
519			end++;
520		last = *end == '\0';
521		*end = '\0';
522		if (os_strcmp(start, "WPA-PSK") == 0)
523			val |= WPA_KEY_MGMT_PSK;
524		else if (os_strcmp(start, "WPA-EAP") == 0)
525			val |= WPA_KEY_MGMT_IEEE8021X;
526		else if (os_strcmp(start, "IEEE8021X") == 0)
527			val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
528		else if (os_strcmp(start, "NONE") == 0)
529			val |= WPA_KEY_MGMT_NONE;
530		else if (os_strcmp(start, "WPA-NONE") == 0)
531			val |= WPA_KEY_MGMT_WPA_NONE;
532#ifdef CONFIG_IEEE80211R
533		else if (os_strcmp(start, "FT-PSK") == 0)
534			val |= WPA_KEY_MGMT_FT_PSK;
535		else if (os_strcmp(start, "FT-EAP") == 0)
536			val |= WPA_KEY_MGMT_FT_IEEE8021X;
537#endif /* CONFIG_IEEE80211R */
538#ifdef CONFIG_IEEE80211W
539		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
540			val |= WPA_KEY_MGMT_PSK_SHA256;
541		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
542			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
543#endif /* CONFIG_IEEE80211W */
544#ifdef CONFIG_WPS
545		else if (os_strcmp(start, "WPS") == 0)
546			val |= WPA_KEY_MGMT_WPS;
547#endif /* CONFIG_WPS */
548		else {
549			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
550				   line, start);
551			errors++;
552		}
553
554		if (last)
555			break;
556		start = end + 1;
557	}
558	os_free(buf);
559
560	if (val == 0) {
561		wpa_printf(MSG_ERROR,
562			   "Line %d: no key_mgmt values configured.", line);
563		errors++;
564	}
565
566	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
567	ssid->key_mgmt = val;
568	return errors ? -1 : 0;
569}
570
571
572#ifndef NO_CONFIG_WRITE
573static char * wpa_config_write_key_mgmt(const struct parse_data *data,
574					struct wpa_ssid *ssid)
575{
576	char *buf, *pos, *end;
577	int ret;
578
579	pos = buf = os_zalloc(50);
580	if (buf == NULL)
581		return NULL;
582	end = buf + 50;
583
584	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
585		ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
586				  pos == buf ? "" : " ");
587		if (ret < 0 || ret >= end - pos) {
588			end[-1] = '\0';
589			return buf;
590		}
591		pos += ret;
592	}
593
594	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
595		ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
596				  pos == buf ? "" : " ");
597		if (ret < 0 || ret >= end - pos) {
598			end[-1] = '\0';
599			return buf;
600		}
601		pos += ret;
602	}
603
604	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
605		ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
606				  pos == buf ? "" : " ");
607		if (ret < 0 || ret >= end - pos) {
608			end[-1] = '\0';
609			return buf;
610		}
611		pos += ret;
612	}
613
614	if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
615		ret = os_snprintf(pos, end - pos, "%sNONE",
616				  pos == buf ? "" : " ");
617		if (ret < 0 || ret >= end - pos) {
618			end[-1] = '\0';
619			return buf;
620		}
621		pos += ret;
622	}
623
624	if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
625		ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
626				  pos == buf ? "" : " ");
627		if (ret < 0 || ret >= end - pos) {
628			end[-1] = '\0';
629			return buf;
630		}
631		pos += ret;
632	}
633
634#ifdef CONFIG_IEEE80211R
635	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK)
636		pos += os_snprintf(pos, end - pos, "%sFT-PSK",
637				   pos == buf ? "" : " ");
638
639	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
640		pos += os_snprintf(pos, end - pos, "%sFT-EAP",
641				   pos == buf ? "" : " ");
642#endif /* CONFIG_IEEE80211R */
643
644#ifdef CONFIG_IEEE80211W
645	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
646		pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
647				   pos == buf ? "" : " ");
648
649	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
650		pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
651				   pos == buf ? "" : " ");
652#endif /* CONFIG_IEEE80211W */
653
654#ifdef CONFIG_WPS
655	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
656		pos += os_snprintf(pos, end - pos, "%sWPS",
657				   pos == buf ? "" : " ");
658#endif /* CONFIG_WPS */
659
660	return buf;
661}
662#endif /* NO_CONFIG_WRITE */
663
664
665static int wpa_config_parse_cipher(int line, const char *value)
666{
667	int val = 0, last;
668	char *start, *end, *buf;
669
670	buf = os_strdup(value);
671	if (buf == NULL)
672		return -1;
673	start = buf;
674
675	while (*start != '\0') {
676		while (*start == ' ' || *start == '\t')
677			start++;
678		if (*start == '\0')
679			break;
680		end = start;
681		while (*end != ' ' && *end != '\t' && *end != '\0')
682			end++;
683		last = *end == '\0';
684		*end = '\0';
685		if (os_strcmp(start, "CCMP") == 0)
686			val |= WPA_CIPHER_CCMP;
687		else if (os_strcmp(start, "TKIP") == 0)
688			val |= WPA_CIPHER_TKIP;
689		else if (os_strcmp(start, "WEP104") == 0)
690			val |= WPA_CIPHER_WEP104;
691		else if (os_strcmp(start, "WEP40") == 0)
692			val |= WPA_CIPHER_WEP40;
693		else if (os_strcmp(start, "NONE") == 0)
694			val |= WPA_CIPHER_NONE;
695		else {
696			wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
697				   line, start);
698			os_free(buf);
699			return -1;
700		}
701
702		if (last)
703			break;
704		start = end + 1;
705	}
706	os_free(buf);
707
708	if (val == 0) {
709		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
710			   line);
711		return -1;
712	}
713	return val;
714}
715
716
717#ifndef NO_CONFIG_WRITE
718static char * wpa_config_write_cipher(int cipher)
719{
720	char *buf, *pos, *end;
721	int ret;
722
723	pos = buf = os_zalloc(50);
724	if (buf == NULL)
725		return NULL;
726	end = buf + 50;
727
728	if (cipher & WPA_CIPHER_CCMP) {
729		ret = os_snprintf(pos, end - pos, "%sCCMP",
730				  pos == buf ? "" : " ");
731		if (ret < 0 || ret >= end - pos) {
732			end[-1] = '\0';
733			return buf;
734		}
735		pos += ret;
736	}
737
738	if (cipher & WPA_CIPHER_TKIP) {
739		ret = os_snprintf(pos, end - pos, "%sTKIP",
740				  pos == buf ? "" : " ");
741		if (ret < 0 || ret >= end - pos) {
742			end[-1] = '\0';
743			return buf;
744		}
745		pos += ret;
746	}
747
748	if (cipher & WPA_CIPHER_WEP104) {
749		ret = os_snprintf(pos, end - pos, "%sWEP104",
750				  pos == buf ? "" : " ");
751		if (ret < 0 || ret >= end - pos) {
752			end[-1] = '\0';
753			return buf;
754		}
755		pos += ret;
756	}
757
758	if (cipher & WPA_CIPHER_WEP40) {
759		ret = os_snprintf(pos, end - pos, "%sWEP40",
760				  pos == buf ? "" : " ");
761		if (ret < 0 || ret >= end - pos) {
762			end[-1] = '\0';
763			return buf;
764		}
765		pos += ret;
766	}
767
768	if (cipher & WPA_CIPHER_NONE) {
769		ret = os_snprintf(pos, end - pos, "%sNONE",
770				  pos == buf ? "" : " ");
771		if (ret < 0 || ret >= end - pos) {
772			end[-1] = '\0';
773			return buf;
774		}
775		pos += ret;
776	}
777
778	return buf;
779}
780#endif /* NO_CONFIG_WRITE */
781
782
783static int wpa_config_parse_pairwise(const struct parse_data *data,
784				     struct wpa_ssid *ssid, int line,
785				     const char *value)
786{
787	int val;
788	val = wpa_config_parse_cipher(line, value);
789	if (val == -1)
790		return -1;
791	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
792		wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
793			   "(0x%x).", line, val);
794		return -1;
795	}
796
797	wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
798	ssid->pairwise_cipher = val;
799	return 0;
800}
801
802
803#ifndef NO_CONFIG_WRITE
804static char * wpa_config_write_pairwise(const struct parse_data *data,
805					struct wpa_ssid *ssid)
806{
807	return wpa_config_write_cipher(ssid->pairwise_cipher);
808}
809#endif /* NO_CONFIG_WRITE */
810
811
812static int wpa_config_parse_group(const struct parse_data *data,
813				  struct wpa_ssid *ssid, int line,
814				  const char *value)
815{
816	int val;
817	val = wpa_config_parse_cipher(line, value);
818	if (val == -1)
819		return -1;
820	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
821		    WPA_CIPHER_WEP40)) {
822		wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
823			   "(0x%x).", line, val);
824		return -1;
825	}
826
827	wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
828	ssid->group_cipher = val;
829	return 0;
830}
831
832
833#ifndef NO_CONFIG_WRITE
834static char * wpa_config_write_group(const struct parse_data *data,
835				     struct wpa_ssid *ssid)
836{
837	return wpa_config_write_cipher(ssid->group_cipher);
838}
839#endif /* NO_CONFIG_WRITE */
840
841
842static int wpa_config_parse_auth_alg(const struct parse_data *data,
843				     struct wpa_ssid *ssid, int line,
844				     const char *value)
845{
846	int val = 0, last, errors = 0;
847	char *start, *end, *buf;
848
849	buf = os_strdup(value);
850	if (buf == NULL)
851		return -1;
852	start = buf;
853
854	while (*start != '\0') {
855		while (*start == ' ' || *start == '\t')
856			start++;
857		if (*start == '\0')
858			break;
859		end = start;
860		while (*end != ' ' && *end != '\t' && *end != '\0')
861			end++;
862		last = *end == '\0';
863		*end = '\0';
864		if (os_strcmp(start, "OPEN") == 0)
865			val |= WPA_AUTH_ALG_OPEN;
866		else if (os_strcmp(start, "SHARED") == 0)
867			val |= WPA_AUTH_ALG_SHARED;
868		else if (os_strcmp(start, "LEAP") == 0)
869			val |= WPA_AUTH_ALG_LEAP;
870		else {
871			wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
872				   line, start);
873			errors++;
874		}
875
876		if (last)
877			break;
878		start = end + 1;
879	}
880	os_free(buf);
881
882	if (val == 0) {
883		wpa_printf(MSG_ERROR,
884			   "Line %d: no auth_alg values configured.", line);
885		errors++;
886	}
887
888	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
889	ssid->auth_alg = val;
890	return errors ? -1 : 0;
891}
892
893
894#ifndef NO_CONFIG_WRITE
895static char * wpa_config_write_auth_alg(const struct parse_data *data,
896					struct wpa_ssid *ssid)
897{
898	char *buf, *pos, *end;
899	int ret;
900
901	pos = buf = os_zalloc(30);
902	if (buf == NULL)
903		return NULL;
904	end = buf + 30;
905
906	if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
907		ret = os_snprintf(pos, end - pos, "%sOPEN",
908				  pos == buf ? "" : " ");
909		if (ret < 0 || ret >= end - pos) {
910			end[-1] = '\0';
911			return buf;
912		}
913		pos += ret;
914	}
915
916	if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
917		ret = os_snprintf(pos, end - pos, "%sSHARED",
918				  pos == buf ? "" : " ");
919		if (ret < 0 || ret >= end - pos) {
920			end[-1] = '\0';
921			return buf;
922		}
923		pos += ret;
924	}
925
926	if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
927		ret = os_snprintf(pos, end - pos, "%sLEAP",
928				  pos == buf ? "" : " ");
929		if (ret < 0 || ret >= end - pos) {
930			end[-1] = '\0';
931			return buf;
932		}
933		pos += ret;
934	}
935
936	return buf;
937}
938#endif /* NO_CONFIG_WRITE */
939
940
941static int * wpa_config_parse_freqs(const struct parse_data *data,
942				    struct wpa_ssid *ssid, int line,
943				    const char *value)
944{
945	int *freqs;
946	size_t used, len;
947	const char *pos;
948
949	used = 0;
950	len = 10;
951	freqs = os_zalloc((len + 1) * sizeof(int));
952	if (freqs == NULL)
953		return NULL;
954
955	pos = value;
956	while (pos) {
957		while (*pos == ' ')
958			pos++;
959		if (used == len) {
960			int *n;
961			size_t i;
962			n = os_realloc(freqs, (len * 2 + 1) * sizeof(int));
963			if (n == NULL) {
964				os_free(freqs);
965				return NULL;
966			}
967			for (i = len; i <= len * 2; i++)
968				n[i] = 0;
969			freqs = n;
970			len *= 2;
971		}
972
973		freqs[used] = atoi(pos);
974		if (freqs[used] == 0)
975			break;
976		used++;
977		pos = os_strchr(pos + 1, ' ');
978	}
979
980	return freqs;
981}
982
983
984static int wpa_config_parse_scan_freq(const struct parse_data *data,
985				      struct wpa_ssid *ssid, int line,
986				      const char *value)
987{
988	int *freqs;
989
990	freqs = wpa_config_parse_freqs(data, ssid, line, value);
991	if (freqs == NULL)
992		return -1;
993	os_free(ssid->scan_freq);
994	ssid->scan_freq = freqs;
995
996	return 0;
997}
998
999
1000static int wpa_config_parse_freq_list(const struct parse_data *data,
1001				      struct wpa_ssid *ssid, int line,
1002				      const char *value)
1003{
1004	int *freqs;
1005
1006	freqs = wpa_config_parse_freqs(data, ssid, line, value);
1007	if (freqs == NULL)
1008		return -1;
1009	os_free(ssid->freq_list);
1010	ssid->freq_list = freqs;
1011
1012	return 0;
1013}
1014
1015
1016#ifndef NO_CONFIG_WRITE
1017static char * wpa_config_write_freqs(const struct parse_data *data,
1018				     const int *freqs)
1019{
1020	char *buf, *pos, *end;
1021	int i, ret;
1022	size_t count;
1023
1024	if (freqs == NULL)
1025		return NULL;
1026
1027	count = 0;
1028	for (i = 0; freqs[i]; i++)
1029		count++;
1030
1031	pos = buf = os_zalloc(10 * count + 1);
1032	if (buf == NULL)
1033		return NULL;
1034	end = buf + 10 * count + 1;
1035
1036	for (i = 0; freqs[i]; i++) {
1037		ret = os_snprintf(pos, end - pos, "%s%u",
1038				  i == 0 ? "" : " ", freqs[i]);
1039		if (ret < 0 || ret >= end - pos) {
1040			end[-1] = '\0';
1041			return buf;
1042		}
1043		pos += ret;
1044	}
1045
1046	return buf;
1047}
1048
1049
1050static char * wpa_config_write_scan_freq(const struct parse_data *data,
1051					 struct wpa_ssid *ssid)
1052{
1053	return wpa_config_write_freqs(data, ssid->scan_freq);
1054}
1055
1056
1057static char * wpa_config_write_freq_list(const struct parse_data *data,
1058					 struct wpa_ssid *ssid)
1059{
1060	return wpa_config_write_freqs(data, ssid->freq_list);
1061}
1062#endif /* NO_CONFIG_WRITE */
1063
1064
1065#ifdef IEEE8021X_EAPOL
1066static int wpa_config_parse_eap(const struct parse_data *data,
1067				struct wpa_ssid *ssid, int line,
1068				const char *value)
1069{
1070	int last, errors = 0;
1071	char *start, *end, *buf;
1072	struct eap_method_type *methods = NULL, *tmp;
1073	size_t num_methods = 0;
1074
1075	buf = os_strdup(value);
1076	if (buf == NULL)
1077		return -1;
1078	start = buf;
1079
1080	while (*start != '\0') {
1081		while (*start == ' ' || *start == '\t')
1082			start++;
1083		if (*start == '\0')
1084			break;
1085		end = start;
1086		while (*end != ' ' && *end != '\t' && *end != '\0')
1087			end++;
1088		last = *end == '\0';
1089		*end = '\0';
1090		tmp = methods;
1091		methods = os_realloc(methods,
1092				     (num_methods + 1) * sizeof(*methods));
1093		if (methods == NULL) {
1094			os_free(tmp);
1095			os_free(buf);
1096			return -1;
1097		}
1098		methods[num_methods].method = eap_peer_get_type(
1099			start, &methods[num_methods].vendor);
1100		if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
1101		    methods[num_methods].method == EAP_TYPE_NONE) {
1102			wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
1103				   "'%s'", line, start);
1104			wpa_printf(MSG_ERROR, "You may need to add support for"
1105				   " this EAP method during wpa_supplicant\n"
1106				   "build time configuration.\n"
1107				   "See README for more information.");
1108			errors++;
1109		} else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
1110			   methods[num_methods].method == EAP_TYPE_LEAP)
1111			ssid->leap++;
1112		else
1113			ssid->non_leap++;
1114		num_methods++;
1115		if (last)
1116			break;
1117		start = end + 1;
1118	}
1119	os_free(buf);
1120
1121	tmp = methods;
1122	methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods));
1123	if (methods == NULL) {
1124		os_free(tmp);
1125		return -1;
1126	}
1127	methods[num_methods].vendor = EAP_VENDOR_IETF;
1128	methods[num_methods].method = EAP_TYPE_NONE;
1129	num_methods++;
1130
1131	wpa_hexdump(MSG_MSGDUMP, "eap methods",
1132		    (u8 *) methods, num_methods * sizeof(*methods));
1133	ssid->eap.eap_methods = methods;
1134	return errors ? -1 : 0;
1135}
1136
1137
1138static char * wpa_config_write_eap(const struct parse_data *data,
1139				   struct wpa_ssid *ssid)
1140{
1141	int i, ret;
1142	char *buf, *pos, *end;
1143	const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
1144	const char *name;
1145
1146	if (eap_methods == NULL)
1147		return NULL;
1148
1149	pos = buf = os_zalloc(100);
1150	if (buf == NULL)
1151		return NULL;
1152	end = buf + 100;
1153
1154	for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
1155		     eap_methods[i].method != EAP_TYPE_NONE; i++) {
1156		name = eap_get_name(eap_methods[i].vendor,
1157				    eap_methods[i].method);
1158		if (name) {
1159			ret = os_snprintf(pos, end - pos, "%s%s",
1160					  pos == buf ? "" : " ", name);
1161			if (ret < 0 || ret >= end - pos)
1162				break;
1163			pos += ret;
1164		}
1165	}
1166
1167	end[-1] = '\0';
1168
1169	return buf;
1170}
1171
1172
1173static int wpa_config_parse_password(const struct parse_data *data,
1174				     struct wpa_ssid *ssid, int line,
1175				     const char *value)
1176{
1177	u8 *hash;
1178
1179	if (os_strcmp(value, "NULL") == 0) {
1180		wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
1181		os_free(ssid->eap.password);
1182		ssid->eap.password = NULL;
1183		ssid->eap.password_len = 0;
1184		return 0;
1185	}
1186
1187	if (os_strncmp(value, "hash:", 5) != 0) {
1188		char *tmp;
1189		size_t res_len;
1190
1191		tmp = wpa_config_parse_string(value, &res_len);
1192		if (tmp == NULL) {
1193			wpa_printf(MSG_ERROR, "Line %d: failed to parse "
1194				   "password.", line);
1195			return -1;
1196		}
1197		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
1198				      (u8 *) tmp, res_len);
1199
1200		os_free(ssid->eap.password);
1201		ssid->eap.password = (u8 *) tmp;
1202		ssid->eap.password_len = res_len;
1203		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1204
1205		return 0;
1206	}
1207
1208
1209	/* NtPasswordHash: hash:<32 hex digits> */
1210	if (os_strlen(value + 5) != 2 * 16) {
1211		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
1212			   "(expected 32 hex digits)", line);
1213		return -1;
1214	}
1215
1216	hash = os_malloc(16);
1217	if (hash == NULL)
1218		return -1;
1219
1220	if (hexstr2bin(value + 5, hash, 16)) {
1221		os_free(hash);
1222		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
1223		return -1;
1224	}
1225
1226	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
1227
1228	os_free(ssid->eap.password);
1229	ssid->eap.password = hash;
1230	ssid->eap.password_len = 16;
1231	ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1232
1233	return 0;
1234}
1235
1236
1237static char * wpa_config_write_password(const struct parse_data *data,
1238					struct wpa_ssid *ssid)
1239{
1240	char *buf;
1241
1242	if (ssid->eap.password == NULL)
1243		return NULL;
1244
1245	if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
1246		return wpa_config_write_string(
1247			ssid->eap.password, ssid->eap.password_len);
1248	}
1249
1250	buf = os_malloc(5 + 32 + 1);
1251	if (buf == NULL)
1252		return NULL;
1253
1254	os_memcpy(buf, "hash:", 5);
1255	wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
1256
1257	return buf;
1258}
1259#endif /* IEEE8021X_EAPOL */
1260
1261
1262static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
1263				    const char *value, int idx)
1264{
1265	char *buf, title[20];
1266	int res;
1267
1268	buf = wpa_config_parse_string(value, len);
1269	if (buf == NULL) {
1270		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
1271			   line, idx, value);
1272		return -1;
1273	}
1274	if (*len > MAX_WEP_KEY_LEN) {
1275		wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
1276			   line, idx, value);
1277		os_free(buf);
1278		return -1;
1279	}
1280	os_memcpy(key, buf, *len);
1281	os_free(buf);
1282	res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
1283	if (res >= 0 && (size_t) res < sizeof(title))
1284		wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
1285	return 0;
1286}
1287
1288
1289static int wpa_config_parse_wep_key0(const struct parse_data *data,
1290				     struct wpa_ssid *ssid, int line,
1291				     const char *value)
1292{
1293	return wpa_config_parse_wep_key(ssid->wep_key[0],
1294					&ssid->wep_key_len[0], line,
1295					value, 0);
1296}
1297
1298
1299static int wpa_config_parse_wep_key1(const struct parse_data *data,
1300				     struct wpa_ssid *ssid, int line,
1301				     const char *value)
1302{
1303	return wpa_config_parse_wep_key(ssid->wep_key[1],
1304					&ssid->wep_key_len[1], line,
1305					value, 1);
1306}
1307
1308
1309static int wpa_config_parse_wep_key2(const struct parse_data *data,
1310				     struct wpa_ssid *ssid, int line,
1311				     const char *value)
1312{
1313	return wpa_config_parse_wep_key(ssid->wep_key[2],
1314					&ssid->wep_key_len[2], line,
1315					value, 2);
1316}
1317
1318
1319static int wpa_config_parse_wep_key3(const struct parse_data *data,
1320				     struct wpa_ssid *ssid, int line,
1321				     const char *value)
1322{
1323	return wpa_config_parse_wep_key(ssid->wep_key[3],
1324					&ssid->wep_key_len[3], line,
1325					value, 3);
1326}
1327
1328
1329#ifndef NO_CONFIG_WRITE
1330static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
1331{
1332	if (ssid->wep_key_len[idx] == 0)
1333		return NULL;
1334	return wpa_config_write_string(ssid->wep_key[idx],
1335				       ssid->wep_key_len[idx]);
1336}
1337
1338
1339static char * wpa_config_write_wep_key0(const struct parse_data *data,
1340					struct wpa_ssid *ssid)
1341{
1342	return wpa_config_write_wep_key(ssid, 0);
1343}
1344
1345
1346static char * wpa_config_write_wep_key1(const struct parse_data *data,
1347					struct wpa_ssid *ssid)
1348{
1349	return wpa_config_write_wep_key(ssid, 1);
1350}
1351
1352
1353static char * wpa_config_write_wep_key2(const struct parse_data *data,
1354					struct wpa_ssid *ssid)
1355{
1356	return wpa_config_write_wep_key(ssid, 2);
1357}
1358
1359
1360static char * wpa_config_write_wep_key3(const struct parse_data *data,
1361					struct wpa_ssid *ssid)
1362{
1363	return wpa_config_write_wep_key(ssid, 3);
1364}
1365#endif /* NO_CONFIG_WRITE */
1366
1367
1368#ifdef CONFIG_P2P
1369
1370static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
1371					    struct wpa_ssid *ssid, int line,
1372					    const char *value)
1373{
1374	const char *pos;
1375	u8 *buf, *n, addr[ETH_ALEN];
1376	size_t count;
1377
1378	buf = NULL;
1379	count = 0;
1380
1381	pos = value;
1382	while (pos && *pos) {
1383		while (*pos == ' ')
1384			pos++;
1385
1386		if (hwaddr_aton(pos, addr)) {
1387			wpa_printf(MSG_ERROR, "Line %d: Invalid "
1388				   "p2p_client_list address '%s'.",
1389				   line, value);
1390			/* continue anyway */
1391		} else {
1392			n = os_realloc(buf, (count + 1) * ETH_ALEN);
1393			if (n == NULL) {
1394				os_free(buf);
1395				return -1;
1396			}
1397			buf = n;
1398			os_memcpy(buf + count * ETH_ALEN, addr, ETH_ALEN);
1399			count++;
1400			wpa_hexdump(MSG_MSGDUMP, "p2p_client_list",
1401				    addr, ETH_ALEN);
1402		}
1403
1404		pos = os_strchr(pos, ' ');
1405	}
1406
1407	os_free(ssid->p2p_client_list);
1408	ssid->p2p_client_list = buf;
1409	ssid->num_p2p_clients = count;
1410
1411	return 0;
1412}
1413
1414
1415#ifndef NO_CONFIG_WRITE
1416static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
1417					       struct wpa_ssid *ssid)
1418{
1419	char *value, *end, *pos;
1420	int res;
1421	size_t i;
1422
1423	if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0)
1424		return NULL;
1425
1426	value = os_malloc(20 * ssid->num_p2p_clients);
1427	if (value == NULL)
1428		return NULL;
1429	pos = value;
1430	end = value + 20 * ssid->num_p2p_clients;
1431
1432	for (i = 0; i < ssid->num_p2p_clients; i++) {
1433		res = os_snprintf(pos, end - pos, MACSTR " ",
1434				  MAC2STR(ssid->p2p_client_list +
1435					  i * ETH_ALEN));
1436		if (res < 0 || res >= end - pos) {
1437			os_free(value);
1438			return NULL;
1439		}
1440		pos += res;
1441	}
1442
1443	if (pos > value)
1444		pos[-1] = '\0';
1445
1446	return value;
1447}
1448#endif /* NO_CONFIG_WRITE */
1449
1450#endif /* CONFIG_P2P */
1451
1452/* Helper macros for network block parser */
1453
1454#ifdef OFFSET
1455#undef OFFSET
1456#endif /* OFFSET */
1457/* OFFSET: Get offset of a variable within the wpa_ssid structure */
1458#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
1459
1460/* STR: Define a string variable for an ASCII string; f = field name */
1461#ifdef NO_CONFIG_WRITE
1462#define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
1463#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
1464#else /* NO_CONFIG_WRITE */
1465#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
1466#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
1467#endif /* NO_CONFIG_WRITE */
1468#define STR(f) _STR(f), NULL, NULL, NULL, 0
1469#define STRe(f) _STRe(f), NULL, NULL, NULL, 0
1470#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
1471#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
1472
1473/* STR_LEN: Define a string variable with a separate variable for storing the
1474 * data length. Unlike STR(), this can be used to store arbitrary binary data
1475 * (i.e., even nul termination character). */
1476#define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
1477#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
1478#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
1479#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
1480#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
1481
1482/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
1483 * explicitly specified. */
1484#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
1485#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
1486#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
1487
1488#ifdef NO_CONFIG_WRITE
1489#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
1490#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
1491#else /* NO_CONFIG_WRITE */
1492#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1493	OFFSET(f), (void *) 0
1494#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1495	OFFSET(eap.f), (void *) 0
1496#ifdef WPA_UNICODE_SSID
1497/* STR_* variants that do not force conversion to ASCII */
1498#define _STR_UNICODE(f) #f, wpa_config_parse_str, wpa_config_write_str_unicode, OFFSET(f)
1499#define STR_UNICODE(f) _STR_UNICODE(f), NULL, NULL, NULL, 0
1500#define _STR_LEN_UNICODE(f) _STR_UNICODE(f), OFFSET(f ## _len)
1501#define STR_LEN_UNICODE(f) _STR_LEN_UNICODE(f), NULL, NULL, 0
1502#define _STR_RANGE_UNICODE(f, min, max) _STR_LEN_UNICODE(f), (void *) (min), (void *) (max)
1503#define STR_RANGE_UNICODE(f, min, max) _STR_RANGE_UNICODE(f, min, max), 0
1504#endif
1505#endif /* NO_CONFIG_WRITE */
1506
1507/* INT: Define an integer variable */
1508#define INT(f) _INT(f), NULL, NULL, 0
1509#define INTe(f) _INTe(f), NULL, NULL, 0
1510
1511/* INT_RANGE: Define an integer variable with allowed value range */
1512#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
1513
1514/* FUNC: Define a configuration variable that uses a custom function for
1515 * parsing and writing the value. */
1516#ifdef NO_CONFIG_WRITE
1517#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
1518#else /* NO_CONFIG_WRITE */
1519#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
1520	NULL, NULL, NULL, NULL
1521#endif /* NO_CONFIG_WRITE */
1522#define FUNC(f) _FUNC(f), 0
1523#define FUNC_KEY(f) _FUNC(f), 1
1524
1525/*
1526 * Table of network configuration variables. This table is used to parse each
1527 * network configuration variable, e.g., each line in wpa_supplicant.conf file
1528 * that is inside a network block.
1529 *
1530 * This table is generated using the helper macros defined above and with
1531 * generous help from the C pre-processor. The field name is stored as a string
1532 * into .name and for STR and INT types, the offset of the target buffer within
1533 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
1534 * offset to the field containing the length of the configuration variable.
1535 * .param3 and .param4 can be used to mark the allowed range (length for STR
1536 * and value for INT).
1537 *
1538 * For each configuration line in wpa_supplicant.conf, the parser goes through
1539 * this table and select the entry that matches with the field name. The parser
1540 * function (.parser) is then called to parse the actual value of the field.
1541 *
1542 * This kind of mechanism makes it easy to add new configuration parameters,
1543 * since only one line needs to be added into this table and into the
1544 * struct wpa_ssid definition if the new variable is either a string or
1545 * integer. More complex types will need to use their own parser and writer
1546 * functions.
1547 */
1548static const struct parse_data ssid_fields[] = {
1549#ifdef WPA_UNICODE_SSID
1550	{ STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) },
1551#else
1552	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1553#endif
1554	{ INT_RANGE(scan_ssid, 0, 1) },
1555	{ FUNC(bssid) },
1556	{ FUNC_KEY(psk) },
1557	{ FUNC(proto) },
1558	{ FUNC(key_mgmt) },
1559	{ FUNC(pairwise) },
1560	{ FUNC(group) },
1561	{ FUNC(auth_alg) },
1562	{ FUNC(scan_freq) },
1563	{ FUNC(freq_list) },
1564#ifdef IEEE8021X_EAPOL
1565	{ FUNC(eap) },
1566	{ STR_LENe(identity) },
1567	{ STR_LENe(anonymous_identity) },
1568	{ FUNC_KEY(password) },
1569	{ STRe(ca_cert) },
1570	{ STRe(ca_path) },
1571	{ STRe(client_cert) },
1572	{ STRe(private_key) },
1573	{ STR_KEYe(private_key_passwd) },
1574	{ STRe(dh_file) },
1575	{ STRe(subject_match) },
1576	{ STRe(altsubject_match) },
1577	{ STRe(ca_cert2) },
1578	{ STRe(ca_path2) },
1579	{ STRe(client_cert2) },
1580	{ STRe(private_key2) },
1581	{ STR_KEYe(private_key2_passwd) },
1582	{ STRe(dh_file2) },
1583	{ STRe(subject_match2) },
1584	{ STRe(altsubject_match2) },
1585	{ STRe(phase1) },
1586	{ STRe(phase2) },
1587	{ STRe(pcsc) },
1588	{ STR_KEYe(pin) },
1589	{ STRe(engine_id) },
1590	{ STRe(key_id) },
1591	{ STRe(cert_id) },
1592	{ STRe(ca_cert_id) },
1593	{ STR_KEYe(pin2) },
1594	{ STRe(engine2_id) },
1595	{ STRe(key2_id) },
1596	{ STRe(cert2_id) },
1597	{ STRe(ca_cert2_id) },
1598	{ INTe(engine) },
1599	{ INTe(engine2) },
1600	{ INT(eapol_flags) },
1601#endif /* IEEE8021X_EAPOL */
1602	{ FUNC_KEY(wep_key0) },
1603	{ FUNC_KEY(wep_key1) },
1604	{ FUNC_KEY(wep_key2) },
1605	{ FUNC_KEY(wep_key3) },
1606	{ INT(wep_tx_keyidx) },
1607	{ INT(priority) },
1608#ifdef IEEE8021X_EAPOL
1609	{ INT(eap_workaround) },
1610	{ STRe(pac_file) },
1611	{ INTe(fragment_size) },
1612#endif /* IEEE8021X_EAPOL */
1613	{ INT_RANGE(mode, 0, 4) },
1614	{ INT_RANGE(proactive_key_caching, 0, 1) },
1615	{ INT_RANGE(disabled, 0, 2) },
1616	{ STR(id_str) },
1617#ifdef CONFIG_IEEE80211W
1618	{ INT_RANGE(ieee80211w, 0, 2) },
1619#endif /* CONFIG_IEEE80211W */
1620	{ INT_RANGE(peerkey, 0, 1) },
1621	{ INT_RANGE(mixed_cell, 0, 1) },
1622	{ INT_RANGE(frequency, 0, 10000) },
1623	{ INT(wpa_ptk_rekey) },
1624	{ STR(bgscan) },
1625#ifdef CONFIG_P2P
1626	{ FUNC(p2p_client_list) },
1627#endif /* CONFIG_P2P */
1628#ifdef CONFIG_HT_OVERRIDES
1629	{ INT_RANGE(disable_ht, 0, 1) },
1630	{ INT_RANGE(disable_ht40, -1, 1) },
1631	{ INT_RANGE(disable_max_amsdu, -1, 1) },
1632	{ INT_RANGE(ampdu_factor, -1, 3) },
1633	{ INT_RANGE(ampdu_density, -1, 7) },
1634	{ STR(ht_mcs) },
1635#endif /* CONFIG_HT_OVERRIDES */
1636};
1637
1638#ifdef WPA_UNICODE_SSID
1639#undef _STR_UNICODE
1640#undef STR_UNICODE
1641#undef _STR_LEN_UNICODE
1642#undef STR_LEN_UNICODE
1643#undef _STR_RANGE_UNICODE
1644#undef STR_RANGE_UNICODE
1645#endif
1646
1647#undef OFFSET
1648#undef _STR
1649#undef STR
1650#undef STR_KEY
1651#undef _STR_LEN
1652#undef STR_LEN
1653#undef STR_LEN_KEY
1654#undef _STR_RANGE
1655#undef STR_RANGE
1656#undef STR_RANGE_KEY
1657#undef _INT
1658#undef INT
1659#undef INT_RANGE
1660#undef _FUNC
1661#undef FUNC
1662#undef FUNC_KEY
1663#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1664
1665
1666/**
1667 * wpa_config_add_prio_network - Add a network to priority lists
1668 * @config: Configuration data from wpa_config_read()
1669 * @ssid: Pointer to the network configuration to be added to the list
1670 * Returns: 0 on success, -1 on failure
1671 *
1672 * This function is used to add a network block to the priority list of
1673 * networks. This must be called for each network when reading in the full
1674 * configuration. In addition, this can be used indirectly when updating
1675 * priorities by calling wpa_config_update_prio_list().
1676 */
1677int wpa_config_add_prio_network(struct wpa_config *config,
1678				struct wpa_ssid *ssid)
1679{
1680	int prio;
1681	struct wpa_ssid *prev, **nlist;
1682
1683	/*
1684	 * Add to an existing priority list if one is available for the
1685	 * configured priority level for this network.
1686	 */
1687	for (prio = 0; prio < config->num_prio; prio++) {
1688		prev = config->pssid[prio];
1689		if (prev->priority == ssid->priority) {
1690			while (prev->pnext)
1691				prev = prev->pnext;
1692			prev->pnext = ssid;
1693			return 0;
1694		}
1695	}
1696
1697	/* First network for this priority - add a new priority list */
1698	nlist = os_realloc(config->pssid,
1699			   (config->num_prio + 1) * sizeof(struct wpa_ssid *));
1700	if (nlist == NULL)
1701		return -1;
1702
1703	for (prio = 0; prio < config->num_prio; prio++) {
1704		if (nlist[prio]->priority < ssid->priority)
1705			break;
1706	}
1707
1708	os_memmove(&nlist[prio + 1], &nlist[prio],
1709		   (config->num_prio - prio) * sizeof(struct wpa_ssid *));
1710
1711	nlist[prio] = ssid;
1712	config->num_prio++;
1713	config->pssid = nlist;
1714
1715	return 0;
1716}
1717
1718
1719/**
1720 * wpa_config_update_prio_list - Update network priority list
1721 * @config: Configuration data from wpa_config_read()
1722 * Returns: 0 on success, -1 on failure
1723 *
1724 * This function is called to update the priority list of networks in the
1725 * configuration when a network is being added or removed. This is also called
1726 * if a priority for a network is changed.
1727 */
1728int wpa_config_update_prio_list(struct wpa_config *config)
1729{
1730	struct wpa_ssid *ssid;
1731	int ret = 0;
1732
1733	os_free(config->pssid);
1734	config->pssid = NULL;
1735	config->num_prio = 0;
1736
1737	ssid = config->ssid;
1738	while (ssid) {
1739		ssid->pnext = NULL;
1740		if (wpa_config_add_prio_network(config, ssid) < 0)
1741			ret = -1;
1742		ssid = ssid->next;
1743	}
1744
1745	return ret;
1746}
1747
1748
1749#ifdef IEEE8021X_EAPOL
1750static void eap_peer_config_free(struct eap_peer_config *eap)
1751{
1752	os_free(eap->eap_methods);
1753	os_free(eap->identity);
1754	os_free(eap->anonymous_identity);
1755	os_free(eap->password);
1756	os_free(eap->ca_cert);
1757	os_free(eap->ca_path);
1758	os_free(eap->client_cert);
1759	os_free(eap->private_key);
1760	os_free(eap->private_key_passwd);
1761	os_free(eap->dh_file);
1762	os_free(eap->subject_match);
1763	os_free(eap->altsubject_match);
1764	os_free(eap->ca_cert2);
1765	os_free(eap->ca_path2);
1766	os_free(eap->client_cert2);
1767	os_free(eap->private_key2);
1768	os_free(eap->private_key2_passwd);
1769	os_free(eap->dh_file2);
1770	os_free(eap->subject_match2);
1771	os_free(eap->altsubject_match2);
1772	os_free(eap->phase1);
1773	os_free(eap->phase2);
1774	os_free(eap->pcsc);
1775	os_free(eap->pin);
1776	os_free(eap->engine_id);
1777	os_free(eap->key_id);
1778	os_free(eap->cert_id);
1779	os_free(eap->ca_cert_id);
1780	os_free(eap->key2_id);
1781	os_free(eap->cert2_id);
1782	os_free(eap->ca_cert2_id);
1783	os_free(eap->pin2);
1784	os_free(eap->engine2_id);
1785	os_free(eap->otp);
1786	os_free(eap->pending_req_otp);
1787	os_free(eap->pac_file);
1788	os_free(eap->new_password);
1789}
1790#endif /* IEEE8021X_EAPOL */
1791
1792
1793/**
1794 * wpa_config_free_ssid - Free network/ssid configuration data
1795 * @ssid: Configuration data for the network
1796 *
1797 * This function frees all resources allocated for the network configuration
1798 * data.
1799 */
1800void wpa_config_free_ssid(struct wpa_ssid *ssid)
1801{
1802	os_free(ssid->ssid);
1803	os_free(ssid->passphrase);
1804#ifdef IEEE8021X_EAPOL
1805	eap_peer_config_free(&ssid->eap);
1806#endif /* IEEE8021X_EAPOL */
1807	os_free(ssid->id_str);
1808	os_free(ssid->scan_freq);
1809	os_free(ssid->freq_list);
1810	os_free(ssid->bgscan);
1811	os_free(ssid->p2p_client_list);
1812#ifdef CONFIG_HT_OVERRIDES
1813	os_free(ssid->ht_mcs);
1814#endif /* CONFIG_HT_OVERRIDES */
1815	os_free(ssid);
1816}
1817
1818
1819/**
1820 * wpa_config_free - Free configuration data
1821 * @config: Configuration data from wpa_config_read()
1822 *
1823 * This function frees all resources allocated for the configuration data by
1824 * wpa_config_read().
1825 */
1826void wpa_config_free(struct wpa_config *config)
1827{
1828#ifndef CONFIG_NO_CONFIG_BLOBS
1829	struct wpa_config_blob *blob, *prevblob;
1830#endif /* CONFIG_NO_CONFIG_BLOBS */
1831	struct wpa_ssid *ssid, *prev = NULL;
1832
1833	ssid = config->ssid;
1834	while (ssid) {
1835		prev = ssid;
1836		ssid = ssid->next;
1837		wpa_config_free_ssid(prev);
1838	}
1839
1840#ifndef CONFIG_NO_CONFIG_BLOBS
1841	blob = config->blobs;
1842	prevblob = NULL;
1843	while (blob) {
1844		prevblob = blob;
1845		blob = blob->next;
1846		wpa_config_free_blob(prevblob);
1847	}
1848#endif /* CONFIG_NO_CONFIG_BLOBS */
1849
1850	os_free(config->ctrl_interface);
1851	os_free(config->ctrl_interface_group);
1852	os_free(config->opensc_engine_path);
1853	os_free(config->pkcs11_engine_path);
1854	os_free(config->pkcs11_module_path);
1855	os_free(config->driver_param);
1856	os_free(config->device_name);
1857	os_free(config->manufacturer);
1858	os_free(config->model_name);
1859	os_free(config->model_number);
1860	os_free(config->serial_number);
1861	os_free(config->config_methods);
1862	os_free(config->p2p_ssid_postfix);
1863	os_free(config->pssid);
1864	os_free(config->home_realm);
1865	os_free(config->home_username);
1866	os_free(config->home_password);
1867	os_free(config->home_ca_cert);
1868	os_free(config->home_imsi);
1869	os_free(config->home_milenage);
1870#ifdef ANDROID_P2P
1871	os_free(config->prioritize);
1872#endif
1873	os_free(config);
1874}
1875
1876
1877/**
1878 * wpa_config_foreach_network - Iterate over each configured network
1879 * @config: Configuration data from wpa_config_read()
1880 * @func: Callback function to process each network
1881 * @arg: Opaque argument to pass to callback function
1882 *
1883 * Iterate over the set of configured networks calling the specified
1884 * function for each item. We guard against callbacks removing the
1885 * supplied network.
1886 */
1887void wpa_config_foreach_network(struct wpa_config *config,
1888				void (*func)(void *, struct wpa_ssid *),
1889				void *arg)
1890{
1891	struct wpa_ssid *ssid, *next;
1892
1893	ssid = config->ssid;
1894	while (ssid) {
1895		next = ssid->next;
1896		func(arg, ssid);
1897		ssid = next;
1898	}
1899}
1900
1901
1902/**
1903 * wpa_config_get_network - Get configured network based on id
1904 * @config: Configuration data from wpa_config_read()
1905 * @id: Unique network id to search for
1906 * Returns: Network configuration or %NULL if not found
1907 */
1908struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1909{
1910	struct wpa_ssid *ssid;
1911
1912	ssid = config->ssid;
1913	while (ssid) {
1914		if (id == ssid->id)
1915			break;
1916		ssid = ssid->next;
1917	}
1918
1919	return ssid;
1920}
1921
1922
1923/**
1924 * wpa_config_add_network - Add a new network with empty configuration
1925 * @config: Configuration data from wpa_config_read()
1926 * Returns: The new network configuration or %NULL if operation failed
1927 */
1928struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1929{
1930	int id;
1931	struct wpa_ssid *ssid, *last = NULL;
1932
1933	id = -1;
1934	ssid = config->ssid;
1935	while (ssid) {
1936		if (ssid->id > id)
1937			id = ssid->id;
1938		last = ssid;
1939		ssid = ssid->next;
1940	}
1941	id++;
1942
1943	ssid = os_zalloc(sizeof(*ssid));
1944	if (ssid == NULL)
1945		return NULL;
1946	ssid->id = id;
1947	if (last)
1948		last->next = ssid;
1949	else
1950		config->ssid = ssid;
1951
1952	wpa_config_update_prio_list(config);
1953
1954	return ssid;
1955}
1956
1957
1958/**
1959 * wpa_config_remove_network - Remove a configured network based on id
1960 * @config: Configuration data from wpa_config_read()
1961 * @id: Unique network id to search for
1962 * Returns: 0 on success, or -1 if the network was not found
1963 */
1964int wpa_config_remove_network(struct wpa_config *config, int id)
1965{
1966	struct wpa_ssid *ssid, *prev = NULL;
1967
1968	ssid = config->ssid;
1969	while (ssid) {
1970		if (id == ssid->id)
1971			break;
1972		prev = ssid;
1973		ssid = ssid->next;
1974	}
1975
1976	if (ssid == NULL)
1977		return -1;
1978
1979	if (prev)
1980		prev->next = ssid->next;
1981	else
1982		config->ssid = ssid->next;
1983
1984	wpa_config_update_prio_list(config);
1985	wpa_config_free_ssid(ssid);
1986	return 0;
1987}
1988
1989
1990/**
1991 * wpa_config_set_network_defaults - Set network default values
1992 * @ssid: Pointer to network configuration data
1993 */
1994void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
1995{
1996	ssid->proto = DEFAULT_PROTO;
1997	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
1998	ssid->group_cipher = DEFAULT_GROUP;
1999	ssid->key_mgmt = DEFAULT_KEY_MGMT;
2000#ifdef IEEE8021X_EAPOL
2001	ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
2002	ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
2003	ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
2004#endif /* IEEE8021X_EAPOL */
2005#ifdef CONFIG_HT_OVERRIDES
2006	ssid->disable_ht = DEFAULT_DISABLE_HT;
2007	ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
2008	ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
2009	ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
2010	ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
2011#endif /* CONFIG_HT_OVERRIDES */
2012}
2013
2014
2015/**
2016 * wpa_config_set - Set a variable in network configuration
2017 * @ssid: Pointer to network configuration data
2018 * @var: Variable name, e.g., "ssid"
2019 * @value: Variable value
2020 * @line: Line number in configuration file or 0 if not used
2021 * Returns: 0 on success, -1 on failure
2022 *
2023 * This function can be used to set network configuration variables based on
2024 * both the configuration file and management interface input. The value
2025 * parameter must be in the same format as the text-based configuration file is
2026 * using. For example, strings are using double quotation marks.
2027 */
2028int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
2029		   int line)
2030{
2031	size_t i;
2032	int ret = 0;
2033
2034	if (ssid == NULL || var == NULL || value == NULL)
2035		return -1;
2036
2037	for (i = 0; i < NUM_SSID_FIELDS; i++) {
2038		const struct parse_data *field = &ssid_fields[i];
2039		if (os_strcmp(var, field->name) != 0)
2040			continue;
2041
2042		if (field->parser(field, ssid, line, value)) {
2043			if (line) {
2044				wpa_printf(MSG_ERROR, "Line %d: failed to "
2045					   "parse %s '%s'.", line, var, value);
2046			}
2047			ret = -1;
2048		}
2049		break;
2050	}
2051	if (i == NUM_SSID_FIELDS) {
2052		if (line) {
2053			wpa_printf(MSG_ERROR, "Line %d: unknown network field "
2054				   "'%s'.", line, var);
2055		}
2056		ret = -1;
2057	}
2058
2059	return ret;
2060}
2061
2062
2063int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var,
2064			  const char *value)
2065{
2066	size_t len;
2067	char *buf;
2068	int ret;
2069
2070	len = os_strlen(value);
2071	buf = os_malloc(len + 3);
2072	if (buf == NULL)
2073		return -1;
2074	buf[0] = '"';
2075	os_memcpy(buf + 1, value, len);
2076	buf[len + 1] = '"';
2077	buf[len + 2] = '\0';
2078	ret = wpa_config_set(ssid, var, buf, 0);
2079	os_free(buf);
2080	return ret;
2081}
2082
2083
2084/**
2085 * wpa_config_get_all - Get all options from network configuration
2086 * @ssid: Pointer to network configuration data
2087 * @get_keys: Determines if keys/passwords will be included in returned list
2088 *	(if they may be exported)
2089 * Returns: %NULL terminated list of all set keys and their values in the form
2090 * of [key1, val1, key2, val2, ... , NULL]
2091 *
2092 * This function can be used to get list of all configured network properties.
2093 * The caller is responsible for freeing the returned list and all its
2094 * elements.
2095 */
2096char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
2097{
2098	const struct parse_data *field;
2099	char *key, *value;
2100	size_t i;
2101	char **props;
2102	int fields_num;
2103
2104	get_keys = get_keys && ssid->export_keys;
2105
2106	props = os_zalloc(sizeof(char *) * ((2 * NUM_SSID_FIELDS) + 1));
2107	if (!props)
2108		return NULL;
2109
2110	fields_num = 0;
2111	for (i = 0; i < NUM_SSID_FIELDS; i++) {
2112		field = &ssid_fields[i];
2113		if (field->key_data && !get_keys)
2114			continue;
2115		value = field->writer(field, ssid);
2116		if (value == NULL)
2117			continue;
2118		if (os_strlen(value) == 0) {
2119			os_free(value);
2120			continue;
2121		}
2122
2123		key = os_strdup(field->name);
2124		if (key == NULL) {
2125			os_free(value);
2126			goto err;
2127		}
2128
2129		props[fields_num * 2] = key;
2130		props[fields_num * 2 + 1] = value;
2131
2132		fields_num++;
2133	}
2134
2135	return props;
2136
2137err:
2138	value = *props;
2139	while (value)
2140		os_free(value++);
2141	os_free(props);
2142	return NULL;
2143}
2144
2145
2146#ifndef NO_CONFIG_WRITE
2147/**
2148 * wpa_config_get - Get a variable in network configuration
2149 * @ssid: Pointer to network configuration data
2150 * @var: Variable name, e.g., "ssid"
2151 * Returns: Value of the variable or %NULL on failure
2152 *
2153 * This function can be used to get network configuration variables. The
2154 * returned value is a copy of the configuration variable in text format, i.e,.
2155 * the same format that the text-based configuration file and wpa_config_set()
2156 * are using for the value. The caller is responsible for freeing the returned
2157 * value.
2158 */
2159char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
2160{
2161	size_t i;
2162
2163	if (ssid == NULL || var == NULL)
2164		return NULL;
2165
2166	for (i = 0; i < NUM_SSID_FIELDS; i++) {
2167		const struct parse_data *field = &ssid_fields[i];
2168		if (os_strcmp(var, field->name) == 0)
2169			return field->writer(field, ssid);
2170	}
2171
2172	return NULL;
2173}
2174
2175
2176/**
2177 * wpa_config_get_no_key - Get a variable in network configuration (no keys)
2178 * @ssid: Pointer to network configuration data
2179 * @var: Variable name, e.g., "ssid"
2180 * Returns: Value of the variable or %NULL on failure
2181 *
2182 * This function can be used to get network configuration variable like
2183 * wpa_config_get(). The only difference is that this functions does not expose
2184 * key/password material from the configuration. In case a key/password field
2185 * is requested, the returned value is an empty string or %NULL if the variable
2186 * is not set or "*" if the variable is set (regardless of its value). The
2187 * returned value is a copy of the configuration variable in text format, i.e,.
2188 * the same format that the text-based configuration file and wpa_config_set()
2189 * are using for the value. The caller is responsible for freeing the returned
2190 * value.
2191 */
2192char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
2193{
2194	size_t i;
2195
2196	if (ssid == NULL || var == NULL)
2197		return NULL;
2198
2199	for (i = 0; i < NUM_SSID_FIELDS; i++) {
2200		const struct parse_data *field = &ssid_fields[i];
2201		if (os_strcmp(var, field->name) == 0) {
2202			char *res = field->writer(field, ssid);
2203			if (field->key_data) {
2204				if (res && res[0]) {
2205					wpa_printf(MSG_DEBUG, "Do not allow "
2206						   "key_data field to be "
2207						   "exposed");
2208					os_free(res);
2209					return os_strdup("*");
2210				}
2211
2212				os_free(res);
2213				return NULL;
2214			}
2215			return res;
2216		}
2217	}
2218
2219	return NULL;
2220}
2221#endif /* NO_CONFIG_WRITE */
2222
2223
2224/**
2225 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
2226 * @ssid: Pointer to network configuration data
2227 *
2228 * This function must be called to update WPA PSK when either SSID or the
2229 * passphrase has changed for the network configuration.
2230 */
2231void wpa_config_update_psk(struct wpa_ssid *ssid)
2232{
2233#ifndef CONFIG_NO_PBKDF2
2234	pbkdf2_sha1(ssid->passphrase,
2235		    (char *) ssid->ssid, ssid->ssid_len, 4096,
2236		    ssid->psk, PMK_LEN);
2237	wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
2238			ssid->psk, PMK_LEN);
2239	ssid->psk_set = 1;
2240#endif /* CONFIG_NO_PBKDF2 */
2241}
2242
2243
2244#ifndef CONFIG_NO_CONFIG_BLOBS
2245/**
2246 * wpa_config_get_blob - Get a named configuration blob
2247 * @config: Configuration data from wpa_config_read()
2248 * @name: Name of the blob
2249 * Returns: Pointer to blob data or %NULL if not found
2250 */
2251const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
2252						   const char *name)
2253{
2254	struct wpa_config_blob *blob = config->blobs;
2255
2256	while (blob) {
2257		if (os_strcmp(blob->name, name) == 0)
2258			return blob;
2259		blob = blob->next;
2260	}
2261	return NULL;
2262}
2263
2264
2265/**
2266 * wpa_config_set_blob - Set or add a named configuration blob
2267 * @config: Configuration data from wpa_config_read()
2268 * @blob: New value for the blob
2269 *
2270 * Adds a new configuration blob or replaces the current value of an existing
2271 * blob.
2272 */
2273void wpa_config_set_blob(struct wpa_config *config,
2274			 struct wpa_config_blob *blob)
2275{
2276	wpa_config_remove_blob(config, blob->name);
2277	blob->next = config->blobs;
2278	config->blobs = blob;
2279}
2280
2281
2282/**
2283 * wpa_config_free_blob - Free blob data
2284 * @blob: Pointer to blob to be freed
2285 */
2286void wpa_config_free_blob(struct wpa_config_blob *blob)
2287{
2288	if (blob) {
2289		os_free(blob->name);
2290		os_free(blob->data);
2291		os_free(blob);
2292	}
2293}
2294
2295
2296/**
2297 * wpa_config_remove_blob - Remove a named configuration blob
2298 * @config: Configuration data from wpa_config_read()
2299 * @name: Name of the blob to remove
2300 * Returns: 0 if blob was removed or -1 if blob was not found
2301 */
2302int wpa_config_remove_blob(struct wpa_config *config, const char *name)
2303{
2304	struct wpa_config_blob *pos = config->blobs, *prev = NULL;
2305
2306	while (pos) {
2307		if (os_strcmp(pos->name, name) == 0) {
2308			if (prev)
2309				prev->next = pos->next;
2310			else
2311				config->blobs = pos->next;
2312			wpa_config_free_blob(pos);
2313			return 0;
2314		}
2315		prev = pos;
2316		pos = pos->next;
2317	}
2318
2319	return -1;
2320}
2321#endif /* CONFIG_NO_CONFIG_BLOBS */
2322
2323
2324/**
2325 * wpa_config_alloc_empty - Allocate an empty configuration
2326 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
2327 * socket
2328 * @driver_param: Driver parameters
2329 * Returns: Pointer to allocated configuration data or %NULL on failure
2330 */
2331struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
2332					   const char *driver_param)
2333{
2334	struct wpa_config *config;
2335
2336	config = os_zalloc(sizeof(*config));
2337	if (config == NULL)
2338		return NULL;
2339	config->eapol_version = DEFAULT_EAPOL_VERSION;
2340	config->ap_scan = DEFAULT_AP_SCAN;
2341	config->fast_reauth = DEFAULT_FAST_REAUTH;
2342	config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
2343	config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
2344	config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
2345	config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
2346	config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
2347	config->max_num_sta = DEFAULT_MAX_NUM_STA;
2348	config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
2349
2350	if (ctrl_interface)
2351		config->ctrl_interface = os_strdup(ctrl_interface);
2352	if (driver_param)
2353		config->driver_param = os_strdup(driver_param);
2354
2355	return config;
2356}
2357
2358
2359#ifndef CONFIG_NO_STDOUT_DEBUG
2360/**
2361 * wpa_config_debug_dump_networks - Debug dump of configured networks
2362 * @config: Configuration data from wpa_config_read()
2363 */
2364void wpa_config_debug_dump_networks(struct wpa_config *config)
2365{
2366	int prio;
2367	struct wpa_ssid *ssid;
2368
2369	for (prio = 0; prio < config->num_prio; prio++) {
2370		ssid = config->pssid[prio];
2371		wpa_printf(MSG_DEBUG, "Priority group %d",
2372			   ssid->priority);
2373		while (ssid) {
2374			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
2375				   ssid->id,
2376				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2377			ssid = ssid->pnext;
2378		}
2379	}
2380}
2381#endif /* CONFIG_NO_STDOUT_DEBUG */
2382
2383
2384struct global_parse_data {
2385	char *name;
2386	int (*parser)(const struct global_parse_data *data,
2387		      struct wpa_config *config, int line, const char *value);
2388	void *param1, *param2, *param3;
2389	unsigned int changed_flag;
2390};
2391
2392
2393static int wpa_global_config_parse_int(const struct global_parse_data *data,
2394				       struct wpa_config *config, int line,
2395				       const char *pos)
2396{
2397	int *dst;
2398	dst = (int *) (((u8 *) config) + (long) data->param1);
2399	*dst = atoi(pos);
2400	wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
2401
2402	if (data->param2 && *dst < (long) data->param2) {
2403		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
2404			   "min_value=%ld)", line, data->name, *dst,
2405			   (long) data->param2);
2406		*dst = (long) data->param2;
2407		return -1;
2408	}
2409
2410	if (data->param3 && *dst > (long) data->param3) {
2411		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
2412			   "max_value=%ld)", line, data->name, *dst,
2413			   (long) data->param3);
2414		*dst = (long) data->param3;
2415		return -1;
2416	}
2417
2418	return 0;
2419}
2420
2421
2422static int wpa_global_config_parse_str(const struct global_parse_data *data,
2423				       struct wpa_config *config, int line,
2424				       const char *pos)
2425{
2426	size_t len;
2427	char **dst, *tmp;
2428
2429	len = os_strlen(pos);
2430	if (data->param2 && len < (size_t) data->param2) {
2431		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
2432			   "min_len=%ld)", line, data->name,
2433			   (unsigned long) len, (long) data->param2);
2434		return -1;
2435	}
2436
2437	if (data->param3 && len > (size_t) data->param3) {
2438		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
2439			   "max_len=%ld)", line, data->name,
2440			   (unsigned long) len, (long) data->param3);
2441		return -1;
2442	}
2443
2444	tmp = os_strdup(pos);
2445	if (tmp == NULL)
2446		return -1;
2447
2448	dst = (char **) (((u8 *) config) + (long) data->param1);
2449	os_free(*dst);
2450	*dst = tmp;
2451	wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
2452
2453	return 0;
2454}
2455
2456
2457static int wpa_config_process_country(const struct global_parse_data *data,
2458				      struct wpa_config *config, int line,
2459				      const char *pos)
2460{
2461	if (!pos[0] || !pos[1]) {
2462		wpa_printf(MSG_DEBUG, "Invalid country set");
2463		return -1;
2464	}
2465	config->country[0] = pos[0];
2466	config->country[1] = pos[1];
2467	wpa_printf(MSG_DEBUG, "country='%c%c'",
2468		   config->country[0], config->country[1]);
2469	return 0;
2470}
2471
2472
2473static int wpa_config_process_load_dynamic_eap(
2474	const struct global_parse_data *data, struct wpa_config *config,
2475	int line, const char *so)
2476{
2477	int ret;
2478	wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
2479	ret = eap_peer_method_load(so);
2480	if (ret == -2) {
2481		wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
2482			   "reloading.");
2483	} else if (ret) {
2484		wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
2485			   "method '%s'.", line, so);
2486		return -1;
2487	}
2488
2489	return 0;
2490}
2491
2492
2493#ifdef CONFIG_WPS
2494
2495static int wpa_config_process_uuid(const struct global_parse_data *data,
2496				   struct wpa_config *config, int line,
2497				   const char *pos)
2498{
2499	char buf[40];
2500	if (uuid_str2bin(pos, config->uuid)) {
2501		wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
2502		return -1;
2503	}
2504	uuid_bin2str(config->uuid, buf, sizeof(buf));
2505	wpa_printf(MSG_DEBUG, "uuid=%s", buf);
2506	return 0;
2507}
2508
2509
2510static int wpa_config_process_device_type(
2511	const struct global_parse_data *data,
2512	struct wpa_config *config, int line, const char *pos)
2513{
2514	return wps_dev_type_str2bin(pos, config->device_type);
2515}
2516
2517
2518static int wpa_config_process_os_version(const struct global_parse_data *data,
2519					 struct wpa_config *config, int line,
2520					 const char *pos)
2521{
2522	if (hexstr2bin(pos, config->os_version, 4)) {
2523		wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
2524		return -1;
2525	}
2526	wpa_printf(MSG_DEBUG, "os_version=%08x",
2527		   WPA_GET_BE32(config->os_version));
2528	return 0;
2529}
2530
2531#endif /* CONFIG_WPS */
2532
2533#ifdef CONFIG_P2P
2534static int wpa_config_process_sec_device_type(
2535	const struct global_parse_data *data,
2536	struct wpa_config *config, int line, const char *pos)
2537{
2538	int idx;
2539
2540	if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) {
2541		wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type "
2542			   "items", line);
2543		return -1;
2544	}
2545
2546	idx = config->num_sec_device_types;
2547
2548	if (wps_dev_type_str2bin(pos, config->sec_device_type[idx]))
2549		return -1;
2550
2551	config->num_sec_device_types++;
2552	return 0;
2553}
2554#endif /* CONFIG_P2P */
2555
2556
2557static int wpa_config_process_hessid(
2558	const struct global_parse_data *data,
2559	struct wpa_config *config, int line, const char *pos)
2560{
2561	if (hwaddr_aton2(pos, config->hessid) < 0) {
2562		wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'",
2563			   line, pos);
2564		return -1;
2565	}
2566
2567	return 0;
2568}
2569
2570
2571#ifdef OFFSET
2572#undef OFFSET
2573#endif /* OFFSET */
2574/* OFFSET: Get offset of a variable within the wpa_config structure */
2575#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
2576
2577#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
2578#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
2579#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
2580#define INT(f) _INT(f), NULL, NULL
2581#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
2582#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
2583#define STR(f) _STR(f), NULL, NULL
2584#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
2585
2586static const struct global_parse_data global_fields[] = {
2587#ifdef CONFIG_CTRL_IFACE
2588	{ STR(ctrl_interface), 0 },
2589	{ STR(ctrl_interface_group), 0 } /* deprecated */,
2590#endif /* CONFIG_CTRL_IFACE */
2591	{ INT_RANGE(eapol_version, 1, 2), 0 },
2592	{ INT(ap_scan), 0 },
2593	{ INT(fast_reauth), 0 },
2594	{ STR(opensc_engine_path), 0 },
2595	{ STR(pkcs11_engine_path), 0 },
2596	{ STR(pkcs11_module_path), 0 },
2597	{ STR(driver_param), 0 },
2598	{ INT(dot11RSNAConfigPMKLifetime), 0 },
2599	{ INT(dot11RSNAConfigPMKReauthThreshold), 0 },
2600	{ INT(dot11RSNAConfigSATimeout), 0 },
2601#ifndef CONFIG_NO_CONFIG_WRITE
2602	{ INT(update_config), 0 },
2603#endif /* CONFIG_NO_CONFIG_WRITE */
2604	{ FUNC_NO_VAR(load_dynamic_eap), 0 },
2605#ifdef CONFIG_WPS
2606	{ FUNC(uuid), CFG_CHANGED_UUID },
2607	{ STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME },
2608	{ STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
2609	{ STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
2610	{ STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
2611	{ STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING },
2612	{ FUNC(device_type), CFG_CHANGED_DEVICE_TYPE },
2613	{ FUNC(os_version), CFG_CHANGED_OS_VERSION },
2614	{ STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
2615	{ INT_RANGE(wps_cred_processing, 0, 2), 0 },
2616#endif /* CONFIG_WPS */
2617#ifdef CONFIG_P2P
2618	{ FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
2619	{ INT(p2p_listen_reg_class), 0 },
2620	{ INT(p2p_listen_channel), 0 },
2621	{ INT(p2p_oper_reg_class), 0 },
2622	{ INT(p2p_oper_channel), 0 },
2623	{ INT_RANGE(p2p_go_intent, 0, 15), 0 },
2624	{ STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
2625	{ INT_RANGE(persistent_reconnect, 0, 1), 0 },
2626	{ INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
2627	{ INT(p2p_group_idle), 0 },
2628#endif /* CONFIG_P2P */
2629#ifdef ANDROID_P2P
2630	{ STR_RANGE(prioritize, 0, 32), CFG_CHANGED_IFACE_PRIORITY },
2631#endif
2632	{ FUNC(country), CFG_CHANGED_COUNTRY },
2633	{ INT(bss_max_count), 0 },
2634	{ INT(bss_expiration_age), 0 },
2635	{ INT(bss_expiration_scan_count), 0 },
2636	{ INT_RANGE(filter_ssids, 0, 1), 0 },
2637	{ INT(max_num_sta), 0 },
2638	{ INT_RANGE(disassoc_low_ack, 0, 1), 0 },
2639	{ STR(home_realm), 0 },
2640	{ STR(home_username), 0 },
2641	{ STR(home_password), 0 },
2642	{ STR(home_ca_cert), 0 },
2643	{ STR(home_imsi), 0 },
2644	{ STR(home_milenage), 0 },
2645	{ INT_RANGE(interworking, 0, 1), 0 },
2646	{ FUNC(hessid), 0 },
2647	{ INT_RANGE(access_network_type, 0, 15), 0 }
2648};
2649
2650#undef FUNC
2651#undef _INT
2652#undef INT
2653#undef INT_RANGE
2654#undef _STR
2655#undef STR
2656#undef STR_RANGE
2657#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0]))
2658
2659
2660int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
2661{
2662	size_t i;
2663	int ret = 0;
2664
2665	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
2666		const struct global_parse_data *field = &global_fields[i];
2667		size_t flen = os_strlen(field->name);
2668		if (os_strncmp(pos, field->name, flen) != 0 ||
2669		    pos[flen] != '=')
2670			continue;
2671
2672		if (field->parser(field, config, line, pos + flen + 1)) {
2673			wpa_printf(MSG_ERROR, "Line %d: failed to "
2674				   "parse '%s'.", line, pos);
2675			ret = -1;
2676		}
2677		config->changed_parameters |= field->changed_flag;
2678		break;
2679	}
2680	if (i == NUM_GLOBAL_FIELDS) {
2681		if (line < 0)
2682			return -1;
2683		wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
2684			   line, pos);
2685		ret = -1;
2686	}
2687
2688	return ret;
2689}
2690