Get rid of compiler warning in no-CONFIG_CTRL_IFACE builds
[mech_eap.git] / wpa_supplicant / config.c
1 /*
2  * WPA Supplicant / Configuration parser and common functions
3  * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "utils/uuid.h"
13 #include "crypto/sha1.h"
14 #include "rsn_supp/wpa.h"
15 #include "eap_peer/eap.h"
16 #include "p2p/p2p.h"
17 #include "config.h"
18
19
20 #if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE)
21 #define NO_CONFIG_WRITE
22 #endif
23
24 /*
25  * Structure for network configuration parsing. This data is used to implement
26  * a generic parser for each network block variable. The table of configuration
27  * variables is defined below in this file (ssid_fields[]).
28  */
29 struct parse_data {
30         /* Configuration variable name */
31         char *name;
32
33         /* Parser function for this variable */
34         int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
35                       int line, const char *value);
36
37 #ifndef NO_CONFIG_WRITE
38         /* Writer function (i.e., to get the variable in text format from
39          * internal presentation). */
40         char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
41 #endif /* NO_CONFIG_WRITE */
42
43         /* Variable specific parameters for the parser. */
44         void *param1, *param2, *param3, *param4;
45
46         /* 0 = this variable can be included in debug output and ctrl_iface
47          * 1 = this variable contains key/private data and it must not be
48          *     included in debug output unless explicitly requested. In
49          *     addition, this variable will not be readable through the
50          *     ctrl_iface.
51          */
52         int key_data;
53 };
54
55
56 static int wpa_config_parse_str(const struct parse_data *data,
57                                 struct wpa_ssid *ssid,
58                                 int line, const char *value)
59 {
60         size_t res_len, *dst_len;
61         char **dst, *tmp;
62
63         if (os_strcmp(value, "NULL") == 0) {
64                 wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
65                            data->name);
66                 tmp = NULL;
67                 res_len = 0;
68                 goto set;
69         }
70
71         tmp = wpa_config_parse_string(value, &res_len);
72         if (tmp == NULL) {
73                 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
74                            line, data->name,
75                            data->key_data ? "[KEY DATA REMOVED]" : value);
76                 return -1;
77         }
78
79         if (data->key_data) {
80                 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
81                                       (u8 *) tmp, res_len);
82         } else {
83                 wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
84                                   (u8 *) tmp, res_len);
85         }
86
87         if (data->param3 && res_len < (size_t) data->param3) {
88                 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
89                            "min_len=%ld)", line, data->name,
90                            (unsigned long) res_len, (long) data->param3);
91                 os_free(tmp);
92                 return -1;
93         }
94
95         if (data->param4 && res_len > (size_t) data->param4) {
96                 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
97                            "max_len=%ld)", line, data->name,
98                            (unsigned long) res_len, (long) data->param4);
99                 os_free(tmp);
100                 return -1;
101         }
102
103 set:
104         dst = (char **) (((u8 *) ssid) + (long) data->param1);
105         dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
106         os_free(*dst);
107         *dst = tmp;
108         if (data->param2)
109                 *dst_len = res_len;
110
111         return 0;
112 }
113
114
115 #ifndef NO_CONFIG_WRITE
116 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
117 {
118         char *buf;
119
120         buf = os_malloc(len + 3);
121         if (buf == NULL)
122                 return NULL;
123         buf[0] = '"';
124         os_memcpy(buf + 1, value, len);
125         buf[len + 1] = '"';
126         buf[len + 2] = '\0';
127
128         return buf;
129 }
130
131
132 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
133 {
134         char *buf;
135
136         buf = os_zalloc(2 * len + 1);
137         if (buf == NULL)
138                 return NULL;
139         wpa_snprintf_hex(buf, 2 * len + 1, value, len);
140
141         return buf;
142 }
143
144
145 static char * wpa_config_write_string(const u8 *value, size_t len)
146 {
147         if (value == NULL)
148                 return NULL;
149
150         if (is_hex(value, len))
151                 return wpa_config_write_string_hex(value, len);
152         else
153                 return wpa_config_write_string_ascii(value, len);
154 }
155
156
157 static char * wpa_config_write_str(const struct parse_data *data,
158                                    struct wpa_ssid *ssid)
159 {
160         size_t len;
161         char **src;
162
163         src = (char **) (((u8 *) ssid) + (long) data->param1);
164         if (*src == NULL)
165                 return NULL;
166
167         if (data->param2)
168                 len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
169         else
170                 len = os_strlen(*src);
171
172         return wpa_config_write_string((const u8 *) *src, len);
173 }
174 #endif /* NO_CONFIG_WRITE */
175
176
177 static int wpa_config_parse_int(const struct parse_data *data,
178                                 struct wpa_ssid *ssid,
179                                 int line, const char *value)
180 {
181         int val, *dst;
182         char *end;
183
184         dst = (int *) (((u8 *) ssid) + (long) data->param1);
185         val = strtol(value, &end, 0);
186         if (*end) {
187                 wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"",
188                            line, value);
189                 return -1;
190         }
191         *dst = val;
192         wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
193
194         if (data->param3 && *dst < (long) data->param3) {
195                 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
196                            "min_value=%ld)", line, data->name, *dst,
197                            (long) data->param3);
198                 *dst = (long) data->param3;
199                 return -1;
200         }
201
202         if (data->param4 && *dst > (long) data->param4) {
203                 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
204                            "max_value=%ld)", line, data->name, *dst,
205                            (long) data->param4);
206                 *dst = (long) data->param4;
207                 return -1;
208         }
209
210         return 0;
211 }
212
213
214 #ifndef NO_CONFIG_WRITE
215 static char * wpa_config_write_int(const struct parse_data *data,
216                                    struct wpa_ssid *ssid)
217 {
218         int *src, res;
219         char *value;
220
221         src = (int *) (((u8 *) ssid) + (long) data->param1);
222
223         value = os_malloc(20);
224         if (value == NULL)
225                 return NULL;
226         res = os_snprintf(value, 20, "%d", *src);
227         if (res < 0 || res >= 20) {
228                 os_free(value);
229                 return NULL;
230         }
231         value[20 - 1] = '\0';
232         return value;
233 }
234 #endif /* NO_CONFIG_WRITE */
235
236
237 static int wpa_config_parse_bssid(const struct parse_data *data,
238                                   struct wpa_ssid *ssid, int line,
239                                   const char *value)
240 {
241         if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
242             os_strcmp(value, "any") == 0) {
243                 ssid->bssid_set = 0;
244                 wpa_printf(MSG_MSGDUMP, "BSSID any");
245                 return 0;
246         }
247         if (hwaddr_aton(value, ssid->bssid)) {
248                 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
249                            line, value);
250                 return -1;
251         }
252         ssid->bssid_set = 1;
253         wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
254         return 0;
255 }
256
257
258 #ifndef NO_CONFIG_WRITE
259 static char * wpa_config_write_bssid(const struct parse_data *data,
260                                      struct wpa_ssid *ssid)
261 {
262         char *value;
263         int res;
264
265         if (!ssid->bssid_set)
266                 return NULL;
267
268         value = os_malloc(20);
269         if (value == NULL)
270                 return NULL;
271         res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
272         if (res < 0 || res >= 20) {
273                 os_free(value);
274                 return NULL;
275         }
276         value[20 - 1] = '\0';
277         return value;
278 }
279 #endif /* NO_CONFIG_WRITE */
280
281
282 static int wpa_config_parse_psk(const struct parse_data *data,
283                                 struct wpa_ssid *ssid, int line,
284                                 const char *value)
285 {
286 #ifdef CONFIG_EXT_PASSWORD
287         if (os_strncmp(value, "ext:", 4) == 0) {
288                 os_free(ssid->passphrase);
289                 ssid->passphrase = NULL;
290                 ssid->psk_set = 0;
291                 os_free(ssid->ext_psk);
292                 ssid->ext_psk = os_strdup(value + 4);
293                 if (ssid->ext_psk == NULL)
294                         return -1;
295                 wpa_printf(MSG_DEBUG, "PSK: External password '%s'",
296                            ssid->ext_psk);
297                 return 0;
298         }
299 #endif /* CONFIG_EXT_PASSWORD */
300
301         if (*value == '"') {
302 #ifndef CONFIG_NO_PBKDF2
303                 const char *pos;
304                 size_t len;
305
306                 value++;
307                 pos = os_strrchr(value, '"');
308                 if (pos)
309                         len = pos - value;
310                 else
311                         len = os_strlen(value);
312                 if (len < 8 || len > 63) {
313                         wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
314                                    "length %lu (expected: 8..63) '%s'.",
315                                    line, (unsigned long) len, value);
316                         return -1;
317                 }
318                 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
319                                       (u8 *) value, len);
320                 if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
321                     os_memcmp(ssid->passphrase, value, len) == 0)
322                         return 0;
323                 ssid->psk_set = 0;
324                 os_free(ssid->passphrase);
325                 ssid->passphrase = dup_binstr(value, len);
326                 if (ssid->passphrase == NULL)
327                         return -1;
328                 return 0;
329 #else /* CONFIG_NO_PBKDF2 */
330                 wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
331                            "supported.", line);
332                 return -1;
333 #endif /* CONFIG_NO_PBKDF2 */
334         }
335
336         if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
337             value[PMK_LEN * 2] != '\0') {
338                 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
339                            line, value);
340                 return -1;
341         }
342
343         os_free(ssid->passphrase);
344         ssid->passphrase = NULL;
345
346         ssid->psk_set = 1;
347         wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
348         return 0;
349 }
350
351
352 #ifndef NO_CONFIG_WRITE
353 static char * wpa_config_write_psk(const struct parse_data *data,
354                                    struct wpa_ssid *ssid)
355 {
356 #ifdef CONFIG_EXT_PASSWORD
357         if (ssid->ext_psk) {
358                 size_t len = 4 + os_strlen(ssid->ext_psk) + 1;
359                 char *buf = os_malloc(len);
360                 if (buf == NULL)
361                         return NULL;
362                 os_snprintf(buf, len, "ext:%s", ssid->ext_psk);
363                 return buf;
364         }
365 #endif /* CONFIG_EXT_PASSWORD */
366
367         if (ssid->passphrase)
368                 return wpa_config_write_string_ascii(
369                         (const u8 *) ssid->passphrase,
370                         os_strlen(ssid->passphrase));
371
372         if (ssid->psk_set)
373                 return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
374
375         return NULL;
376 }
377 #endif /* NO_CONFIG_WRITE */
378
379
380 static int wpa_config_parse_proto(const struct parse_data *data,
381                                   struct wpa_ssid *ssid, int line,
382                                   const char *value)
383 {
384         int val = 0, last, errors = 0;
385         char *start, *end, *buf;
386
387         buf = os_strdup(value);
388         if (buf == NULL)
389                 return -1;
390         start = buf;
391
392         while (*start != '\0') {
393                 while (*start == ' ' || *start == '\t')
394                         start++;
395                 if (*start == '\0')
396                         break;
397                 end = start;
398                 while (*end != ' ' && *end != '\t' && *end != '\0')
399                         end++;
400                 last = *end == '\0';
401                 *end = '\0';
402                 if (os_strcmp(start, "WPA") == 0)
403                         val |= WPA_PROTO_WPA;
404                 else if (os_strcmp(start, "RSN") == 0 ||
405                          os_strcmp(start, "WPA2") == 0)
406                         val |= WPA_PROTO_RSN;
407                 else {
408                         wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
409                                    line, start);
410                         errors++;
411                 }
412
413                 if (last)
414                         break;
415                 start = end + 1;
416         }
417         os_free(buf);
418
419         if (val == 0) {
420                 wpa_printf(MSG_ERROR,
421                            "Line %d: no proto values configured.", line);
422                 errors++;
423         }
424
425         wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
426         ssid->proto = val;
427         return errors ? -1 : 0;
428 }
429
430
431 #ifndef NO_CONFIG_WRITE
432 static char * wpa_config_write_proto(const struct parse_data *data,
433                                      struct wpa_ssid *ssid)
434 {
435         int first = 1, ret;
436         char *buf, *pos, *end;
437
438         pos = buf = os_zalloc(10);
439         if (buf == NULL)
440                 return NULL;
441         end = buf + 10;
442
443         if (ssid->proto & WPA_PROTO_WPA) {
444                 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
445                 if (ret < 0 || ret >= end - pos)
446                         return buf;
447                 pos += ret;
448                 first = 0;
449         }
450
451         if (ssid->proto & WPA_PROTO_RSN) {
452                 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
453                 if (ret < 0 || ret >= end - pos)
454                         return buf;
455                 pos += ret;
456                 first = 0;
457         }
458
459         return buf;
460 }
461 #endif /* NO_CONFIG_WRITE */
462
463
464 static int wpa_config_parse_key_mgmt(const struct parse_data *data,
465                                      struct wpa_ssid *ssid, int line,
466                                      const char *value)
467 {
468         int val = 0, last, errors = 0;
469         char *start, *end, *buf;
470
471         buf = os_strdup(value);
472         if (buf == NULL)
473                 return -1;
474         start = buf;
475
476         while (*start != '\0') {
477                 while (*start == ' ' || *start == '\t')
478                         start++;
479                 if (*start == '\0')
480                         break;
481                 end = start;
482                 while (*end != ' ' && *end != '\t' && *end != '\0')
483                         end++;
484                 last = *end == '\0';
485                 *end = '\0';
486                 if (os_strcmp(start, "WPA-PSK") == 0)
487                         val |= WPA_KEY_MGMT_PSK;
488                 else if (os_strcmp(start, "WPA-EAP") == 0)
489                         val |= WPA_KEY_MGMT_IEEE8021X;
490                 else if (os_strcmp(start, "IEEE8021X") == 0)
491                         val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
492                 else if (os_strcmp(start, "NONE") == 0)
493                         val |= WPA_KEY_MGMT_NONE;
494                 else if (os_strcmp(start, "WPA-NONE") == 0)
495                         val |= WPA_KEY_MGMT_WPA_NONE;
496 #ifdef CONFIG_IEEE80211R
497                 else if (os_strcmp(start, "FT-PSK") == 0)
498                         val |= WPA_KEY_MGMT_FT_PSK;
499                 else if (os_strcmp(start, "FT-EAP") == 0)
500                         val |= WPA_KEY_MGMT_FT_IEEE8021X;
501 #endif /* CONFIG_IEEE80211R */
502 #ifdef CONFIG_IEEE80211W
503                 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
504                         val |= WPA_KEY_MGMT_PSK_SHA256;
505                 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
506                         val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
507 #endif /* CONFIG_IEEE80211W */
508 #ifdef CONFIG_WPS
509                 else if (os_strcmp(start, "WPS") == 0)
510                         val |= WPA_KEY_MGMT_WPS;
511 #endif /* CONFIG_WPS */
512 #ifdef CONFIG_SAE
513                 else if (os_strcmp(start, "SAE") == 0)
514                         val |= WPA_KEY_MGMT_SAE;
515                 else if (os_strcmp(start, "FT-SAE") == 0)
516                         val |= WPA_KEY_MGMT_FT_SAE;
517 #endif /* CONFIG_SAE */
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 #ifdef CONFIG_WPS
625         if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
626                 pos += os_snprintf(pos, end - pos, "%sWPS",
627                                    pos == buf ? "" : " ");
628 #endif /* CONFIG_WPS */
629
630         return buf;
631 }
632 #endif /* NO_CONFIG_WRITE */
633
634
635 static int wpa_config_parse_cipher(int line, const char *value)
636 {
637         int val = wpa_parse_cipher(value);
638         if (val < 0) {
639                 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
640                            line, value);
641                 return -1;
642         }
643         if (val == 0) {
644                 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
645                            line);
646                 return -1;
647         }
648         return val;
649 }
650
651
652 #ifndef NO_CONFIG_WRITE
653 static char * wpa_config_write_cipher(int cipher)
654 {
655         char *buf = os_zalloc(50);
656         if (buf == NULL)
657                 return NULL;
658
659         if (wpa_write_ciphers(buf, buf + 50, cipher, " ") < 0) {
660                 os_free(buf);
661                 return NULL;
662         }
663
664         return buf;
665 }
666 #endif /* NO_CONFIG_WRITE */
667
668
669 static int wpa_config_parse_pairwise(const struct parse_data *data,
670                                      struct wpa_ssid *ssid, int line,
671                                      const char *value)
672 {
673         int val;
674         val = wpa_config_parse_cipher(line, value);
675         if (val == -1)
676                 return -1;
677         if (val & ~WPA_ALLOWED_PAIRWISE_CIPHERS) {
678                 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
679                            "(0x%x).", line, val);
680                 return -1;
681         }
682
683         wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
684         ssid->pairwise_cipher = val;
685         return 0;
686 }
687
688
689 #ifndef NO_CONFIG_WRITE
690 static char * wpa_config_write_pairwise(const struct parse_data *data,
691                                         struct wpa_ssid *ssid)
692 {
693         return wpa_config_write_cipher(ssid->pairwise_cipher);
694 }
695 #endif /* NO_CONFIG_WRITE */
696
697
698 static int wpa_config_parse_group(const struct parse_data *data,
699                                   struct wpa_ssid *ssid, int line,
700                                   const char *value)
701 {
702         int val;
703         val = wpa_config_parse_cipher(line, value);
704         if (val == -1)
705                 return -1;
706         if (val & ~WPA_ALLOWED_GROUP_CIPHERS) {
707                 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
708                            "(0x%x).", line, val);
709                 return -1;
710         }
711
712         wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
713         ssid->group_cipher = val;
714         return 0;
715 }
716
717
718 #ifndef NO_CONFIG_WRITE
719 static char * wpa_config_write_group(const struct parse_data *data,
720                                      struct wpa_ssid *ssid)
721 {
722         return wpa_config_write_cipher(ssid->group_cipher);
723 }
724 #endif /* NO_CONFIG_WRITE */
725
726
727 static int wpa_config_parse_auth_alg(const struct parse_data *data,
728                                      struct wpa_ssid *ssid, int line,
729                                      const char *value)
730 {
731         int val = 0, last, errors = 0;
732         char *start, *end, *buf;
733
734         buf = os_strdup(value);
735         if (buf == NULL)
736                 return -1;
737         start = buf;
738
739         while (*start != '\0') {
740                 while (*start == ' ' || *start == '\t')
741                         start++;
742                 if (*start == '\0')
743                         break;
744                 end = start;
745                 while (*end != ' ' && *end != '\t' && *end != '\0')
746                         end++;
747                 last = *end == '\0';
748                 *end = '\0';
749                 if (os_strcmp(start, "OPEN") == 0)
750                         val |= WPA_AUTH_ALG_OPEN;
751                 else if (os_strcmp(start, "SHARED") == 0)
752                         val |= WPA_AUTH_ALG_SHARED;
753                 else if (os_strcmp(start, "LEAP") == 0)
754                         val |= WPA_AUTH_ALG_LEAP;
755                 else {
756                         wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
757                                    line, start);
758                         errors++;
759                 }
760
761                 if (last)
762                         break;
763                 start = end + 1;
764         }
765         os_free(buf);
766
767         if (val == 0) {
768                 wpa_printf(MSG_ERROR,
769                            "Line %d: no auth_alg values configured.", line);
770                 errors++;
771         }
772
773         wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
774         ssid->auth_alg = val;
775         return errors ? -1 : 0;
776 }
777
778
779 #ifndef NO_CONFIG_WRITE
780 static char * wpa_config_write_auth_alg(const struct parse_data *data,
781                                         struct wpa_ssid *ssid)
782 {
783         char *buf, *pos, *end;
784         int ret;
785
786         pos = buf = os_zalloc(30);
787         if (buf == NULL)
788                 return NULL;
789         end = buf + 30;
790
791         if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
792                 ret = os_snprintf(pos, end - pos, "%sOPEN",
793                                   pos == buf ? "" : " ");
794                 if (ret < 0 || ret >= end - pos) {
795                         end[-1] = '\0';
796                         return buf;
797                 }
798                 pos += ret;
799         }
800
801         if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
802                 ret = os_snprintf(pos, end - pos, "%sSHARED",
803                                   pos == buf ? "" : " ");
804                 if (ret < 0 || ret >= end - pos) {
805                         end[-1] = '\0';
806                         return buf;
807                 }
808                 pos += ret;
809         }
810
811         if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
812                 ret = os_snprintf(pos, end - pos, "%sLEAP",
813                                   pos == buf ? "" : " ");
814                 if (ret < 0 || ret >= end - pos) {
815                         end[-1] = '\0';
816                         return buf;
817                 }
818                 pos += ret;
819         }
820
821         return buf;
822 }
823 #endif /* NO_CONFIG_WRITE */
824
825
826 static int * wpa_config_parse_int_array(const char *value)
827 {
828         int *freqs;
829         size_t used, len;
830         const char *pos;
831
832         used = 0;
833         len = 10;
834         freqs = os_calloc(len + 1, sizeof(int));
835         if (freqs == NULL)
836                 return NULL;
837
838         pos = value;
839         while (pos) {
840                 while (*pos == ' ')
841                         pos++;
842                 if (used == len) {
843                         int *n;
844                         size_t i;
845                         n = os_realloc_array(freqs, len * 2 + 1, sizeof(int));
846                         if (n == NULL) {
847                                 os_free(freqs);
848                                 return NULL;
849                         }
850                         for (i = len; i <= len * 2; i++)
851                                 n[i] = 0;
852                         freqs = n;
853                         len *= 2;
854                 }
855
856                 freqs[used] = atoi(pos);
857                 if (freqs[used] == 0)
858                         break;
859                 used++;
860                 pos = os_strchr(pos + 1, ' ');
861         }
862
863         return freqs;
864 }
865
866
867 static int wpa_config_parse_scan_freq(const struct parse_data *data,
868                                       struct wpa_ssid *ssid, int line,
869                                       const char *value)
870 {
871         int *freqs;
872
873         freqs = wpa_config_parse_int_array(value);
874         if (freqs == NULL)
875                 return -1;
876         if (freqs[0] == 0) {
877                 os_free(freqs);
878                 freqs = NULL;
879         }
880         os_free(ssid->scan_freq);
881         ssid->scan_freq = freqs;
882
883         return 0;
884 }
885
886
887 static int wpa_config_parse_freq_list(const struct parse_data *data,
888                                       struct wpa_ssid *ssid, int line,
889                                       const char *value)
890 {
891         int *freqs;
892
893         freqs = wpa_config_parse_int_array(value);
894         if (freqs == NULL)
895                 return -1;
896         if (freqs[0] == 0) {
897                 os_free(freqs);
898                 freqs = NULL;
899         }
900         os_free(ssid->freq_list);
901         ssid->freq_list = freqs;
902
903         return 0;
904 }
905
906
907 #ifndef NO_CONFIG_WRITE
908 static char * wpa_config_write_freqs(const struct parse_data *data,
909                                      const int *freqs)
910 {
911         char *buf, *pos, *end;
912         int i, ret;
913         size_t count;
914
915         if (freqs == NULL)
916                 return NULL;
917
918         count = 0;
919         for (i = 0; freqs[i]; i++)
920                 count++;
921
922         pos = buf = os_zalloc(10 * count + 1);
923         if (buf == NULL)
924                 return NULL;
925         end = buf + 10 * count + 1;
926
927         for (i = 0; freqs[i]; i++) {
928                 ret = os_snprintf(pos, end - pos, "%s%u",
929                                   i == 0 ? "" : " ", freqs[i]);
930                 if (ret < 0 || ret >= end - pos) {
931                         end[-1] = '\0';
932                         return buf;
933                 }
934                 pos += ret;
935         }
936
937         return buf;
938 }
939
940
941 static char * wpa_config_write_scan_freq(const struct parse_data *data,
942                                          struct wpa_ssid *ssid)
943 {
944         return wpa_config_write_freqs(data, ssid->scan_freq);
945 }
946
947
948 static char * wpa_config_write_freq_list(const struct parse_data *data,
949                                          struct wpa_ssid *ssid)
950 {
951         return wpa_config_write_freqs(data, ssid->freq_list);
952 }
953 #endif /* NO_CONFIG_WRITE */
954
955
956 #ifdef IEEE8021X_EAPOL
957 static int wpa_config_parse_eap(const struct parse_data *data,
958                                 struct wpa_ssid *ssid, int line,
959                                 const char *value)
960 {
961         int last, errors = 0;
962         char *start, *end, *buf;
963         struct eap_method_type *methods = NULL, *tmp;
964         size_t num_methods = 0;
965
966         buf = os_strdup(value);
967         if (buf == NULL)
968                 return -1;
969         start = buf;
970
971         while (*start != '\0') {
972                 while (*start == ' ' || *start == '\t')
973                         start++;
974                 if (*start == '\0')
975                         break;
976                 end = start;
977                 while (*end != ' ' && *end != '\t' && *end != '\0')
978                         end++;
979                 last = *end == '\0';
980                 *end = '\0';
981                 tmp = methods;
982                 methods = os_realloc_array(methods, num_methods + 1,
983                                            sizeof(*methods));
984                 if (methods == NULL) {
985                         os_free(tmp);
986                         os_free(buf);
987                         return -1;
988                 }
989                 methods[num_methods].method = eap_peer_get_type(
990                         start, &methods[num_methods].vendor);
991                 if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
992                     methods[num_methods].method == EAP_TYPE_NONE) {
993                         wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
994                                    "'%s'", line, start);
995                         wpa_printf(MSG_ERROR, "You may need to add support for"
996                                    " this EAP method during wpa_supplicant\n"
997                                    "build time configuration.\n"
998                                    "See README for more information.");
999                         errors++;
1000                 } else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
1001                            methods[num_methods].method == EAP_TYPE_LEAP)
1002                         ssid->leap++;
1003                 else
1004                         ssid->non_leap++;
1005                 num_methods++;
1006                 if (last)
1007                         break;
1008                 start = end + 1;
1009         }
1010         os_free(buf);
1011
1012         tmp = methods;
1013         methods = os_realloc_array(methods, num_methods + 1, sizeof(*methods));
1014         if (methods == NULL) {
1015                 os_free(tmp);
1016                 return -1;
1017         }
1018         methods[num_methods].vendor = EAP_VENDOR_IETF;
1019         methods[num_methods].method = EAP_TYPE_NONE;
1020         num_methods++;
1021
1022         wpa_hexdump(MSG_MSGDUMP, "eap methods",
1023                     (u8 *) methods, num_methods * sizeof(*methods));
1024         os_free(ssid->eap.eap_methods);
1025         ssid->eap.eap_methods = methods;
1026         return errors ? -1 : 0;
1027 }
1028
1029
1030 static char * wpa_config_write_eap(const struct parse_data *data,
1031                                    struct wpa_ssid *ssid)
1032 {
1033         int i, ret;
1034         char *buf, *pos, *end;
1035         const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
1036         const char *name;
1037
1038         if (eap_methods == NULL)
1039                 return NULL;
1040
1041         pos = buf = os_zalloc(100);
1042         if (buf == NULL)
1043                 return NULL;
1044         end = buf + 100;
1045
1046         for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
1047                      eap_methods[i].method != EAP_TYPE_NONE; i++) {
1048                 name = eap_get_name(eap_methods[i].vendor,
1049                                     eap_methods[i].method);
1050                 if (name) {
1051                         ret = os_snprintf(pos, end - pos, "%s%s",
1052                                           pos == buf ? "" : " ", name);
1053                         if (ret < 0 || ret >= end - pos)
1054                                 break;
1055                         pos += ret;
1056                 }
1057         }
1058
1059         end[-1] = '\0';
1060
1061         return buf;
1062 }
1063
1064
1065 static int wpa_config_parse_password(const struct parse_data *data,
1066                                      struct wpa_ssid *ssid, int line,
1067                                      const char *value)
1068 {
1069         u8 *hash;
1070
1071         if (os_strcmp(value, "NULL") == 0) {
1072                 wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
1073                 os_free(ssid->eap.password);
1074                 ssid->eap.password = NULL;
1075                 ssid->eap.password_len = 0;
1076                 return 0;
1077         }
1078
1079 #ifdef CONFIG_EXT_PASSWORD
1080         if (os_strncmp(value, "ext:", 4) == 0) {
1081                 char *name = os_strdup(value + 4);
1082                 if (name == NULL)
1083                         return -1;
1084                 os_free(ssid->eap.password);
1085                 ssid->eap.password = (u8 *) name;
1086                 ssid->eap.password_len = os_strlen(name);
1087                 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1088                 ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_PASSWORD;
1089                 return 0;
1090         }
1091 #endif /* CONFIG_EXT_PASSWORD */
1092
1093         if (os_strncmp(value, "hash:", 5) != 0) {
1094                 char *tmp;
1095                 size_t res_len;
1096
1097                 tmp = wpa_config_parse_string(value, &res_len);
1098                 if (tmp == NULL) {
1099                         wpa_printf(MSG_ERROR, "Line %d: failed to parse "
1100                                    "password.", line);
1101                         return -1;
1102                 }
1103                 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
1104                                       (u8 *) tmp, res_len);
1105
1106                 os_free(ssid->eap.password);
1107                 ssid->eap.password = (u8 *) tmp;
1108                 ssid->eap.password_len = res_len;
1109                 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1110                 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
1111
1112                 return 0;
1113         }
1114
1115
1116         /* NtPasswordHash: hash:<32 hex digits> */
1117         if (os_strlen(value + 5) != 2 * 16) {
1118                 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
1119                            "(expected 32 hex digits)", line);
1120                 return -1;
1121         }
1122
1123         hash = os_malloc(16);
1124         if (hash == NULL)
1125                 return -1;
1126
1127         if (hexstr2bin(value + 5, hash, 16)) {
1128                 os_free(hash);
1129                 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
1130                 return -1;
1131         }
1132
1133         wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
1134
1135         os_free(ssid->eap.password);
1136         ssid->eap.password = hash;
1137         ssid->eap.password_len = 16;
1138         ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1139         ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
1140
1141         return 0;
1142 }
1143
1144
1145 static char * wpa_config_write_password(const struct parse_data *data,
1146                                         struct wpa_ssid *ssid)
1147 {
1148         char *buf;
1149
1150         if (ssid->eap.password == NULL)
1151                 return NULL;
1152
1153 #ifdef CONFIG_EXT_PASSWORD
1154         if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
1155                 buf = os_zalloc(4 + ssid->eap.password_len + 1);
1156                 if (buf == NULL)
1157                         return NULL;
1158                 os_memcpy(buf, "ext:", 4);
1159                 os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len);
1160                 return buf;
1161         }
1162 #endif /* CONFIG_EXT_PASSWORD */
1163
1164         if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
1165                 return wpa_config_write_string(
1166                         ssid->eap.password, ssid->eap.password_len);
1167         }
1168
1169         buf = os_malloc(5 + 32 + 1);
1170         if (buf == NULL)
1171                 return NULL;
1172
1173         os_memcpy(buf, "hash:", 5);
1174         wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
1175
1176         return buf;
1177 }
1178 #endif /* IEEE8021X_EAPOL */
1179
1180
1181 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
1182                                     const char *value, int idx)
1183 {
1184         char *buf, title[20];
1185         int res;
1186
1187         buf = wpa_config_parse_string(value, len);
1188         if (buf == NULL) {
1189                 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
1190                            line, idx, value);
1191                 return -1;
1192         }
1193         if (*len > MAX_WEP_KEY_LEN) {
1194                 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
1195                            line, idx, value);
1196                 os_free(buf);
1197                 return -1;
1198         }
1199         if (*len && *len != 5 && *len != 13 && *len != 16) {
1200                 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key length %u - "
1201                            "this network block will be ignored",
1202                            line, (unsigned int) *len);
1203         }
1204         os_memcpy(key, buf, *len);
1205         os_free(buf);
1206         res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
1207         if (res >= 0 && (size_t) res < sizeof(title))
1208                 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
1209         return 0;
1210 }
1211
1212
1213 static int wpa_config_parse_wep_key0(const struct parse_data *data,
1214                                      struct wpa_ssid *ssid, int line,
1215                                      const char *value)
1216 {
1217         return wpa_config_parse_wep_key(ssid->wep_key[0],
1218                                         &ssid->wep_key_len[0], line,
1219                                         value, 0);
1220 }
1221
1222
1223 static int wpa_config_parse_wep_key1(const struct parse_data *data,
1224                                      struct wpa_ssid *ssid, int line,
1225                                      const char *value)
1226 {
1227         return wpa_config_parse_wep_key(ssid->wep_key[1],
1228                                         &ssid->wep_key_len[1], line,
1229                                         value, 1);
1230 }
1231
1232
1233 static int wpa_config_parse_wep_key2(const struct parse_data *data,
1234                                      struct wpa_ssid *ssid, int line,
1235                                      const char *value)
1236 {
1237         return wpa_config_parse_wep_key(ssid->wep_key[2],
1238                                         &ssid->wep_key_len[2], line,
1239                                         value, 2);
1240 }
1241
1242
1243 static int wpa_config_parse_wep_key3(const struct parse_data *data,
1244                                      struct wpa_ssid *ssid, int line,
1245                                      const char *value)
1246 {
1247         return wpa_config_parse_wep_key(ssid->wep_key[3],
1248                                         &ssid->wep_key_len[3], line,
1249                                         value, 3);
1250 }
1251
1252
1253 #ifndef NO_CONFIG_WRITE
1254 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
1255 {
1256         if (ssid->wep_key_len[idx] == 0)
1257                 return NULL;
1258         return wpa_config_write_string(ssid->wep_key[idx],
1259                                        ssid->wep_key_len[idx]);
1260 }
1261
1262
1263 static char * wpa_config_write_wep_key0(const struct parse_data *data,
1264                                         struct wpa_ssid *ssid)
1265 {
1266         return wpa_config_write_wep_key(ssid, 0);
1267 }
1268
1269
1270 static char * wpa_config_write_wep_key1(const struct parse_data *data,
1271                                         struct wpa_ssid *ssid)
1272 {
1273         return wpa_config_write_wep_key(ssid, 1);
1274 }
1275
1276
1277 static char * wpa_config_write_wep_key2(const struct parse_data *data,
1278                                         struct wpa_ssid *ssid)
1279 {
1280         return wpa_config_write_wep_key(ssid, 2);
1281 }
1282
1283
1284 static char * wpa_config_write_wep_key3(const struct parse_data *data,
1285                                         struct wpa_ssid *ssid)
1286 {
1287         return wpa_config_write_wep_key(ssid, 3);
1288 }
1289 #endif /* NO_CONFIG_WRITE */
1290
1291
1292 #ifdef CONFIG_P2P
1293
1294 static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
1295                                             struct wpa_ssid *ssid, int line,
1296                                             const char *value)
1297 {
1298         const char *pos;
1299         u8 *buf, *n, addr[ETH_ALEN];
1300         size_t count;
1301
1302         buf = NULL;
1303         count = 0;
1304
1305         pos = value;
1306         while (pos && *pos) {
1307                 while (*pos == ' ')
1308                         pos++;
1309
1310                 if (hwaddr_aton(pos, addr)) {
1311                         if (count == 0) {
1312                                 wpa_printf(MSG_ERROR, "Line %d: Invalid "
1313                                            "p2p_client_list address '%s'.",
1314                                            line, value);
1315                                 os_free(buf);
1316                                 return -1;
1317                         }
1318                         /* continue anyway since this could have been from a
1319                          * truncated configuration file line */
1320                         wpa_printf(MSG_INFO, "Line %d: Ignore likely "
1321                                    "truncated p2p_client_list address '%s'",
1322                                    line, pos);
1323                 } else {
1324                         n = os_realloc_array(buf, count + 1, ETH_ALEN);
1325                         if (n == NULL) {
1326                                 os_free(buf);
1327                                 return -1;
1328                         }
1329                         buf = n;
1330                         os_memmove(buf + ETH_ALEN, buf, count * ETH_ALEN);
1331                         os_memcpy(buf, addr, ETH_ALEN);
1332                         count++;
1333                         wpa_hexdump(MSG_MSGDUMP, "p2p_client_list",
1334                                     addr, ETH_ALEN);
1335                 }
1336
1337                 pos = os_strchr(pos, ' ');
1338         }
1339
1340         os_free(ssid->p2p_client_list);
1341         ssid->p2p_client_list = buf;
1342         ssid->num_p2p_clients = count;
1343
1344         return 0;
1345 }
1346
1347
1348 #ifndef NO_CONFIG_WRITE
1349 static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
1350                                                struct wpa_ssid *ssid)
1351 {
1352         char *value, *end, *pos;
1353         int res;
1354         size_t i;
1355
1356         if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0)
1357                 return NULL;
1358
1359         value = os_malloc(20 * ssid->num_p2p_clients);
1360         if (value == NULL)
1361                 return NULL;
1362         pos = value;
1363         end = value + 20 * ssid->num_p2p_clients;
1364
1365         for (i = ssid->num_p2p_clients; i > 0; i--) {
1366                 res = os_snprintf(pos, end - pos, MACSTR " ",
1367                                   MAC2STR(ssid->p2p_client_list +
1368                                           (i - 1) * ETH_ALEN));
1369                 if (res < 0 || res >= end - pos) {
1370                         os_free(value);
1371                         return NULL;
1372                 }
1373                 pos += res;
1374         }
1375
1376         if (pos > value)
1377                 pos[-1] = '\0';
1378
1379         return value;
1380 }
1381 #endif /* NO_CONFIG_WRITE */
1382
1383
1384 static int wpa_config_parse_psk_list(const struct parse_data *data,
1385                                      struct wpa_ssid *ssid, int line,
1386                                      const char *value)
1387 {
1388         struct psk_list_entry *p;
1389         const char *pos;
1390
1391         p = os_zalloc(sizeof(*p));
1392         if (p == NULL)
1393                 return -1;
1394
1395         pos = value;
1396         if (os_strncmp(pos, "P2P-", 4) == 0) {
1397                 p->p2p = 1;
1398                 pos += 4;
1399         }
1400
1401         if (hwaddr_aton(pos, p->addr)) {
1402                 wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list address '%s'",
1403                            line, pos);
1404                 os_free(p);
1405                 return -1;
1406         }
1407         pos += 17;
1408         if (*pos != '-') {
1409                 wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list '%s'",
1410                            line, pos);
1411                 os_free(p);
1412                 return -1;
1413         }
1414         pos++;
1415
1416         if (hexstr2bin(pos, p->psk, PMK_LEN) || pos[PMK_LEN * 2] != '\0') {
1417                 wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list PSK '%s'",
1418                            line, pos);
1419                 os_free(p);
1420                 return -1;
1421         }
1422
1423         dl_list_add(&ssid->psk_list, &p->list);
1424
1425         return 0;
1426 }
1427
1428
1429 #ifndef NO_CONFIG_WRITE
1430 static char * wpa_config_write_psk_list(const struct parse_data *data,
1431                                         struct wpa_ssid *ssid)
1432 {
1433         return NULL;
1434 }
1435 #endif /* NO_CONFIG_WRITE */
1436
1437 #endif /* CONFIG_P2P */
1438
1439 /* Helper macros for network block parser */
1440
1441 #ifdef OFFSET
1442 #undef OFFSET
1443 #endif /* OFFSET */
1444 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
1445 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
1446
1447 /* STR: Define a string variable for an ASCII string; f = field name */
1448 #ifdef NO_CONFIG_WRITE
1449 #define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
1450 #define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
1451 #else /* NO_CONFIG_WRITE */
1452 #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
1453 #define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
1454 #endif /* NO_CONFIG_WRITE */
1455 #define STR(f) _STR(f), NULL, NULL, NULL, 0
1456 #define STRe(f) _STRe(f), NULL, NULL, NULL, 0
1457 #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
1458 #define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
1459
1460 /* STR_LEN: Define a string variable with a separate variable for storing the
1461  * data length. Unlike STR(), this can be used to store arbitrary binary data
1462  * (i.e., even nul termination character). */
1463 #define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
1464 #define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
1465 #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
1466 #define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
1467 #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
1468
1469 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
1470  * explicitly specified. */
1471 #define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
1472 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
1473 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
1474
1475 #ifdef NO_CONFIG_WRITE
1476 #define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
1477 #define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
1478 #else /* NO_CONFIG_WRITE */
1479 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1480         OFFSET(f), (void *) 0
1481 #define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1482         OFFSET(eap.f), (void *) 0
1483 #endif /* NO_CONFIG_WRITE */
1484
1485 /* INT: Define an integer variable */
1486 #define INT(f) _INT(f), NULL, NULL, 0
1487 #define INTe(f) _INTe(f), NULL, NULL, 0
1488
1489 /* INT_RANGE: Define an integer variable with allowed value range */
1490 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
1491
1492 /* FUNC: Define a configuration variable that uses a custom function for
1493  * parsing and writing the value. */
1494 #ifdef NO_CONFIG_WRITE
1495 #define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
1496 #else /* NO_CONFIG_WRITE */
1497 #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
1498         NULL, NULL, NULL, NULL
1499 #endif /* NO_CONFIG_WRITE */
1500 #define FUNC(f) _FUNC(f), 0
1501 #define FUNC_KEY(f) _FUNC(f), 1
1502
1503 /*
1504  * Table of network configuration variables. This table is used to parse each
1505  * network configuration variable, e.g., each line in wpa_supplicant.conf file
1506  * that is inside a network block.
1507  *
1508  * This table is generated using the helper macros defined above and with
1509  * generous help from the C pre-processor. The field name is stored as a string
1510  * into .name and for STR and INT types, the offset of the target buffer within
1511  * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
1512  * offset to the field containing the length of the configuration variable.
1513  * .param3 and .param4 can be used to mark the allowed range (length for STR
1514  * and value for INT).
1515  *
1516  * For each configuration line in wpa_supplicant.conf, the parser goes through
1517  * this table and select the entry that matches with the field name. The parser
1518  * function (.parser) is then called to parse the actual value of the field.
1519  *
1520  * This kind of mechanism makes it easy to add new configuration parameters,
1521  * since only one line needs to be added into this table and into the
1522  * struct wpa_ssid definition if the new variable is either a string or
1523  * integer. More complex types will need to use their own parser and writer
1524  * functions.
1525  */
1526 static const struct parse_data ssid_fields[] = {
1527         { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1528         { INT_RANGE(scan_ssid, 0, 1) },
1529         { FUNC(bssid) },
1530         { FUNC_KEY(psk) },
1531         { FUNC(proto) },
1532         { FUNC(key_mgmt) },
1533         { INT(bg_scan_period) },
1534         { FUNC(pairwise) },
1535         { FUNC(group) },
1536         { FUNC(auth_alg) },
1537         { FUNC(scan_freq) },
1538         { FUNC(freq_list) },
1539 #ifdef IEEE8021X_EAPOL
1540         { FUNC(eap) },
1541         { STR_LENe(identity) },
1542         { STR_LENe(anonymous_identity) },
1543         { FUNC_KEY(password) },
1544         { STRe(ca_cert) },
1545         { STRe(ca_path) },
1546         { STRe(client_cert) },
1547         { STRe(private_key) },
1548         { STR_KEYe(private_key_passwd) },
1549         { STRe(dh_file) },
1550         { STRe(subject_match) },
1551         { STRe(altsubject_match) },
1552         { STRe(ca_cert2) },
1553         { STRe(ca_path2) },
1554         { STRe(client_cert2) },
1555         { STRe(private_key2) },
1556         { STR_KEYe(private_key2_passwd) },
1557         { STRe(dh_file2) },
1558         { STRe(subject_match2) },
1559         { STRe(altsubject_match2) },
1560         { STRe(phase1) },
1561         { STRe(phase2) },
1562         { STRe(pcsc) },
1563         { STR_KEYe(pin) },
1564         { STRe(engine_id) },
1565         { STRe(key_id) },
1566         { STRe(cert_id) },
1567         { STRe(ca_cert_id) },
1568         { STR_KEYe(pin2) },
1569         { STRe(engine2_id) },
1570         { STRe(key2_id) },
1571         { STRe(cert2_id) },
1572         { STRe(ca_cert2_id) },
1573         { INTe(engine) },
1574         { INTe(engine2) },
1575         { INT(eapol_flags) },
1576 #endif /* IEEE8021X_EAPOL */
1577         { FUNC_KEY(wep_key0) },
1578         { FUNC_KEY(wep_key1) },
1579         { FUNC_KEY(wep_key2) },
1580         { FUNC_KEY(wep_key3) },
1581         { INT(wep_tx_keyidx) },
1582         { INT(priority) },
1583 #ifdef IEEE8021X_EAPOL
1584         { INT(eap_workaround) },
1585         { STRe(pac_file) },
1586         { INTe(fragment_size) },
1587         { INTe(ocsp) },
1588 #endif /* IEEE8021X_EAPOL */
1589         { INT_RANGE(mode, 0, 4) },
1590         { INT_RANGE(proactive_key_caching, 0, 1) },
1591         { INT_RANGE(disabled, 0, 2) },
1592         { STR(id_str) },
1593 #ifdef CONFIG_IEEE80211W
1594         { INT_RANGE(ieee80211w, 0, 2) },
1595 #endif /* CONFIG_IEEE80211W */
1596         { INT_RANGE(peerkey, 0, 1) },
1597         { INT_RANGE(mixed_cell, 0, 1) },
1598         { INT_RANGE(frequency, 0, 65000) },
1599         { INT(wpa_ptk_rekey) },
1600         { STR(bgscan) },
1601         { INT_RANGE(ignore_broadcast_ssid, 0, 2) },
1602 #ifdef CONFIG_P2P
1603         { FUNC(p2p_client_list) },
1604         { FUNC(psk_list) },
1605 #endif /* CONFIG_P2P */
1606 #ifdef CONFIG_HT_OVERRIDES
1607         { INT_RANGE(disable_ht, 0, 1) },
1608         { INT_RANGE(disable_ht40, -1, 1) },
1609         { INT_RANGE(disable_sgi, 0, 1) },
1610         { INT_RANGE(disable_max_amsdu, -1, 1) },
1611         { INT_RANGE(ampdu_factor, -1, 3) },
1612         { INT_RANGE(ampdu_density, -1, 7) },
1613         { STR(ht_mcs) },
1614 #endif /* CONFIG_HT_OVERRIDES */
1615 #ifdef CONFIG_VHT_OVERRIDES
1616         { INT_RANGE(disable_vht, 0, 1) },
1617         { INT(vht_capa) },
1618         { INT(vht_capa_mask) },
1619         { INT_RANGE(vht_rx_mcs_nss_1, -1, 3) },
1620         { INT_RANGE(vht_rx_mcs_nss_2, -1, 3) },
1621         { INT_RANGE(vht_rx_mcs_nss_3, -1, 3) },
1622         { INT_RANGE(vht_rx_mcs_nss_4, -1, 3) },
1623         { INT_RANGE(vht_rx_mcs_nss_5, -1, 3) },
1624         { INT_RANGE(vht_rx_mcs_nss_6, -1, 3) },
1625         { INT_RANGE(vht_rx_mcs_nss_7, -1, 3) },
1626         { INT_RANGE(vht_rx_mcs_nss_8, -1, 3) },
1627         { INT_RANGE(vht_tx_mcs_nss_1, -1, 3) },
1628         { INT_RANGE(vht_tx_mcs_nss_2, -1, 3) },
1629         { INT_RANGE(vht_tx_mcs_nss_3, -1, 3) },
1630         { INT_RANGE(vht_tx_mcs_nss_4, -1, 3) },
1631         { INT_RANGE(vht_tx_mcs_nss_5, -1, 3) },
1632         { INT_RANGE(vht_tx_mcs_nss_6, -1, 3) },
1633         { INT_RANGE(vht_tx_mcs_nss_7, -1, 3) },
1634         { INT_RANGE(vht_tx_mcs_nss_8, -1, 3) },
1635 #endif /* CONFIG_VHT_OVERRIDES */
1636         { INT(ap_max_inactivity) },
1637         { INT(dtim_period) },
1638         { INT(beacon_int) },
1639 };
1640
1641 #undef OFFSET
1642 #undef _STR
1643 #undef STR
1644 #undef STR_KEY
1645 #undef _STR_LEN
1646 #undef STR_LEN
1647 #undef STR_LEN_KEY
1648 #undef _STR_RANGE
1649 #undef STR_RANGE
1650 #undef STR_RANGE_KEY
1651 #undef _INT
1652 #undef INT
1653 #undef INT_RANGE
1654 #undef _FUNC
1655 #undef FUNC
1656 #undef FUNC_KEY
1657 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1658
1659
1660 /**
1661  * wpa_config_add_prio_network - Add a network to priority lists
1662  * @config: Configuration data from wpa_config_read()
1663  * @ssid: Pointer to the network configuration to be added to the list
1664  * Returns: 0 on success, -1 on failure
1665  *
1666  * This function is used to add a network block to the priority list of
1667  * networks. This must be called for each network when reading in the full
1668  * configuration. In addition, this can be used indirectly when updating
1669  * priorities by calling wpa_config_update_prio_list().
1670  */
1671 int wpa_config_add_prio_network(struct wpa_config *config,
1672                                 struct wpa_ssid *ssid)
1673 {
1674         int prio;
1675         struct wpa_ssid *prev, **nlist;
1676
1677         /*
1678          * Add to an existing priority list if one is available for the
1679          * configured priority level for this network.
1680          */
1681         for (prio = 0; prio < config->num_prio; prio++) {
1682                 prev = config->pssid[prio];
1683                 if (prev->priority == ssid->priority) {
1684                         while (prev->pnext)
1685                                 prev = prev->pnext;
1686                         prev->pnext = ssid;
1687                         return 0;
1688                 }
1689         }
1690
1691         /* First network for this priority - add a new priority list */
1692         nlist = os_realloc_array(config->pssid, config->num_prio + 1,
1693                                  sizeof(struct wpa_ssid *));
1694         if (nlist == NULL)
1695                 return -1;
1696
1697         for (prio = 0; prio < config->num_prio; prio++) {
1698                 if (nlist[prio]->priority < ssid->priority) {
1699                         os_memmove(&nlist[prio + 1], &nlist[prio],
1700                                    (config->num_prio - prio) *
1701                                    sizeof(struct wpa_ssid *));
1702                         break;
1703                 }
1704         }
1705
1706         nlist[prio] = ssid;
1707         config->num_prio++;
1708         config->pssid = nlist;
1709
1710         return 0;
1711 }
1712
1713
1714 /**
1715  * wpa_config_update_prio_list - Update network priority list
1716  * @config: Configuration data from wpa_config_read()
1717  * Returns: 0 on success, -1 on failure
1718  *
1719  * This function is called to update the priority list of networks in the
1720  * configuration when a network is being added or removed. This is also called
1721  * if a priority for a network is changed.
1722  */
1723 int wpa_config_update_prio_list(struct wpa_config *config)
1724 {
1725         struct wpa_ssid *ssid;
1726         int ret = 0;
1727
1728         os_free(config->pssid);
1729         config->pssid = NULL;
1730         config->num_prio = 0;
1731
1732         ssid = config->ssid;
1733         while (ssid) {
1734                 ssid->pnext = NULL;
1735                 if (wpa_config_add_prio_network(config, ssid) < 0)
1736                         ret = -1;
1737                 ssid = ssid->next;
1738         }
1739
1740         return ret;
1741 }
1742
1743
1744 #ifdef IEEE8021X_EAPOL
1745 static void eap_peer_config_free(struct eap_peer_config *eap)
1746 {
1747         os_free(eap->eap_methods);
1748         os_free(eap->identity);
1749         os_free(eap->anonymous_identity);
1750         os_free(eap->password);
1751         os_free(eap->ca_cert);
1752         os_free(eap->ca_path);
1753         os_free(eap->client_cert);
1754         os_free(eap->private_key);
1755         os_free(eap->private_key_passwd);
1756         os_free(eap->dh_file);
1757         os_free(eap->subject_match);
1758         os_free(eap->altsubject_match);
1759         os_free(eap->ca_cert2);
1760         os_free(eap->ca_path2);
1761         os_free(eap->client_cert2);
1762         os_free(eap->private_key2);
1763         os_free(eap->private_key2_passwd);
1764         os_free(eap->dh_file2);
1765         os_free(eap->subject_match2);
1766         os_free(eap->altsubject_match2);
1767         os_free(eap->phase1);
1768         os_free(eap->phase2);
1769         os_free(eap->pcsc);
1770         os_free(eap->pin);
1771         os_free(eap->engine_id);
1772         os_free(eap->key_id);
1773         os_free(eap->cert_id);
1774         os_free(eap->ca_cert_id);
1775         os_free(eap->key2_id);
1776         os_free(eap->cert2_id);
1777         os_free(eap->ca_cert2_id);
1778         os_free(eap->pin2);
1779         os_free(eap->engine2_id);
1780         os_free(eap->otp);
1781         os_free(eap->pending_req_otp);
1782         os_free(eap->pac_file);
1783         os_free(eap->new_password);
1784 }
1785 #endif /* IEEE8021X_EAPOL */
1786
1787
1788 /**
1789  * wpa_config_free_ssid - Free network/ssid configuration data
1790  * @ssid: Configuration data for the network
1791  *
1792  * This function frees all resources allocated for the network configuration
1793  * data.
1794  */
1795 void wpa_config_free_ssid(struct wpa_ssid *ssid)
1796 {
1797         struct psk_list_entry *psk;
1798
1799         os_free(ssid->ssid);
1800         os_free(ssid->passphrase);
1801         os_free(ssid->ext_psk);
1802 #ifdef IEEE8021X_EAPOL
1803         eap_peer_config_free(&ssid->eap);
1804 #endif /* IEEE8021X_EAPOL */
1805         os_free(ssid->id_str);
1806         os_free(ssid->scan_freq);
1807         os_free(ssid->freq_list);
1808         os_free(ssid->bgscan);
1809         os_free(ssid->p2p_client_list);
1810 #ifdef CONFIG_HT_OVERRIDES
1811         os_free(ssid->ht_mcs);
1812 #endif /* CONFIG_HT_OVERRIDES */
1813         while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
1814                                     list))) {
1815                 dl_list_del(&psk->list);
1816                 os_free(psk);
1817         }
1818         os_free(ssid);
1819 }
1820
1821
1822 void wpa_config_free_cred(struct wpa_cred *cred)
1823 {
1824         os_free(cred->realm);
1825         os_free(cred->username);
1826         os_free(cred->password);
1827         os_free(cred->ca_cert);
1828         os_free(cred->client_cert);
1829         os_free(cred->private_key);
1830         os_free(cred->private_key_passwd);
1831         os_free(cred->imsi);
1832         os_free(cred->milenage);
1833         os_free(cred->domain);
1834         os_free(cred->eap_method);
1835         os_free(cred->phase1);
1836         os_free(cred->phase2);
1837         os_free(cred->excluded_ssid);
1838         os_free(cred);
1839 }
1840
1841
1842 /**
1843  * wpa_config_free - Free configuration data
1844  * @config: Configuration data from wpa_config_read()
1845  *
1846  * This function frees all resources allocated for the configuration data by
1847  * wpa_config_read().
1848  */
1849 void wpa_config_free(struct wpa_config *config)
1850 {
1851 #ifndef CONFIG_NO_CONFIG_BLOBS
1852         struct wpa_config_blob *blob, *prevblob;
1853 #endif /* CONFIG_NO_CONFIG_BLOBS */
1854         struct wpa_ssid *ssid, *prev = NULL;
1855         struct wpa_cred *cred, *cprev;
1856
1857         ssid = config->ssid;
1858         while (ssid) {
1859                 prev = ssid;
1860                 ssid = ssid->next;
1861                 wpa_config_free_ssid(prev);
1862         }
1863
1864         cred = config->cred;
1865         while (cred) {
1866                 cprev = cred;
1867                 cred = cred->next;
1868                 wpa_config_free_cred(cprev);
1869         }
1870
1871 #ifndef CONFIG_NO_CONFIG_BLOBS
1872         blob = config->blobs;
1873         prevblob = NULL;
1874         while (blob) {
1875                 prevblob = blob;
1876                 blob = blob->next;
1877                 wpa_config_free_blob(prevblob);
1878         }
1879 #endif /* CONFIG_NO_CONFIG_BLOBS */
1880
1881         wpabuf_free(config->wps_vendor_ext_m1);
1882         os_free(config->ctrl_interface);
1883         os_free(config->ctrl_interface_group);
1884         os_free(config->opensc_engine_path);
1885         os_free(config->pkcs11_engine_path);
1886         os_free(config->pkcs11_module_path);
1887         os_free(config->pcsc_reader);
1888         os_free(config->pcsc_pin);
1889         os_free(config->driver_param);
1890         os_free(config->device_name);
1891         os_free(config->manufacturer);
1892         os_free(config->model_name);
1893         os_free(config->model_number);
1894         os_free(config->serial_number);
1895         os_free(config->config_methods);
1896         os_free(config->p2p_ssid_postfix);
1897         os_free(config->pssid);
1898         os_free(config->p2p_pref_chan);
1899         os_free(config->autoscan);
1900         os_free(config->freq_list);
1901         wpabuf_free(config->wps_nfc_dh_pubkey);
1902         wpabuf_free(config->wps_nfc_dh_privkey);
1903         wpabuf_free(config->wps_nfc_dev_pw);
1904         os_free(config->ext_password_backend);
1905         os_free(config->sae_groups);
1906         wpabuf_free(config->ap_vendor_elements);
1907         os_free(config);
1908 }
1909
1910
1911 /**
1912  * wpa_config_foreach_network - Iterate over each configured network
1913  * @config: Configuration data from wpa_config_read()
1914  * @func: Callback function to process each network
1915  * @arg: Opaque argument to pass to callback function
1916  *
1917  * Iterate over the set of configured networks calling the specified
1918  * function for each item. We guard against callbacks removing the
1919  * supplied network.
1920  */
1921 void wpa_config_foreach_network(struct wpa_config *config,
1922                                 void (*func)(void *, struct wpa_ssid *),
1923                                 void *arg)
1924 {
1925         struct wpa_ssid *ssid, *next;
1926
1927         ssid = config->ssid;
1928         while (ssid) {
1929                 next = ssid->next;
1930                 func(arg, ssid);
1931                 ssid = next;
1932         }
1933 }
1934
1935
1936 /**
1937  * wpa_config_get_network - Get configured network based on id
1938  * @config: Configuration data from wpa_config_read()
1939  * @id: Unique network id to search for
1940  * Returns: Network configuration or %NULL if not found
1941  */
1942 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1943 {
1944         struct wpa_ssid *ssid;
1945
1946         ssid = config->ssid;
1947         while (ssid) {
1948                 if (id == ssid->id)
1949                         break;
1950                 ssid = ssid->next;
1951         }
1952
1953         return ssid;
1954 }
1955
1956
1957 /**
1958  * wpa_config_add_network - Add a new network with empty configuration
1959  * @config: Configuration data from wpa_config_read()
1960  * Returns: The new network configuration or %NULL if operation failed
1961  */
1962 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1963 {
1964         int id;
1965         struct wpa_ssid *ssid, *last = NULL;
1966
1967         id = -1;
1968         ssid = config->ssid;
1969         while (ssid) {
1970                 if (ssid->id > id)
1971                         id = ssid->id;
1972                 last = ssid;
1973                 ssid = ssid->next;
1974         }
1975         id++;
1976
1977         ssid = os_zalloc(sizeof(*ssid));
1978         if (ssid == NULL)
1979                 return NULL;
1980         ssid->id = id;
1981         dl_list_init(&ssid->psk_list);
1982         if (last)
1983                 last->next = ssid;
1984         else
1985                 config->ssid = ssid;
1986
1987         wpa_config_update_prio_list(config);
1988
1989         return ssid;
1990 }
1991
1992
1993 /**
1994  * wpa_config_remove_network - Remove a configured network based on id
1995  * @config: Configuration data from wpa_config_read()
1996  * @id: Unique network id to search for
1997  * Returns: 0 on success, or -1 if the network was not found
1998  */
1999 int wpa_config_remove_network(struct wpa_config *config, int id)
2000 {
2001         struct wpa_ssid *ssid, *prev = NULL;
2002
2003         ssid = config->ssid;
2004         while (ssid) {
2005                 if (id == ssid->id)
2006                         break;
2007                 prev = ssid;
2008                 ssid = ssid->next;
2009         }
2010
2011         if (ssid == NULL)
2012                 return -1;
2013
2014         if (prev)
2015                 prev->next = ssid->next;
2016         else
2017                 config->ssid = ssid->next;
2018
2019         wpa_config_update_prio_list(config);
2020         wpa_config_free_ssid(ssid);
2021         return 0;
2022 }
2023
2024
2025 /**
2026  * wpa_config_set_network_defaults - Set network default values
2027  * @ssid: Pointer to network configuration data
2028  */
2029 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
2030 {
2031         ssid->proto = DEFAULT_PROTO;
2032         ssid->pairwise_cipher = DEFAULT_PAIRWISE;
2033         ssid->group_cipher = DEFAULT_GROUP;
2034         ssid->key_mgmt = DEFAULT_KEY_MGMT;
2035         ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
2036 #ifdef IEEE8021X_EAPOL
2037         ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
2038         ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
2039         ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
2040 #endif /* IEEE8021X_EAPOL */
2041 #ifdef CONFIG_HT_OVERRIDES
2042         ssid->disable_ht = DEFAULT_DISABLE_HT;
2043         ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
2044         ssid->disable_sgi = DEFAULT_DISABLE_SGI;
2045         ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
2046         ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
2047         ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
2048 #endif /* CONFIG_HT_OVERRIDES */
2049 #ifdef CONFIG_VHT_OVERRIDES
2050         ssid->vht_rx_mcs_nss_1 = -1;
2051         ssid->vht_rx_mcs_nss_2 = -1;
2052         ssid->vht_rx_mcs_nss_3 = -1;
2053         ssid->vht_rx_mcs_nss_4 = -1;
2054         ssid->vht_rx_mcs_nss_5 = -1;
2055         ssid->vht_rx_mcs_nss_6 = -1;
2056         ssid->vht_rx_mcs_nss_7 = -1;
2057         ssid->vht_rx_mcs_nss_8 = -1;
2058         ssid->vht_tx_mcs_nss_1 = -1;
2059         ssid->vht_tx_mcs_nss_2 = -1;
2060         ssid->vht_tx_mcs_nss_3 = -1;
2061         ssid->vht_tx_mcs_nss_4 = -1;
2062         ssid->vht_tx_mcs_nss_5 = -1;
2063         ssid->vht_tx_mcs_nss_6 = -1;
2064         ssid->vht_tx_mcs_nss_7 = -1;
2065         ssid->vht_tx_mcs_nss_8 = -1;
2066 #endif /* CONFIG_VHT_OVERRIDES */
2067         ssid->proactive_key_caching = -1;
2068 #ifdef CONFIG_IEEE80211W
2069         ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
2070 #endif /* CONFIG_IEEE80211W */
2071 }
2072
2073
2074 /**
2075  * wpa_config_set - Set a variable in network configuration
2076  * @ssid: Pointer to network configuration data
2077  * @var: Variable name, e.g., "ssid"
2078  * @value: Variable value
2079  * @line: Line number in configuration file or 0 if not used
2080  * Returns: 0 on success, -1 on failure
2081  *
2082  * This function can be used to set network configuration variables based on
2083  * both the configuration file and management interface input. The value
2084  * parameter must be in the same format as the text-based configuration file is
2085  * using. For example, strings are using double quotation marks.
2086  */
2087 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
2088                    int line)
2089 {
2090         size_t i;
2091         int ret = 0;
2092
2093         if (ssid == NULL || var == NULL || value == NULL)
2094                 return -1;
2095
2096         for (i = 0; i < NUM_SSID_FIELDS; i++) {
2097                 const struct parse_data *field = &ssid_fields[i];
2098                 if (os_strcmp(var, field->name) != 0)
2099                         continue;
2100
2101                 if (field->parser(field, ssid, line, value)) {
2102                         if (line) {
2103                                 wpa_printf(MSG_ERROR, "Line %d: failed to "
2104                                            "parse %s '%s'.", line, var, value);
2105                         }
2106                         ret = -1;
2107                 }
2108                 break;
2109         }
2110         if (i == NUM_SSID_FIELDS) {
2111                 if (line) {
2112                         wpa_printf(MSG_ERROR, "Line %d: unknown network field "
2113                                    "'%s'.", line, var);
2114                 }
2115                 ret = -1;
2116         }
2117
2118         return ret;
2119 }
2120
2121
2122 int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var,
2123                           const char *value)
2124 {
2125         size_t len;
2126         char *buf;
2127         int ret;
2128
2129         len = os_strlen(value);
2130         buf = os_malloc(len + 3);
2131         if (buf == NULL)
2132                 return -1;
2133         buf[0] = '"';
2134         os_memcpy(buf + 1, value, len);
2135         buf[len + 1] = '"';
2136         buf[len + 2] = '\0';
2137         ret = wpa_config_set(ssid, var, buf, 0);
2138         os_free(buf);
2139         return ret;
2140 }
2141
2142
2143 /**
2144  * wpa_config_get_all - Get all options from network configuration
2145  * @ssid: Pointer to network configuration data
2146  * @get_keys: Determines if keys/passwords will be included in returned list
2147  *      (if they may be exported)
2148  * Returns: %NULL terminated list of all set keys and their values in the form
2149  * of [key1, val1, key2, val2, ... , NULL]
2150  *
2151  * This function can be used to get list of all configured network properties.
2152  * The caller is responsible for freeing the returned list and all its
2153  * elements.
2154  */
2155 char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
2156 {
2157         const struct parse_data *field;
2158         char *key, *value;
2159         size_t i;
2160         char **props;
2161         int fields_num;
2162
2163         get_keys = get_keys && ssid->export_keys;
2164
2165         props = os_calloc(2 * NUM_SSID_FIELDS + 1, sizeof(char *));
2166         if (!props)
2167                 return NULL;
2168
2169         fields_num = 0;
2170         for (i = 0; i < NUM_SSID_FIELDS; i++) {
2171                 field = &ssid_fields[i];
2172                 if (field->key_data && !get_keys)
2173                         continue;
2174                 value = field->writer(field, ssid);
2175                 if (value == NULL)
2176                         continue;
2177                 if (os_strlen(value) == 0) {
2178                         os_free(value);
2179                         continue;
2180                 }
2181
2182                 key = os_strdup(field->name);
2183                 if (key == NULL) {
2184                         os_free(value);
2185                         goto err;
2186                 }
2187
2188                 props[fields_num * 2] = key;
2189                 props[fields_num * 2 + 1] = value;
2190
2191                 fields_num++;
2192         }
2193
2194         return props;
2195
2196 err:
2197         value = *props;
2198         while (value)
2199                 os_free(value++);
2200         os_free(props);
2201         return NULL;
2202 }
2203
2204
2205 #ifndef NO_CONFIG_WRITE
2206 /**
2207  * wpa_config_get - Get a variable in network configuration
2208  * @ssid: Pointer to network configuration data
2209  * @var: Variable name, e.g., "ssid"
2210  * Returns: Value of the variable or %NULL on failure
2211  *
2212  * This function can be used to get network configuration variables. The
2213  * returned value is a copy of the configuration variable in text format, i.e,.
2214  * the same format that the text-based configuration file and wpa_config_set()
2215  * are using for the value. The caller is responsible for freeing the returned
2216  * value.
2217  */
2218 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
2219 {
2220         size_t i;
2221
2222         if (ssid == NULL || var == NULL)
2223                 return NULL;
2224
2225         for (i = 0; i < NUM_SSID_FIELDS; i++) {
2226                 const struct parse_data *field = &ssid_fields[i];
2227                 if (os_strcmp(var, field->name) == 0)
2228                         return field->writer(field, ssid);
2229         }
2230
2231         return NULL;
2232 }
2233
2234
2235 /**
2236  * wpa_config_get_no_key - Get a variable in network configuration (no keys)
2237  * @ssid: Pointer to network configuration data
2238  * @var: Variable name, e.g., "ssid"
2239  * Returns: Value of the variable or %NULL on failure
2240  *
2241  * This function can be used to get network configuration variable like
2242  * wpa_config_get(). The only difference is that this functions does not expose
2243  * key/password material from the configuration. In case a key/password field
2244  * is requested, the returned value is an empty string or %NULL if the variable
2245  * is not set or "*" if the variable is set (regardless of its value). The
2246  * returned value is a copy of the configuration variable in text format, i.e,.
2247  * the same format that the text-based configuration file and wpa_config_set()
2248  * are using for the value. The caller is responsible for freeing the returned
2249  * value.
2250  */
2251 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
2252 {
2253         size_t i;
2254
2255         if (ssid == NULL || var == NULL)
2256                 return NULL;
2257
2258         for (i = 0; i < NUM_SSID_FIELDS; i++) {
2259                 const struct parse_data *field = &ssid_fields[i];
2260                 if (os_strcmp(var, field->name) == 0) {
2261                         char *res = field->writer(field, ssid);
2262                         if (field->key_data) {
2263                                 if (res && res[0]) {
2264                                         wpa_printf(MSG_DEBUG, "Do not allow "
2265                                                    "key_data field to be "
2266                                                    "exposed");
2267                                         os_free(res);
2268                                         return os_strdup("*");
2269                                 }
2270
2271                                 os_free(res);
2272                                 return NULL;
2273                         }
2274                         return res;
2275                 }
2276         }
2277
2278         return NULL;
2279 }
2280 #endif /* NO_CONFIG_WRITE */
2281
2282
2283 /**
2284  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
2285  * @ssid: Pointer to network configuration data
2286  *
2287  * This function must be called to update WPA PSK when either SSID or the
2288  * passphrase has changed for the network configuration.
2289  */
2290 void wpa_config_update_psk(struct wpa_ssid *ssid)
2291 {
2292 #ifndef CONFIG_NO_PBKDF2
2293         pbkdf2_sha1(ssid->passphrase, ssid->ssid, ssid->ssid_len, 4096,
2294                     ssid->psk, PMK_LEN);
2295         wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
2296                         ssid->psk, PMK_LEN);
2297         ssid->psk_set = 1;
2298 #endif /* CONFIG_NO_PBKDF2 */
2299 }
2300
2301
2302 int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
2303                         const char *value, int line)
2304 {
2305         char *val;
2306         size_t len;
2307
2308         if (os_strcmp(var, "priority") == 0) {
2309                 cred->priority = atoi(value);
2310                 return 0;
2311         }
2312
2313         if (os_strcmp(var, "pcsc") == 0) {
2314                 cred->pcsc = atoi(value);
2315                 return 0;
2316         }
2317
2318         if (os_strcmp(var, "eap") == 0) {
2319                 struct eap_method_type method;
2320                 method.method = eap_peer_get_type(value, &method.vendor);
2321                 if (method.vendor == EAP_VENDOR_IETF &&
2322                     method.method == EAP_TYPE_NONE) {
2323                         wpa_printf(MSG_ERROR, "Line %d: unknown EAP type '%s' "
2324                                    "for a credential", line, value);
2325                         return -1;
2326                 }
2327                 os_free(cred->eap_method);
2328                 cred->eap_method = os_malloc(sizeof(*cred->eap_method));
2329                 if (cred->eap_method == NULL)
2330                         return -1;
2331                 os_memcpy(cred->eap_method, &method, sizeof(method));
2332                 return 0;
2333         }
2334
2335         if (os_strcmp(var, "password") == 0 &&
2336             os_strncmp(value, "ext:", 4) == 0) {
2337                 os_free(cred->password);
2338                 cred->password = os_strdup(value);
2339                 cred->ext_password = 1;
2340                 return 0;
2341         }
2342
2343         val = wpa_config_parse_string(value, &len);
2344         if (val == NULL) {
2345                 wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
2346                            "value '%s'.", line, var, value);
2347                 return -1;
2348         }
2349
2350         if (os_strcmp(var, "realm") == 0) {
2351                 os_free(cred->realm);
2352                 cred->realm = val;
2353                 return 0;
2354         }
2355
2356         if (os_strcmp(var, "username") == 0) {
2357                 os_free(cred->username);
2358                 cred->username = val;
2359                 return 0;
2360         }
2361
2362         if (os_strcmp(var, "password") == 0) {
2363                 os_free(cred->password);
2364                 cred->password = val;
2365                 cred->ext_password = 0;
2366                 return 0;
2367         }
2368
2369         if (os_strcmp(var, "ca_cert") == 0) {
2370                 os_free(cred->ca_cert);
2371                 cred->ca_cert = val;
2372                 return 0;
2373         }
2374
2375         if (os_strcmp(var, "client_cert") == 0) {
2376                 os_free(cred->client_cert);
2377                 cred->client_cert = val;
2378                 return 0;
2379         }
2380
2381         if (os_strcmp(var, "private_key") == 0) {
2382                 os_free(cred->private_key);
2383                 cred->private_key = val;
2384                 return 0;
2385         }
2386
2387         if (os_strcmp(var, "private_key_passwd") == 0) {
2388                 os_free(cred->private_key_passwd);
2389                 cred->private_key_passwd = val;
2390                 return 0;
2391         }
2392
2393         if (os_strcmp(var, "imsi") == 0) {
2394                 os_free(cred->imsi);
2395                 cred->imsi = val;
2396                 return 0;
2397         }
2398
2399         if (os_strcmp(var, "milenage") == 0) {
2400                 os_free(cred->milenage);
2401                 cred->milenage = val;
2402                 return 0;
2403         }
2404
2405         if (os_strcmp(var, "domain") == 0) {
2406                 os_free(cred->domain);
2407                 cred->domain = val;
2408                 return 0;
2409         }
2410
2411         if (os_strcmp(var, "phase1") == 0) {
2412                 os_free(cred->phase1);
2413                 cred->phase1 = val;
2414                 return 0;
2415         }
2416
2417         if (os_strcmp(var, "phase2") == 0) {
2418                 os_free(cred->phase2);
2419                 cred->phase2 = val;
2420                 return 0;
2421         }
2422
2423         if (os_strcmp(var, "roaming_consortium") == 0) {
2424                 if (len < 3 || len > sizeof(cred->roaming_consortium)) {
2425                         wpa_printf(MSG_ERROR, "Line %d: invalid "
2426                                    "roaming_consortium length %d (3..15 "
2427                                    "expected)", line, (int) len);
2428                         os_free(val);
2429                         return -1;
2430                 }
2431                 os_memcpy(cred->roaming_consortium, val, len);
2432                 cred->roaming_consortium_len = len;
2433                 os_free(val);
2434                 return 0;
2435         }
2436
2437         if (os_strcmp(var, "excluded_ssid") == 0) {
2438                 struct excluded_ssid *e;
2439
2440                 if (len > MAX_SSID_LEN) {
2441                         wpa_printf(MSG_ERROR, "Line %d: invalid "
2442                                    "excluded_ssid length %d", line, (int) len);
2443                         os_free(val);
2444                         return -1;
2445                 }
2446
2447                 e = os_realloc_array(cred->excluded_ssid,
2448                                      cred->num_excluded_ssid + 1,
2449                                      sizeof(struct excluded_ssid));
2450                 if (e == NULL) {
2451                         os_free(val);
2452                         return -1;
2453                 }
2454                 cred->excluded_ssid = e;
2455
2456                 e = &cred->excluded_ssid[cred->num_excluded_ssid++];
2457                 os_memcpy(e->ssid, val, len);
2458                 e->ssid_len = len;
2459
2460                 os_free(val);
2461
2462                 return 0;
2463         }
2464
2465         if (line) {
2466                 wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.",
2467                            line, var);
2468         }
2469
2470         os_free(val);
2471
2472         return -1;
2473 }
2474
2475
2476 struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id)
2477 {
2478         struct wpa_cred *cred;
2479
2480         cred = config->cred;
2481         while (cred) {
2482                 if (id == cred->id)
2483                         break;
2484                 cred = cred->next;
2485         }
2486
2487         return cred;
2488 }
2489
2490
2491 struct wpa_cred * wpa_config_add_cred(struct wpa_config *config)
2492 {
2493         int id;
2494         struct wpa_cred *cred, *last = NULL;
2495
2496         id = -1;
2497         cred = config->cred;
2498         while (cred) {
2499                 if (cred->id > id)
2500                         id = cred->id;
2501                 last = cred;
2502                 cred = cred->next;
2503         }
2504         id++;
2505
2506         cred = os_zalloc(sizeof(*cred));
2507         if (cred == NULL)
2508                 return NULL;
2509         cred->id = id;
2510         if (last)
2511                 last->next = cred;
2512         else
2513                 config->cred = cred;
2514
2515         return cred;
2516 }
2517
2518
2519 int wpa_config_remove_cred(struct wpa_config *config, int id)
2520 {
2521         struct wpa_cred *cred, *prev = NULL;
2522
2523         cred = config->cred;
2524         while (cred) {
2525                 if (id == cred->id)
2526                         break;
2527                 prev = cred;
2528                 cred = cred->next;
2529         }
2530
2531         if (cred == NULL)
2532                 return -1;
2533
2534         if (prev)
2535                 prev->next = cred->next;
2536         else
2537                 config->cred = cred->next;
2538
2539         wpa_config_free_cred(cred);
2540         return 0;
2541 }
2542
2543
2544 #ifndef CONFIG_NO_CONFIG_BLOBS
2545 /**
2546  * wpa_config_get_blob - Get a named configuration blob
2547  * @config: Configuration data from wpa_config_read()
2548  * @name: Name of the blob
2549  * Returns: Pointer to blob data or %NULL if not found
2550  */
2551 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
2552                                                    const char *name)
2553 {
2554         struct wpa_config_blob *blob = config->blobs;
2555
2556         while (blob) {
2557                 if (os_strcmp(blob->name, name) == 0)
2558                         return blob;
2559                 blob = blob->next;
2560         }
2561         return NULL;
2562 }
2563
2564
2565 /**
2566  * wpa_config_set_blob - Set or add a named configuration blob
2567  * @config: Configuration data from wpa_config_read()
2568  * @blob: New value for the blob
2569  *
2570  * Adds a new configuration blob or replaces the current value of an existing
2571  * blob.
2572  */
2573 void wpa_config_set_blob(struct wpa_config *config,
2574                          struct wpa_config_blob *blob)
2575 {
2576         wpa_config_remove_blob(config, blob->name);
2577         blob->next = config->blobs;
2578         config->blobs = blob;
2579 }
2580
2581
2582 /**
2583  * wpa_config_free_blob - Free blob data
2584  * @blob: Pointer to blob to be freed
2585  */
2586 void wpa_config_free_blob(struct wpa_config_blob *blob)
2587 {
2588         if (blob) {
2589                 os_free(blob->name);
2590                 os_free(blob->data);
2591                 os_free(blob);
2592         }
2593 }
2594
2595
2596 /**
2597  * wpa_config_remove_blob - Remove a named configuration blob
2598  * @config: Configuration data from wpa_config_read()
2599  * @name: Name of the blob to remove
2600  * Returns: 0 if blob was removed or -1 if blob was not found
2601  */
2602 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
2603 {
2604         struct wpa_config_blob *pos = config->blobs, *prev = NULL;
2605
2606         while (pos) {
2607                 if (os_strcmp(pos->name, name) == 0) {
2608                         if (prev)
2609                                 prev->next = pos->next;
2610                         else
2611                                 config->blobs = pos->next;
2612                         wpa_config_free_blob(pos);
2613                         return 0;
2614                 }
2615                 prev = pos;
2616                 pos = pos->next;
2617         }
2618
2619         return -1;
2620 }
2621 #endif /* CONFIG_NO_CONFIG_BLOBS */
2622
2623
2624 /**
2625  * wpa_config_alloc_empty - Allocate an empty configuration
2626  * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
2627  * socket
2628  * @driver_param: Driver parameters
2629  * Returns: Pointer to allocated configuration data or %NULL on failure
2630  */
2631 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
2632                                            const char *driver_param)
2633 {
2634         struct wpa_config *config;
2635         const int aCWmin = 4, aCWmax = 10;
2636         const struct hostapd_wmm_ac_params ac_bk =
2637                 { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
2638         const struct hostapd_wmm_ac_params ac_be =
2639                 { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
2640         const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
2641                 { aCWmin - 1, aCWmin, 2, 3000 / 32, 0 };
2642         const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
2643                 { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 };
2644
2645         config = os_zalloc(sizeof(*config));
2646         if (config == NULL)
2647                 return NULL;
2648         config->eapol_version = DEFAULT_EAPOL_VERSION;
2649         config->ap_scan = DEFAULT_AP_SCAN;
2650         config->fast_reauth = DEFAULT_FAST_REAUTH;
2651         config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
2652         config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
2653         config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY;
2654         config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
2655         config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
2656         config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
2657         config->max_num_sta = DEFAULT_MAX_NUM_STA;
2658         config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
2659         config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ;
2660         config->wmm_ac_params[0] = ac_be;
2661         config->wmm_ac_params[1] = ac_bk;
2662         config->wmm_ac_params[2] = ac_vi;
2663         config->wmm_ac_params[3] = ac_vo;
2664
2665         if (ctrl_interface)
2666                 config->ctrl_interface = os_strdup(ctrl_interface);
2667         if (driver_param)
2668                 config->driver_param = os_strdup(driver_param);
2669
2670         return config;
2671 }
2672
2673
2674 #ifndef CONFIG_NO_STDOUT_DEBUG
2675 /**
2676  * wpa_config_debug_dump_networks - Debug dump of configured networks
2677  * @config: Configuration data from wpa_config_read()
2678  */
2679 void wpa_config_debug_dump_networks(struct wpa_config *config)
2680 {
2681         int prio;
2682         struct wpa_ssid *ssid;
2683
2684         for (prio = 0; prio < config->num_prio; prio++) {
2685                 ssid = config->pssid[prio];
2686                 wpa_printf(MSG_DEBUG, "Priority group %d",
2687                            ssid->priority);
2688                 while (ssid) {
2689                         wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
2690                                    ssid->id,
2691                                    wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2692                         ssid = ssid->pnext;
2693                 }
2694         }
2695 }
2696 #endif /* CONFIG_NO_STDOUT_DEBUG */
2697
2698
2699 struct global_parse_data {
2700         char *name;
2701         int (*parser)(const struct global_parse_data *data,
2702                       struct wpa_config *config, int line, const char *value);
2703         void *param1, *param2, *param3;
2704         unsigned int changed_flag;
2705 };
2706
2707
2708 static int wpa_global_config_parse_int(const struct global_parse_data *data,
2709                                        struct wpa_config *config, int line,
2710                                        const char *pos)
2711 {
2712         int val, *dst;
2713         char *end;
2714
2715         dst = (int *) (((u8 *) config) + (long) data->param1);
2716         val = strtol(pos, &end, 0);
2717         if (*end) {
2718                 wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"",
2719                            line, pos);
2720                 return -1;
2721         }
2722         *dst = val;
2723
2724         wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
2725
2726         if (data->param2 && *dst < (long) data->param2) {
2727                 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
2728                            "min_value=%ld)", line, data->name, *dst,
2729                            (long) data->param2);
2730                 *dst = (long) data->param2;
2731                 return -1;
2732         }
2733
2734         if (data->param3 && *dst > (long) data->param3) {
2735                 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
2736                            "max_value=%ld)", line, data->name, *dst,
2737                            (long) data->param3);
2738                 *dst = (long) data->param3;
2739                 return -1;
2740         }
2741
2742         return 0;
2743 }
2744
2745
2746 static int wpa_global_config_parse_str(const struct global_parse_data *data,
2747                                        struct wpa_config *config, int line,
2748                                        const char *pos)
2749 {
2750         size_t len;
2751         char **dst, *tmp;
2752
2753         len = os_strlen(pos);
2754         if (data->param2 && len < (size_t) data->param2) {
2755                 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
2756                            "min_len=%ld)", line, data->name,
2757                            (unsigned long) len, (long) data->param2);
2758                 return -1;
2759         }
2760
2761         if (data->param3 && len > (size_t) data->param3) {
2762                 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
2763                            "max_len=%ld)", line, data->name,
2764                            (unsigned long) len, (long) data->param3);
2765                 return -1;
2766         }
2767
2768         tmp = os_strdup(pos);
2769         if (tmp == NULL)
2770                 return -1;
2771
2772         dst = (char **) (((u8 *) config) + (long) data->param1);
2773         os_free(*dst);
2774         *dst = tmp;
2775         wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
2776
2777         return 0;
2778 }
2779
2780
2781 static int wpa_global_config_parse_bin(const struct global_parse_data *data,
2782                                        struct wpa_config *config, int line,
2783                                        const char *pos)
2784 {
2785         size_t len;
2786         struct wpabuf **dst, *tmp;
2787
2788         len = os_strlen(pos);
2789         if (len & 0x01)
2790                 return -1;
2791
2792         tmp = wpabuf_alloc(len / 2);
2793         if (tmp == NULL)
2794                 return -1;
2795
2796         if (hexstr2bin(pos, wpabuf_put(tmp, len / 2), len / 2)) {
2797                 wpabuf_free(tmp);
2798                 return -1;
2799         }
2800
2801         dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1);
2802         wpabuf_free(*dst);
2803         *dst = tmp;
2804         wpa_printf(MSG_DEBUG, "%s", data->name);
2805
2806         return 0;
2807 }
2808
2809
2810 static int wpa_config_process_freq_list(const struct global_parse_data *data,
2811                                         struct wpa_config *config, int line,
2812                                         const char *value)
2813 {
2814         int *freqs;
2815
2816         freqs = wpa_config_parse_int_array(value);
2817         if (freqs == NULL)
2818                 return -1;
2819         if (freqs[0] == 0) {
2820                 os_free(freqs);
2821                 freqs = NULL;
2822         }
2823         os_free(config->freq_list);
2824         config->freq_list = freqs;
2825         return 0;
2826 }
2827
2828
2829 static int wpa_config_process_country(const struct global_parse_data *data,
2830                                       struct wpa_config *config, int line,
2831                                       const char *pos)
2832 {
2833         if (!pos[0] || !pos[1]) {
2834                 wpa_printf(MSG_DEBUG, "Invalid country set");
2835                 return -1;
2836         }
2837         config->country[0] = pos[0];
2838         config->country[1] = pos[1];
2839         wpa_printf(MSG_DEBUG, "country='%c%c'",
2840                    config->country[0], config->country[1]);
2841         return 0;
2842 }
2843
2844
2845 static int wpa_config_process_load_dynamic_eap(
2846         const struct global_parse_data *data, struct wpa_config *config,
2847         int line, const char *so)
2848 {
2849         int ret;
2850         wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
2851         ret = eap_peer_method_load(so);
2852         if (ret == -2) {
2853                 wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
2854                            "reloading.");
2855         } else if (ret) {
2856                 wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
2857                            "method '%s'.", line, so);
2858                 return -1;
2859         }
2860
2861         return 0;
2862 }
2863
2864
2865 #ifdef CONFIG_WPS
2866
2867 static int wpa_config_process_uuid(const struct global_parse_data *data,
2868                                    struct wpa_config *config, int line,
2869                                    const char *pos)
2870 {
2871         char buf[40];
2872         if (uuid_str2bin(pos, config->uuid)) {
2873                 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
2874                 return -1;
2875         }
2876         uuid_bin2str(config->uuid, buf, sizeof(buf));
2877         wpa_printf(MSG_DEBUG, "uuid=%s", buf);
2878         return 0;
2879 }
2880
2881
2882 static int wpa_config_process_device_type(
2883         const struct global_parse_data *data,
2884         struct wpa_config *config, int line, const char *pos)
2885 {
2886         return wps_dev_type_str2bin(pos, config->device_type);
2887 }
2888
2889
2890 static int wpa_config_process_os_version(const struct global_parse_data *data,
2891                                          struct wpa_config *config, int line,
2892                                          const char *pos)
2893 {
2894         if (hexstr2bin(pos, config->os_version, 4)) {
2895                 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
2896                 return -1;
2897         }
2898         wpa_printf(MSG_DEBUG, "os_version=%08x",
2899                    WPA_GET_BE32(config->os_version));
2900         return 0;
2901 }
2902
2903
2904 static int wpa_config_process_wps_vendor_ext_m1(
2905         const struct global_parse_data *data,
2906         struct wpa_config *config, int line, const char *pos)
2907 {
2908         struct wpabuf *tmp;
2909         int len = os_strlen(pos) / 2;
2910         u8 *p;
2911
2912         if (!len) {
2913                 wpa_printf(MSG_ERROR, "Line %d: "
2914                            "invalid wps_vendor_ext_m1", line);
2915                 return -1;
2916         }
2917
2918         tmp = wpabuf_alloc(len);
2919         if (tmp) {
2920                 p = wpabuf_put(tmp, len);
2921
2922                 if (hexstr2bin(pos, p, len)) {
2923                         wpa_printf(MSG_ERROR, "Line %d: "
2924                                    "invalid wps_vendor_ext_m1", line);
2925                         wpabuf_free(tmp);
2926                         return -1;
2927                 }
2928
2929                 wpabuf_free(config->wps_vendor_ext_m1);
2930                 config->wps_vendor_ext_m1 = tmp;
2931         } else {
2932                 wpa_printf(MSG_ERROR, "Can not allocate "
2933                            "memory for wps_vendor_ext_m1");
2934                 return -1;
2935         }
2936
2937         return 0;
2938 }
2939
2940 #endif /* CONFIG_WPS */
2941
2942 #ifdef CONFIG_P2P
2943 static int wpa_config_process_sec_device_type(
2944         const struct global_parse_data *data,
2945         struct wpa_config *config, int line, const char *pos)
2946 {
2947         int idx;
2948
2949         if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) {
2950                 wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type "
2951                            "items", line);
2952                 return -1;
2953         }
2954
2955         idx = config->num_sec_device_types;
2956
2957         if (wps_dev_type_str2bin(pos, config->sec_device_type[idx]))
2958                 return -1;
2959
2960         config->num_sec_device_types++;
2961         return 0;
2962 }
2963
2964
2965 static int wpa_config_process_p2p_pref_chan(
2966         const struct global_parse_data *data,
2967         struct wpa_config *config, int line, const char *pos)
2968 {
2969         struct p2p_channel *pref = NULL, *n;
2970         unsigned int num = 0;
2971         const char *pos2;
2972         u8 op_class, chan;
2973
2974         /* format: class:chan,class:chan,... */
2975
2976         while (*pos) {
2977                 op_class = atoi(pos);
2978                 pos2 = os_strchr(pos, ':');
2979                 if (pos2 == NULL)
2980                         goto fail;
2981                 pos2++;
2982                 chan = atoi(pos2);
2983
2984                 n = os_realloc_array(pref, num + 1,
2985                                      sizeof(struct p2p_channel));
2986                 if (n == NULL)
2987                         goto fail;
2988                 pref = n;
2989                 pref[num].op_class = op_class;
2990                 pref[num].chan = chan;
2991                 num++;
2992
2993                 pos = os_strchr(pos2, ',');
2994                 if (pos == NULL)
2995                         break;
2996                 pos++;
2997         }
2998
2999         os_free(config->p2p_pref_chan);
3000         config->p2p_pref_chan = pref;
3001         config->num_p2p_pref_chan = num;
3002         wpa_hexdump(MSG_DEBUG, "P2P: Preferred class/channel pairs",
3003                     (u8 *) config->p2p_pref_chan,
3004                     config->num_p2p_pref_chan * sizeof(struct p2p_channel));
3005
3006         return 0;
3007
3008 fail:
3009         os_free(pref);
3010         wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_pref_chan list", line);
3011         return -1;
3012 }
3013 #endif /* CONFIG_P2P */
3014
3015
3016 static int wpa_config_process_hessid(
3017         const struct global_parse_data *data,
3018         struct wpa_config *config, int line, const char *pos)
3019 {
3020         if (hwaddr_aton2(pos, config->hessid) < 0) {
3021                 wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'",
3022                            line, pos);
3023                 return -1;
3024         }
3025
3026         return 0;
3027 }
3028
3029
3030 static int wpa_config_process_sae_groups(
3031         const struct global_parse_data *data,
3032         struct wpa_config *config, int line, const char *pos)
3033 {
3034         int *groups = wpa_config_parse_int_array(pos);
3035         if (groups == NULL) {
3036                 wpa_printf(MSG_ERROR, "Line %d: Invalid sae_groups '%s'",
3037                            line, pos);
3038                 return -1;
3039         }
3040
3041         os_free(config->sae_groups);
3042         config->sae_groups = groups;
3043
3044         return 0;
3045 }
3046
3047
3048 static int wpa_config_process_ap_vendor_elements(
3049         const struct global_parse_data *data,
3050         struct wpa_config *config, int line, const char *pos)
3051 {
3052         struct wpabuf *tmp;
3053         int len = os_strlen(pos) / 2;
3054         u8 *p;
3055
3056         if (!len) {
3057                 wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements",
3058                            line);
3059                 return -1;
3060         }
3061
3062         tmp = wpabuf_alloc(len);
3063         if (tmp) {
3064                 p = wpabuf_put(tmp, len);
3065
3066                 if (hexstr2bin(pos, p, len)) {
3067                         wpa_printf(MSG_ERROR, "Line %d: invalid "
3068                                    "ap_vendor_elements", line);
3069                         wpabuf_free(tmp);
3070                         return -1;
3071                 }
3072
3073                 wpabuf_free(config->ap_vendor_elements);
3074                 config->ap_vendor_elements = tmp;
3075         } else {
3076                 wpa_printf(MSG_ERROR, "Cannot allocate memory for "
3077                            "ap_vendor_elements");
3078                 return -1;
3079         }
3080
3081         return 0;
3082 }
3083
3084
3085 #ifdef CONFIG_CTRL_IFACE
3086 static int wpa_config_process_no_ctrl_interface(
3087         const struct global_parse_data *data,
3088         struct wpa_config *config, int line, const char *pos)
3089 {
3090         wpa_printf(MSG_DEBUG, "no_ctrl_interface -> ctrl_interface=NULL");
3091         os_free(config->ctrl_interface);
3092         config->ctrl_interface = NULL;
3093         return 0;
3094 }
3095 #endif /* CONFIG_CTRL_IFACE */
3096
3097
3098 #ifdef OFFSET
3099 #undef OFFSET
3100 #endif /* OFFSET */
3101 /* OFFSET: Get offset of a variable within the wpa_config structure */
3102 #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
3103
3104 #define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
3105 #define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
3106 #define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
3107 #define INT(f) _INT(f), NULL, NULL
3108 #define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
3109 #define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
3110 #define STR(f) _STR(f), NULL, NULL
3111 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
3112 #define BIN(f) #f, wpa_global_config_parse_bin, OFFSET(f), NULL, NULL
3113
3114 static const struct global_parse_data global_fields[] = {
3115 #ifdef CONFIG_CTRL_IFACE
3116         { STR(ctrl_interface), 0 },
3117         { FUNC_NO_VAR(no_ctrl_interface), 0 },
3118         { STR(ctrl_interface_group), 0 } /* deprecated */,
3119 #endif /* CONFIG_CTRL_IFACE */
3120         { INT_RANGE(eapol_version, 1, 2), 0 },
3121         { INT(ap_scan), 0 },
3122         { INT(disable_scan_offload), 0 },
3123         { INT(fast_reauth), 0 },
3124         { STR(opensc_engine_path), 0 },
3125         { STR(pkcs11_engine_path), 0 },
3126         { STR(pkcs11_module_path), 0 },
3127         { STR(pcsc_reader), 0 },
3128         { STR(pcsc_pin), 0 },
3129         { STR(driver_param), 0 },
3130         { INT(dot11RSNAConfigPMKLifetime), 0 },
3131         { INT(dot11RSNAConfigPMKReauthThreshold), 0 },
3132         { INT(dot11RSNAConfigSATimeout), 0 },
3133 #ifndef CONFIG_NO_CONFIG_WRITE
3134         { INT(update_config), 0 },
3135 #endif /* CONFIG_NO_CONFIG_WRITE */
3136         { FUNC_NO_VAR(load_dynamic_eap), 0 },
3137 #ifdef CONFIG_WPS
3138         { FUNC(uuid), CFG_CHANGED_UUID },
3139         { STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME },
3140         { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
3141         { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
3142         { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
3143         { STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING },
3144         { FUNC(device_type), CFG_CHANGED_DEVICE_TYPE },
3145         { FUNC(os_version), CFG_CHANGED_OS_VERSION },
3146         { STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
3147         { INT_RANGE(wps_cred_processing, 0, 2), 0 },
3148         { FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION },
3149 #endif /* CONFIG_WPS */
3150 #ifdef CONFIG_P2P
3151         { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
3152         { INT(p2p_listen_reg_class), 0 },
3153         { INT(p2p_listen_channel), 0 },
3154         { INT(p2p_oper_reg_class), CFG_CHANGED_P2P_OPER_CHANNEL },
3155         { INT(p2p_oper_channel), CFG_CHANGED_P2P_OPER_CHANNEL },
3156         { INT_RANGE(p2p_go_intent, 0, 15), 0 },
3157         { STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
3158         { INT_RANGE(persistent_reconnect, 0, 1), 0 },
3159         { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
3160         { INT(p2p_group_idle), 0 },
3161         { FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN },
3162         { INT(p2p_go_ht40), 0 },
3163         { INT(p2p_disabled), 0 },
3164         { INT(p2p_no_group_iface), 0 },
3165         { INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 },
3166 #endif /* CONFIG_P2P */
3167         { FUNC(country), CFG_CHANGED_COUNTRY },
3168         { INT(bss_max_count), 0 },
3169         { INT(bss_expiration_age), 0 },
3170         { INT(bss_expiration_scan_count), 0 },
3171         { INT_RANGE(filter_ssids, 0, 1), 0 },
3172         { INT_RANGE(filter_rssi, -100, 0), 0 },
3173         { INT(max_num_sta), 0 },
3174         { INT_RANGE(disassoc_low_ack, 0, 1), 0 },
3175 #ifdef CONFIG_HS20
3176         { INT_RANGE(hs20, 0, 1), 0 },
3177 #endif /* CONFIG_HS20 */
3178         { INT_RANGE(interworking, 0, 1), 0 },
3179         { FUNC(hessid), 0 },
3180         { INT_RANGE(access_network_type, 0, 15), 0 },
3181         { INT_RANGE(pbc_in_m1, 0, 1), 0 },
3182         { STR(autoscan), 0 },
3183         { INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff),
3184           CFG_CHANGED_NFC_PASSWORD_TOKEN },
3185         { BIN(wps_nfc_dh_pubkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
3186         { BIN(wps_nfc_dh_privkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
3187         { BIN(wps_nfc_dev_pw), CFG_CHANGED_NFC_PASSWORD_TOKEN },
3188         { STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND },
3189         { INT(p2p_go_max_inactivity), 0 },
3190         { INT_RANGE(auto_interworking, 0, 1), 0 },
3191         { INT(okc), 0 },
3192         { INT(pmf), 0 },
3193         { FUNC(sae_groups), 0 },
3194         { INT(dtim_period), 0 },
3195         { INT(beacon_int), 0 },
3196         { FUNC(ap_vendor_elements), 0 },
3197         { INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
3198         { FUNC(freq_list), 0 },
3199         { INT(scan_cur_freq), 0 },
3200         { INT(sched_scan_interval), 0 },
3201 };
3202
3203 #undef FUNC
3204 #undef _INT
3205 #undef INT
3206 #undef INT_RANGE
3207 #undef _STR
3208 #undef STR
3209 #undef STR_RANGE
3210 #undef BIN
3211 #define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0]))
3212
3213
3214 int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
3215 {
3216         size_t i;
3217         int ret = 0;
3218
3219         for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
3220                 const struct global_parse_data *field = &global_fields[i];
3221                 size_t flen = os_strlen(field->name);
3222                 if (os_strncmp(pos, field->name, flen) != 0 ||
3223                     pos[flen] != '=')
3224                         continue;
3225
3226                 if (field->parser(field, config, line, pos + flen + 1)) {
3227                         wpa_printf(MSG_ERROR, "Line %d: failed to "
3228                                    "parse '%s'.", line, pos);
3229                         ret = -1;
3230                 }
3231                 if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN)
3232                         config->wps_nfc_pw_from_config = 1;
3233                 config->changed_parameters |= field->changed_flag;
3234                 break;
3235         }
3236         if (i == NUM_GLOBAL_FIELDS) {
3237 #ifdef CONFIG_AP
3238                 if (os_strncmp(pos, "wmm_ac_", 7) == 0) {
3239                         char *tmp = os_strchr(pos, '=');
3240                         if (tmp == NULL) {
3241                                 if (line < 0)
3242                                         return -1;
3243                                 wpa_printf(MSG_ERROR, "Line %d: invalid line "
3244                                            "'%s'", line, pos);
3245                                 return -1;
3246                         }
3247                         *tmp++ = '\0';
3248                         if (hostapd_config_wmm_ac(config->wmm_ac_params, pos,
3249                                                   tmp)) {
3250                                 wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
3251                                            "AC item", line);
3252                                 return -1;
3253                         }
3254                 }
3255 #endif /* CONFIG_AP */
3256                 if (line < 0)
3257                         return -1;
3258                 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
3259                            line, pos);
3260                 ret = -1;
3261         }
3262
3263         return ret;
3264 }