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