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