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