Coverage Report

Created: 2023-03-26 06:22

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