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