• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/wpa_supplicant/wpa_supplicant/
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 "wpa.h"
19#include "sha1.h"
20#include "eap_peer/eap.h"
21#include "config.h"
22
23
24#if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE)
25#define NO_CONFIG_WRITE
26#endif
27
28/*
29 * Structure for network configuration parsing. This data is used to implement
30 * a generic parser for each network block variable. The table of configuration
31 * variables is defined below in this file (ssid_fields[]).
32 */
33struct parse_data {
34	/* Configuration variable name */
35	char *name;
36
37	/* Parser function for this variable */
38	int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
39		      int line, const char *value);
40
41#ifndef NO_CONFIG_WRITE
42	/* Writer function (i.e., to get the variable in text format from
43	 * internal presentation). */
44	char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
45#endif /* NO_CONFIG_WRITE */
46
47	/* Variable specific parameters for the parser. */
48	void *param1, *param2, *param3, *param4;
49
50	/* 0 = this variable can be included in debug output and ctrl_iface
51	 * 1 = this variable contains key/private data and it must not be
52	 *     included in debug output unless explicitly requested. In
53	 *     addition, this variable will not be readable through the
54	 *     ctrl_iface.
55	 */
56	int key_data;
57};
58
59
60static char * wpa_config_parse_string(const char *value, size_t *len)
61{
62	if (*value == '"') {
63		const char *pos;
64		char *str;
65		value++;
66		pos = os_strrchr(value, '"');
67		if (pos == NULL || pos[1] != '\0')
68			return NULL;
69		*len = pos - value;
70		str = os_malloc(*len + 1);
71		if (str == NULL)
72			return NULL;
73		os_memcpy(str, value, *len);
74		str[*len] = '\0';
75		return str;
76	} else {
77		u8 *str;
78		size_t tlen, hlen = os_strlen(value);
79		if (hlen & 1)
80			return NULL;
81		tlen = hlen / 2;
82		str = os_malloc(tlen + 1);
83		if (str == NULL)
84			return NULL;
85		if (hexstr2bin(value, str, tlen)) {
86			os_free(str);
87			return NULL;
88		}
89		str[tlen] = '\0';
90		*len = tlen;
91		return (char *) str;
92	}
93}
94
95
96static int wpa_config_parse_str(const struct parse_data *data,
97				struct wpa_ssid *ssid,
98				int line, const char *value)
99{
100	size_t res_len, *dst_len;
101	char **dst, *tmp;
102
103	if (os_strcmp(value, "NULL") == 0) {
104		wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
105			   data->name);
106		tmp = NULL;
107		res_len = 0;
108		goto set;
109	}
110
111	tmp = wpa_config_parse_string(value, &res_len);
112	if (tmp == NULL) {
113		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
114			   line, data->name,
115			   data->key_data ? "[KEY DATA REMOVED]" : value);
116		return -1;
117	}
118
119	if (data->key_data) {
120		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
121				      (u8 *) tmp, res_len);
122	} else {
123		wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
124				  (u8 *) tmp, res_len);
125	}
126
127	if (data->param3 && res_len < (size_t) data->param3) {
128		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
129			   "min_len=%ld)", line, data->name,
130			   (unsigned long) res_len, (long) data->param3);
131		os_free(tmp);
132		return -1;
133	}
134
135	if (data->param4 && res_len > (size_t) data->param4) {
136		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
137			   "max_len=%ld)", line, data->name,
138			   (unsigned long) res_len, (long) data->param4);
139		os_free(tmp);
140		return -1;
141	}
142
143set:
144	dst = (char **) (((u8 *) ssid) + (long) data->param1);
145	dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
146	os_free(*dst);
147	*dst = tmp;
148	if (data->param2)
149		*dst_len = res_len;
150
151	return 0;
152}
153
154
155#ifndef NO_CONFIG_WRITE
156static int is_hex(const u8 *data, size_t len)
157{
158	size_t i;
159
160	for (i = 0; i < len; i++) {
161		if (data[i] < 32 || data[i] >= 127)
162			return 1;
163	}
164	return 0;
165}
166
167
168static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
169{
170	char *buf;
171
172	buf = os_malloc(len + 3);
173	if (buf == NULL)
174		return NULL;
175	buf[0] = '"';
176	os_memcpy(buf + 1, value, len);
177	buf[len + 1] = '"';
178	buf[len + 2] = '\0';
179
180	return buf;
181}
182
183
184static char * wpa_config_write_string_hex(const u8 *value, size_t len)
185{
186	char *buf;
187
188	buf = os_zalloc(2 * len + 1);
189	if (buf == NULL)
190		return NULL;
191	wpa_snprintf_hex(buf, 2 * len + 1, value, len);
192
193	return buf;
194}
195
196
197static char * wpa_config_write_string(const u8 *value, size_t len)
198{
199	if (value == NULL)
200		return NULL;
201
202	if (is_hex(value, len))
203		return wpa_config_write_string_hex(value, len);
204	else
205		return wpa_config_write_string_ascii(value, len);
206}
207
208
209static char * wpa_config_write_str(const struct parse_data *data,
210				   struct wpa_ssid *ssid)
211{
212	size_t len;
213	char **src;
214
215	src = (char **) (((u8 *) ssid) + (long) data->param1);
216	if (*src == NULL)
217		return NULL;
218
219	if (data->param2)
220		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
221	else
222		len = os_strlen(*src);
223
224	return wpa_config_write_string((const u8 *) *src, len);
225}
226#endif /* NO_CONFIG_WRITE */
227
228
229static int wpa_config_parse_int(const struct parse_data *data,
230				struct wpa_ssid *ssid,
231				int line, const char *value)
232{
233	int *dst;
234
235	dst = (int *) (((u8 *) ssid) + (long) data->param1);
236	*dst = atoi(value);
237	wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
238
239	if (data->param3 && *dst < (long) data->param3) {
240		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
241			   "min_value=%ld)", line, data->name, *dst,
242			   (long) data->param3);
243		*dst = (long) data->param3;
244		return -1;
245	}
246
247	if (data->param4 && *dst > (long) data->param4) {
248		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
249			   "max_value=%ld)", line, data->name, *dst,
250			   (long) data->param4);
251		*dst = (long) data->param4;
252		return -1;
253	}
254
255	return 0;
256}
257
258
259#ifndef NO_CONFIG_WRITE
260static char * wpa_config_write_int(const struct parse_data *data,
261				   struct wpa_ssid *ssid)
262{
263	int *src, res;
264	char *value;
265
266	src = (int *) (((u8 *) ssid) + (long) data->param1);
267
268	value = os_malloc(20);
269	if (value == NULL)
270		return NULL;
271	res = os_snprintf(value, 20, "%d", *src);
272	if (res < 0 || res >= 20) {
273		os_free(value);
274		return NULL;
275	}
276	value[20 - 1] = '\0';
277	return value;
278}
279#endif /* NO_CONFIG_WRITE */
280
281
282static int wpa_config_parse_bssid(const struct parse_data *data,
283				  struct wpa_ssid *ssid, int line,
284				  const char *value)
285{
286	if (hwaddr_aton(value, ssid->bssid)) {
287		wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
288			   line, value);
289		return -1;
290	}
291	ssid->bssid_set = 1;
292	wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
293	return 0;
294}
295
296
297#ifndef NO_CONFIG_WRITE
298static char * wpa_config_write_bssid(const struct parse_data *data,
299				     struct wpa_ssid *ssid)
300{
301	char *value;
302	int res;
303
304	if (!ssid->bssid_set)
305		return NULL;
306
307	value = os_malloc(20);
308	if (value == NULL)
309		return NULL;
310	res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
311	if (res < 0 || res >= 20) {
312		os_free(value);
313		return NULL;
314	}
315	value[20 - 1] = '\0';
316	return value;
317}
318#endif /* NO_CONFIG_WRITE */
319
320
321static int wpa_config_parse_psk(const struct parse_data *data,
322				struct wpa_ssid *ssid, int line,
323				const char *value)
324{
325	if (*value == '"') {
326#ifndef CONFIG_NO_PBKDF2
327		const char *pos;
328		size_t len;
329
330		value++;
331		pos = os_strrchr(value, '"');
332		if (pos)
333			len = pos - value;
334		else
335			len = os_strlen(value);
336		if (len < 8 || len > 63) {
337			wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
338				   "length %lu (expected: 8..63) '%s'.",
339				   line, (unsigned long) len, value);
340			return -1;
341		}
342		wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
343				      (u8 *) value, len);
344		if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
345		    os_memcmp(ssid->passphrase, value, len) == 0)
346			return 0;
347		ssid->psk_set = 0;
348		os_free(ssid->passphrase);
349		ssid->passphrase = os_malloc(len + 1);
350		if (ssid->passphrase == NULL)
351			return -1;
352		os_memcpy(ssid->passphrase, value, len);
353		ssid->passphrase[len] = '\0';
354		return 0;
355#else /* CONFIG_NO_PBKDF2 */
356		wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
357			   "supported.", line);
358		return -1;
359#endif /* CONFIG_NO_PBKDF2 */
360	}
361
362	if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
363	    value[PMK_LEN * 2] != '\0') {
364		wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
365			   line, value);
366		return -1;
367	}
368
369	os_free(ssid->passphrase);
370	ssid->passphrase = NULL;
371
372	ssid->psk_set = 1;
373	wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
374	return 0;
375}
376
377
378#ifndef NO_CONFIG_WRITE
379static char * wpa_config_write_psk(const struct parse_data *data,
380				   struct wpa_ssid *ssid)
381{
382	if (ssid->passphrase)
383		return wpa_config_write_string_ascii(
384			(const u8 *) ssid->passphrase,
385			os_strlen(ssid->passphrase));
386
387	if (ssid->psk_set)
388		return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
389
390	return NULL;
391}
392#endif /* NO_CONFIG_WRITE */
393
394
395static int wpa_config_parse_proto(const struct parse_data *data,
396				  struct wpa_ssid *ssid, int line,
397				  const char *value)
398{
399	int val = 0, last, errors = 0;
400	char *start, *end, *buf;
401
402	buf = os_strdup(value);
403	if (buf == NULL)
404		return -1;
405	start = buf;
406
407	while (*start != '\0') {
408		while (*start == ' ' || *start == '\t')
409			start++;
410		if (*start == '\0')
411			break;
412		end = start;
413		while (*end != ' ' && *end != '\t' && *end != '\0')
414			end++;
415		last = *end == '\0';
416		*end = '\0';
417		if (os_strcmp(start, "WPA") == 0)
418			val |= WPA_PROTO_WPA;
419		else if (os_strcmp(start, "RSN") == 0 ||
420			 os_strcmp(start, "WPA2") == 0)
421			val |= WPA_PROTO_RSN;
422		else {
423			wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
424				   line, start);
425			errors++;
426		}
427
428		if (last)
429			break;
430		start = end + 1;
431	}
432	os_free(buf);
433
434	if (val == 0) {
435		wpa_printf(MSG_ERROR,
436			   "Line %d: no proto values configured.", line);
437		errors++;
438	}
439
440	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
441	ssid->proto = val;
442	return errors ? -1 : 0;
443}
444
445
446#ifndef NO_CONFIG_WRITE
447static char * wpa_config_write_proto(const struct parse_data *data,
448				     struct wpa_ssid *ssid)
449{
450	int first = 1, ret;
451	char *buf, *pos, *end;
452
453	pos = buf = os_zalloc(10);
454	if (buf == NULL)
455		return NULL;
456	end = buf + 10;
457
458	if (ssid->proto & WPA_PROTO_WPA) {
459		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
460		if (ret < 0 || ret >= end - pos)
461			return buf;
462		pos += ret;
463		first = 0;
464	}
465
466	if (ssid->proto & WPA_PROTO_RSN) {
467		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
468		if (ret < 0 || ret >= end - pos)
469			return buf;
470		pos += ret;
471		first = 0;
472	}
473
474	return buf;
475}
476#endif /* NO_CONFIG_WRITE */
477
478
479static int wpa_config_parse_key_mgmt(const struct parse_data *data,
480				     struct wpa_ssid *ssid, int line,
481				     const char *value)
482{
483	int val = 0, last, errors = 0;
484	char *start, *end, *buf;
485
486	buf = os_strdup(value);
487	if (buf == NULL)
488		return -1;
489	start = buf;
490
491	while (*start != '\0') {
492		while (*start == ' ' || *start == '\t')
493			start++;
494		if (*start == '\0')
495			break;
496		end = start;
497		while (*end != ' ' && *end != '\t' && *end != '\0')
498			end++;
499		last = *end == '\0';
500		*end = '\0';
501		if (os_strcmp(start, "WPA-PSK") == 0)
502			val |= WPA_KEY_MGMT_PSK;
503		else if (os_strcmp(start, "WPA-EAP") == 0)
504			val |= WPA_KEY_MGMT_IEEE8021X;
505		else if (os_strcmp(start, "IEEE8021X") == 0)
506			val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
507		else if (os_strcmp(start, "NONE") == 0)
508			val |= WPA_KEY_MGMT_NONE;
509		else if (os_strcmp(start, "WPA-NONE") == 0)
510			val |= WPA_KEY_MGMT_WPA_NONE;
511#ifdef CONFIG_IEEE80211R
512		else if (os_strcmp(start, "FT-PSK") == 0)
513			val |= WPA_KEY_MGMT_FT_PSK;
514		else if (os_strcmp(start, "FT-EAP") == 0)
515			val |= WPA_KEY_MGMT_FT_IEEE8021X;
516#endif /* CONFIG_IEEE80211R */
517#ifdef CONFIG_IEEE80211W
518		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
519			val |= WPA_KEY_MGMT_PSK_SHA256;
520		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
521			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
522#endif /* CONFIG_IEEE80211W */
523#ifdef CONFIG_WPS
524		else if (os_strcmp(start, "WPS") == 0)
525			val |= WPA_KEY_MGMT_WPS;
526#endif /* CONFIG_WPS */
527		else {
528			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
529				   line, start);
530			errors++;
531		}
532
533		if (last)
534			break;
535		start = end + 1;
536	}
537	os_free(buf);
538
539	if (val == 0) {
540		wpa_printf(MSG_ERROR,
541			   "Line %d: no key_mgmt values configured.", line);
542		errors++;
543	}
544
545	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
546	ssid->key_mgmt = val;
547	return errors ? -1 : 0;
548}
549
550
551#ifndef NO_CONFIG_WRITE
552static char * wpa_config_write_key_mgmt(const struct parse_data *data,
553					struct wpa_ssid *ssid)
554{
555	char *buf, *pos, *end;
556	int ret;
557
558	pos = buf = os_zalloc(50);
559	if (buf == NULL)
560		return NULL;
561	end = buf + 50;
562
563	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
564		ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
565				  pos == buf ? "" : " ");
566		if (ret < 0 || ret >= end - pos) {
567			end[-1] = '\0';
568			return buf;
569		}
570		pos += ret;
571	}
572
573	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
574		ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
575				  pos == buf ? "" : " ");
576		if (ret < 0 || ret >= end - pos) {
577			end[-1] = '\0';
578			return buf;
579		}
580		pos += ret;
581	}
582
583	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
584		ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
585				  pos == buf ? "" : " ");
586		if (ret < 0 || ret >= end - pos) {
587			end[-1] = '\0';
588			return buf;
589		}
590		pos += ret;
591	}
592
593	if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
594		ret = os_snprintf(pos, end - pos, "%sNONE",
595				  pos == buf ? "" : " ");
596		if (ret < 0 || ret >= end - pos) {
597			end[-1] = '\0';
598			return buf;
599		}
600		pos += ret;
601	}
602
603	if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
604		ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
605				  pos == buf ? "" : " ");
606		if (ret < 0 || ret >= end - pos) {
607			end[-1] = '\0';
608			return buf;
609		}
610		pos += ret;
611	}
612
613#ifdef CONFIG_IEEE80211R
614	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK)
615		pos += os_snprintf(pos, end - pos, "%sFT-PSK",
616				   pos == buf ? "" : " ");
617
618	if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
619		pos += os_snprintf(pos, end - pos, "%sFT-EAP",
620				   pos == buf ? "" : " ");
621#endif /* CONFIG_IEEE80211R */
622
623#ifdef CONFIG_IEEE80211W
624	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
625		pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
626				   pos == buf ? "" : " ");
627
628	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
629		pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
630				   pos == buf ? "" : " ");
631#endif /* CONFIG_IEEE80211W */
632
633#ifdef CONFIG_WPS
634	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
635		pos += os_snprintf(pos, end - pos, "%sWPS",
636				   pos == buf ? "" : " ");
637#endif /* CONFIG_WPS */
638
639	return buf;
640}
641#endif /* NO_CONFIG_WRITE */
642
643
644static int wpa_config_parse_cipher(int line, const char *value)
645{
646	int val = 0, last;
647	char *start, *end, *buf;
648
649	buf = os_strdup(value);
650	if (buf == NULL)
651		return -1;
652	start = buf;
653
654	while (*start != '\0') {
655		while (*start == ' ' || *start == '\t')
656			start++;
657		if (*start == '\0')
658			break;
659		end = start;
660		while (*end != ' ' && *end != '\t' && *end != '\0')
661			end++;
662		last = *end == '\0';
663		*end = '\0';
664		if (os_strcmp(start, "CCMP") == 0)
665			val |= WPA_CIPHER_CCMP;
666		else if (os_strcmp(start, "TKIP") == 0)
667			val |= WPA_CIPHER_TKIP;
668		else if (os_strcmp(start, "WEP104") == 0)
669			val |= WPA_CIPHER_WEP104;
670		else if (os_strcmp(start, "WEP40") == 0)
671			val |= WPA_CIPHER_WEP40;
672		else if (os_strcmp(start, "NONE") == 0)
673			val |= WPA_CIPHER_NONE;
674		else {
675			wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
676				   line, start);
677			os_free(buf);
678			return -1;
679		}
680
681		if (last)
682			break;
683		start = end + 1;
684	}
685	os_free(buf);
686
687	if (val == 0) {
688		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
689			   line);
690		return -1;
691	}
692	return val;
693}
694
695
696#ifndef NO_CONFIG_WRITE
697static char * wpa_config_write_cipher(int cipher)
698{
699	char *buf, *pos, *end;
700	int ret;
701
702	pos = buf = os_zalloc(50);
703	if (buf == NULL)
704		return NULL;
705	end = buf + 50;
706
707	if (cipher & WPA_CIPHER_CCMP) {
708		ret = os_snprintf(pos, end - pos, "%sCCMP",
709				  pos == buf ? "" : " ");
710		if (ret < 0 || ret >= end - pos) {
711			end[-1] = '\0';
712			return buf;
713		}
714		pos += ret;
715	}
716
717	if (cipher & WPA_CIPHER_TKIP) {
718		ret = os_snprintf(pos, end - pos, "%sTKIP",
719				  pos == buf ? "" : " ");
720		if (ret < 0 || ret >= end - pos) {
721			end[-1] = '\0';
722			return buf;
723		}
724		pos += ret;
725	}
726
727	if (cipher & WPA_CIPHER_WEP104) {
728		ret = os_snprintf(pos, end - pos, "%sWEP104",
729				  pos == buf ? "" : " ");
730		if (ret < 0 || ret >= end - pos) {
731			end[-1] = '\0';
732			return buf;
733		}
734		pos += ret;
735	}
736
737	if (cipher & WPA_CIPHER_WEP40) {
738		ret = os_snprintf(pos, end - pos, "%sWEP40",
739				  pos == buf ? "" : " ");
740		if (ret < 0 || ret >= end - pos) {
741			end[-1] = '\0';
742			return buf;
743		}
744		pos += ret;
745	}
746
747	if (cipher & WPA_CIPHER_NONE) {
748		ret = os_snprintf(pos, end - pos, "%sNONE",
749				  pos == buf ? "" : " ");
750		if (ret < 0 || ret >= end - pos) {
751			end[-1] = '\0';
752			return buf;
753		}
754		pos += ret;
755	}
756
757	return buf;
758}
759#endif /* NO_CONFIG_WRITE */
760
761
762static int wpa_config_parse_pairwise(const struct parse_data *data,
763				     struct wpa_ssid *ssid, int line,
764				     const char *value)
765{
766	int val;
767	val = wpa_config_parse_cipher(line, value);
768	if (val == -1)
769		return -1;
770	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
771		wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
772			   "(0x%x).", line, val);
773		return -1;
774	}
775
776	wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
777	ssid->pairwise_cipher = val;
778	return 0;
779}
780
781
782#ifndef NO_CONFIG_WRITE
783static char * wpa_config_write_pairwise(const struct parse_data *data,
784					struct wpa_ssid *ssid)
785{
786	return wpa_config_write_cipher(ssid->pairwise_cipher);
787}
788#endif /* NO_CONFIG_WRITE */
789
790
791static int wpa_config_parse_group(const struct parse_data *data,
792				  struct wpa_ssid *ssid, int line,
793				  const char *value)
794{
795	int val;
796	val = wpa_config_parse_cipher(line, value);
797	if (val == -1)
798		return -1;
799	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
800		    WPA_CIPHER_WEP40)) {
801		wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
802			   "(0x%x).", line, val);
803		return -1;
804	}
805
806	wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
807	ssid->group_cipher = val;
808	return 0;
809}
810
811
812#ifndef NO_CONFIG_WRITE
813static char * wpa_config_write_group(const struct parse_data *data,
814				     struct wpa_ssid *ssid)
815{
816	return wpa_config_write_cipher(ssid->group_cipher);
817}
818#endif /* NO_CONFIG_WRITE */
819
820
821static int wpa_config_parse_auth_alg(const struct parse_data *data,
822				     struct wpa_ssid *ssid, int line,
823				     const char *value)
824{
825	int val = 0, last, errors = 0;
826	char *start, *end, *buf;
827
828	buf = os_strdup(value);
829	if (buf == NULL)
830		return -1;
831	start = buf;
832
833	while (*start != '\0') {
834		while (*start == ' ' || *start == '\t')
835			start++;
836		if (*start == '\0')
837			break;
838		end = start;
839		while (*end != ' ' && *end != '\t' && *end != '\0')
840			end++;
841		last = *end == '\0';
842		*end = '\0';
843		if (os_strcmp(start, "OPEN") == 0)
844			val |= WPA_AUTH_ALG_OPEN;
845		else if (os_strcmp(start, "SHARED") == 0)
846			val |= WPA_AUTH_ALG_SHARED;
847		else if (os_strcmp(start, "LEAP") == 0)
848			val |= WPA_AUTH_ALG_LEAP;
849		else {
850			wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
851				   line, start);
852			errors++;
853		}
854
855		if (last)
856			break;
857		start = end + 1;
858	}
859	os_free(buf);
860
861	if (val == 0) {
862		wpa_printf(MSG_ERROR,
863			   "Line %d: no auth_alg values configured.", line);
864		errors++;
865	}
866
867	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
868	ssid->auth_alg = val;
869	return errors ? -1 : 0;
870}
871
872
873#ifndef NO_CONFIG_WRITE
874static char * wpa_config_write_auth_alg(const struct parse_data *data,
875					struct wpa_ssid *ssid)
876{
877	char *buf, *pos, *end;
878	int ret;
879
880	pos = buf = os_zalloc(30);
881	if (buf == NULL)
882		return NULL;
883	end = buf + 30;
884
885	if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
886		ret = os_snprintf(pos, end - pos, "%sOPEN",
887				  pos == buf ? "" : " ");
888		if (ret < 0 || ret >= end - pos) {
889			end[-1] = '\0';
890			return buf;
891		}
892		pos += ret;
893	}
894
895	if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
896		ret = os_snprintf(pos, end - pos, "%sSHARED",
897				  pos == buf ? "" : " ");
898		if (ret < 0 || ret >= end - pos) {
899			end[-1] = '\0';
900			return buf;
901		}
902		pos += ret;
903	}
904
905	if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
906		ret = os_snprintf(pos, end - pos, "%sLEAP",
907				  pos == buf ? "" : " ");
908		if (ret < 0 || ret >= end - pos) {
909			end[-1] = '\0';
910			return buf;
911		}
912		pos += ret;
913	}
914
915	return buf;
916}
917#endif /* NO_CONFIG_WRITE */
918
919
920#ifdef IEEE8021X_EAPOL
921static int wpa_config_parse_eap(const struct parse_data *data,
922				struct wpa_ssid *ssid, int line,
923				const char *value)
924{
925	int last, errors = 0;
926	char *start, *end, *buf;
927	struct eap_method_type *methods = NULL, *tmp;
928	size_t num_methods = 0;
929
930	buf = os_strdup(value);
931	if (buf == NULL)
932		return -1;
933	start = buf;
934
935	while (*start != '\0') {
936		while (*start == ' ' || *start == '\t')
937			start++;
938		if (*start == '\0')
939			break;
940		end = start;
941		while (*end != ' ' && *end != '\t' && *end != '\0')
942			end++;
943		last = *end == '\0';
944		*end = '\0';
945		tmp = methods;
946		methods = os_realloc(methods,
947				     (num_methods + 1) * sizeof(*methods));
948		if (methods == NULL) {
949			os_free(tmp);
950			os_free(buf);
951			return -1;
952		}
953		methods[num_methods].method = eap_peer_get_type(
954			start, &methods[num_methods].vendor);
955		if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
956		    methods[num_methods].method == EAP_TYPE_NONE) {
957			wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
958				   "'%s'", line, start);
959			wpa_printf(MSG_ERROR, "You may need to add support for"
960				   " this EAP method during wpa_supplicant\n"
961				   "build time configuration.\n"
962				   "See README for more information.");
963			errors++;
964		} else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
965			   methods[num_methods].method == EAP_TYPE_LEAP)
966			ssid->leap++;
967		else
968			ssid->non_leap++;
969		num_methods++;
970		if (last)
971			break;
972		start = end + 1;
973	}
974	os_free(buf);
975
976	tmp = methods;
977	methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods));
978	if (methods == NULL) {
979		os_free(tmp);
980		return -1;
981	}
982	methods[num_methods].vendor = EAP_VENDOR_IETF;
983	methods[num_methods].method = EAP_TYPE_NONE;
984	num_methods++;
985
986	wpa_hexdump(MSG_MSGDUMP, "eap methods",
987		    (u8 *) methods, num_methods * sizeof(*methods));
988	ssid->eap.eap_methods = methods;
989	return errors ? -1 : 0;
990}
991
992
993#ifndef NO_CONFIG_WRITE
994static char * wpa_config_write_eap(const struct parse_data *data,
995				   struct wpa_ssid *ssid)
996{
997	int i, ret;
998	char *buf, *pos, *end;
999	const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
1000	const char *name;
1001
1002	if (eap_methods == NULL)
1003		return NULL;
1004
1005	pos = buf = os_zalloc(100);
1006	if (buf == NULL)
1007		return NULL;
1008	end = buf + 100;
1009
1010	for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
1011		     eap_methods[i].method != EAP_TYPE_NONE; i++) {
1012		name = eap_get_name(eap_methods[i].vendor,
1013				    eap_methods[i].method);
1014		if (name) {
1015			ret = os_snprintf(pos, end - pos, "%s%s",
1016					  pos == buf ? "" : " ", name);
1017			if (ret < 0 || ret >= end - pos)
1018				break;
1019			pos += ret;
1020		}
1021	}
1022
1023	end[-1] = '\0';
1024
1025	return buf;
1026}
1027#endif
1028
1029
1030static int wpa_config_parse_password(const struct parse_data *data,
1031				     struct wpa_ssid *ssid, int line,
1032				     const char *value)
1033{
1034	u8 *hash;
1035
1036	if (os_strcmp(value, "NULL") == 0) {
1037		wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
1038		os_free(ssid->eap.password);
1039		ssid->eap.password = NULL;
1040		ssid->eap.password_len = 0;
1041		return 0;
1042	}
1043
1044	if (os_strncmp(value, "hash:", 5) != 0) {
1045		char *tmp;
1046		size_t res_len;
1047
1048		tmp = wpa_config_parse_string(value, &res_len);
1049		if (tmp == NULL) {
1050			wpa_printf(MSG_ERROR, "Line %d: failed to parse "
1051				   "password.", line);
1052			return -1;
1053		}
1054		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
1055				      (u8 *) tmp, res_len);
1056
1057		os_free(ssid->eap.password);
1058		ssid->eap.password = (u8 *) tmp;
1059		ssid->eap.password_len = res_len;
1060		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1061
1062		return 0;
1063	}
1064
1065
1066	/* NtPasswordHash: hash:<32 hex digits> */
1067	if (os_strlen(value + 5) != 2 * 16) {
1068		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
1069			   "(expected 32 hex digits)", line);
1070		return -1;
1071	}
1072
1073	hash = os_malloc(16);
1074	if (hash == NULL)
1075		return -1;
1076
1077	if (hexstr2bin(value + 5, hash, 16)) {
1078		os_free(hash);
1079		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
1080		return -1;
1081	}
1082
1083	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
1084
1085	os_free(ssid->eap.password);
1086	ssid->eap.password = hash;
1087	ssid->eap.password_len = 16;
1088	ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1089
1090	return 0;
1091}
1092
1093
1094#ifndef NO_CONFIG_WRITE
1095static char * wpa_config_write_password(const struct parse_data *data,
1096					struct wpa_ssid *ssid)
1097{
1098	char *buf;
1099
1100	if (ssid->eap.password == NULL)
1101		return NULL;
1102
1103	if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
1104		return wpa_config_write_string(
1105			ssid->eap.password, ssid->eap.password_len);
1106	}
1107
1108	buf = os_malloc(5 + 32 + 1);
1109	if (buf == NULL)
1110		return NULL;
1111
1112	os_memcpy(buf, "hash:", 5);
1113	wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
1114
1115	return buf;
1116}
1117#endif
1118#endif /* IEEE8021X_EAPOL */
1119
1120
1121static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
1122				    const char *value, int idx)
1123{
1124	char *buf, title[20];
1125	int res;
1126
1127	buf = wpa_config_parse_string(value, len);
1128	if (buf == NULL) {
1129		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
1130			   line, idx, value);
1131		return -1;
1132	}
1133	if (*len > MAX_WEP_KEY_LEN) {
1134		wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
1135			   line, idx, value);
1136		os_free(buf);
1137		return -1;
1138	}
1139	os_memcpy(key, buf, *len);
1140	os_free(buf);
1141	res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
1142	if (res >= 0 && (size_t) res < sizeof(title))
1143		wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
1144	return 0;
1145}
1146
1147
1148static int wpa_config_parse_wep_key0(const struct parse_data *data,
1149				     struct wpa_ssid *ssid, int line,
1150				     const char *value)
1151{
1152	return wpa_config_parse_wep_key(ssid->wep_key[0],
1153					&ssid->wep_key_len[0], line,
1154					value, 0);
1155}
1156
1157
1158static int wpa_config_parse_wep_key1(const struct parse_data *data,
1159				     struct wpa_ssid *ssid, int line,
1160				     const char *value)
1161{
1162	return wpa_config_parse_wep_key(ssid->wep_key[1],
1163					&ssid->wep_key_len[1], line,
1164					value, 1);
1165}
1166
1167
1168static int wpa_config_parse_wep_key2(const struct parse_data *data,
1169				     struct wpa_ssid *ssid, int line,
1170				     const char *value)
1171{
1172	return wpa_config_parse_wep_key(ssid->wep_key[2],
1173					&ssid->wep_key_len[2], line,
1174					value, 2);
1175}
1176
1177
1178static int wpa_config_parse_wep_key3(const struct parse_data *data,
1179				     struct wpa_ssid *ssid, int line,
1180				     const char *value)
1181{
1182	return wpa_config_parse_wep_key(ssid->wep_key[3],
1183					&ssid->wep_key_len[3], line,
1184					value, 3);
1185}
1186
1187
1188#ifndef NO_CONFIG_WRITE
1189static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
1190{
1191	if (ssid->wep_key_len[idx] == 0)
1192		return NULL;
1193	return wpa_config_write_string(ssid->wep_key[idx],
1194				       ssid->wep_key_len[idx]);
1195}
1196
1197
1198static char * wpa_config_write_wep_key0(const struct parse_data *data,
1199					struct wpa_ssid *ssid)
1200{
1201	return wpa_config_write_wep_key(ssid, 0);
1202}
1203
1204
1205static char * wpa_config_write_wep_key1(const struct parse_data *data,
1206					struct wpa_ssid *ssid)
1207{
1208	return wpa_config_write_wep_key(ssid, 1);
1209}
1210
1211
1212static char * wpa_config_write_wep_key2(const struct parse_data *data,
1213					struct wpa_ssid *ssid)
1214{
1215	return wpa_config_write_wep_key(ssid, 2);
1216}
1217
1218
1219static char * wpa_config_write_wep_key3(const struct parse_data *data,
1220					struct wpa_ssid *ssid)
1221{
1222	return wpa_config_write_wep_key(ssid, 3);
1223}
1224#endif /* NO_CONFIG_WRITE */
1225
1226
1227/* Helper macros for network block parser */
1228
1229#ifdef OFFSET
1230#undef OFFSET
1231#endif /* OFFSET */
1232/* OFFSET: Get offset of a variable within the wpa_ssid structure */
1233#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
1234
1235/* STR: Define a string variable for an ASCII string; f = field name */
1236#ifdef NO_CONFIG_WRITE
1237#define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
1238#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
1239#else /* NO_CONFIG_WRITE */
1240#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
1241#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
1242#endif /* NO_CONFIG_WRITE */
1243#define STR(f) _STR(f), NULL, NULL, NULL, 0
1244#define STRe(f) _STRe(f), NULL, NULL, NULL, 0
1245#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
1246#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
1247
1248/* STR_LEN: Define a string variable with a separate variable for storing the
1249 * data length. Unlike STR(), this can be used to store arbitrary binary data
1250 * (i.e., even nul termination character). */
1251#define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
1252#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
1253#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
1254#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
1255#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
1256
1257/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
1258 * explicitly specified. */
1259#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
1260#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
1261#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
1262
1263#ifdef NO_CONFIG_WRITE
1264#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
1265#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
1266#else /* NO_CONFIG_WRITE */
1267#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1268	OFFSET(f), (void *) 0
1269#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1270	OFFSET(eap.f), (void *) 0
1271#endif /* NO_CONFIG_WRITE */
1272
1273/* INT: Define an integer variable */
1274#define INT(f) _INT(f), NULL, NULL, 0
1275#define INTe(f) _INTe(f), NULL, NULL, 0
1276
1277/* INT_RANGE: Define an integer variable with allowed value range */
1278#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
1279
1280/* FUNC: Define a configuration variable that uses a custom function for
1281 * parsing and writing the value. */
1282#ifdef NO_CONFIG_WRITE
1283#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
1284#else /* NO_CONFIG_WRITE */
1285#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
1286	NULL, NULL, NULL, NULL
1287#endif /* NO_CONFIG_WRITE */
1288#define FUNC(f) _FUNC(f), 0
1289#define FUNC_KEY(f) _FUNC(f), 1
1290
1291/*
1292 * Table of network configuration variables. This table is used to parse each
1293 * network configuration variable, e.g., each line in wpa_supplicant.conf file
1294 * that is inside a network block.
1295 *
1296 * This table is generated using the helper macros defined above and with
1297 * generous help from the C pre-processor. The field name is stored as a string
1298 * into .name and for STR and INT types, the offset of the target buffer within
1299 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
1300 * offset to the field containing the length of the configuration variable.
1301 * .param3 and .param4 can be used to mark the allowed range (length for STR
1302 * and value for INT).
1303 *
1304 * For each configuration line in wpa_supplicant.conf, the parser goes through
1305 * this table and select the entry that matches with the field name. The parser
1306 * function (.parser) is then called to parse the actual value of the field.
1307 *
1308 * This kind of mechanism makes it easy to add new configuration parameters,
1309 * since only one line needs to be added into this table and into the
1310 * struct wpa_ssid definition if the new variable is either a string or
1311 * integer. More complex types will need to use their own parser and writer
1312 * functions.
1313 */
1314static const struct parse_data ssid_fields[] = {
1315	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1316	{ INT_RANGE(scan_ssid, 0, 1) },
1317	{ FUNC(bssid) },
1318	{ FUNC_KEY(psk) },
1319	{ FUNC(proto) },
1320	{ FUNC(key_mgmt) },
1321	{ FUNC(pairwise) },
1322	{ FUNC(group) },
1323	{ FUNC(auth_alg) },
1324#ifdef IEEE8021X_EAPOL
1325	{ FUNC(eap) },
1326	{ STR_LENe(identity) },
1327	{ STR_LENe(anonymous_identity) },
1328	{ FUNC_KEY(password) },
1329	{ STRe(ca_cert) },
1330	{ STRe(ca_path) },
1331	{ STRe(client_cert) },
1332	{ STRe(private_key) },
1333	{ STR_KEYe(private_key_passwd) },
1334	{ STRe(dh_file) },
1335	{ STRe(subject_match) },
1336	{ STRe(altsubject_match) },
1337	{ STRe(ca_cert2) },
1338	{ STRe(ca_path2) },
1339	{ STRe(client_cert2) },
1340	{ STRe(private_key2) },
1341	{ STR_KEYe(private_key2_passwd) },
1342	{ STRe(dh_file2) },
1343	{ STRe(subject_match2) },
1344	{ STRe(altsubject_match2) },
1345	{ STRe(phase1) },
1346	{ STRe(phase2) },
1347	{ STRe(pcsc) },
1348	{ STR_KEYe(pin) },
1349	{ STRe(engine_id) },
1350	{ STRe(key_id) },
1351	{ STRe(cert_id) },
1352	{ STRe(ca_cert_id) },
1353	{ STR_KEYe(pin2) },
1354	{ STRe(engine2_id) },
1355	{ STRe(key2_id) },
1356	{ STRe(cert2_id) },
1357	{ STRe(ca_cert2_id) },
1358	{ INTe(engine) },
1359	{ INTe(engine2) },
1360	{ INT(eapol_flags) },
1361#endif /* IEEE8021X_EAPOL */
1362	{ FUNC_KEY(wep_key0) },
1363	{ FUNC_KEY(wep_key1) },
1364	{ FUNC_KEY(wep_key2) },
1365	{ FUNC_KEY(wep_key3) },
1366	{ INT(wep_tx_keyidx) },
1367	{ INT(priority) },
1368#ifdef IEEE8021X_EAPOL
1369	{ INT(eap_workaround) },
1370	{ STRe(pac_file) },
1371	{ INTe(fragment_size) },
1372#endif /* IEEE8021X_EAPOL */
1373	{ INT_RANGE(mode, 0, 1) },
1374	{ INT_RANGE(proactive_key_caching, 0, 1) },
1375	{ INT_RANGE(disabled, 0, 1) },
1376	{ STR(id_str) },
1377#ifdef CONFIG_IEEE80211W
1378	{ INT_RANGE(ieee80211w, 0, 2) },
1379#endif /* CONFIG_IEEE80211W */
1380	{ INT_RANGE(peerkey, 0, 1) },
1381	{ INT_RANGE(mixed_cell, 0, 1) },
1382	{ INT_RANGE(frequency, 0, 10000) },
1383	{ INT(wpa_ptk_rekey) }
1384};
1385
1386#undef OFFSET
1387#undef _STR
1388#undef STR
1389#undef STR_KEY
1390#undef _STR_LEN
1391#undef STR_LEN
1392#undef STR_LEN_KEY
1393#undef _STR_RANGE
1394#undef STR_RANGE
1395#undef STR_RANGE_KEY
1396#undef _INT
1397#undef INT
1398#undef INT_RANGE
1399#undef _FUNC
1400#undef FUNC
1401#undef FUNC_KEY
1402#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1403
1404
1405/**
1406 * wpa_config_add_prio_network - Add a network to priority lists
1407 * @config: Configuration data from wpa_config_read()
1408 * @ssid: Pointer to the network configuration to be added to the list
1409 * Returns: 0 on success, -1 on failure
1410 *
1411 * This function is used to add a network block to the priority list of
1412 * networks. This must be called for each network when reading in the full
1413 * configuration. In addition, this can be used indirectly when updating
1414 * priorities by calling wpa_config_update_prio_list().
1415 */
1416int wpa_config_add_prio_network(struct wpa_config *config,
1417				struct wpa_ssid *ssid)
1418{
1419	int prio;
1420	struct wpa_ssid *prev, **nlist;
1421
1422	/*
1423	 * Add to an existing priority list if one is available for the
1424	 * configured priority level for this network.
1425	 */
1426	for (prio = 0; prio < config->num_prio; prio++) {
1427		prev = config->pssid[prio];
1428		if (prev->priority == ssid->priority) {
1429			while (prev->pnext)
1430				prev = prev->pnext;
1431			prev->pnext = ssid;
1432			return 0;
1433		}
1434	}
1435
1436	/* First network for this priority - add a new priority list */
1437	nlist = os_realloc(config->pssid,
1438			   (config->num_prio + 1) * sizeof(struct wpa_ssid *));
1439	if (nlist == NULL)
1440		return -1;
1441
1442	for (prio = 0; prio < config->num_prio; prio++) {
1443		if (nlist[prio]->priority < ssid->priority)
1444			break;
1445	}
1446
1447	os_memmove(&nlist[prio + 1], &nlist[prio],
1448		   (config->num_prio - prio) * sizeof(struct wpa_ssid *));
1449
1450	nlist[prio] = ssid;
1451	config->num_prio++;
1452	config->pssid = nlist;
1453
1454	return 0;
1455}
1456
1457
1458/**
1459 * wpa_config_update_prio_list - Update network priority list
1460 * @config: Configuration data from wpa_config_read()
1461 * Returns: 0 on success, -1 on failure
1462 *
1463 * This function is called to update the priority list of networks in the
1464 * configuration when a network is being added or removed. This is also called
1465 * if a priority for a network is changed.
1466 */
1467static int wpa_config_update_prio_list(struct wpa_config *config)
1468{
1469	struct wpa_ssid *ssid;
1470	int ret = 0;
1471
1472	os_free(config->pssid);
1473	config->pssid = NULL;
1474	config->num_prio = 0;
1475
1476	ssid = config->ssid;
1477	while (ssid) {
1478		ssid->pnext = NULL;
1479		if (wpa_config_add_prio_network(config, ssid) < 0)
1480			ret = -1;
1481		ssid = ssid->next;
1482	}
1483
1484	return ret;
1485}
1486
1487
1488#ifdef IEEE8021X_EAPOL
1489static void eap_peer_config_free(struct eap_peer_config *eap)
1490{
1491	os_free(eap->eap_methods);
1492	os_free(eap->identity);
1493	os_free(eap->anonymous_identity);
1494	os_free(eap->password);
1495	os_free(eap->ca_cert);
1496	os_free(eap->ca_path);
1497	os_free(eap->client_cert);
1498	os_free(eap->private_key);
1499	os_free(eap->private_key_passwd);
1500	os_free(eap->dh_file);
1501	os_free(eap->subject_match);
1502	os_free(eap->altsubject_match);
1503	os_free(eap->ca_cert2);
1504	os_free(eap->ca_path2);
1505	os_free(eap->client_cert2);
1506	os_free(eap->private_key2);
1507	os_free(eap->private_key2_passwd);
1508	os_free(eap->dh_file2);
1509	os_free(eap->subject_match2);
1510	os_free(eap->altsubject_match2);
1511	os_free(eap->phase1);
1512	os_free(eap->phase2);
1513	os_free(eap->pcsc);
1514	os_free(eap->pin);
1515	os_free(eap->engine_id);
1516	os_free(eap->key_id);
1517	os_free(eap->cert_id);
1518	os_free(eap->ca_cert_id);
1519	os_free(eap->key2_id);
1520	os_free(eap->cert2_id);
1521	os_free(eap->ca_cert2_id);
1522	os_free(eap->pin2);
1523	os_free(eap->engine2_id);
1524	os_free(eap->otp);
1525	os_free(eap->pending_req_otp);
1526	os_free(eap->pac_file);
1527	os_free(eap->new_password);
1528}
1529#endif /* IEEE8021X_EAPOL */
1530
1531
1532/**
1533 * wpa_config_free_ssid - Free network/ssid configuration data
1534 * @ssid: Configuration data for the network
1535 *
1536 * This function frees all resources allocated for the network configuration
1537 * data.
1538 */
1539void wpa_config_free_ssid(struct wpa_ssid *ssid)
1540{
1541	os_free(ssid->ssid);
1542	os_free(ssid->passphrase);
1543#ifdef IEEE8021X_EAPOL
1544	eap_peer_config_free(&ssid->eap);
1545#endif /* IEEE8021X_EAPOL */
1546	os_free(ssid->id_str);
1547	os_free(ssid);
1548}
1549
1550
1551/**
1552 * wpa_config_free - Free configuration data
1553 * @config: Configuration data from wpa_config_read()
1554 *
1555 * This function frees all resources allocated for the configuration data by
1556 * wpa_config_read().
1557 */
1558void wpa_config_free(struct wpa_config *config)
1559{
1560#ifndef CONFIG_NO_CONFIG_BLOBS
1561	struct wpa_config_blob *blob, *prevblob;
1562#endif /* CONFIG_NO_CONFIG_BLOBS */
1563	struct wpa_ssid *ssid, *prev = NULL;
1564	ssid = config->ssid;
1565	while (ssid) {
1566		prev = ssid;
1567		ssid = ssid->next;
1568		wpa_config_free_ssid(prev);
1569	}
1570
1571#ifndef CONFIG_NO_CONFIG_BLOBS
1572	blob = config->blobs;
1573	prevblob = NULL;
1574	while (blob) {
1575		prevblob = blob;
1576		blob = blob->next;
1577		wpa_config_free_blob(prevblob);
1578	}
1579#endif /* CONFIG_NO_CONFIG_BLOBS */
1580
1581	os_free(config->ctrl_interface);
1582	os_free(config->ctrl_interface_group);
1583#ifdef EAP_TLS_OPENSSL
1584	os_free(config->opensc_engine_path);
1585	os_free(config->pkcs11_engine_path);
1586	os_free(config->pkcs11_module_path);
1587#endif /* EAP_TLS_OPENSSL */
1588	os_free(config->driver_param);
1589	os_free(config->device_name);
1590	os_free(config->manufacturer);
1591	os_free(config->model_name);
1592	os_free(config->model_number);
1593	os_free(config->serial_number);
1594	os_free(config->device_type);
1595	os_free(config->pssid);
1596	os_free(config);
1597}
1598
1599
1600/**
1601 * wpa_config_get_network - Get configured network based on id
1602 * @config: Configuration data from wpa_config_read()
1603 * @id: Unique network id to search for
1604 * Returns: Network configuration or %NULL if not found
1605 */
1606struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1607{
1608	struct wpa_ssid *ssid;
1609
1610	ssid = config->ssid;
1611	while (ssid) {
1612		if (id == ssid->id)
1613			break;
1614		ssid = ssid->next;
1615	}
1616
1617	return ssid;
1618}
1619
1620
1621/**
1622 * wpa_config_add_network - Add a new network with empty configuration
1623 * @config: Configuration data from wpa_config_read()
1624 * Returns: The new network configuration or %NULL if operation failed
1625 */
1626struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1627{
1628	int id;
1629	struct wpa_ssid *ssid, *last = NULL;
1630
1631	id = -1;
1632	ssid = config->ssid;
1633	while (ssid) {
1634		if (ssid->id > id)
1635			id = ssid->id;
1636		last = ssid;
1637		ssid = ssid->next;
1638	}
1639	id++;
1640
1641	ssid = os_zalloc(sizeof(*ssid));
1642	if (ssid == NULL)
1643		return NULL;
1644	ssid->id = id;
1645	if (last)
1646		last->next = ssid;
1647	else
1648		config->ssid = ssid;
1649
1650	wpa_config_update_prio_list(config);
1651
1652	return ssid;
1653}
1654
1655
1656/**
1657 * wpa_config_remove_network - Remove a configured network based on id
1658 * @config: Configuration data from wpa_config_read()
1659 * @id: Unique network id to search for
1660 * Returns: 0 on success, or -1 if the network was not found
1661 */
1662int wpa_config_remove_network(struct wpa_config *config, int id)
1663{
1664	struct wpa_ssid *ssid, *prev = NULL;
1665
1666	ssid = config->ssid;
1667	while (ssid) {
1668		if (id == ssid->id)
1669			break;
1670		prev = ssid;
1671		ssid = ssid->next;
1672	}
1673
1674	if (ssid == NULL)
1675		return -1;
1676
1677	if (prev)
1678		prev->next = ssid->next;
1679	else
1680		config->ssid = ssid->next;
1681
1682	wpa_config_update_prio_list(config);
1683	wpa_config_free_ssid(ssid);
1684	return 0;
1685}
1686
1687
1688/**
1689 * wpa_config_set_network_defaults - Set network default values
1690 * @ssid: Pointer to network configuration data
1691 */
1692void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
1693{
1694	ssid->proto = DEFAULT_PROTO;
1695	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
1696	ssid->group_cipher = DEFAULT_GROUP;
1697	ssid->key_mgmt = DEFAULT_KEY_MGMT;
1698#ifdef IEEE8021X_EAPOL
1699	ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
1700	ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
1701	ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
1702#endif /* IEEE8021X_EAPOL */
1703}
1704
1705
1706/**
1707 * wpa_config_set - Set a variable in network configuration
1708 * @ssid: Pointer to network configuration data
1709 * @var: Variable name, e.g., "ssid"
1710 * @value: Variable value
1711 * @line: Line number in configuration file or 0 if not used
1712 * Returns: 0 on success, -1 on failure
1713 *
1714 * This function can be used to set network configuration variables based on
1715 * both the configuration file and management interface input. The value
1716 * parameter must be in the same format as the text-based configuration file is
1717 * using. For example, strings are using double quotation marks.
1718 */
1719int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
1720		   int line)
1721{
1722	size_t i;
1723	int ret = 0;
1724
1725	if (ssid == NULL || var == NULL || value == NULL)
1726		return -1;
1727
1728	for (i = 0; i < NUM_SSID_FIELDS; i++) {
1729		const struct parse_data *field = &ssid_fields[i];
1730		if (os_strcmp(var, field->name) != 0)
1731			continue;
1732
1733		if (field->parser(field, ssid, line, value)) {
1734			if (line) {
1735				wpa_printf(MSG_ERROR, "Line %d: failed to "
1736					   "parse %s '%s'.", line, var, value);
1737			}
1738			ret = -1;
1739		}
1740		break;
1741	}
1742	if (i == NUM_SSID_FIELDS) {
1743		if (line) {
1744			wpa_printf(MSG_ERROR, "Line %d: unknown network field "
1745				   "'%s'.", line, var);
1746		}
1747		ret = -1;
1748	}
1749
1750	return ret;
1751}
1752
1753
1754#ifndef NO_CONFIG_WRITE
1755/**
1756 * wpa_config_get - Get a variable in network configuration
1757 * @ssid: Pointer to network configuration data
1758 * @var: Variable name, e.g., "ssid"
1759 * Returns: Value of the variable or %NULL on failure
1760 *
1761 * This function can be used to get network configuration variables. The
1762 * returned value is a copy of the configuration variable in text format, i.e,.
1763 * the same format that the text-based configuration file and wpa_config_set()
1764 * are using for the value. The caller is responsible for freeing the returned
1765 * value.
1766 */
1767char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
1768{
1769	size_t i;
1770
1771	if (ssid == NULL || var == NULL)
1772		return NULL;
1773
1774	for (i = 0; i < NUM_SSID_FIELDS; i++) {
1775		const struct parse_data *field = &ssid_fields[i];
1776		if (os_strcmp(var, field->name) == 0)
1777			return field->writer(field, ssid);
1778	}
1779
1780	return NULL;
1781}
1782
1783
1784/**
1785 * wpa_config_get_no_key - Get a variable in network configuration (no keys)
1786 * @ssid: Pointer to network configuration data
1787 * @var: Variable name, e.g., "ssid"
1788 * Returns: Value of the variable or %NULL on failure
1789 *
1790 * This function can be used to get network configuration variable like
1791 * wpa_config_get(). The only difference is that this functions does not expose
1792 * key/password material from the configuration. In case a key/password field
1793 * is requested, the returned value is an empty string or %NULL if the variable
1794 * is not set or "*" if the variable is set (regardless of its value). The
1795 * returned value is a copy of the configuration variable in text format, i.e,.
1796 * the same format that the text-based configuration file and wpa_config_set()
1797 * are using for the value. The caller is responsible for freeing the returned
1798 * value.
1799 */
1800char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
1801{
1802	size_t i;
1803
1804	if (ssid == NULL || var == NULL)
1805		return NULL;
1806
1807	for (i = 0; i < NUM_SSID_FIELDS; i++) {
1808		const struct parse_data *field = &ssid_fields[i];
1809		if (os_strcmp(var, field->name) == 0) {
1810			char *res = field->writer(field, ssid);
1811			if (field->key_data) {
1812				if (res && res[0]) {
1813					wpa_printf(MSG_DEBUG, "Do not allow "
1814						   "key_data field to be "
1815						   "exposed");
1816					os_free(res);
1817					return os_strdup("*");
1818				}
1819
1820				os_free(res);
1821				return NULL;
1822			}
1823			return res;
1824		}
1825	}
1826
1827	return NULL;
1828}
1829#endif /* NO_CONFIG_WRITE */
1830
1831
1832/**
1833 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
1834 * @ssid: Pointer to network configuration data
1835 *
1836 * This function must be called to update WPA PSK when either SSID or the
1837 * passphrase has changed for the network configuration.
1838 */
1839void wpa_config_update_psk(struct wpa_ssid *ssid)
1840{
1841#ifndef CONFIG_NO_PBKDF2
1842	pbkdf2_sha1(ssid->passphrase,
1843		    (char *) ssid->ssid, ssid->ssid_len, 4096,
1844		    ssid->psk, PMK_LEN);
1845	wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1846			ssid->psk, PMK_LEN);
1847	ssid->psk_set = 1;
1848#endif /* CONFIG_NO_PBKDF2 */
1849}
1850
1851
1852#ifndef CONFIG_NO_CONFIG_BLOBS
1853/**
1854 * wpa_config_get_blob - Get a named configuration blob
1855 * @config: Configuration data from wpa_config_read()
1856 * @name: Name of the blob
1857 * Returns: Pointer to blob data or %NULL if not found
1858 */
1859const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
1860						   const char *name)
1861{
1862	struct wpa_config_blob *blob = config->blobs;
1863
1864	while (blob) {
1865		if (os_strcmp(blob->name, name) == 0)
1866			return blob;
1867		blob = blob->next;
1868	}
1869	return NULL;
1870}
1871
1872
1873/**
1874 * wpa_config_set_blob - Set or add a named configuration blob
1875 * @config: Configuration data from wpa_config_read()
1876 * @blob: New value for the blob
1877 *
1878 * Adds a new configuration blob or replaces the current value of an existing
1879 * blob.
1880 */
1881void wpa_config_set_blob(struct wpa_config *config,
1882			 struct wpa_config_blob *blob)
1883{
1884	wpa_config_remove_blob(config, blob->name);
1885	blob->next = config->blobs;
1886	config->blobs = blob;
1887}
1888
1889
1890/**
1891 * wpa_config_free_blob - Free blob data
1892 * @blob: Pointer to blob to be freed
1893 */
1894void wpa_config_free_blob(struct wpa_config_blob *blob)
1895{
1896	if (blob) {
1897		os_free(blob->name);
1898		os_free(blob->data);
1899		os_free(blob);
1900	}
1901}
1902
1903
1904/**
1905 * wpa_config_remove_blob - Remove a named configuration blob
1906 * @config: Configuration data from wpa_config_read()
1907 * @name: Name of the blob to remove
1908 * Returns: 0 if blob was removed or -1 if blob was not found
1909 */
1910int wpa_config_remove_blob(struct wpa_config *config, const char *name)
1911{
1912	struct wpa_config_blob *pos = config->blobs, *prev = NULL;
1913
1914	while (pos) {
1915		if (os_strcmp(pos->name, name) == 0) {
1916			if (prev)
1917				prev->next = pos->next;
1918			else
1919				config->blobs = pos->next;
1920			wpa_config_free_blob(pos);
1921			return 0;
1922		}
1923		prev = pos;
1924		pos = pos->next;
1925	}
1926
1927	return -1;
1928}
1929#endif /* CONFIG_NO_CONFIG_BLOBS */
1930
1931
1932/**
1933 * wpa_config_alloc_empty - Allocate an empty configuration
1934 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
1935 * socket
1936 * @driver_param: Driver parameters
1937 * Returns: Pointer to allocated configuration data or %NULL on failure
1938 */
1939struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
1940					   const char *driver_param)
1941{
1942	struct wpa_config *config;
1943
1944	config = os_zalloc(sizeof(*config));
1945	if (config == NULL)
1946		return NULL;
1947	config->eapol_version = DEFAULT_EAPOL_VERSION;
1948	config->ap_scan = DEFAULT_AP_SCAN;
1949	config->fast_reauth = DEFAULT_FAST_REAUTH;
1950
1951	if (ctrl_interface)
1952		config->ctrl_interface = os_strdup(ctrl_interface);
1953	if (driver_param)
1954		config->driver_param = os_strdup(driver_param);
1955
1956	return config;
1957}
1958
1959
1960#ifndef CONFIG_NO_STDOUT_DEBUG
1961/**
1962 * wpa_config_debug_dump_networks - Debug dump of configured networks
1963 * @config: Configuration data from wpa_config_read()
1964 */
1965void wpa_config_debug_dump_networks(struct wpa_config *config)
1966{
1967	int prio;
1968	struct wpa_ssid *ssid;
1969
1970	for (prio = 0; prio < config->num_prio; prio++) {
1971		ssid = config->pssid[prio];
1972		wpa_printf(MSG_DEBUG, "Priority group %d",
1973			   ssid->priority);
1974		while (ssid) {
1975			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
1976				   ssid->id,
1977				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1978			ssid = ssid->pnext;
1979		}
1980	}
1981}
1982#endif /* CONFIG_NO_STDOUT_DEBUG */
1983