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