OSDN Git Service

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