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