Re-initialize hostapd/wpa_supplicant git repository based on 0.6.3 release
[wpasupplicant] / 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         { INTe(engine) },
1300         { INT(eapol_flags) },
1301 #endif /* IEEE8021X_EAPOL */
1302         { FUNC_KEY(wep_key0) },
1303         { FUNC_KEY(wep_key1) },
1304         { FUNC_KEY(wep_key2) },
1305         { FUNC_KEY(wep_key3) },
1306         { INT(wep_tx_keyidx) },
1307         { INT(priority) },
1308 #ifdef IEEE8021X_EAPOL
1309         { INT(eap_workaround) },
1310         { STRe(pac_file) },
1311         { INTe(fragment_size) },
1312 #endif /* IEEE8021X_EAPOL */
1313         { INT_RANGE(mode, 0, 1) },
1314         { INT_RANGE(proactive_key_caching, 0, 1) },
1315         { INT_RANGE(disabled, 0, 1) },
1316         { STR(id_str) },
1317 #ifdef CONFIG_IEEE80211W
1318         { INT_RANGE(ieee80211w, 0, 2) },
1319 #endif /* CONFIG_IEEE80211W */
1320         { INT_RANGE(peerkey, 0, 1) },
1321         { INT_RANGE(mixed_cell, 0, 1) },
1322         { INT_RANGE(frequency, 0, 10000) }
1323 };
1324
1325 #undef OFFSET
1326 #undef _STR
1327 #undef STR
1328 #undef STR_KEY
1329 #undef _STR_LEN
1330 #undef STR_LEN
1331 #undef STR_LEN_KEY
1332 #undef _STR_RANGE
1333 #undef STR_RANGE
1334 #undef STR_RANGE_KEY
1335 #undef _INT
1336 #undef INT
1337 #undef INT_RANGE
1338 #undef _FUNC
1339 #undef FUNC
1340 #undef FUNC_KEY
1341 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1342
1343
1344 /**
1345  * wpa_config_add_prio_network - Add a network to priority lists
1346  * @config: Configuration data from wpa_config_read()
1347  * @ssid: Pointer to the network configuration to be added to the list
1348  * Returns: 0 on success, -1 on failure
1349  *
1350  * This function is used to add a network block to the priority list of
1351  * networks. This must be called for each network when reading in the full
1352  * configuration. In addition, this can be used indirectly when updating
1353  * priorities by calling wpa_config_update_prio_list().
1354  */
1355 int wpa_config_add_prio_network(struct wpa_config *config,
1356                                 struct wpa_ssid *ssid)
1357 {
1358         int prio;
1359         struct wpa_ssid *prev, **nlist;
1360
1361         /*
1362          * Add to an existing priority list if one is available for the
1363          * configured priority level for this network.
1364          */
1365         for (prio = 0; prio < config->num_prio; prio++) {
1366                 prev = config->pssid[prio];
1367                 if (prev->priority == ssid->priority) {
1368                         while (prev->pnext)
1369                                 prev = prev->pnext;
1370                         prev->pnext = ssid;
1371                         return 0;
1372                 }
1373         }
1374
1375         /* First network for this priority - add a new priority list */
1376         nlist = os_realloc(config->pssid,
1377                            (config->num_prio + 1) * sizeof(struct wpa_ssid *));
1378         if (nlist == NULL)
1379                 return -1;
1380
1381         for (prio = 0; prio < config->num_prio; prio++) {
1382                 if (nlist[prio]->priority < ssid->priority)
1383                         break;
1384         }
1385
1386         os_memmove(&nlist[prio + 1], &nlist[prio],
1387                    (config->num_prio - prio) * sizeof(struct wpa_ssid *));
1388
1389         nlist[prio] = ssid;
1390         config->num_prio++;
1391         config->pssid = nlist;
1392
1393         return 0;
1394 }
1395
1396
1397 /**
1398  * wpa_config_update_prio_list - Update network priority list
1399  * @config: Configuration data from wpa_config_read()
1400  * Returns: 0 on success, -1 on failure
1401  *
1402  * This function is called to update the priority list of networks in the
1403  * configuration when a network is being added or removed. This is also called
1404  * if a priority for a network is changed.
1405  */
1406 static int wpa_config_update_prio_list(struct wpa_config *config)
1407 {
1408         struct wpa_ssid *ssid;
1409         int ret = 0;
1410
1411         os_free(config->pssid);
1412         config->pssid = NULL;
1413         config->num_prio = 0;
1414
1415         ssid = config->ssid;
1416         while (ssid) {
1417                 ssid->pnext = NULL;
1418                 if (wpa_config_add_prio_network(config, ssid) < 0)
1419                         ret = -1;
1420                 ssid = ssid->next;
1421         }
1422
1423         return ret;
1424 }
1425
1426
1427 #ifdef IEEE8021X_EAPOL
1428 static void eap_peer_config_free(struct eap_peer_config *eap)
1429 {
1430         os_free(eap->eap_methods);
1431         os_free(eap->identity);
1432         os_free(eap->anonymous_identity);
1433         os_free(eap->password);
1434         os_free(eap->ca_cert);
1435         os_free(eap->ca_path);
1436         os_free(eap->client_cert);
1437         os_free(eap->private_key);
1438         os_free(eap->private_key_passwd);
1439         os_free(eap->dh_file);
1440         os_free(eap->subject_match);
1441         os_free(eap->altsubject_match);
1442         os_free(eap->ca_cert2);
1443         os_free(eap->ca_path2);
1444         os_free(eap->client_cert2);
1445         os_free(eap->private_key2);
1446         os_free(eap->private_key2_passwd);
1447         os_free(eap->dh_file2);
1448         os_free(eap->subject_match2);
1449         os_free(eap->altsubject_match2);
1450         os_free(eap->phase1);
1451         os_free(eap->phase2);
1452         os_free(eap->pcsc);
1453         os_free(eap->pin);
1454         os_free(eap->engine_id);
1455         os_free(eap->key_id);
1456         os_free(eap->otp);
1457         os_free(eap->pending_req_otp);
1458         os_free(eap->pac_file);
1459         os_free(eap->new_password);
1460 }
1461 #endif /* IEEE8021X_EAPOL */
1462
1463
1464 /**
1465  * wpa_config_free_ssid - Free network/ssid configuration data
1466  * @ssid: Configuration data for the network
1467  *
1468  * This function frees all resources allocated for the network configuration
1469  * data.
1470  */
1471 void wpa_config_free_ssid(struct wpa_ssid *ssid)
1472 {
1473         os_free(ssid->ssid);
1474         os_free(ssid->passphrase);
1475 #ifdef IEEE8021X_EAPOL
1476         eap_peer_config_free(&ssid->eap);
1477 #endif /* IEEE8021X_EAPOL */
1478         os_free(ssid->id_str);
1479         os_free(ssid);
1480 }
1481
1482
1483 /**
1484  * wpa_config_free - Free configuration data
1485  * @config: Configuration data from wpa_config_read()
1486  *
1487  * This function frees all resources allocated for the configuration data by
1488  * wpa_config_read().
1489  */
1490 void wpa_config_free(struct wpa_config *config)
1491 {
1492 #ifndef CONFIG_NO_CONFIG_BLOBS
1493         struct wpa_config_blob *blob, *prevblob;
1494 #endif /* CONFIG_NO_CONFIG_BLOBS */
1495         struct wpa_ssid *ssid, *prev = NULL;
1496         ssid = config->ssid;
1497         while (ssid) {
1498                 prev = ssid;
1499                 ssid = ssid->next;
1500                 wpa_config_free_ssid(prev);
1501         }
1502
1503 #ifndef CONFIG_NO_CONFIG_BLOBS
1504         blob = config->blobs;
1505         prevblob = NULL;
1506         while (blob) {
1507                 prevblob = blob;
1508                 blob = blob->next;
1509                 wpa_config_free_blob(prevblob);
1510         }
1511 #endif /* CONFIG_NO_CONFIG_BLOBS */
1512
1513         os_free(config->ctrl_interface);
1514         os_free(config->ctrl_interface_group);
1515 #ifdef EAP_TLS_OPENSSL
1516         os_free(config->opensc_engine_path);
1517         os_free(config->pkcs11_engine_path);
1518         os_free(config->pkcs11_module_path);
1519 #endif /* EAP_TLS_OPENSSL */
1520         os_free(config->driver_param);
1521         os_free(config->pssid);
1522         os_free(config);
1523 }
1524
1525
1526 /**
1527  * wpa_config_get_network - Get configured network based on id
1528  * @config: Configuration data from wpa_config_read()
1529  * @id: Unique network id to search for
1530  * Returns: Network configuration or %NULL if not found
1531  */
1532 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1533 {
1534         struct wpa_ssid *ssid;
1535
1536         ssid = config->ssid;
1537         while (ssid) {
1538                 if (id == ssid->id)
1539                         break;
1540                 ssid = ssid->next;
1541         }
1542
1543         return ssid;
1544 }
1545
1546
1547 /**
1548  * wpa_config_add_network - Add a new network with empty configuration
1549  * @config: Configuration data from wpa_config_read()
1550  * Returns: The new network configuration or %NULL if operation failed
1551  */
1552 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1553 {
1554         int id;
1555         struct wpa_ssid *ssid, *last = NULL;
1556
1557         id = -1;
1558         ssid = config->ssid;
1559         while (ssid) {
1560                 if (ssid->id > id)
1561                         id = ssid->id;
1562                 last = ssid;
1563                 ssid = ssid->next;
1564         }
1565         id++;
1566
1567         ssid = os_zalloc(sizeof(*ssid));
1568         if (ssid == NULL)
1569                 return NULL;
1570         ssid->id = id;
1571         if (last)
1572                 last->next = ssid;
1573         else
1574                 config->ssid = ssid;
1575
1576         wpa_config_update_prio_list(config);
1577
1578         return ssid;
1579 }
1580
1581
1582 /**
1583  * wpa_config_remove_network - Remove a configured network based on id
1584  * @config: Configuration data from wpa_config_read()
1585  * @id: Unique network id to search for
1586  * Returns: 0 on success, or -1 if the network was not found
1587  */
1588 int wpa_config_remove_network(struct wpa_config *config, int id)
1589 {
1590         struct wpa_ssid *ssid, *prev = NULL;
1591
1592         ssid = config->ssid;
1593         while (ssid) {
1594                 if (id == ssid->id)
1595                         break;
1596                 prev = ssid;
1597                 ssid = ssid->next;
1598         }
1599
1600         if (ssid == NULL)
1601                 return -1;
1602
1603         if (prev)
1604                 prev->next = ssid->next;
1605         else
1606                 config->ssid = ssid->next;
1607
1608         wpa_config_update_prio_list(config);
1609         wpa_config_free_ssid(ssid);
1610         return 0;
1611 }
1612
1613
1614 /**
1615  * wpa_config_set_network_defaults - Set network default values
1616  * @ssid: Pointer to network configuration data
1617  */
1618 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
1619 {
1620         ssid->proto = DEFAULT_PROTO;
1621         ssid->pairwise_cipher = DEFAULT_PAIRWISE;
1622         ssid->group_cipher = DEFAULT_GROUP;
1623         ssid->key_mgmt = DEFAULT_KEY_MGMT;
1624 #ifdef IEEE8021X_EAPOL
1625         ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
1626         ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
1627         ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
1628 #endif /* IEEE8021X_EAPOL */
1629 }
1630
1631
1632 /**
1633  * wpa_config_set - Set a variable in network configuration
1634  * @ssid: Pointer to network configuration data
1635  * @var: Variable name, e.g., "ssid"
1636  * @value: Variable value
1637  * @line: Line number in configuration file or 0 if not used
1638  * Returns: 0 on success, -1 on failure
1639  *
1640  * This function can be used to set network configuration variables based on
1641  * both the configuration file and management interface input. The value
1642  * parameter must be in the same format as the text-based configuration file is
1643  * using. For example, strings are using double quotation marks.
1644  */
1645 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
1646                    int line)
1647 {
1648         size_t i;
1649         int ret = 0;
1650
1651         if (ssid == NULL || var == NULL || value == NULL)
1652                 return -1;
1653
1654         for (i = 0; i < NUM_SSID_FIELDS; i++) {
1655                 const struct parse_data *field = &ssid_fields[i];
1656                 if (os_strcmp(var, field->name) != 0)
1657                         continue;
1658
1659                 if (field->parser(field, ssid, line, value)) {
1660                         if (line) {
1661                                 wpa_printf(MSG_ERROR, "Line %d: failed to "
1662                                            "parse %s '%s'.", line, var, value);
1663                         }
1664                         ret = -1;
1665                 }
1666                 break;
1667         }
1668         if (i == NUM_SSID_FIELDS) {
1669                 if (line) {
1670                         wpa_printf(MSG_ERROR, "Line %d: unknown network field "
1671                                    "'%s'.", line, var);
1672                 }
1673                 ret = -1;
1674         }
1675
1676         return ret;
1677 }
1678
1679
1680 #ifndef NO_CONFIG_WRITE
1681 /**
1682  * wpa_config_get - Get a variable in network configuration
1683  * @ssid: Pointer to network configuration data
1684  * @var: Variable name, e.g., "ssid"
1685  * Returns: Value of the variable or %NULL on failure
1686  *
1687  * This function can be used to get network configuration variables. The
1688  * returned value is a copy of the configuration variable in text format, i.e,.
1689  * the same format that the text-based configuration file and wpa_config_set()
1690  * are using for the value. The caller is responsible for freeing the returned
1691  * value.
1692  */
1693 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
1694 {
1695         size_t i;
1696
1697         if (ssid == NULL || var == NULL)
1698                 return NULL;
1699
1700         for (i = 0; i < NUM_SSID_FIELDS; i++) {
1701                 const struct parse_data *field = &ssid_fields[i];
1702                 if (os_strcmp(var, field->name) == 0)
1703                         return field->writer(field, ssid);
1704         }
1705
1706         return NULL;
1707 }
1708
1709
1710 /**
1711  * wpa_config_get_no_key - Get a variable in network configuration (no keys)
1712  * @ssid: Pointer to network configuration data
1713  * @var: Variable name, e.g., "ssid"
1714  * Returns: Value of the variable or %NULL on failure
1715  *
1716  * This function can be used to get network configuration variable like
1717  * wpa_config_get(). The only difference is that this functions does not expose
1718  * key/password material from the configuration. In case a key/password field
1719  * is requested, the returned value is an empty string or %NULL if the variable
1720  * is not set or "*" if the variable is set (regardless of its value). The
1721  * returned value is a copy of the configuration variable in text format, i.e,.
1722  * the same format that the text-based configuration file and wpa_config_set()
1723  * are using for the value. The caller is responsible for freeing the returned
1724  * value.
1725  */
1726 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
1727 {
1728         size_t i;
1729
1730         if (ssid == NULL || var == NULL)
1731                 return NULL;
1732
1733         for (i = 0; i < NUM_SSID_FIELDS; i++) {
1734                 const struct parse_data *field = &ssid_fields[i];
1735                 if (os_strcmp(var, field->name) == 0) {
1736                         char *res = field->writer(field, ssid);
1737                         if (field->key_data) {
1738                                 if (res && res[0]) {
1739                                         wpa_printf(MSG_DEBUG, "Do not allow "
1740                                                    "key_data field to be "
1741                                                    "exposed");
1742                                         os_free(res);
1743                                         return os_strdup("*");
1744                                 }
1745
1746                                 os_free(res);
1747                                 return NULL;
1748                         }
1749                         return res;
1750                 }
1751         }
1752
1753         return NULL;
1754 }
1755 #endif /* NO_CONFIG_WRITE */
1756
1757
1758 /**
1759  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
1760  * @ssid: Pointer to network configuration data
1761  *
1762  * This function must be called to update WPA PSK when either SSID or the
1763  * passphrase has changed for the network configuration.
1764  */
1765 void wpa_config_update_psk(struct wpa_ssid *ssid)
1766 {
1767 #ifndef CONFIG_NO_PBKDF2
1768         pbkdf2_sha1(ssid->passphrase,
1769                     (char *) ssid->ssid, ssid->ssid_len, 4096,
1770                     ssid->psk, PMK_LEN);
1771         wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1772                         ssid->psk, PMK_LEN);
1773         ssid->psk_set = 1;
1774 #endif /* CONFIG_NO_PBKDF2 */
1775 }
1776
1777
1778 #ifndef CONFIG_NO_CONFIG_BLOBS
1779 /**
1780  * wpa_config_get_blob - Get a named configuration blob
1781  * @config: Configuration data from wpa_config_read()
1782  * @name: Name of the blob
1783  * Returns: Pointer to blob data or %NULL if not found
1784  */
1785 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
1786                                                    const char *name)
1787 {
1788         struct wpa_config_blob *blob = config->blobs;
1789
1790         while (blob) {
1791                 if (os_strcmp(blob->name, name) == 0)
1792                         return blob;
1793                 blob = blob->next;
1794         }
1795         return NULL;
1796 }
1797
1798
1799 /**
1800  * wpa_config_set_blob - Set or add a named configuration blob
1801  * @config: Configuration data from wpa_config_read()
1802  * @blob: New value for the blob
1803  *
1804  * Adds a new configuration blob or replaces the current value of an existing
1805  * blob.
1806  */
1807 void wpa_config_set_blob(struct wpa_config *config,
1808                          struct wpa_config_blob *blob)
1809 {
1810         wpa_config_remove_blob(config, blob->name);
1811         blob->next = config->blobs;
1812         config->blobs = blob;
1813 }
1814
1815
1816 /**
1817  * wpa_config_free_blob - Free blob data
1818  * @blob: Pointer to blob to be freed
1819  */
1820 void wpa_config_free_blob(struct wpa_config_blob *blob)
1821 {
1822         if (blob) {
1823                 os_free(blob->name);
1824                 os_free(blob->data);
1825                 os_free(blob);
1826         }
1827 }
1828
1829
1830 /**
1831  * wpa_config_remove_blob - Remove a named configuration blob
1832  * @config: Configuration data from wpa_config_read()
1833  * @name: Name of the blob to remove
1834  * Returns: 0 if blob was removed or -1 if blob was not found
1835  */
1836 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
1837 {
1838         struct wpa_config_blob *pos = config->blobs, *prev = NULL;
1839
1840         while (pos) {
1841                 if (os_strcmp(pos->name, name) == 0) {
1842                         if (prev)
1843                                 prev->next = pos->next;
1844                         else
1845                                 config->blobs = pos->next;
1846                         wpa_config_free_blob(pos);
1847                         return 0;
1848                 }
1849                 prev = pos;
1850                 pos = pos->next;
1851         }
1852
1853         return -1;
1854 }
1855 #endif /* CONFIG_NO_CONFIG_BLOBS */
1856
1857
1858 /**
1859  * wpa_config_alloc_empty - Allocate an empty configuration
1860  * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
1861  * socket
1862  * @driver_param: Driver parameters
1863  * Returns: Pointer to allocated configuration data or %NULL on failure
1864  */
1865 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
1866                                            const char *driver_param)
1867 {
1868         struct wpa_config *config;
1869
1870         config = os_zalloc(sizeof(*config));
1871         if (config == NULL)
1872                 return NULL;
1873         config->eapol_version = DEFAULT_EAPOL_VERSION;
1874         config->ap_scan = DEFAULT_AP_SCAN;
1875         config->fast_reauth = DEFAULT_FAST_REAUTH;
1876
1877         if (ctrl_interface)
1878                 config->ctrl_interface = os_strdup(ctrl_interface);
1879         if (driver_param)
1880                 config->driver_param = os_strdup(driver_param);
1881
1882         return config;
1883 }
1884
1885
1886 #ifndef CONFIG_NO_STDOUT_DEBUG
1887 /**
1888  * wpa_config_debug_dump_networks - Debug dump of configured networks
1889  * @config: Configuration data from wpa_config_read()
1890  */
1891 void wpa_config_debug_dump_networks(struct wpa_config *config)
1892 {
1893         int prio;
1894         struct wpa_ssid *ssid;
1895
1896         for (prio = 0; prio < config->num_prio; prio++) {
1897                 ssid = config->pssid[prio];
1898                 wpa_printf(MSG_DEBUG, "Priority group %d",
1899                            ssid->priority);
1900                 while (ssid) {
1901                         wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
1902                                    ssid->id,
1903                                    wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1904                         ssid = ssid->pnext;
1905                 }
1906         }
1907 }
1908 #endif /* CONFIG_NO_STDOUT_DEBUG */