e0703573747a2e8d3e53b1e06b7d1fe105f43289
[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 "utils/ip_addr.h"
14 #include "crypto/sha1.h"
15 #include "rsn_supp/wpa.h"
16 #include "eap_peer/eap.h"
17 #include "p2p/p2p.h"
18 #include "config.h"
19
20
21 #if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE)
22 #define NO_CONFIG_WRITE
23 #endif
24
25 /*
26  * Structure for network configuration parsing. This data is used to implement
27  * a generic parser for each network block variable. The table of configuration
28  * variables is defined below in this file (ssid_fields[]).
29  */
30 struct parse_data {
31         /* Configuration variable name */
32         char *name;
33
34         /* Parser function for this variable */
35         int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
36                       int line, const char *value);
37
38 #ifndef NO_CONFIG_WRITE
39         /* Writer function (i.e., to get the variable in text format from
40          * internal presentation). */
41         char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
42 #endif /* NO_CONFIG_WRITE */
43
44         /* Variable specific parameters for the parser. */
45         void *param1, *param2, *param3, *param4;
46
47         /* 0 = this variable can be included in debug output and ctrl_iface
48          * 1 = this variable contains key/private data and it must not be
49          *     included in debug output unless explicitly requested. In
50          *     addition, this variable will not be readable through the
51          *     ctrl_iface.
52          */
53         int key_data;
54 };
55
56
57 static int wpa_config_parse_str(const struct parse_data *data,
58                                 struct wpa_ssid *ssid,
59                                 int line, const char *value)
60 {
61         size_t res_len, *dst_len;
62         char **dst, *tmp;
63
64         if (os_strcmp(value, "NULL") == 0) {
65                 wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
66                            data->name);
67                 tmp = NULL;
68                 res_len = 0;
69                 goto set;
70         }
71
72         tmp = wpa_config_parse_string(value, &res_len);
73         if (tmp == NULL) {
74                 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
75                            line, data->name,
76                            data->key_data ? "[KEY DATA REMOVED]" : value);
77                 return -1;
78         }
79
80         if (data->key_data) {
81                 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
82                                       (u8 *) tmp, res_len);
83         } else {
84                 wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
85                                   (u8 *) tmp, res_len);
86         }
87
88         if (data->param3 && res_len < (size_t) data->param3) {
89                 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
90                            "min_len=%ld)", line, data->name,
91                            (unsigned long) res_len, (long) data->param3);
92                 os_free(tmp);
93                 return -1;
94         }
95
96         if (data->param4 && res_len > (size_t) data->param4) {
97                 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
98                            "max_len=%ld)", line, data->name,
99                            (unsigned long) res_len, (long) data->param4);
100                 os_free(tmp);
101                 return -1;
102         }
103
104 set:
105         dst = (char **) (((u8 *) ssid) + (long) data->param1);
106         dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
107         os_free(*dst);
108         *dst = tmp;
109         if (data->param2)
110                 *dst_len = res_len;
111
112         return 0;
113 }
114
115
116 #ifndef NO_CONFIG_WRITE
117 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
118 {
119         char *buf;
120
121         buf = os_malloc(len + 3);
122         if (buf == NULL)
123                 return NULL;
124         buf[0] = '"';
125         os_memcpy(buf + 1, value, len);
126         buf[len + 1] = '"';
127         buf[len + 2] = '\0';
128
129         return buf;
130 }
131
132
133 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
134 {
135         char *buf;
136
137         buf = os_zalloc(2 * len + 1);
138         if (buf == NULL)
139                 return NULL;
140         wpa_snprintf_hex(buf, 2 * len + 1, value, len);
141
142         return buf;
143 }
144
145
146 static char * wpa_config_write_string(const u8 *value, size_t len)
147 {
148         if (value == NULL)
149                 return NULL;
150
151         if (is_hex(value, len))
152                 return wpa_config_write_string_hex(value, len);
153         else
154                 return wpa_config_write_string_ascii(value, len);
155 }
156
157
158 static char * wpa_config_write_str(const struct parse_data *data,
159                                    struct wpa_ssid *ssid)
160 {
161         size_t len;
162         char **src;
163
164         src = (char **) (((u8 *) ssid) + (long) data->param1);
165         if (*src == NULL)
166                 return NULL;
167
168         if (data->param2)
169                 len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
170         else
171                 len = os_strlen(*src);
172
173         return wpa_config_write_string((const u8 *) *src, len);
174 }
175 #endif /* NO_CONFIG_WRITE */
176
177
178 static int wpa_config_parse_int(const struct parse_data *data,
179                                 struct wpa_ssid *ssid,
180                                 int line, const char *value)
181 {
182         int val, *dst;
183         char *end;
184
185         dst = (int *) (((u8 *) ssid) + (long) data->param1);
186         val = strtol(value, &end, 0);
187         if (*end) {
188                 wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"",
189                            line, value);
190                 return -1;
191         }
192         *dst = val;
193         wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
194
195         if (data->param3 && *dst < (long) data->param3) {
196                 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
197                            "min_value=%ld)", line, data->name, *dst,
198                            (long) data->param3);
199                 *dst = (long) data->param3;
200                 return -1;
201         }
202
203         if (data->param4 && *dst > (long) data->param4) {
204                 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
205                            "max_value=%ld)", line, data->name, *dst,
206                            (long) data->param4);
207                 *dst = (long) data->param4;
208                 return -1;
209         }
210
211         return 0;
212 }
213
214
215 #ifndef NO_CONFIG_WRITE
216 static char * wpa_config_write_int(const struct parse_data *data,
217                                    struct wpa_ssid *ssid)
218 {
219         int *src, res;
220         char *value;
221
222         src = (int *) (((u8 *) ssid) + (long) data->param1);
223
224         value = os_malloc(20);
225         if (value == NULL)
226                 return NULL;
227         res = os_snprintf(value, 20, "%d", *src);
228         if (os_snprintf_error(20, res)) {
229                 os_free(value);
230                 return NULL;
231         }
232         value[20 - 1] = '\0';
233         return value;
234 }
235 #endif /* NO_CONFIG_WRITE */
236
237
238 static int wpa_config_parse_addr_list(const struct parse_data *data,
239                                       int line, const char *value,
240                                       u8 **list, size_t *num, char *name,
241                                       u8 abort_on_error)
242 {
243         const char *pos;
244         u8 *buf, *n, addr[ETH_ALEN];
245         size_t count;
246
247         buf = NULL;
248         count = 0;
249
250         pos = value;
251         while (pos && *pos) {
252                 while (*pos == ' ')
253                         pos++;
254
255                 if (hwaddr_aton(pos, addr)) {
256                         if (abort_on_error || count == 0) {
257                                 wpa_printf(MSG_ERROR,
258                                            "Line %d: Invalid %s address '%s'",
259                                            line, name, value);
260                                 os_free(buf);
261                                 return -1;
262                         }
263                         /* continue anyway since this could have been from a
264                          * truncated configuration file line */
265                         wpa_printf(MSG_INFO,
266                                    "Line %d: Ignore likely truncated %s address '%s'",
267                                    line, name, pos);
268                 } else {
269                         n = os_realloc_array(buf, count + 1, ETH_ALEN);
270                         if (n == NULL) {
271                                 os_free(buf);
272                                 return -1;
273                         }
274                         buf = n;
275                         os_memmove(buf + ETH_ALEN, buf, count * ETH_ALEN);
276                         os_memcpy(buf, addr, ETH_ALEN);
277                         count++;
278                         wpa_hexdump(MSG_MSGDUMP, name, addr, ETH_ALEN);
279                 }
280
281                 pos = os_strchr(pos, ' ');
282         }
283
284         os_free(*list);
285         *list = buf;
286         *num = count;
287
288         return 0;
289 }
290
291
292 #ifndef NO_CONFIG_WRITE
293 static char * wpa_config_write_addr_list(const struct parse_data *data,
294                                          const u8 *list, size_t num, char *name)
295 {
296         char *value, *end, *pos;
297         int res;
298         size_t i;
299
300         if (list == NULL || num == 0)
301                 return NULL;
302
303         value = os_malloc(20 * num);
304         if (value == NULL)
305                 return NULL;
306         pos = value;
307         end = value + 20 * num;
308
309         for (i = num; i > 0; i--) {
310                 res = os_snprintf(pos, end - pos, MACSTR " ",
311                                   MAC2STR(list + (i - 1) * ETH_ALEN));
312                 if (os_snprintf_error(end - pos, res)) {
313                         os_free(value);
314                         return NULL;
315                 }
316                 pos += res;
317         }
318
319         if (pos > value)
320                 pos[-1] = '\0';
321
322         return value;
323 }
324 #endif /* NO_CONFIG_WRITE */
325
326 static int wpa_config_parse_bssid(const struct parse_data *data,
327                                   struct wpa_ssid *ssid, int line,
328                                   const char *value)
329 {
330         if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
331             os_strcmp(value, "any") == 0) {
332                 ssid->bssid_set = 0;
333                 wpa_printf(MSG_MSGDUMP, "BSSID any");
334                 return 0;
335         }
336         if (hwaddr_aton(value, ssid->bssid)) {
337                 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
338                            line, value);
339                 return -1;
340         }
341         ssid->bssid_set = 1;
342         wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
343         return 0;
344 }
345
346
347 #ifndef NO_CONFIG_WRITE
348 static char * wpa_config_write_bssid(const struct parse_data *data,
349                                      struct wpa_ssid *ssid)
350 {
351         char *value;
352         int res;
353
354         if (!ssid->bssid_set)
355                 return NULL;
356
357         value = os_malloc(20);
358         if (value == NULL)
359                 return NULL;
360         res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
361         if (os_snprintf_error(20, res)) {
362                 os_free(value);
363                 return NULL;
364         }
365         value[20 - 1] = '\0';
366         return value;
367 }
368 #endif /* NO_CONFIG_WRITE */
369
370
371 static int wpa_config_parse_psk(const struct parse_data *data,
372                                 struct wpa_ssid *ssid, int line,
373                                 const char *value)
374 {
375 #ifdef CONFIG_EXT_PASSWORD
376         if (os_strncmp(value, "ext:", 4) == 0) {
377                 str_clear_free(ssid->passphrase);
378                 ssid->passphrase = NULL;
379                 ssid->psk_set = 0;
380                 os_free(ssid->ext_psk);
381                 ssid->ext_psk = os_strdup(value + 4);
382                 if (ssid->ext_psk == NULL)
383                         return -1;
384                 wpa_printf(MSG_DEBUG, "PSK: External password '%s'",
385                            ssid->ext_psk);
386                 return 0;
387         }
388 #endif /* CONFIG_EXT_PASSWORD */
389
390         if (*value == '"') {
391 #ifndef CONFIG_NO_PBKDF2
392                 const char *pos;
393                 size_t len;
394
395                 value++;
396                 pos = os_strrchr(value, '"');
397                 if (pos)
398                         len = pos - value;
399                 else
400                         len = os_strlen(value);
401                 if (len < 8 || len > 63) {
402                         wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
403                                    "length %lu (expected: 8..63) '%s'.",
404                                    line, (unsigned long) len, value);
405                         return -1;
406                 }
407                 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
408                                       (u8 *) value, len);
409                 if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
410                     os_memcmp(ssid->passphrase, value, len) == 0)
411                         return 0;
412                 ssid->psk_set = 0;
413                 str_clear_free(ssid->passphrase);
414                 ssid->passphrase = dup_binstr(value, len);
415                 if (ssid->passphrase == NULL)
416                         return -1;
417                 return 0;
418 #else /* CONFIG_NO_PBKDF2 */
419                 wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
420                            "supported.", line);
421                 return -1;
422 #endif /* CONFIG_NO_PBKDF2 */
423         }
424
425         if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
426             value[PMK_LEN * 2] != '\0') {
427                 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
428                            line, value);
429                 return -1;
430         }
431
432         str_clear_free(ssid->passphrase);
433         ssid->passphrase = NULL;
434
435         ssid->psk_set = 1;
436         wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
437         return 0;
438 }
439
440
441 #ifndef NO_CONFIG_WRITE
442 static char * wpa_config_write_psk(const struct parse_data *data,
443                                    struct wpa_ssid *ssid)
444 {
445 #ifdef CONFIG_EXT_PASSWORD
446         if (ssid->ext_psk) {
447                 size_t len = 4 + os_strlen(ssid->ext_psk) + 1;
448                 char *buf = os_malloc(len);
449                 int res;
450
451                 if (buf == NULL)
452                         return NULL;
453                 res = os_snprintf(buf, len, "ext:%s", ssid->ext_psk);
454                 if (os_snprintf_error(len, res)) {
455                         os_free(buf);
456                         buf = NULL;
457                 }
458                 return buf;
459         }
460 #endif /* CONFIG_EXT_PASSWORD */
461
462         if (ssid->passphrase)
463                 return wpa_config_write_string_ascii(
464                         (const u8 *) ssid->passphrase,
465                         os_strlen(ssid->passphrase));
466
467         if (ssid->psk_set)
468                 return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
469
470         return NULL;
471 }
472 #endif /* NO_CONFIG_WRITE */
473
474
475 static int wpa_config_parse_proto(const struct parse_data *data,
476                                   struct wpa_ssid *ssid, int line,
477                                   const char *value)
478 {
479         int val = 0, last, errors = 0;
480         char *start, *end, *buf;
481
482         buf = os_strdup(value);
483         if (buf == NULL)
484                 return -1;
485         start = buf;
486
487         while (*start != '\0') {
488                 while (*start == ' ' || *start == '\t')
489                         start++;
490                 if (*start == '\0')
491                         break;
492                 end = start;
493                 while (*end != ' ' && *end != '\t' && *end != '\0')
494                         end++;
495                 last = *end == '\0';
496                 *end = '\0';
497                 if (os_strcmp(start, "WPA") == 0)
498                         val |= WPA_PROTO_WPA;
499                 else if (os_strcmp(start, "RSN") == 0 ||
500                          os_strcmp(start, "WPA2") == 0)
501                         val |= WPA_PROTO_RSN;
502                 else if (os_strcmp(start, "OSEN") == 0)
503                         val |= WPA_PROTO_OSEN;
504                 else {
505                         wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
506                                    line, start);
507                         errors++;
508                 }
509
510                 if (last)
511                         break;
512                 start = end + 1;
513         }
514         os_free(buf);
515
516         if (val == 0) {
517                 wpa_printf(MSG_ERROR,
518                            "Line %d: no proto values configured.", line);
519                 errors++;
520         }
521
522         wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
523         ssid->proto = val;
524         return errors ? -1 : 0;
525 }
526
527
528 #ifndef NO_CONFIG_WRITE
529 static char * wpa_config_write_proto(const struct parse_data *data,
530                                      struct wpa_ssid *ssid)
531 {
532         int ret;
533         char *buf, *pos, *end;
534
535         pos = buf = os_zalloc(20);
536         if (buf == NULL)
537                 return NULL;
538         end = buf + 20;
539
540         if (ssid->proto & WPA_PROTO_WPA) {
541                 ret = os_snprintf(pos, end - pos, "%sWPA",
542                                   pos == buf ? "" : " ");
543                 if (os_snprintf_error(end - pos, ret))
544                         return buf;
545                 pos += ret;
546         }
547
548         if (ssid->proto & WPA_PROTO_RSN) {
549                 ret = os_snprintf(pos, end - pos, "%sRSN",
550                                   pos == buf ? "" : " ");
551                 if (os_snprintf_error(end - pos, ret))
552                         return buf;
553                 pos += ret;
554         }
555
556         if (ssid->proto & WPA_PROTO_OSEN) {
557                 ret = os_snprintf(pos, end - pos, "%sOSEN",
558                                   pos == buf ? "" : " ");
559                 if (os_snprintf_error(end - pos, ret))
560                         return buf;
561                 pos += ret;
562         }
563
564         if (pos == buf) {
565                 os_free(buf);
566                 buf = NULL;
567         }
568
569         return buf;
570 }
571 #endif /* NO_CONFIG_WRITE */
572
573
574 static int wpa_config_parse_key_mgmt(const struct parse_data *data,
575                                      struct wpa_ssid *ssid, int line,
576                                      const char *value)
577 {
578         int val = 0, last, errors = 0;
579         char *start, *end, *buf;
580
581         buf = os_strdup(value);
582         if (buf == NULL)
583                 return -1;
584         start = buf;
585
586         while (*start != '\0') {
587                 while (*start == ' ' || *start == '\t')
588                         start++;
589                 if (*start == '\0')
590                         break;
591                 end = start;
592                 while (*end != ' ' && *end != '\t' && *end != '\0')
593                         end++;
594                 last = *end == '\0';
595                 *end = '\0';
596                 if (os_strcmp(start, "WPA-PSK") == 0)
597                         val |= WPA_KEY_MGMT_PSK;
598                 else if (os_strcmp(start, "WPA-EAP") == 0)
599                         val |= WPA_KEY_MGMT_IEEE8021X;
600                 else if (os_strcmp(start, "IEEE8021X") == 0)
601                         val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
602                 else if (os_strcmp(start, "NONE") == 0)
603                         val |= WPA_KEY_MGMT_NONE;
604                 else if (os_strcmp(start, "WPA-NONE") == 0)
605                         val |= WPA_KEY_MGMT_WPA_NONE;
606 #ifdef CONFIG_IEEE80211R
607                 else if (os_strcmp(start, "FT-PSK") == 0)
608                         val |= WPA_KEY_MGMT_FT_PSK;
609                 else if (os_strcmp(start, "FT-EAP") == 0)
610                         val |= WPA_KEY_MGMT_FT_IEEE8021X;
611 #endif /* CONFIG_IEEE80211R */
612 #ifdef CONFIG_IEEE80211W
613                 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
614                         val |= WPA_KEY_MGMT_PSK_SHA256;
615                 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
616                         val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
617 #endif /* CONFIG_IEEE80211W */
618 #ifdef CONFIG_WPS
619                 else if (os_strcmp(start, "WPS") == 0)
620                         val |= WPA_KEY_MGMT_WPS;
621 #endif /* CONFIG_WPS */
622 #ifdef CONFIG_SAE
623                 else if (os_strcmp(start, "SAE") == 0)
624                         val |= WPA_KEY_MGMT_SAE;
625                 else if (os_strcmp(start, "FT-SAE") == 0)
626                         val |= WPA_KEY_MGMT_FT_SAE;
627 #endif /* CONFIG_SAE */
628 #ifdef CONFIG_HS20
629                 else if (os_strcmp(start, "OSEN") == 0)
630                         val |= WPA_KEY_MGMT_OSEN;
631 #endif /* CONFIG_HS20 */
632                 else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
633                         val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
634                 else {
635                         wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
636                                    line, start);
637                         errors++;
638                 }
639
640                 if (last)
641                         break;
642                 start = end + 1;
643         }
644         os_free(buf);
645
646         if (val == 0) {
647                 wpa_printf(MSG_ERROR,
648                            "Line %d: no key_mgmt values configured.", line);
649                 errors++;
650         }
651
652         wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
653         ssid->key_mgmt = val;
654         return errors ? -1 : 0;
655 }
656
657
658 #ifndef NO_CONFIG_WRITE
659 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
660                                         struct wpa_ssid *ssid)
661 {
662         char *buf, *pos, *end;
663         int ret;
664
665         pos = buf = os_zalloc(100);
666         if (buf == NULL)
667                 return NULL;
668         end = buf + 100;
669
670         if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
671                 ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
672                                   pos == buf ? "" : " ");
673                 if (os_snprintf_error(end - pos, ret)) {
674                         end[-1] = '\0';
675                         return buf;
676                 }
677                 pos += ret;
678         }
679
680         if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
681                 ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
682                                   pos == buf ? "" : " ");
683                 if (os_snprintf_error(end - pos, ret)) {
684                         end[-1] = '\0';
685                         return buf;
686                 }
687                 pos += ret;
688         }
689
690         if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
691                 ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
692                                   pos == buf ? "" : " ");
693                 if (os_snprintf_error(end - pos, ret)) {
694                         end[-1] = '\0';
695                         return buf;
696                 }
697                 pos += ret;
698         }
699
700         if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
701                 ret = os_snprintf(pos, end - pos, "%sNONE",
702                                   pos == buf ? "" : " ");
703                 if (os_snprintf_error(end - pos, ret)) {
704                         end[-1] = '\0';
705                         return buf;
706                 }
707                 pos += ret;
708         }
709
710         if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
711                 ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
712                                   pos == buf ? "" : " ");
713                 if (os_snprintf_error(end - pos, ret)) {
714                         end[-1] = '\0';
715                         return buf;
716                 }
717                 pos += ret;
718         }
719
720 #ifdef CONFIG_IEEE80211R
721         if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) {
722                 ret = os_snprintf(pos, end - pos, "%sFT-PSK",
723                                   pos == buf ? "" : " ");
724                 if (os_snprintf_error(end - pos, ret)) {
725                         end[-1] = '\0';
726                         return buf;
727                 }
728                 pos += ret;
729         }
730
731         if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
732                 ret = os_snprintf(pos, end - pos, "%sFT-EAP",
733                                   pos == buf ? "" : " ");
734                 if (os_snprintf_error(end - pos, ret)) {
735                         end[-1] = '\0';
736                         return buf;
737                 }
738                 pos += ret;
739         }
740 #endif /* CONFIG_IEEE80211R */
741
742 #ifdef CONFIG_IEEE80211W
743         if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
744                 ret = os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
745                                   pos == buf ? "" : " ");
746                 if (os_snprintf_error(end - pos, ret)) {
747                         end[-1] = '\0';
748                         return buf;
749                 }
750                 pos += ret;
751         }
752
753         if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
754                 ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
755                                   pos == buf ? "" : " ");
756                 if (os_snprintf_error(end - pos, ret)) {
757                         end[-1] = '\0';
758                         return buf;
759                 }
760                 pos += ret;
761         }
762 #endif /* CONFIG_IEEE80211W */
763
764 #ifdef CONFIG_WPS
765         if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
766                 ret = os_snprintf(pos, end - pos, "%sWPS",
767                                   pos == buf ? "" : " ");
768                 if (os_snprintf_error(end - pos, ret)) {
769                         end[-1] = '\0';
770                         return buf;
771                 }
772                 pos += ret;
773         }
774 #endif /* CONFIG_WPS */
775
776 #ifdef CONFIG_SAE
777         if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
778                 ret = os_snprintf(pos, end - pos, "%sSAE",
779                                   pos == buf ? "" : " ");
780                 if (os_snprintf_error(end - pos, ret)) {
781                         end[-1] = '\0';
782                         return buf;
783                 }
784                 pos += ret;
785         }
786
787         if (ssid->key_mgmt & WPA_KEY_MGMT_FT_SAE) {
788                 ret = os_snprintf(pos, end - pos, "%sFT-SAE",
789                                   pos == buf ? "" : " ");
790                 if (os_snprintf_error(end - pos, ret)) {
791                         end[-1] = '\0';
792                         return buf;
793                 }
794                 pos += ret;
795         }
796 #endif /* CONFIG_SAE */
797
798 #ifdef CONFIG_HS20
799         if (ssid->key_mgmt & WPA_KEY_MGMT_OSEN) {
800                 ret = os_snprintf(pos, end - pos, "%sOSEN",
801                                   pos == buf ? "" : " ");
802                 if (os_snprintf_error(end - pos, ret)) {
803                         end[-1] = '\0';
804                         return buf;
805                 }
806                 pos += ret;
807         }
808 #endif /* CONFIG_HS20 */
809
810         if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
811                 ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B",
812                                   pos == buf ? "" : " ");
813                 if (os_snprintf_error(end - pos, ret)) {
814                         end[-1] = '\0';
815                         return buf;
816                 }
817                 pos += ret;
818         }
819
820         if (pos == buf) {
821                 os_free(buf);
822                 buf = NULL;
823         }
824
825         return buf;
826 }
827 #endif /* NO_CONFIG_WRITE */
828
829
830 static int wpa_config_parse_cipher(int line, const char *value)
831 {
832         int val = wpa_parse_cipher(value);
833         if (val < 0) {
834                 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
835                            line, value);
836                 return -1;
837         }
838         if (val == 0) {
839                 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
840                            line);
841                 return -1;
842         }
843         return val;
844 }
845
846
847 #ifndef NO_CONFIG_WRITE
848 static char * wpa_config_write_cipher(int cipher)
849 {
850         char *buf = os_zalloc(50);
851         if (buf == NULL)
852                 return NULL;
853
854         if (wpa_write_ciphers(buf, buf + 50, cipher, " ") < 0) {
855                 os_free(buf);
856                 return NULL;
857         }
858
859         return buf;
860 }
861 #endif /* NO_CONFIG_WRITE */
862
863
864 static int wpa_config_parse_pairwise(const struct parse_data *data,
865                                      struct wpa_ssid *ssid, int line,
866                                      const char *value)
867 {
868         int val;
869         val = wpa_config_parse_cipher(line, value);
870         if (val == -1)
871                 return -1;
872         if (val & ~WPA_ALLOWED_PAIRWISE_CIPHERS) {
873                 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
874                            "(0x%x).", line, val);
875                 return -1;
876         }
877
878         wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
879         ssid->pairwise_cipher = val;
880         return 0;
881 }
882
883
884 #ifndef NO_CONFIG_WRITE
885 static char * wpa_config_write_pairwise(const struct parse_data *data,
886                                         struct wpa_ssid *ssid)
887 {
888         return wpa_config_write_cipher(ssid->pairwise_cipher);
889 }
890 #endif /* NO_CONFIG_WRITE */
891
892
893 static int wpa_config_parse_group(const struct parse_data *data,
894                                   struct wpa_ssid *ssid, int line,
895                                   const char *value)
896 {
897         int val;
898         val = wpa_config_parse_cipher(line, value);
899         if (val == -1)
900                 return -1;
901         if (val & ~WPA_ALLOWED_GROUP_CIPHERS) {
902                 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
903                            "(0x%x).", line, val);
904                 return -1;
905         }
906
907         wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
908         ssid->group_cipher = val;
909         return 0;
910 }
911
912
913 #ifndef NO_CONFIG_WRITE
914 static char * wpa_config_write_group(const struct parse_data *data,
915                                      struct wpa_ssid *ssid)
916 {
917         return wpa_config_write_cipher(ssid->group_cipher);
918 }
919 #endif /* NO_CONFIG_WRITE */
920
921
922 static int wpa_config_parse_auth_alg(const struct parse_data *data,
923                                      struct wpa_ssid *ssid, int line,
924                                      const char *value)
925 {
926         int val = 0, last, errors = 0;
927         char *start, *end, *buf;
928
929         buf = os_strdup(value);
930         if (buf == NULL)
931                 return -1;
932         start = buf;
933
934         while (*start != '\0') {
935                 while (*start == ' ' || *start == '\t')
936                         start++;
937                 if (*start == '\0')
938                         break;
939                 end = start;
940                 while (*end != ' ' && *end != '\t' && *end != '\0')
941                         end++;
942                 last = *end == '\0';
943                 *end = '\0';
944                 if (os_strcmp(start, "OPEN") == 0)
945                         val |= WPA_AUTH_ALG_OPEN;
946                 else if (os_strcmp(start, "SHARED") == 0)
947                         val |= WPA_AUTH_ALG_SHARED;
948                 else if (os_strcmp(start, "LEAP") == 0)
949                         val |= WPA_AUTH_ALG_LEAP;
950                 else {
951                         wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
952                                    line, start);
953                         errors++;
954                 }
955
956                 if (last)
957                         break;
958                 start = end + 1;
959         }
960         os_free(buf);
961
962         if (val == 0) {
963                 wpa_printf(MSG_ERROR,
964                            "Line %d: no auth_alg values configured.", line);
965                 errors++;
966         }
967
968         wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
969         ssid->auth_alg = val;
970         return errors ? -1 : 0;
971 }
972
973
974 #ifndef NO_CONFIG_WRITE
975 static char * wpa_config_write_auth_alg(const struct parse_data *data,
976                                         struct wpa_ssid *ssid)
977 {
978         char *buf, *pos, *end;
979         int ret;
980
981         pos = buf = os_zalloc(30);
982         if (buf == NULL)
983                 return NULL;
984         end = buf + 30;
985
986         if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
987                 ret = os_snprintf(pos, end - pos, "%sOPEN",
988                                   pos == buf ? "" : " ");
989                 if (os_snprintf_error(end - pos, ret)) {
990                         end[-1] = '\0';
991                         return buf;
992                 }
993                 pos += ret;
994         }
995
996         if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
997                 ret = os_snprintf(pos, end - pos, "%sSHARED",
998                                   pos == buf ? "" : " ");
999                 if (os_snprintf_error(end - pos, ret)) {
1000                         end[-1] = '\0';
1001                         return buf;
1002                 }
1003                 pos += ret;
1004         }
1005
1006         if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
1007                 ret = os_snprintf(pos, end - pos, "%sLEAP",
1008                                   pos == buf ? "" : " ");
1009                 if (os_snprintf_error(end - pos, ret)) {
1010                         end[-1] = '\0';
1011                         return buf;
1012                 }
1013                 pos += ret;
1014         }
1015
1016         if (pos == buf) {
1017                 os_free(buf);
1018                 buf = NULL;
1019         }
1020
1021         return buf;
1022 }
1023 #endif /* NO_CONFIG_WRITE */
1024
1025
1026 static int * wpa_config_parse_int_array(const char *value)
1027 {
1028         int *freqs;
1029         size_t used, len;
1030         const char *pos;
1031
1032         used = 0;
1033         len = 10;
1034         freqs = os_calloc(len + 1, sizeof(int));
1035         if (freqs == NULL)
1036                 return NULL;
1037
1038         pos = value;
1039         while (pos) {
1040                 while (*pos == ' ')
1041                         pos++;
1042                 if (used == len) {
1043                         int *n;
1044                         size_t i;
1045                         n = os_realloc_array(freqs, len * 2 + 1, sizeof(int));
1046                         if (n == NULL) {
1047                                 os_free(freqs);
1048                                 return NULL;
1049                         }
1050                         for (i = len; i <= len * 2; i++)
1051                                 n[i] = 0;
1052                         freqs = n;
1053                         len *= 2;
1054                 }
1055
1056                 freqs[used] = atoi(pos);
1057                 if (freqs[used] == 0)
1058                         break;
1059                 used++;
1060                 pos = os_strchr(pos + 1, ' ');
1061         }
1062
1063         return freqs;
1064 }
1065
1066
1067 static int wpa_config_parse_scan_freq(const struct parse_data *data,
1068                                       struct wpa_ssid *ssid, int line,
1069                                       const char *value)
1070 {
1071         int *freqs;
1072
1073         freqs = wpa_config_parse_int_array(value);
1074         if (freqs == NULL)
1075                 return -1;
1076         if (freqs[0] == 0) {
1077                 os_free(freqs);
1078                 freqs = NULL;
1079         }
1080         os_free(ssid->scan_freq);
1081         ssid->scan_freq = freqs;
1082
1083         return 0;
1084 }
1085
1086
1087 static int wpa_config_parse_freq_list(const struct parse_data *data,
1088                                       struct wpa_ssid *ssid, int line,
1089                                       const char *value)
1090 {
1091         int *freqs;
1092
1093         freqs = wpa_config_parse_int_array(value);
1094         if (freqs == NULL)
1095                 return -1;
1096         if (freqs[0] == 0) {
1097                 os_free(freqs);
1098                 freqs = NULL;
1099         }
1100         os_free(ssid->freq_list);
1101         ssid->freq_list = freqs;
1102
1103         return 0;
1104 }
1105
1106
1107 #ifndef NO_CONFIG_WRITE
1108 static char * wpa_config_write_freqs(const struct parse_data *data,
1109                                      const int *freqs)
1110 {
1111         char *buf, *pos, *end;
1112         int i, ret;
1113         size_t count;
1114
1115         if (freqs == NULL)
1116                 return NULL;
1117
1118         count = 0;
1119         for (i = 0; freqs[i]; i++)
1120                 count++;
1121
1122         pos = buf = os_zalloc(10 * count + 1);
1123         if (buf == NULL)
1124                 return NULL;
1125         end = buf + 10 * count + 1;
1126
1127         for (i = 0; freqs[i]; i++) {
1128                 ret = os_snprintf(pos, end - pos, "%s%u",
1129                                   i == 0 ? "" : " ", freqs[i]);
1130                 if (os_snprintf_error(end - pos, ret)) {
1131                         end[-1] = '\0';
1132                         return buf;
1133                 }
1134                 pos += ret;
1135         }
1136
1137         return buf;
1138 }
1139
1140
1141 static char * wpa_config_write_scan_freq(const struct parse_data *data,
1142                                          struct wpa_ssid *ssid)
1143 {
1144         return wpa_config_write_freqs(data, ssid->scan_freq);
1145 }
1146
1147
1148 static char * wpa_config_write_freq_list(const struct parse_data *data,
1149                                          struct wpa_ssid *ssid)
1150 {
1151         return wpa_config_write_freqs(data, ssid->freq_list);
1152 }
1153 #endif /* NO_CONFIG_WRITE */
1154
1155
1156 #ifdef IEEE8021X_EAPOL
1157 static int wpa_config_parse_eap(const struct parse_data *data,
1158                                 struct wpa_ssid *ssid, int line,
1159                                 const char *value)
1160 {
1161         int last, errors = 0;
1162         char *start, *end, *buf;
1163         struct eap_method_type *methods = NULL, *tmp;
1164         size_t num_methods = 0;
1165
1166         buf = os_strdup(value);
1167         if (buf == NULL)
1168                 return -1;
1169         start = buf;
1170
1171         while (*start != '\0') {
1172                 while (*start == ' ' || *start == '\t')
1173                         start++;
1174                 if (*start == '\0')
1175                         break;
1176                 end = start;
1177                 while (*end != ' ' && *end != '\t' && *end != '\0')
1178                         end++;
1179                 last = *end == '\0';
1180                 *end = '\0';
1181                 tmp = methods;
1182                 methods = os_realloc_array(methods, num_methods + 1,
1183                                            sizeof(*methods));
1184                 if (methods == NULL) {
1185                         os_free(tmp);
1186                         os_free(buf);
1187                         return -1;
1188                 }
1189                 methods[num_methods].method = eap_peer_get_type(
1190                         start, &methods[num_methods].vendor);
1191                 if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
1192                     methods[num_methods].method == EAP_TYPE_NONE) {
1193                         wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
1194                                    "'%s'", line, start);
1195                         wpa_printf(MSG_ERROR, "You may need to add support for"
1196                                    " this EAP method during wpa_supplicant\n"
1197                                    "build time configuration.\n"
1198                                    "See README for more information.");
1199                         errors++;
1200                 } else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
1201                            methods[num_methods].method == EAP_TYPE_LEAP)
1202                         ssid->leap++;
1203                 else
1204                         ssid->non_leap++;
1205                 num_methods++;
1206                 if (last)
1207                         break;
1208                 start = end + 1;
1209         }
1210         os_free(buf);
1211
1212         tmp = methods;
1213         methods = os_realloc_array(methods, num_methods + 1, sizeof(*methods));
1214         if (methods == NULL) {
1215                 os_free(tmp);
1216                 return -1;
1217         }
1218         methods[num_methods].vendor = EAP_VENDOR_IETF;
1219         methods[num_methods].method = EAP_TYPE_NONE;
1220         num_methods++;
1221
1222         wpa_hexdump(MSG_MSGDUMP, "eap methods",
1223                     (u8 *) methods, num_methods * sizeof(*methods));
1224         os_free(ssid->eap.eap_methods);
1225         ssid->eap.eap_methods = methods;
1226         return errors ? -1 : 0;
1227 }
1228
1229
1230 static char * wpa_config_write_eap(const struct parse_data *data,
1231                                    struct wpa_ssid *ssid)
1232 {
1233         int i, ret;
1234         char *buf, *pos, *end;
1235         const struct eap_method_type *eap_methods = ssid->eap.eap_methods;
1236         const char *name;
1237
1238         if (eap_methods == NULL)
1239                 return NULL;
1240
1241         pos = buf = os_zalloc(100);
1242         if (buf == NULL)
1243                 return NULL;
1244         end = buf + 100;
1245
1246         for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
1247                      eap_methods[i].method != EAP_TYPE_NONE; i++) {
1248                 name = eap_get_name(eap_methods[i].vendor,
1249                                     eap_methods[i].method);
1250                 if (name) {
1251                         ret = os_snprintf(pos, end - pos, "%s%s",
1252                                           pos == buf ? "" : " ", name);
1253                         if (os_snprintf_error(end - pos, ret))
1254                                 break;
1255                         pos += ret;
1256                 }
1257         }
1258
1259         end[-1] = '\0';
1260
1261         return buf;
1262 }
1263
1264
1265 static int wpa_config_parse_password(const struct parse_data *data,
1266                                      struct wpa_ssid *ssid, int line,
1267                                      const char *value)
1268 {
1269         u8 *hash;
1270
1271         if (os_strcmp(value, "NULL") == 0) {
1272                 wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
1273                 bin_clear_free(ssid->eap.password, ssid->eap.password_len);
1274                 ssid->eap.password = NULL;
1275                 ssid->eap.password_len = 0;
1276                 return 0;
1277         }
1278
1279 #ifdef CONFIG_EXT_PASSWORD
1280         if (os_strncmp(value, "ext:", 4) == 0) {
1281                 char *name = os_strdup(value + 4);
1282                 if (name == NULL)
1283                         return -1;
1284                 bin_clear_free(ssid->eap.password, ssid->eap.password_len);
1285                 ssid->eap.password = (u8 *) name;
1286                 ssid->eap.password_len = os_strlen(name);
1287                 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1288                 ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_PASSWORD;
1289                 return 0;
1290         }
1291 #endif /* CONFIG_EXT_PASSWORD */
1292
1293         if (os_strncmp(value, "hash:", 5) != 0) {
1294                 char *tmp;
1295                 size_t res_len;
1296
1297                 tmp = wpa_config_parse_string(value, &res_len);
1298                 if (tmp == NULL) {
1299                         wpa_printf(MSG_ERROR, "Line %d: failed to parse "
1300                                    "password.", line);
1301                         return -1;
1302                 }
1303                 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
1304                                       (u8 *) tmp, res_len);
1305
1306                 bin_clear_free(ssid->eap.password, ssid->eap.password_len);
1307                 ssid->eap.password = (u8 *) tmp;
1308                 ssid->eap.password_len = res_len;
1309                 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1310                 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
1311
1312                 return 0;
1313         }
1314
1315
1316         /* NtPasswordHash: hash:<32 hex digits> */
1317         if (os_strlen(value + 5) != 2 * 16) {
1318                 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
1319                            "(expected 32 hex digits)", line);
1320                 return -1;
1321         }
1322
1323         hash = os_malloc(16);
1324         if (hash == NULL)
1325                 return -1;
1326
1327         if (hexstr2bin(value + 5, hash, 16)) {
1328                 os_free(hash);
1329                 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
1330                 return -1;
1331         }
1332
1333         wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
1334
1335         bin_clear_free(ssid->eap.password, ssid->eap.password_len);
1336         ssid->eap.password = hash;
1337         ssid->eap.password_len = 16;
1338         ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
1339         ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
1340
1341         return 0;
1342 }
1343
1344
1345 static char * wpa_config_write_password(const struct parse_data *data,
1346                                         struct wpa_ssid *ssid)
1347 {
1348         char *buf;
1349
1350         if (ssid->eap.password == NULL)
1351                 return NULL;
1352
1353 #ifdef CONFIG_EXT_PASSWORD
1354         if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
1355                 buf = os_zalloc(4 + ssid->eap.password_len + 1);
1356                 if (buf == NULL)
1357                         return NULL;
1358                 os_memcpy(buf, "ext:", 4);
1359                 os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len);
1360                 return buf;
1361         }
1362 #endif /* CONFIG_EXT_PASSWORD */
1363
1364         if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
1365                 return wpa_config_write_string(
1366                         ssid->eap.password, ssid->eap.password_len);
1367         }
1368
1369         buf = os_malloc(5 + 32 + 1);
1370         if (buf == NULL)
1371                 return NULL;
1372
1373         os_memcpy(buf, "hash:", 5);
1374         wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16);
1375
1376         return buf;
1377 }
1378 #endif /* IEEE8021X_EAPOL */
1379
1380
1381 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
1382                                     const char *value, int idx)
1383 {
1384         char *buf, title[20];
1385         int res;
1386
1387         buf = wpa_config_parse_string(value, len);
1388         if (buf == NULL) {
1389                 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
1390                            line, idx, value);
1391                 return -1;
1392         }
1393         if (*len > MAX_WEP_KEY_LEN) {
1394                 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
1395                            line, idx, value);
1396                 os_free(buf);
1397                 return -1;
1398         }
1399         if (*len && *len != 5 && *len != 13 && *len != 16) {
1400                 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key length %u - "
1401                            "this network block will be ignored",
1402                            line, (unsigned int) *len);
1403         }
1404         os_memcpy(key, buf, *len);
1405         str_clear_free(buf);
1406         res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
1407         if (!os_snprintf_error(sizeof(title), res))
1408                 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
1409         return 0;
1410 }
1411
1412
1413 static int wpa_config_parse_wep_key0(const struct parse_data *data,
1414                                      struct wpa_ssid *ssid, int line,
1415                                      const char *value)
1416 {
1417         return wpa_config_parse_wep_key(ssid->wep_key[0],
1418                                         &ssid->wep_key_len[0], line,
1419                                         value, 0);
1420 }
1421
1422
1423 static int wpa_config_parse_wep_key1(const struct parse_data *data,
1424                                      struct wpa_ssid *ssid, int line,
1425                                      const char *value)
1426 {
1427         return wpa_config_parse_wep_key(ssid->wep_key[1],
1428                                         &ssid->wep_key_len[1], line,
1429                                         value, 1);
1430 }
1431
1432
1433 static int wpa_config_parse_wep_key2(const struct parse_data *data,
1434                                      struct wpa_ssid *ssid, int line,
1435                                      const char *value)
1436 {
1437         return wpa_config_parse_wep_key(ssid->wep_key[2],
1438                                         &ssid->wep_key_len[2], line,
1439                                         value, 2);
1440 }
1441
1442
1443 static int wpa_config_parse_wep_key3(const struct parse_data *data,
1444                                      struct wpa_ssid *ssid, int line,
1445                                      const char *value)
1446 {
1447         return wpa_config_parse_wep_key(ssid->wep_key[3],
1448                                         &ssid->wep_key_len[3], line,
1449                                         value, 3);
1450 }
1451
1452
1453 #ifndef NO_CONFIG_WRITE
1454 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
1455 {
1456         if (ssid->wep_key_len[idx] == 0)
1457                 return NULL;
1458         return wpa_config_write_string(ssid->wep_key[idx],
1459                                        ssid->wep_key_len[idx]);
1460 }
1461
1462
1463 static char * wpa_config_write_wep_key0(const struct parse_data *data,
1464                                         struct wpa_ssid *ssid)
1465 {
1466         return wpa_config_write_wep_key(ssid, 0);
1467 }
1468
1469
1470 static char * wpa_config_write_wep_key1(const struct parse_data *data,
1471                                         struct wpa_ssid *ssid)
1472 {
1473         return wpa_config_write_wep_key(ssid, 1);
1474 }
1475
1476
1477 static char * wpa_config_write_wep_key2(const struct parse_data *data,
1478                                         struct wpa_ssid *ssid)
1479 {
1480         return wpa_config_write_wep_key(ssid, 2);
1481 }
1482
1483
1484 static char * wpa_config_write_wep_key3(const struct parse_data *data,
1485                                         struct wpa_ssid *ssid)
1486 {
1487         return wpa_config_write_wep_key(ssid, 3);
1488 }
1489 #endif /* NO_CONFIG_WRITE */
1490
1491
1492 #ifdef CONFIG_P2P
1493
1494 static int wpa_config_parse_go_p2p_dev_addr(const struct parse_data *data,
1495                                             struct wpa_ssid *ssid, int line,
1496                                             const char *value)
1497 {
1498         if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
1499             os_strcmp(value, "any") == 0) {
1500                 os_memset(ssid->go_p2p_dev_addr, 0, ETH_ALEN);
1501                 wpa_printf(MSG_MSGDUMP, "GO P2P Device Address any");
1502                 return 0;
1503         }
1504         if (hwaddr_aton(value, ssid->go_p2p_dev_addr)) {
1505                 wpa_printf(MSG_ERROR, "Line %d: Invalid GO P2P Device Address '%s'.",
1506                            line, value);
1507                 return -1;
1508         }
1509         ssid->bssid_set = 1;
1510         wpa_printf(MSG_MSGDUMP, "GO P2P Device Address " MACSTR,
1511                    MAC2STR(ssid->go_p2p_dev_addr));
1512         return 0;
1513 }
1514
1515
1516 #ifndef NO_CONFIG_WRITE
1517 static char * wpa_config_write_go_p2p_dev_addr(const struct parse_data *data,
1518                                                struct wpa_ssid *ssid)
1519 {
1520         char *value;
1521         int res;
1522
1523         if (is_zero_ether_addr(ssid->go_p2p_dev_addr))
1524                 return NULL;
1525
1526         value = os_malloc(20);
1527         if (value == NULL)
1528                 return NULL;
1529         res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->go_p2p_dev_addr));
1530         if (os_snprintf_error(20, res)) {
1531                 os_free(value);
1532                 return NULL;
1533         }
1534         value[20 - 1] = '\0';
1535         return value;
1536 }
1537 #endif /* NO_CONFIG_WRITE */
1538
1539
1540 static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
1541                                             struct wpa_ssid *ssid, int line,
1542                                             const char *value)
1543 {
1544         return wpa_config_parse_addr_list(data, line, value,
1545                                           &ssid->p2p_client_list,
1546                                           &ssid->num_p2p_clients,
1547                                           "p2p_client_list", 0);
1548 }
1549
1550
1551 #ifndef NO_CONFIG_WRITE
1552 static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
1553                                                struct wpa_ssid *ssid)
1554 {
1555         return wpa_config_write_addr_list(data, ssid->p2p_client_list,
1556                                           ssid->num_p2p_clients,
1557                                           "p2p_client_list");
1558 }
1559 #endif /* NO_CONFIG_WRITE */
1560
1561
1562 static int wpa_config_parse_psk_list(const struct parse_data *data,
1563                                      struct wpa_ssid *ssid, int line,
1564                                      const char *value)
1565 {
1566         struct psk_list_entry *p;
1567         const char *pos;
1568
1569         p = os_zalloc(sizeof(*p));
1570         if (p == NULL)
1571                 return -1;
1572
1573         pos = value;
1574         if (os_strncmp(pos, "P2P-", 4) == 0) {
1575                 p->p2p = 1;
1576                 pos += 4;
1577         }
1578
1579         if (hwaddr_aton(pos, p->addr)) {
1580                 wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list address '%s'",
1581                            line, pos);
1582                 os_free(p);
1583                 return -1;
1584         }
1585         pos += 17;
1586         if (*pos != '-') {
1587                 wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list '%s'",
1588                            line, pos);
1589                 os_free(p);
1590                 return -1;
1591         }
1592         pos++;
1593
1594         if (hexstr2bin(pos, p->psk, PMK_LEN) || pos[PMK_LEN * 2] != '\0') {
1595                 wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list PSK '%s'",
1596                            line, pos);
1597                 os_free(p);
1598                 return -1;
1599         }
1600
1601         dl_list_add(&ssid->psk_list, &p->list);
1602
1603         return 0;
1604 }
1605
1606
1607 #ifndef NO_CONFIG_WRITE
1608 static char * wpa_config_write_psk_list(const struct parse_data *data,
1609                                         struct wpa_ssid *ssid)
1610 {
1611         return NULL;
1612 }
1613 #endif /* NO_CONFIG_WRITE */
1614
1615 #endif /* CONFIG_P2P */
1616
1617
1618 #ifdef CONFIG_MESH
1619
1620 static int wpa_config_parse_mesh_basic_rates(const struct parse_data *data,
1621                                              struct wpa_ssid *ssid, int line,
1622                                              const char *value)
1623 {
1624         int *rates = wpa_config_parse_int_array(value);
1625
1626         if (rates == NULL) {
1627                 wpa_printf(MSG_ERROR, "Line %d: Invalid mesh_basic_rates '%s'",
1628                            line, value);
1629                 return -1;
1630         }
1631         if (rates[0] == 0) {
1632                 os_free(rates);
1633                 rates = NULL;
1634         }
1635
1636         os_free(ssid->mesh_basic_rates);
1637         ssid->mesh_basic_rates = rates;
1638
1639         return 0;
1640 }
1641
1642
1643 #ifndef NO_CONFIG_WRITE
1644
1645 static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data,
1646                                                 struct wpa_ssid *ssid)
1647 {
1648         return wpa_config_write_freqs(data, ssid->mesh_basic_rates);
1649 }
1650
1651 #endif /* NO_CONFIG_WRITE */
1652
1653 #endif /* CONFIG_MESH */
1654
1655
1656 /* Helper macros for network block parser */
1657
1658 #ifdef OFFSET
1659 #undef OFFSET
1660 #endif /* OFFSET */
1661 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
1662 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
1663
1664 /* STR: Define a string variable for an ASCII string; f = field name */
1665 #ifdef NO_CONFIG_WRITE
1666 #define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
1667 #define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
1668 #else /* NO_CONFIG_WRITE */
1669 #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
1670 #define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
1671 #endif /* NO_CONFIG_WRITE */
1672 #define STR(f) _STR(f), NULL, NULL, NULL, 0
1673 #define STRe(f) _STRe(f), NULL, NULL, NULL, 0
1674 #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
1675 #define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
1676
1677 /* STR_LEN: Define a string variable with a separate variable for storing the
1678  * data length. Unlike STR(), this can be used to store arbitrary binary data
1679  * (i.e., even nul termination character). */
1680 #define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
1681 #define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
1682 #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
1683 #define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
1684 #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
1685
1686 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
1687  * explicitly specified. */
1688 #define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
1689 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
1690 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
1691
1692 #ifdef NO_CONFIG_WRITE
1693 #define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
1694 #define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
1695 #else /* NO_CONFIG_WRITE */
1696 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1697         OFFSET(f), (void *) 0
1698 #define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1699         OFFSET(eap.f), (void *) 0
1700 #endif /* NO_CONFIG_WRITE */
1701
1702 /* INT: Define an integer variable */
1703 #define INT(f) _INT(f), NULL, NULL, 0
1704 #define INTe(f) _INTe(f), NULL, NULL, 0
1705
1706 /* INT_RANGE: Define an integer variable with allowed value range */
1707 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
1708
1709 /* FUNC: Define a configuration variable that uses a custom function for
1710  * parsing and writing the value. */
1711 #ifdef NO_CONFIG_WRITE
1712 #define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
1713 #else /* NO_CONFIG_WRITE */
1714 #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
1715         NULL, NULL, NULL, NULL
1716 #endif /* NO_CONFIG_WRITE */
1717 #define FUNC(f) _FUNC(f), 0
1718 #define FUNC_KEY(f) _FUNC(f), 1
1719
1720 /*
1721  * Table of network configuration variables. This table is used to parse each
1722  * network configuration variable, e.g., each line in wpa_supplicant.conf file
1723  * that is inside a network block.
1724  *
1725  * This table is generated using the helper macros defined above and with
1726  * generous help from the C pre-processor. The field name is stored as a string
1727  * into .name and for STR and INT types, the offset of the target buffer within
1728  * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
1729  * offset to the field containing the length of the configuration variable.
1730  * .param3 and .param4 can be used to mark the allowed range (length for STR
1731  * and value for INT).
1732  *
1733  * For each configuration line in wpa_supplicant.conf, the parser goes through
1734  * this table and select the entry that matches with the field name. The parser
1735  * function (.parser) is then called to parse the actual value of the field.
1736  *
1737  * This kind of mechanism makes it easy to add new configuration parameters,
1738  * since only one line needs to be added into this table and into the
1739  * struct wpa_ssid definition if the new variable is either a string or
1740  * integer. More complex types will need to use their own parser and writer
1741  * functions.
1742  */
1743 static const struct parse_data ssid_fields[] = {
1744         { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1745         { INT_RANGE(scan_ssid, 0, 1) },
1746         { FUNC(bssid) },
1747         { FUNC_KEY(psk) },
1748         { FUNC(proto) },
1749         { FUNC(key_mgmt) },
1750         { INT(bg_scan_period) },
1751         { FUNC(pairwise) },
1752         { FUNC(group) },
1753         { FUNC(auth_alg) },
1754         { FUNC(scan_freq) },
1755         { FUNC(freq_list) },
1756 #ifdef IEEE8021X_EAPOL
1757         { FUNC(eap) },
1758         { STR_LENe(identity) },
1759         { STR_LENe(anonymous_identity) },
1760         { FUNC_KEY(password) },
1761         { STRe(ca_cert) },
1762         { STRe(ca_path) },
1763         { STRe(client_cert) },
1764         { STRe(private_key) },
1765         { STR_KEYe(private_key_passwd) },
1766         { STRe(dh_file) },
1767         { STRe(subject_match) },
1768         { STRe(altsubject_match) },
1769         { STRe(domain_suffix_match) },
1770         { STRe(ca_cert2) },
1771         { STRe(ca_path2) },
1772         { STRe(client_cert2) },
1773         { STRe(private_key2) },
1774         { STR_KEYe(private_key2_passwd) },
1775         { STRe(dh_file2) },
1776         { STRe(subject_match2) },
1777         { STRe(altsubject_match2) },
1778         { STRe(domain_suffix_match2) },
1779         { STRe(phase1) },
1780         { STRe(phase2) },
1781         { STRe(pcsc) },
1782         { STR_KEYe(pin) },
1783         { STRe(engine_id) },
1784         { STRe(key_id) },
1785         { STRe(cert_id) },
1786         { STRe(ca_cert_id) },
1787         { STR_KEYe(pin2) },
1788         { STRe(engine2_id) },
1789         { STRe(key2_id) },
1790         { STRe(cert2_id) },
1791         { STRe(ca_cert2_id) },
1792         { INTe(engine) },
1793         { INTe(engine2) },
1794         { INT(eapol_flags) },
1795         { INTe(sim_num) },
1796         { STRe(openssl_ciphers) },
1797         { INTe(erp) },
1798 #endif /* IEEE8021X_EAPOL */
1799         { FUNC_KEY(wep_key0) },
1800         { FUNC_KEY(wep_key1) },
1801         { FUNC_KEY(wep_key2) },
1802         { FUNC_KEY(wep_key3) },
1803         { INT(wep_tx_keyidx) },
1804         { INT(priority) },
1805 #ifdef IEEE8021X_EAPOL
1806         { INT(eap_workaround) },
1807         { STRe(pac_file) },
1808         { INTe(fragment_size) },
1809         { INTe(ocsp) },
1810 #endif /* IEEE8021X_EAPOL */
1811 #ifdef CONFIG_MESH
1812         { INT_RANGE(mode, 0, 5) },
1813         { INT_RANGE(no_auto_peer, 0, 1) },
1814 #else /* CONFIG_MESH */
1815         { INT_RANGE(mode, 0, 4) },
1816 #endif /* CONFIG_MESH */
1817         { INT_RANGE(proactive_key_caching, 0, 1) },
1818         { INT_RANGE(disabled, 0, 2) },
1819         { STR(id_str) },
1820 #ifdef CONFIG_IEEE80211W
1821         { INT_RANGE(ieee80211w, 0, 2) },
1822 #endif /* CONFIG_IEEE80211W */
1823         { INT_RANGE(peerkey, 0, 1) },
1824         { INT_RANGE(mixed_cell, 0, 1) },
1825         { INT_RANGE(frequency, 0, 65000) },
1826 #ifdef CONFIG_MESH
1827         { FUNC(mesh_basic_rates) },
1828         { INT(dot11MeshMaxRetries) },
1829         { INT(dot11MeshRetryTimeout) },
1830         { INT(dot11MeshConfirmTimeout) },
1831         { INT(dot11MeshHoldingTimeout) },
1832 #endif /* CONFIG_MESH */
1833         { INT(wpa_ptk_rekey) },
1834         { STR(bgscan) },
1835         { INT_RANGE(ignore_broadcast_ssid, 0, 2) },
1836 #ifdef CONFIG_P2P
1837         { FUNC(go_p2p_dev_addr) },
1838         { FUNC(p2p_client_list) },
1839         { FUNC(psk_list) },
1840 #endif /* CONFIG_P2P */
1841 #ifdef CONFIG_HT_OVERRIDES
1842         { INT_RANGE(disable_ht, 0, 1) },
1843         { INT_RANGE(disable_ht40, -1, 1) },
1844         { INT_RANGE(disable_sgi, 0, 1) },
1845         { INT_RANGE(disable_ldpc, 0, 1) },
1846         { INT_RANGE(ht40_intolerant, 0, 1) },
1847         { INT_RANGE(disable_max_amsdu, -1, 1) },
1848         { INT_RANGE(ampdu_factor, -1, 3) },
1849         { INT_RANGE(ampdu_density, -1, 7) },
1850         { STR(ht_mcs) },
1851 #endif /* CONFIG_HT_OVERRIDES */
1852 #ifdef CONFIG_VHT_OVERRIDES
1853         { INT_RANGE(disable_vht, 0, 1) },
1854         { INT(vht_capa) },
1855         { INT(vht_capa_mask) },
1856         { INT_RANGE(vht_rx_mcs_nss_1, -1, 3) },
1857         { INT_RANGE(vht_rx_mcs_nss_2, -1, 3) },
1858         { INT_RANGE(vht_rx_mcs_nss_3, -1, 3) },
1859         { INT_RANGE(vht_rx_mcs_nss_4, -1, 3) },
1860         { INT_RANGE(vht_rx_mcs_nss_5, -1, 3) },
1861         { INT_RANGE(vht_rx_mcs_nss_6, -1, 3) },
1862         { INT_RANGE(vht_rx_mcs_nss_7, -1, 3) },
1863         { INT_RANGE(vht_rx_mcs_nss_8, -1, 3) },
1864         { INT_RANGE(vht_tx_mcs_nss_1, -1, 3) },
1865         { INT_RANGE(vht_tx_mcs_nss_2, -1, 3) },
1866         { INT_RANGE(vht_tx_mcs_nss_3, -1, 3) },
1867         { INT_RANGE(vht_tx_mcs_nss_4, -1, 3) },
1868         { INT_RANGE(vht_tx_mcs_nss_5, -1, 3) },
1869         { INT_RANGE(vht_tx_mcs_nss_6, -1, 3) },
1870         { INT_RANGE(vht_tx_mcs_nss_7, -1, 3) },
1871         { INT_RANGE(vht_tx_mcs_nss_8, -1, 3) },
1872 #endif /* CONFIG_VHT_OVERRIDES */
1873         { INT(ap_max_inactivity) },
1874         { INT(dtim_period) },
1875         { INT(beacon_int) },
1876 #ifdef CONFIG_MACSEC
1877         { INT_RANGE(macsec_policy, 0, 1) },
1878 #endif /* CONFIG_MACSEC */
1879 #ifdef CONFIG_HS20
1880         { INT(update_identifier) },
1881 #endif /* CONFIG_HS20 */
1882         { INT_RANGE(mac_addr, 0, 2) },
1883 };
1884
1885 #undef OFFSET
1886 #undef _STR
1887 #undef STR
1888 #undef STR_KEY
1889 #undef _STR_LEN
1890 #undef STR_LEN
1891 #undef STR_LEN_KEY
1892 #undef _STR_RANGE
1893 #undef STR_RANGE
1894 #undef STR_RANGE_KEY
1895 #undef _INT
1896 #undef INT
1897 #undef INT_RANGE
1898 #undef _FUNC
1899 #undef FUNC
1900 #undef FUNC_KEY
1901 #define NUM_SSID_FIELDS ARRAY_SIZE(ssid_fields)
1902
1903
1904 /**
1905  * wpa_config_add_prio_network - Add a network to priority lists
1906  * @config: Configuration data from wpa_config_read()
1907  * @ssid: Pointer to the network configuration to be added to the list
1908  * Returns: 0 on success, -1 on failure
1909  *
1910  * This function is used to add a network block to the priority list of
1911  * networks. This must be called for each network when reading in the full
1912  * configuration. In addition, this can be used indirectly when updating
1913  * priorities by calling wpa_config_update_prio_list().
1914  */
1915 int wpa_config_add_prio_network(struct wpa_config *config,
1916                                 struct wpa_ssid *ssid)
1917 {
1918         int prio;
1919         struct wpa_ssid *prev, **nlist;
1920
1921         /*
1922          * Add to an existing priority list if one is available for the
1923          * configured priority level for this network.
1924          */
1925         for (prio = 0; prio < config->num_prio; prio++) {
1926                 prev = config->pssid[prio];
1927                 if (prev->priority == ssid->priority) {
1928                         while (prev->pnext)
1929                                 prev = prev->pnext;
1930                         prev->pnext = ssid;
1931                         return 0;
1932                 }
1933         }
1934
1935         /* First network for this priority - add a new priority list */
1936         nlist = os_realloc_array(config->pssid, config->num_prio + 1,
1937                                  sizeof(struct wpa_ssid *));
1938         if (nlist == NULL)
1939                 return -1;
1940
1941         for (prio = 0; prio < config->num_prio; prio++) {
1942                 if (nlist[prio]->priority < ssid->priority) {
1943                         os_memmove(&nlist[prio + 1], &nlist[prio],
1944                                    (config->num_prio - prio) *
1945                                    sizeof(struct wpa_ssid *));
1946                         break;
1947                 }
1948         }
1949
1950         nlist[prio] = ssid;
1951         config->num_prio++;
1952         config->pssid = nlist;
1953
1954         return 0;
1955 }
1956
1957
1958 /**
1959  * wpa_config_update_prio_list - Update network priority list
1960  * @config: Configuration data from wpa_config_read()
1961  * Returns: 0 on success, -1 on failure
1962  *
1963  * This function is called to update the priority list of networks in the
1964  * configuration when a network is being added or removed. This is also called
1965  * if a priority for a network is changed.
1966  */
1967 int wpa_config_update_prio_list(struct wpa_config *config)
1968 {
1969         struct wpa_ssid *ssid;
1970         int ret = 0;
1971
1972         os_free(config->pssid);
1973         config->pssid = NULL;
1974         config->num_prio = 0;
1975
1976         ssid = config->ssid;
1977         while (ssid) {
1978                 ssid->pnext = NULL;
1979                 if (wpa_config_add_prio_network(config, ssid) < 0)
1980                         ret = -1;
1981                 ssid = ssid->next;
1982         }
1983
1984         return ret;
1985 }
1986
1987
1988 #ifdef IEEE8021X_EAPOL
1989 static void eap_peer_config_free(struct eap_peer_config *eap)
1990 {
1991         os_free(eap->eap_methods);
1992         bin_clear_free(eap->identity, eap->identity_len);
1993         os_free(eap->anonymous_identity);
1994         bin_clear_free(eap->password, eap->password_len);
1995         os_free(eap->ca_cert);
1996         os_free(eap->ca_path);
1997         os_free(eap->client_cert);
1998         os_free(eap->private_key);
1999         str_clear_free(eap->private_key_passwd);
2000         os_free(eap->dh_file);
2001         os_free(eap->subject_match);
2002         os_free(eap->altsubject_match);
2003         os_free(eap->domain_suffix_match);
2004         os_free(eap->ca_cert2);
2005         os_free(eap->ca_path2);
2006         os_free(eap->client_cert2);
2007         os_free(eap->private_key2);
2008         str_clear_free(eap->private_key2_passwd);
2009         os_free(eap->dh_file2);
2010         os_free(eap->subject_match2);
2011         os_free(eap->altsubject_match2);
2012         os_free(eap->domain_suffix_match2);
2013         os_free(eap->phase1);
2014         os_free(eap->phase2);
2015         os_free(eap->pcsc);
2016         str_clear_free(eap->pin);
2017         os_free(eap->engine_id);
2018         os_free(eap->key_id);
2019         os_free(eap->cert_id);
2020         os_free(eap->ca_cert_id);
2021         os_free(eap->key2_id);
2022         os_free(eap->cert2_id);
2023         os_free(eap->ca_cert2_id);
2024         str_clear_free(eap->pin2);
2025         os_free(eap->engine2_id);
2026         os_free(eap->otp);
2027         os_free(eap->pending_req_otp);
2028         os_free(eap->pac_file);
2029         bin_clear_free(eap->new_password, eap->new_password_len);
2030         str_clear_free(eap->external_sim_resp);
2031         os_free(eap->openssl_ciphers);
2032 }
2033 #endif /* IEEE8021X_EAPOL */
2034
2035
2036 /**
2037  * wpa_config_free_ssid - Free network/ssid configuration data
2038  * @ssid: Configuration data for the network
2039  *
2040  * This function frees all resources allocated for the network configuration
2041  * data.
2042  */
2043 void wpa_config_free_ssid(struct wpa_ssid *ssid)
2044 {
2045         struct psk_list_entry *psk;
2046
2047         os_free(ssid->ssid);
2048         str_clear_free(ssid->passphrase);
2049         os_free(ssid->ext_psk);
2050 #ifdef IEEE8021X_EAPOL
2051         eap_peer_config_free(&ssid->eap);
2052 #endif /* IEEE8021X_EAPOL */
2053         os_free(ssid->id_str);
2054         os_free(ssid->scan_freq);
2055         os_free(ssid->freq_list);
2056         os_free(ssid->bgscan);
2057         os_free(ssid->p2p_client_list);
2058 #ifdef CONFIG_HT_OVERRIDES
2059         os_free(ssid->ht_mcs);
2060 #endif /* CONFIG_HT_OVERRIDES */
2061 #ifdef CONFIG_MESH
2062         os_free(ssid->mesh_basic_rates);
2063 #endif /* CONFIG_MESH */
2064         while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
2065                                     list))) {
2066                 dl_list_del(&psk->list);
2067                 bin_clear_free(psk, sizeof(*psk));
2068         }
2069         bin_clear_free(ssid, sizeof(*ssid));
2070 }
2071
2072
2073 void wpa_config_free_cred(struct wpa_cred *cred)
2074 {
2075         size_t i;
2076
2077         os_free(cred->realm);
2078         str_clear_free(cred->username);
2079         str_clear_free(cred->password);
2080         os_free(cred->ca_cert);
2081         os_free(cred->client_cert);
2082         os_free(cred->private_key);
2083         str_clear_free(cred->private_key_passwd);
2084         os_free(cred->imsi);
2085         str_clear_free(cred->milenage);
2086         for (i = 0; i < cred->num_domain; i++)
2087                 os_free(cred->domain[i]);
2088         os_free(cred->domain);
2089         os_free(cred->domain_suffix_match);
2090         os_free(cred->eap_method);
2091         os_free(cred->phase1);
2092         os_free(cred->phase2);
2093         os_free(cred->excluded_ssid);
2094         os_free(cred->roaming_partner);
2095         os_free(cred->provisioning_sp);
2096         for (i = 0; i < cred->num_req_conn_capab; i++)
2097                 os_free(cred->req_conn_capab_port[i]);
2098         os_free(cred->req_conn_capab_port);
2099         os_free(cred->req_conn_capab_proto);
2100         os_free(cred);
2101 }
2102
2103
2104 void wpa_config_flush_blobs(struct wpa_config *config)
2105 {
2106 #ifndef CONFIG_NO_CONFIG_BLOBS
2107         struct wpa_config_blob *blob, *prev;
2108
2109         blob = config->blobs;
2110         config->blobs = NULL;
2111         while (blob) {
2112                 prev = blob;
2113                 blob = blob->next;
2114                 wpa_config_free_blob(prev);
2115         }
2116 #endif /* CONFIG_NO_CONFIG_BLOBS */
2117 }
2118
2119
2120 /**
2121  * wpa_config_free - Free configuration data
2122  * @config: Configuration data from wpa_config_read()
2123  *
2124  * This function frees all resources allocated for the configuration data by
2125  * wpa_config_read().
2126  */
2127 void wpa_config_free(struct wpa_config *config)
2128 {
2129         struct wpa_ssid *ssid, *prev = NULL;
2130         struct wpa_cred *cred, *cprev;
2131         int i;
2132
2133         ssid = config->ssid;
2134         while (ssid) {
2135                 prev = ssid;
2136                 ssid = ssid->next;
2137                 wpa_config_free_ssid(prev);
2138         }
2139
2140         cred = config->cred;
2141         while (cred) {
2142                 cprev = cred;
2143                 cred = cred->next;
2144                 wpa_config_free_cred(cprev);
2145         }
2146
2147         wpa_config_flush_blobs(config);
2148
2149         wpabuf_free(config->wps_vendor_ext_m1);
2150         for (i = 0; i < MAX_WPS_VENDOR_EXT; i++)
2151                 wpabuf_free(config->wps_vendor_ext[i]);
2152         os_free(config->ctrl_interface);
2153         os_free(config->ctrl_interface_group);
2154         os_free(config->opensc_engine_path);
2155         os_free(config->pkcs11_engine_path);
2156         os_free(config->pkcs11_module_path);
2157         os_free(config->openssl_ciphers);
2158         os_free(config->pcsc_reader);
2159         str_clear_free(config->pcsc_pin);
2160         os_free(config->driver_param);
2161         os_free(config->device_name);
2162         os_free(config->manufacturer);
2163         os_free(config->model_name);
2164         os_free(config->model_number);
2165         os_free(config->serial_number);
2166         os_free(config->config_methods);
2167         os_free(config->p2p_ssid_postfix);
2168         os_free(config->pssid);
2169         os_free(config->p2p_pref_chan);
2170         os_free(config->p2p_no_go_freq.range);
2171         os_free(config->autoscan);
2172         os_free(config->freq_list);
2173         wpabuf_free(config->wps_nfc_dh_pubkey);
2174         wpabuf_free(config->wps_nfc_dh_privkey);
2175         wpabuf_free(config->wps_nfc_dev_pw);
2176         os_free(config->ext_password_backend);
2177         os_free(config->sae_groups);
2178         wpabuf_free(config->ap_vendor_elements);
2179         os_free(config->osu_dir);
2180         os_free(config->wowlan_triggers);
2181         os_free(config);
2182 }
2183
2184
2185 /**
2186  * wpa_config_foreach_network - Iterate over each configured network
2187  * @config: Configuration data from wpa_config_read()
2188  * @func: Callback function to process each network
2189  * @arg: Opaque argument to pass to callback function
2190  *
2191  * Iterate over the set of configured networks calling the specified
2192  * function for each item. We guard against callbacks removing the
2193  * supplied network.
2194  */
2195 void wpa_config_foreach_network(struct wpa_config *config,
2196                                 void (*func)(void *, struct wpa_ssid *),
2197                                 void *arg)
2198 {
2199         struct wpa_ssid *ssid, *next;
2200
2201         ssid = config->ssid;
2202         while (ssid) {
2203                 next = ssid->next;
2204                 func(arg, ssid);
2205                 ssid = next;
2206         }
2207 }
2208
2209
2210 /**
2211  * wpa_config_get_network - Get configured network based on id
2212  * @config: Configuration data from wpa_config_read()
2213  * @id: Unique network id to search for
2214  * Returns: Network configuration or %NULL if not found
2215  */
2216 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
2217 {
2218         struct wpa_ssid *ssid;
2219
2220         ssid = config->ssid;
2221         while (ssid) {
2222                 if (id == ssid->id)
2223                         break;
2224                 ssid = ssid->next;
2225         }
2226
2227         return ssid;
2228 }
2229
2230
2231 /**
2232  * wpa_config_add_network - Add a new network with empty configuration
2233  * @config: Configuration data from wpa_config_read()
2234  * Returns: The new network configuration or %NULL if operation failed
2235  */
2236 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
2237 {
2238         int id;
2239         struct wpa_ssid *ssid, *last = NULL;
2240
2241         id = -1;
2242         ssid = config->ssid;
2243         while (ssid) {
2244                 if (ssid->id > id)
2245                         id = ssid->id;
2246                 last = ssid;
2247                 ssid = ssid->next;
2248         }
2249         id++;
2250
2251         ssid = os_zalloc(sizeof(*ssid));
2252         if (ssid == NULL)
2253                 return NULL;
2254         ssid->id = id;
2255         dl_list_init(&ssid->psk_list);
2256         if (last)
2257                 last->next = ssid;
2258         else
2259                 config->ssid = ssid;
2260
2261         wpa_config_update_prio_list(config);
2262
2263         return ssid;
2264 }
2265
2266
2267 /**
2268  * wpa_config_remove_network - Remove a configured network based on id
2269  * @config: Configuration data from wpa_config_read()
2270  * @id: Unique network id to search for
2271  * Returns: 0 on success, or -1 if the network was not found
2272  */
2273 int wpa_config_remove_network(struct wpa_config *config, int id)
2274 {
2275         struct wpa_ssid *ssid, *prev = NULL;
2276
2277         ssid = config->ssid;
2278         while (ssid) {
2279                 if (id == ssid->id)
2280                         break;
2281                 prev = ssid;
2282                 ssid = ssid->next;
2283         }
2284
2285         if (ssid == NULL)
2286                 return -1;
2287
2288         if (prev)
2289                 prev->next = ssid->next;
2290         else
2291                 config->ssid = ssid->next;
2292
2293         wpa_config_update_prio_list(config);
2294         wpa_config_free_ssid(ssid);
2295         return 0;
2296 }
2297
2298
2299 /**
2300  * wpa_config_set_network_defaults - Set network default values
2301  * @ssid: Pointer to network configuration data
2302  */
2303 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
2304 {
2305         ssid->proto = DEFAULT_PROTO;
2306         ssid->pairwise_cipher = DEFAULT_PAIRWISE;
2307         ssid->group_cipher = DEFAULT_GROUP;
2308         ssid->key_mgmt = DEFAULT_KEY_MGMT;
2309         ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
2310 #ifdef IEEE8021X_EAPOL
2311         ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
2312         ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
2313         ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
2314         ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM;
2315 #endif /* IEEE8021X_EAPOL */
2316 #ifdef CONFIG_MESH
2317         ssid->dot11MeshMaxRetries = DEFAULT_MESH_MAX_RETRIES;
2318         ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
2319         ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
2320         ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
2321 #endif /* CONFIG_MESH */
2322 #ifdef CONFIG_HT_OVERRIDES
2323         ssid->disable_ht = DEFAULT_DISABLE_HT;
2324         ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
2325         ssid->disable_sgi = DEFAULT_DISABLE_SGI;
2326         ssid->disable_ldpc = DEFAULT_DISABLE_LDPC;
2327         ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
2328         ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
2329         ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
2330 #endif /* CONFIG_HT_OVERRIDES */
2331 #ifdef CONFIG_VHT_OVERRIDES
2332         ssid->vht_rx_mcs_nss_1 = -1;
2333         ssid->vht_rx_mcs_nss_2 = -1;
2334         ssid->vht_rx_mcs_nss_3 = -1;
2335         ssid->vht_rx_mcs_nss_4 = -1;
2336         ssid->vht_rx_mcs_nss_5 = -1;
2337         ssid->vht_rx_mcs_nss_6 = -1;
2338         ssid->vht_rx_mcs_nss_7 = -1;
2339         ssid->vht_rx_mcs_nss_8 = -1;
2340         ssid->vht_tx_mcs_nss_1 = -1;
2341         ssid->vht_tx_mcs_nss_2 = -1;
2342         ssid->vht_tx_mcs_nss_3 = -1;
2343         ssid->vht_tx_mcs_nss_4 = -1;
2344         ssid->vht_tx_mcs_nss_5 = -1;
2345         ssid->vht_tx_mcs_nss_6 = -1;
2346         ssid->vht_tx_mcs_nss_7 = -1;
2347         ssid->vht_tx_mcs_nss_8 = -1;
2348 #endif /* CONFIG_VHT_OVERRIDES */
2349         ssid->proactive_key_caching = -1;
2350 #ifdef CONFIG_IEEE80211W
2351         ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
2352 #endif /* CONFIG_IEEE80211W */
2353         ssid->mac_addr = -1;
2354 }
2355
2356
2357 /**
2358  * wpa_config_set - Set a variable in network configuration
2359  * @ssid: Pointer to network configuration data
2360  * @var: Variable name, e.g., "ssid"
2361  * @value: Variable value
2362  * @line: Line number in configuration file or 0 if not used
2363  * Returns: 0 on success, -1 on failure
2364  *
2365  * This function can be used to set network configuration variables based on
2366  * both the configuration file and management interface input. The value
2367  * parameter must be in the same format as the text-based configuration file is
2368  * using. For example, strings are using double quotation marks.
2369  */
2370 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
2371                    int line)
2372 {
2373         size_t i;
2374         int ret = 0;
2375
2376         if (ssid == NULL || var == NULL || value == NULL)
2377                 return -1;
2378
2379         for (i = 0; i < NUM_SSID_FIELDS; i++) {
2380                 const struct parse_data *field = &ssid_fields[i];
2381                 if (os_strcmp(var, field->name) != 0)
2382                         continue;
2383
2384                 if (field->parser(field, ssid, line, value)) {
2385                         if (line) {
2386                                 wpa_printf(MSG_ERROR, "Line %d: failed to "
2387                                            "parse %s '%s'.", line, var, value);
2388                         }
2389                         ret = -1;
2390                 }
2391                 break;
2392         }
2393         if (i == NUM_SSID_FIELDS) {
2394                 if (line) {
2395                         wpa_printf(MSG_ERROR, "Line %d: unknown network field "
2396                                    "'%s'.", line, var);
2397                 }
2398                 ret = -1;
2399         }
2400
2401         return ret;
2402 }
2403
2404
2405 int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var,
2406                           const char *value)
2407 {
2408         size_t len;
2409         char *buf;
2410         int ret;
2411
2412         len = os_strlen(value);
2413         buf = os_malloc(len + 3);
2414         if (buf == NULL)
2415                 return -1;
2416         buf[0] = '"';
2417         os_memcpy(buf + 1, value, len);
2418         buf[len + 1] = '"';
2419         buf[len + 2] = '\0';
2420         ret = wpa_config_set(ssid, var, buf, 0);
2421         os_free(buf);
2422         return ret;
2423 }
2424
2425
2426 /**
2427  * wpa_config_get_all - Get all options from network configuration
2428  * @ssid: Pointer to network configuration data
2429  * @get_keys: Determines if keys/passwords will be included in returned list
2430  *      (if they may be exported)
2431  * Returns: %NULL terminated list of all set keys and their values in the form
2432  * of [key1, val1, key2, val2, ... , NULL]
2433  *
2434  * This function can be used to get list of all configured network properties.
2435  * The caller is responsible for freeing the returned list and all its
2436  * elements.
2437  */
2438 char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
2439 {
2440         const struct parse_data *field;
2441         char *key, *value;
2442         size_t i;
2443         char **props;
2444         int fields_num;
2445
2446         get_keys = get_keys && ssid->export_keys;
2447
2448         props = os_calloc(2 * NUM_SSID_FIELDS + 1, sizeof(char *));
2449         if (!props)
2450                 return NULL;
2451
2452         fields_num = 0;
2453         for (i = 0; i < NUM_SSID_FIELDS; i++) {
2454                 field = &ssid_fields[i];
2455                 if (field->key_data && !get_keys)
2456                         continue;
2457                 value = field->writer(field, ssid);
2458                 if (value == NULL)
2459                         continue;
2460                 if (os_strlen(value) == 0) {
2461                         os_free(value);
2462                         continue;
2463                 }
2464
2465                 key = os_strdup(field->name);
2466                 if (key == NULL) {
2467                         os_free(value);
2468                         goto err;
2469                 }
2470
2471                 props[fields_num * 2] = key;
2472                 props[fields_num * 2 + 1] = value;
2473
2474                 fields_num++;
2475         }
2476
2477         return props;
2478
2479 err:
2480         value = *props;
2481         while (value)
2482                 os_free(value++);
2483         os_free(props);
2484         return NULL;
2485 }
2486
2487
2488 #ifndef NO_CONFIG_WRITE
2489 /**
2490  * wpa_config_get - Get a variable in network configuration
2491  * @ssid: Pointer to network configuration data
2492  * @var: Variable name, e.g., "ssid"
2493  * Returns: Value of the variable or %NULL on failure
2494  *
2495  * This function can be used to get network configuration variables. The
2496  * returned value is a copy of the configuration variable in text format, i.e,.
2497  * the same format that the text-based configuration file and wpa_config_set()
2498  * are using for the value. The caller is responsible for freeing the returned
2499  * value.
2500  */
2501 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
2502 {
2503         size_t i;
2504
2505         if (ssid == NULL || var == NULL)
2506                 return NULL;
2507
2508         for (i = 0; i < NUM_SSID_FIELDS; i++) {
2509                 const struct parse_data *field = &ssid_fields[i];
2510                 if (os_strcmp(var, field->name) == 0)
2511                         return field->writer(field, ssid);
2512         }
2513
2514         return NULL;
2515 }
2516
2517
2518 /**
2519  * wpa_config_get_no_key - Get a variable in network configuration (no keys)
2520  * @ssid: Pointer to network configuration data
2521  * @var: Variable name, e.g., "ssid"
2522  * Returns: Value of the variable or %NULL on failure
2523  *
2524  * This function can be used to get network configuration variable like
2525  * wpa_config_get(). The only difference is that this functions does not expose
2526  * key/password material from the configuration. In case a key/password field
2527  * is requested, the returned value is an empty string or %NULL if the variable
2528  * is not set or "*" if the variable is set (regardless of its value). The
2529  * returned value is a copy of the configuration variable in text format, i.e,.
2530  * the same format that the text-based configuration file and wpa_config_set()
2531  * are using for the value. The caller is responsible for freeing the returned
2532  * value.
2533  */
2534 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
2535 {
2536         size_t i;
2537
2538         if (ssid == NULL || var == NULL)
2539                 return NULL;
2540
2541         for (i = 0; i < NUM_SSID_FIELDS; i++) {
2542                 const struct parse_data *field = &ssid_fields[i];
2543                 if (os_strcmp(var, field->name) == 0) {
2544                         char *res = field->writer(field, ssid);
2545                         if (field->key_data) {
2546                                 if (res && res[0]) {
2547                                         wpa_printf(MSG_DEBUG, "Do not allow "
2548                                                    "key_data field to be "
2549                                                    "exposed");
2550                                         str_clear_free(res);
2551                                         return os_strdup("*");
2552                                 }
2553
2554                                 os_free(res);
2555                                 return NULL;
2556                         }
2557                         return res;
2558                 }
2559         }
2560
2561         return NULL;
2562 }
2563 #endif /* NO_CONFIG_WRITE */
2564
2565
2566 /**
2567  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
2568  * @ssid: Pointer to network configuration data
2569  *
2570  * This function must be called to update WPA PSK when either SSID or the
2571  * passphrase has changed for the network configuration.
2572  */
2573 void wpa_config_update_psk(struct wpa_ssid *ssid)
2574 {
2575 #ifndef CONFIG_NO_PBKDF2
2576         pbkdf2_sha1(ssid->passphrase, ssid->ssid, ssid->ssid_len, 4096,
2577                     ssid->psk, PMK_LEN);
2578         wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
2579                         ssid->psk, PMK_LEN);
2580         ssid->psk_set = 1;
2581 #endif /* CONFIG_NO_PBKDF2 */
2582 }
2583
2584
2585 static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred,
2586                                               const char *value)
2587 {
2588         u8 *proto;
2589         int **port;
2590         int *ports, *nports;
2591         const char *pos;
2592         unsigned int num_ports;
2593
2594         proto = os_realloc_array(cred->req_conn_capab_proto,
2595                                  cred->num_req_conn_capab + 1, sizeof(u8));
2596         if (proto == NULL)
2597                 return -1;
2598         cred->req_conn_capab_proto = proto;
2599
2600         port = os_realloc_array(cred->req_conn_capab_port,
2601                                 cred->num_req_conn_capab + 1, sizeof(int *));
2602         if (port == NULL)
2603                 return -1;
2604         cred->req_conn_capab_port = port;
2605
2606         proto[cred->num_req_conn_capab] = atoi(value);
2607
2608         pos = os_strchr(value, ':');
2609         if (pos == NULL) {
2610                 port[cred->num_req_conn_capab] = NULL;
2611                 cred->num_req_conn_capab++;
2612                 return 0;
2613         }
2614         pos++;
2615
2616         ports = NULL;
2617         num_ports = 0;
2618
2619         while (*pos) {
2620                 nports = os_realloc_array(ports, num_ports + 1, sizeof(int));
2621                 if (nports == NULL) {
2622                         os_free(ports);
2623                         return -1;
2624                 }
2625                 ports = nports;
2626                 ports[num_ports++] = atoi(pos);
2627
2628                 pos = os_strchr(pos, ',');
2629                 if (pos == NULL)
2630                         break;
2631                 pos++;
2632         }
2633
2634         nports = os_realloc_array(ports, num_ports + 1, sizeof(int));
2635         if (nports == NULL) {
2636                 os_free(ports);
2637                 return -1;
2638         }
2639         ports = nports;
2640         ports[num_ports] = -1;
2641
2642         port[cred->num_req_conn_capab] = ports;
2643         cred->num_req_conn_capab++;
2644         return 0;
2645 }
2646
2647
2648 int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
2649                         const char *value, int line)
2650 {
2651         char *val;
2652         size_t len;
2653
2654         if (os_strcmp(var, "temporary") == 0) {
2655                 cred->temporary = atoi(value);
2656                 return 0;
2657         }
2658
2659         if (os_strcmp(var, "priority") == 0) {
2660                 cred->priority = atoi(value);
2661                 return 0;
2662         }
2663
2664         if (os_strcmp(var, "sp_priority") == 0) {
2665                 int prio = atoi(value);
2666                 if (prio < 0 || prio > 255)
2667                         return -1;
2668                 cred->sp_priority = prio;
2669                 return 0;
2670         }
2671
2672         if (os_strcmp(var, "pcsc") == 0) {
2673                 cred->pcsc = atoi(value);
2674                 return 0;
2675         }
2676
2677         if (os_strcmp(var, "eap") == 0) {
2678                 struct eap_method_type method;
2679                 method.method = eap_peer_get_type(value, &method.vendor);
2680                 if (method.vendor == EAP_VENDOR_IETF &&
2681                     method.method == EAP_TYPE_NONE) {
2682                         wpa_printf(MSG_ERROR, "Line %d: unknown EAP type '%s' "
2683                                    "for a credential", line, value);
2684                         return -1;
2685                 }
2686                 os_free(cred->eap_method);
2687                 cred->eap_method = os_malloc(sizeof(*cred->eap_method));
2688                 if (cred->eap_method == NULL)
2689                         return -1;
2690                 os_memcpy(cred->eap_method, &method, sizeof(method));
2691                 return 0;
2692         }
2693
2694         if (os_strcmp(var, "password") == 0 &&
2695             os_strncmp(value, "ext:", 4) == 0) {
2696                 str_clear_free(cred->password);
2697                 cred->password = os_strdup(value);
2698                 cred->ext_password = 1;
2699                 return 0;
2700         }
2701
2702         if (os_strcmp(var, "update_identifier") == 0) {
2703                 cred->update_identifier = atoi(value);
2704                 return 0;
2705         }
2706
2707         if (os_strcmp(var, "min_dl_bandwidth_home") == 0) {
2708                 cred->min_dl_bandwidth_home = atoi(value);
2709                 return 0;
2710         }
2711
2712         if (os_strcmp(var, "min_ul_bandwidth_home") == 0) {
2713                 cred->min_ul_bandwidth_home = atoi(value);
2714                 return 0;
2715         }
2716
2717         if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0) {
2718                 cred->min_dl_bandwidth_roaming = atoi(value);
2719                 return 0;
2720         }
2721
2722         if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0) {
2723                 cred->min_ul_bandwidth_roaming = atoi(value);
2724                 return 0;
2725         }
2726
2727         if (os_strcmp(var, "max_bss_load") == 0) {
2728                 cred->max_bss_load = atoi(value);
2729                 return 0;
2730         }
2731
2732         if (os_strcmp(var, "req_conn_capab") == 0)
2733                 return wpa_config_set_cred_req_conn_capab(cred, value);
2734
2735         if (os_strcmp(var, "ocsp") == 0) {
2736                 cred->ocsp = atoi(value);
2737                 return 0;
2738         }
2739
2740         if (os_strcmp(var, "sim_num") == 0) {
2741                 cred->sim_num = atoi(value);
2742                 return 0;
2743         }
2744
2745         val = wpa_config_parse_string(value, &len);
2746         if (val == NULL) {
2747                 wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
2748                            "value '%s'.", line, var, value);
2749                 return -1;
2750         }
2751
2752         if (os_strcmp(var, "realm") == 0) {
2753                 os_free(cred->realm);
2754                 cred->realm = val;
2755                 return 0;
2756         }
2757
2758         if (os_strcmp(var, "username") == 0) {
2759                 str_clear_free(cred->username);
2760                 cred->username = val;
2761                 return 0;
2762         }
2763
2764         if (os_strcmp(var, "password") == 0) {
2765                 str_clear_free(cred->password);
2766                 cred->password = val;
2767                 cred->ext_password = 0;
2768                 return 0;
2769         }
2770
2771         if (os_strcmp(var, "ca_cert") == 0) {
2772                 os_free(cred->ca_cert);
2773                 cred->ca_cert = val;
2774                 return 0;
2775         }
2776
2777         if (os_strcmp(var, "client_cert") == 0) {
2778                 os_free(cred->client_cert);
2779                 cred->client_cert = val;
2780                 return 0;
2781         }
2782
2783         if (os_strcmp(var, "private_key") == 0) {
2784                 os_free(cred->private_key);
2785                 cred->private_key = val;
2786                 return 0;
2787         }
2788
2789         if (os_strcmp(var, "private_key_passwd") == 0) {
2790                 str_clear_free(cred->private_key_passwd);
2791                 cred->private_key_passwd = val;
2792                 return 0;
2793         }
2794
2795         if (os_strcmp(var, "imsi") == 0) {
2796                 os_free(cred->imsi);
2797                 cred->imsi = val;
2798                 return 0;
2799         }
2800
2801         if (os_strcmp(var, "milenage") == 0) {
2802                 str_clear_free(cred->milenage);
2803                 cred->milenage = val;
2804                 return 0;
2805         }
2806
2807         if (os_strcmp(var, "domain_suffix_match") == 0) {
2808                 os_free(cred->domain_suffix_match);
2809                 cred->domain_suffix_match = val;
2810                 return 0;
2811         }
2812
2813         if (os_strcmp(var, "domain") == 0) {
2814                 char **new_domain;
2815                 new_domain = os_realloc_array(cred->domain,
2816                                               cred->num_domain + 1,
2817                                               sizeof(char *));
2818                 if (new_domain == NULL) {
2819                         os_free(val);
2820                         return -1;
2821                 }
2822                 new_domain[cred->num_domain++] = val;
2823                 cred->domain = new_domain;
2824                 return 0;
2825         }
2826
2827         if (os_strcmp(var, "phase1") == 0) {
2828                 os_free(cred->phase1);
2829                 cred->phase1 = val;
2830                 return 0;
2831         }
2832
2833         if (os_strcmp(var, "phase2") == 0) {
2834                 os_free(cred->phase2);
2835                 cred->phase2 = val;
2836                 return 0;
2837         }
2838
2839         if (os_strcmp(var, "roaming_consortium") == 0) {
2840                 if (len < 3 || len > sizeof(cred->roaming_consortium)) {
2841                         wpa_printf(MSG_ERROR, "Line %d: invalid "
2842                                    "roaming_consortium length %d (3..15 "
2843                                    "expected)", line, (int) len);
2844                         os_free(val);
2845                         return -1;
2846                 }
2847                 os_memcpy(cred->roaming_consortium, val, len);
2848                 cred->roaming_consortium_len = len;
2849                 os_free(val);
2850                 return 0;
2851         }
2852
2853         if (os_strcmp(var, "required_roaming_consortium") == 0) {
2854                 if (len < 3 || len > sizeof(cred->required_roaming_consortium))
2855                 {
2856                         wpa_printf(MSG_ERROR, "Line %d: invalid "
2857                                    "required_roaming_consortium length %d "
2858                                    "(3..15 expected)", line, (int) len);
2859                         os_free(val);
2860                         return -1;
2861                 }
2862                 os_memcpy(cred->required_roaming_consortium, val, len);
2863                 cred->required_roaming_consortium_len = len;
2864                 os_free(val);
2865                 return 0;
2866         }
2867
2868         if (os_strcmp(var, "excluded_ssid") == 0) {
2869                 struct excluded_ssid *e;
2870
2871                 if (len > MAX_SSID_LEN) {
2872                         wpa_printf(MSG_ERROR, "Line %d: invalid "
2873                                    "excluded_ssid length %d", line, (int) len);
2874                         os_free(val);
2875                         return -1;
2876                 }
2877
2878                 e = os_realloc_array(cred->excluded_ssid,
2879                                      cred->num_excluded_ssid + 1,
2880                                      sizeof(struct excluded_ssid));
2881                 if (e == NULL) {
2882                         os_free(val);
2883                         return -1;
2884                 }
2885                 cred->excluded_ssid = e;
2886
2887                 e = &cred->excluded_ssid[cred->num_excluded_ssid++];
2888                 os_memcpy(e->ssid, val, len);
2889                 e->ssid_len = len;
2890
2891                 os_free(val);
2892
2893                 return 0;
2894         }
2895
2896         if (os_strcmp(var, "roaming_partner") == 0) {
2897                 struct roaming_partner *p;
2898                 char *pos;
2899
2900                 p = os_realloc_array(cred->roaming_partner,
2901                                      cred->num_roaming_partner + 1,
2902                                      sizeof(struct roaming_partner));
2903                 if (p == NULL) {
2904                         os_free(val);
2905                         return -1;
2906                 }
2907                 cred->roaming_partner = p;
2908
2909                 p = &cred->roaming_partner[cred->num_roaming_partner];
2910
2911                 pos = os_strchr(val, ',');
2912                 if (pos == NULL) {
2913                         os_free(val);
2914                         return -1;
2915                 }
2916                 *pos++ = '\0';
2917                 if (pos - val - 1 >= (int) sizeof(p->fqdn)) {
2918                         os_free(val);
2919                         return -1;
2920                 }
2921                 os_memcpy(p->fqdn, val, pos - val);
2922
2923                 p->exact_match = atoi(pos);
2924
2925                 pos = os_strchr(pos, ',');
2926                 if (pos == NULL) {
2927                         os_free(val);
2928                         return -1;
2929                 }
2930                 *pos++ = '\0';
2931
2932                 p->priority = atoi(pos);
2933
2934                 pos = os_strchr(pos, ',');
2935                 if (pos == NULL) {
2936                         os_free(val);
2937                         return -1;
2938                 }
2939                 *pos++ = '\0';
2940
2941                 if (os_strlen(pos) >= sizeof(p->country)) {
2942                         os_free(val);
2943                         return -1;
2944                 }
2945                 os_memcpy(p->country, pos, os_strlen(pos) + 1);
2946
2947                 cred->num_roaming_partner++;
2948                 os_free(val);
2949
2950                 return 0;
2951         }
2952
2953         if (os_strcmp(var, "provisioning_sp") == 0) {
2954                 os_free(cred->provisioning_sp);
2955                 cred->provisioning_sp = val;
2956                 return 0;
2957         }
2958
2959         if (line) {
2960                 wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.",
2961                            line, var);
2962         }
2963
2964         os_free(val);
2965
2966         return -1;
2967 }
2968
2969
2970 static char * alloc_int_str(int val)
2971 {
2972         const unsigned int bufsize = 20;
2973         char *buf;
2974         int res;
2975
2976         buf = os_malloc(bufsize);
2977         if (buf == NULL)
2978                 return NULL;
2979         res = os_snprintf(buf, bufsize, "%d", val);
2980         if (os_snprintf_error(bufsize, res)) {
2981                 os_free(buf);
2982                 buf = NULL;
2983         }
2984         return buf;
2985 }
2986
2987
2988 static char * alloc_strdup(const char *str)
2989 {
2990         if (str == NULL)
2991                 return NULL;
2992         return os_strdup(str);
2993 }
2994
2995
2996 char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
2997 {
2998         if (os_strcmp(var, "temporary") == 0)
2999                 return alloc_int_str(cred->temporary);
3000
3001         if (os_strcmp(var, "priority") == 0)
3002                 return alloc_int_str(cred->priority);
3003
3004         if (os_strcmp(var, "sp_priority") == 0)
3005                 return alloc_int_str(cred->sp_priority);
3006
3007         if (os_strcmp(var, "pcsc") == 0)
3008                 return alloc_int_str(cred->pcsc);
3009
3010         if (os_strcmp(var, "eap") == 0) {
3011                 if (!cred->eap_method)
3012                         return NULL;
3013                 return alloc_strdup(eap_get_name(cred->eap_method[0].vendor,
3014                                                  cred->eap_method[0].method));
3015         }
3016
3017         if (os_strcmp(var, "update_identifier") == 0)
3018                 return alloc_int_str(cred->update_identifier);
3019
3020         if (os_strcmp(var, "min_dl_bandwidth_home") == 0)
3021                 return alloc_int_str(cred->min_dl_bandwidth_home);
3022
3023         if (os_strcmp(var, "min_ul_bandwidth_home") == 0)
3024                 return alloc_int_str(cred->min_ul_bandwidth_home);
3025
3026         if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0)
3027                 return alloc_int_str(cred->min_dl_bandwidth_roaming);
3028
3029         if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0)
3030                 return alloc_int_str(cred->min_ul_bandwidth_roaming);
3031
3032         if (os_strcmp(var, "max_bss_load") == 0)
3033                 return alloc_int_str(cred->max_bss_load);
3034
3035         if (os_strcmp(var, "req_conn_capab") == 0) {
3036                 unsigned int i;
3037                 char *buf, *end, *pos;
3038                 int ret;
3039
3040                 if (!cred->num_req_conn_capab)
3041                         return NULL;
3042
3043                 buf = os_malloc(4000);
3044                 if (buf == NULL)
3045                         return NULL;
3046                 pos = buf;
3047                 end = pos + 4000;
3048                 for (i = 0; i < cred->num_req_conn_capab; i++) {
3049                         int *ports;
3050
3051                         ret = os_snprintf(pos, end - pos, "%s%u",
3052                                           i > 0 ? "\n" : "",
3053                                           cred->req_conn_capab_proto[i]);
3054                         if (os_snprintf_error(end - pos, ret))
3055                                 return buf;
3056                         pos += ret;
3057
3058                         ports = cred->req_conn_capab_port[i];
3059                         if (ports) {
3060                                 int j;
3061                                 for (j = 0; ports[j] != -1; j++) {
3062                                         ret = os_snprintf(pos, end - pos,
3063                                                           "%s%d",
3064                                                           j > 0 ? "," : ":",
3065                                                           ports[j]);
3066                                         if (os_snprintf_error(end - pos, ret))
3067                                                 return buf;
3068                                         pos += ret;
3069                                 }
3070                         }
3071                 }
3072
3073                 return buf;
3074         }
3075
3076         if (os_strcmp(var, "ocsp") == 0)
3077                 return alloc_int_str(cred->ocsp);
3078
3079         if (os_strcmp(var, "realm") == 0)
3080                 return alloc_strdup(cred->realm);
3081
3082         if (os_strcmp(var, "username") == 0)
3083                 return alloc_strdup(cred->username);
3084
3085         if (os_strcmp(var, "password") == 0) {
3086                 if (!cred->password)
3087                         return NULL;
3088                 return alloc_strdup("*");
3089         }
3090
3091         if (os_strcmp(var, "ca_cert") == 0)
3092                 return alloc_strdup(cred->ca_cert);
3093
3094         if (os_strcmp(var, "client_cert") == 0)
3095                 return alloc_strdup(cred->client_cert);
3096
3097         if (os_strcmp(var, "private_key") == 0)
3098                 return alloc_strdup(cred->private_key);
3099
3100         if (os_strcmp(var, "private_key_passwd") == 0) {
3101                 if (!cred->private_key_passwd)
3102                         return NULL;
3103                 return alloc_strdup("*");
3104         }
3105
3106         if (os_strcmp(var, "imsi") == 0)
3107                 return alloc_strdup(cred->imsi);
3108
3109         if (os_strcmp(var, "milenage") == 0) {
3110                 if (!(cred->milenage))
3111                         return NULL;
3112                 return alloc_strdup("*");
3113         }
3114
3115         if (os_strcmp(var, "domain_suffix_match") == 0)
3116                 return alloc_strdup(cred->domain_suffix_match);
3117
3118         if (os_strcmp(var, "domain") == 0) {
3119                 unsigned int i;
3120                 char *buf, *end, *pos;
3121                 int ret;
3122
3123                 if (!cred->num_domain)
3124                         return NULL;
3125
3126                 buf = os_malloc(4000);
3127                 if (buf == NULL)
3128                         return NULL;
3129                 pos = buf;
3130                 end = pos + 4000;
3131
3132                 for (i = 0; i < cred->num_domain; i++) {
3133                         ret = os_snprintf(pos, end - pos, "%s%s",
3134                                           i > 0 ? "\n" : "", cred->domain[i]);
3135                         if (os_snprintf_error(end - pos, ret))
3136                                 return buf;
3137                         pos += ret;
3138                 }
3139
3140                 return buf;
3141         }
3142
3143         if (os_strcmp(var, "phase1") == 0)
3144                 return alloc_strdup(cred->phase1);
3145
3146         if (os_strcmp(var, "phase2") == 0)
3147                 return alloc_strdup(cred->phase2);
3148
3149         if (os_strcmp(var, "roaming_consortium") == 0) {
3150                 size_t buflen;
3151                 char *buf;
3152
3153                 if (!cred->roaming_consortium_len)
3154                         return NULL;
3155                 buflen = cred->roaming_consortium_len * 2 + 1;
3156                 buf = os_malloc(buflen);
3157                 if (buf == NULL)
3158                         return NULL;
3159                 wpa_snprintf_hex(buf, buflen, cred->roaming_consortium,
3160                                  cred->roaming_consortium_len);
3161                 return buf;
3162         }
3163
3164         if (os_strcmp(var, "required_roaming_consortium") == 0) {
3165                 size_t buflen;
3166                 char *buf;
3167
3168                 if (!cred->required_roaming_consortium_len)
3169                         return NULL;
3170                 buflen = cred->required_roaming_consortium_len * 2 + 1;
3171                 buf = os_malloc(buflen);
3172                 if (buf == NULL)
3173                         return NULL;
3174                 wpa_snprintf_hex(buf, buflen, cred->required_roaming_consortium,
3175                                  cred->required_roaming_consortium_len);
3176                 return buf;
3177         }
3178
3179         if (os_strcmp(var, "excluded_ssid") == 0) {
3180                 unsigned int i;
3181                 char *buf, *end, *pos;
3182
3183                 if (!cred->num_excluded_ssid)
3184                         return NULL;
3185
3186                 buf = os_malloc(4000);
3187                 if (buf == NULL)
3188                         return NULL;
3189                 pos = buf;
3190                 end = pos + 4000;
3191
3192                 for (i = 0; i < cred->num_excluded_ssid; i++) {
3193                         struct excluded_ssid *e;
3194                         int ret;
3195
3196                         e = &cred->excluded_ssid[i];
3197                         ret = os_snprintf(pos, end - pos, "%s%s",
3198                                           i > 0 ? "\n" : "",
3199                                           wpa_ssid_txt(e->ssid, e->ssid_len));
3200                         if (os_snprintf_error(end - pos, ret))
3201                                 return buf;
3202                         pos += ret;
3203                 }
3204
3205                 return buf;
3206         }
3207
3208         if (os_strcmp(var, "roaming_partner") == 0) {
3209                 unsigned int i;
3210                 char *buf, *end, *pos;
3211
3212                 if (!cred->num_roaming_partner)
3213                         return NULL;
3214
3215                 buf = os_malloc(4000);
3216                 if (buf == NULL)
3217                         return NULL;
3218                 pos = buf;
3219                 end = pos + 4000;
3220
3221                 for (i = 0; i < cred->num_roaming_partner; i++) {
3222                         struct roaming_partner *p;
3223                         int ret;
3224
3225                         p = &cred->roaming_partner[i];
3226                         ret = os_snprintf(pos, end - pos, "%s%s,%d,%u,%s",
3227                                           i > 0 ? "\n" : "",
3228                                           p->fqdn, p->exact_match, p->priority,
3229                                           p->country);
3230                         if (os_snprintf_error(end - pos, ret))
3231                                 return buf;
3232                         pos += ret;
3233                 }
3234
3235                 return buf;
3236         }
3237
3238         if (os_strcmp(var, "provisioning_sp") == 0)
3239                 return alloc_strdup(cred->provisioning_sp);
3240
3241         return NULL;
3242 }
3243
3244
3245 struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id)
3246 {
3247         struct wpa_cred *cred;
3248
3249         cred = config->cred;
3250         while (cred) {
3251                 if (id == cred->id)
3252                         break;
3253                 cred = cred->next;
3254         }
3255
3256         return cred;
3257 }
3258
3259
3260 struct wpa_cred * wpa_config_add_cred(struct wpa_config *config)
3261 {
3262         int id;
3263         struct wpa_cred *cred, *last = NULL;
3264
3265         id = -1;
3266         cred = config->cred;
3267         while (cred) {
3268                 if (cred->id > id)
3269                         id = cred->id;
3270                 last = cred;
3271                 cred = cred->next;
3272         }
3273         id++;
3274
3275         cred = os_zalloc(sizeof(*cred));
3276         if (cred == NULL)
3277                 return NULL;
3278         cred->id = id;
3279         cred->sim_num = DEFAULT_USER_SELECTED_SIM;
3280         if (last)
3281                 last->next = cred;
3282         else
3283                 config->cred = cred;
3284
3285         return cred;
3286 }
3287
3288
3289 int wpa_config_remove_cred(struct wpa_config *config, int id)
3290 {
3291         struct wpa_cred *cred, *prev = NULL;
3292
3293         cred = config->cred;
3294         while (cred) {
3295                 if (id == cred->id)
3296                         break;
3297                 prev = cred;
3298                 cred = cred->next;
3299         }
3300
3301         if (cred == NULL)
3302                 return -1;
3303
3304         if (prev)
3305                 prev->next = cred->next;
3306         else
3307                 config->cred = cred->next;
3308
3309         wpa_config_free_cred(cred);
3310         return 0;
3311 }
3312
3313
3314 #ifndef CONFIG_NO_CONFIG_BLOBS
3315 /**
3316  * wpa_config_get_blob - Get a named configuration blob
3317  * @config: Configuration data from wpa_config_read()
3318  * @name: Name of the blob
3319  * Returns: Pointer to blob data or %NULL if not found
3320  */
3321 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
3322                                                    const char *name)
3323 {
3324         struct wpa_config_blob *blob = config->blobs;
3325
3326         while (blob) {
3327                 if (os_strcmp(blob->name, name) == 0)
3328                         return blob;
3329                 blob = blob->next;
3330         }
3331         return NULL;
3332 }
3333
3334
3335 /**
3336  * wpa_config_set_blob - Set or add a named configuration blob
3337  * @config: Configuration data from wpa_config_read()
3338  * @blob: New value for the blob
3339  *
3340  * Adds a new configuration blob or replaces the current value of an existing
3341  * blob.
3342  */
3343 void wpa_config_set_blob(struct wpa_config *config,
3344                          struct wpa_config_blob *blob)
3345 {
3346         wpa_config_remove_blob(config, blob->name);
3347         blob->next = config->blobs;
3348         config->blobs = blob;
3349 }
3350
3351
3352 /**
3353  * wpa_config_free_blob - Free blob data
3354  * @blob: Pointer to blob to be freed
3355  */
3356 void wpa_config_free_blob(struct wpa_config_blob *blob)
3357 {
3358         if (blob) {
3359                 os_free(blob->name);
3360                 bin_clear_free(blob->data, blob->len);
3361                 os_free(blob);
3362         }
3363 }
3364
3365
3366 /**
3367  * wpa_config_remove_blob - Remove a named configuration blob
3368  * @config: Configuration data from wpa_config_read()
3369  * @name: Name of the blob to remove
3370  * Returns: 0 if blob was removed or -1 if blob was not found
3371  */
3372 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
3373 {
3374         struct wpa_config_blob *pos = config->blobs, *prev = NULL;
3375
3376         while (pos) {
3377                 if (os_strcmp(pos->name, name) == 0) {
3378                         if (prev)
3379                                 prev->next = pos->next;
3380                         else
3381                                 config->blobs = pos->next;
3382                         wpa_config_free_blob(pos);
3383                         return 0;
3384                 }
3385                 prev = pos;
3386                 pos = pos->next;
3387         }
3388
3389         return -1;
3390 }
3391 #endif /* CONFIG_NO_CONFIG_BLOBS */
3392
3393
3394 /**
3395  * wpa_config_alloc_empty - Allocate an empty configuration
3396  * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
3397  * socket
3398  * @driver_param: Driver parameters
3399  * Returns: Pointer to allocated configuration data or %NULL on failure
3400  */
3401 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
3402                                            const char *driver_param)
3403 {
3404         struct wpa_config *config;
3405         const int aCWmin = 4, aCWmax = 10;
3406         const struct hostapd_wmm_ac_params ac_bk =
3407                 { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
3408         const struct hostapd_wmm_ac_params ac_be =
3409                 { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
3410         const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
3411                 { aCWmin - 1, aCWmin, 2, 3000 / 32, 0 };
3412         const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
3413                 { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 };
3414
3415         config = os_zalloc(sizeof(*config));
3416         if (config == NULL)
3417                 return NULL;
3418         config->eapol_version = DEFAULT_EAPOL_VERSION;
3419         config->ap_scan = DEFAULT_AP_SCAN;
3420         config->user_mpm = DEFAULT_USER_MPM;
3421         config->max_peer_links = DEFAULT_MAX_PEER_LINKS;
3422         config->fast_reauth = DEFAULT_FAST_REAUTH;
3423         config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
3424         config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
3425         config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY;
3426         config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN;
3427         config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
3428         config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
3429         config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
3430         config->max_num_sta = DEFAULT_MAX_NUM_STA;
3431         config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
3432         config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ;
3433         config->wmm_ac_params[0] = ac_be;
3434         config->wmm_ac_params[1] = ac_bk;
3435         config->wmm_ac_params[2] = ac_vi;
3436         config->wmm_ac_params[3] = ac_vo;
3437         config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY;
3438         config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
3439         config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD;
3440
3441         if (ctrl_interface)
3442                 config->ctrl_interface = os_strdup(ctrl_interface);
3443         if (driver_param)
3444                 config->driver_param = os_strdup(driver_param);
3445
3446         return config;
3447 }
3448
3449
3450 #ifndef CONFIG_NO_STDOUT_DEBUG
3451 /**
3452  * wpa_config_debug_dump_networks - Debug dump of configured networks
3453  * @config: Configuration data from wpa_config_read()
3454  */
3455 void wpa_config_debug_dump_networks(struct wpa_config *config)
3456 {
3457         int prio;
3458         struct wpa_ssid *ssid;
3459
3460         for (prio = 0; prio < config->num_prio; prio++) {
3461                 ssid = config->pssid[prio];
3462                 wpa_printf(MSG_DEBUG, "Priority group %d",
3463                            ssid->priority);
3464                 while (ssid) {
3465                         wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
3466                                    ssid->id,
3467                                    wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
3468                         ssid = ssid->pnext;
3469                 }
3470         }
3471 }
3472 #endif /* CONFIG_NO_STDOUT_DEBUG */
3473
3474
3475 struct global_parse_data {
3476         char *name;
3477         int (*parser)(const struct global_parse_data *data,
3478                       struct wpa_config *config, int line, const char *value);
3479         void *param1, *param2, *param3;
3480         unsigned int changed_flag;
3481 };
3482
3483
3484 static int wpa_global_config_parse_int(const struct global_parse_data *data,
3485                                        struct wpa_config *config, int line,
3486                                        const char *pos)
3487 {
3488         int val, *dst;
3489         char *end;
3490
3491         dst = (int *) (((u8 *) config) + (long) data->param1);
3492         val = strtol(pos, &end, 0);
3493         if (*end) {
3494                 wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"",
3495                            line, pos);
3496                 return -1;
3497         }
3498         *dst = val;
3499
3500         wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
3501
3502         if (data->param2 && *dst < (long) data->param2) {
3503                 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
3504                            "min_value=%ld)", line, data->name, *dst,
3505                            (long) data->param2);
3506                 *dst = (long) data->param2;
3507                 return -1;
3508         }
3509
3510         if (data->param3 && *dst > (long) data->param3) {
3511                 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
3512                            "max_value=%ld)", line, data->name, *dst,
3513                            (long) data->param3);
3514                 *dst = (long) data->param3;
3515                 return -1;
3516         }
3517
3518         return 0;
3519 }
3520
3521
3522 static int wpa_global_config_parse_str(const struct global_parse_data *data,
3523                                        struct wpa_config *config, int line,
3524                                        const char *pos)
3525 {
3526         size_t len;
3527         char **dst, *tmp;
3528
3529         len = os_strlen(pos);
3530         if (data->param2 && len < (size_t) data->param2) {
3531                 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
3532                            "min_len=%ld)", line, data->name,
3533                            (unsigned long) len, (long) data->param2);
3534                 return -1;
3535         }
3536
3537         if (data->param3 && len > (size_t) data->param3) {
3538                 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
3539                            "max_len=%ld)", line, data->name,
3540                            (unsigned long) len, (long) data->param3);
3541                 return -1;
3542         }
3543
3544         tmp = os_strdup(pos);
3545         if (tmp == NULL)
3546                 return -1;
3547
3548         dst = (char **) (((u8 *) config) + (long) data->param1);
3549         os_free(*dst);
3550         *dst = tmp;
3551         wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
3552
3553         return 0;
3554 }
3555
3556
3557 static int wpa_config_process_bgscan(const struct global_parse_data *data,
3558                                      struct wpa_config *config, int line,
3559                                      const char *pos)
3560 {
3561         size_t len;
3562         char *tmp;
3563         int res;
3564
3565         tmp = wpa_config_parse_string(pos, &len);
3566         if (tmp == NULL) {
3567                 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s",
3568                            line, data->name);
3569                 return -1;
3570         }
3571
3572         res = wpa_global_config_parse_str(data, config, line, tmp);
3573         os_free(tmp);
3574         return res;
3575 }
3576
3577
3578 static int wpa_global_config_parse_bin(const struct global_parse_data *data,
3579                                        struct wpa_config *config, int line,
3580                                        const char *pos)
3581 {
3582         size_t len;
3583         struct wpabuf **dst, *tmp;
3584
3585         len = os_strlen(pos);
3586         if (len & 0x01)
3587                 return -1;
3588
3589         tmp = wpabuf_alloc(len / 2);
3590         if (tmp == NULL)
3591                 return -1;
3592
3593         if (hexstr2bin(pos, wpabuf_put(tmp, len / 2), len / 2)) {
3594                 wpabuf_free(tmp);
3595                 return -1;
3596         }
3597
3598         dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1);
3599         wpabuf_free(*dst);
3600         *dst = tmp;
3601         wpa_printf(MSG_DEBUG, "%s", data->name);
3602
3603         return 0;
3604 }
3605
3606
3607 static int wpa_config_process_freq_list(const struct global_parse_data *data,
3608                                         struct wpa_config *config, int line,
3609                                         const char *value)
3610 {
3611         int *freqs;
3612
3613         freqs = wpa_config_parse_int_array(value);
3614         if (freqs == NULL)
3615                 return -1;
3616         if (freqs[0] == 0) {
3617                 os_free(freqs);
3618                 freqs = NULL;
3619         }
3620         os_free(config->freq_list);
3621         config->freq_list = freqs;
3622         return 0;
3623 }
3624
3625
3626 #ifdef CONFIG_P2P
3627 static int wpa_global_config_parse_ipv4(const struct global_parse_data *data,
3628                                         struct wpa_config *config, int line,
3629                                         const char *pos)
3630 {
3631         u32 *dst;
3632         struct hostapd_ip_addr addr;
3633
3634         if (hostapd_parse_ip_addr(pos, &addr) < 0)
3635                 return -1;
3636         if (addr.af != AF_INET)
3637                 return -1;
3638
3639         dst = (u32 *) (((u8 *) config) + (long) data->param1);
3640         os_memcpy(dst, &addr.u.v4.s_addr, 4);
3641         wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name,
3642                    WPA_GET_BE32((u8 *) dst));
3643
3644         return 0;
3645 }
3646 #endif /* CONFIG_P2P */
3647
3648
3649 static int wpa_config_process_country(const struct global_parse_data *data,
3650                                       struct wpa_config *config, int line,
3651                                       const char *pos)
3652 {
3653         if (!pos[0] || !pos[1]) {
3654                 wpa_printf(MSG_DEBUG, "Invalid country set");
3655                 return -1;
3656         }
3657         config->country[0] = pos[0];
3658         config->country[1] = pos[1];
3659         wpa_printf(MSG_DEBUG, "country='%c%c'",
3660                    config->country[0], config->country[1]);
3661         return 0;
3662 }
3663
3664
3665 static int wpa_config_process_load_dynamic_eap(
3666         const struct global_parse_data *data, struct wpa_config *config,
3667         int line, const char *so)
3668 {
3669         int ret;
3670         wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
3671         ret = eap_peer_method_load(so);
3672         if (ret == -2) {
3673                 wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
3674                            "reloading.");
3675         } else if (ret) {
3676                 wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
3677                            "method '%s'.", line, so);
3678                 return -1;
3679         }
3680
3681         return 0;
3682 }
3683
3684
3685 #ifdef CONFIG_WPS
3686
3687 static int wpa_config_process_uuid(const struct global_parse_data *data,
3688                                    struct wpa_config *config, int line,
3689                                    const char *pos)
3690 {
3691         char buf[40];
3692         if (uuid_str2bin(pos, config->uuid)) {
3693                 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
3694                 return -1;
3695         }
3696         uuid_bin2str(config->uuid, buf, sizeof(buf));
3697         wpa_printf(MSG_DEBUG, "uuid=%s", buf);
3698         return 0;
3699 }
3700
3701
3702 static int wpa_config_process_device_type(
3703         const struct global_parse_data *data,
3704         struct wpa_config *config, int line, const char *pos)
3705 {
3706         return wps_dev_type_str2bin(pos, config->device_type);
3707 }
3708
3709
3710 static int wpa_config_process_os_version(const struct global_parse_data *data,
3711                                          struct wpa_config *config, int line,
3712                                          const char *pos)
3713 {
3714         if (hexstr2bin(pos, config->os_version, 4)) {
3715                 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
3716                 return -1;
3717         }
3718         wpa_printf(MSG_DEBUG, "os_version=%08x",
3719                    WPA_GET_BE32(config->os_version));
3720         return 0;
3721 }
3722
3723
3724 static int wpa_config_process_wps_vendor_ext_m1(
3725         const struct global_parse_data *data,
3726         struct wpa_config *config, int line, const char *pos)
3727 {
3728         struct wpabuf *tmp;
3729         int len = os_strlen(pos) / 2;
3730         u8 *p;
3731
3732         if (!len) {
3733                 wpa_printf(MSG_ERROR, "Line %d: "
3734                            "invalid wps_vendor_ext_m1", line);
3735                 return -1;
3736         }
3737
3738         tmp = wpabuf_alloc(len);
3739         if (tmp) {
3740                 p = wpabuf_put(tmp, len);
3741
3742                 if (hexstr2bin(pos, p, len)) {
3743                         wpa_printf(MSG_ERROR, "Line %d: "
3744                                    "invalid wps_vendor_ext_m1", line);
3745                         wpabuf_free(tmp);
3746                         return -1;
3747                 }
3748
3749                 wpabuf_free(config->wps_vendor_ext_m1);
3750                 config->wps_vendor_ext_m1 = tmp;
3751         } else {
3752                 wpa_printf(MSG_ERROR, "Can not allocate "
3753                            "memory for wps_vendor_ext_m1");
3754                 return -1;
3755         }
3756
3757         return 0;
3758 }
3759
3760 #endif /* CONFIG_WPS */
3761
3762 #ifdef CONFIG_P2P
3763 static int wpa_config_process_sec_device_type(
3764         const struct global_parse_data *data,
3765         struct wpa_config *config, int line, const char *pos)
3766 {
3767         int idx;
3768
3769         if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) {
3770                 wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type "
3771                            "items", line);
3772                 return -1;
3773         }
3774
3775         idx = config->num_sec_device_types;
3776
3777         if (wps_dev_type_str2bin(pos, config->sec_device_type[idx]))
3778                 return -1;
3779
3780         config->num_sec_device_types++;
3781         return 0;
3782 }
3783
3784
3785 static int wpa_config_process_p2p_pref_chan(
3786         const struct global_parse_data *data,
3787         struct wpa_config *config, int line, const char *pos)
3788 {
3789         struct p2p_channel *pref = NULL, *n;
3790         unsigned int num = 0;
3791         const char *pos2;
3792         u8 op_class, chan;
3793
3794         /* format: class:chan,class:chan,... */
3795
3796         while (*pos) {
3797                 op_class = atoi(pos);
3798                 pos2 = os_strchr(pos, ':');
3799                 if (pos2 == NULL)
3800                         goto fail;
3801                 pos2++;
3802                 chan = atoi(pos2);
3803
3804                 n = os_realloc_array(pref, num + 1,
3805                                      sizeof(struct p2p_channel));
3806                 if (n == NULL)
3807                         goto fail;
3808                 pref = n;
3809                 pref[num].op_class = op_class;
3810                 pref[num].chan = chan;
3811                 num++;
3812
3813                 pos = os_strchr(pos2, ',');
3814                 if (pos == NULL)
3815                         break;
3816                 pos++;
3817         }
3818
3819         os_free(config->p2p_pref_chan);
3820         config->p2p_pref_chan = pref;
3821         config->num_p2p_pref_chan = num;
3822         wpa_hexdump(MSG_DEBUG, "P2P: Preferred class/channel pairs",
3823                     (u8 *) config->p2p_pref_chan,
3824                     config->num_p2p_pref_chan * sizeof(struct p2p_channel));
3825
3826         return 0;
3827
3828 fail:
3829         os_free(pref);
3830         wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_pref_chan list", line);
3831         return -1;
3832 }
3833
3834
3835 static int wpa_config_process_p2p_no_go_freq(
3836         const struct global_parse_data *data,
3837         struct wpa_config *config, int line, const char *pos)
3838 {
3839         int ret;
3840
3841         ret = freq_range_list_parse(&config->p2p_no_go_freq, pos);
3842         if (ret < 0) {
3843                 wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_no_go_freq", line);
3844                 return -1;
3845         }
3846
3847         wpa_printf(MSG_DEBUG, "P2P: p2p_no_go_freq with %u items",
3848                    config->p2p_no_go_freq.num);
3849
3850         return 0;
3851 }
3852
3853 #endif /* CONFIG_P2P */
3854
3855
3856 static int wpa_config_process_hessid(
3857         const struct global_parse_data *data,
3858         struct wpa_config *config, int line, const char *pos)
3859 {
3860         if (hwaddr_aton2(pos, config->hessid) < 0) {
3861                 wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'",
3862                            line, pos);
3863                 return -1;
3864         }
3865
3866         return 0;
3867 }
3868
3869
3870 static int wpa_config_process_sae_groups(
3871         const struct global_parse_data *data,
3872         struct wpa_config *config, int line, const char *pos)
3873 {
3874         int *groups = wpa_config_parse_int_array(pos);
3875         if (groups == NULL) {
3876                 wpa_printf(MSG_ERROR, "Line %d: Invalid sae_groups '%s'",
3877                            line, pos);
3878                 return -1;
3879         }
3880
3881         os_free(config->sae_groups);
3882         config->sae_groups = groups;
3883
3884         return 0;
3885 }
3886
3887
3888 static int wpa_config_process_ap_vendor_elements(
3889         const struct global_parse_data *data,
3890         struct wpa_config *config, int line, const char *pos)
3891 {
3892         struct wpabuf *tmp;
3893         int len = os_strlen(pos) / 2;
3894         u8 *p;
3895
3896         if (!len) {
3897                 wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements",
3898                            line);
3899                 return -1;
3900         }
3901
3902         tmp = wpabuf_alloc(len);
3903         if (tmp) {
3904                 p = wpabuf_put(tmp, len);
3905
3906                 if (hexstr2bin(pos, p, len)) {
3907                         wpa_printf(MSG_ERROR, "Line %d: invalid "
3908                                    "ap_vendor_elements", line);
3909                         wpabuf_free(tmp);
3910                         return -1;
3911                 }
3912
3913                 wpabuf_free(config->ap_vendor_elements);
3914                 config->ap_vendor_elements = tmp;
3915         } else {
3916                 wpa_printf(MSG_ERROR, "Cannot allocate memory for "
3917                            "ap_vendor_elements");
3918                 return -1;
3919         }
3920
3921         return 0;
3922 }
3923
3924
3925 #ifdef CONFIG_CTRL_IFACE
3926 static int wpa_config_process_no_ctrl_interface(
3927         const struct global_parse_data *data,
3928         struct wpa_config *config, int line, const char *pos)
3929 {
3930         wpa_printf(MSG_DEBUG, "no_ctrl_interface -> ctrl_interface=NULL");
3931         os_free(config->ctrl_interface);
3932         config->ctrl_interface = NULL;
3933         return 0;
3934 }
3935 #endif /* CONFIG_CTRL_IFACE */
3936
3937
3938 #ifdef OFFSET
3939 #undef OFFSET
3940 #endif /* OFFSET */
3941 /* OFFSET: Get offset of a variable within the wpa_config structure */
3942 #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
3943
3944 #define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
3945 #define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
3946 #define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
3947 #define INT(f) _INT(f), NULL, NULL
3948 #define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
3949 #define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
3950 #define STR(f) _STR(f), NULL, NULL
3951 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
3952 #define BIN(f) #f, wpa_global_config_parse_bin, OFFSET(f), NULL, NULL
3953 #define IPV4(f) #f, wpa_global_config_parse_ipv4, OFFSET(f), NULL, NULL
3954
3955 static const struct global_parse_data global_fields[] = {
3956 #ifdef CONFIG_CTRL_IFACE
3957         { STR(ctrl_interface), 0 },
3958         { FUNC_NO_VAR(no_ctrl_interface), 0 },
3959         { STR(ctrl_interface_group), 0 } /* deprecated */,
3960 #endif /* CONFIG_CTRL_IFACE */
3961 #ifdef CONFIG_MACSEC
3962         { INT_RANGE(eapol_version, 1, 3), 0 },
3963 #else /* CONFIG_MACSEC */
3964         { INT_RANGE(eapol_version, 1, 2), 0 },
3965 #endif /* CONFIG_MACSEC */
3966         { INT(ap_scan), 0 },
3967         { FUNC(bgscan), 0 },
3968 #ifdef CONFIG_MESH
3969         { INT(user_mpm), 0 },
3970         { INT_RANGE(max_peer_links, 0, 255), 0 },
3971 #endif /* CONFIG_MESH */
3972         { INT(disable_scan_offload), 0 },
3973         { INT(fast_reauth), 0 },
3974         { STR(opensc_engine_path), 0 },
3975         { STR(pkcs11_engine_path), 0 },
3976         { STR(pkcs11_module_path), 0 },
3977         { STR(openssl_ciphers), 0 },
3978         { STR(pcsc_reader), 0 },
3979         { STR(pcsc_pin), 0 },
3980         { INT(external_sim), 0 },
3981         { STR(driver_param), 0 },
3982         { INT(dot11RSNAConfigPMKLifetime), 0 },
3983         { INT(dot11RSNAConfigPMKReauthThreshold), 0 },
3984         { INT(dot11RSNAConfigSATimeout), 0 },
3985 #ifndef CONFIG_NO_CONFIG_WRITE
3986         { INT(update_config), 0 },
3987 #endif /* CONFIG_NO_CONFIG_WRITE */
3988         { FUNC_NO_VAR(load_dynamic_eap), 0 },
3989 #ifdef CONFIG_WPS
3990         { FUNC(uuid), CFG_CHANGED_UUID },
3991         { STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME },
3992         { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
3993         { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
3994         { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
3995         { STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING },
3996         { FUNC(device_type), CFG_CHANGED_DEVICE_TYPE },
3997         { FUNC(os_version), CFG_CHANGED_OS_VERSION },
3998         { STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
3999         { INT_RANGE(wps_cred_processing, 0, 2), 0 },
4000         { FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION },
4001 #endif /* CONFIG_WPS */
4002 #ifdef CONFIG_P2P
4003         { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
4004         { INT(p2p_listen_reg_class), 0 },
4005         { INT(p2p_listen_channel), 0 },
4006         { INT(p2p_oper_reg_class), CFG_CHANGED_P2P_OPER_CHANNEL },
4007         { INT(p2p_oper_channel), CFG_CHANGED_P2P_OPER_CHANNEL },
4008         { INT_RANGE(p2p_go_intent, 0, 15), 0 },
4009         { STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
4010         { INT_RANGE(persistent_reconnect, 0, 1), 0 },
4011         { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
4012         { INT(p2p_group_idle), 0 },
4013         { INT_RANGE(p2p_passphrase_len, 8, 63),
4014           CFG_CHANGED_P2P_PASSPHRASE_LEN },
4015         { FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN },
4016         { FUNC(p2p_no_go_freq), CFG_CHANGED_P2P_PREF_CHAN },
4017         { INT_RANGE(p2p_add_cli_chan, 0, 1), 0 },
4018         { INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 },
4019         { INT(p2p_go_ht40), 0 },
4020         { INT(p2p_go_vht), 0 },
4021         { INT(p2p_disabled), 0 },
4022         { INT(p2p_no_group_iface), 0 },
4023         { INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 },
4024         { IPV4(ip_addr_go), 0 },
4025         { IPV4(ip_addr_mask), 0 },
4026         { IPV4(ip_addr_start), 0 },
4027         { IPV4(ip_addr_end), 0 },
4028 #endif /* CONFIG_P2P */
4029         { FUNC(country), CFG_CHANGED_COUNTRY },
4030         { INT(bss_max_count), 0 },
4031         { INT(bss_expiration_age), 0 },
4032         { INT(bss_expiration_scan_count), 0 },
4033         { INT_RANGE(filter_ssids, 0, 1), 0 },
4034         { INT_RANGE(filter_rssi, -100, 0), 0 },
4035         { INT(max_num_sta), 0 },
4036         { INT_RANGE(disassoc_low_ack, 0, 1), 0 },
4037 #ifdef CONFIG_HS20
4038         { INT_RANGE(hs20, 0, 1), 0 },
4039 #endif /* CONFIG_HS20 */
4040         { INT_RANGE(interworking, 0, 1), 0 },
4041         { FUNC(hessid), 0 },
4042         { INT_RANGE(access_network_type, 0, 15), 0 },
4043         { INT_RANGE(pbc_in_m1, 0, 1), 0 },
4044         { STR(autoscan), 0 },
4045         { INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff),
4046           CFG_CHANGED_NFC_PASSWORD_TOKEN },
4047         { BIN(wps_nfc_dh_pubkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
4048         { BIN(wps_nfc_dh_privkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
4049         { BIN(wps_nfc_dev_pw), CFG_CHANGED_NFC_PASSWORD_TOKEN },
4050         { STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND },
4051         { INT(p2p_go_max_inactivity), 0 },
4052         { INT_RANGE(auto_interworking, 0, 1), 0 },
4053         { INT(okc), 0 },
4054         { INT(pmf), 0 },
4055         { FUNC(sae_groups), 0 },
4056         { INT(dtim_period), 0 },
4057         { INT(beacon_int), 0 },
4058         { FUNC(ap_vendor_elements), 0 },
4059         { INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
4060         { FUNC(freq_list), 0 },
4061         { INT(scan_cur_freq), 0 },
4062         { INT(sched_scan_interval), 0 },
4063         { INT(tdls_external_control), 0},
4064         { STR(osu_dir), 0 },
4065         { STR(wowlan_triggers), 0 },
4066         { INT(p2p_search_delay), 0},
4067         { INT(mac_addr), 0 },
4068         { INT(rand_addr_lifetime), 0 },
4069         { INT(preassoc_mac_addr), 0 },
4070         { INT(key_mgmt_offload), 0},
4071 };
4072
4073 #undef FUNC
4074 #undef _INT
4075 #undef INT
4076 #undef INT_RANGE
4077 #undef _STR
4078 #undef STR
4079 #undef STR_RANGE
4080 #undef BIN
4081 #undef IPV4
4082 #define NUM_GLOBAL_FIELDS ARRAY_SIZE(global_fields)
4083
4084
4085 int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
4086 {
4087         size_t i;
4088         int ret = 0;
4089
4090         for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
4091                 const struct global_parse_data *field = &global_fields[i];
4092                 size_t flen = os_strlen(field->name);
4093                 if (os_strncmp(pos, field->name, flen) != 0 ||
4094                     pos[flen] != '=')
4095                         continue;
4096
4097                 if (field->parser(field, config, line, pos + flen + 1)) {
4098                         wpa_printf(MSG_ERROR, "Line %d: failed to "
4099                                    "parse '%s'.", line, pos);
4100                         ret = -1;
4101                 }
4102                 if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN)
4103                         config->wps_nfc_pw_from_config = 1;
4104                 config->changed_parameters |= field->changed_flag;
4105                 break;
4106         }
4107         if (i == NUM_GLOBAL_FIELDS) {
4108 #ifdef CONFIG_AP
4109                 if (os_strncmp(pos, "wmm_ac_", 7) == 0) {
4110                         char *tmp = os_strchr(pos, '=');
4111                         if (tmp == NULL) {
4112                                 if (line < 0)
4113                                         return -1;
4114                                 wpa_printf(MSG_ERROR, "Line %d: invalid line "
4115                                            "'%s'", line, pos);
4116                                 return -1;
4117                         }
4118                         *tmp++ = '\0';
4119                         if (hostapd_config_wmm_ac(config->wmm_ac_params, pos,
4120                                                   tmp)) {
4121                                 wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
4122                                            "AC item", line);
4123                                 return -1;
4124                         }
4125                 }
4126 #endif /* CONFIG_AP */
4127                 if (line < 0)
4128                         return -1;
4129                 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
4130                            line, pos);
4131                 ret = -1;
4132         }
4133
4134         return ret;
4135 }