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