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