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