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