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_rssi_threshold, -255, 1) }, 2531 #else /* CONFIG_MESH */ 2532 { INT_RANGE(mode, 0, 4) }, 2533 #endif /* CONFIG_MESH */ 2534 { INT_RANGE(proactive_key_caching, 0, 1) }, 2535 { INT_RANGE(disabled, 0, 2) }, 2536 { STR(id_str) }, 2537 { INT_RANGE(ieee80211w, 0, 2) }, 2538 #ifdef CONFIG_OCV 2539 { FUNC(ocv) }, 2540 #endif /* CONFIG_OCV */ 2541 { FUNC(peerkey) /* obsolete - removed */ }, 2542 { INT_RANGE(mixed_cell, 0, 1) }, 2543 { INT_RANGE(frequency, 0, 70200) }, 2544 { INT_RANGE(fixed_freq, 0, 1) }, 2545 { INT_RANGE(enable_edmg, 0, 1) }, 2546 { INT_RANGE(edmg_channel, 9, 13) }, 2547 #ifdef CONFIG_ACS 2548 { INT_RANGE(acs, 0, 1) }, 2549 #endif /* CONFIG_ACS */ 2550 #ifdef CONFIG_MESH 2551 { FUNC(mesh_basic_rates) }, 2552 { INT(dot11MeshMaxRetries) }, 2553 { INT(dot11MeshRetryTimeout) }, 2554 { INT(dot11MeshConfirmTimeout) }, 2555 { INT(dot11MeshHoldingTimeout) }, 2556 #endif /* CONFIG_MESH */ 2557 { INT(wpa_ptk_rekey) }, 2558 { INT_RANGE(wpa_deny_ptk0_rekey, 0, 2) }, 2559 { INT(group_rekey) }, 2560 { STR(bgscan) }, 2561 { INT_RANGE(ignore_broadcast_ssid, 0, 2) }, 2562 #ifdef CONFIG_P2P 2563 { FUNC(go_p2p_dev_addr) }, 2564 { FUNC(p2p_client_list) }, 2565 { FUNC(psk_list) }, 2566 #endif /* CONFIG_P2P */ 2567 #ifdef CONFIG_HT_OVERRIDES 2568 { INT_RANGE(disable_ht, 0, 1) }, 2569 { INT_RANGE(disable_ht40, -1, 1) }, 2570 { INT_RANGE(disable_sgi, 0, 1) }, 2571 { INT_RANGE(disable_ldpc, 0, 1) }, 2572 { INT_RANGE(ht40_intolerant, 0, 1) }, 2573 { INT_RANGE(tx_stbc, -1, 1) }, 2574 { INT_RANGE(rx_stbc, -1, 3) }, 2575 { INT_RANGE(disable_max_amsdu, -1, 1) }, 2576 { INT_RANGE(ampdu_factor, -1, 3) }, 2577 { INT_RANGE(ampdu_density, -1, 7) }, 2578 { STR(ht_mcs) }, 2579 #endif /* CONFIG_HT_OVERRIDES */ 2580 #ifdef CONFIG_VHT_OVERRIDES 2581 { INT_RANGE(disable_vht, 0, 1) }, 2582 { INT(vht_capa) }, 2583 { INT(vht_capa_mask) }, 2584 { INT_RANGE(vht_rx_mcs_nss_1, -1, 3) }, 2585 { INT_RANGE(vht_rx_mcs_nss_2, -1, 3) }, 2586 { INT_RANGE(vht_rx_mcs_nss_3, -1, 3) }, 2587 { INT_RANGE(vht_rx_mcs_nss_4, -1, 3) }, 2588 { INT_RANGE(vht_rx_mcs_nss_5, -1, 3) }, 2589 { INT_RANGE(vht_rx_mcs_nss_6, -1, 3) }, 2590 { INT_RANGE(vht_rx_mcs_nss_7, -1, 3) }, 2591 { INT_RANGE(vht_rx_mcs_nss_8, -1, 3) }, 2592 { INT_RANGE(vht_tx_mcs_nss_1, -1, 3) }, 2593 { INT_RANGE(vht_tx_mcs_nss_2, -1, 3) }, 2594 { INT_RANGE(vht_tx_mcs_nss_3, -1, 3) }, 2595 { INT_RANGE(vht_tx_mcs_nss_4, -1, 3) }, 2596 { INT_RANGE(vht_tx_mcs_nss_5, -1, 3) }, 2597 { INT_RANGE(vht_tx_mcs_nss_6, -1, 3) }, 2598 { INT_RANGE(vht_tx_mcs_nss_7, -1, 3) }, 2599 { INT_RANGE(vht_tx_mcs_nss_8, -1, 3) }, 2600 #endif /* CONFIG_VHT_OVERRIDES */ 2601 #ifdef CONFIG_HE_OVERRIDES 2602 { INT_RANGE(disable_he, 0, 1)}, 2603 #endif /* CONFIG_HE_OVERRIDES */ 2604 { INT(ap_max_inactivity) }, 2605 { INT(dtim_period) }, 2606 { INT(beacon_int) }, 2607 #ifdef CONFIG_MACSEC 2608 { INT_RANGE(macsec_policy, 0, 1) }, 2609 { INT_RANGE(macsec_integ_only, 0, 1) }, 2610 { INT_RANGE(macsec_replay_protect, 0, 1) }, 2611 { INT(macsec_replay_window) }, 2612 { INT_RANGE(macsec_port, 1, 65534) }, 2613 { INT_RANGE(mka_priority, 0, 255) }, 2614 { FUNC_KEY(mka_cak) }, 2615 { FUNC_KEY(mka_ckn) }, 2616 #endif /* CONFIG_MACSEC */ 2617 #ifdef CONFIG_HS20 2618 { INT(update_identifier) }, 2619 { STR_RANGE(roaming_consortium_selection, 0, MAX_ROAMING_CONS_OI_LEN) }, 2620 #endif /* CONFIG_HS20 */ 2621 { INT_RANGE(mac_addr, 0, 2) }, 2622 { INT_RANGE(pbss, 0, 2) }, 2623 { INT_RANGE(wps_disabled, 0, 1) }, 2624 { INT_RANGE(fils_dh_group, 0, 65535) }, 2625 #ifdef CONFIG_DPP 2626 { STR(dpp_connector) }, 2627 { STR_LEN(dpp_netaccesskey) }, 2628 { INT(dpp_netaccesskey_expiry) }, 2629 { STR_LEN(dpp_csign) }, 2630 { STR_LEN(dpp_pp_key) }, 2631 { INT_RANGE(dpp_pfs, 0, 2) }, 2632 #endif /* CONFIG_DPP */ 2633 { INT_RANGE(owe_group, 0, 65535) }, 2634 { INT_RANGE(owe_only, 0, 1) }, 2635 { INT_RANGE(owe_ptk_workaround, 0, 1) }, 2636 { INT_RANGE(multi_ap_backhaul_sta, 0, 1) }, 2637 { INT_RANGE(ft_eap_pmksa_caching, 0, 1) }, 2638 { INT_RANGE(beacon_prot, 0, 1) }, 2639 { INT_RANGE(transition_disable, 0, 255) }, 2640 { INT_RANGE(sae_pk, 0, 2) }, 2641 }; 2642 2643 #undef OFFSET 2644 #undef _STR 2645 #undef STR 2646 #undef STR_KEY 2647 #undef _STR_LEN 2648 #undef STR_LEN 2649 #undef STR_LEN_KEY 2650 #undef _STR_RANGE 2651 #undef STR_RANGE 2652 #undef STR_RANGE_KEY 2653 #undef _INT 2654 #undef INT 2655 #undef INT_RANGE 2656 #undef _FUNC 2657 #undef FUNC 2658 #undef FUNC_KEY 2659 #define NUM_SSID_FIELDS ARRAY_SIZE(ssid_fields) 2660 2661 2662 /** 2663 * wpa_config_add_prio_network - Add a network to priority lists 2664 * @config: Configuration data from wpa_config_read() 2665 * @ssid: Pointer to the network configuration to be added to the list 2666 * Returns: 0 on success, -1 on failure 2667 * 2668 * This function is used to add a network block to the priority list of 2669 * networks. This must be called for each network when reading in the full 2670 * configuration. In addition, this can be used indirectly when updating 2671 * priorities by calling wpa_config_update_prio_list(). 2672 */ 2673 int wpa_config_add_prio_network(struct wpa_config *config, 2674 struct wpa_ssid *ssid) 2675 { 2676 size_t prio; 2677 struct wpa_ssid *prev, **nlist; 2678 2679 /* 2680 * Add to an existing priority list if one is available for the 2681 * configured priority level for this network. 2682 */ 2683 for (prio = 0; prio < config->num_prio; prio++) { 2684 prev = config->pssid[prio]; 2685 if (prev->priority == ssid->priority) { 2686 while (prev->pnext) 2687 prev = prev->pnext; 2688 prev->pnext = ssid; 2689 return 0; 2690 } 2691 } 2692 2693 /* First network for this priority - add a new priority list */ 2694 nlist = os_realloc_array(config->pssid, config->num_prio + 1, 2695 sizeof(struct wpa_ssid *)); 2696 if (nlist == NULL) 2697 return -1; 2698 2699 for (prio = 0; prio < config->num_prio; prio++) { 2700 if (nlist[prio]->priority < ssid->priority) { 2701 os_memmove(&nlist[prio + 1], &nlist[prio], 2702 (config->num_prio - prio) * 2703 sizeof(struct wpa_ssid *)); 2704 break; 2705 } 2706 } 2707 2708 nlist[prio] = ssid; 2709 config->num_prio++; 2710 config->pssid = nlist; 2711 2712 return 0; 2713 } 2714 2715 2716 /** 2717 * wpa_config_update_prio_list - Update network priority list 2718 * @config: Configuration data from wpa_config_read() 2719 * Returns: 0 on success, -1 on failure 2720 * 2721 * This function is called to update the priority list of networks in the 2722 * configuration when a network is being added or removed. This is also called 2723 * if a priority for a network is changed. 2724 */ 2725 int wpa_config_update_prio_list(struct wpa_config *config) 2726 { 2727 struct wpa_ssid *ssid; 2728 int ret = 0; 2729 2730 os_free(config->pssid); 2731 config->pssid = NULL; 2732 config->num_prio = 0; 2733 2734 ssid = config->ssid; 2735 while (ssid) { 2736 ssid->pnext = NULL; 2737 if (wpa_config_add_prio_network(config, ssid) < 0) 2738 ret = -1; 2739 ssid = ssid->next; 2740 } 2741 2742 return ret; 2743 } 2744 2745 2746 #ifdef IEEE8021X_EAPOL 2747 2748 static void eap_peer_config_free_cert(struct eap_peer_cert_config *cert) 2749 { 2750 os_free(cert->ca_cert); 2751 os_free(cert->ca_path); 2752 os_free(cert->client_cert); 2753 os_free(cert->private_key); 2754 str_clear_free(cert->private_key_passwd); 2755 os_free(cert->dh_file); 2756 os_free(cert->subject_match); 2757 os_free(cert->check_cert_subject); 2758 os_free(cert->altsubject_match); 2759 os_free(cert->domain_suffix_match); 2760 os_free(cert->domain_match); 2761 str_clear_free(cert->pin); 2762 os_free(cert->engine_id); 2763 os_free(cert->key_id); 2764 os_free(cert->cert_id); 2765 os_free(cert->ca_cert_id); 2766 } 2767 2768 2769 static void eap_peer_config_free(struct eap_peer_config *eap) 2770 { 2771 os_free(eap->eap_methods); 2772 bin_clear_free(eap->identity, eap->identity_len); 2773 os_free(eap->anonymous_identity); 2774 os_free(eap->imsi_identity); 2775 os_free(eap->machine_identity); 2776 bin_clear_free(eap->password, eap->password_len); 2777 bin_clear_free(eap->machine_password, eap->machine_password_len); 2778 eap_peer_config_free_cert(&eap->cert); 2779 eap_peer_config_free_cert(&eap->phase2_cert); 2780 eap_peer_config_free_cert(&eap->machine_cert); 2781 os_free(eap->phase1); 2782 os_free(eap->phase2); 2783 os_free(eap->machine_phase2); 2784 os_free(eap->pcsc); 2785 os_free(eap->otp); 2786 os_free(eap->pending_req_otp); 2787 os_free(eap->pac_file); 2788 bin_clear_free(eap->new_password, eap->new_password_len); 2789 str_clear_free(eap->external_sim_resp); 2790 os_free(eap->openssl_ciphers); 2791 } 2792 2793 #endif /* IEEE8021X_EAPOL */ 2794 2795 2796 /** 2797 * wpa_config_free_ssid - Free network/ssid configuration data 2798 * @ssid: Configuration data for the network 2799 * 2800 * This function frees all resources allocated for the network configuration 2801 * data. 2802 */ 2803 void wpa_config_free_ssid(struct wpa_ssid *ssid) 2804 { 2805 struct psk_list_entry *psk; 2806 2807 os_free(ssid->ssid); 2808 str_clear_free(ssid->passphrase); 2809 os_free(ssid->ext_psk); 2810 str_clear_free(ssid->sae_password); 2811 os_free(ssid->sae_password_id); 2812 #ifdef IEEE8021X_EAPOL 2813 eap_peer_config_free(&ssid->eap); 2814 #endif /* IEEE8021X_EAPOL */ 2815 os_free(ssid->id_str); 2816 os_free(ssid->scan_freq); 2817 os_free(ssid->freq_list); 2818 os_free(ssid->bgscan); 2819 os_free(ssid->p2p_client_list); 2820 os_free(ssid->bssid_ignore); 2821 os_free(ssid->bssid_accept); 2822 #ifdef CONFIG_HT_OVERRIDES 2823 os_free(ssid->ht_mcs); 2824 #endif /* CONFIG_HT_OVERRIDES */ 2825 #ifdef CONFIG_MESH 2826 os_free(ssid->mesh_basic_rates); 2827 #endif /* CONFIG_MESH */ 2828 #ifdef CONFIG_HS20 2829 os_free(ssid->roaming_consortium_selection); 2830 #endif /* CONFIG_HS20 */ 2831 os_free(ssid->dpp_connector); 2832 bin_clear_free(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len); 2833 os_free(ssid->dpp_csign); 2834 os_free(ssid->dpp_pp_key); 2835 while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry, 2836 list))) { 2837 dl_list_del(&psk->list); 2838 bin_clear_free(psk, sizeof(*psk)); 2839 } 2840 #ifdef CONFIG_SAE 2841 sae_deinit_pt(ssid->pt); 2842 #endif /* CONFIG_SAE */ 2843 bin_clear_free(ssid, sizeof(*ssid)); 2844 } 2845 2846 2847 void wpa_config_free_cred(struct wpa_cred *cred) 2848 { 2849 size_t i; 2850 2851 os_free(cred->realm); 2852 str_clear_free(cred->username); 2853 str_clear_free(cred->password); 2854 os_free(cred->ca_cert); 2855 os_free(cred->client_cert); 2856 os_free(cred->private_key); 2857 str_clear_free(cred->private_key_passwd); 2858 os_free(cred->imsi); 2859 str_clear_free(cred->milenage); 2860 for (i = 0; i < cred->num_domain; i++) 2861 os_free(cred->domain[i]); 2862 os_free(cred->domain); 2863 os_free(cred->domain_suffix_match); 2864 os_free(cred->eap_method); 2865 os_free(cred->phase1); 2866 os_free(cred->phase2); 2867 os_free(cred->excluded_ssid); 2868 os_free(cred->roaming_partner); 2869 os_free(cred->provisioning_sp); 2870 for (i = 0; i < cred->num_req_conn_capab; i++) 2871 os_free(cred->req_conn_capab_port[i]); 2872 os_free(cred->req_conn_capab_port); 2873 os_free(cred->req_conn_capab_proto); 2874 os_free(cred); 2875 } 2876 2877 2878 void wpa_config_flush_blobs(struct wpa_config *config) 2879 { 2880 #ifndef CONFIG_NO_CONFIG_BLOBS 2881 struct wpa_config_blob *blob, *prev; 2882 2883 blob = config->blobs; 2884 config->blobs = NULL; 2885 while (blob) { 2886 prev = blob; 2887 blob = blob->next; 2888 wpa_config_free_blob(prev); 2889 } 2890 #endif /* CONFIG_NO_CONFIG_BLOBS */ 2891 } 2892 2893 2894 /** 2895 * wpa_config_free - Free configuration data 2896 * @config: Configuration data from wpa_config_read() 2897 * 2898 * This function frees all resources allocated for the configuration data by 2899 * wpa_config_read(). 2900 */ 2901 void wpa_config_free(struct wpa_config *config) 2902 { 2903 struct wpa_ssid *ssid, *prev = NULL; 2904 struct wpa_cred *cred, *cprev; 2905 int i; 2906 2907 ssid = config->ssid; 2908 while (ssid) { 2909 prev = ssid; 2910 ssid = ssid->next; 2911 wpa_config_free_ssid(prev); 2912 } 2913 2914 cred = config->cred; 2915 while (cred) { 2916 cprev = cred; 2917 cred = cred->next; 2918 wpa_config_free_cred(cprev); 2919 } 2920 2921 wpa_config_flush_blobs(config); 2922 2923 wpabuf_free(config->wps_vendor_ext_m1); 2924 for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) 2925 wpabuf_free(config->wps_vendor_ext[i]); 2926 os_free(config->ctrl_interface); 2927 os_free(config->ctrl_interface_group); 2928 os_free(config->opensc_engine_path); 2929 os_free(config->pkcs11_engine_path); 2930 os_free(config->pkcs11_module_path); 2931 os_free(config->openssl_ciphers); 2932 os_free(config->pcsc_reader); 2933 str_clear_free(config->pcsc_pin); 2934 os_free(config->driver_param); 2935 os_free(config->device_name); 2936 os_free(config->manufacturer); 2937 os_free(config->model_name); 2938 os_free(config->model_number); 2939 os_free(config->serial_number); 2940 os_free(config->config_methods); 2941 os_free(config->p2p_ssid_postfix); 2942 os_free(config->pssid); 2943 os_free(config->p2p_pref_chan); 2944 os_free(config->p2p_no_go_freq.range); 2945 os_free(config->autoscan); 2946 os_free(config->freq_list); 2947 os_free(config->initial_freq_list); 2948 wpabuf_free(config->wps_nfc_dh_pubkey); 2949 wpabuf_free(config->wps_nfc_dh_privkey); 2950 wpabuf_free(config->wps_nfc_dev_pw); 2951 os_free(config->ext_password_backend); 2952 os_free(config->sae_groups); 2953 wpabuf_free(config->ap_vendor_elements); 2954 wpabuf_free(config->ap_assocresp_elements); 2955 os_free(config->osu_dir); 2956 os_free(config->bgscan); 2957 os_free(config->wowlan_triggers); 2958 os_free(config->fst_group_id); 2959 os_free(config->sched_scan_plans); 2960 #ifdef CONFIG_MBO 2961 os_free(config->non_pref_chan); 2962 #endif /* CONFIG_MBO */ 2963 os_free(config->dpp_name); 2964 os_free(config->dpp_mud_url); 2965 2966 os_free(config); 2967 } 2968 2969 2970 /** 2971 * wpa_config_foreach_network - Iterate over each configured network 2972 * @config: Configuration data from wpa_config_read() 2973 * @func: Callback function to process each network 2974 * @arg: Opaque argument to pass to callback function 2975 * 2976 * Iterate over the set of configured networks calling the specified 2977 * function for each item. We guard against callbacks removing the 2978 * supplied network. 2979 */ 2980 void wpa_config_foreach_network(struct wpa_config *config, 2981 void (*func)(void *, struct wpa_ssid *), 2982 void *arg) 2983 { 2984 struct wpa_ssid *ssid, *next; 2985 2986 ssid = config->ssid; 2987 while (ssid) { 2988 next = ssid->next; 2989 func(arg, ssid); 2990 ssid = next; 2991 } 2992 } 2993 2994 2995 /** 2996 * wpa_config_get_network - Get configured network based on id 2997 * @config: Configuration data from wpa_config_read() 2998 * @id: Unique network id to search for 2999 * Returns: Network configuration or %NULL if not found 3000 */ 3001 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id) 3002 { 3003 struct wpa_ssid *ssid; 3004 3005 ssid = config->ssid; 3006 while (ssid) { 3007 if (id == ssid->id) 3008 break; 3009 ssid = ssid->next; 3010 } 3011 3012 return ssid; 3013 } 3014 3015 3016 /** 3017 * wpa_config_add_network - Add a new network with empty configuration 3018 * @config: Configuration data from wpa_config_read() 3019 * Returns: The new network configuration or %NULL if operation failed 3020 */ 3021 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config) 3022 { 3023 int id; 3024 struct wpa_ssid *ssid, *last = NULL; 3025 3026 id = -1; 3027 ssid = config->ssid; 3028 while (ssid) { 3029 if (ssid->id > id) 3030 id = ssid->id; 3031 last = ssid; 3032 ssid = ssid->next; 3033 } 3034 id++; 3035 3036 ssid = os_zalloc(sizeof(*ssid)); 3037 if (ssid == NULL) 3038 return NULL; 3039 ssid->id = id; 3040 dl_list_init(&ssid->psk_list); 3041 if (last) 3042 last->next = ssid; 3043 else 3044 config->ssid = ssid; 3045 3046 wpa_config_update_prio_list(config); 3047 3048 return ssid; 3049 } 3050 3051 3052 /** 3053 * wpa_config_remove_network - Remove a configured network based on id 3054 * @config: Configuration data from wpa_config_read() 3055 * @id: Unique network id to search for 3056 * Returns: 0 on success, or -1 if the network was not found 3057 */ 3058 int wpa_config_remove_network(struct wpa_config *config, int id) 3059 { 3060 struct wpa_ssid *ssid, *prev = NULL; 3061 3062 ssid = config->ssid; 3063 while (ssid) { 3064 if (id == ssid->id) 3065 break; 3066 prev = ssid; 3067 ssid = ssid->next; 3068 } 3069 3070 if (ssid == NULL) 3071 return -1; 3072 3073 if (prev) 3074 prev->next = ssid->next; 3075 else 3076 config->ssid = ssid->next; 3077 3078 wpa_config_update_prio_list(config); 3079 wpa_config_free_ssid(ssid); 3080 return 0; 3081 } 3082 3083 3084 /** 3085 * wpa_config_set_network_defaults - Set network default values 3086 * @ssid: Pointer to network configuration data 3087 */ 3088 void wpa_config_set_network_defaults(struct wpa_ssid *ssid) 3089 { 3090 ssid->proto = DEFAULT_PROTO; 3091 ssid->pairwise_cipher = DEFAULT_PAIRWISE; 3092 ssid->group_cipher = DEFAULT_GROUP; 3093 ssid->key_mgmt = DEFAULT_KEY_MGMT; 3094 ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS; 3095 ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD; 3096 ssid->ht = 1; 3097 ssid->vht = 1; 3098 ssid->he = 1; 3099 #ifdef IEEE8021X_EAPOL 3100 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; 3101 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; 3102 ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE; 3103 ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM; 3104 #endif /* IEEE8021X_EAPOL */ 3105 #ifdef CONFIG_MESH 3106 ssid->dot11MeshMaxRetries = DEFAULT_MESH_MAX_RETRIES; 3107 ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT; 3108 ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT; 3109 ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT; 3110 ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD; 3111 #endif /* CONFIG_MESH */ 3112 #ifdef CONFIG_HT_OVERRIDES 3113 ssid->disable_ht = DEFAULT_DISABLE_HT; 3114 ssid->disable_ht40 = DEFAULT_DISABLE_HT40; 3115 ssid->disable_sgi = DEFAULT_DISABLE_SGI; 3116 ssid->disable_ldpc = DEFAULT_DISABLE_LDPC; 3117 ssid->tx_stbc = DEFAULT_TX_STBC; 3118 ssid->rx_stbc = DEFAULT_RX_STBC; 3119 ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU; 3120 ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR; 3121 ssid->ampdu_density = DEFAULT_AMPDU_DENSITY; 3122 #endif /* CONFIG_HT_OVERRIDES */ 3123 #ifdef CONFIG_VHT_OVERRIDES 3124 ssid->vht_rx_mcs_nss_1 = -1; 3125 ssid->vht_rx_mcs_nss_2 = -1; 3126 ssid->vht_rx_mcs_nss_3 = -1; 3127 ssid->vht_rx_mcs_nss_4 = -1; 3128 ssid->vht_rx_mcs_nss_5 = -1; 3129 ssid->vht_rx_mcs_nss_6 = -1; 3130 ssid->vht_rx_mcs_nss_7 = -1; 3131 ssid->vht_rx_mcs_nss_8 = -1; 3132 ssid->vht_tx_mcs_nss_1 = -1; 3133 ssid->vht_tx_mcs_nss_2 = -1; 3134 ssid->vht_tx_mcs_nss_3 = -1; 3135 ssid->vht_tx_mcs_nss_4 = -1; 3136 ssid->vht_tx_mcs_nss_5 = -1; 3137 ssid->vht_tx_mcs_nss_6 = -1; 3138 ssid->vht_tx_mcs_nss_7 = -1; 3139 ssid->vht_tx_mcs_nss_8 = -1; 3140 #endif /* CONFIG_VHT_OVERRIDES */ 3141 ssid->proactive_key_caching = -1; 3142 ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT; 3143 ssid->sae_pwe = DEFAULT_SAE_PWE; 3144 #ifdef CONFIG_MACSEC 3145 ssid->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER; 3146 #endif /* CONFIG_MACSEC */ 3147 ssid->mac_addr = -1; 3148 ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH; 3149 } 3150 3151 3152 /** 3153 * wpa_config_set - Set a variable in network configuration 3154 * @ssid: Pointer to network configuration data 3155 * @var: Variable name, e.g., "ssid" 3156 * @value: Variable value 3157 * @line: Line number in configuration file or 0 if not used 3158 * Returns: 0 on success with possible change in the value, 1 on success with 3159 * no change to previously configured value, or -1 on failure 3160 * 3161 * This function can be used to set network configuration variables based on 3162 * both the configuration file and management interface input. The value 3163 * parameter must be in the same format as the text-based configuration file is 3164 * using. For example, strings are using double quotation marks. 3165 */ 3166 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, 3167 int line) 3168 { 3169 size_t i; 3170 int ret = 0; 3171 3172 if (ssid == NULL || var == NULL || value == NULL) 3173 return -1; 3174 3175 for (i = 0; i < NUM_SSID_FIELDS; i++) { 3176 const struct parse_data *field = &ssid_fields[i]; 3177 if (os_strcmp(var, field->name) != 0) 3178 continue; 3179 3180 ret = field->parser(field, ssid, line, value); 3181 if (ret < 0) { 3182 if (line) { 3183 wpa_printf(MSG_ERROR, "Line %d: failed to " 3184 "parse %s '%s'.", line, var, value); 3185 } 3186 ret = -1; 3187 } 3188 #ifdef CONFIG_SAE 3189 if (os_strcmp(var, "ssid") == 0 || 3190 os_strcmp(var, "psk") == 0 || 3191 os_strcmp(var, "sae_password") == 0 || 3192 os_strcmp(var, "sae_password_id") == 0) { 3193 sae_deinit_pt(ssid->pt); 3194 ssid->pt = NULL; 3195 } 3196 #endif /* CONFIG_SAE */ 3197 break; 3198 } 3199 if (i == NUM_SSID_FIELDS) { 3200 if (line) { 3201 wpa_printf(MSG_ERROR, "Line %d: unknown network field " 3202 "'%s'.", line, var); 3203 } 3204 ret = -1; 3205 } 3206 ssid->was_recently_reconfigured = true; 3207 3208 return ret; 3209 } 3210 3211 3212 int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var, 3213 const char *value) 3214 { 3215 size_t len; 3216 char *buf; 3217 int ret; 3218 3219 len = os_strlen(value); 3220 buf = os_malloc(len + 3); 3221 if (buf == NULL) 3222 return -1; 3223 buf[0] = '"'; 3224 os_memcpy(buf + 1, value, len); 3225 buf[len + 1] = '"'; 3226 buf[len + 2] = '\0'; 3227 ret = wpa_config_set(ssid, var, buf, 0); 3228 os_free(buf); 3229 return ret; 3230 } 3231 3232 3233 /** 3234 * wpa_config_get_all - Get all options from network configuration 3235 * @ssid: Pointer to network configuration data 3236 * @get_keys: Determines if keys/passwords will be included in returned list 3237 * (if they may be exported) 3238 * Returns: %NULL terminated list of all set keys and their values in the form 3239 * of [key1, val1, key2, val2, ... , NULL] 3240 * 3241 * This function can be used to get list of all configured network properties. 3242 * The caller is responsible for freeing the returned list and all its 3243 * elements. 3244 */ 3245 char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys) 3246 { 3247 #ifdef NO_CONFIG_WRITE 3248 return NULL; 3249 #else /* NO_CONFIG_WRITE */ 3250 const struct parse_data *field; 3251 char *key, *value; 3252 size_t i; 3253 char **props; 3254 int fields_num; 3255 3256 get_keys = get_keys && ssid->export_keys; 3257 3258 props = os_calloc(2 * NUM_SSID_FIELDS + 1, sizeof(char *)); 3259 if (!props) 3260 return NULL; 3261 3262 fields_num = 0; 3263 for (i = 0; i < NUM_SSID_FIELDS; i++) { 3264 field = &ssid_fields[i]; 3265 if (field->key_data && !get_keys) 3266 continue; 3267 value = field->writer(field, ssid); 3268 if (value == NULL) 3269 continue; 3270 if (os_strlen(value) == 0) { 3271 os_free(value); 3272 continue; 3273 } 3274 3275 key = os_strdup(field->name); 3276 if (key == NULL) { 3277 os_free(value); 3278 goto err; 3279 } 3280 3281 props[fields_num * 2] = key; 3282 props[fields_num * 2 + 1] = value; 3283 3284 fields_num++; 3285 } 3286 3287 return props; 3288 3289 err: 3290 for (i = 0; props[i]; i++) 3291 os_free(props[i]); 3292 os_free(props); 3293 return NULL; 3294 #endif /* NO_CONFIG_WRITE */ 3295 } 3296 3297 3298 #ifndef NO_CONFIG_WRITE 3299 /** 3300 * wpa_config_get - Get a variable in network configuration 3301 * @ssid: Pointer to network configuration data 3302 * @var: Variable name, e.g., "ssid" 3303 * Returns: Value of the variable or %NULL on failure 3304 * 3305 * This function can be used to get network configuration variables. The 3306 * returned value is a copy of the configuration variable in text format, i.e,. 3307 * the same format that the text-based configuration file and wpa_config_set() 3308 * are using for the value. The caller is responsible for freeing the returned 3309 * value. 3310 */ 3311 char * wpa_config_get(struct wpa_ssid *ssid, const char *var) 3312 { 3313 size_t i; 3314 3315 if (ssid == NULL || var == NULL) 3316 return NULL; 3317 3318 for (i = 0; i < NUM_SSID_FIELDS; i++) { 3319 const struct parse_data *field = &ssid_fields[i]; 3320 if (os_strcmp(var, field->name) == 0) { 3321 char *ret = field->writer(field, ssid); 3322 3323 if (ret && has_newline(ret)) { 3324 wpa_printf(MSG_ERROR, 3325 "Found newline in value for %s; not returning it", 3326 var); 3327 os_free(ret); 3328 ret = NULL; 3329 } 3330 3331 return ret; 3332 } 3333 } 3334 3335 return NULL; 3336 } 3337 3338 3339 /** 3340 * wpa_config_get_no_key - Get a variable in network configuration (no keys) 3341 * @ssid: Pointer to network configuration data 3342 * @var: Variable name, e.g., "ssid" 3343 * Returns: Value of the variable or %NULL on failure 3344 * 3345 * This function can be used to get network configuration variable like 3346 * wpa_config_get(). The only difference is that this functions does not expose 3347 * key/password material from the configuration. In case a key/password field 3348 * is requested, the returned value is an empty string or %NULL if the variable 3349 * is not set or "*" if the variable is set (regardless of its value). The 3350 * returned value is a copy of the configuration variable in text format, i.e,. 3351 * the same format that the text-based configuration file and wpa_config_set() 3352 * are using for the value. The caller is responsible for freeing the returned 3353 * value. 3354 */ 3355 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var) 3356 { 3357 size_t i; 3358 3359 if (ssid == NULL || var == NULL) 3360 return NULL; 3361 3362 for (i = 0; i < NUM_SSID_FIELDS; i++) { 3363 const struct parse_data *field = &ssid_fields[i]; 3364 if (os_strcmp(var, field->name) == 0) { 3365 char *res = field->writer(field, ssid); 3366 if (field->key_data) { 3367 if (res && res[0]) { 3368 wpa_printf(MSG_DEBUG, "Do not allow " 3369 "key_data field to be " 3370 "exposed"); 3371 str_clear_free(res); 3372 return os_strdup("*"); 3373 } 3374 3375 os_free(res); 3376 return NULL; 3377 } 3378 return res; 3379 } 3380 } 3381 3382 return NULL; 3383 } 3384 #endif /* NO_CONFIG_WRITE */ 3385 3386 3387 /** 3388 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID 3389 * @ssid: Pointer to network configuration data 3390 * 3391 * This function must be called to update WPA PSK when either SSID or the 3392 * passphrase has changed for the network configuration. 3393 */ 3394 void wpa_config_update_psk(struct wpa_ssid *ssid) 3395 { 3396 #ifndef CONFIG_NO_PBKDF2 3397 pbkdf2_sha1(ssid->passphrase, ssid->ssid, ssid->ssid_len, 4096, 3398 ssid->psk, PMK_LEN); 3399 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", 3400 ssid->psk, PMK_LEN); 3401 ssid->psk_set = 1; 3402 #endif /* CONFIG_NO_PBKDF2 */ 3403 } 3404 3405 3406 static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred, 3407 const char *value) 3408 { 3409 u8 *proto; 3410 int **port; 3411 int *ports, *nports; 3412 const char *pos; 3413 unsigned int num_ports; 3414 3415 proto = os_realloc_array(cred->req_conn_capab_proto, 3416 cred->num_req_conn_capab + 1, sizeof(u8)); 3417 if (proto == NULL) 3418 return -1; 3419 cred->req_conn_capab_proto = proto; 3420 3421 port = os_realloc_array(cred->req_conn_capab_port, 3422 cred->num_req_conn_capab + 1, sizeof(int *)); 3423 if (port == NULL) 3424 return -1; 3425 cred->req_conn_capab_port = port; 3426 3427 proto[cred->num_req_conn_capab] = atoi(value); 3428 3429 pos = os_strchr(value, ':'); 3430 if (pos == NULL) { 3431 port[cred->num_req_conn_capab] = NULL; 3432 cred->num_req_conn_capab++; 3433 return 0; 3434 } 3435 pos++; 3436 3437 ports = NULL; 3438 num_ports = 0; 3439 3440 while (*pos) { 3441 nports = os_realloc_array(ports, num_ports + 1, sizeof(int)); 3442 if (nports == NULL) { 3443 os_free(ports); 3444 return -1; 3445 } 3446 ports = nports; 3447 ports[num_ports++] = atoi(pos); 3448 3449 pos = os_strchr(pos, ','); 3450 if (pos == NULL) 3451 break; 3452 pos++; 3453 } 3454 3455 nports = os_realloc_array(ports, num_ports + 1, sizeof(int)); 3456 if (nports == NULL) { 3457 os_free(ports); 3458 return -1; 3459 } 3460 ports = nports; 3461 ports[num_ports] = -1; 3462 3463 port[cred->num_req_conn_capab] = ports; 3464 cred->num_req_conn_capab++; 3465 return 0; 3466 } 3467 3468 3469 static int wpa_config_set_cred_roaming_consortiums(struct wpa_cred *cred, 3470 const char *value) 3471 { 3472 u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN]; 3473 size_t roaming_consortiums_len[MAX_ROAMING_CONS]; 3474 unsigned int num_roaming_consortiums = 0; 3475 const char *pos, *end; 3476 size_t len; 3477 3478 os_memset(roaming_consortiums, 0, sizeof(roaming_consortiums)); 3479 os_memset(roaming_consortiums_len, 0, sizeof(roaming_consortiums_len)); 3480 3481 for (pos = value;;) { 3482 end = os_strchr(pos, ','); 3483 len = end ? (size_t) (end - pos) : os_strlen(pos); 3484 if (!end && len == 0) 3485 break; 3486 if (len == 0 || (len & 1) != 0 || 3487 len / 2 > MAX_ROAMING_CONS_OI_LEN || 3488 hexstr2bin(pos, 3489 roaming_consortiums[num_roaming_consortiums], 3490 len / 2) < 0) { 3491 wpa_printf(MSG_INFO, 3492 "Invalid roaming_consortiums entry: %s", 3493 pos); 3494 return -1; 3495 } 3496 roaming_consortiums_len[num_roaming_consortiums] = len / 2; 3497 num_roaming_consortiums++; 3498 3499 if (!end) 3500 break; 3501 3502 if (num_roaming_consortiums >= MAX_ROAMING_CONS) { 3503 wpa_printf(MSG_INFO, 3504 "Too many roaming_consortiums OIs"); 3505 return -1; 3506 } 3507 3508 pos = end + 1; 3509 } 3510 3511 os_memcpy(cred->roaming_consortiums, roaming_consortiums, 3512 sizeof(roaming_consortiums)); 3513 os_memcpy(cred->roaming_consortiums_len, roaming_consortiums_len, 3514 sizeof(roaming_consortiums_len)); 3515 cred->num_roaming_consortiums = num_roaming_consortiums; 3516 3517 return 0; 3518 } 3519 3520 3521 int wpa_config_set_cred(struct wpa_cred *cred, const char *var, 3522 const char *value, int line) 3523 { 3524 char *val; 3525 size_t len; 3526 int res; 3527 3528 if (os_strcmp(var, "temporary") == 0) { 3529 cred->temporary = atoi(value); 3530 return 0; 3531 } 3532 3533 if (os_strcmp(var, "priority") == 0) { 3534 cred->priority = atoi(value); 3535 return 0; 3536 } 3537 3538 if (os_strcmp(var, "sp_priority") == 0) { 3539 int prio = atoi(value); 3540 if (prio < 0 || prio > 255) 3541 return -1; 3542 cred->sp_priority = prio; 3543 return 0; 3544 } 3545 3546 if (os_strcmp(var, "pcsc") == 0) { 3547 cred->pcsc = atoi(value); 3548 return 0; 3549 } 3550 3551 if (os_strcmp(var, "eap") == 0) { 3552 struct eap_method_type method; 3553 method.method = eap_peer_get_type(value, &method.vendor); 3554 if (method.vendor == EAP_VENDOR_IETF && 3555 method.method == EAP_TYPE_NONE) { 3556 wpa_printf(MSG_ERROR, "Line %d: unknown EAP type '%s' " 3557 "for a credential", line, value); 3558 return -1; 3559 } 3560 os_free(cred->eap_method); 3561 cred->eap_method = os_malloc(sizeof(*cred->eap_method)); 3562 if (cred->eap_method == NULL) 3563 return -1; 3564 os_memcpy(cred->eap_method, &method, sizeof(method)); 3565 return 0; 3566 } 3567 3568 if (os_strcmp(var, "password") == 0 && 3569 os_strncmp(value, "ext:", 4) == 0) { 3570 if (has_newline(value)) 3571 return -1; 3572 str_clear_free(cred->password); 3573 cred->password = os_strdup(value); 3574 cred->ext_password = 1; 3575 return 0; 3576 } 3577 3578 if (os_strcmp(var, "update_identifier") == 0) { 3579 cred->update_identifier = atoi(value); 3580 return 0; 3581 } 3582 3583 if (os_strcmp(var, "min_dl_bandwidth_home") == 0) { 3584 cred->min_dl_bandwidth_home = atoi(value); 3585 return 0; 3586 } 3587 3588 if (os_strcmp(var, "min_ul_bandwidth_home") == 0) { 3589 cred->min_ul_bandwidth_home = atoi(value); 3590 return 0; 3591 } 3592 3593 if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0) { 3594 cred->min_dl_bandwidth_roaming = atoi(value); 3595 return 0; 3596 } 3597 3598 if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0) { 3599 cred->min_ul_bandwidth_roaming = atoi(value); 3600 return 0; 3601 } 3602 3603 if (os_strcmp(var, "max_bss_load") == 0) { 3604 cred->max_bss_load = atoi(value); 3605 return 0; 3606 } 3607 3608 if (os_strcmp(var, "req_conn_capab") == 0) 3609 return wpa_config_set_cred_req_conn_capab(cred, value); 3610 3611 if (os_strcmp(var, "ocsp") == 0) { 3612 cred->ocsp = atoi(value); 3613 return 0; 3614 } 3615 3616 if (os_strcmp(var, "sim_num") == 0) { 3617 cred->sim_num = atoi(value); 3618 return 0; 3619 } 3620 3621 val = wpa_config_parse_string(value, &len); 3622 if (val == NULL || 3623 (os_strcmp(var, "excluded_ssid") != 0 && 3624 os_strcmp(var, "roaming_consortium") != 0 && 3625 os_strcmp(var, "required_roaming_consortium") != 0 && 3626 has_newline(val))) { 3627 wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string " 3628 "value '%s'.", line, var, value); 3629 os_free(val); 3630 return -1; 3631 } 3632 3633 if (os_strcmp(var, "realm") == 0) { 3634 os_free(cred->realm); 3635 cred->realm = val; 3636 return 0; 3637 } 3638 3639 if (os_strcmp(var, "username") == 0) { 3640 str_clear_free(cred->username); 3641 cred->username = val; 3642 return 0; 3643 } 3644 3645 if (os_strcmp(var, "password") == 0) { 3646 str_clear_free(cred->password); 3647 cred->password = val; 3648 cred->ext_password = 0; 3649 return 0; 3650 } 3651 3652 if (os_strcmp(var, "ca_cert") == 0) { 3653 os_free(cred->ca_cert); 3654 cred->ca_cert = val; 3655 return 0; 3656 } 3657 3658 if (os_strcmp(var, "client_cert") == 0) { 3659 os_free(cred->client_cert); 3660 cred->client_cert = val; 3661 return 0; 3662 } 3663 3664 if (os_strcmp(var, "private_key") == 0) { 3665 os_free(cred->private_key); 3666 cred->private_key = val; 3667 return 0; 3668 } 3669 3670 if (os_strcmp(var, "private_key_passwd") == 0) { 3671 str_clear_free(cred->private_key_passwd); 3672 cred->private_key_passwd = val; 3673 return 0; 3674 } 3675 3676 if (os_strcmp(var, "imsi") == 0) { 3677 os_free(cred->imsi); 3678 cred->imsi = val; 3679 return 0; 3680 } 3681 3682 if (os_strcmp(var, "milenage") == 0) { 3683 str_clear_free(cred->milenage); 3684 cred->milenage = val; 3685 return 0; 3686 } 3687 3688 if (os_strcmp(var, "domain_suffix_match") == 0) { 3689 os_free(cred->domain_suffix_match); 3690 cred->domain_suffix_match = val; 3691 return 0; 3692 } 3693 3694 if (os_strcmp(var, "domain") == 0) { 3695 char **new_domain; 3696 new_domain = os_realloc_array(cred->domain, 3697 cred->num_domain + 1, 3698 sizeof(char *)); 3699 if (new_domain == NULL) { 3700 os_free(val); 3701 return -1; 3702 } 3703 new_domain[cred->num_domain++] = val; 3704 cred->domain = new_domain; 3705 return 0; 3706 } 3707 3708 if (os_strcmp(var, "phase1") == 0) { 3709 os_free(cred->phase1); 3710 cred->phase1 = val; 3711 return 0; 3712 } 3713 3714 if (os_strcmp(var, "phase2") == 0) { 3715 os_free(cred->phase2); 3716 cred->phase2 = val; 3717 return 0; 3718 } 3719 3720 if (os_strcmp(var, "roaming_consortium") == 0) { 3721 if (len < 3 || len > sizeof(cred->roaming_consortium)) { 3722 wpa_printf(MSG_ERROR, "Line %d: invalid " 3723 "roaming_consortium length %d (3..15 " 3724 "expected)", line, (int) len); 3725 os_free(val); 3726 return -1; 3727 } 3728 os_memcpy(cred->roaming_consortium, val, len); 3729 cred->roaming_consortium_len = len; 3730 os_free(val); 3731 return 0; 3732 } 3733 3734 if (os_strcmp(var, "required_roaming_consortium") == 0) { 3735 if (len < 3 || len > sizeof(cred->required_roaming_consortium)) 3736 { 3737 wpa_printf(MSG_ERROR, "Line %d: invalid " 3738 "required_roaming_consortium length %d " 3739 "(3..15 expected)", line, (int) len); 3740 os_free(val); 3741 return -1; 3742 } 3743 os_memcpy(cred->required_roaming_consortium, val, len); 3744 cred->required_roaming_consortium_len = len; 3745 os_free(val); 3746 return 0; 3747 } 3748 3749 if (os_strcmp(var, "roaming_consortiums") == 0) { 3750 res = wpa_config_set_cred_roaming_consortiums(cred, val); 3751 if (res < 0) 3752 wpa_printf(MSG_ERROR, 3753 "Line %d: invalid roaming_consortiums", 3754 line); 3755 os_free(val); 3756 return res; 3757 } 3758 3759 if (os_strcmp(var, "excluded_ssid") == 0) { 3760 struct excluded_ssid *e; 3761 3762 if (len > SSID_MAX_LEN) { 3763 wpa_printf(MSG_ERROR, "Line %d: invalid " 3764 "excluded_ssid length %d", line, (int) len); 3765 os_free(val); 3766 return -1; 3767 } 3768 3769 e = os_realloc_array(cred->excluded_ssid, 3770 cred->num_excluded_ssid + 1, 3771 sizeof(struct excluded_ssid)); 3772 if (e == NULL) { 3773 os_free(val); 3774 return -1; 3775 } 3776 cred->excluded_ssid = e; 3777 3778 e = &cred->excluded_ssid[cred->num_excluded_ssid++]; 3779 os_memcpy(e->ssid, val, len); 3780 e->ssid_len = len; 3781 3782 os_free(val); 3783 3784 return 0; 3785 } 3786 3787 if (os_strcmp(var, "roaming_partner") == 0) { 3788 struct roaming_partner *p; 3789 char *pos; 3790 3791 p = os_realloc_array(cred->roaming_partner, 3792 cred->num_roaming_partner + 1, 3793 sizeof(struct roaming_partner)); 3794 if (p == NULL) { 3795 os_free(val); 3796 return -1; 3797 } 3798 cred->roaming_partner = p; 3799 3800 p = &cred->roaming_partner[cred->num_roaming_partner]; 3801 3802 pos = os_strchr(val, ','); 3803 if (pos == NULL) { 3804 os_free(val); 3805 return -1; 3806 } 3807 *pos++ = '\0'; 3808 if (pos - val - 1 >= (int) sizeof(p->fqdn)) { 3809 os_free(val); 3810 return -1; 3811 } 3812 os_memcpy(p->fqdn, val, pos - val); 3813 3814 p->exact_match = atoi(pos); 3815 3816 pos = os_strchr(pos, ','); 3817 if (pos == NULL) { 3818 os_free(val); 3819 return -1; 3820 } 3821 *pos++ = '\0'; 3822 3823 p->priority = atoi(pos); 3824 3825 pos = os_strchr(pos, ','); 3826 if (pos == NULL) { 3827 os_free(val); 3828 return -1; 3829 } 3830 *pos++ = '\0'; 3831 3832 if (os_strlen(pos) >= sizeof(p->country)) { 3833 os_free(val); 3834 return -1; 3835 } 3836 os_memcpy(p->country, pos, os_strlen(pos) + 1); 3837 3838 cred->num_roaming_partner++; 3839 os_free(val); 3840 3841 return 0; 3842 } 3843 3844 if (os_strcmp(var, "provisioning_sp") == 0) { 3845 os_free(cred->provisioning_sp); 3846 cred->provisioning_sp = val; 3847 return 0; 3848 } 3849 3850 if (line) { 3851 wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.", 3852 line, var); 3853 } 3854 3855 os_free(val); 3856 3857 return -1; 3858 } 3859 3860 3861 static char * alloc_int_str(int val) 3862 { 3863 const unsigned int bufsize = 20; 3864 char *buf; 3865 int res; 3866 3867 buf = os_malloc(bufsize); 3868 if (buf == NULL) 3869 return NULL; 3870 res = os_snprintf(buf, bufsize, "%d", val); 3871 if (os_snprintf_error(bufsize, res)) { 3872 os_free(buf); 3873 buf = NULL; 3874 } 3875 return buf; 3876 } 3877 3878 3879 static char * alloc_strdup(const char *str) 3880 { 3881 if (str == NULL) 3882 return NULL; 3883 return os_strdup(str); 3884 } 3885 3886 3887 char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) 3888 { 3889 if (os_strcmp(var, "temporary") == 0) 3890 return alloc_int_str(cred->temporary); 3891 3892 if (os_strcmp(var, "priority") == 0) 3893 return alloc_int_str(cred->priority); 3894 3895 if (os_strcmp(var, "sp_priority") == 0) 3896 return alloc_int_str(cred->sp_priority); 3897 3898 if (os_strcmp(var, "pcsc") == 0) 3899 return alloc_int_str(cred->pcsc); 3900 3901 if (os_strcmp(var, "eap") == 0) { 3902 if (!cred->eap_method) 3903 return NULL; 3904 return alloc_strdup(eap_get_name(cred->eap_method[0].vendor, 3905 cred->eap_method[0].method)); 3906 } 3907 3908 if (os_strcmp(var, "update_identifier") == 0) 3909 return alloc_int_str(cred->update_identifier); 3910 3911 if (os_strcmp(var, "min_dl_bandwidth_home") == 0) 3912 return alloc_int_str(cred->min_dl_bandwidth_home); 3913 3914 if (os_strcmp(var, "min_ul_bandwidth_home") == 0) 3915 return alloc_int_str(cred->min_ul_bandwidth_home); 3916 3917 if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0) 3918 return alloc_int_str(cred->min_dl_bandwidth_roaming); 3919 3920 if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0) 3921 return alloc_int_str(cred->min_ul_bandwidth_roaming); 3922 3923 if (os_strcmp(var, "max_bss_load") == 0) 3924 return alloc_int_str(cred->max_bss_load); 3925 3926 if (os_strcmp(var, "req_conn_capab") == 0) { 3927 unsigned int i; 3928 char *buf, *end, *pos; 3929 int ret; 3930 3931 if (!cred->num_req_conn_capab) 3932 return NULL; 3933 3934 buf = os_malloc(4000); 3935 if (buf == NULL) 3936 return NULL; 3937 pos = buf; 3938 end = pos + 4000; 3939 for (i = 0; i < cred->num_req_conn_capab; i++) { 3940 int *ports; 3941 3942 ret = os_snprintf(pos, end - pos, "%s%u", 3943 i > 0 ? "\n" : "", 3944 cred->req_conn_capab_proto[i]); 3945 if (os_snprintf_error(end - pos, ret)) 3946 return buf; 3947 pos += ret; 3948 3949 ports = cred->req_conn_capab_port[i]; 3950 if (ports) { 3951 int j; 3952 for (j = 0; ports[j] != -1; j++) { 3953 ret = os_snprintf(pos, end - pos, 3954 "%s%d", 3955 j > 0 ? "," : ":", 3956 ports[j]); 3957 if (os_snprintf_error(end - pos, ret)) 3958 return buf; 3959 pos += ret; 3960 } 3961 } 3962 } 3963 3964 return buf; 3965 } 3966 3967 if (os_strcmp(var, "ocsp") == 0) 3968 return alloc_int_str(cred->ocsp); 3969 3970 if (os_strcmp(var, "realm") == 0) 3971 return alloc_strdup(cred->realm); 3972 3973 if (os_strcmp(var, "username") == 0) 3974 return alloc_strdup(cred->username); 3975 3976 if (os_strcmp(var, "password") == 0) { 3977 if (!cred->password) 3978 return NULL; 3979 return alloc_strdup("*"); 3980 } 3981 3982 if (os_strcmp(var, "ca_cert") == 0) 3983 return alloc_strdup(cred->ca_cert); 3984 3985 if (os_strcmp(var, "client_cert") == 0) 3986 return alloc_strdup(cred->client_cert); 3987 3988 if (os_strcmp(var, "private_key") == 0) 3989 return alloc_strdup(cred->private_key); 3990 3991 if (os_strcmp(var, "private_key_passwd") == 0) { 3992 if (!cred->private_key_passwd) 3993 return NULL; 3994 return alloc_strdup("*"); 3995 } 3996 3997 if (os_strcmp(var, "imsi") == 0) 3998 return alloc_strdup(cred->imsi); 3999 4000 if (os_strcmp(var, "milenage") == 0) { 4001 if (!(cred->milenage)) 4002 return NULL; 4003 return alloc_strdup("*"); 4004 } 4005 4006 if (os_strcmp(var, "domain_suffix_match") == 0) 4007 return alloc_strdup(cred->domain_suffix_match); 4008 4009 if (os_strcmp(var, "domain") == 0) { 4010 unsigned int i; 4011 char *buf, *end, *pos; 4012 int ret; 4013 4014 if (!cred->num_domain) 4015 return NULL; 4016 4017 buf = os_malloc(4000); 4018 if (buf == NULL) 4019 return NULL; 4020 pos = buf; 4021 end = pos + 4000; 4022 4023 for (i = 0; i < cred->num_domain; i++) { 4024 ret = os_snprintf(pos, end - pos, "%s%s", 4025 i > 0 ? "\n" : "", cred->domain[i]); 4026 if (os_snprintf_error(end - pos, ret)) 4027 return buf; 4028 pos += ret; 4029 } 4030 4031 return buf; 4032 } 4033 4034 if (os_strcmp(var, "phase1") == 0) 4035 return alloc_strdup(cred->phase1); 4036 4037 if (os_strcmp(var, "phase2") == 0) 4038 return alloc_strdup(cred->phase2); 4039 4040 if (os_strcmp(var, "roaming_consortium") == 0) { 4041 size_t buflen; 4042 char *buf; 4043 4044 if (!cred->roaming_consortium_len) 4045 return NULL; 4046 buflen = cred->roaming_consortium_len * 2 + 1; 4047 buf = os_malloc(buflen); 4048 if (buf == NULL) 4049 return NULL; 4050 wpa_snprintf_hex(buf, buflen, cred->roaming_consortium, 4051 cred->roaming_consortium_len); 4052 return buf; 4053 } 4054 4055 if (os_strcmp(var, "required_roaming_consortium") == 0) { 4056 size_t buflen; 4057 char *buf; 4058 4059 if (!cred->required_roaming_consortium_len) 4060 return NULL; 4061 buflen = cred->required_roaming_consortium_len * 2 + 1; 4062 buf = os_malloc(buflen); 4063 if (buf == NULL) 4064 return NULL; 4065 wpa_snprintf_hex(buf, buflen, cred->required_roaming_consortium, 4066 cred->required_roaming_consortium_len); 4067 return buf; 4068 } 4069 4070 if (os_strcmp(var, "roaming_consortiums") == 0) { 4071 size_t buflen; 4072 char *buf, *pos; 4073 size_t i; 4074 4075 if (!cred->num_roaming_consortiums) 4076 return NULL; 4077 buflen = cred->num_roaming_consortiums * 4078 MAX_ROAMING_CONS_OI_LEN * 2 + 1; 4079 buf = os_malloc(buflen); 4080 if (!buf) 4081 return NULL; 4082 pos = buf; 4083 for (i = 0; i < cred->num_roaming_consortiums; i++) { 4084 if (i > 0) 4085 *pos++ = ','; 4086 pos += wpa_snprintf_hex( 4087 pos, buf + buflen - pos, 4088 cred->roaming_consortiums[i], 4089 cred->roaming_consortiums_len[i]); 4090 } 4091 *pos = '\0'; 4092 return buf; 4093 } 4094 4095 if (os_strcmp(var, "excluded_ssid") == 0) { 4096 unsigned int i; 4097 char *buf, *end, *pos; 4098 4099 if (!cred->num_excluded_ssid) 4100 return NULL; 4101 4102 buf = os_malloc(4000); 4103 if (buf == NULL) 4104 return NULL; 4105 pos = buf; 4106 end = pos + 4000; 4107 4108 for (i = 0; i < cred->num_excluded_ssid; i++) { 4109 struct excluded_ssid *e; 4110 int ret; 4111 4112 e = &cred->excluded_ssid[i]; 4113 ret = os_snprintf(pos, end - pos, "%s%s", 4114 i > 0 ? "\n" : "", 4115 wpa_ssid_txt(e->ssid, e->ssid_len)); 4116 if (os_snprintf_error(end - pos, ret)) 4117 return buf; 4118 pos += ret; 4119 } 4120 4121 return buf; 4122 } 4123 4124 if (os_strcmp(var, "roaming_partner") == 0) { 4125 unsigned int i; 4126 char *buf, *end, *pos; 4127 4128 if (!cred->num_roaming_partner) 4129 return NULL; 4130 4131 buf = os_malloc(4000); 4132 if (buf == NULL) 4133 return NULL; 4134 pos = buf; 4135 end = pos + 4000; 4136 4137 for (i = 0; i < cred->num_roaming_partner; i++) { 4138 struct roaming_partner *p; 4139 int ret; 4140 4141 p = &cred->roaming_partner[i]; 4142 ret = os_snprintf(pos, end - pos, "%s%s,%d,%u,%s", 4143 i > 0 ? "\n" : "", 4144 p->fqdn, p->exact_match, p->priority, 4145 p->country); 4146 if (os_snprintf_error(end - pos, ret)) 4147 return buf; 4148 pos += ret; 4149 } 4150 4151 return buf; 4152 } 4153 4154 if (os_strcmp(var, "provisioning_sp") == 0) 4155 return alloc_strdup(cred->provisioning_sp); 4156 4157 return NULL; 4158 } 4159 4160 4161 struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id) 4162 { 4163 struct wpa_cred *cred; 4164 4165 cred = config->cred; 4166 while (cred) { 4167 if (id == cred->id) 4168 break; 4169 cred = cred->next; 4170 } 4171 4172 return cred; 4173 } 4174 4175 4176 struct wpa_cred * wpa_config_add_cred(struct wpa_config *config) 4177 { 4178 int id; 4179 struct wpa_cred *cred, *last = NULL; 4180 4181 id = -1; 4182 cred = config->cred; 4183 while (cred) { 4184 if (cred->id > id) 4185 id = cred->id; 4186 last = cred; 4187 cred = cred->next; 4188 } 4189 id++; 4190 4191 cred = os_zalloc(sizeof(*cred)); 4192 if (cred == NULL) 4193 return NULL; 4194 cred->id = id; 4195 cred->sim_num = DEFAULT_USER_SELECTED_SIM; 4196 if (last) 4197 last->next = cred; 4198 else 4199 config->cred = cred; 4200 4201 return cred; 4202 } 4203 4204 4205 int wpa_config_remove_cred(struct wpa_config *config, int id) 4206 { 4207 struct wpa_cred *cred, *prev = NULL; 4208 4209 cred = config->cred; 4210 while (cred) { 4211 if (id == cred->id) 4212 break; 4213 prev = cred; 4214 cred = cred->next; 4215 } 4216 4217 if (cred == NULL) 4218 return -1; 4219 4220 if (prev) 4221 prev->next = cred->next; 4222 else 4223 config->cred = cred->next; 4224 4225 wpa_config_free_cred(cred); 4226 return 0; 4227 } 4228 4229 4230 #ifndef CONFIG_NO_CONFIG_BLOBS 4231 /** 4232 * wpa_config_get_blob - Get a named configuration blob 4233 * @config: Configuration data from wpa_config_read() 4234 * @name: Name of the blob 4235 * Returns: Pointer to blob data or %NULL if not found 4236 */ 4237 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config, 4238 const char *name) 4239 { 4240 struct wpa_config_blob *blob = config->blobs; 4241 4242 while (blob) { 4243 if (os_strcmp(blob->name, name) == 0) 4244 return blob; 4245 blob = blob->next; 4246 } 4247 return NULL; 4248 } 4249 4250 4251 /** 4252 * wpa_config_set_blob - Set or add a named configuration blob 4253 * @config: Configuration data from wpa_config_read() 4254 * @blob: New value for the blob 4255 * 4256 * Adds a new configuration blob or replaces the current value of an existing 4257 * blob. 4258 */ 4259 void wpa_config_set_blob(struct wpa_config *config, 4260 struct wpa_config_blob *blob) 4261 { 4262 wpa_config_remove_blob(config, blob->name); 4263 blob->next = config->blobs; 4264 config->blobs = blob; 4265 } 4266 4267 4268 /** 4269 * wpa_config_free_blob - Free blob data 4270 * @blob: Pointer to blob to be freed 4271 */ 4272 void wpa_config_free_blob(struct wpa_config_blob *blob) 4273 { 4274 if (blob) { 4275 os_free(blob->name); 4276 bin_clear_free(blob->data, blob->len); 4277 os_free(blob); 4278 } 4279 } 4280 4281 4282 /** 4283 * wpa_config_remove_blob - Remove a named configuration blob 4284 * @config: Configuration data from wpa_config_read() 4285 * @name: Name of the blob to remove 4286 * Returns: 0 if blob was removed or -1 if blob was not found 4287 */ 4288 int wpa_config_remove_blob(struct wpa_config *config, const char *name) 4289 { 4290 struct wpa_config_blob *pos = config->blobs, *prev = NULL; 4291 4292 while (pos) { 4293 if (os_strcmp(pos->name, name) == 0) { 4294 if (prev) 4295 prev->next = pos->next; 4296 else 4297 config->blobs = pos->next; 4298 wpa_config_free_blob(pos); 4299 return 0; 4300 } 4301 prev = pos; 4302 pos = pos->next; 4303 } 4304 4305 return -1; 4306 } 4307 #endif /* CONFIG_NO_CONFIG_BLOBS */ 4308 4309 4310 /** 4311 * wpa_config_alloc_empty - Allocate an empty configuration 4312 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain 4313 * socket 4314 * @driver_param: Driver parameters 4315 * Returns: Pointer to allocated configuration data or %NULL on failure 4316 */ 4317 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, 4318 const char *driver_param) 4319 { 4320 #define ecw2cw(ecw) ((1 << (ecw)) - 1) 4321 4322 struct wpa_config *config; 4323 const int aCWmin = 4, aCWmax = 10; 4324 const struct hostapd_wmm_ac_params ac_bk = 4325 { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ 4326 const struct hostapd_wmm_ac_params ac_be = 4327 { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ 4328 const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ 4329 { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 }; 4330 const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ 4331 { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 }; 4332 const struct hostapd_tx_queue_params txq_bk = 4333 { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; 4334 const struct hostapd_tx_queue_params txq_be = 4335 { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0 }; 4336 const struct hostapd_tx_queue_params txq_vi = 4337 { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30 }; 4338 const struct hostapd_tx_queue_params txq_vo = 4339 { 1, (ecw2cw(aCWmin) + 1) / 4 - 1, 4340 (ecw2cw(aCWmin) + 1) / 2 - 1, 15 }; 4341 4342 #undef ecw2cw 4343 4344 config = os_zalloc(sizeof(*config)); 4345 if (config == NULL) 4346 return NULL; 4347 config->eapol_version = DEFAULT_EAPOL_VERSION; 4348 config->ap_scan = DEFAULT_AP_SCAN; 4349 config->user_mpm = DEFAULT_USER_MPM; 4350 config->max_peer_links = DEFAULT_MAX_PEER_LINKS; 4351 config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY; 4352 config->dot11RSNASAERetransPeriod = 4353 DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD; 4354 config->fast_reauth = DEFAULT_FAST_REAUTH; 4355 config->p2p_go_intent = DEFAULT_P2P_GO_INTENT; 4356 config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS; 4357 config->p2p_go_freq_change_policy = DEFAULT_P2P_GO_FREQ_MOVE; 4358 config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY; 4359 config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN; 4360 config->p2p_go_ctwindow = DEFAULT_P2P_GO_CTWINDOW; 4361 config->bss_max_count = DEFAULT_BSS_MAX_COUNT; 4362 config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE; 4363 config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT; 4364 config->max_num_sta = DEFAULT_MAX_NUM_STA; 4365 config->ap_isolate = DEFAULT_AP_ISOLATE; 4366 config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE; 4367 config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ; 4368 config->scan_res_valid_for_connect = DEFAULT_SCAN_RES_VALID_FOR_CONNECT; 4369 config->wmm_ac_params[0] = ac_be; 4370 config->wmm_ac_params[1] = ac_bk; 4371 config->wmm_ac_params[2] = ac_vi; 4372 config->wmm_ac_params[3] = ac_vo; 4373 config->tx_queue[0] = txq_vo; 4374 config->tx_queue[1] = txq_vi; 4375 config->tx_queue[2] = txq_be; 4376 config->tx_queue[3] = txq_bk; 4377 config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY; 4378 config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME; 4379 config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD; 4380 config->cert_in_cb = DEFAULT_CERT_IN_CB; 4381 config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION; 4382 config->extended_key_id = DEFAULT_EXTENDED_KEY_ID; 4383 4384 #ifdef CONFIG_MBO 4385 config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA; 4386 config->disassoc_imminent_rssi_threshold = 4387 DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD; 4388 config->oce = DEFAULT_OCE_SUPPORT; 4389 #endif /* CONFIG_MBO */ 4390 4391 if (ctrl_interface) 4392 config->ctrl_interface = os_strdup(ctrl_interface); 4393 if (driver_param) 4394 config->driver_param = os_strdup(driver_param); 4395 config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME; 4396 4397 return config; 4398 } 4399 4400 4401 #ifndef CONFIG_NO_STDOUT_DEBUG 4402 /** 4403 * wpa_config_debug_dump_networks - Debug dump of configured networks 4404 * @config: Configuration data from wpa_config_read() 4405 */ 4406 void wpa_config_debug_dump_networks(struct wpa_config *config) 4407 { 4408 size_t prio; 4409 struct wpa_ssid *ssid; 4410 4411 for (prio = 0; prio < config->num_prio; prio++) { 4412 ssid = config->pssid[prio]; 4413 wpa_printf(MSG_DEBUG, "Priority group %d", 4414 ssid->priority); 4415 while (ssid) { 4416 wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", 4417 ssid->id, 4418 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 4419 ssid = ssid->pnext; 4420 } 4421 } 4422 } 4423 #endif /* CONFIG_NO_STDOUT_DEBUG */ 4424 4425 4426 /** 4427 * Structure for global configuration parsing. This data is used to implement a 4428 * generic parser for the global interface configuration. The table of variables 4429 * is defined below in this file (global_fields[]). 4430 */ 4431 struct global_parse_data { 4432 /* Configuration variable name */ 4433 char *name; 4434 4435 /* Parser function for this variable. The parser functions return 0 or 1 4436 * to indicate success. Value 0 indicates that the parameter value may 4437 * have changed while value 1 means that the value did not change. 4438 * Error cases (failure to parse the string) are indicated by returning 4439 * -1. */ 4440 int (*parser)(const struct global_parse_data *data, 4441 struct wpa_config *config, int line, const char *value); 4442 4443 /* Getter function to print the variable in text format to buf. */ 4444 int (*get)(const char *name, struct wpa_config *config, long offset, 4445 char *buf, size_t buflen, int pretty_print); 4446 4447 /* Variable specific parameters for the parser. */ 4448 void *param1, *param2, *param3; 4449 4450 /* Indicates which configuration variable has changed. */ 4451 unsigned int changed_flag; 4452 }; 4453 4454 4455 static int wpa_global_config_parse_int(const struct global_parse_data *data, 4456 struct wpa_config *config, int line, 4457 const char *pos) 4458 { 4459 int val, *dst; 4460 char *end; 4461 bool same; 4462 4463 dst = (int *) (((u8 *) config) + (long) data->param1); 4464 val = strtol(pos, &end, 0); 4465 if (*end) { 4466 wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"", 4467 line, pos); 4468 return -1; 4469 } 4470 same = *dst == val; 4471 *dst = val; 4472 4473 wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); 4474 4475 if (data->param2 && *dst < (long) data->param2) { 4476 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " 4477 "min_value=%ld)", line, data->name, *dst, 4478 (long) data->param2); 4479 *dst = (long) data->param2; 4480 return -1; 4481 } 4482 4483 if (data->param3 && *dst > (long) data->param3) { 4484 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " 4485 "max_value=%ld)", line, data->name, *dst, 4486 (long) data->param3); 4487 *dst = (long) data->param3; 4488 return -1; 4489 } 4490 4491 return same; 4492 } 4493 4494 4495 static int wpa_global_config_parse_str(const struct global_parse_data *data, 4496 struct wpa_config *config, int line, 4497 const char *pos) 4498 { 4499 size_t len, prev_len; 4500 char **dst, *tmp; 4501 4502 len = os_strlen(pos); 4503 if (data->param2 && len < (size_t) data->param2) { 4504 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " 4505 "min_len=%ld)", line, data->name, 4506 (unsigned long) len, (long) data->param2); 4507 return -1; 4508 } 4509 4510 if (data->param3 && len > (size_t) data->param3) { 4511 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " 4512 "max_len=%ld)", line, data->name, 4513 (unsigned long) len, (long) data->param3); 4514 return -1; 4515 } 4516 4517 if (has_newline(pos)) { 4518 wpa_printf(MSG_ERROR, "Line %d: invalid %s value with newline", 4519 line, data->name); 4520 return -1; 4521 } 4522 4523 dst = (char **) (((u8 *) config) + (long) data->param1); 4524 if (*dst) 4525 prev_len = os_strlen(*dst); 4526 else 4527 prev_len = 0; 4528 4529 /* No change to the previously configured value */ 4530 if (*dst && prev_len == len && os_memcmp(*dst, pos, len) == 0) 4531 return 1; 4532 4533 tmp = os_strdup(pos); 4534 if (tmp == NULL) 4535 return -1; 4536 4537 os_free(*dst); 4538 *dst = tmp; 4539 wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); 4540 4541 return 0; 4542 } 4543 4544 4545 static int wpa_config_process_bgscan(const struct global_parse_data *data, 4546 struct wpa_config *config, int line, 4547 const char *pos) 4548 { 4549 size_t len; 4550 char *tmp; 4551 int res; 4552 4553 tmp = wpa_config_parse_string(pos, &len); 4554 if (tmp == NULL) { 4555 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s", 4556 line, data->name); 4557 return -1; 4558 } 4559 4560 res = wpa_global_config_parse_str(data, config, line, tmp); 4561 os_free(tmp); 4562 return res; 4563 } 4564 4565 4566 static int wpa_global_config_parse_bin(const struct global_parse_data *data, 4567 struct wpa_config *config, int line, 4568 const char *pos) 4569 { 4570 struct wpabuf **dst, *tmp; 4571 4572 tmp = wpabuf_parse_bin(pos); 4573 if (!tmp) 4574 return -1; 4575 4576 dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1); 4577 if (wpabuf_cmp(*dst, tmp) == 0) { 4578 wpabuf_free(tmp); 4579 return 1; 4580 } 4581 wpabuf_free(*dst); 4582 *dst = tmp; 4583 wpa_printf(MSG_DEBUG, "%s", data->name); 4584 4585 return 0; 4586 } 4587 4588 4589 static int wpa_config_process_freq_list(const struct global_parse_data *data, 4590 struct wpa_config *config, int line, 4591 const char *value) 4592 { 4593 int *freqs; 4594 4595 freqs = wpa_config_parse_int_array(value); 4596 if (freqs == NULL) 4597 return -1; 4598 if (freqs[0] == 0) { 4599 os_free(freqs); 4600 freqs = NULL; 4601 } 4602 os_free(config->freq_list); 4603 config->freq_list = freqs; 4604 return 0; 4605 } 4606 4607 4608 static int 4609 wpa_config_process_initial_freq_list(const struct global_parse_data *data, 4610 struct wpa_config *config, int line, 4611 const char *value) 4612 { 4613 int *freqs; 4614 4615 freqs = wpa_config_parse_int_array(value); 4616 if (!freqs) 4617 return -1; 4618 if (freqs[0] == 0) { 4619 os_free(freqs); 4620 freqs = NULL; 4621 } 4622 os_free(config->initial_freq_list); 4623 config->initial_freq_list = freqs; 4624 return 0; 4625 } 4626 4627 4628 #ifdef CONFIG_P2P 4629 static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, 4630 struct wpa_config *config, int line, 4631 const char *pos) 4632 { 4633 u32 *dst; 4634 struct hostapd_ip_addr addr; 4635 4636 if (hostapd_parse_ip_addr(pos, &addr) < 0) 4637 return -1; 4638 if (addr.af != AF_INET) 4639 return -1; 4640 4641 dst = (u32 *) (((u8 *) config) + (long) data->param1); 4642 if (os_memcmp(dst, &addr.u.v4.s_addr, 4) == 0) 4643 return 1; 4644 os_memcpy(dst, &addr.u.v4.s_addr, 4); 4645 wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name, 4646 WPA_GET_BE32((u8 *) dst)); 4647 4648 return 0; 4649 } 4650 #endif /* CONFIG_P2P */ 4651 4652 4653 static int wpa_config_process_country(const struct global_parse_data *data, 4654 struct wpa_config *config, int line, 4655 const char *pos) 4656 { 4657 if (!pos[0] || !pos[1]) { 4658 wpa_printf(MSG_DEBUG, "Invalid country set"); 4659 return -1; 4660 } 4661 if (pos[0] == config->country[0] && pos[1] == config->country[1]) 4662 return 1; 4663 config->country[0] = pos[0]; 4664 config->country[1] = pos[1]; 4665 wpa_printf(MSG_DEBUG, "country='%c%c'", 4666 config->country[0], config->country[1]); 4667 return 0; 4668 } 4669 4670 4671 static int wpa_config_process_load_dynamic_eap( 4672 const struct global_parse_data *data, struct wpa_config *config, 4673 int line, const char *so) 4674 { 4675 int ret; 4676 wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); 4677 ret = eap_peer_method_load(so); 4678 if (ret == -2) { 4679 wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not " 4680 "reloading."); 4681 } else if (ret) { 4682 wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP " 4683 "method '%s'.", line, so); 4684 return -1; 4685 } 4686 4687 return 0; 4688 } 4689 4690 4691 #ifdef CONFIG_WPS 4692 4693 static int wpa_config_process_uuid(const struct global_parse_data *data, 4694 struct wpa_config *config, int line, 4695 const char *pos) 4696 { 4697 char buf[40]; 4698 if (uuid_str2bin(pos, config->uuid)) { 4699 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); 4700 return -1; 4701 } 4702 uuid_bin2str(config->uuid, buf, sizeof(buf)); 4703 wpa_printf(MSG_DEBUG, "uuid=%s", buf); 4704 return 0; 4705 } 4706 4707 4708 static int wpa_config_process_device_type( 4709 const struct global_parse_data *data, 4710 struct wpa_config *config, int line, const char *pos) 4711 { 4712 return wps_dev_type_str2bin(pos, config->device_type); 4713 } 4714 4715 4716 static int wpa_config_process_os_version(const struct global_parse_data *data, 4717 struct wpa_config *config, int line, 4718 const char *pos) 4719 { 4720 if (hexstr2bin(pos, config->os_version, 4)) { 4721 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line); 4722 return -1; 4723 } 4724 wpa_printf(MSG_DEBUG, "os_version=%08x", 4725 WPA_GET_BE32(config->os_version)); 4726 return 0; 4727 } 4728 4729 4730 static int wpa_config_process_wps_vendor_ext_m1( 4731 const struct global_parse_data *data, 4732 struct wpa_config *config, int line, const char *pos) 4733 { 4734 struct wpabuf *tmp; 4735 int len = os_strlen(pos) / 2; 4736 u8 *p; 4737 4738 if (!len) { 4739 wpa_printf(MSG_ERROR, "Line %d: " 4740 "invalid wps_vendor_ext_m1", line); 4741 return -1; 4742 } 4743 4744 tmp = wpabuf_alloc(len); 4745 if (tmp) { 4746 p = wpabuf_put(tmp, len); 4747 4748 if (hexstr2bin(pos, p, len)) { 4749 wpa_printf(MSG_ERROR, "Line %d: " 4750 "invalid wps_vendor_ext_m1", line); 4751 wpabuf_free(tmp); 4752 return -1; 4753 } 4754 4755 wpabuf_free(config->wps_vendor_ext_m1); 4756 config->wps_vendor_ext_m1 = tmp; 4757 } else { 4758 wpa_printf(MSG_ERROR, "Can not allocate " 4759 "memory for wps_vendor_ext_m1"); 4760 return -1; 4761 } 4762 4763 return 0; 4764 } 4765 4766 #endif /* CONFIG_WPS */ 4767 4768 #ifdef CONFIG_P2P 4769 static int wpa_config_process_sec_device_type( 4770 const struct global_parse_data *data, 4771 struct wpa_config *config, int line, const char *pos) 4772 { 4773 int idx; 4774 4775 if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) { 4776 wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type " 4777 "items", line); 4778 return -1; 4779 } 4780 4781 idx = config->num_sec_device_types; 4782 4783 if (wps_dev_type_str2bin(pos, config->sec_device_type[idx])) 4784 return -1; 4785 4786 config->num_sec_device_types++; 4787 return 0; 4788 } 4789 4790 4791 static int wpa_config_process_p2p_pref_chan( 4792 const struct global_parse_data *data, 4793 struct wpa_config *config, int line, const char *pos) 4794 { 4795 struct p2p_channel *pref = NULL, *n; 4796 size_t num = 0; 4797 const char *pos2; 4798 u8 op_class, chan; 4799 4800 /* format: class:chan,class:chan,... */ 4801 4802 while (*pos) { 4803 op_class = atoi(pos); 4804 pos2 = os_strchr(pos, ':'); 4805 if (pos2 == NULL) 4806 goto fail; 4807 pos2++; 4808 chan = atoi(pos2); 4809 4810 n = os_realloc_array(pref, num + 1, 4811 sizeof(struct p2p_channel)); 4812 if (n == NULL) 4813 goto fail; 4814 pref = n; 4815 pref[num].op_class = op_class; 4816 pref[num].chan = chan; 4817 num++; 4818 4819 pos = os_strchr(pos2, ','); 4820 if (pos == NULL) 4821 break; 4822 pos++; 4823 } 4824 4825 os_free(config->p2p_pref_chan); 4826 config->p2p_pref_chan = pref; 4827 config->num_p2p_pref_chan = num; 4828 wpa_hexdump(MSG_DEBUG, "P2P: Preferred class/channel pairs", 4829 (u8 *) config->p2p_pref_chan, 4830 config->num_p2p_pref_chan * sizeof(struct p2p_channel)); 4831 4832 return 0; 4833 4834 fail: 4835 os_free(pref); 4836 wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_pref_chan list", line); 4837 return -1; 4838 } 4839 4840 4841 static int wpa_config_process_p2p_no_go_freq( 4842 const struct global_parse_data *data, 4843 struct wpa_config *config, int line, const char *pos) 4844 { 4845 int ret; 4846 4847 ret = freq_range_list_parse(&config->p2p_no_go_freq, pos); 4848 if (ret < 0) { 4849 wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_no_go_freq", line); 4850 return -1; 4851 } 4852 4853 wpa_printf(MSG_DEBUG, "P2P: p2p_no_go_freq with %u items", 4854 config->p2p_no_go_freq.num); 4855 4856 return 0; 4857 } 4858 4859 4860 static int wpa_config_process_p2p_device_persistent_mac_addr( 4861 const struct global_parse_data *data, 4862 struct wpa_config *config, int line, const char *pos) 4863 { 4864 if (hwaddr_aton2(pos, config->p2p_device_persistent_mac_addr) < 0) { 4865 wpa_printf(MSG_ERROR, 4866 "Line %d: Invalid p2p_device_persistent_mac_addr '%s'", 4867 line, pos); 4868 return -1; 4869 } 4870 4871 return 0; 4872 } 4873 4874 #endif /* CONFIG_P2P */ 4875 4876 4877 static int wpa_config_process_hessid( 4878 const struct global_parse_data *data, 4879 struct wpa_config *config, int line, const char *pos) 4880 { 4881 if (hwaddr_aton2(pos, config->hessid) < 0) { 4882 wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'", 4883 line, pos); 4884 return -1; 4885 } 4886 4887 return 0; 4888 } 4889 4890 4891 static int wpa_config_process_sae_groups( 4892 const struct global_parse_data *data, 4893 struct wpa_config *config, int line, const char *pos) 4894 { 4895 int *groups = wpa_config_parse_int_array(pos); 4896 if (groups == NULL) { 4897 wpa_printf(MSG_ERROR, "Line %d: Invalid sae_groups '%s'", 4898 line, pos); 4899 return -1; 4900 } 4901 4902 os_free(config->sae_groups); 4903 config->sae_groups = groups; 4904 4905 return 0; 4906 } 4907 4908 4909 static int wpa_config_process_ap_vendor_elements( 4910 const struct global_parse_data *data, 4911 struct wpa_config *config, int line, const char *pos) 4912 { 4913 struct wpabuf *tmp; 4914 4915 if (!*pos) { 4916 wpabuf_free(config->ap_vendor_elements); 4917 config->ap_vendor_elements = NULL; 4918 return 0; 4919 } 4920 4921 tmp = wpabuf_parse_bin(pos); 4922 if (!tmp) { 4923 wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements", 4924 line); 4925 return -1; 4926 } 4927 wpabuf_free(config->ap_vendor_elements); 4928 config->ap_vendor_elements = tmp; 4929 4930 return 0; 4931 } 4932 4933 4934 static int wpa_config_process_ap_assocresp_elements( 4935 const struct global_parse_data *data, 4936 struct wpa_config *config, int line, const char *pos) 4937 { 4938 struct wpabuf *tmp; 4939 4940 if (!*pos) { 4941 wpabuf_free(config->ap_assocresp_elements); 4942 config->ap_assocresp_elements = NULL; 4943 return 0; 4944 } 4945 4946 tmp = wpabuf_parse_bin(pos); 4947 if (!tmp) { 4948 wpa_printf(MSG_ERROR, "Line %d: invalid ap_assocresp_elements", 4949 line); 4950 return -1; 4951 } 4952 wpabuf_free(config->ap_assocresp_elements); 4953 config->ap_assocresp_elements = tmp; 4954 4955 return 0; 4956 } 4957 4958 4959 #ifdef CONFIG_CTRL_IFACE 4960 static int wpa_config_process_no_ctrl_interface( 4961 const struct global_parse_data *data, 4962 struct wpa_config *config, int line, const char *pos) 4963 { 4964 wpa_printf(MSG_DEBUG, "no_ctrl_interface -> ctrl_interface=NULL"); 4965 os_free(config->ctrl_interface); 4966 config->ctrl_interface = NULL; 4967 return 0; 4968 } 4969 #endif /* CONFIG_CTRL_IFACE */ 4970 4971 4972 static int wpa_config_get_int(const char *name, struct wpa_config *config, 4973 long offset, char *buf, size_t buflen, 4974 int pretty_print) 4975 { 4976 int *val = (int *) (((u8 *) config) + (long) offset); 4977 4978 if (pretty_print) 4979 return os_snprintf(buf, buflen, "%s=%d\n", name, *val); 4980 return os_snprintf(buf, buflen, "%d", *val); 4981 } 4982 4983 4984 static int wpa_config_get_str(const char *name, struct wpa_config *config, 4985 long offset, char *buf, size_t buflen, 4986 int pretty_print) 4987 { 4988 char **val = (char **) (((u8 *) config) + (long) offset); 4989 int res; 4990 4991 if (pretty_print) 4992 res = os_snprintf(buf, buflen, "%s=%s\n", name, 4993 *val ? *val : "null"); 4994 else if (!*val) 4995 return -1; 4996 else 4997 res = os_snprintf(buf, buflen, "%s", *val); 4998 if (os_snprintf_error(buflen, res)) 4999 res = -1; 5000 5001 return res; 5002 } 5003 5004 5005 #ifdef CONFIG_P2P 5006 static int wpa_config_get_ipv4(const char *name, struct wpa_config *config, 5007 long offset, char *buf, size_t buflen, 5008 int pretty_print) 5009 { 5010 void *val = ((u8 *) config) + (long) offset; 5011 int res; 5012 char addr[INET_ADDRSTRLEN]; 5013 5014 if (!val || !inet_ntop(AF_INET, val, addr, sizeof(addr))) 5015 return -1; 5016 5017 if (pretty_print) 5018 res = os_snprintf(buf, buflen, "%s=%s\n", name, addr); 5019 else 5020 res = os_snprintf(buf, buflen, "%s", addr); 5021 5022 if (os_snprintf_error(buflen, res)) 5023 res = -1; 5024 5025 return res; 5026 } 5027 #endif /* CONFIG_P2P */ 5028 5029 5030 #ifdef OFFSET 5031 #undef OFFSET 5032 #endif /* OFFSET */ 5033 /* OFFSET: Get offset of a variable within the wpa_config structure */ 5034 #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v) 5035 5036 #define FUNC(f) #f, wpa_config_process_ ## f, NULL, OFFSET(f), NULL, NULL 5037 #define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL, NULL 5038 #define _INT(f) #f, wpa_global_config_parse_int, wpa_config_get_int, OFFSET(f) 5039 #define INT(f) _INT(f), NULL, NULL 5040 #define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max 5041 #define _STR(f) #f, wpa_global_config_parse_str, wpa_config_get_str, OFFSET(f) 5042 #define STR(f) _STR(f), NULL, NULL 5043 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max 5044 #define BIN(f) #f, wpa_global_config_parse_bin, NULL, OFFSET(f), NULL, NULL 5045 #define IPV4(f) #f, wpa_global_config_parse_ipv4, wpa_config_get_ipv4, \ 5046 OFFSET(f), NULL, NULL 5047 5048 static const struct global_parse_data global_fields[] = { 5049 #ifdef CONFIG_CTRL_IFACE 5050 { STR(ctrl_interface), 0 }, 5051 { FUNC_NO_VAR(no_ctrl_interface), 0 }, 5052 { STR(ctrl_interface_group), 0 } /* deprecated */, 5053 #endif /* CONFIG_CTRL_IFACE */ 5054 #ifdef CONFIG_MACSEC 5055 { INT_RANGE(eapol_version, 1, 3), 0 }, 5056 #else /* CONFIG_MACSEC */ 5057 { INT_RANGE(eapol_version, 1, 2), 0 }, 5058 #endif /* CONFIG_MACSEC */ 5059 { INT(ap_scan), 0 }, 5060 { FUNC(bgscan), CFG_CHANGED_BGSCAN }, 5061 #ifdef CONFIG_MESH 5062 { INT(user_mpm), 0 }, 5063 { INT_RANGE(max_peer_links, 0, 255), 0 }, 5064 { INT(mesh_max_inactivity), 0 }, 5065 { INT(dot11RSNASAERetransPeriod), 0 }, 5066 #endif /* CONFIG_MESH */ 5067 { INT(disable_scan_offload), 0 }, 5068 { INT(fast_reauth), 0 }, 5069 { STR(opensc_engine_path), 0 }, 5070 { STR(pkcs11_engine_path), 0 }, 5071 { STR(pkcs11_module_path), 0 }, 5072 { STR(openssl_ciphers), 0 }, 5073 { STR(pcsc_reader), 0 }, 5074 { STR(pcsc_pin), 0 }, 5075 { INT(external_sim), 0 }, 5076 { STR(driver_param), 0 }, 5077 { INT(dot11RSNAConfigPMKLifetime), 0 }, 5078 { INT(dot11RSNAConfigPMKReauthThreshold), 0 }, 5079 { INT(dot11RSNAConfigSATimeout), 0 }, 5080 #ifndef CONFIG_NO_CONFIG_WRITE 5081 { INT(update_config), 0 }, 5082 #endif /* CONFIG_NO_CONFIG_WRITE */ 5083 { FUNC_NO_VAR(load_dynamic_eap), 0 }, 5084 #ifdef CONFIG_WPS 5085 { FUNC(uuid), CFG_CHANGED_UUID }, 5086 { INT_RANGE(auto_uuid, 0, 1), 0 }, 5087 { STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN), 5088 CFG_CHANGED_DEVICE_NAME }, 5089 { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING }, 5090 { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING }, 5091 { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING }, 5092 { STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING }, 5093 { FUNC(device_type), CFG_CHANGED_DEVICE_TYPE }, 5094 { FUNC(os_version), CFG_CHANGED_OS_VERSION }, 5095 { STR(config_methods), CFG_CHANGED_CONFIG_METHODS }, 5096 { INT_RANGE(wps_cred_processing, 0, 2), 0 }, 5097 { INT_RANGE(wps_cred_add_sae, 0, 1), 0 }, 5098 { FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION }, 5099 #endif /* CONFIG_WPS */ 5100 #ifdef CONFIG_P2P 5101 { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE }, 5102 { INT(p2p_listen_reg_class), CFG_CHANGED_P2P_LISTEN_CHANNEL }, 5103 { INT(p2p_listen_channel), CFG_CHANGED_P2P_LISTEN_CHANNEL }, 5104 { INT(p2p_oper_reg_class), CFG_CHANGED_P2P_OPER_CHANNEL }, 5105 { INT(p2p_oper_channel), CFG_CHANGED_P2P_OPER_CHANNEL }, 5106 { INT_RANGE(p2p_go_intent, 0, 15), 0 }, 5107 { STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX }, 5108 { INT_RANGE(persistent_reconnect, 0, 1), 0 }, 5109 { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS }, 5110 { INT(p2p_group_idle), 0 }, 5111 { INT_RANGE(p2p_go_freq_change_policy, 0, P2P_GO_FREQ_MOVE_MAX), 0 }, 5112 { INT_RANGE(p2p_passphrase_len, 8, 63), 5113 CFG_CHANGED_P2P_PASSPHRASE_LEN }, 5114 { FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN }, 5115 { FUNC(p2p_no_go_freq), CFG_CHANGED_P2P_PREF_CHAN }, 5116 { INT_RANGE(p2p_add_cli_chan, 0, 1), 0 }, 5117 { INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 }, 5118 { INT(p2p_go_ht40), 0 }, 5119 { INT(p2p_go_vht), 0 }, 5120 { INT(p2p_go_he), 0 }, 5121 { INT(p2p_go_edmg), 0 }, 5122 { INT(p2p_disabled), 0 }, 5123 { INT_RANGE(p2p_go_ctwindow, 0, 127), 0 }, 5124 { INT(p2p_no_group_iface), 0 }, 5125 { INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 }, 5126 { IPV4(ip_addr_go), 0 }, 5127 { IPV4(ip_addr_mask), 0 }, 5128 { IPV4(ip_addr_start), 0 }, 5129 { IPV4(ip_addr_end), 0 }, 5130 { INT_RANGE(p2p_cli_probe, 0, 1), 0 }, 5131 { INT(p2p_device_random_mac_addr), 0 }, 5132 { FUNC(p2p_device_persistent_mac_addr), 0 }, 5133 { INT(p2p_interface_random_mac_addr), 0 }, 5134 { INT(p2p_6ghz_disable), 0 }, 5135 #endif /* CONFIG_P2P */ 5136 { FUNC(country), CFG_CHANGED_COUNTRY }, 5137 { INT(bss_max_count), 0 }, 5138 { INT(bss_expiration_age), 0 }, 5139 { INT(bss_expiration_scan_count), 0 }, 5140 { INT_RANGE(filter_ssids, 0, 1), 0 }, 5141 { INT_RANGE(filter_rssi, -100, 0), 0 }, 5142 { INT(max_num_sta), 0 }, 5143 { INT_RANGE(ap_isolate, 0, 1), 0 }, 5144 { INT_RANGE(disassoc_low_ack, 0, 1), 0 }, 5145 #ifdef CONFIG_HS20 5146 { INT_RANGE(hs20, 0, 1), 0 }, 5147 #endif /* CONFIG_HS20 */ 5148 { INT_RANGE(interworking, 0, 1), 0 }, 5149 { FUNC(hessid), 0 }, 5150 { INT_RANGE(access_network_type, 0, 15), 0 }, 5151 { INT_RANGE(go_interworking, 0, 1), 0 }, 5152 { INT_RANGE(go_access_network_type, 0, 15), 0 }, 5153 { INT_RANGE(go_internet, 0, 1), 0 }, 5154 { INT_RANGE(go_venue_group, 0, 255), 0 }, 5155 { INT_RANGE(go_venue_type, 0, 255), 0 }, 5156 { INT_RANGE(pbc_in_m1, 0, 1), 0 }, 5157 { STR(autoscan), 0 }, 5158 { INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff), 5159 CFG_CHANGED_NFC_PASSWORD_TOKEN }, 5160 { BIN(wps_nfc_dh_pubkey), CFG_CHANGED_NFC_PASSWORD_TOKEN }, 5161 { BIN(wps_nfc_dh_privkey), CFG_CHANGED_NFC_PASSWORD_TOKEN }, 5162 { BIN(wps_nfc_dev_pw), CFG_CHANGED_NFC_PASSWORD_TOKEN }, 5163 { STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND }, 5164 { INT(p2p_go_max_inactivity), 0 }, 5165 { INT_RANGE(auto_interworking, 0, 1), 0 }, 5166 { INT(okc), 0 }, 5167 { INT(pmf), 0 }, 5168 { FUNC(sae_groups), 0 }, 5169 { INT_RANGE(sae_pwe, 0, 3), 0 }, 5170 { INT_RANGE(sae_pmkid_in_assoc, 0, 1), 0 }, 5171 { INT(dtim_period), 0 }, 5172 { INT(beacon_int), 0 }, 5173 { FUNC(ap_assocresp_elements), 0 }, 5174 { FUNC(ap_vendor_elements), 0 }, 5175 { INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, 5176 { FUNC(freq_list), 0 }, 5177 { FUNC(initial_freq_list), 0}, 5178 { INT(scan_cur_freq), 0 }, 5179 { INT(scan_res_valid_for_connect), 0}, 5180 { INT(sched_scan_interval), 0 }, 5181 { INT(sched_scan_start_delay), 0 }, 5182 { INT(tdls_external_control), 0}, 5183 { STR(osu_dir), 0 }, 5184 { STR(wowlan_triggers), CFG_CHANGED_WOWLAN_TRIGGERS }, 5185 { INT(p2p_search_delay), 0}, 5186 { INT(mac_addr), 0 }, 5187 { INT(rand_addr_lifetime), 0 }, 5188 { INT(preassoc_mac_addr), 0 }, 5189 { INT(key_mgmt_offload), 0}, 5190 { INT(passive_scan), 0 }, 5191 { INT(reassoc_same_bss_optim), 0 }, 5192 { INT(wps_priority), 0}, 5193 #ifdef CONFIG_FST 5194 { STR_RANGE(fst_group_id, 1, FST_MAX_GROUP_ID_LEN), 0 }, 5195 { INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 }, 5196 { INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 }, 5197 #endif /* CONFIG_FST */ 5198 { INT_RANGE(cert_in_cb, 0, 1), 0 }, 5199 { INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 }, 5200 { STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS }, 5201 #ifdef CONFIG_MBO 5202 { STR(non_pref_chan), 0 }, 5203 { INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE, 5204 MBO_CELL_CAPA_NOT_SUPPORTED), 0 }, 5205 { INT_RANGE(disassoc_imminent_rssi_threshold, -120, 0), 0 }, 5206 { INT_RANGE(oce, 0, 3), 0 }, 5207 #endif /* CONFIG_MBO */ 5208 { INT(gas_address3), 0 }, 5209 { INT_RANGE(ftm_responder, 0, 1), 0 }, 5210 { INT_RANGE(ftm_initiator, 0, 1), 0 }, 5211 { INT(gas_rand_addr_lifetime), 0 }, 5212 { INT_RANGE(gas_rand_mac_addr, 0, 2), 0 }, 5213 #ifdef CONFIG_DPP 5214 { INT_RANGE(dpp_config_processing, 0, 2), 0 }, 5215 { STR(dpp_name), 0 }, 5216 { STR(dpp_mud_url), 0 }, 5217 #endif /* CONFIG_DPP */ 5218 { INT_RANGE(coloc_intf_reporting, 0, 1), 0 }, 5219 #ifdef CONFIG_WNM 5220 { INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM }, 5221 { INT_RANGE(extended_key_id, 0, 1), 0 }, 5222 #endif /* CONFIG_WNM */ 5223 { INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0}, 5224 #ifdef CONFIG_PASN 5225 #ifdef CONFIG_TESTING_OPTIONS 5226 { INT_RANGE(force_kdk_derivation, 0, 1), 0 }, 5227 { INT_RANGE(pasn_corrupt_mic, 0, 1), 0 }, 5228 #endif /* CONFIG_TESTING_OPTIONS */ 5229 #endif /* CONFIG_PASN */ 5230 }; 5231 5232 #undef FUNC 5233 #undef _INT 5234 #undef INT 5235 #undef INT_RANGE 5236 #undef _STR 5237 #undef STR 5238 #undef STR_RANGE 5239 #undef BIN 5240 #undef IPV4 5241 #define NUM_GLOBAL_FIELDS ARRAY_SIZE(global_fields) 5242 5243 5244 int wpa_config_dump_values(struct wpa_config *config, char *buf, size_t buflen) 5245 { 5246 int result = 0; 5247 size_t i; 5248 5249 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 5250 const struct global_parse_data *field = &global_fields[i]; 5251 int tmp; 5252 5253 if (!field->get) 5254 continue; 5255 5256 tmp = field->get(field->name, config, (long) field->param1, 5257 buf, buflen, 1); 5258 if (tmp < 0) 5259 return -1; 5260 buf += tmp; 5261 buflen -= tmp; 5262 result += tmp; 5263 } 5264 return result; 5265 } 5266 5267 5268 int wpa_config_get_value(const char *name, struct wpa_config *config, 5269 char *buf, size_t buflen) 5270 { 5271 size_t i; 5272 5273 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 5274 const struct global_parse_data *field = &global_fields[i]; 5275 5276 if (os_strcmp(name, field->name) != 0) 5277 continue; 5278 if (!field->get) 5279 break; 5280 return field->get(name, config, (long) field->param1, 5281 buf, buflen, 0); 5282 } 5283 5284 return -1; 5285 } 5286 5287 5288 int wpa_config_get_num_global_field_names(void) 5289 { 5290 return NUM_GLOBAL_FIELDS; 5291 } 5292 5293 5294 const char * wpa_config_get_global_field_name(unsigned int i, int *no_var) 5295 { 5296 if (i >= NUM_GLOBAL_FIELDS) 5297 return NULL; 5298 5299 if (no_var) 5300 *no_var = !global_fields[i].param1; 5301 return global_fields[i].name; 5302 } 5303 5304 5305 /** 5306 * wpa_config_process_global - Set a variable in global configuration 5307 * @config: Pointer to global configuration data 5308 * @pos: Name and value in the format "{name}={value}" 5309 * @line: Line number in configuration file or 0 if not used 5310 * Returns: 0 on success with a possible change in value, 1 on success with no 5311 * change to previously configured value, or -1 on failure 5312 * 5313 * This function can be used to set global configuration variables based on 5314 * both the configuration file and management interface input. The value 5315 * parameter must be in the same format as the text-based configuration file is 5316 * using. For example, strings are using double quotation marks. 5317 */ 5318 int wpa_config_process_global(struct wpa_config *config, char *pos, int line) 5319 { 5320 size_t i; 5321 int ret = 0; 5322 5323 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 5324 const struct global_parse_data *field = &global_fields[i]; 5325 size_t flen = os_strlen(field->name); 5326 if (os_strncmp(pos, field->name, flen) != 0 || 5327 pos[flen] != '=') 5328 continue; 5329 5330 ret = field->parser(field, config, line, pos + flen + 1); 5331 if (ret < 0) { 5332 wpa_printf(MSG_ERROR, "Line %d: failed to " 5333 "parse '%s'.", line, pos); 5334 ret = -1; 5335 } 5336 if (ret == 1) 5337 break; 5338 if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN) 5339 config->wps_nfc_pw_from_config = 1; 5340 config->changed_parameters |= field->changed_flag; 5341 break; 5342 } 5343 if (i == NUM_GLOBAL_FIELDS) { 5344 #ifdef CONFIG_AP 5345 if (os_strncmp(pos, "tx_queue_", 9) == 0) { 5346 char *tmp = os_strchr(pos, '='); 5347 5348 if (!tmp) { 5349 if (line < 0) 5350 wpa_printf(MSG_ERROR, 5351 "Line %d: invalid line %s", 5352 line, pos); 5353 return -1; 5354 } 5355 *tmp++ = '\0'; 5356 if (hostapd_config_tx_queue(config->tx_queue, pos, 5357 tmp)) { 5358 wpa_printf(MSG_ERROR, 5359 "Line %d: invalid TX queue item", 5360 line); 5361 return -1; 5362 } 5363 } 5364 5365 if (os_strncmp(pos, "wmm_ac_", 7) == 0) { 5366 char *tmp = os_strchr(pos, '='); 5367 if (tmp == NULL) { 5368 if (line < 0) 5369 return -1; 5370 wpa_printf(MSG_ERROR, "Line %d: invalid line " 5371 "'%s'", line, pos); 5372 return -1; 5373 } 5374 *tmp++ = '\0'; 5375 if (hostapd_config_wmm_ac(config->wmm_ac_params, pos, 5376 tmp)) { 5377 wpa_printf(MSG_ERROR, "Line %d: invalid WMM " 5378 "AC item", line); 5379 return -1; 5380 } 5381 return ret; 5382 } 5383 #endif /* CONFIG_AP */ 5384 if (line < 0) 5385 return -1; 5386 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", 5387 line, pos); 5388 ret = -1; 5389 } 5390 5391 return ret; 5392 } 5393