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