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