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