Add support to wpa_supplicant configuring eap_peer for client cert and CA
[libeap.git] / wpa_supplicant / config.c
1 /*
2  * WPA Supplicant / Configuration parser and common functions
3  * Copyright (c) 2003-2007, 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                 else {
504                         wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
505                                    line, start);
506                         errors++;
507                 }
508
509                 if (last)
510                         break;
511                 start = end + 1;
512         }
513         os_free(buf);
514
515         if (val == 0) {
516                 wpa_printf(MSG_ERROR,
517                            "Line %d: no key_mgmt values configured.", line);
518                 errors++;
519         }
520
521         wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
522         ssid->key_mgmt = val;
523         return errors ? -1 : 0;
524 }
525
526
527 #ifndef NO_CONFIG_WRITE
528 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
529                                         struct wpa_ssid *ssid)
530 {
531         char *buf, *pos, *end;
532         int ret;
533
534         pos = buf = os_zalloc(50);
535         if (buf == NULL)
536                 return NULL;
537         end = buf + 50;
538
539         if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
540                 ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
541                                   pos == buf ? "" : " ");
542                 if (ret < 0 || ret >= end - pos) {
543                         end[-1] = '\0';
544                         return buf;
545                 }
546                 pos += ret;
547         }
548
549         if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
550                 ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
551                                   pos == buf ? "" : " ");
552                 if (ret < 0 || ret >= end - pos) {
553                         end[-1] = '\0';
554                         return buf;
555                 }
556                 pos += ret;
557         }
558
559         if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
560                 ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
561                                   pos == buf ? "" : " ");
562                 if (ret < 0 || ret >= end - pos) {
563                         end[-1] = '\0';
564                         return buf;
565                 }
566                 pos += ret;
567         }
568
569         if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
570                 ret = os_snprintf(pos, end - pos, "%sNONE",
571                                   pos == buf ? "" : " ");
572                 if (ret < 0 || ret >= end - pos) {
573                         end[-1] = '\0';
574                         return buf;
575                 }
576                 pos += ret;
577         }
578
579         if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
580                 ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
581                                   pos == buf ? "" : " ");
582                 if (ret < 0 || ret >= end - pos) {
583                         end[-1] = '\0';
584                         return buf;
585                 }
586                 pos += ret;
587         }
588
589 #ifdef CONFIG_IEEE80211R
590         if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK)
591                 pos += os_snprintf(pos, end - pos, "%sFT-PSK",
592                                    pos == buf ? "" : " ");
593
594         if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
595                 pos += os_snprintf(pos, end - pos, "%sFT-EAP",
596                                    pos == buf ? "" : " ");
597 #endif /* CONFIG_IEEE80211R */
598
599         return buf;
600 }
601 #endif /* NO_CONFIG_WRITE */
602
603
604 static int wpa_config_parse_cipher(int line, const char *value)
605 {
606         int val = 0, last;
607         char *start, *end, *buf;
608
609         buf = os_strdup(value);
610         if (buf == NULL)
611                 return -1;
612         start = buf;
613
614         while (*start != '\0') {
615                 while (*start == ' ' || *start == '\t')
616                         start++;
617                 if (*start == '\0')
618                         break;
619                 end = start;
620                 while (*end != ' ' && *end != '\t' && *end != '\0')
621                         end++;
622                 last = *end == '\0';
623                 *end = '\0';
624                 if (os_strcmp(start, "CCMP") == 0)
625                         val |= WPA_CIPHER_CCMP;
626                 else if (os_strcmp(start, "TKIP") == 0)
627                         val |= WPA_CIPHER_TKIP;
628                 else if (os_strcmp(start, "WEP104") == 0)
629                         val |= WPA_CIPHER_WEP104;
630                 else if (os_strcmp(start, "WEP40") == 0)
631                         val |= WPA_CIPHER_WEP40;
632                 else if (os_strcmp(start, "NONE") == 0)
633                         val |= WPA_CIPHER_NONE;
634                 else {
635                         wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
636                                    line, start);
637                         os_free(buf);
638                         return -1;
639                 }
640
641                 if (last)
642                         break;
643                 start = end + 1;
644         }
645         os_free(buf);
646
647         if (val == 0) {
648                 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
649                            line);
650                 return -1;
651         }
652         return val;
653 }
654
655
656 #ifndef NO_CONFIG_WRITE
657 static char * wpa_config_write_cipher(int cipher)
658 {
659         char *buf, *pos, *end;
660         int ret;
661
662         pos = buf = os_zalloc(50);
663         if (buf == NULL)
664                 return NULL;
665         end = buf + 50;
666
667         if (cipher & WPA_CIPHER_CCMP) {
668                 ret = os_snprintf(pos, end - pos, "%sCCMP",
669                                   pos == buf ? "" : " ");
670                 if (ret < 0 || ret >= end - pos) {
671                         end[-1] = '\0';
672                         return buf;
673                 }
674                 pos += ret;
675         }
676
677         if (cipher & WPA_CIPHER_TKIP) {
678                 ret = os_snprintf(pos, end - pos, "%sTKIP",
679                                   pos == buf ? "" : " ");
680                 if (ret < 0 || ret >= end - pos) {
681                         end[-1] = '\0';
682                         return buf;
683                 }
684                 pos += ret;
685         }
686
687         if (cipher & WPA_CIPHER_WEP104) {
688                 ret = os_snprintf(pos, end - pos, "%sWEP104",
689                                   pos == buf ? "" : " ");
690                 if (ret < 0 || ret >= end - pos) {
691                         end[-1] = '\0';
692                         return buf;
693                 }
694                 pos += ret;
695         }
696
697         if (cipher & WPA_CIPHER_WEP40) {
698                 ret = os_snprintf(pos, end - pos, "%sWEP40",
699                                   pos == buf ? "" : " ");
700                 if (ret < 0 || ret >= end - pos) {
701                         end[-1] = '\0';
702                         return buf;
703                 }
704                 pos += ret;
705         }
706
707         if (cipher & WPA_CIPHER_NONE) {
708                 ret = os_snprintf(pos, end - pos, "%sNONE",
709                                   pos == buf ? "" : " ");
710                 if (ret < 0 || ret >= end - pos) {
711                         end[-1] = '\0';
712                         return buf;
713                 }
714                 pos += ret;
715         }
716
717         return buf;
718 }
719 #endif /* NO_CONFIG_WRITE */
720
721
722 static int wpa_config_parse_pairwise(const struct parse_data *data,
723                                      struct wpa_ssid *ssid, int line,
724                                      const char *value)
725 {
726         int val;
727         val = wpa_config_parse_cipher(line, value);
728         if (val == -1)
729                 return -1;
730         if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
731                 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
732                            "(0x%x).", line, val);
733                 return -1;
734         }
735
736         wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
737         ssid->pairwise_cipher = val;
738         return 0;
739 }
740
741
742 #ifndef NO_CONFIG_WRITE
743 static char * wpa_config_write_pairwise(const struct parse_data *data,
744                                         struct wpa_ssid *ssid)
745 {
746         return wpa_config_write_cipher(ssid->pairwise_cipher);
747 }
748 #endif /* NO_CONFIG_WRITE */
749
750
751 static int wpa_config_parse_group(const struct parse_data *data,
752                                   struct wpa_ssid *ssid, int line,
753                                   const char *value)
754 {
755         int val;
756         val = wpa_config_parse_cipher(line, value);
757         if (val == -1)
758                 return -1;
759         if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
760                     WPA_CIPHER_WEP40)) {
761                 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
762                            "(0x%x).", line, val);
763                 return -1;
764         }
765
766         wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
767         ssid->group_cipher = val;
768         return 0;
769 }
770
771
772 #ifndef NO_CONFIG_WRITE
773 static char * wpa_config_write_group(const struct parse_data *data,
774                                      struct wpa_ssid *ssid)
775 {
776         return wpa_config_write_cipher(ssid->group_cipher);
777 }
778 #endif /* NO_CONFIG_WRITE */
779
780
781 static int wpa_config_parse_auth_alg(const struct parse_data *data,
782                                      struct wpa_ssid *ssid, int line,
783                                      const char *value)
784 {
785         int val = 0, last, errors = 0;
786         char *start, *end, *buf;
787
788         buf = os_strdup(value);
789         if (buf == NULL)
790                 return -1;
791         start = buf;
792
793         while (*start != '\0') {
794                 while (*start == ' ' || *start == '\t')
795                         start++;
796                 if (*start == '\0')
797                         break;
798                 end = start;
799                 while (*end != ' ' && *end != '\t' && *end != '\0')
800                         end++;
801                 last = *end == '\0';
802                 *end = '\0';
803                 if (os_strcmp(start, "OPEN") == 0)
804                         val |= WPA_AUTH_ALG_OPEN;
805                 else if (os_strcmp(start, "SHARED") == 0)
806                         val |= WPA_AUTH_ALG_SHARED;
807                 else if (os_strcmp(start, "LEAP") == 0)
808                         val |= WPA_AUTH_ALG_LEAP;
809                 else {
810                         wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
811                                    line, start);
812                         errors++;
813                 }
814
815                 if (last)
816                         break;
817                 start = end + 1;
818         }
819         os_free(buf);
820
821         if (val == 0) {
822                 wpa_printf(MSG_ERROR,
823                            "Line %d: no auth_alg values configured.", line);
824                 errors++;
825         }
826
827         wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
828         ssid->auth_alg = val;
829         return errors ? -1 : 0;
830 }
831
832
833 #ifndef NO_CONFIG_WRITE
834 static char * wpa_config_write_auth_alg(const struct parse_data *data,
835                                         struct wpa_ssid *ssid)
836 {
837         char *buf, *pos, *end;
838         int ret;
839
840         pos = buf = os_zalloc(30);
841         if (buf == NULL)
842                 return NULL;
843         end = buf + 30;
844
845         if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
846                 ret = os_snprintf(pos, end - pos, "%sOPEN",
847                                   pos == buf ? "" : " ");
848                 if (ret < 0 || ret >= end - pos) {
849                         end[-1] = '\0';
850                         return buf;
851                 }
852                 pos += ret;
853         }
854
855         if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
856                 ret = os_snprintf(pos, end - pos, "%sSHARED",
857                                   pos == buf ? "" : " ");
858                 if (ret < 0 || ret >= end - pos) {
859                         end[-1] = '\0';
860                         return buf;
861                 }
862                 pos += ret;
863         }
864
865         if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
866                 ret = os_snprintf(pos, end - pos, "%sLEAP",
867                                   pos == buf ? "" : " ");
868                 if (ret < 0 || ret >= end - pos) {
869                         end[-1] = '\0';
870                         return buf;
871                 }
872                 pos += ret;
873         }
874
875         return buf;
876 }
877 #endif /* NO_CONFIG_WRITE */
878
879
880 #ifdef IEEE8021X_EAPOL
881 static int wpa_config_parse_eap(const struct parse_data *data,
882                                 struct wpa_ssid *ssid, int line,
883                                 const char *value)
884 {
885         int last, errors = 0;
886         char *start, *end, *buf;
887         struct eap_method_type *methods = NULL, *tmp;
888         size_t num_methods = 0;
889
890         buf = os_strdup(value);
891         if (buf == NULL)
892                 return -1;
893         start = buf;
894
895         while (*start != '\0') {
896                 while (*start == ' ' || *start == '\t')
897                         start++;
898                 if (*start == '\0')
899                         break;
900                 end = start;
901                 while (*end != ' ' && *end != '\t' && *end != '\0')
902                         end++;
903                 last = *end == '\0';
904                 *end = '\0';
905                 tmp = methods;
906                 methods = os_realloc(methods,
907                                      (num_methods + 1) * sizeof(*methods));
908                 if (methods == NULL) {
909                         os_free(tmp);
910                         os_free(buf);
911                         return -1;
912                 }
913                 methods[num_methods].method = eap_peer_get_type(
914                         start, &methods[num_methods].vendor);
915                 if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
916                     methods[num_methods].method == EAP_TYPE_NONE) {
917                         wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
918                                    "'%s'", line, start);
919                         wpa_printf(MSG_ERROR, "You may need to add support for"
920                                    " this EAP method during wpa_supplicant\n"
921                                    "build time configuration.\n"
922                                    "See README for more information.");
923                         errors++;
924                 } else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
925                            methods[num_methods].method == EAP_TYPE_LEAP)
926                         ssid->leap++;
927                 else
928                         ssid->non_leap++;
929                 num_methods++;
930                 if (last)
931                         break;
932                 start = end + 1;
933         }
934         os_free(buf);
935
936         tmp = methods;
937         methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods));
938         if (methods == NULL) {
939                 os_free(tmp);
940                 return -1;
941         }
942         methods[num_methods].vendor = EAP_VENDOR_IETF;
943         methods[num_methods].method = EAP_TYPE_NONE;
944         num_methods++;
945
946         wpa_hexdump(MSG_MSGDUMP, "eap methods",
947                     (u8 *) methods, num_methods * sizeof(*methods));
948         ssid->eap.eap_methods = methods;
949         return errors ? -1 : 0;
950 }
951
952
953 static char * wpa_config_write_eap(const struct parse_data *data,
954                                    struct wpa_ssid *ssid)
955 {
956         int i, ret;
957         char *buf, *pos, *end;
958         const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
959         const char *name;
960
961         if (eap_methods == NULL)
962                 return NULL;
963
964         pos = buf = os_zalloc(100);
965         if (buf == NULL)
966                 return NULL;
967         end = buf + 100;
968
969         for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
970                      eap_methods[i].method != EAP_TYPE_NONE; i++) {
971                 name = eap_get_name(eap_methods[i].vendor,
972                                     eap_methods[i].method);
973                 if (name) {
974                         ret = os_snprintf(pos, end - pos, "%s%s",
975                                           pos == buf ? "" : " ", name);
976                         if (ret < 0 || ret >= end - pos)
977                                 break;
978                         pos += ret;
979                 }
980         }
981
982         end[-1] = '\0';
983
984         return buf;
985 }
986
987
988 static int wpa_config_parse_password(const struct parse_data *data,
989                                      struct wpa_ssid *ssid, int line,
990                                      const char *value)
991 {
992         u8 *hash;
993
994         if (os_strncmp(value, "hash:", 5) != 0) {
995                 char *tmp;
996                 size_t res_len;
997
998                 tmp = wpa_config_parse_string(value, &res_len);
999                 if (tmp == NULL) {
1000                         wpa_printf(MSG_ERROR, "Line %d: failed to parse "
1001                                    "password.", line);
1002                         return -1;
1003                 }
1004                 wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
1005                                   (u8 *) tmp, res_len);
1006
1007                 os_free(ssid->eap.password);
1008                 ssid->eap.password = (u8 *) tmp;
1009                 ssid->eap.password_len = res_len;
1010                 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1011
1012                 return 0;
1013         }
1014
1015
1016         /* NtPasswordHash: hash:<32 hex digits> */
1017         if (os_strlen(value + 5) != 2 * 16) {
1018                 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
1019                            "(expected 32 hex digits)", line);
1020                 return -1;
1021         }
1022
1023         hash = os_malloc(16);
1024         if (hash == NULL)
1025                 return -1;
1026
1027         if (hexstr2bin(value + 5, hash, 16)) {
1028                 os_free(hash);
1029                 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
1030                 return -1;
1031         }
1032
1033         wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
1034
1035         os_free(ssid->eap.password);
1036         ssid->eap.password = hash;
1037         ssid->eap.password_len = 16;
1038         ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1039
1040         return 0;
1041 }
1042
1043
1044 static char * wpa_config_write_password(const struct parse_data *data,
1045                                         struct wpa_ssid *ssid)
1046 {
1047         char *buf;
1048
1049         if (ssid->eap.password == NULL)
1050                 return NULL;
1051
1052         if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
1053                 return wpa_config_write_string(
1054                         ssid->eap.password, ssid->eap.password_len);
1055         }
1056
1057         buf = os_malloc(5 + 32 + 1);
1058         if (buf == NULL)
1059                 return NULL;
1060
1061         os_memcpy(buf, "hash:", 5);
1062         wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
1063
1064         return buf;
1065 }
1066 #endif /* IEEE8021X_EAPOL */
1067
1068
1069 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
1070                                     const char *value, int idx)
1071 {
1072         char *buf, title[20];
1073         int res;
1074
1075         buf = wpa_config_parse_string(value, len);
1076         if (buf == NULL) {
1077                 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
1078                            line, idx, value);
1079                 return -1;
1080         }
1081         if (*len > MAX_WEP_KEY_LEN) {
1082                 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
1083                            line, idx, value);
1084                 os_free(buf);
1085                 return -1;
1086         }
1087         os_memcpy(key, buf, *len);
1088         os_free(buf);
1089         res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
1090         if (res >= 0 && (size_t) res < sizeof(title))
1091                 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
1092         return 0;
1093 }
1094
1095
1096 static int wpa_config_parse_wep_key0(const struct parse_data *data,
1097                                      struct wpa_ssid *ssid, int line,
1098                                      const char *value)
1099 {
1100         return wpa_config_parse_wep_key(ssid->wep_key[0],
1101                                         &ssid->wep_key_len[0], line,
1102                                         value, 0);
1103 }
1104
1105
1106 static int wpa_config_parse_wep_key1(const struct parse_data *data,
1107                                      struct wpa_ssid *ssid, int line,
1108                                      const char *value)
1109 {
1110         return wpa_config_parse_wep_key(ssid->wep_key[1],
1111                                         &ssid->wep_key_len[1], line,
1112                                         value, 1);
1113 }
1114
1115
1116 static int wpa_config_parse_wep_key2(const struct parse_data *data,
1117                                      struct wpa_ssid *ssid, int line,
1118                                      const char *value)
1119 {
1120         return wpa_config_parse_wep_key(ssid->wep_key[2],
1121                                         &ssid->wep_key_len[2], line,
1122                                         value, 2);
1123 }
1124
1125
1126 static int wpa_config_parse_wep_key3(const struct parse_data *data,
1127                                      struct wpa_ssid *ssid, int line,
1128                                      const char *value)
1129 {
1130         return wpa_config_parse_wep_key(ssid->wep_key[3],
1131                                         &ssid->wep_key_len[3], line,
1132                                         value, 3);
1133 }
1134
1135
1136 #ifndef NO_CONFIG_WRITE
1137 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
1138 {
1139         if (ssid->wep_key_len[idx] == 0)
1140                 return NULL;
1141         return wpa_config_write_string(ssid->wep_key[idx],
1142                                        ssid->wep_key_len[idx]);
1143 }
1144
1145
1146 static char * wpa_config_write_wep_key0(const struct parse_data *data,
1147                                         struct wpa_ssid *ssid)
1148 {
1149         return wpa_config_write_wep_key(ssid, 0);
1150 }
1151
1152
1153 static char * wpa_config_write_wep_key1(const struct parse_data *data,
1154                                         struct wpa_ssid *ssid)
1155 {
1156         return wpa_config_write_wep_key(ssid, 1);
1157 }
1158
1159
1160 static char * wpa_config_write_wep_key2(const struct parse_data *data,
1161                                         struct wpa_ssid *ssid)
1162 {
1163         return wpa_config_write_wep_key(ssid, 2);
1164 }
1165
1166
1167 static char * wpa_config_write_wep_key3(const struct parse_data *data,
1168                                         struct wpa_ssid *ssid)
1169 {
1170         return wpa_config_write_wep_key(ssid, 3);
1171 }
1172 #endif /* NO_CONFIG_WRITE */
1173
1174
1175 /* Helper macros for network block parser */
1176
1177 #ifdef OFFSET
1178 #undef OFFSET
1179 #endif /* OFFSET */
1180 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
1181 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
1182
1183 /* STR: Define a string variable for an ASCII string; f = field name */
1184 #ifdef NO_CONFIG_WRITE
1185 #define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
1186 #define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
1187 #else /* NO_CONFIG_WRITE */
1188 #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
1189 #define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
1190 #endif /* NO_CONFIG_WRITE */
1191 #define STR(f) _STR(f), NULL, NULL, NULL, 0
1192 #define STRe(f) _STRe(f), NULL, NULL, NULL, 0
1193 #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
1194 #define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
1195
1196 /* STR_LEN: Define a string variable with a separate variable for storing the
1197  * data length. Unlike STR(), this can be used to store arbitrary binary data
1198  * (i.e., even nul termination character). */
1199 #define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
1200 #define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
1201 #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
1202 #define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
1203 #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
1204
1205 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
1206  * explicitly specified. */
1207 #define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
1208 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
1209 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
1210
1211 #ifdef NO_CONFIG_WRITE
1212 #define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
1213 #define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
1214 #else /* NO_CONFIG_WRITE */
1215 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1216         OFFSET(f), (void *) 0
1217 #define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1218         OFFSET(eap.f), (void *) 0
1219 #endif /* NO_CONFIG_WRITE */
1220
1221 /* INT: Define an integer variable */
1222 #define INT(f) _INT(f), NULL, NULL, 0
1223 #define INTe(f) _INTe(f), NULL, NULL, 0
1224
1225 /* INT_RANGE: Define an integer variable with allowed value range */
1226 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
1227
1228 /* FUNC: Define a configuration variable that uses a custom function for
1229  * parsing and writing the value. */
1230 #ifdef NO_CONFIG_WRITE
1231 #define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
1232 #else /* NO_CONFIG_WRITE */
1233 #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
1234         NULL, NULL, NULL, NULL
1235 #endif /* NO_CONFIG_WRITE */
1236 #define FUNC(f) _FUNC(f), 0
1237 #define FUNC_KEY(f) _FUNC(f), 1
1238
1239 /*
1240  * Table of network configuration variables. This table is used to parse each
1241  * network configuration variable, e.g., each line in wpa_supplicant.conf file
1242  * that is inside a network block.
1243  *
1244  * This table is generated using the helper macros defined above and with
1245  * generous help from the C pre-processor. The field name is stored as a string
1246  * into .name and for STR and INT types, the offset of the target buffer within
1247  * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
1248  * offset to the field containing the length of the configuration variable.
1249  * .param3 and .param4 can be used to mark the allowed range (length for STR
1250  * and value for INT).
1251  *
1252  * For each configuration line in wpa_supplicant.conf, the parser goes through
1253  * this table and select the entry that matches with the field name. The parser
1254  * function (.parser) is then called to parse the actual value of the field.
1255  *
1256  * This kind of mechanism makes it easy to add new configuration parameters,
1257  * since only one line needs to be added into this table and into the
1258  * struct wpa_ssid definition if the new variable is either a string or
1259  * integer. More complex types will need to use their own parser and writer
1260  * functions.
1261  */
1262 static const struct parse_data ssid_fields[] = {
1263         { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1264         { INT_RANGE(scan_ssid, 0, 1) },
1265         { FUNC(bssid) },
1266         { FUNC_KEY(psk) },
1267         { FUNC(proto) },
1268         { FUNC(key_mgmt) },
1269         { FUNC(pairwise) },
1270         { FUNC(group) },
1271         { FUNC(auth_alg) },
1272 #ifdef IEEE8021X_EAPOL
1273         { FUNC(eap) },
1274         { STR_LENe(identity) },
1275         { STR_LENe(anonymous_identity) },
1276         { FUNC(password) },
1277         { STRe(ca_cert) },
1278         { STRe(ca_path) },
1279         { STRe(client_cert) },
1280         { STRe(private_key) },
1281         { STR_KEYe(private_key_passwd) },
1282         { STRe(dh_file) },
1283         { STRe(subject_match) },
1284         { STRe(altsubject_match) },
1285         { STRe(ca_cert2) },
1286         { STRe(ca_path2) },
1287         { STRe(client_cert2) },
1288         { STRe(private_key2) },
1289         { STR_KEYe(private_key2_passwd) },
1290         { STRe(dh_file2) },
1291         { STRe(subject_match2) },
1292         { STRe(altsubject_match2) },
1293         { STRe(phase1) },
1294         { STRe(phase2) },
1295         { STRe(pcsc) },
1296         { STR_KEYe(pin) },
1297         { STRe(engine_id) },
1298         { STRe(key_id) },
1299         { STRe(cert_id) },
1300         { STRe(ca_cert_id) },
1301         { STRe(key2_id) },
1302         { STRe(cert2_id) },
1303         { STRe(ca_cert2_id) },
1304         { INTe(engine) },
1305         { INT(eapol_flags) },
1306 #endif /* IEEE8021X_EAPOL */
1307         { FUNC_KEY(wep_key0) },
1308         { FUNC_KEY(wep_key1) },
1309         { FUNC_KEY(wep_key2) },
1310         { FUNC_KEY(wep_key3) },
1311         { INT(wep_tx_keyidx) },
1312         { INT(priority) },
1313 #ifdef IEEE8021X_EAPOL
1314         { INT(eap_workaround) },
1315         { STRe(pac_file) },
1316         { INTe(fragment_size) },
1317 #endif /* IEEE8021X_EAPOL */
1318         { INT_RANGE(mode, 0, 1) },
1319         { INT_RANGE(proactive_key_caching, 0, 1) },
1320         { INT_RANGE(disabled, 0, 1) },
1321         { STR(id_str) },
1322 #ifdef CONFIG_IEEE80211W
1323         { INT_RANGE(ieee80211w, 0, 2) },
1324 #endif /* CONFIG_IEEE80211W */
1325         { INT_RANGE(peerkey, 0, 1) },
1326         { INT_RANGE(mixed_cell, 0, 1) },
1327         { INT_RANGE(frequency, 0, 10000) }
1328 };
1329
1330 #undef OFFSET
1331 #undef _STR
1332 #undef STR
1333 #undef STR_KEY
1334 #undef _STR_LEN
1335 #undef STR_LEN
1336 #undef STR_LEN_KEY
1337 #undef _STR_RANGE
1338 #undef STR_RANGE
1339 #undef STR_RANGE_KEY
1340 #undef _INT
1341 #undef INT
1342 #undef INT_RANGE
1343 #undef _FUNC
1344 #undef FUNC
1345 #undef FUNC_KEY
1346 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1347
1348
1349 /**
1350  * wpa_config_add_prio_network - Add a network to priority lists
1351  * @config: Configuration data from wpa_config_read()
1352  * @ssid: Pointer to the network configuration to be added to the list
1353  * Returns: 0 on success, -1 on failure
1354  *
1355  * This function is used to add a network block to the priority list of
1356  * networks. This must be called for each network when reading in the full
1357  * configuration. In addition, this can be used indirectly when updating
1358  * priorities by calling wpa_config_update_prio_list().
1359  */
1360 int wpa_config_add_prio_network(struct wpa_config *config,
1361                                 struct wpa_ssid *ssid)
1362 {
1363         int prio;
1364         struct wpa_ssid *prev, **nlist;
1365
1366         /*
1367          * Add to an existing priority list if one is available for the
1368          * configured priority level for this network.
1369          */
1370         for (prio = 0; prio < config->num_prio; prio++) {
1371                 prev = config->pssid[prio];
1372                 if (prev->priority == ssid->priority) {
1373                         while (prev->pnext)
1374                                 prev = prev->pnext;
1375                         prev->pnext = ssid;
1376                         return 0;
1377                 }
1378         }
1379
1380         /* First network for this priority - add a new priority list */
1381         nlist = os_realloc(config->pssid,
1382                            (config->num_prio + 1) * sizeof(struct wpa_ssid *));
1383         if (nlist == NULL)
1384                 return -1;
1385
1386         for (prio = 0; prio < config->num_prio; prio++) {
1387                 if (nlist[prio]->priority < ssid->priority)
1388                         break;
1389         }
1390
1391         os_memmove(&nlist[prio + 1], &nlist[prio],
1392                    (config->num_prio - prio) * sizeof(struct wpa_ssid *));
1393
1394         nlist[prio] = ssid;
1395         config->num_prio++;
1396         config->pssid = nlist;
1397
1398         return 0;
1399 }
1400
1401
1402 /**
1403  * wpa_config_update_prio_list - Update network priority list
1404  * @config: Configuration data from wpa_config_read()
1405  * Returns: 0 on success, -1 on failure
1406  *
1407  * This function is called to update the priority list of networks in the
1408  * configuration when a network is being added or removed. This is also called
1409  * if a priority for a network is changed.
1410  */
1411 static int wpa_config_update_prio_list(struct wpa_config *config)
1412 {
1413         struct wpa_ssid *ssid;
1414         int ret = 0;
1415
1416         os_free(config->pssid);
1417         config->pssid = NULL;
1418         config->num_prio = 0;
1419
1420         ssid = config->ssid;
1421         while (ssid) {
1422                 ssid->pnext = NULL;
1423                 if (wpa_config_add_prio_network(config, ssid) < 0)
1424                         ret = -1;
1425                 ssid = ssid->next;
1426         }
1427
1428         return ret;
1429 }
1430
1431
1432 #ifdef IEEE8021X_EAPOL
1433 static void eap_peer_config_free(struct eap_peer_config *eap)
1434 {
1435         os_free(eap->eap_methods);
1436         os_free(eap->identity);
1437         os_free(eap->anonymous_identity);
1438         os_free(eap->password);
1439         os_free(eap->ca_cert);
1440         os_free(eap->ca_path);
1441         os_free(eap->client_cert);
1442         os_free(eap->private_key);
1443         os_free(eap->private_key_passwd);
1444         os_free(eap->dh_file);
1445         os_free(eap->subject_match);
1446         os_free(eap->altsubject_match);
1447         os_free(eap->ca_cert2);
1448         os_free(eap->ca_path2);
1449         os_free(eap->client_cert2);
1450         os_free(eap->private_key2);
1451         os_free(eap->private_key2_passwd);
1452         os_free(eap->dh_file2);
1453         os_free(eap->subject_match2);
1454         os_free(eap->altsubject_match2);
1455         os_free(eap->phase1);
1456         os_free(eap->phase2);
1457         os_free(eap->pcsc);
1458         os_free(eap->pin);
1459         os_free(eap->engine_id);
1460         os_free(eap->key_id);
1461         os_free(eap->cert_id);
1462         os_free(eap->ca_cert_id);
1463         os_free(eap->key2_id);
1464         os_free(eap->cert2_id);
1465         os_free(eap->ca_cert2_id);
1466         os_free(eap->otp);
1467         os_free(eap->pending_req_otp);
1468         os_free(eap->pac_file);
1469         os_free(eap->new_password);
1470 }
1471 #endif /* IEEE8021X_EAPOL */
1472
1473
1474 /**
1475  * wpa_config_free_ssid - Free network/ssid configuration data
1476  * @ssid: Configuration data for the network
1477  *
1478  * This function frees all resources allocated for the network configuration
1479  * data.
1480  */
1481 void wpa_config_free_ssid(struct wpa_ssid *ssid)
1482 {
1483         os_free(ssid->ssid);
1484         os_free(ssid->passphrase);
1485 #ifdef IEEE8021X_EAPOL
1486         eap_peer_config_free(&ssid->eap);
1487 #endif /* IEEE8021X_EAPOL */
1488         os_free(ssid->id_str);
1489         os_free(ssid);
1490 }
1491
1492
1493 /**
1494  * wpa_config_free - Free configuration data
1495  * @config: Configuration data from wpa_config_read()
1496  *
1497  * This function frees all resources allocated for the configuration data by
1498  * wpa_config_read().
1499  */
1500 void wpa_config_free(struct wpa_config *config)
1501 {
1502 #ifndef CONFIG_NO_CONFIG_BLOBS
1503         struct wpa_config_blob *blob, *prevblob;
1504 #endif /* CONFIG_NO_CONFIG_BLOBS */
1505         struct wpa_ssid *ssid, *prev = NULL;
1506         ssid = config->ssid;
1507         while (ssid) {
1508                 prev = ssid;
1509                 ssid = ssid->next;
1510                 wpa_config_free_ssid(prev);
1511         }
1512
1513 #ifndef CONFIG_NO_CONFIG_BLOBS
1514         blob = config->blobs;
1515         prevblob = NULL;
1516         while (blob) {
1517                 prevblob = blob;
1518                 blob = blob->next;
1519                 wpa_config_free_blob(prevblob);
1520         }
1521 #endif /* CONFIG_NO_CONFIG_BLOBS */
1522
1523         os_free(config->ctrl_interface);
1524         os_free(config->ctrl_interface_group);
1525 #ifdef EAP_TLS_OPENSSL
1526         os_free(config->opensc_engine_path);
1527         os_free(config->pkcs11_engine_path);
1528         os_free(config->pkcs11_module_path);
1529 #endif /* EAP_TLS_OPENSSL */
1530         os_free(config->driver_param);
1531         os_free(config->pssid);
1532         os_free(config);
1533 }
1534
1535
1536 /**
1537  * wpa_config_get_network - Get configured network based on id
1538  * @config: Configuration data from wpa_config_read()
1539  * @id: Unique network id to search for
1540  * Returns: Network configuration or %NULL if not found
1541  */
1542 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1543 {
1544         struct wpa_ssid *ssid;
1545
1546         ssid = config->ssid;
1547         while (ssid) {
1548                 if (id == ssid->id)
1549                         break;
1550                 ssid = ssid->next;
1551         }
1552
1553         return ssid;
1554 }
1555
1556
1557 /**
1558  * wpa_config_add_network - Add a new network with empty configuration
1559  * @config: Configuration data from wpa_config_read()
1560  * Returns: The new network configuration or %NULL if operation failed
1561  */
1562 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1563 {
1564         int id;
1565         struct wpa_ssid *ssid, *last = NULL;
1566
1567         id = -1;
1568         ssid = config->ssid;
1569         while (ssid) {
1570                 if (ssid->id > id)
1571                         id = ssid->id;
1572                 last = ssid;
1573                 ssid = ssid->next;
1574         }
1575         id++;
1576
1577         ssid = os_zalloc(sizeof(*ssid));
1578         if (ssid == NULL)
1579                 return NULL;
1580         ssid->id = id;
1581         if (last)
1582                 last->next = ssid;
1583         else
1584                 config->ssid = ssid;
1585
1586         wpa_config_update_prio_list(config);
1587
1588         return ssid;
1589 }
1590
1591
1592 /**
1593  * wpa_config_remove_network - Remove a configured network based on id
1594  * @config: Configuration data from wpa_config_read()
1595  * @id: Unique network id to search for
1596  * Returns: 0 on success, or -1 if the network was not found
1597  */
1598 int wpa_config_remove_network(struct wpa_config *config, int id)
1599 {
1600         struct wpa_ssid *ssid, *prev = NULL;
1601
1602         ssid = config->ssid;
1603         while (ssid) {
1604                 if (id == ssid->id)
1605                         break;
1606                 prev = ssid;
1607                 ssid = ssid->next;
1608         }
1609
1610         if (ssid == NULL)
1611                 return -1;
1612
1613         if (prev)
1614                 prev->next = ssid->next;
1615         else
1616                 config->ssid = ssid->next;
1617
1618         wpa_config_update_prio_list(config);
1619         wpa_config_free_ssid(ssid);
1620         return 0;
1621 }
1622
1623
1624 /**
1625  * wpa_config_set_network_defaults - Set network default values
1626  * @ssid: Pointer to network configuration data
1627  */
1628 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
1629 {
1630         ssid->proto = DEFAULT_PROTO;
1631         ssid->pairwise_cipher = DEFAULT_PAIRWISE;
1632         ssid->group_cipher = DEFAULT_GROUP;
1633         ssid->key_mgmt = DEFAULT_KEY_MGMT;
1634 #ifdef IEEE8021X_EAPOL
1635         ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
1636         ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
1637         ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
1638 #endif /* IEEE8021X_EAPOL */
1639 }
1640
1641
1642 /**
1643  * wpa_config_set - Set a variable in network configuration
1644  * @ssid: Pointer to network configuration data
1645  * @var: Variable name, e.g., "ssid"
1646  * @value: Variable value
1647  * @line: Line number in configuration file or 0 if not used
1648  * Returns: 0 on success, -1 on failure
1649  *
1650  * This function can be used to set network configuration variables based on
1651  * both the configuration file and management interface input. The value
1652  * parameter must be in the same format as the text-based configuration file is
1653  * using. For example, strings are using double quotation marks.
1654  */
1655 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
1656                    int line)
1657 {
1658         size_t i;
1659         int ret = 0;
1660
1661         if (ssid == NULL || var == NULL || value == NULL)
1662                 return -1;
1663
1664         for (i = 0; i < NUM_SSID_FIELDS; i++) {
1665                 const struct parse_data *field = &ssid_fields[i];
1666                 if (os_strcmp(var, field->name) != 0)
1667                         continue;
1668
1669                 if (field->parser(field, ssid, line, value)) {
1670                         if (line) {
1671                                 wpa_printf(MSG_ERROR, "Line %d: failed to "
1672                                            "parse %s '%s'.", line, var, value);
1673                         }
1674                         ret = -1;
1675                 }
1676                 break;
1677         }
1678         if (i == NUM_SSID_FIELDS) {
1679                 if (line) {
1680                         wpa_printf(MSG_ERROR, "Line %d: unknown network field "
1681                                    "'%s'.", line, var);
1682                 }
1683                 ret = -1;
1684         }
1685
1686         return ret;
1687 }
1688
1689
1690 #ifndef NO_CONFIG_WRITE
1691 /**
1692  * wpa_config_get - Get a variable in network configuration
1693  * @ssid: Pointer to network configuration data
1694  * @var: Variable name, e.g., "ssid"
1695  * Returns: Value of the variable or %NULL on failure
1696  *
1697  * This function can be used to get network configuration variables. The
1698  * returned value is a copy of the configuration variable in text format, i.e,.
1699  * the same format that the text-based configuration file and wpa_config_set()
1700  * are using for the value. The caller is responsible for freeing the returned
1701  * value.
1702  */
1703 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
1704 {
1705         size_t i;
1706
1707         if (ssid == NULL || var == NULL)
1708                 return NULL;
1709
1710         for (i = 0; i < NUM_SSID_FIELDS; i++) {
1711                 const struct parse_data *field = &ssid_fields[i];
1712                 if (os_strcmp(var, field->name) == 0)
1713                         return field->writer(field, ssid);
1714         }
1715
1716         return NULL;
1717 }
1718
1719
1720 /**
1721  * wpa_config_get_no_key - Get a variable in network configuration (no keys)
1722  * @ssid: Pointer to network configuration data
1723  * @var: Variable name, e.g., "ssid"
1724  * Returns: Value of the variable or %NULL on failure
1725  *
1726  * This function can be used to get network configuration variable like
1727  * wpa_config_get(). The only difference is that this functions does not expose
1728  * key/password material from the configuration. In case a key/password field
1729  * is requested, the returned value is an empty string or %NULL if the variable
1730  * is not set or "*" if the variable is set (regardless of its value). The
1731  * returned value is a copy of the configuration variable in text format, i.e,.
1732  * the same format that the text-based configuration file and wpa_config_set()
1733  * are using for the value. The caller is responsible for freeing the returned
1734  * value.
1735  */
1736 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
1737 {
1738         size_t i;
1739
1740         if (ssid == NULL || var == NULL)
1741                 return NULL;
1742
1743         for (i = 0; i < NUM_SSID_FIELDS; i++) {
1744                 const struct parse_data *field = &ssid_fields[i];
1745                 if (os_strcmp(var, field->name) == 0) {
1746                         char *res = field->writer(field, ssid);
1747                         if (field->key_data) {
1748                                 if (res && res[0]) {
1749                                         wpa_printf(MSG_DEBUG, "Do not allow "
1750                                                    "key_data field to be "
1751                                                    "exposed");
1752                                         os_free(res);
1753                                         return os_strdup("*");
1754                                 }
1755
1756                                 os_free(res);
1757                                 return NULL;
1758                         }
1759                         return res;
1760                 }
1761         }
1762
1763         return NULL;
1764 }
1765 #endif /* NO_CONFIG_WRITE */
1766
1767
1768 /**
1769  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
1770  * @ssid: Pointer to network configuration data
1771  *
1772  * This function must be called to update WPA PSK when either SSID or the
1773  * passphrase has changed for the network configuration.
1774  */
1775 void wpa_config_update_psk(struct wpa_ssid *ssid)
1776 {
1777 #ifndef CONFIG_NO_PBKDF2
1778         pbkdf2_sha1(ssid->passphrase,
1779                     (char *) ssid->ssid, ssid->ssid_len, 4096,
1780                     ssid->psk, PMK_LEN);
1781         wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1782                         ssid->psk, PMK_LEN);
1783         ssid->psk_set = 1;
1784 #endif /* CONFIG_NO_PBKDF2 */
1785 }
1786
1787
1788 #ifndef CONFIG_NO_CONFIG_BLOBS
1789 /**
1790  * wpa_config_get_blob - Get a named configuration blob
1791  * @config: Configuration data from wpa_config_read()
1792  * @name: Name of the blob
1793  * Returns: Pointer to blob data or %NULL if not found
1794  */
1795 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
1796                                                    const char *name)
1797 {
1798         struct wpa_config_blob *blob = config->blobs;
1799
1800         while (blob) {
1801                 if (os_strcmp(blob->name, name) == 0)
1802                         return blob;
1803                 blob = blob->next;
1804         }
1805         return NULL;
1806 }
1807
1808
1809 /**
1810  * wpa_config_set_blob - Set or add a named configuration blob
1811  * @config: Configuration data from wpa_config_read()
1812  * @blob: New value for the blob
1813  *
1814  * Adds a new configuration blob or replaces the current value of an existing
1815  * blob.
1816  */
1817 void wpa_config_set_blob(struct wpa_config *config,
1818                          struct wpa_config_blob *blob)
1819 {
1820         wpa_config_remove_blob(config, blob->name);
1821         blob->next = config->blobs;
1822         config->blobs = blob;
1823 }
1824
1825
1826 /**
1827  * wpa_config_free_blob - Free blob data
1828  * @blob: Pointer to blob to be freed
1829  */
1830 void wpa_config_free_blob(struct wpa_config_blob *blob)
1831 {
1832         if (blob) {
1833                 os_free(blob->name);
1834                 os_free(blob->data);
1835                 os_free(blob);
1836         }
1837 }
1838
1839
1840 /**
1841  * wpa_config_remove_blob - Remove a named configuration blob
1842  * @config: Configuration data from wpa_config_read()
1843  * @name: Name of the blob to remove
1844  * Returns: 0 if blob was removed or -1 if blob was not found
1845  */
1846 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
1847 {
1848         struct wpa_config_blob *pos = config->blobs, *prev = NULL;
1849
1850         while (pos) {
1851                 if (os_strcmp(pos->name, name) == 0) {
1852                         if (prev)
1853                                 prev->next = pos->next;
1854                         else
1855                                 config->blobs = pos->next;
1856                         wpa_config_free_blob(pos);
1857                         return 0;
1858                 }
1859                 prev = pos;
1860                 pos = pos->next;
1861         }
1862
1863         return -1;
1864 }
1865 #endif /* CONFIG_NO_CONFIG_BLOBS */
1866
1867
1868 /**
1869  * wpa_config_alloc_empty - Allocate an empty configuration
1870  * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
1871  * socket
1872  * @driver_param: Driver parameters
1873  * Returns: Pointer to allocated configuration data or %NULL on failure
1874  */
1875 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
1876                                            const char *driver_param)
1877 {
1878         struct wpa_config *config;
1879
1880         config = os_zalloc(sizeof(*config));
1881         if (config == NULL)
1882                 return NULL;
1883         config->eapol_version = DEFAULT_EAPOL_VERSION;
1884         config->ap_scan = DEFAULT_AP_SCAN;
1885         config->fast_reauth = DEFAULT_FAST_REAUTH;
1886
1887         if (ctrl_interface)
1888                 config->ctrl_interface = os_strdup(ctrl_interface);
1889         if (driver_param)
1890                 config->driver_param = os_strdup(driver_param);
1891
1892         return config;
1893 }
1894
1895
1896 #ifndef CONFIG_NO_STDOUT_DEBUG
1897 /**
1898  * wpa_config_debug_dump_networks - Debug dump of configured networks
1899  * @config: Configuration data from wpa_config_read()
1900  */
1901 void wpa_config_debug_dump_networks(struct wpa_config *config)
1902 {
1903         int prio;
1904         struct wpa_ssid *ssid;
1905
1906         for (prio = 0; prio < config->num_prio; prio++) {
1907                 ssid = config->pssid[prio];
1908                 wpa_printf(MSG_DEBUG, "Priority group %d",
1909                            ssid->priority);
1910                 while (ssid) {
1911                         wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
1912                                    ssid->id,
1913                                    wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1914                         ssid = ssid->pnext;
1915                 }
1916         }
1917 }
1918 #endif /* CONFIG_NO_STDOUT_DEBUG */