blob: 19c810b475a8c2d3a530404a95f53abafb771928 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
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 "utils/uuid.h"
19#include "crypto/sha1.h"
20#include "rsn_supp/wpa.h"
21#include "eap_peer/eap.h"
22#include "config.h"
23
24
25#if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE)
26#define NO_CONFIG_WRITE
27#endif
28
29/*
30 * Structure for network configuration parsing. This data is used to implement
31 * a generic parser for each network block variable. The table of configuration
32 * variables is defined below in this file (ssid_fields[]).
33 */
34struct parse_data {
35 /* Configuration variable name */
36 char *name;
37
38 /* Parser function for this variable */
39 int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
40 int line, const char *value);
41
42#ifndef NO_CONFIG_WRITE
43 /* Writer function (i.e., to get the variable in text format from
44 * internal presentation). */
45 char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
46#endif /* NO_CONFIG_WRITE */
47
48 /* Variable specific parameters for the parser. */
49 void *param1, *param2, *param3, *param4;
50
51 /* 0 = this variable can be included in debug output and ctrl_iface
52 * 1 = this variable contains key/private data and it must not be
53 * included in debug output unless explicitly requested. In
54 * addition, this variable will not be readable through the
55 * ctrl_iface.
56 */
57 int key_data;
58};
59
60
61static char * wpa_config_parse_string(const char *value, size_t *len)
62{
63 if (*value == '"') {
64 const char *pos;
65 char *str;
66 value++;
67 pos = os_strrchr(value, '"');
68 if (pos == NULL || pos[1] != '\0')
69 return NULL;
70 *len = pos - value;
71 str = os_malloc(*len + 1);
72 if (str == NULL)
73 return NULL;
74 os_memcpy(str, value, *len);
75 str[*len] = '\0';
76 return str;
77 } else {
78 u8 *str;
79 size_t tlen, hlen = os_strlen(value);
80 if (hlen & 1)
81 return NULL;
82 tlen = hlen / 2;
83 str = os_malloc(tlen + 1);
84 if (str == NULL)
85 return NULL;
86 if (hexstr2bin(value, str, tlen)) {
87 os_free(str);
88 return NULL;
89 }
90 str[tlen] = '\0';
91 *len = tlen;
92 return (char *) str;
93 }
94}
95
96
97static int wpa_config_parse_str(const struct parse_data *data,
98 struct wpa_ssid *ssid,
99 int line, const char *value)
100{
101 size_t res_len, *dst_len;
102 char **dst, *tmp;
103
104 if (os_strcmp(value, "NULL") == 0) {
105 wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
106 data->name);
107 tmp = NULL;
108 res_len = 0;
109 goto set;
110 }
111
112 tmp = wpa_config_parse_string(value, &res_len);
113 if (tmp == NULL) {
114 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
115 line, data->name,
116 data->key_data ? "[KEY DATA REMOVED]" : value);
117 return -1;
118 }
119
120 if (data->key_data) {
121 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
122 (u8 *) tmp, res_len);
123 } else {
124 wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
125 (u8 *) tmp, res_len);
126 }
127
128 if (data->param3 && res_len < (size_t) data->param3) {
129 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
130 "min_len=%ld)", line, data->name,
131 (unsigned long) res_len, (long) data->param3);
132 os_free(tmp);
133 return -1;
134 }
135
136 if (data->param4 && res_len > (size_t) data->param4) {
137 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
138 "max_len=%ld)", line, data->name,
139 (unsigned long) res_len, (long) data->param4);
140 os_free(tmp);
141 return -1;
142 }
143
144set:
145 dst = (char **) (((u8 *) ssid) + (long) data->param1);
146 dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
147 os_free(*dst);
148 *dst = tmp;
149 if (data->param2)
150 *dst_len = res_len;
151
152 return 0;
153}
154
155
156#ifndef NO_CONFIG_WRITE
157static int is_hex(const u8 *data, size_t len)
158{
159 size_t i;
160
161 for (i = 0; i < len; i++) {
162 if (data[i] < 32 || data[i] >= 127)
163 return 1;
164 }
165 return 0;
166}
167
168
169static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
170{
171 char *buf;
172
173 buf = os_malloc(len + 3);
174 if (buf == NULL)
175 return NULL;
176 buf[0] = '"';
177 os_memcpy(buf + 1, value, len);
178 buf[len + 1] = '"';
179 buf[len + 2] = '\0';
180
181 return buf;
182}
183
184
185static char * wpa_config_write_string_hex(const u8 *value, size_t len)
186{
187 char *buf;
188
189 buf = os_zalloc(2 * len + 1);
190 if (buf == NULL)
191 return NULL;
192 wpa_snprintf_hex(buf, 2 * len + 1, value, len);
193
194 return buf;
195}
196
197
198static char * wpa_config_write_string(const u8 *value, size_t len)
199{
200 if (value == NULL)
201 return NULL;
202
203 if (is_hex(value, len))
204 return wpa_config_write_string_hex(value, len);
205 else
206 return wpa_config_write_string_ascii(value, len);
207}
208
209
210static char * wpa_config_write_str(const struct parse_data *data,
211 struct wpa_ssid *ssid)
212{
213 size_t len;
214 char **src;
215
216 src = (char **) (((u8 *) ssid) + (long) data->param1);
217 if (*src == NULL)
218 return NULL;
219
220 if (data->param2)
221 len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
222 else
223 len = os_strlen(*src);
224
225 return wpa_config_write_string((const u8 *) *src, len);
226}
Dmitry Shmidtc5da5d22011-07-15 15:32:26 -0700227
228#ifdef WPA_UNICODE_SSID
229static char * wpa_config_write_str_unicode(const struct parse_data *data,
230 struct wpa_ssid *ssid)
231{
232 size_t len;
233 char **src;
234
235 src = (char **) (((u8 *) ssid) + (long) data->param1);
236 if (*src == NULL)
237 return NULL;
238
239 if (data->param2)
240 len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
241 else
242 len = os_strlen(*src);
243
244 return wpa_config_write_string_ascii((const u8 *) *src, len);
245}
246#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700247#endif /* NO_CONFIG_WRITE */
248
249
250static int wpa_config_parse_int(const struct parse_data *data,
251 struct wpa_ssid *ssid,
252 int line, const char *value)
253{
254 int *dst;
255
256 dst = (int *) (((u8 *) ssid) + (long) data->param1);
257 *dst = atoi(value);
258 wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
259
260 if (data->param3 && *dst < (long) data->param3) {
261 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
262 "min_value=%ld)", line, data->name, *dst,
263 (long) data->param3);
264 *dst = (long) data->param3;
265 return -1;
266 }
267
268 if (data->param4 && *dst > (long) data->param4) {
269 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
270 "max_value=%ld)", line, data->name, *dst,
271 (long) data->param4);
272 *dst = (long) data->param4;
273 return -1;
274 }
275
276 return 0;
277}
278
279
280#ifndef NO_CONFIG_WRITE
281static char * wpa_config_write_int(const struct parse_data *data,
282 struct wpa_ssid *ssid)
283{
284 int *src, res;
285 char *value;
286
287 src = (int *) (((u8 *) ssid) + (long) data->param1);
288
289 value = os_malloc(20);
290 if (value == NULL)
291 return NULL;
292 res = os_snprintf(value, 20, "%d", *src);
293 if (res < 0 || res >= 20) {
294 os_free(value);
295 return NULL;
296 }
297 value[20 - 1] = '\0';
298 return value;
299}
300#endif /* NO_CONFIG_WRITE */
301
302
303static int wpa_config_parse_bssid(const struct parse_data *data,
304 struct wpa_ssid *ssid, int line,
305 const char *value)
306{
307 if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
308 os_strcmp(value, "any") == 0) {
309 ssid->bssid_set = 0;
310 wpa_printf(MSG_MSGDUMP, "BSSID any");
311 return 0;
312 }
313 if (hwaddr_aton(value, ssid->bssid)) {
314 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
315 line, value);
316 return -1;
317 }
318 ssid->bssid_set = 1;
319 wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
320 return 0;
321}
322
323
324#ifndef NO_CONFIG_WRITE
325static char * wpa_config_write_bssid(const struct parse_data *data,
326 struct wpa_ssid *ssid)
327{
328 char *value;
329 int res;
330
331 if (!ssid->bssid_set)
332 return NULL;
333
334 value = os_malloc(20);
335 if (value == NULL)
336 return NULL;
337 res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
338 if (res < 0 || res >= 20) {
339 os_free(value);
340 return NULL;
341 }
342 value[20 - 1] = '\0';
343 return value;
344}
345#endif /* NO_CONFIG_WRITE */
346
347
348static int wpa_config_parse_psk(const struct parse_data *data,
349 struct wpa_ssid *ssid, int line,
350 const char *value)
351{
352 if (*value == '"') {
353#ifndef CONFIG_NO_PBKDF2
354 const char *pos;
355 size_t len;
356
357 value++;
358 pos = os_strrchr(value, '"');
359 if (pos)
360 len = pos - value;
361 else
362 len = os_strlen(value);
363 if (len < 8 || len > 63) {
364 wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
365 "length %lu (expected: 8..63) '%s'.",
366 line, (unsigned long) len, value);
367 return -1;
368 }
369 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
370 (u8 *) value, len);
371 if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
372 os_memcmp(ssid->passphrase, value, len) == 0)
373 return 0;
374 ssid->psk_set = 0;
375 os_free(ssid->passphrase);
376 ssid->passphrase = os_malloc(len + 1);
377 if (ssid->passphrase == NULL)
378 return -1;
379 os_memcpy(ssid->passphrase, value, len);
380 ssid->passphrase[len] = '\0';
381 return 0;
382#else /* CONFIG_NO_PBKDF2 */
383 wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
384 "supported.", line);
385 return -1;
386#endif /* CONFIG_NO_PBKDF2 */
387 }
388
389 if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
390 value[PMK_LEN * 2] != '\0') {
391 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
392 line, value);
393 return -1;
394 }
395
396 os_free(ssid->passphrase);
397 ssid->passphrase = NULL;
398
399 ssid->psk_set = 1;
400 wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
401 return 0;
402}
403
404
405#ifndef NO_CONFIG_WRITE
406static char * wpa_config_write_psk(const struct parse_data *data,
407 struct wpa_ssid *ssid)
408{
409 if (ssid->passphrase)
410 return wpa_config_write_string_ascii(
411 (const u8 *) ssid->passphrase,
412 os_strlen(ssid->passphrase));
413
414 if (ssid->psk_set)
415 return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
416
417 return NULL;
418}
419#endif /* NO_CONFIG_WRITE */
420
421
422static int wpa_config_parse_proto(const struct parse_data *data,
423 struct wpa_ssid *ssid, int line,
424 const char *value)
425{
426 int val = 0, last, errors = 0;
427 char *start, *end, *buf;
428
429 buf = os_strdup(value);
430 if (buf == NULL)
431 return -1;
432 start = buf;
433
434 while (*start != '\0') {
435 while (*start == ' ' || *start == '\t')
436 start++;
437 if (*start == '\0')
438 break;
439 end = start;
440 while (*end != ' ' && *end != '\t' && *end != '\0')
441 end++;
442 last = *end == '\0';
443 *end = '\0';
444 if (os_strcmp(start, "WPA") == 0)
445 val |= WPA_PROTO_WPA;
446 else if (os_strcmp(start, "RSN") == 0 ||
447 os_strcmp(start, "WPA2") == 0)
448 val |= WPA_PROTO_RSN;
449 else {
450 wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
451 line, start);
452 errors++;
453 }
454
455 if (last)
456 break;
457 start = end + 1;
458 }
459 os_free(buf);
460
461 if (val == 0) {
462 wpa_printf(MSG_ERROR,
463 "Line %d: no proto values configured.", line);
464 errors++;
465 }
466
467 wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
468 ssid->proto = val;
469 return errors ? -1 : 0;
470}
471
472
473#ifndef NO_CONFIG_WRITE
474static char * wpa_config_write_proto(const struct parse_data *data,
475 struct wpa_ssid *ssid)
476{
477 int first = 1, ret;
478 char *buf, *pos, *end;
479
480 pos = buf = os_zalloc(10);
481 if (buf == NULL)
482 return NULL;
483 end = buf + 10;
484
485 if (ssid->proto & WPA_PROTO_WPA) {
486 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
487 if (ret < 0 || ret >= end - pos)
488 return buf;
489 pos += ret;
490 first = 0;
491 }
492
493 if (ssid->proto & WPA_PROTO_RSN) {
494 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
495 if (ret < 0 || ret >= end - pos)
496 return buf;
497 pos += ret;
498 first = 0;
499 }
500
501 return buf;
502}
503#endif /* NO_CONFIG_WRITE */
504
505
506static int wpa_config_parse_key_mgmt(const struct parse_data *data,
507 struct wpa_ssid *ssid, int line,
508 const char *value)
509{
510 int val = 0, last, errors = 0;
511 char *start, *end, *buf;
512
513 buf = os_strdup(value);
514 if (buf == NULL)
515 return -1;
516 start = buf;
517
518 while (*start != '\0') {
519 while (*start == ' ' || *start == '\t')
520 start++;
521 if (*start == '\0')
522 break;
523 end = start;
524 while (*end != ' ' && *end != '\t' && *end != '\0')
525 end++;
526 last = *end == '\0';
527 *end = '\0';
528 if (os_strcmp(start, "WPA-PSK") == 0)
529 val |= WPA_KEY_MGMT_PSK;
530 else if (os_strcmp(start, "WPA-EAP") == 0)
531 val |= WPA_KEY_MGMT_IEEE8021X;
532 else if (os_strcmp(start, "IEEE8021X") == 0)
533 val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
534 else if (os_strcmp(start, "NONE") == 0)
535 val |= WPA_KEY_MGMT_NONE;
536 else if (os_strcmp(start, "WPA-NONE") == 0)
537 val |= WPA_KEY_MGMT_WPA_NONE;
538#ifdef CONFIG_IEEE80211R
539 else if (os_strcmp(start, "FT-PSK") == 0)
540 val |= WPA_KEY_MGMT_FT_PSK;
541 else if (os_strcmp(start, "FT-EAP") == 0)
542 val |= WPA_KEY_MGMT_FT_IEEE8021X;
543#endif /* CONFIG_IEEE80211R */
544#ifdef CONFIG_IEEE80211W
545 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
546 val |= WPA_KEY_MGMT_PSK_SHA256;
547 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
548 val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
549#endif /* CONFIG_IEEE80211W */
550#ifdef CONFIG_WPS
551 else if (os_strcmp(start, "WPS") == 0)
552 val |= WPA_KEY_MGMT_WPS;
553#endif /* CONFIG_WPS */
554 else {
555 wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
556 line, start);
557 errors++;
558 }
559
560 if (last)
561 break;
562 start = end + 1;
563 }
564 os_free(buf);
565
566 if (val == 0) {
567 wpa_printf(MSG_ERROR,
568 "Line %d: no key_mgmt values configured.", line);
569 errors++;
570 }
571
572 wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
573 ssid->key_mgmt = val;
574 return errors ? -1 : 0;
575}
576
577
578#ifndef NO_CONFIG_WRITE
579static char * wpa_config_write_key_mgmt(const struct parse_data *data,
580 struct wpa_ssid *ssid)
581{
582 char *buf, *pos, *end;
583 int ret;
584
585 pos = buf = os_zalloc(50);
586 if (buf == NULL)
587 return NULL;
588 end = buf + 50;
589
590 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
591 ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
592 pos == buf ? "" : " ");
593 if (ret < 0 || ret >= end - pos) {
594 end[-1] = '\0';
595 return buf;
596 }
597 pos += ret;
598 }
599
600 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
601 ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
602 pos == buf ? "" : " ");
603 if (ret < 0 || ret >= end - pos) {
604 end[-1] = '\0';
605 return buf;
606 }
607 pos += ret;
608 }
609
610 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
611 ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
612 pos == buf ? "" : " ");
613 if (ret < 0 || ret >= end - pos) {
614 end[-1] = '\0';
615 return buf;
616 }
617 pos += ret;
618 }
619
620 if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
621 ret = os_snprintf(pos, end - pos, "%sNONE",
622 pos == buf ? "" : " ");
623 if (ret < 0 || ret >= end - pos) {
624 end[-1] = '\0';
625 return buf;
626 }
627 pos += ret;
628 }
629
630 if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
631 ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
632 pos == buf ? "" : " ");
633 if (ret < 0 || ret >= end - pos) {
634 end[-1] = '\0';
635 return buf;
636 }
637 pos += ret;
638 }
639
640#ifdef CONFIG_IEEE80211R
641 if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK)
642 pos += os_snprintf(pos, end - pos, "%sFT-PSK",
643 pos == buf ? "" : " ");
644
645 if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
646 pos += os_snprintf(pos, end - pos, "%sFT-EAP",
647 pos == buf ? "" : " ");
648#endif /* CONFIG_IEEE80211R */
649
650#ifdef CONFIG_IEEE80211W
651 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
652 pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
653 pos == buf ? "" : " ");
654
655 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
656 pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
657 pos == buf ? "" : " ");
658#endif /* CONFIG_IEEE80211W */
659
660#ifdef CONFIG_WPS
661 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
662 pos += os_snprintf(pos, end - pos, "%sWPS",
663 pos == buf ? "" : " ");
664#endif /* CONFIG_WPS */
665
666 return buf;
667}
668#endif /* NO_CONFIG_WRITE */
669
670
671static int wpa_config_parse_cipher(int line, const char *value)
672{
673 int val = 0, last;
674 char *start, *end, *buf;
675
676 buf = os_strdup(value);
677 if (buf == NULL)
678 return -1;
679 start = buf;
680
681 while (*start != '\0') {
682 while (*start == ' ' || *start == '\t')
683 start++;
684 if (*start == '\0')
685 break;
686 end = start;
687 while (*end != ' ' && *end != '\t' && *end != '\0')
688 end++;
689 last = *end == '\0';
690 *end = '\0';
691 if (os_strcmp(start, "CCMP") == 0)
692 val |= WPA_CIPHER_CCMP;
693 else if (os_strcmp(start, "TKIP") == 0)
694 val |= WPA_CIPHER_TKIP;
695 else if (os_strcmp(start, "WEP104") == 0)
696 val |= WPA_CIPHER_WEP104;
697 else if (os_strcmp(start, "WEP40") == 0)
698 val |= WPA_CIPHER_WEP40;
699 else if (os_strcmp(start, "NONE") == 0)
700 val |= WPA_CIPHER_NONE;
701 else {
702 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
703 line, start);
704 os_free(buf);
705 return -1;
706 }
707
708 if (last)
709 break;
710 start = end + 1;
711 }
712 os_free(buf);
713
714 if (val == 0) {
715 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
716 line);
717 return -1;
718 }
719 return val;
720}
721
722
723#ifndef NO_CONFIG_WRITE
724static char * wpa_config_write_cipher(int cipher)
725{
726 char *buf, *pos, *end;
727 int ret;
728
729 pos = buf = os_zalloc(50);
730 if (buf == NULL)
731 return NULL;
732 end = buf + 50;
733
734 if (cipher & WPA_CIPHER_CCMP) {
735 ret = os_snprintf(pos, end - pos, "%sCCMP",
736 pos == buf ? "" : " ");
737 if (ret < 0 || ret >= end - pos) {
738 end[-1] = '\0';
739 return buf;
740 }
741 pos += ret;
742 }
743
744 if (cipher & WPA_CIPHER_TKIP) {
745 ret = os_snprintf(pos, end - pos, "%sTKIP",
746 pos == buf ? "" : " ");
747 if (ret < 0 || ret >= end - pos) {
748 end[-1] = '\0';
749 return buf;
750 }
751 pos += ret;
752 }
753
754 if (cipher & WPA_CIPHER_WEP104) {
755 ret = os_snprintf(pos, end - pos, "%sWEP104",
756 pos == buf ? "" : " ");
757 if (ret < 0 || ret >= end - pos) {
758 end[-1] = '\0';
759 return buf;
760 }
761 pos += ret;
762 }
763
764 if (cipher & WPA_CIPHER_WEP40) {
765 ret = os_snprintf(pos, end - pos, "%sWEP40",
766 pos == buf ? "" : " ");
767 if (ret < 0 || ret >= end - pos) {
768 end[-1] = '\0';
769 return buf;
770 }
771 pos += ret;
772 }
773
774 if (cipher & WPA_CIPHER_NONE) {
775 ret = os_snprintf(pos, end - pos, "%sNONE",
776 pos == buf ? "" : " ");
777 if (ret < 0 || ret >= end - pos) {
778 end[-1] = '\0';
779 return buf;
780 }
781 pos += ret;
782 }
783
784 return buf;
785}
786#endif /* NO_CONFIG_WRITE */
787
788
789static int wpa_config_parse_pairwise(const struct parse_data *data,
790 struct wpa_ssid *ssid, int line,
791 const char *value)
792{
793 int val;
794 val = wpa_config_parse_cipher(line, value);
795 if (val == -1)
796 return -1;
797 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
798 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
799 "(0x%x).", line, val);
800 return -1;
801 }
802
803 wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
804 ssid->pairwise_cipher = val;
805 return 0;
806}
807
808
809#ifndef NO_CONFIG_WRITE
810static char * wpa_config_write_pairwise(const struct parse_data *data,
811 struct wpa_ssid *ssid)
812{
813 return wpa_config_write_cipher(ssid->pairwise_cipher);
814}
815#endif /* NO_CONFIG_WRITE */
816
817
818static int wpa_config_parse_group(const struct parse_data *data,
819 struct wpa_ssid *ssid, int line,
820 const char *value)
821{
822 int val;
823 val = wpa_config_parse_cipher(line, value);
824 if (val == -1)
825 return -1;
826 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
827 WPA_CIPHER_WEP40)) {
828 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
829 "(0x%x).", line, val);
830 return -1;
831 }
832
833 wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
834 ssid->group_cipher = val;
835 return 0;
836}
837
838
839#ifndef NO_CONFIG_WRITE
840static char * wpa_config_write_group(const struct parse_data *data,
841 struct wpa_ssid *ssid)
842{
843 return wpa_config_write_cipher(ssid->group_cipher);
844}
845#endif /* NO_CONFIG_WRITE */
846
847
848static int wpa_config_parse_auth_alg(const struct parse_data *data,
849 struct wpa_ssid *ssid, int line,
850 const char *value)
851{
852 int val = 0, last, errors = 0;
853 char *start, *end, *buf;
854
855 buf = os_strdup(value);
856 if (buf == NULL)
857 return -1;
858 start = buf;
859
860 while (*start != '\0') {
861 while (*start == ' ' || *start == '\t')
862 start++;
863 if (*start == '\0')
864 break;
865 end = start;
866 while (*end != ' ' && *end != '\t' && *end != '\0')
867 end++;
868 last = *end == '\0';
869 *end = '\0';
870 if (os_strcmp(start, "OPEN") == 0)
871 val |= WPA_AUTH_ALG_OPEN;
872 else if (os_strcmp(start, "SHARED") == 0)
873 val |= WPA_AUTH_ALG_SHARED;
874 else if (os_strcmp(start, "LEAP") == 0)
875 val |= WPA_AUTH_ALG_LEAP;
876 else {
877 wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
878 line, start);
879 errors++;
880 }
881
882 if (last)
883 break;
884 start = end + 1;
885 }
886 os_free(buf);
887
888 if (val == 0) {
889 wpa_printf(MSG_ERROR,
890 "Line %d: no auth_alg values configured.", line);
891 errors++;
892 }
893
894 wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
895 ssid->auth_alg = val;
896 return errors ? -1 : 0;
897}
898
899
900#ifndef NO_CONFIG_WRITE
901static char * wpa_config_write_auth_alg(const struct parse_data *data,
902 struct wpa_ssid *ssid)
903{
904 char *buf, *pos, *end;
905 int ret;
906
907 pos = buf = os_zalloc(30);
908 if (buf == NULL)
909 return NULL;
910 end = buf + 30;
911
912 if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
913 ret = os_snprintf(pos, end - pos, "%sOPEN",
914 pos == buf ? "" : " ");
915 if (ret < 0 || ret >= end - pos) {
916 end[-1] = '\0';
917 return buf;
918 }
919 pos += ret;
920 }
921
922 if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
923 ret = os_snprintf(pos, end - pos, "%sSHARED",
924 pos == buf ? "" : " ");
925 if (ret < 0 || ret >= end - pos) {
926 end[-1] = '\0';
927 return buf;
928 }
929 pos += ret;
930 }
931
932 if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
933 ret = os_snprintf(pos, end - pos, "%sLEAP",
934 pos == buf ? "" : " ");
935 if (ret < 0 || ret >= end - pos) {
936 end[-1] = '\0';
937 return buf;
938 }
939 pos += ret;
940 }
941
942 return buf;
943}
944#endif /* NO_CONFIG_WRITE */
945
946
947static int * wpa_config_parse_freqs(const struct parse_data *data,
948 struct wpa_ssid *ssid, int line,
949 const char *value)
950{
951 int *freqs;
952 size_t used, len;
953 const char *pos;
954
955 used = 0;
956 len = 10;
957 freqs = os_zalloc((len + 1) * sizeof(int));
958 if (freqs == NULL)
959 return NULL;
960
961 pos = value;
962 while (pos) {
963 while (*pos == ' ')
964 pos++;
965 if (used == len) {
966 int *n;
967 size_t i;
968 n = os_realloc(freqs, (len * 2 + 1) * sizeof(int));
969 if (n == NULL) {
970 os_free(freqs);
971 return NULL;
972 }
973 for (i = len; i <= len * 2; i++)
974 n[i] = 0;
975 freqs = n;
976 len *= 2;
977 }
978
979 freqs[used] = atoi(pos);
980 if (freqs[used] == 0)
981 break;
982 used++;
983 pos = os_strchr(pos + 1, ' ');
984 }
985
986 return freqs;
987}
988
989
990static int wpa_config_parse_scan_freq(const struct parse_data *data,
991 struct wpa_ssid *ssid, int line,
992 const char *value)
993{
994 int *freqs;
995
996 freqs = wpa_config_parse_freqs(data, ssid, line, value);
997 if (freqs == NULL)
998 return -1;
999 os_free(ssid->scan_freq);
1000 ssid->scan_freq = freqs;
1001
1002 return 0;
1003}
1004
1005
1006static int wpa_config_parse_freq_list(const struct parse_data *data,
1007 struct wpa_ssid *ssid, int line,
1008 const char *value)
1009{
1010 int *freqs;
1011
1012 freqs = wpa_config_parse_freqs(data, ssid, line, value);
1013 if (freqs == NULL)
1014 return -1;
1015 os_free(ssid->freq_list);
1016 ssid->freq_list = freqs;
1017
1018 return 0;
1019}
1020
1021
1022#ifndef NO_CONFIG_WRITE
1023static char * wpa_config_write_freqs(const struct parse_data *data,
1024 const int *freqs)
1025{
1026 char *buf, *pos, *end;
1027 int i, ret;
1028 size_t count;
1029
1030 if (freqs == NULL)
1031 return NULL;
1032
1033 count = 0;
1034 for (i = 0; freqs[i]; i++)
1035 count++;
1036
1037 pos = buf = os_zalloc(10 * count + 1);
1038 if (buf == NULL)
1039 return NULL;
1040 end = buf + 10 * count + 1;
1041
1042 for (i = 0; freqs[i]; i++) {
1043 ret = os_snprintf(pos, end - pos, "%s%u",
1044 i == 0 ? "" : " ", freqs[i]);
1045 if (ret < 0 || ret >= end - pos) {
1046 end[-1] = '\0';
1047 return buf;
1048 }
1049 pos += ret;
1050 }
1051
1052 return buf;
1053}
1054
1055
1056static char * wpa_config_write_scan_freq(const struct parse_data *data,
1057 struct wpa_ssid *ssid)
1058{
1059 return wpa_config_write_freqs(data, ssid->scan_freq);
1060}
1061
1062
1063static char * wpa_config_write_freq_list(const struct parse_data *data,
1064 struct wpa_ssid *ssid)
1065{
1066 return wpa_config_write_freqs(data, ssid->freq_list);
1067}
1068#endif /* NO_CONFIG_WRITE */
1069
1070
1071#ifdef IEEE8021X_EAPOL
1072static int wpa_config_parse_eap(const struct parse_data *data,
1073 struct wpa_ssid *ssid, int line,
1074 const char *value)
1075{
1076 int last, errors = 0;
1077 char *start, *end, *buf;
1078 struct eap_method_type *methods = NULL, *tmp;
1079 size_t num_methods = 0;
1080
1081 buf = os_strdup(value);
1082 if (buf == NULL)
1083 return -1;
1084 start = buf;
1085
1086 while (*start != '\0') {
1087 while (*start == ' ' || *start == '\t')
1088 start++;
1089 if (*start == '\0')
1090 break;
1091 end = start;
1092 while (*end != ' ' && *end != '\t' && *end != '\0')
1093 end++;
1094 last = *end == '\0';
1095 *end = '\0';
1096 tmp = methods;
1097 methods = os_realloc(methods,
1098 (num_methods + 1) * sizeof(*methods));
1099 if (methods == NULL) {
1100 os_free(tmp);
1101 os_free(buf);
1102 return -1;
1103 }
1104 methods[num_methods].method = eap_peer_get_type(
1105 start, &methods[num_methods].vendor);
1106 if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
1107 methods[num_methods].method == EAP_TYPE_NONE) {
1108 wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
1109 "'%s'", line, start);
1110 wpa_printf(MSG_ERROR, "You may need to add support for"
1111 " this EAP method during wpa_supplicant\n"
1112 "build time configuration.\n"
1113 "See README for more information.");
1114 errors++;
1115 } else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
1116 methods[num_methods].method == EAP_TYPE_LEAP)
1117 ssid->leap++;
1118 else
1119 ssid->non_leap++;
1120 num_methods++;
1121 if (last)
1122 break;
1123 start = end + 1;
1124 }
1125 os_free(buf);
1126
1127 tmp = methods;
1128 methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods));
1129 if (methods == NULL) {
1130 os_free(tmp);
1131 return -1;
1132 }
1133 methods[num_methods].vendor = EAP_VENDOR_IETF;
1134 methods[num_methods].method = EAP_TYPE_NONE;
1135 num_methods++;
1136
1137 wpa_hexdump(MSG_MSGDUMP, "eap methods",
1138 (u8 *) methods, num_methods * sizeof(*methods));
1139 ssid->eap.eap_methods = methods;
1140 return errors ? -1 : 0;
1141}
1142
1143
1144static char * wpa_config_write_eap(const struct parse_data *data,
1145 struct wpa_ssid *ssid)
1146{
1147 int i, ret;
1148 char *buf, *pos, *end;
1149 const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
1150 const char *name;
1151
1152 if (eap_methods == NULL)
1153 return NULL;
1154
1155 pos = buf = os_zalloc(100);
1156 if (buf == NULL)
1157 return NULL;
1158 end = buf + 100;
1159
1160 for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
1161 eap_methods[i].method != EAP_TYPE_NONE; i++) {
1162 name = eap_get_name(eap_methods[i].vendor,
1163 eap_methods[i].method);
1164 if (name) {
1165 ret = os_snprintf(pos, end - pos, "%s%s",
1166 pos == buf ? "" : " ", name);
1167 if (ret < 0 || ret >= end - pos)
1168 break;
1169 pos += ret;
1170 }
1171 }
1172
1173 end[-1] = '\0';
1174
1175 return buf;
1176}
1177
1178
1179static int wpa_config_parse_password(const struct parse_data *data,
1180 struct wpa_ssid *ssid, int line,
1181 const char *value)
1182{
1183 u8 *hash;
1184
1185 if (os_strcmp(value, "NULL") == 0) {
1186 wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
1187 os_free(ssid->eap.password);
1188 ssid->eap.password = NULL;
1189 ssid->eap.password_len = 0;
1190 return 0;
1191 }
1192
1193 if (os_strncmp(value, "hash:", 5) != 0) {
1194 char *tmp;
1195 size_t res_len;
1196
1197 tmp = wpa_config_parse_string(value, &res_len);
1198 if (tmp == NULL) {
1199 wpa_printf(MSG_ERROR, "Line %d: failed to parse "
1200 "password.", line);
1201 return -1;
1202 }
1203 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
1204 (u8 *) tmp, res_len);
1205
1206 os_free(ssid->eap.password);
1207 ssid->eap.password = (u8 *) tmp;
1208 ssid->eap.password_len = res_len;
1209 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1210
1211 return 0;
1212 }
1213
1214
1215 /* NtPasswordHash: hash:<32 hex digits> */
1216 if (os_strlen(value + 5) != 2 * 16) {
1217 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
1218 "(expected 32 hex digits)", line);
1219 return -1;
1220 }
1221
1222 hash = os_malloc(16);
1223 if (hash == NULL)
1224 return -1;
1225
1226 if (hexstr2bin(value + 5, hash, 16)) {
1227 os_free(hash);
1228 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
1229 return -1;
1230 }
1231
1232 wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
1233
1234 os_free(ssid->eap.password);
1235 ssid->eap.password = hash;
1236 ssid->eap.password_len = 16;
1237 ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1238
1239 return 0;
1240}
1241
1242
1243static char * wpa_config_write_password(const struct parse_data *data,
1244 struct wpa_ssid *ssid)
1245{
1246 char *buf;
1247
1248 if (ssid->eap.password == NULL)
1249 return NULL;
1250
1251 if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
1252 return wpa_config_write_string(
1253 ssid->eap.password, ssid->eap.password_len);
1254 }
1255
1256 buf = os_malloc(5 + 32 + 1);
1257 if (buf == NULL)
1258 return NULL;
1259
1260 os_memcpy(buf, "hash:", 5);
1261 wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
1262
1263 return buf;
1264}
1265#endif /* IEEE8021X_EAPOL */
1266
1267
1268static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
1269 const char *value, int idx)
1270{
1271 char *buf, title[20];
1272 int res;
1273
1274 buf = wpa_config_parse_string(value, len);
1275 if (buf == NULL) {
1276 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
1277 line, idx, value);
1278 return -1;
1279 }
1280 if (*len > MAX_WEP_KEY_LEN) {
1281 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
1282 line, idx, value);
1283 os_free(buf);
1284 return -1;
1285 }
1286 os_memcpy(key, buf, *len);
1287 os_free(buf);
1288 res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
1289 if (res >= 0 && (size_t) res < sizeof(title))
1290 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
1291 return 0;
1292}
1293
1294
1295static int wpa_config_parse_wep_key0(const struct parse_data *data,
1296 struct wpa_ssid *ssid, int line,
1297 const char *value)
1298{
1299 return wpa_config_parse_wep_key(ssid->wep_key[0],
1300 &ssid->wep_key_len[0], line,
1301 value, 0);
1302}
1303
1304
1305static int wpa_config_parse_wep_key1(const struct parse_data *data,
1306 struct wpa_ssid *ssid, int line,
1307 const char *value)
1308{
1309 return wpa_config_parse_wep_key(ssid->wep_key[1],
1310 &ssid->wep_key_len[1], line,
1311 value, 1);
1312}
1313
1314
1315static int wpa_config_parse_wep_key2(const struct parse_data *data,
1316 struct wpa_ssid *ssid, int line,
1317 const char *value)
1318{
1319 return wpa_config_parse_wep_key(ssid->wep_key[2],
1320 &ssid->wep_key_len[2], line,
1321 value, 2);
1322}
1323
1324
1325static int wpa_config_parse_wep_key3(const struct parse_data *data,
1326 struct wpa_ssid *ssid, int line,
1327 const char *value)
1328{
1329 return wpa_config_parse_wep_key(ssid->wep_key[3],
1330 &ssid->wep_key_len[3], line,
1331 value, 3);
1332}
1333
1334
1335#ifndef NO_CONFIG_WRITE
1336static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
1337{
1338 if (ssid->wep_key_len[idx] == 0)
1339 return NULL;
1340 return wpa_config_write_string(ssid->wep_key[idx],
1341 ssid->wep_key_len[idx]);
1342}
1343
1344
1345static char * wpa_config_write_wep_key0(const struct parse_data *data,
1346 struct wpa_ssid *ssid)
1347{
1348 return wpa_config_write_wep_key(ssid, 0);
1349}
1350
1351
1352static char * wpa_config_write_wep_key1(const struct parse_data *data,
1353 struct wpa_ssid *ssid)
1354{
1355 return wpa_config_write_wep_key(ssid, 1);
1356}
1357
1358
1359static char * wpa_config_write_wep_key2(const struct parse_data *data,
1360 struct wpa_ssid *ssid)
1361{
1362 return wpa_config_write_wep_key(ssid, 2);
1363}
1364
1365
1366static char * wpa_config_write_wep_key3(const struct parse_data *data,
1367 struct wpa_ssid *ssid)
1368{
1369 return wpa_config_write_wep_key(ssid, 3);
1370}
1371#endif /* NO_CONFIG_WRITE */
1372
1373
1374/* Helper macros for network block parser */
1375
1376#ifdef OFFSET
1377#undef OFFSET
1378#endif /* OFFSET */
1379/* OFFSET: Get offset of a variable within the wpa_ssid structure */
1380#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
1381
1382/* STR: Define a string variable for an ASCII string; f = field name */
1383#ifdef NO_CONFIG_WRITE
1384#define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
1385#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
1386#else /* NO_CONFIG_WRITE */
1387#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
1388#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
1389#endif /* NO_CONFIG_WRITE */
1390#define STR(f) _STR(f), NULL, NULL, NULL, 0
1391#define STRe(f) _STRe(f), NULL, NULL, NULL, 0
1392#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
1393#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
1394
1395/* STR_LEN: Define a string variable with a separate variable for storing the
1396 * data length. Unlike STR(), this can be used to store arbitrary binary data
1397 * (i.e., even nul termination character). */
1398#define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
1399#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
1400#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
1401#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
1402#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
1403
1404/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
1405 * explicitly specified. */
1406#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
1407#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
1408#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
1409
1410#ifdef NO_CONFIG_WRITE
1411#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
1412#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
1413#else /* NO_CONFIG_WRITE */
1414#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1415 OFFSET(f), (void *) 0
1416#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1417 OFFSET(eap.f), (void *) 0
Dmitry Shmidtc5da5d22011-07-15 15:32:26 -07001418#ifdef WPA_UNICODE_SSID
1419/* STR_* variants that do not force conversion to ASCII */
1420#define _STR_UNICODE(f) #f, wpa_config_parse_str, wpa_config_write_str_unicode, OFFSET(f)
1421#define STR_UNICODE(f) _STR_UNICODE(f), NULL, NULL, NULL, 0
1422#define _STR_LEN_UNICODE(f) _STR_UNICODE(f), OFFSET(f ## _len)
1423#define STR_LEN_UNICODE(f) _STR_LEN_UNICODE(f), NULL, NULL, 0
1424#define _STR_RANGE_UNICODE(f, min, max) _STR_LEN_UNICODE(f), (void *) (min), (void *) (max)
1425#define STR_RANGE_UNICODE(f, min, max) _STR_RANGE_UNICODE(f, min, max), 0
1426#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001427#endif /* NO_CONFIG_WRITE */
1428
1429/* INT: Define an integer variable */
1430#define INT(f) _INT(f), NULL, NULL, 0
1431#define INTe(f) _INTe(f), NULL, NULL, 0
1432
1433/* INT_RANGE: Define an integer variable with allowed value range */
1434#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
1435
1436/* FUNC: Define a configuration variable that uses a custom function for
1437 * parsing and writing the value. */
1438#ifdef NO_CONFIG_WRITE
1439#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
1440#else /* NO_CONFIG_WRITE */
1441#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
1442 NULL, NULL, NULL, NULL
1443#endif /* NO_CONFIG_WRITE */
1444#define FUNC(f) _FUNC(f), 0
1445#define FUNC_KEY(f) _FUNC(f), 1
1446
1447/*
1448 * Table of network configuration variables. This table is used to parse each
1449 * network configuration variable, e.g., each line in wpa_supplicant.conf file
1450 * that is inside a network block.
1451 *
1452 * This table is generated using the helper macros defined above and with
1453 * generous help from the C pre-processor. The field name is stored as a string
1454 * into .name and for STR and INT types, the offset of the target buffer within
1455 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
1456 * offset to the field containing the length of the configuration variable.
1457 * .param3 and .param4 can be used to mark the allowed range (length for STR
1458 * and value for INT).
1459 *
1460 * For each configuration line in wpa_supplicant.conf, the parser goes through
1461 * this table and select the entry that matches with the field name. The parser
1462 * function (.parser) is then called to parse the actual value of the field.
1463 *
1464 * This kind of mechanism makes it easy to add new configuration parameters,
1465 * since only one line needs to be added into this table and into the
1466 * struct wpa_ssid definition if the new variable is either a string or
1467 * integer. More complex types will need to use their own parser and writer
1468 * functions.
1469 */
1470static const struct parse_data ssid_fields[] = {
Dmitry Shmidtc5da5d22011-07-15 15:32:26 -07001471#ifdef WPA_UNICODE_SSID
1472 { STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) },
1473#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001474 { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
Dmitry Shmidtc5da5d22011-07-15 15:32:26 -07001475#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001476 { INT_RANGE(scan_ssid, 0, 1) },
1477 { FUNC(bssid) },
1478 { FUNC_KEY(psk) },
1479 { FUNC(proto) },
1480 { FUNC(key_mgmt) },
1481 { FUNC(pairwise) },
1482 { FUNC(group) },
1483 { FUNC(auth_alg) },
1484 { FUNC(scan_freq) },
1485 { FUNC(freq_list) },
1486#ifdef IEEE8021X_EAPOL
1487 { FUNC(eap) },
1488 { STR_LENe(identity) },
1489 { STR_LENe(anonymous_identity) },
1490 { FUNC_KEY(password) },
1491 { STRe(ca_cert) },
1492 { STRe(ca_path) },
1493 { STRe(client_cert) },
1494 { STRe(private_key) },
1495 { STR_KEYe(private_key_passwd) },
1496 { STRe(dh_file) },
1497 { STRe(subject_match) },
1498 { STRe(altsubject_match) },
1499 { STRe(ca_cert2) },
1500 { STRe(ca_path2) },
1501 { STRe(client_cert2) },
1502 { STRe(private_key2) },
1503 { STR_KEYe(private_key2_passwd) },
1504 { STRe(dh_file2) },
1505 { STRe(subject_match2) },
1506 { STRe(altsubject_match2) },
1507 { STRe(phase1) },
1508 { STRe(phase2) },
1509 { STRe(pcsc) },
1510 { STR_KEYe(pin) },
1511 { STRe(engine_id) },
1512 { STRe(key_id) },
1513 { STRe(cert_id) },
1514 { STRe(ca_cert_id) },
1515 { STR_KEYe(pin2) },
1516 { STRe(engine2_id) },
1517 { STRe(key2_id) },
1518 { STRe(cert2_id) },
1519 { STRe(ca_cert2_id) },
1520 { INTe(engine) },
1521 { INTe(engine2) },
1522 { INT(eapol_flags) },
1523#endif /* IEEE8021X_EAPOL */
1524 { FUNC_KEY(wep_key0) },
1525 { FUNC_KEY(wep_key1) },
1526 { FUNC_KEY(wep_key2) },
1527 { FUNC_KEY(wep_key3) },
1528 { INT(wep_tx_keyidx) },
1529 { INT(priority) },
1530#ifdef IEEE8021X_EAPOL
1531 { INT(eap_workaround) },
1532 { STRe(pac_file) },
1533 { INTe(fragment_size) },
1534#endif /* IEEE8021X_EAPOL */
1535 { INT_RANGE(mode, 0, 4) },
1536 { INT_RANGE(proactive_key_caching, 0, 1) },
1537 { INT_RANGE(disabled, 0, 2) },
1538 { STR(id_str) },
1539#ifdef CONFIG_IEEE80211W
1540 { INT_RANGE(ieee80211w, 0, 2) },
1541#endif /* CONFIG_IEEE80211W */
1542 { INT_RANGE(peerkey, 0, 1) },
1543 { INT_RANGE(mixed_cell, 0, 1) },
1544 { INT_RANGE(frequency, 0, 10000) },
1545 { INT(wpa_ptk_rekey) },
1546 { STR(bgscan) },
1547};
1548
Dmitry Shmidtc5da5d22011-07-15 15:32:26 -07001549#ifdef WPA_UNICODE_SSID
1550#undef _STR_UNICODE
1551#undef STR_UNICODE
1552#undef _STR_LEN_UNICODE
1553#undef STR_LEN_UNICODE
1554#undef _STR_RANGE_UNICODE
1555#undef STR_RANGE_UNICODE
1556#endif
1557
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558#undef OFFSET
1559#undef _STR
1560#undef STR
1561#undef STR_KEY
1562#undef _STR_LEN
1563#undef STR_LEN
1564#undef STR_LEN_KEY
1565#undef _STR_RANGE
1566#undef STR_RANGE
1567#undef STR_RANGE_KEY
1568#undef _INT
1569#undef INT
1570#undef INT_RANGE
1571#undef _FUNC
1572#undef FUNC
1573#undef FUNC_KEY
1574#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1575
1576
1577/**
1578 * wpa_config_add_prio_network - Add a network to priority lists
1579 * @config: Configuration data from wpa_config_read()
1580 * @ssid: Pointer to the network configuration to be added to the list
1581 * Returns: 0 on success, -1 on failure
1582 *
1583 * This function is used to add a network block to the priority list of
1584 * networks. This must be called for each network when reading in the full
1585 * configuration. In addition, this can be used indirectly when updating
1586 * priorities by calling wpa_config_update_prio_list().
1587 */
1588int wpa_config_add_prio_network(struct wpa_config *config,
1589 struct wpa_ssid *ssid)
1590{
1591 int prio;
1592 struct wpa_ssid *prev, **nlist;
1593
1594 /*
1595 * Add to an existing priority list if one is available for the
1596 * configured priority level for this network.
1597 */
1598 for (prio = 0; prio < config->num_prio; prio++) {
1599 prev = config->pssid[prio];
1600 if (prev->priority == ssid->priority) {
1601 while (prev->pnext)
1602 prev = prev->pnext;
1603 prev->pnext = ssid;
1604 return 0;
1605 }
1606 }
1607
1608 /* First network for this priority - add a new priority list */
1609 nlist = os_realloc(config->pssid,
1610 (config->num_prio + 1) * sizeof(struct wpa_ssid *));
1611 if (nlist == NULL)
1612 return -1;
1613
1614 for (prio = 0; prio < config->num_prio; prio++) {
1615 if (nlist[prio]->priority < ssid->priority)
1616 break;
1617 }
1618
1619 os_memmove(&nlist[prio + 1], &nlist[prio],
1620 (config->num_prio - prio) * sizeof(struct wpa_ssid *));
1621
1622 nlist[prio] = ssid;
1623 config->num_prio++;
1624 config->pssid = nlist;
1625
1626 return 0;
1627}
1628
1629
1630/**
1631 * wpa_config_update_prio_list - Update network priority list
1632 * @config: Configuration data from wpa_config_read()
1633 * Returns: 0 on success, -1 on failure
1634 *
1635 * This function is called to update the priority list of networks in the
1636 * configuration when a network is being added or removed. This is also called
1637 * if a priority for a network is changed.
1638 */
1639int wpa_config_update_prio_list(struct wpa_config *config)
1640{
1641 struct wpa_ssid *ssid;
1642 int ret = 0;
1643
1644 os_free(config->pssid);
1645 config->pssid = NULL;
1646 config->num_prio = 0;
1647
1648 ssid = config->ssid;
1649 while (ssid) {
1650 ssid->pnext = NULL;
1651 if (wpa_config_add_prio_network(config, ssid) < 0)
1652 ret = -1;
1653 ssid = ssid->next;
1654 }
1655
1656 return ret;
1657}
1658
1659
1660#ifdef IEEE8021X_EAPOL
1661static void eap_peer_config_free(struct eap_peer_config *eap)
1662{
1663 os_free(eap->eap_methods);
1664 os_free(eap->identity);
1665 os_free(eap->anonymous_identity);
1666 os_free(eap->password);
1667 os_free(eap->ca_cert);
1668 os_free(eap->ca_path);
1669 os_free(eap->client_cert);
1670 os_free(eap->private_key);
1671 os_free(eap->private_key_passwd);
1672 os_free(eap->dh_file);
1673 os_free(eap->subject_match);
1674 os_free(eap->altsubject_match);
1675 os_free(eap->ca_cert2);
1676 os_free(eap->ca_path2);
1677 os_free(eap->client_cert2);
1678 os_free(eap->private_key2);
1679 os_free(eap->private_key2_passwd);
1680 os_free(eap->dh_file2);
1681 os_free(eap->subject_match2);
1682 os_free(eap->altsubject_match2);
1683 os_free(eap->phase1);
1684 os_free(eap->phase2);
1685 os_free(eap->pcsc);
1686 os_free(eap->pin);
1687 os_free(eap->engine_id);
1688 os_free(eap->key_id);
1689 os_free(eap->cert_id);
1690 os_free(eap->ca_cert_id);
1691 os_free(eap->key2_id);
1692 os_free(eap->cert2_id);
1693 os_free(eap->ca_cert2_id);
1694 os_free(eap->pin2);
1695 os_free(eap->engine2_id);
1696 os_free(eap->otp);
1697 os_free(eap->pending_req_otp);
1698 os_free(eap->pac_file);
1699 os_free(eap->new_password);
1700}
1701#endif /* IEEE8021X_EAPOL */
1702
1703
1704/**
1705 * wpa_config_free_ssid - Free network/ssid configuration data
1706 * @ssid: Configuration data for the network
1707 *
1708 * This function frees all resources allocated for the network configuration
1709 * data.
1710 */
1711void wpa_config_free_ssid(struct wpa_ssid *ssid)
1712{
1713 os_free(ssid->ssid);
1714 os_free(ssid->passphrase);
1715#ifdef IEEE8021X_EAPOL
1716 eap_peer_config_free(&ssid->eap);
1717#endif /* IEEE8021X_EAPOL */
1718 os_free(ssid->id_str);
1719 os_free(ssid->scan_freq);
1720 os_free(ssid->freq_list);
1721 os_free(ssid->bgscan);
1722 os_free(ssid);
1723}
1724
1725
1726/**
1727 * wpa_config_free - Free configuration data
1728 * @config: Configuration data from wpa_config_read()
1729 *
1730 * This function frees all resources allocated for the configuration data by
1731 * wpa_config_read().
1732 */
1733void wpa_config_free(struct wpa_config *config)
1734{
1735#ifndef CONFIG_NO_CONFIG_BLOBS
1736 struct wpa_config_blob *blob, *prevblob;
1737#endif /* CONFIG_NO_CONFIG_BLOBS */
1738 struct wpa_ssid *ssid, *prev = NULL;
1739
1740 ssid = config->ssid;
1741 while (ssid) {
1742 prev = ssid;
1743 ssid = ssid->next;
1744 wpa_config_free_ssid(prev);
1745 }
1746
1747#ifndef CONFIG_NO_CONFIG_BLOBS
1748 blob = config->blobs;
1749 prevblob = NULL;
1750 while (blob) {
1751 prevblob = blob;
1752 blob = blob->next;
1753 wpa_config_free_blob(prevblob);
1754 }
1755#endif /* CONFIG_NO_CONFIG_BLOBS */
1756
1757 os_free(config->ctrl_interface);
1758 os_free(config->ctrl_interface_group);
1759 os_free(config->opensc_engine_path);
1760 os_free(config->pkcs11_engine_path);
1761 os_free(config->pkcs11_module_path);
1762 os_free(config->driver_param);
1763 os_free(config->device_name);
1764 os_free(config->manufacturer);
1765 os_free(config->model_name);
1766 os_free(config->model_number);
1767 os_free(config->serial_number);
1768 os_free(config->config_methods);
1769 os_free(config->p2p_ssid_postfix);
1770 os_free(config->pssid);
1771 os_free(config);
1772}
1773
1774
1775/**
1776 * wpa_config_foreach_network - Iterate over each configured network
1777 * @config: Configuration data from wpa_config_read()
1778 * @func: Callback function to process each network
1779 * @arg: Opaque argument to pass to callback function
1780 *
1781 * Iterate over the set of configured networks calling the specified
1782 * function for each item. We guard against callbacks removing the
1783 * supplied network.
1784 */
1785void wpa_config_foreach_network(struct wpa_config *config,
1786 void (*func)(void *, struct wpa_ssid *),
1787 void *arg)
1788{
1789 struct wpa_ssid *ssid, *next;
1790
1791 ssid = config->ssid;
1792 while (ssid) {
1793 next = ssid->next;
1794 func(arg, ssid);
1795 ssid = next;
1796 }
1797}
1798
1799
1800/**
1801 * wpa_config_get_network - Get configured network based on id
1802 * @config: Configuration data from wpa_config_read()
1803 * @id: Unique network id to search for
1804 * Returns: Network configuration or %NULL if not found
1805 */
1806struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1807{
1808 struct wpa_ssid *ssid;
1809
1810 ssid = config->ssid;
1811 while (ssid) {
1812 if (id == ssid->id)
1813 break;
1814 ssid = ssid->next;
1815 }
1816
1817 return ssid;
1818}
1819
1820
1821/**
1822 * wpa_config_add_network - Add a new network with empty configuration
1823 * @config: Configuration data from wpa_config_read()
1824 * Returns: The new network configuration or %NULL if operation failed
1825 */
1826struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1827{
1828 int id;
1829 struct wpa_ssid *ssid, *last = NULL;
1830
1831 id = -1;
1832 ssid = config->ssid;
1833 while (ssid) {
1834 if (ssid->id > id)
1835 id = ssid->id;
1836 last = ssid;
1837 ssid = ssid->next;
1838 }
1839 id++;
1840
1841 ssid = os_zalloc(sizeof(*ssid));
1842 if (ssid == NULL)
1843 return NULL;
1844 ssid->id = id;
1845 if (last)
1846 last->next = ssid;
1847 else
1848 config->ssid = ssid;
1849
1850 wpa_config_update_prio_list(config);
1851
1852 return ssid;
1853}
1854
1855
1856/**
1857 * wpa_config_remove_network - Remove a configured network based on id
1858 * @config: Configuration data from wpa_config_read()
1859 * @id: Unique network id to search for
1860 * Returns: 0 on success, or -1 if the network was not found
1861 */
1862int wpa_config_remove_network(struct wpa_config *config, int id)
1863{
1864 struct wpa_ssid *ssid, *prev = NULL;
1865
1866 ssid = config->ssid;
1867 while (ssid) {
1868 if (id == ssid->id)
1869 break;
1870 prev = ssid;
1871 ssid = ssid->next;
1872 }
1873
1874 if (ssid == NULL)
1875 return -1;
1876
1877 if (prev)
1878 prev->next = ssid->next;
1879 else
1880 config->ssid = ssid->next;
1881
1882 wpa_config_update_prio_list(config);
1883 wpa_config_free_ssid(ssid);
1884 return 0;
1885}
1886
1887
1888/**
1889 * wpa_config_set_network_defaults - Set network default values
1890 * @ssid: Pointer to network configuration data
1891 */
1892void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
1893{
1894 ssid->proto = DEFAULT_PROTO;
1895 ssid->pairwise_cipher = DEFAULT_PAIRWISE;
1896 ssid->group_cipher = DEFAULT_GROUP;
1897 ssid->key_mgmt = DEFAULT_KEY_MGMT;
1898#ifdef IEEE8021X_EAPOL
1899 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
1900 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
1901 ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
1902#endif /* IEEE8021X_EAPOL */
1903}
1904
1905
1906/**
1907 * wpa_config_set - Set a variable in network configuration
1908 * @ssid: Pointer to network configuration data
1909 * @var: Variable name, e.g., "ssid"
1910 * @value: Variable value
1911 * @line: Line number in configuration file or 0 if not used
1912 * Returns: 0 on success, -1 on failure
1913 *
1914 * This function can be used to set network configuration variables based on
1915 * both the configuration file and management interface input. The value
1916 * parameter must be in the same format as the text-based configuration file is
1917 * using. For example, strings are using double quotation marks.
1918 */
1919int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
1920 int line)
1921{
1922 size_t i;
1923 int ret = 0;
1924
1925 if (ssid == NULL || var == NULL || value == NULL)
1926 return -1;
1927
1928 for (i = 0; i < NUM_SSID_FIELDS; i++) {
1929 const struct parse_data *field = &ssid_fields[i];
1930 if (os_strcmp(var, field->name) != 0)
1931 continue;
1932
1933 if (field->parser(field, ssid, line, value)) {
1934 if (line) {
1935 wpa_printf(MSG_ERROR, "Line %d: failed to "
1936 "parse %s '%s'.", line, var, value);
1937 }
1938 ret = -1;
1939 }
1940 break;
1941 }
1942 if (i == NUM_SSID_FIELDS) {
1943 if (line) {
1944 wpa_printf(MSG_ERROR, "Line %d: unknown network field "
1945 "'%s'.", line, var);
1946 }
1947 ret = -1;
1948 }
1949
1950 return ret;
1951}
1952
1953
1954/**
1955 * wpa_config_get_all - Get all options from network configuration
1956 * @ssid: Pointer to network configuration data
1957 * @get_keys: Determines if keys/passwords will be included in returned list
1958 * (if they may be exported)
1959 * Returns: %NULL terminated list of all set keys and their values in the form
1960 * of [key1, val1, key2, val2, ... , NULL]
1961 *
1962 * This function can be used to get list of all configured network properties.
1963 * The caller is responsible for freeing the returned list and all its
1964 * elements.
1965 */
1966char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
1967{
1968 const struct parse_data *field;
1969 char *key, *value;
1970 size_t i;
1971 char **props;
1972 int fields_num;
1973
1974 get_keys = get_keys && ssid->export_keys;
1975
1976 props = os_zalloc(sizeof(char *) * ((2 * NUM_SSID_FIELDS) + 1));
1977 if (!props)
1978 return NULL;
1979
1980 fields_num = 0;
1981 for (i = 0; i < NUM_SSID_FIELDS; i++) {
1982 field = &ssid_fields[i];
1983 if (field->key_data && !get_keys)
1984 continue;
1985 value = field->writer(field, ssid);
1986 if (value == NULL)
1987 continue;
1988 if (os_strlen(value) == 0) {
1989 os_free(value);
1990 continue;
1991 }
1992
1993 key = os_strdup(field->name);
1994 if (key == NULL) {
1995 os_free(value);
1996 goto err;
1997 }
1998
1999 props[fields_num * 2] = key;
2000 props[fields_num * 2 + 1] = value;
2001
2002 fields_num++;
2003 }
2004
2005 return props;
2006
2007err:
2008 value = *props;
2009 while (value)
2010 os_free(value++);
2011 os_free(props);
2012 return NULL;
2013}
2014
2015
2016#ifndef NO_CONFIG_WRITE
2017/**
2018 * wpa_config_get - Get a variable in network configuration
2019 * @ssid: Pointer to network configuration data
2020 * @var: Variable name, e.g., "ssid"
2021 * Returns: Value of the variable or %NULL on failure
2022 *
2023 * This function can be used to get network configuration variables. The
2024 * returned value is a copy of the configuration variable in text format, i.e,.
2025 * the same format that the text-based configuration file and wpa_config_set()
2026 * are using for the value. The caller is responsible for freeing the returned
2027 * value.
2028 */
2029char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
2030{
2031 size_t i;
2032
2033 if (ssid == NULL || var == NULL)
2034 return NULL;
2035
2036 for (i = 0; i < NUM_SSID_FIELDS; i++) {
2037 const struct parse_data *field = &ssid_fields[i];
2038 if (os_strcmp(var, field->name) == 0)
2039 return field->writer(field, ssid);
2040 }
2041
2042 return NULL;
2043}
2044
2045
2046/**
2047 * wpa_config_get_no_key - Get a variable in network configuration (no keys)
2048 * @ssid: Pointer to network configuration data
2049 * @var: Variable name, e.g., "ssid"
2050 * Returns: Value of the variable or %NULL on failure
2051 *
2052 * This function can be used to get network configuration variable like
2053 * wpa_config_get(). The only difference is that this functions does not expose
2054 * key/password material from the configuration. In case a key/password field
2055 * is requested, the returned value is an empty string or %NULL if the variable
2056 * is not set or "*" if the variable is set (regardless of its value). The
2057 * returned value is a copy of the configuration variable in text format, i.e,.
2058 * the same format that the text-based configuration file and wpa_config_set()
2059 * are using for the value. The caller is responsible for freeing the returned
2060 * value.
2061 */
2062char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
2063{
2064 size_t i;
2065
2066 if (ssid == NULL || var == NULL)
2067 return NULL;
2068
2069 for (i = 0; i < NUM_SSID_FIELDS; i++) {
2070 const struct parse_data *field = &ssid_fields[i];
2071 if (os_strcmp(var, field->name) == 0) {
2072 char *res = field->writer(field, ssid);
2073 if (field->key_data) {
2074 if (res && res[0]) {
2075 wpa_printf(MSG_DEBUG, "Do not allow "
2076 "key_data field to be "
2077 "exposed");
2078 os_free(res);
2079 return os_strdup("*");
2080 }
2081
2082 os_free(res);
2083 return NULL;
2084 }
2085 return res;
2086 }
2087 }
2088
2089 return NULL;
2090}
2091#endif /* NO_CONFIG_WRITE */
2092
2093
2094/**
2095 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
2096 * @ssid: Pointer to network configuration data
2097 *
2098 * This function must be called to update WPA PSK when either SSID or the
2099 * passphrase has changed for the network configuration.
2100 */
2101void wpa_config_update_psk(struct wpa_ssid *ssid)
2102{
2103#ifndef CONFIG_NO_PBKDF2
2104 pbkdf2_sha1(ssid->passphrase,
2105 (char *) ssid->ssid, ssid->ssid_len, 4096,
2106 ssid->psk, PMK_LEN);
2107 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
2108 ssid->psk, PMK_LEN);
2109 ssid->psk_set = 1;
2110#endif /* CONFIG_NO_PBKDF2 */
2111}
2112
2113
2114#ifndef CONFIG_NO_CONFIG_BLOBS
2115/**
2116 * wpa_config_get_blob - Get a named configuration blob
2117 * @config: Configuration data from wpa_config_read()
2118 * @name: Name of the blob
2119 * Returns: Pointer to blob data or %NULL if not found
2120 */
2121const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
2122 const char *name)
2123{
2124 struct wpa_config_blob *blob = config->blobs;
2125
2126 while (blob) {
2127 if (os_strcmp(blob->name, name) == 0)
2128 return blob;
2129 blob = blob->next;
2130 }
2131 return NULL;
2132}
2133
2134
2135/**
2136 * wpa_config_set_blob - Set or add a named configuration blob
2137 * @config: Configuration data from wpa_config_read()
2138 * @blob: New value for the blob
2139 *
2140 * Adds a new configuration blob or replaces the current value of an existing
2141 * blob.
2142 */
2143void wpa_config_set_blob(struct wpa_config *config,
2144 struct wpa_config_blob *blob)
2145{
2146 wpa_config_remove_blob(config, blob->name);
2147 blob->next = config->blobs;
2148 config->blobs = blob;
2149}
2150
2151
2152/**
2153 * wpa_config_free_blob - Free blob data
2154 * @blob: Pointer to blob to be freed
2155 */
2156void wpa_config_free_blob(struct wpa_config_blob *blob)
2157{
2158 if (blob) {
2159 os_free(blob->name);
2160 os_free(blob->data);
2161 os_free(blob);
2162 }
2163}
2164
2165
2166/**
2167 * wpa_config_remove_blob - Remove a named configuration blob
2168 * @config: Configuration data from wpa_config_read()
2169 * @name: Name of the blob to remove
2170 * Returns: 0 if blob was removed or -1 if blob was not found
2171 */
2172int wpa_config_remove_blob(struct wpa_config *config, const char *name)
2173{
2174 struct wpa_config_blob *pos = config->blobs, *prev = NULL;
2175
2176 while (pos) {
2177 if (os_strcmp(pos->name, name) == 0) {
2178 if (prev)
2179 prev->next = pos->next;
2180 else
2181 config->blobs = pos->next;
2182 wpa_config_free_blob(pos);
2183 return 0;
2184 }
2185 prev = pos;
2186 pos = pos->next;
2187 }
2188
2189 return -1;
2190}
2191#endif /* CONFIG_NO_CONFIG_BLOBS */
2192
2193
2194/**
2195 * wpa_config_alloc_empty - Allocate an empty configuration
2196 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
2197 * socket
2198 * @driver_param: Driver parameters
2199 * Returns: Pointer to allocated configuration data or %NULL on failure
2200 */
2201struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
2202 const char *driver_param)
2203{
2204 struct wpa_config *config;
2205
2206 config = os_zalloc(sizeof(*config));
2207 if (config == NULL)
2208 return NULL;
2209 config->eapol_version = DEFAULT_EAPOL_VERSION;
2210 config->ap_scan = DEFAULT_AP_SCAN;
2211 config->fast_reauth = DEFAULT_FAST_REAUTH;
2212 config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
2213 config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
2214 config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
2215 config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
2216 config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
2217 config->max_num_sta = DEFAULT_MAX_NUM_STA;
2218
2219 if (ctrl_interface)
2220 config->ctrl_interface = os_strdup(ctrl_interface);
2221 if (driver_param)
2222 config->driver_param = os_strdup(driver_param);
2223
2224 return config;
2225}
2226
2227
2228#ifndef CONFIG_NO_STDOUT_DEBUG
2229/**
2230 * wpa_config_debug_dump_networks - Debug dump of configured networks
2231 * @config: Configuration data from wpa_config_read()
2232 */
2233void wpa_config_debug_dump_networks(struct wpa_config *config)
2234{
2235 int prio;
2236 struct wpa_ssid *ssid;
2237
2238 for (prio = 0; prio < config->num_prio; prio++) {
2239 ssid = config->pssid[prio];
2240 wpa_printf(MSG_DEBUG, "Priority group %d",
2241 ssid->priority);
2242 while (ssid) {
2243 wpa_printf(MSG_DEBUG, " id=%d ssid='%s'",
2244 ssid->id,
2245 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2246 ssid = ssid->pnext;
2247 }
2248 }
2249}
2250#endif /* CONFIG_NO_STDOUT_DEBUG */
2251
2252
2253struct global_parse_data {
2254 char *name;
2255 int (*parser)(const struct global_parse_data *data,
2256 struct wpa_config *config, int line, const char *value);
2257 void *param1, *param2, *param3;
2258 unsigned int changed_flag;
2259};
2260
2261
2262static int wpa_global_config_parse_int(const struct global_parse_data *data,
2263 struct wpa_config *config, int line,
2264 const char *pos)
2265{
2266 int *dst;
2267 dst = (int *) (((u8 *) config) + (long) data->param1);
2268 *dst = atoi(pos);
2269 wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
2270
2271 if (data->param2 && *dst < (long) data->param2) {
2272 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
2273 "min_value=%ld)", line, data->name, *dst,
2274 (long) data->param2);
2275 *dst = (long) data->param2;
2276 return -1;
2277 }
2278
2279 if (data->param3 && *dst > (long) data->param3) {
2280 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
2281 "max_value=%ld)", line, data->name, *dst,
2282 (long) data->param3);
2283 *dst = (long) data->param3;
2284 return -1;
2285 }
2286
2287 return 0;
2288}
2289
2290
2291static int wpa_global_config_parse_str(const struct global_parse_data *data,
2292 struct wpa_config *config, int line,
2293 const char *pos)
2294{
2295 size_t len;
2296 char **dst, *tmp;
2297
2298 len = os_strlen(pos);
2299 if (data->param2 && len < (size_t) data->param2) {
2300 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
2301 "min_len=%ld)", line, data->name,
2302 (unsigned long) len, (long) data->param2);
2303 return -1;
2304 }
2305
2306 if (data->param3 && len > (size_t) data->param3) {
2307 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
2308 "max_len=%ld)", line, data->name,
2309 (unsigned long) len, (long) data->param3);
2310 return -1;
2311 }
2312
2313 tmp = os_strdup(pos);
2314 if (tmp == NULL)
2315 return -1;
2316
2317 dst = (char **) (((u8 *) config) + (long) data->param1);
2318 os_free(*dst);
2319 *dst = tmp;
2320 wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
2321
2322 return 0;
2323}
2324
2325
2326static int wpa_config_process_country(const struct global_parse_data *data,
2327 struct wpa_config *config, int line,
2328 const char *pos)
2329{
2330 if (!pos[0] || !pos[1]) {
2331 wpa_printf(MSG_DEBUG, "Invalid country set");
2332 return -1;
2333 }
2334 config->country[0] = pos[0];
2335 config->country[1] = pos[1];
2336 wpa_printf(MSG_DEBUG, "country='%c%c'",
2337 config->country[0], config->country[1]);
2338 return 0;
2339}
2340
2341
2342static int wpa_config_process_load_dynamic_eap(
2343 const struct global_parse_data *data, struct wpa_config *config,
2344 int line, const char *so)
2345{
2346 int ret;
2347 wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
2348 ret = eap_peer_method_load(so);
2349 if (ret == -2) {
2350 wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
2351 "reloading.");
2352 } else if (ret) {
2353 wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
2354 "method '%s'.", line, so);
2355 return -1;
2356 }
2357
2358 return 0;
2359}
2360
2361
2362#ifdef CONFIG_WPS
2363
2364static int wpa_config_process_uuid(const struct global_parse_data *data,
2365 struct wpa_config *config, int line,
2366 const char *pos)
2367{
2368 char buf[40];
2369 if (uuid_str2bin(pos, config->uuid)) {
2370 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
2371 return -1;
2372 }
2373 uuid_bin2str(config->uuid, buf, sizeof(buf));
2374 wpa_printf(MSG_DEBUG, "uuid=%s", buf);
2375 return 0;
2376}
2377
2378
2379static int wpa_config_process_device_type(
2380 const struct global_parse_data *data,
2381 struct wpa_config *config, int line, const char *pos)
2382{
2383 return wps_dev_type_str2bin(pos, config->device_type);
2384}
2385
2386
2387static int wpa_config_process_os_version(const struct global_parse_data *data,
2388 struct wpa_config *config, int line,
2389 const char *pos)
2390{
2391 if (hexstr2bin(pos, config->os_version, 4)) {
2392 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
2393 return -1;
2394 }
2395 wpa_printf(MSG_DEBUG, "os_version=%08x",
2396 WPA_GET_BE32(config->os_version));
2397 return 0;
2398}
2399
2400#endif /* CONFIG_WPS */
2401
2402#ifdef CONFIG_P2P
2403static int wpa_config_process_sec_device_type(
2404 const struct global_parse_data *data,
2405 struct wpa_config *config, int line, const char *pos)
2406{
2407 int idx;
2408
2409 if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) {
2410 wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type "
2411 "items", line);
2412 return -1;
2413 }
2414
2415 idx = config->num_sec_device_types;
2416
2417 if (wps_dev_type_str2bin(pos, config->sec_device_type[idx]))
2418 return -1;
2419
2420 config->num_sec_device_types++;
2421 return 0;
2422}
2423#endif /* CONFIG_P2P */
2424
2425
2426#ifdef OFFSET
2427#undef OFFSET
2428#endif /* OFFSET */
2429/* OFFSET: Get offset of a variable within the wpa_config structure */
2430#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
2431
2432#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
2433#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
2434#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
2435#define INT(f) _INT(f), NULL, NULL
2436#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
2437#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
2438#define STR(f) _STR(f), NULL, NULL
2439#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
2440
2441static const struct global_parse_data global_fields[] = {
2442#ifdef CONFIG_CTRL_IFACE
2443 { STR(ctrl_interface), 0 },
2444 { STR(ctrl_interface_group), 0 } /* deprecated */,
2445#endif /* CONFIG_CTRL_IFACE */
2446 { INT_RANGE(eapol_version, 1, 2), 0 },
2447 { INT(ap_scan), 0 },
2448 { INT(fast_reauth), 0 },
2449 { STR(opensc_engine_path), 0 },
2450 { STR(pkcs11_engine_path), 0 },
2451 { STR(pkcs11_module_path), 0 },
2452 { STR(driver_param), 0 },
2453 { INT(dot11RSNAConfigPMKLifetime), 0 },
2454 { INT(dot11RSNAConfigPMKReauthThreshold), 0 },
2455 { INT(dot11RSNAConfigSATimeout), 0 },
2456#ifndef CONFIG_NO_CONFIG_WRITE
2457 { INT(update_config), 0 },
2458#endif /* CONFIG_NO_CONFIG_WRITE */
2459 { FUNC_NO_VAR(load_dynamic_eap), 0 },
2460#ifdef CONFIG_WPS
2461 { FUNC(uuid), CFG_CHANGED_UUID },
2462 { STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME },
2463 { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
2464 { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
2465 { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
2466 { STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING },
2467 { FUNC(device_type), CFG_CHANGED_DEVICE_TYPE },
2468 { FUNC(os_version), CFG_CHANGED_OS_VERSION },
2469 { STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
2470 { INT_RANGE(wps_cred_processing, 0, 2), 0 },
2471#endif /* CONFIG_WPS */
2472#ifdef CONFIG_P2P
2473 { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
2474 { INT(p2p_listen_reg_class), 0 },
2475 { INT(p2p_listen_channel), 0 },
2476 { INT(p2p_oper_reg_class), 0 },
2477 { INT(p2p_oper_channel), 0 },
2478 { INT_RANGE(p2p_go_intent, 0, 15), 0 },
2479 { STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
2480 { INT_RANGE(persistent_reconnect, 0, 1), 0 },
2481 { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
2482 { INT(p2p_group_idle), 0 },
2483#endif /* CONFIG_P2P */
2484 { FUNC(country), CFG_CHANGED_COUNTRY },
2485 { INT(bss_max_count), 0 },
2486 { INT(bss_expiration_age), 0 },
2487 { INT(bss_expiration_scan_count), 0 },
2488 { INT_RANGE(filter_ssids, 0, 1), 0 },
2489 { INT(max_num_sta), 0 },
2490 { INT_RANGE(disassoc_low_ack, 0, 1), 0 }
2491};
2492
2493#undef FUNC
2494#undef _INT
2495#undef INT
2496#undef INT_RANGE
2497#undef _STR
2498#undef STR
2499#undef STR_RANGE
2500#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0]))
2501
2502
2503int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
2504{
2505 size_t i;
2506 int ret = 0;
2507
2508 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
2509 const struct global_parse_data *field = &global_fields[i];
2510 size_t flen = os_strlen(field->name);
2511 if (os_strncmp(pos, field->name, flen) != 0 ||
2512 pos[flen] != '=')
2513 continue;
2514
2515 if (field->parser(field, config, line, pos + flen + 1)) {
2516 wpa_printf(MSG_ERROR, "Line %d: failed to "
2517 "parse '%s'.", line, pos);
2518 ret = -1;
2519 }
2520 config->changed_parameters |= field->changed_flag;
2521 break;
2522 }
2523 if (i == NUM_GLOBAL_FIELDS) {
2524 if (line < 0)
2525 return -1;
2526 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
2527 line, pos);
2528 ret = -1;
2529 }
2530
2531 return ret;
2532}