1 /*
2 * WPA Supplicant / Configuration parser and common functions
3 * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "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 */
34 struct 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
wpa_config_parse_string(const char * value,size_t * len)61 static 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
wpa_config_parse_str(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)97 static 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
144 set:
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
is_hex(const u8 * data,size_t len)157 static 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
wpa_config_write_string_ascii(const u8 * value,size_t len)169 static 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
wpa_config_write_string_hex(const u8 * value,size_t len)185 static 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
wpa_config_write_string(const u8 * value,size_t len)198 static 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
wpa_config_write_str(const struct parse_data * data,struct wpa_ssid * ssid)210 static 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 }
227
228 #ifdef WPA_UNICODE_SSID
wpa_config_write_str_unicode(const struct parse_data * data,struct wpa_ssid * ssid)229 static 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
247 #endif /* NO_CONFIG_WRITE */
248
249
wpa_config_parse_int(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)250 static 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
wpa_config_write_int(const struct parse_data * data,struct wpa_ssid * ssid)281 static 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
wpa_config_parse_bssid(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)303 static 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
wpa_config_write_bssid(const struct parse_data * data,struct wpa_ssid * ssid)325 static 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
wpa_config_parse_psk(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)348 static 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
wpa_config_write_psk(const struct parse_data * data,struct wpa_ssid * ssid)406 static 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
wpa_config_parse_proto(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)422 static 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
wpa_config_write_proto(const struct parse_data * data,struct wpa_ssid * ssid)474 static 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
wpa_config_parse_key_mgmt(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)506 static 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
wpa_config_write_key_mgmt(const struct parse_data * data,struct wpa_ssid * ssid)579 static 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
wpa_config_parse_cipher(int line,const char * value)671 static 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
wpa_config_write_cipher(int cipher)724 static 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
wpa_config_parse_pairwise(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)789 static 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
wpa_config_write_pairwise(const struct parse_data * data,struct wpa_ssid * ssid)810 static 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
wpa_config_parse_group(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)818 static 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
wpa_config_write_group(const struct parse_data * data,struct wpa_ssid * ssid)840 static 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
wpa_config_parse_auth_alg(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)848 static 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
wpa_config_write_auth_alg(const struct parse_data * data,struct wpa_ssid * ssid)901 static 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
wpa_config_parse_freqs(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)947 static 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
wpa_config_parse_scan_freq(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)990 static 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
wpa_config_parse_freq_list(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)1006 static 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
wpa_config_write_freqs(const struct parse_data * data,const int * freqs)1023 static 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
wpa_config_write_scan_freq(const struct parse_data * data,struct wpa_ssid * ssid)1056 static 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
wpa_config_write_freq_list(const struct parse_data * data,struct wpa_ssid * ssid)1063 static 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
wpa_config_parse_eap(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)1072 static 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
wpa_config_write_eap(const struct parse_data * data,struct wpa_ssid * ssid)1144 static 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
wpa_config_parse_password(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)1179 static 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
wpa_config_write_password(const struct parse_data * data,struct wpa_ssid * ssid)1243 static 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
wpa_config_parse_wep_key(u8 * key,size_t * len,int line,const char * value,int idx)1268 static 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
wpa_config_parse_wep_key0(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)1295 static 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
wpa_config_parse_wep_key1(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)1305 static 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
wpa_config_parse_wep_key2(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)1315 static 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
wpa_config_parse_wep_key3(const struct parse_data * data,struct wpa_ssid * ssid,int line,const char * value)1325 static 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
wpa_config_write_wep_key(struct wpa_ssid * ssid,int idx)1336 static 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
wpa_config_write_wep_key0(const struct parse_data * data,struct wpa_ssid * ssid)1345 static 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
wpa_config_write_wep_key1(const struct parse_data * data,struct wpa_ssid * ssid)1352 static 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
wpa_config_write_wep_key2(const struct parse_data * data,struct wpa_ssid * ssid)1359 static 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
wpa_config_write_wep_key3(const struct parse_data * data,struct wpa_ssid * ssid)1366 static 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
1418 #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
1427 #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 */
1470 static const struct parse_data ssid_fields[] = {
1471 #ifdef WPA_UNICODE_SSID
1472 { STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) },
1473 #else
1474 { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1475 #endif
1476 { 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
1549 #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
1558 #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 */
wpa_config_add_prio_network(struct wpa_config * config,struct wpa_ssid * ssid)1588 int 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 */
wpa_config_update_prio_list(struct wpa_config * config)1639 int 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
eap_peer_config_free(struct eap_peer_config * eap)1661 static 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 */
wpa_config_free_ssid(struct wpa_ssid * ssid)1711 void 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 */
wpa_config_free(struct wpa_config * config)1733 void 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 */
wpa_config_foreach_network(struct wpa_config * config,void (* func)(void *,struct wpa_ssid *),void * arg)1785 void 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 */
wpa_config_get_network(struct wpa_config * config,int id)1806 struct 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 */
wpa_config_add_network(struct wpa_config * config)1826 struct 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 */
wpa_config_remove_network(struct wpa_config * config,int id)1862 int 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 */
wpa_config_set_network_defaults(struct wpa_ssid * ssid)1892 void 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 */
wpa_config_set(struct wpa_ssid * ssid,const char * var,const char * value,int line)1919 int 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 */
wpa_config_get_all(struct wpa_ssid * ssid,int get_keys)1966 char ** 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
2007 err:
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 */
wpa_config_get(struct wpa_ssid * ssid,const char * var)2029 char * 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 */
wpa_config_get_no_key(struct wpa_ssid * ssid,const char * var)2062 char * 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 */
wpa_config_update_psk(struct wpa_ssid * ssid)2101 void 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 */
wpa_config_get_blob(struct wpa_config * config,const char * name)2121 const 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 */
wpa_config_set_blob(struct wpa_config * config,struct wpa_config_blob * blob)2143 void 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 */
wpa_config_free_blob(struct wpa_config_blob * blob)2156 void 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 */
wpa_config_remove_blob(struct wpa_config * config,const char * name)2172 int 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 */
wpa_config_alloc_empty(const char * ctrl_interface,const char * driver_param)2201 struct 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 */
wpa_config_debug_dump_networks(struct wpa_config * config)2233 void 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
2253 struct 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
wpa_global_config_parse_int(const struct global_parse_data * data,struct wpa_config * config,int line,const char * pos)2262 static 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
wpa_global_config_parse_str(const struct global_parse_data * data,struct wpa_config * config,int line,const char * pos)2291 static 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
wpa_config_process_country(const struct global_parse_data * data,struct wpa_config * config,int line,const char * pos)2326 static 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
wpa_config_process_load_dynamic_eap(const struct global_parse_data * data,struct wpa_config * config,int line,const char * so)2342 static 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
wpa_config_process_uuid(const struct global_parse_data * data,struct wpa_config * config,int line,const char * pos)2364 static 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
wpa_config_process_device_type(const struct global_parse_data * data,struct wpa_config * config,int line,const char * pos)2379 static 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
wpa_config_process_os_version(const struct global_parse_data * data,struct wpa_config * config,int line,const char * pos)2387 static 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
wpa_config_process_sec_device_type(const struct global_parse_data * data,struct wpa_config * config,int line,const char * pos)2403 static 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
2441 static 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
wpa_config_process_global(struct wpa_config * config,char * pos,int line)2503 int 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 }
2533