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