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