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