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