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