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