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