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