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