config.c revision c5da5d2e24c1148757b2493dc351c4adec48360d
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/* Helper macros for network block parser */
1375
1376#ifdef OFFSET
1377#undef OFFSET
1378#endif /* OFFSET */
1379/* OFFSET: Get offset of a variable within the wpa_ssid structure */
1380#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
1381
1382/* STR: Define a string variable for an ASCII string; f = field name */
1383#ifdef NO_CONFIG_WRITE
1384#define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
1385#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
1386#else /* NO_CONFIG_WRITE */
1387#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
1388#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
1389#endif /* NO_CONFIG_WRITE */
1390#define STR(f) _STR(f), NULL, NULL, NULL, 0
1391#define STRe(f) _STRe(f), NULL, NULL, NULL, 0
1392#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
1393#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
1394
1395/* STR_LEN: Define a string variable with a separate variable for storing the
1396 * data length. Unlike STR(), this can be used to store arbitrary binary data
1397 * (i.e., even nul termination character). */
1398#define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
1399#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
1400#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
1401#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
1402#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
1403
1404/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
1405 * explicitly specified. */
1406#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
1407#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
1408#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
1409
1410#ifdef NO_CONFIG_WRITE
1411#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
1412#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
1413#else /* NO_CONFIG_WRITE */
1414#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1415	OFFSET(f), (void *) 0
1416#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1417	OFFSET(eap.f), (void *) 0
1418#ifdef WPA_UNICODE_SSID
1419/* STR_* variants that do not force conversion to ASCII */
1420#define _STR_UNICODE(f) #f, wpa_config_parse_str, wpa_config_write_str_unicode, OFFSET(f)
1421#define STR_UNICODE(f) _STR_UNICODE(f), NULL, NULL, NULL, 0
1422#define _STR_LEN_UNICODE(f) _STR_UNICODE(f), OFFSET(f ## _len)
1423#define STR_LEN_UNICODE(f) _STR_LEN_UNICODE(f), NULL, NULL, 0
1424#define _STR_RANGE_UNICODE(f, min, max) _STR_LEN_UNICODE(f), (void *) (min), (void *) (max)
1425#define STR_RANGE_UNICODE(f, min, max) _STR_RANGE_UNICODE(f, min, max), 0
1426#endif
1427#endif /* NO_CONFIG_WRITE */
1428
1429/* INT: Define an integer variable */
1430#define INT(f) _INT(f), NULL, NULL, 0
1431#define INTe(f) _INTe(f), NULL, NULL, 0
1432
1433/* INT_RANGE: Define an integer variable with allowed value range */
1434#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
1435
1436/* FUNC: Define a configuration variable that uses a custom function for
1437 * parsing and writing the value. */
1438#ifdef NO_CONFIG_WRITE
1439#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
1440#else /* NO_CONFIG_WRITE */
1441#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
1442	NULL, NULL, NULL, NULL
1443#endif /* NO_CONFIG_WRITE */
1444#define FUNC(f) _FUNC(f), 0
1445#define FUNC_KEY(f) _FUNC(f), 1
1446
1447/*
1448 * Table of network configuration variables. This table is used to parse each
1449 * network configuration variable, e.g., each line in wpa_supplicant.conf file
1450 * that is inside a network block.
1451 *
1452 * This table is generated using the helper macros defined above and with
1453 * generous help from the C pre-processor. The field name is stored as a string
1454 * into .name and for STR and INT types, the offset of the target buffer within
1455 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
1456 * offset to the field containing the length of the configuration variable.
1457 * .param3 and .param4 can be used to mark the allowed range (length for STR
1458 * and value for INT).
1459 *
1460 * For each configuration line in wpa_supplicant.conf, the parser goes through
1461 * this table and select the entry that matches with the field name. The parser
1462 * function (.parser) is then called to parse the actual value of the field.
1463 *
1464 * This kind of mechanism makes it easy to add new configuration parameters,
1465 * since only one line needs to be added into this table and into the
1466 * struct wpa_ssid definition if the new variable is either a string or
1467 * integer. More complex types will need to use their own parser and writer
1468 * functions.
1469 */
1470static const struct parse_data ssid_fields[] = {
1471#ifdef WPA_UNICODE_SSID
1472	{ STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) },
1473#else
1474	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1475#endif
1476	{ INT_RANGE(scan_ssid, 0, 1) },
1477	{ FUNC(bssid) },
1478	{ FUNC_KEY(psk) },
1479	{ FUNC(proto) },
1480	{ FUNC(key_mgmt) },
1481	{ FUNC(pairwise) },
1482	{ FUNC(group) },
1483	{ FUNC(auth_alg) },
1484	{ FUNC(scan_freq) },
1485	{ FUNC(freq_list) },
1486#ifdef IEEE8021X_EAPOL
1487	{ FUNC(eap) },
1488	{ STR_LENe(identity) },
1489	{ STR_LENe(anonymous_identity) },
1490	{ FUNC_KEY(password) },
1491	{ STRe(ca_cert) },
1492	{ STRe(ca_path) },
1493	{ STRe(client_cert) },
1494	{ STRe(private_key) },
1495	{ STR_KEYe(private_key_passwd) },
1496	{ STRe(dh_file) },
1497	{ STRe(subject_match) },
1498	{ STRe(altsubject_match) },
1499	{ STRe(ca_cert2) },
1500	{ STRe(ca_path2) },
1501	{ STRe(client_cert2) },
1502	{ STRe(private_key2) },
1503	{ STR_KEYe(private_key2_passwd) },
1504	{ STRe(dh_file2) },
1505	{ STRe(subject_match2) },
1506	{ STRe(altsubject_match2) },
1507	{ STRe(phase1) },
1508	{ STRe(phase2) },
1509	{ STRe(pcsc) },
1510	{ STR_KEYe(pin) },
1511	{ STRe(engine_id) },
1512	{ STRe(key_id) },
1513	{ STRe(cert_id) },
1514	{ STRe(ca_cert_id) },
1515	{ STR_KEYe(pin2) },
1516	{ STRe(engine2_id) },
1517	{ STRe(key2_id) },
1518	{ STRe(cert2_id) },
1519	{ STRe(ca_cert2_id) },
1520	{ INTe(engine) },
1521	{ INTe(engine2) },
1522	{ INT(eapol_flags) },
1523#endif /* IEEE8021X_EAPOL */
1524	{ FUNC_KEY(wep_key0) },
1525	{ FUNC_KEY(wep_key1) },
1526	{ FUNC_KEY(wep_key2) },
1527	{ FUNC_KEY(wep_key3) },
1528	{ INT(wep_tx_keyidx) },
1529	{ INT(priority) },
1530#ifdef IEEE8021X_EAPOL
1531	{ INT(eap_workaround) },
1532	{ STRe(pac_file) },
1533	{ INTe(fragment_size) },
1534#endif /* IEEE8021X_EAPOL */
1535	{ INT_RANGE(mode, 0, 4) },
1536	{ INT_RANGE(proactive_key_caching, 0, 1) },
1537	{ INT_RANGE(disabled, 0, 2) },
1538	{ STR(id_str) },
1539#ifdef CONFIG_IEEE80211W
1540	{ INT_RANGE(ieee80211w, 0, 2) },
1541#endif /* CONFIG_IEEE80211W */
1542	{ INT_RANGE(peerkey, 0, 1) },
1543	{ INT_RANGE(mixed_cell, 0, 1) },
1544	{ INT_RANGE(frequency, 0, 10000) },
1545	{ INT(wpa_ptk_rekey) },
1546	{ STR(bgscan) },
1547};
1548
1549#ifdef WPA_UNICODE_SSID
1550#undef _STR_UNICODE
1551#undef STR_UNICODE
1552#undef _STR_LEN_UNICODE
1553#undef STR_LEN_UNICODE
1554#undef _STR_RANGE_UNICODE
1555#undef STR_RANGE_UNICODE
1556#endif
1557
1558#undef OFFSET
1559#undef _STR
1560#undef STR
1561#undef STR_KEY
1562#undef _STR_LEN
1563#undef STR_LEN
1564#undef STR_LEN_KEY
1565#undef _STR_RANGE
1566#undef STR_RANGE
1567#undef STR_RANGE_KEY
1568#undef _INT
1569#undef INT
1570#undef INT_RANGE
1571#undef _FUNC
1572#undef FUNC
1573#undef FUNC_KEY
1574#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1575
1576
1577/**
1578 * wpa_config_add_prio_network - Add a network to priority lists
1579 * @config: Configuration data from wpa_config_read()
1580 * @ssid: Pointer to the network configuration to be added to the list
1581 * Returns: 0 on success, -1 on failure
1582 *
1583 * This function is used to add a network block to the priority list of
1584 * networks. This must be called for each network when reading in the full
1585 * configuration. In addition, this can be used indirectly when updating
1586 * priorities by calling wpa_config_update_prio_list().
1587 */
1588int wpa_config_add_prio_network(struct wpa_config *config,
1589				struct wpa_ssid *ssid)
1590{
1591	int prio;
1592	struct wpa_ssid *prev, **nlist;
1593
1594	/*
1595	 * Add to an existing priority list if one is available for the
1596	 * configured priority level for this network.
1597	 */
1598	for (prio = 0; prio < config->num_prio; prio++) {
1599		prev = config->pssid[prio];
1600		if (prev->priority == ssid->priority) {
1601			while (prev->pnext)
1602				prev = prev->pnext;
1603			prev->pnext = ssid;
1604			return 0;
1605		}
1606	}
1607
1608	/* First network for this priority - add a new priority list */
1609	nlist = os_realloc(config->pssid,
1610			   (config->num_prio + 1) * sizeof(struct wpa_ssid *));
1611	if (nlist == NULL)
1612		return -1;
1613
1614	for (prio = 0; prio < config->num_prio; prio++) {
1615		if (nlist[prio]->priority < ssid->priority)
1616			break;
1617	}
1618
1619	os_memmove(&nlist[prio + 1], &nlist[prio],
1620		   (config->num_prio - prio) * sizeof(struct wpa_ssid *));
1621
1622	nlist[prio] = ssid;
1623	config->num_prio++;
1624	config->pssid = nlist;
1625
1626	return 0;
1627}
1628
1629
1630/**
1631 * wpa_config_update_prio_list - Update network priority list
1632 * @config: Configuration data from wpa_config_read()
1633 * Returns: 0 on success, -1 on failure
1634 *
1635 * This function is called to update the priority list of networks in the
1636 * configuration when a network is being added or removed. This is also called
1637 * if a priority for a network is changed.
1638 */
1639int wpa_config_update_prio_list(struct wpa_config *config)
1640{
1641	struct wpa_ssid *ssid;
1642	int ret = 0;
1643
1644	os_free(config->pssid);
1645	config->pssid = NULL;
1646	config->num_prio = 0;
1647
1648	ssid = config->ssid;
1649	while (ssid) {
1650		ssid->pnext = NULL;
1651		if (wpa_config_add_prio_network(config, ssid) < 0)
1652			ret = -1;
1653		ssid = ssid->next;
1654	}
1655
1656	return ret;
1657}
1658
1659
1660#ifdef IEEE8021X_EAPOL
1661static void eap_peer_config_free(struct eap_peer_config *eap)
1662{
1663	os_free(eap->eap_methods);
1664	os_free(eap->identity);
1665	os_free(eap->anonymous_identity);
1666	os_free(eap->password);
1667	os_free(eap->ca_cert);
1668	os_free(eap->ca_path);
1669	os_free(eap->client_cert);
1670	os_free(eap->private_key);
1671	os_free(eap->private_key_passwd);
1672	os_free(eap->dh_file);
1673	os_free(eap->subject_match);
1674	os_free(eap->altsubject_match);
1675	os_free(eap->ca_cert2);
1676	os_free(eap->ca_path2);
1677	os_free(eap->client_cert2);
1678	os_free(eap->private_key2);
1679	os_free(eap->private_key2_passwd);
1680	os_free(eap->dh_file2);
1681	os_free(eap->subject_match2);
1682	os_free(eap->altsubject_match2);
1683	os_free(eap->phase1);
1684	os_free(eap->phase2);
1685	os_free(eap->pcsc);
1686	os_free(eap->pin);
1687	os_free(eap->engine_id);
1688	os_free(eap->key_id);
1689	os_free(eap->cert_id);
1690	os_free(eap->ca_cert_id);
1691	os_free(eap->key2_id);
1692	os_free(eap->cert2_id);
1693	os_free(eap->ca_cert2_id);
1694	os_free(eap->pin2);
1695	os_free(eap->engine2_id);
1696	os_free(eap->otp);
1697	os_free(eap->pending_req_otp);
1698	os_free(eap->pac_file);
1699	os_free(eap->new_password);
1700}
1701#endif /* IEEE8021X_EAPOL */
1702
1703
1704/**
1705 * wpa_config_free_ssid - Free network/ssid configuration data
1706 * @ssid: Configuration data for the network
1707 *
1708 * This function frees all resources allocated for the network configuration
1709 * data.
1710 */
1711void wpa_config_free_ssid(struct wpa_ssid *ssid)
1712{
1713	os_free(ssid->ssid);
1714	os_free(ssid->passphrase);
1715#ifdef IEEE8021X_EAPOL
1716	eap_peer_config_free(&ssid->eap);
1717#endif /* IEEE8021X_EAPOL */
1718	os_free(ssid->id_str);
1719	os_free(ssid->scan_freq);
1720	os_free(ssid->freq_list);
1721	os_free(ssid->bgscan);
1722	os_free(ssid);
1723}
1724
1725
1726/**
1727 * wpa_config_free - Free configuration data
1728 * @config: Configuration data from wpa_config_read()
1729 *
1730 * This function frees all resources allocated for the configuration data by
1731 * wpa_config_read().
1732 */
1733void wpa_config_free(struct wpa_config *config)
1734{
1735#ifndef CONFIG_NO_CONFIG_BLOBS
1736	struct wpa_config_blob *blob, *prevblob;
1737#endif /* CONFIG_NO_CONFIG_BLOBS */
1738	struct wpa_ssid *ssid, *prev = NULL;
1739
1740	ssid = config->ssid;
1741	while (ssid) {
1742		prev = ssid;
1743		ssid = ssid->next;
1744		wpa_config_free_ssid(prev);
1745	}
1746
1747#ifndef CONFIG_NO_CONFIG_BLOBS
1748	blob = config->blobs;
1749	prevblob = NULL;
1750	while (blob) {
1751		prevblob = blob;
1752		blob = blob->next;
1753		wpa_config_free_blob(prevblob);
1754	}
1755#endif /* CONFIG_NO_CONFIG_BLOBS */
1756
1757	os_free(config->ctrl_interface);
1758	os_free(config->ctrl_interface_group);
1759	os_free(config->opensc_engine_path);
1760	os_free(config->pkcs11_engine_path);
1761	os_free(config->pkcs11_module_path);
1762	os_free(config->driver_param);
1763	os_free(config->device_name);
1764	os_free(config->manufacturer);
1765	os_free(config->model_name);
1766	os_free(config->model_number);
1767	os_free(config->serial_number);
1768	os_free(config->config_methods);
1769	os_free(config->p2p_ssid_postfix);
1770	os_free(config->pssid);
1771	os_free(config);
1772}
1773
1774
1775/**
1776 * wpa_config_foreach_network - Iterate over each configured network
1777 * @config: Configuration data from wpa_config_read()
1778 * @func: Callback function to process each network
1779 * @arg: Opaque argument to pass to callback function
1780 *
1781 * Iterate over the set of configured networks calling the specified
1782 * function for each item. We guard against callbacks removing the
1783 * supplied network.
1784 */
1785void wpa_config_foreach_network(struct wpa_config *config,
1786				void (*func)(void *, struct wpa_ssid *),
1787				void *arg)
1788{
1789	struct wpa_ssid *ssid, *next;
1790
1791	ssid = config->ssid;
1792	while (ssid) {
1793		next = ssid->next;
1794		func(arg, ssid);
1795		ssid = next;
1796	}
1797}
1798
1799
1800/**
1801 * wpa_config_get_network - Get configured network based on id
1802 * @config: Configuration data from wpa_config_read()
1803 * @id: Unique network id to search for
1804 * Returns: Network configuration or %NULL if not found
1805 */
1806struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1807{
1808	struct wpa_ssid *ssid;
1809
1810	ssid = config->ssid;
1811	while (ssid) {
1812		if (id == ssid->id)
1813			break;
1814		ssid = ssid->next;
1815	}
1816
1817	return ssid;
1818}
1819
1820
1821/**
1822 * wpa_config_add_network - Add a new network with empty configuration
1823 * @config: Configuration data from wpa_config_read()
1824 * Returns: The new network configuration or %NULL if operation failed
1825 */
1826struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1827{
1828	int id;
1829	struct wpa_ssid *ssid, *last = NULL;
1830
1831	id = -1;
1832	ssid = config->ssid;
1833	while (ssid) {
1834		if (ssid->id > id)
1835			id = ssid->id;
1836		last = ssid;
1837		ssid = ssid->next;
1838	}
1839	id++;
1840
1841	ssid = os_zalloc(sizeof(*ssid));
1842	if (ssid == NULL)
1843		return NULL;
1844	ssid->id = id;
1845	if (last)
1846		last->next = ssid;
1847	else
1848		config->ssid = ssid;
1849
1850	wpa_config_update_prio_list(config);
1851
1852	return ssid;
1853}
1854
1855
1856/**
1857 * wpa_config_remove_network - Remove a configured network based on id
1858 * @config: Configuration data from wpa_config_read()
1859 * @id: Unique network id to search for
1860 * Returns: 0 on success, or -1 if the network was not found
1861 */
1862int wpa_config_remove_network(struct wpa_config *config, int id)
1863{
1864	struct wpa_ssid *ssid, *prev = NULL;
1865
1866	ssid = config->ssid;
1867	while (ssid) {
1868		if (id == ssid->id)
1869			break;
1870		prev = ssid;
1871		ssid = ssid->next;
1872	}
1873
1874	if (ssid == NULL)
1875		return -1;
1876
1877	if (prev)
1878		prev->next = ssid->next;
1879	else
1880		config->ssid = ssid->next;
1881
1882	wpa_config_update_prio_list(config);
1883	wpa_config_free_ssid(ssid);
1884	return 0;
1885}
1886
1887
1888/**
1889 * wpa_config_set_network_defaults - Set network default values
1890 * @ssid: Pointer to network configuration data
1891 */
1892void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
1893{
1894	ssid->proto = DEFAULT_PROTO;
1895	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
1896	ssid->group_cipher = DEFAULT_GROUP;
1897	ssid->key_mgmt = DEFAULT_KEY_MGMT;
1898#ifdef IEEE8021X_EAPOL
1899	ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
1900	ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
1901	ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
1902#endif /* IEEE8021X_EAPOL */
1903}
1904
1905
1906/**
1907 * wpa_config_set - Set a variable in network configuration
1908 * @ssid: Pointer to network configuration data
1909 * @var: Variable name, e.g., "ssid"
1910 * @value: Variable value
1911 * @line: Line number in configuration file or 0 if not used
1912 * Returns: 0 on success, -1 on failure
1913 *
1914 * This function can be used to set network configuration variables based on
1915 * both the configuration file and management interface input. The value
1916 * parameter must be in the same format as the text-based configuration file is
1917 * using. For example, strings are using double quotation marks.
1918 */
1919int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
1920		   int line)
1921{
1922	size_t i;
1923	int ret = 0;
1924
1925	if (ssid == NULL || var == NULL || value == NULL)
1926		return -1;
1927
1928	for (i = 0; i < NUM_SSID_FIELDS; i++) {
1929		const struct parse_data *field = &ssid_fields[i];
1930		if (os_strcmp(var, field->name) != 0)
1931			continue;
1932
1933		if (field->parser(field, ssid, line, value)) {
1934			if (line) {
1935				wpa_printf(MSG_ERROR, "Line %d: failed to "
1936					   "parse %s '%s'.", line, var, value);
1937			}
1938			ret = -1;
1939		}
1940		break;
1941	}
1942	if (i == NUM_SSID_FIELDS) {
1943		if (line) {
1944			wpa_printf(MSG_ERROR, "Line %d: unknown network field "
1945				   "'%s'.", line, var);
1946		}
1947		ret = -1;
1948	}
1949
1950	return ret;
1951}
1952
1953
1954/**
1955 * wpa_config_get_all - Get all options from network configuration
1956 * @ssid: Pointer to network configuration data
1957 * @get_keys: Determines if keys/passwords will be included in returned list
1958 *	(if they may be exported)
1959 * Returns: %NULL terminated list of all set keys and their values in the form
1960 * of [key1, val1, key2, val2, ... , NULL]
1961 *
1962 * This function can be used to get list of all configured network properties.
1963 * The caller is responsible for freeing the returned list and all its
1964 * elements.
1965 */
1966char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
1967{
1968	const struct parse_data *field;
1969	char *key, *value;
1970	size_t i;
1971	char **props;
1972	int fields_num;
1973
1974	get_keys = get_keys && ssid->export_keys;
1975
1976	props = os_zalloc(sizeof(char *) * ((2 * NUM_SSID_FIELDS) + 1));
1977	if (!props)
1978		return NULL;
1979
1980	fields_num = 0;
1981	for (i = 0; i < NUM_SSID_FIELDS; i++) {
1982		field = &ssid_fields[i];
1983		if (field->key_data && !get_keys)
1984			continue;
1985		value = field->writer(field, ssid);
1986		if (value == NULL)
1987			continue;
1988		if (os_strlen(value) == 0) {
1989			os_free(value);
1990			continue;
1991		}
1992
1993		key = os_strdup(field->name);
1994		if (key == NULL) {
1995			os_free(value);
1996			goto err;
1997		}
1998
1999		props[fields_num * 2] = key;
2000		props[fields_num * 2 + 1] = value;
2001
2002		fields_num++;
2003	}
2004
2005	return props;
2006
2007err:
2008	value = *props;
2009	while (value)
2010		os_free(value++);
2011	os_free(props);
2012	return NULL;
2013}
2014
2015
2016#ifndef NO_CONFIG_WRITE
2017/**
2018 * wpa_config_get - Get a variable in network configuration
2019 * @ssid: Pointer to network configuration data
2020 * @var: Variable name, e.g., "ssid"
2021 * Returns: Value of the variable or %NULL on failure
2022 *
2023 * This function can be used to get network configuration variables. The
2024 * returned value is a copy of the configuration variable in text format, i.e,.
2025 * the same format that the text-based configuration file and wpa_config_set()
2026 * are using for the value. The caller is responsible for freeing the returned
2027 * value.
2028 */
2029char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
2030{
2031	size_t i;
2032
2033	if (ssid == NULL || var == NULL)
2034		return NULL;
2035
2036	for (i = 0; i < NUM_SSID_FIELDS; i++) {
2037		const struct parse_data *field = &ssid_fields[i];
2038		if (os_strcmp(var, field->name) == 0)
2039			return field->writer(field, ssid);
2040	}
2041
2042	return NULL;
2043}
2044
2045
2046/**
2047 * wpa_config_get_no_key - Get a variable in network configuration (no keys)
2048 * @ssid: Pointer to network configuration data
2049 * @var: Variable name, e.g., "ssid"
2050 * Returns: Value of the variable or %NULL on failure
2051 *
2052 * This function can be used to get network configuration variable like
2053 * wpa_config_get(). The only difference is that this functions does not expose
2054 * key/password material from the configuration. In case a key/password field
2055 * is requested, the returned value is an empty string or %NULL if the variable
2056 * is not set or "*" if the variable is set (regardless of its value). The
2057 * returned value is a copy of the configuration variable in text format, i.e,.
2058 * the same format that the text-based configuration file and wpa_config_set()
2059 * are using for the value. The caller is responsible for freeing the returned
2060 * value.
2061 */
2062char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
2063{
2064	size_t i;
2065
2066	if (ssid == NULL || var == NULL)
2067		return NULL;
2068
2069	for (i = 0; i < NUM_SSID_FIELDS; i++) {
2070		const struct parse_data *field = &ssid_fields[i];
2071		if (os_strcmp(var, field->name) == 0) {
2072			char *res = field->writer(field, ssid);
2073			if (field->key_data) {
2074				if (res && res[0]) {
2075					wpa_printf(MSG_DEBUG, "Do not allow "
2076						   "key_data field to be "
2077						   "exposed");
2078					os_free(res);
2079					return os_strdup("*");
2080				}
2081
2082				os_free(res);
2083				return NULL;
2084			}
2085			return res;
2086		}
2087	}
2088
2089	return NULL;
2090}
2091#endif /* NO_CONFIG_WRITE */
2092
2093
2094/**
2095 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
2096 * @ssid: Pointer to network configuration data
2097 *
2098 * This function must be called to update WPA PSK when either SSID or the
2099 * passphrase has changed for the network configuration.
2100 */
2101void wpa_config_update_psk(struct wpa_ssid *ssid)
2102{
2103#ifndef CONFIG_NO_PBKDF2
2104	pbkdf2_sha1(ssid->passphrase,
2105		    (char *) ssid->ssid, ssid->ssid_len, 4096,
2106		    ssid->psk, PMK_LEN);
2107	wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
2108			ssid->psk, PMK_LEN);
2109	ssid->psk_set = 1;
2110#endif /* CONFIG_NO_PBKDF2 */
2111}
2112
2113
2114#ifndef CONFIG_NO_CONFIG_BLOBS
2115/**
2116 * wpa_config_get_blob - Get a named configuration blob
2117 * @config: Configuration data from wpa_config_read()
2118 * @name: Name of the blob
2119 * Returns: Pointer to blob data or %NULL if not found
2120 */
2121const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
2122						   const char *name)
2123{
2124	struct wpa_config_blob *blob = config->blobs;
2125
2126	while (blob) {
2127		if (os_strcmp(blob->name, name) == 0)
2128			return blob;
2129		blob = blob->next;
2130	}
2131	return NULL;
2132}
2133
2134
2135/**
2136 * wpa_config_set_blob - Set or add a named configuration blob
2137 * @config: Configuration data from wpa_config_read()
2138 * @blob: New value for the blob
2139 *
2140 * Adds a new configuration blob or replaces the current value of an existing
2141 * blob.
2142 */
2143void wpa_config_set_blob(struct wpa_config *config,
2144			 struct wpa_config_blob *blob)
2145{
2146	wpa_config_remove_blob(config, blob->name);
2147	blob->next = config->blobs;
2148	config->blobs = blob;
2149}
2150
2151
2152/**
2153 * wpa_config_free_blob - Free blob data
2154 * @blob: Pointer to blob to be freed
2155 */
2156void wpa_config_free_blob(struct wpa_config_blob *blob)
2157{
2158	if (blob) {
2159		os_free(blob->name);
2160		os_free(blob->data);
2161		os_free(blob);
2162	}
2163}
2164
2165
2166/**
2167 * wpa_config_remove_blob - Remove a named configuration blob
2168 * @config: Configuration data from wpa_config_read()
2169 * @name: Name of the blob to remove
2170 * Returns: 0 if blob was removed or -1 if blob was not found
2171 */
2172int wpa_config_remove_blob(struct wpa_config *config, const char *name)
2173{
2174	struct wpa_config_blob *pos = config->blobs, *prev = NULL;
2175
2176	while (pos) {
2177		if (os_strcmp(pos->name, name) == 0) {
2178			if (prev)
2179				prev->next = pos->next;
2180			else
2181				config->blobs = pos->next;
2182			wpa_config_free_blob(pos);
2183			return 0;
2184		}
2185		prev = pos;
2186		pos = pos->next;
2187	}
2188
2189	return -1;
2190}
2191#endif /* CONFIG_NO_CONFIG_BLOBS */
2192
2193
2194/**
2195 * wpa_config_alloc_empty - Allocate an empty configuration
2196 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
2197 * socket
2198 * @driver_param: Driver parameters
2199 * Returns: Pointer to allocated configuration data or %NULL on failure
2200 */
2201struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
2202					   const char *driver_param)
2203{
2204	struct wpa_config *config;
2205
2206	config = os_zalloc(sizeof(*config));
2207	if (config == NULL)
2208		return NULL;
2209	config->eapol_version = DEFAULT_EAPOL_VERSION;
2210	config->ap_scan = DEFAULT_AP_SCAN;
2211	config->fast_reauth = DEFAULT_FAST_REAUTH;
2212	config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
2213	config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
2214	config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
2215	config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
2216	config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
2217	config->max_num_sta = DEFAULT_MAX_NUM_STA;
2218
2219	if (ctrl_interface)
2220		config->ctrl_interface = os_strdup(ctrl_interface);
2221	if (driver_param)
2222		config->driver_param = os_strdup(driver_param);
2223
2224	return config;
2225}
2226
2227
2228#ifndef CONFIG_NO_STDOUT_DEBUG
2229/**
2230 * wpa_config_debug_dump_networks - Debug dump of configured networks
2231 * @config: Configuration data from wpa_config_read()
2232 */
2233void wpa_config_debug_dump_networks(struct wpa_config *config)
2234{
2235	int prio;
2236	struct wpa_ssid *ssid;
2237
2238	for (prio = 0; prio < config->num_prio; prio++) {
2239		ssid = config->pssid[prio];
2240		wpa_printf(MSG_DEBUG, "Priority group %d",
2241			   ssid->priority);
2242		while (ssid) {
2243			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
2244				   ssid->id,
2245				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2246			ssid = ssid->pnext;
2247		}
2248	}
2249}
2250#endif /* CONFIG_NO_STDOUT_DEBUG */
2251
2252
2253struct global_parse_data {
2254	char *name;
2255	int (*parser)(const struct global_parse_data *data,
2256		      struct wpa_config *config, int line, const char *value);
2257	void *param1, *param2, *param3;
2258	unsigned int changed_flag;
2259};
2260
2261
2262static int wpa_global_config_parse_int(const struct global_parse_data *data,
2263				       struct wpa_config *config, int line,
2264				       const char *pos)
2265{
2266	int *dst;
2267	dst = (int *) (((u8 *) config) + (long) data->param1);
2268	*dst = atoi(pos);
2269	wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
2270
2271	if (data->param2 && *dst < (long) data->param2) {
2272		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
2273			   "min_value=%ld)", line, data->name, *dst,
2274			   (long) data->param2);
2275		*dst = (long) data->param2;
2276		return -1;
2277	}
2278
2279	if (data->param3 && *dst > (long) data->param3) {
2280		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
2281			   "max_value=%ld)", line, data->name, *dst,
2282			   (long) data->param3);
2283		*dst = (long) data->param3;
2284		return -1;
2285	}
2286
2287	return 0;
2288}
2289
2290
2291static int wpa_global_config_parse_str(const struct global_parse_data *data,
2292				       struct wpa_config *config, int line,
2293				       const char *pos)
2294{
2295	size_t len;
2296	char **dst, *tmp;
2297
2298	len = os_strlen(pos);
2299	if (data->param2 && len < (size_t) data->param2) {
2300		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
2301			   "min_len=%ld)", line, data->name,
2302			   (unsigned long) len, (long) data->param2);
2303		return -1;
2304	}
2305
2306	if (data->param3 && len > (size_t) data->param3) {
2307		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
2308			   "max_len=%ld)", line, data->name,
2309			   (unsigned long) len, (long) data->param3);
2310		return -1;
2311	}
2312
2313	tmp = os_strdup(pos);
2314	if (tmp == NULL)
2315		return -1;
2316
2317	dst = (char **) (((u8 *) config) + (long) data->param1);
2318	os_free(*dst);
2319	*dst = tmp;
2320	wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
2321
2322	return 0;
2323}
2324
2325
2326static int wpa_config_process_country(const struct global_parse_data *data,
2327				      struct wpa_config *config, int line,
2328				      const char *pos)
2329{
2330	if (!pos[0] || !pos[1]) {
2331		wpa_printf(MSG_DEBUG, "Invalid country set");
2332		return -1;
2333	}
2334	config->country[0] = pos[0];
2335	config->country[1] = pos[1];
2336	wpa_printf(MSG_DEBUG, "country='%c%c'",
2337		   config->country[0], config->country[1]);
2338	return 0;
2339}
2340
2341
2342static int wpa_config_process_load_dynamic_eap(
2343	const struct global_parse_data *data, struct wpa_config *config,
2344	int line, const char *so)
2345{
2346	int ret;
2347	wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
2348	ret = eap_peer_method_load(so);
2349	if (ret == -2) {
2350		wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
2351			   "reloading.");
2352	} else if (ret) {
2353		wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
2354			   "method '%s'.", line, so);
2355		return -1;
2356	}
2357
2358	return 0;
2359}
2360
2361
2362#ifdef CONFIG_WPS
2363
2364static int wpa_config_process_uuid(const struct global_parse_data *data,
2365				   struct wpa_config *config, int line,
2366				   const char *pos)
2367{
2368	char buf[40];
2369	if (uuid_str2bin(pos, config->uuid)) {
2370		wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
2371		return -1;
2372	}
2373	uuid_bin2str(config->uuid, buf, sizeof(buf));
2374	wpa_printf(MSG_DEBUG, "uuid=%s", buf);
2375	return 0;
2376}
2377
2378
2379static int wpa_config_process_device_type(
2380	const struct global_parse_data *data,
2381	struct wpa_config *config, int line, const char *pos)
2382{
2383	return wps_dev_type_str2bin(pos, config->device_type);
2384}
2385
2386
2387static int wpa_config_process_os_version(const struct global_parse_data *data,
2388					 struct wpa_config *config, int line,
2389					 const char *pos)
2390{
2391	if (hexstr2bin(pos, config->os_version, 4)) {
2392		wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
2393		return -1;
2394	}
2395	wpa_printf(MSG_DEBUG, "os_version=%08x",
2396		   WPA_GET_BE32(config->os_version));
2397	return 0;
2398}
2399
2400#endif /* CONFIG_WPS */
2401
2402#ifdef CONFIG_P2P
2403static int wpa_config_process_sec_device_type(
2404	const struct global_parse_data *data,
2405	struct wpa_config *config, int line, const char *pos)
2406{
2407	int idx;
2408
2409	if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) {
2410		wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type "
2411			   "items", line);
2412		return -1;
2413	}
2414
2415	idx = config->num_sec_device_types;
2416
2417	if (wps_dev_type_str2bin(pos, config->sec_device_type[idx]))
2418		return -1;
2419
2420	config->num_sec_device_types++;
2421	return 0;
2422}
2423#endif /* CONFIG_P2P */
2424
2425
2426#ifdef OFFSET
2427#undef OFFSET
2428#endif /* OFFSET */
2429/* OFFSET: Get offset of a variable within the wpa_config structure */
2430#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
2431
2432#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
2433#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
2434#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
2435#define INT(f) _INT(f), NULL, NULL
2436#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
2437#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
2438#define STR(f) _STR(f), NULL, NULL
2439#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
2440
2441static const struct global_parse_data global_fields[] = {
2442#ifdef CONFIG_CTRL_IFACE
2443	{ STR(ctrl_interface), 0 },
2444	{ STR(ctrl_interface_group), 0 } /* deprecated */,
2445#endif /* CONFIG_CTRL_IFACE */
2446	{ INT_RANGE(eapol_version, 1, 2), 0 },
2447	{ INT(ap_scan), 0 },
2448	{ INT(fast_reauth), 0 },
2449	{ STR(opensc_engine_path), 0 },
2450	{ STR(pkcs11_engine_path), 0 },
2451	{ STR(pkcs11_module_path), 0 },
2452	{ STR(driver_param), 0 },
2453	{ INT(dot11RSNAConfigPMKLifetime), 0 },
2454	{ INT(dot11RSNAConfigPMKReauthThreshold), 0 },
2455	{ INT(dot11RSNAConfigSATimeout), 0 },
2456#ifndef CONFIG_NO_CONFIG_WRITE
2457	{ INT(update_config), 0 },
2458#endif /* CONFIG_NO_CONFIG_WRITE */
2459	{ FUNC_NO_VAR(load_dynamic_eap), 0 },
2460#ifdef CONFIG_WPS
2461	{ FUNC(uuid), CFG_CHANGED_UUID },
2462	{ STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME },
2463	{ STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
2464	{ STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
2465	{ STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
2466	{ STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING },
2467	{ FUNC(device_type), CFG_CHANGED_DEVICE_TYPE },
2468	{ FUNC(os_version), CFG_CHANGED_OS_VERSION },
2469	{ STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
2470	{ INT_RANGE(wps_cred_processing, 0, 2), 0 },
2471#endif /* CONFIG_WPS */
2472#ifdef CONFIG_P2P
2473	{ FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
2474	{ INT(p2p_listen_reg_class), 0 },
2475	{ INT(p2p_listen_channel), 0 },
2476	{ INT(p2p_oper_reg_class), 0 },
2477	{ INT(p2p_oper_channel), 0 },
2478	{ INT_RANGE(p2p_go_intent, 0, 15), 0 },
2479	{ STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
2480	{ INT_RANGE(persistent_reconnect, 0, 1), 0 },
2481	{ INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
2482	{ INT(p2p_group_idle), 0 },
2483#endif /* CONFIG_P2P */
2484	{ FUNC(country), CFG_CHANGED_COUNTRY },
2485	{ INT(bss_max_count), 0 },
2486	{ INT(bss_expiration_age), 0 },
2487	{ INT(bss_expiration_scan_count), 0 },
2488	{ INT_RANGE(filter_ssids, 0, 1), 0 },
2489	{ INT(max_num_sta), 0 },
2490	{ INT_RANGE(disassoc_low_ack, 0, 1), 0 }
2491};
2492
2493#undef FUNC
2494#undef _INT
2495#undef INT
2496#undef INT_RANGE
2497#undef _STR
2498#undef STR
2499#undef STR_RANGE
2500#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0]))
2501
2502
2503int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
2504{
2505	size_t i;
2506	int ret = 0;
2507
2508	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
2509		const struct global_parse_data *field = &global_fields[i];
2510		size_t flen = os_strlen(field->name);
2511		if (os_strncmp(pos, field->name, flen) != 0 ||
2512		    pos[flen] != '=')
2513			continue;
2514
2515		if (field->parser(field, config, line, pos + flen + 1)) {
2516			wpa_printf(MSG_ERROR, "Line %d: failed to "
2517				   "parse '%s'.", line, pos);
2518			ret = -1;
2519		}
2520		config->changed_parameters |= field->changed_flag;
2521		break;
2522	}
2523	if (i == NUM_GLOBAL_FIELDS) {
2524		if (line < 0)
2525			return -1;
2526		wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
2527			   line, pos);
2528		ret = -1;
2529	}
2530
2531	return ret;
2532}
2533