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