Coverage Report

Created: 2025-11-03 06:51

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