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