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