config.c revision 9d9e60286e05ae45025b672636490bd12586138d
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 */ 30struct 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 57static 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 104set: 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 117static 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 133static 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 146static 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 158static 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 178static 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 216static 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 238static 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 297static 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 331static 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 353static 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 376static 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 388static 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 398static 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 410static 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 420static 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 491static 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 524static 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 578static 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 623static 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 714static 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 899static 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 917static 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 933static 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 954static 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 962static 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 983static 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 991static 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 1044static 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 1095static 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 1136static 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 1156static 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 1177static 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 1210static 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 1217static 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 1226static 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#ifndef NO_CONFIG_WRITE 1300static char * wpa_config_write_eap(const struct parse_data *data, 1301 struct wpa_ssid *ssid) 1302{ 1303 int i, ret; 1304 char *buf, *pos, *end; 1305 const struct eap_method_type *eap_methods = ssid->eap.eap_methods; 1306 const char *name; 1307 1308 if (eap_methods == NULL) 1309 return NULL; 1310 1311 pos = buf = os_zalloc(100); 1312 if (buf == NULL) 1313 return NULL; 1314 end = buf + 100; 1315 1316 for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF || 1317 eap_methods[i].method != EAP_TYPE_NONE; i++) { 1318 name = eap_get_name(eap_methods[i].vendor, 1319 eap_methods[i].method); 1320 if (name) { 1321 ret = os_snprintf(pos, end - pos, "%s%s", 1322 pos == buf ? "" : " ", name); 1323 if (os_snprintf_error(end - pos, ret)) 1324 break; 1325 pos += ret; 1326 } 1327 } 1328 1329 end[-1] = '\0'; 1330 1331 return buf; 1332} 1333#endif /* NO_CONFIG_WRITE */ 1334 1335 1336static int wpa_config_parse_password(const struct parse_data *data, 1337 struct wpa_ssid *ssid, int line, 1338 const char *value) 1339{ 1340 u8 *hash; 1341 1342 if (os_strcmp(value, "NULL") == 0) { 1343 wpa_printf(MSG_DEBUG, "Unset configuration string 'password'"); 1344 bin_clear_free(ssid->eap.password, ssid->eap.password_len); 1345 ssid->eap.password = NULL; 1346 ssid->eap.password_len = 0; 1347 return 0; 1348 } 1349 1350#ifdef CONFIG_EXT_PASSWORD 1351 if (os_strncmp(value, "ext:", 4) == 0) { 1352 char *name = os_strdup(value + 4); 1353 if (name == NULL) 1354 return -1; 1355 bin_clear_free(ssid->eap.password, ssid->eap.password_len); 1356 ssid->eap.password = (u8 *) name; 1357 ssid->eap.password_len = os_strlen(name); 1358 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; 1359 ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_PASSWORD; 1360 return 0; 1361 } 1362#endif /* CONFIG_EXT_PASSWORD */ 1363 1364 if (os_strncmp(value, "hash:", 5) != 0) { 1365 char *tmp; 1366 size_t res_len; 1367 1368 tmp = wpa_config_parse_string(value, &res_len); 1369 if (tmp == NULL) { 1370 wpa_printf(MSG_ERROR, "Line %d: failed to parse " 1371 "password.", line); 1372 return -1; 1373 } 1374 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, 1375 (u8 *) tmp, res_len); 1376 1377 bin_clear_free(ssid->eap.password, ssid->eap.password_len); 1378 ssid->eap.password = (u8 *) tmp; 1379 ssid->eap.password_len = res_len; 1380 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; 1381 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD; 1382 1383 return 0; 1384 } 1385 1386 1387 /* NtPasswordHash: hash:<32 hex digits> */ 1388 if (os_strlen(value + 5) != 2 * 16) { 1389 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length " 1390 "(expected 32 hex digits)", line); 1391 return -1; 1392 } 1393 1394 hash = os_malloc(16); 1395 if (hash == NULL) 1396 return -1; 1397 1398 if (hexstr2bin(value + 5, hash, 16)) { 1399 os_free(hash); 1400 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line); 1401 return -1; 1402 } 1403 1404 wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16); 1405 1406 bin_clear_free(ssid->eap.password, ssid->eap.password_len); 1407 ssid->eap.password = hash; 1408 ssid->eap.password_len = 16; 1409 ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH; 1410 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD; 1411 1412 return 0; 1413} 1414 1415 1416#ifndef NO_CONFIG_WRITE 1417static char * wpa_config_write_password(const struct parse_data *data, 1418 struct wpa_ssid *ssid) 1419{ 1420 char *buf; 1421 1422 if (ssid->eap.password == NULL) 1423 return NULL; 1424 1425#ifdef CONFIG_EXT_PASSWORD 1426 if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) { 1427 buf = os_zalloc(4 + ssid->eap.password_len + 1); 1428 if (buf == NULL) 1429 return NULL; 1430 os_memcpy(buf, "ext:", 4); 1431 os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len); 1432 return buf; 1433 } 1434#endif /* CONFIG_EXT_PASSWORD */ 1435 1436 if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) { 1437 return wpa_config_write_string( 1438 ssid->eap.password, ssid->eap.password_len); 1439 } 1440 1441 buf = os_malloc(5 + 32 + 1); 1442 if (buf == NULL) 1443 return NULL; 1444 1445 os_memcpy(buf, "hash:", 5); 1446 wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16); 1447 1448 return buf; 1449} 1450#endif /* NO_CONFIG_WRITE */ 1451#endif /* IEEE8021X_EAPOL */ 1452 1453 1454static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, 1455 const char *value, int idx) 1456{ 1457 char *buf, title[20]; 1458 int res; 1459 1460 buf = wpa_config_parse_string(value, len); 1461 if (buf == NULL) { 1462 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.", 1463 line, idx, value); 1464 return -1; 1465 } 1466 if (*len > MAX_WEP_KEY_LEN) { 1467 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.", 1468 line, idx, value); 1469 os_free(buf); 1470 return -1; 1471 } 1472 if (*len && *len != 5 && *len != 13 && *len != 16) { 1473 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key length %u - " 1474 "this network block will be ignored", 1475 line, (unsigned int) *len); 1476 } 1477 os_memcpy(key, buf, *len); 1478 str_clear_free(buf); 1479 res = os_snprintf(title, sizeof(title), "wep_key%d", idx); 1480 if (!os_snprintf_error(sizeof(title), res)) 1481 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len); 1482 return 0; 1483} 1484 1485 1486static int wpa_config_parse_wep_key0(const struct parse_data *data, 1487 struct wpa_ssid *ssid, int line, 1488 const char *value) 1489{ 1490 return wpa_config_parse_wep_key(ssid->wep_key[0], 1491 &ssid->wep_key_len[0], line, 1492 value, 0); 1493} 1494 1495 1496static int wpa_config_parse_wep_key1(const struct parse_data *data, 1497 struct wpa_ssid *ssid, int line, 1498 const char *value) 1499{ 1500 return wpa_config_parse_wep_key(ssid->wep_key[1], 1501 &ssid->wep_key_len[1], line, 1502 value, 1); 1503} 1504 1505 1506static int wpa_config_parse_wep_key2(const struct parse_data *data, 1507 struct wpa_ssid *ssid, int line, 1508 const char *value) 1509{ 1510 return wpa_config_parse_wep_key(ssid->wep_key[2], 1511 &ssid->wep_key_len[2], line, 1512 value, 2); 1513} 1514 1515 1516static int wpa_config_parse_wep_key3(const struct parse_data *data, 1517 struct wpa_ssid *ssid, int line, 1518 const char *value) 1519{ 1520 return wpa_config_parse_wep_key(ssid->wep_key[3], 1521 &ssid->wep_key_len[3], line, 1522 value, 3); 1523} 1524 1525 1526#ifndef NO_CONFIG_WRITE 1527static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx) 1528{ 1529 if (ssid->wep_key_len[idx] == 0) 1530 return NULL; 1531 return wpa_config_write_string(ssid->wep_key[idx], 1532 ssid->wep_key_len[idx]); 1533} 1534 1535 1536static char * wpa_config_write_wep_key0(const struct parse_data *data, 1537 struct wpa_ssid *ssid) 1538{ 1539 return wpa_config_write_wep_key(ssid, 0); 1540} 1541 1542 1543static char * wpa_config_write_wep_key1(const struct parse_data *data, 1544 struct wpa_ssid *ssid) 1545{ 1546 return wpa_config_write_wep_key(ssid, 1); 1547} 1548 1549 1550static char * wpa_config_write_wep_key2(const struct parse_data *data, 1551 struct wpa_ssid *ssid) 1552{ 1553 return wpa_config_write_wep_key(ssid, 2); 1554} 1555 1556 1557static char * wpa_config_write_wep_key3(const struct parse_data *data, 1558 struct wpa_ssid *ssid) 1559{ 1560 return wpa_config_write_wep_key(ssid, 3); 1561} 1562#endif /* NO_CONFIG_WRITE */ 1563 1564 1565#ifdef CONFIG_P2P 1566 1567static int wpa_config_parse_go_p2p_dev_addr(const struct parse_data *data, 1568 struct wpa_ssid *ssid, int line, 1569 const char *value) 1570{ 1571 if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 || 1572 os_strcmp(value, "any") == 0) { 1573 os_memset(ssid->go_p2p_dev_addr, 0, ETH_ALEN); 1574 wpa_printf(MSG_MSGDUMP, "GO P2P Device Address any"); 1575 return 0; 1576 } 1577 if (hwaddr_aton(value, ssid->go_p2p_dev_addr)) { 1578 wpa_printf(MSG_ERROR, "Line %d: Invalid GO P2P Device Address '%s'.", 1579 line, value); 1580 return -1; 1581 } 1582 ssid->bssid_set = 1; 1583 wpa_printf(MSG_MSGDUMP, "GO P2P Device Address " MACSTR, 1584 MAC2STR(ssid->go_p2p_dev_addr)); 1585 return 0; 1586} 1587 1588 1589#ifndef NO_CONFIG_WRITE 1590static char * wpa_config_write_go_p2p_dev_addr(const struct parse_data *data, 1591 struct wpa_ssid *ssid) 1592{ 1593 char *value; 1594 int res; 1595 1596 if (is_zero_ether_addr(ssid->go_p2p_dev_addr)) 1597 return NULL; 1598 1599 value = os_malloc(20); 1600 if (value == NULL) 1601 return NULL; 1602 res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->go_p2p_dev_addr)); 1603 if (os_snprintf_error(20, res)) { 1604 os_free(value); 1605 return NULL; 1606 } 1607 value[20 - 1] = '\0'; 1608 return value; 1609} 1610#endif /* NO_CONFIG_WRITE */ 1611 1612 1613static int wpa_config_parse_p2p_client_list(const struct parse_data *data, 1614 struct wpa_ssid *ssid, int line, 1615 const char *value) 1616{ 1617 return wpa_config_parse_addr_list(data, line, value, 1618 &ssid->p2p_client_list, 1619 &ssid->num_p2p_clients, 1620 "p2p_client_list", 0, 0); 1621} 1622 1623 1624#ifndef NO_CONFIG_WRITE 1625static char * wpa_config_write_p2p_client_list(const struct parse_data *data, 1626 struct wpa_ssid *ssid) 1627{ 1628 return wpa_config_write_addr_list(data, ssid->p2p_client_list, 1629 ssid->num_p2p_clients, 1630 "p2p_client_list"); 1631} 1632#endif /* NO_CONFIG_WRITE */ 1633 1634 1635static int wpa_config_parse_psk_list(const struct parse_data *data, 1636 struct wpa_ssid *ssid, int line, 1637 const char *value) 1638{ 1639 struct psk_list_entry *p; 1640 const char *pos; 1641 1642 p = os_zalloc(sizeof(*p)); 1643 if (p == NULL) 1644 return -1; 1645 1646 pos = value; 1647 if (os_strncmp(pos, "P2P-", 4) == 0) { 1648 p->p2p = 1; 1649 pos += 4; 1650 } 1651 1652 if (hwaddr_aton(pos, p->addr)) { 1653 wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list address '%s'", 1654 line, pos); 1655 os_free(p); 1656 return -1; 1657 } 1658 pos += 17; 1659 if (*pos != '-') { 1660 wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list '%s'", 1661 line, pos); 1662 os_free(p); 1663 return -1; 1664 } 1665 pos++; 1666 1667 if (hexstr2bin(pos, p->psk, PMK_LEN) || pos[PMK_LEN * 2] != '\0') { 1668 wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list PSK '%s'", 1669 line, pos); 1670 os_free(p); 1671 return -1; 1672 } 1673 1674 dl_list_add(&ssid->psk_list, &p->list); 1675 1676 return 0; 1677} 1678 1679 1680#ifndef NO_CONFIG_WRITE 1681static char * wpa_config_write_psk_list(const struct parse_data *data, 1682 struct wpa_ssid *ssid) 1683{ 1684 return NULL; 1685} 1686#endif /* NO_CONFIG_WRITE */ 1687 1688#endif /* CONFIG_P2P */ 1689 1690 1691#ifdef CONFIG_MESH 1692 1693static int wpa_config_parse_mesh_basic_rates(const struct parse_data *data, 1694 struct wpa_ssid *ssid, int line, 1695 const char *value) 1696{ 1697 int *rates = wpa_config_parse_int_array(value); 1698 1699 if (rates == NULL) { 1700 wpa_printf(MSG_ERROR, "Line %d: Invalid mesh_basic_rates '%s'", 1701 line, value); 1702 return -1; 1703 } 1704 if (rates[0] == 0) { 1705 os_free(rates); 1706 rates = NULL; 1707 } 1708 1709 os_free(ssid->mesh_basic_rates); 1710 ssid->mesh_basic_rates = rates; 1711 1712 return 0; 1713} 1714 1715 1716#ifndef NO_CONFIG_WRITE 1717 1718static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data, 1719 struct wpa_ssid *ssid) 1720{ 1721 return wpa_config_write_freqs(data, ssid->mesh_basic_rates); 1722} 1723 1724#endif /* NO_CONFIG_WRITE */ 1725 1726#endif /* CONFIG_MESH */ 1727 1728 1729/* Helper macros for network block parser */ 1730 1731#ifdef OFFSET 1732#undef OFFSET 1733#endif /* OFFSET */ 1734/* OFFSET: Get offset of a variable within the wpa_ssid structure */ 1735#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v) 1736 1737/* STR: Define a string variable for an ASCII string; f = field name */ 1738#ifdef NO_CONFIG_WRITE 1739#define _STR(f) #f, wpa_config_parse_str, OFFSET(f) 1740#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f) 1741#else /* NO_CONFIG_WRITE */ 1742#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f) 1743#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f) 1744#endif /* NO_CONFIG_WRITE */ 1745#define STR(f) _STR(f), NULL, NULL, NULL, 0 1746#define STRe(f) _STRe(f), NULL, NULL, NULL, 0 1747#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1 1748#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1 1749 1750/* STR_LEN: Define a string variable with a separate variable for storing the 1751 * data length. Unlike STR(), this can be used to store arbitrary binary data 1752 * (i.e., even nul termination character). */ 1753#define _STR_LEN(f) _STR(f), OFFSET(f ## _len) 1754#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len) 1755#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0 1756#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0 1757#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1 1758 1759/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length 1760 * explicitly specified. */ 1761#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max) 1762#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0 1763#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1 1764 1765#ifdef NO_CONFIG_WRITE 1766#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0 1767#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0 1768#else /* NO_CONFIG_WRITE */ 1769#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 1770 OFFSET(f), (void *) 0 1771#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 1772 OFFSET(eap.f), (void *) 0 1773#endif /* NO_CONFIG_WRITE */ 1774 1775/* INT: Define an integer variable */ 1776#define INT(f) _INT(f), NULL, NULL, 0 1777#define INTe(f) _INTe(f), NULL, NULL, 0 1778 1779/* INT_RANGE: Define an integer variable with allowed value range */ 1780#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0 1781 1782/* FUNC: Define a configuration variable that uses a custom function for 1783 * parsing and writing the value. */ 1784#ifdef NO_CONFIG_WRITE 1785#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL 1786#else /* NO_CONFIG_WRITE */ 1787#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \ 1788 NULL, NULL, NULL, NULL 1789#endif /* NO_CONFIG_WRITE */ 1790#define FUNC(f) _FUNC(f), 0 1791#define FUNC_KEY(f) _FUNC(f), 1 1792 1793/* 1794 * Table of network configuration variables. This table is used to parse each 1795 * network configuration variable, e.g., each line in wpa_supplicant.conf file 1796 * that is inside a network block. 1797 * 1798 * This table is generated using the helper macros defined above and with 1799 * generous help from the C pre-processor. The field name is stored as a string 1800 * into .name and for STR and INT types, the offset of the target buffer within 1801 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar 1802 * offset to the field containing the length of the configuration variable. 1803 * .param3 and .param4 can be used to mark the allowed range (length for STR 1804 * and value for INT). 1805 * 1806 * For each configuration line in wpa_supplicant.conf, the parser goes through 1807 * this table and select the entry that matches with the field name. The parser 1808 * function (.parser) is then called to parse the actual value of the field. 1809 * 1810 * This kind of mechanism makes it easy to add new configuration parameters, 1811 * since only one line needs to be added into this table and into the 1812 * struct wpa_ssid definition if the new variable is either a string or 1813 * integer. More complex types will need to use their own parser and writer 1814 * functions. 1815 */ 1816static const struct parse_data ssid_fields[] = { 1817 { STR_RANGE(ssid, 0, SSID_MAX_LEN) }, 1818 { INT_RANGE(scan_ssid, 0, 1) }, 1819 { FUNC(bssid) }, 1820 { FUNC(bssid_blacklist) }, 1821 { FUNC(bssid_whitelist) }, 1822 { FUNC_KEY(psk) }, 1823 { INT(mem_only_psk) }, 1824 { FUNC(proto) }, 1825 { FUNC(key_mgmt) }, 1826 { INT(bg_scan_period) }, 1827 { FUNC(pairwise) }, 1828 { FUNC(group) }, 1829 { FUNC(auth_alg) }, 1830 { FUNC(scan_freq) }, 1831 { FUNC(freq_list) }, 1832#ifdef IEEE8021X_EAPOL 1833 { FUNC(eap) }, 1834 { STR_LENe(identity) }, 1835 { STR_LENe(anonymous_identity) }, 1836 { FUNC_KEY(password) }, 1837 { STRe(ca_cert) }, 1838 { STRe(ca_path) }, 1839 { STRe(client_cert) }, 1840 { STRe(private_key) }, 1841 { STR_KEYe(private_key_passwd) }, 1842 { STRe(dh_file) }, 1843 { STRe(subject_match) }, 1844 { STRe(altsubject_match) }, 1845 { STRe(domain_suffix_match) }, 1846 { STRe(domain_match) }, 1847 { STRe(ca_cert2) }, 1848 { STRe(ca_path2) }, 1849 { STRe(client_cert2) }, 1850 { STRe(private_key2) }, 1851 { STR_KEYe(private_key2_passwd) }, 1852 { STRe(dh_file2) }, 1853 { STRe(subject_match2) }, 1854 { STRe(altsubject_match2) }, 1855 { STRe(domain_suffix_match2) }, 1856 { STRe(domain_match2) }, 1857 { STRe(phase1) }, 1858 { STRe(phase2) }, 1859 { STRe(pcsc) }, 1860 { STR_KEYe(pin) }, 1861 { STRe(engine_id) }, 1862 { STRe(key_id) }, 1863 { STRe(cert_id) }, 1864 { STRe(ca_cert_id) }, 1865 { STR_KEYe(pin2) }, 1866 { STRe(engine2_id) }, 1867 { STRe(key2_id) }, 1868 { STRe(cert2_id) }, 1869 { STRe(ca_cert2_id) }, 1870 { INTe(engine) }, 1871 { INTe(engine2) }, 1872 { INT(eapol_flags) }, 1873 { INTe(sim_num) }, 1874 { STRe(openssl_ciphers) }, 1875 { INTe(erp) }, 1876#endif /* IEEE8021X_EAPOL */ 1877 { FUNC_KEY(wep_key0) }, 1878 { FUNC_KEY(wep_key1) }, 1879 { FUNC_KEY(wep_key2) }, 1880 { FUNC_KEY(wep_key3) }, 1881 { INT(wep_tx_keyidx) }, 1882 { INT(priority) }, 1883#ifdef IEEE8021X_EAPOL 1884 { INT(eap_workaround) }, 1885 { STRe(pac_file) }, 1886 { INTe(fragment_size) }, 1887 { INTe(ocsp) }, 1888#endif /* IEEE8021X_EAPOL */ 1889#ifdef CONFIG_MESH 1890 { INT_RANGE(mode, 0, 5) }, 1891 { INT_RANGE(no_auto_peer, 0, 1) }, 1892#else /* CONFIG_MESH */ 1893 { INT_RANGE(mode, 0, 4) }, 1894#endif /* CONFIG_MESH */ 1895 { INT_RANGE(proactive_key_caching, 0, 1) }, 1896 { INT_RANGE(disabled, 0, 2) }, 1897 { STR(id_str) }, 1898#ifdef CONFIG_IEEE80211W 1899 { INT_RANGE(ieee80211w, 0, 2) }, 1900#endif /* CONFIG_IEEE80211W */ 1901 { INT_RANGE(peerkey, 0, 1) }, 1902 { INT_RANGE(mixed_cell, 0, 1) }, 1903 { INT_RANGE(frequency, 0, 65000) }, 1904 { INT_RANGE(fixed_freq, 0, 1) }, 1905#ifdef CONFIG_MESH 1906 { FUNC(mesh_basic_rates) }, 1907 { INT(dot11MeshMaxRetries) }, 1908 { INT(dot11MeshRetryTimeout) }, 1909 { INT(dot11MeshConfirmTimeout) }, 1910 { INT(dot11MeshHoldingTimeout) }, 1911#endif /* CONFIG_MESH */ 1912 { INT(wpa_ptk_rekey) }, 1913 { STR(bgscan) }, 1914 { INT_RANGE(ignore_broadcast_ssid, 0, 2) }, 1915#ifdef CONFIG_P2P 1916 { FUNC(go_p2p_dev_addr) }, 1917 { FUNC(p2p_client_list) }, 1918 { FUNC(psk_list) }, 1919#endif /* CONFIG_P2P */ 1920#ifdef CONFIG_HT_OVERRIDES 1921 { INT_RANGE(disable_ht, 0, 1) }, 1922 { INT_RANGE(disable_ht40, -1, 1) }, 1923 { INT_RANGE(disable_sgi, 0, 1) }, 1924 { INT_RANGE(disable_ldpc, 0, 1) }, 1925 { INT_RANGE(ht40_intolerant, 0, 1) }, 1926 { INT_RANGE(disable_max_amsdu, -1, 1) }, 1927 { INT_RANGE(ampdu_factor, -1, 3) }, 1928 { INT_RANGE(ampdu_density, -1, 7) }, 1929 { STR(ht_mcs) }, 1930#endif /* CONFIG_HT_OVERRIDES */ 1931#ifdef CONFIG_VHT_OVERRIDES 1932 { INT_RANGE(disable_vht, 0, 1) }, 1933 { INT(vht_capa) }, 1934 { INT(vht_capa_mask) }, 1935 { INT_RANGE(vht_rx_mcs_nss_1, -1, 3) }, 1936 { INT_RANGE(vht_rx_mcs_nss_2, -1, 3) }, 1937 { INT_RANGE(vht_rx_mcs_nss_3, -1, 3) }, 1938 { INT_RANGE(vht_rx_mcs_nss_4, -1, 3) }, 1939 { INT_RANGE(vht_rx_mcs_nss_5, -1, 3) }, 1940 { INT_RANGE(vht_rx_mcs_nss_6, -1, 3) }, 1941 { INT_RANGE(vht_rx_mcs_nss_7, -1, 3) }, 1942 { INT_RANGE(vht_rx_mcs_nss_8, -1, 3) }, 1943 { INT_RANGE(vht_tx_mcs_nss_1, -1, 3) }, 1944 { INT_RANGE(vht_tx_mcs_nss_2, -1, 3) }, 1945 { INT_RANGE(vht_tx_mcs_nss_3, -1, 3) }, 1946 { INT_RANGE(vht_tx_mcs_nss_4, -1, 3) }, 1947 { INT_RANGE(vht_tx_mcs_nss_5, -1, 3) }, 1948 { INT_RANGE(vht_tx_mcs_nss_6, -1, 3) }, 1949 { INT_RANGE(vht_tx_mcs_nss_7, -1, 3) }, 1950 { INT_RANGE(vht_tx_mcs_nss_8, -1, 3) }, 1951#endif /* CONFIG_VHT_OVERRIDES */ 1952 { INT(ap_max_inactivity) }, 1953 { INT(dtim_period) }, 1954 { INT(beacon_int) }, 1955#ifdef CONFIG_MACSEC 1956 { INT_RANGE(macsec_policy, 0, 1) }, 1957#endif /* CONFIG_MACSEC */ 1958#ifdef CONFIG_HS20 1959 { INT(update_identifier) }, 1960#endif /* CONFIG_HS20 */ 1961 { INT_RANGE(mac_addr, 0, 2) }, 1962}; 1963 1964#undef OFFSET 1965#undef _STR 1966#undef STR 1967#undef STR_KEY 1968#undef _STR_LEN 1969#undef STR_LEN 1970#undef STR_LEN_KEY 1971#undef _STR_RANGE 1972#undef STR_RANGE 1973#undef STR_RANGE_KEY 1974#undef _INT 1975#undef INT 1976#undef INT_RANGE 1977#undef _FUNC 1978#undef FUNC 1979#undef FUNC_KEY 1980#define NUM_SSID_FIELDS ARRAY_SIZE(ssid_fields) 1981 1982 1983/** 1984 * wpa_config_add_prio_network - Add a network to priority lists 1985 * @config: Configuration data from wpa_config_read() 1986 * @ssid: Pointer to the network configuration to be added to the list 1987 * Returns: 0 on success, -1 on failure 1988 * 1989 * This function is used to add a network block to the priority list of 1990 * networks. This must be called for each network when reading in the full 1991 * configuration. In addition, this can be used indirectly when updating 1992 * priorities by calling wpa_config_update_prio_list(). 1993 */ 1994int wpa_config_add_prio_network(struct wpa_config *config, 1995 struct wpa_ssid *ssid) 1996{ 1997 int prio; 1998 struct wpa_ssid *prev, **nlist; 1999 2000 /* 2001 * Add to an existing priority list if one is available for the 2002 * configured priority level for this network. 2003 */ 2004 for (prio = 0; prio < config->num_prio; prio++) { 2005 prev = config->pssid[prio]; 2006 if (prev->priority == ssid->priority) { 2007 while (prev->pnext) 2008 prev = prev->pnext; 2009 prev->pnext = ssid; 2010 return 0; 2011 } 2012 } 2013 2014 /* First network for this priority - add a new priority list */ 2015 nlist = os_realloc_array(config->pssid, config->num_prio + 1, 2016 sizeof(struct wpa_ssid *)); 2017 if (nlist == NULL) 2018 return -1; 2019 2020 for (prio = 0; prio < config->num_prio; prio++) { 2021 if (nlist[prio]->priority < ssid->priority) { 2022 os_memmove(&nlist[prio + 1], &nlist[prio], 2023 (config->num_prio - prio) * 2024 sizeof(struct wpa_ssid *)); 2025 break; 2026 } 2027 } 2028 2029 nlist[prio] = ssid; 2030 config->num_prio++; 2031 config->pssid = nlist; 2032 2033 return 0; 2034} 2035 2036 2037/** 2038 * wpa_config_update_prio_list - Update network priority list 2039 * @config: Configuration data from wpa_config_read() 2040 * Returns: 0 on success, -1 on failure 2041 * 2042 * This function is called to update the priority list of networks in the 2043 * configuration when a network is being added or removed. This is also called 2044 * if a priority for a network is changed. 2045 */ 2046int wpa_config_update_prio_list(struct wpa_config *config) 2047{ 2048 struct wpa_ssid *ssid; 2049 int ret = 0; 2050 2051 os_free(config->pssid); 2052 config->pssid = NULL; 2053 config->num_prio = 0; 2054 2055 ssid = config->ssid; 2056 while (ssid) { 2057 ssid->pnext = NULL; 2058 if (wpa_config_add_prio_network(config, ssid) < 0) 2059 ret = -1; 2060 ssid = ssid->next; 2061 } 2062 2063 return ret; 2064} 2065 2066 2067#ifdef IEEE8021X_EAPOL 2068static void eap_peer_config_free(struct eap_peer_config *eap) 2069{ 2070 os_free(eap->eap_methods); 2071 bin_clear_free(eap->identity, eap->identity_len); 2072 os_free(eap->anonymous_identity); 2073 bin_clear_free(eap->password, eap->password_len); 2074 os_free(eap->ca_cert); 2075 os_free(eap->ca_path); 2076 os_free(eap->client_cert); 2077 os_free(eap->private_key); 2078 str_clear_free(eap->private_key_passwd); 2079 os_free(eap->dh_file); 2080 os_free(eap->subject_match); 2081 os_free(eap->altsubject_match); 2082 os_free(eap->domain_suffix_match); 2083 os_free(eap->domain_match); 2084 os_free(eap->ca_cert2); 2085 os_free(eap->ca_path2); 2086 os_free(eap->client_cert2); 2087 os_free(eap->private_key2); 2088 str_clear_free(eap->private_key2_passwd); 2089 os_free(eap->dh_file2); 2090 os_free(eap->subject_match2); 2091 os_free(eap->altsubject_match2); 2092 os_free(eap->domain_suffix_match2); 2093 os_free(eap->domain_match2); 2094 os_free(eap->phase1); 2095 os_free(eap->phase2); 2096 os_free(eap->pcsc); 2097 str_clear_free(eap->pin); 2098 os_free(eap->engine_id); 2099 os_free(eap->key_id); 2100 os_free(eap->cert_id); 2101 os_free(eap->ca_cert_id); 2102 os_free(eap->key2_id); 2103 os_free(eap->cert2_id); 2104 os_free(eap->ca_cert2_id); 2105 str_clear_free(eap->pin2); 2106 os_free(eap->engine2_id); 2107 os_free(eap->otp); 2108 os_free(eap->pending_req_otp); 2109 os_free(eap->pac_file); 2110 bin_clear_free(eap->new_password, eap->new_password_len); 2111 str_clear_free(eap->external_sim_resp); 2112 os_free(eap->openssl_ciphers); 2113} 2114#endif /* IEEE8021X_EAPOL */ 2115 2116 2117/** 2118 * wpa_config_free_ssid - Free network/ssid configuration data 2119 * @ssid: Configuration data for the network 2120 * 2121 * This function frees all resources allocated for the network configuration 2122 * data. 2123 */ 2124void wpa_config_free_ssid(struct wpa_ssid *ssid) 2125{ 2126 struct psk_list_entry *psk; 2127 2128 os_free(ssid->ssid); 2129 str_clear_free(ssid->passphrase); 2130 os_free(ssid->ext_psk); 2131#ifdef IEEE8021X_EAPOL 2132 eap_peer_config_free(&ssid->eap); 2133#endif /* IEEE8021X_EAPOL */ 2134 os_free(ssid->id_str); 2135 os_free(ssid->scan_freq); 2136 os_free(ssid->freq_list); 2137 os_free(ssid->bgscan); 2138 os_free(ssid->p2p_client_list); 2139 os_free(ssid->bssid_blacklist); 2140 os_free(ssid->bssid_whitelist); 2141#ifdef CONFIG_HT_OVERRIDES 2142 os_free(ssid->ht_mcs); 2143#endif /* CONFIG_HT_OVERRIDES */ 2144#ifdef CONFIG_MESH 2145 os_free(ssid->mesh_basic_rates); 2146#endif /* CONFIG_MESH */ 2147 while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry, 2148 list))) { 2149 dl_list_del(&psk->list); 2150 bin_clear_free(psk, sizeof(*psk)); 2151 } 2152 bin_clear_free(ssid, sizeof(*ssid)); 2153} 2154 2155 2156void wpa_config_free_cred(struct wpa_cred *cred) 2157{ 2158 size_t i; 2159 2160 os_free(cred->realm); 2161 str_clear_free(cred->username); 2162 str_clear_free(cred->password); 2163 os_free(cred->ca_cert); 2164 os_free(cred->client_cert); 2165 os_free(cred->private_key); 2166 str_clear_free(cred->private_key_passwd); 2167 os_free(cred->imsi); 2168 str_clear_free(cred->milenage); 2169 for (i = 0; i < cred->num_domain; i++) 2170 os_free(cred->domain[i]); 2171 os_free(cred->domain); 2172 os_free(cred->domain_suffix_match); 2173 os_free(cred->eap_method); 2174 os_free(cred->phase1); 2175 os_free(cred->phase2); 2176 os_free(cred->excluded_ssid); 2177 os_free(cred->roaming_partner); 2178 os_free(cred->provisioning_sp); 2179 for (i = 0; i < cred->num_req_conn_capab; i++) 2180 os_free(cred->req_conn_capab_port[i]); 2181 os_free(cred->req_conn_capab_port); 2182 os_free(cred->req_conn_capab_proto); 2183 os_free(cred); 2184} 2185 2186 2187void wpa_config_flush_blobs(struct wpa_config *config) 2188{ 2189#ifndef CONFIG_NO_CONFIG_BLOBS 2190 struct wpa_config_blob *blob, *prev; 2191 2192 blob = config->blobs; 2193 config->blobs = NULL; 2194 while (blob) { 2195 prev = blob; 2196 blob = blob->next; 2197 wpa_config_free_blob(prev); 2198 } 2199#endif /* CONFIG_NO_CONFIG_BLOBS */ 2200} 2201 2202 2203/** 2204 * wpa_config_free - Free configuration data 2205 * @config: Configuration data from wpa_config_read() 2206 * 2207 * This function frees all resources allocated for the configuration data by 2208 * wpa_config_read(). 2209 */ 2210void wpa_config_free(struct wpa_config *config) 2211{ 2212 struct wpa_ssid *ssid, *prev = NULL; 2213 struct wpa_cred *cred, *cprev; 2214 int i; 2215 2216 ssid = config->ssid; 2217 while (ssid) { 2218 prev = ssid; 2219 ssid = ssid->next; 2220 wpa_config_free_ssid(prev); 2221 } 2222 2223 cred = config->cred; 2224 while (cred) { 2225 cprev = cred; 2226 cred = cred->next; 2227 wpa_config_free_cred(cprev); 2228 } 2229 2230 wpa_config_flush_blobs(config); 2231 2232 wpabuf_free(config->wps_vendor_ext_m1); 2233 for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) 2234 wpabuf_free(config->wps_vendor_ext[i]); 2235 os_free(config->ctrl_interface); 2236 os_free(config->ctrl_interface_group); 2237 os_free(config->opensc_engine_path); 2238 os_free(config->pkcs11_engine_path); 2239 os_free(config->pkcs11_module_path); 2240 os_free(config->openssl_ciphers); 2241 os_free(config->pcsc_reader); 2242 str_clear_free(config->pcsc_pin); 2243 os_free(config->driver_param); 2244 os_free(config->device_name); 2245 os_free(config->manufacturer); 2246 os_free(config->model_name); 2247 os_free(config->model_number); 2248 os_free(config->serial_number); 2249 os_free(config->config_methods); 2250 os_free(config->p2p_ssid_postfix); 2251 os_free(config->pssid); 2252 os_free(config->p2p_pref_chan); 2253 os_free(config->p2p_no_go_freq.range); 2254 os_free(config->autoscan); 2255 os_free(config->freq_list); 2256 wpabuf_free(config->wps_nfc_dh_pubkey); 2257 wpabuf_free(config->wps_nfc_dh_privkey); 2258 wpabuf_free(config->wps_nfc_dev_pw); 2259 os_free(config->ext_password_backend); 2260 os_free(config->sae_groups); 2261 wpabuf_free(config->ap_vendor_elements); 2262 os_free(config->osu_dir); 2263 os_free(config->bgscan); 2264 os_free(config->wowlan_triggers); 2265 os_free(config); 2266} 2267 2268 2269/** 2270 * wpa_config_foreach_network - Iterate over each configured network 2271 * @config: Configuration data from wpa_config_read() 2272 * @func: Callback function to process each network 2273 * @arg: Opaque argument to pass to callback function 2274 * 2275 * Iterate over the set of configured networks calling the specified 2276 * function for each item. We guard against callbacks removing the 2277 * supplied network. 2278 */ 2279void wpa_config_foreach_network(struct wpa_config *config, 2280 void (*func)(void *, struct wpa_ssid *), 2281 void *arg) 2282{ 2283 struct wpa_ssid *ssid, *next; 2284 2285 ssid = config->ssid; 2286 while (ssid) { 2287 next = ssid->next; 2288 func(arg, ssid); 2289 ssid = next; 2290 } 2291} 2292 2293 2294/** 2295 * wpa_config_get_network - Get configured network based on id 2296 * @config: Configuration data from wpa_config_read() 2297 * @id: Unique network id to search for 2298 * Returns: Network configuration or %NULL if not found 2299 */ 2300struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id) 2301{ 2302 struct wpa_ssid *ssid; 2303 2304 ssid = config->ssid; 2305 while (ssid) { 2306 if (id == ssid->id) 2307 break; 2308 ssid = ssid->next; 2309 } 2310 2311 return ssid; 2312} 2313 2314 2315/** 2316 * wpa_config_add_network - Add a new network with empty configuration 2317 * @config: Configuration data from wpa_config_read() 2318 * Returns: The new network configuration or %NULL if operation failed 2319 */ 2320struct wpa_ssid * wpa_config_add_network(struct wpa_config *config) 2321{ 2322 int id; 2323 struct wpa_ssid *ssid, *last = NULL; 2324 2325 id = -1; 2326 ssid = config->ssid; 2327 while (ssid) { 2328 if (ssid->id > id) 2329 id = ssid->id; 2330 last = ssid; 2331 ssid = ssid->next; 2332 } 2333 id++; 2334 2335 ssid = os_zalloc(sizeof(*ssid)); 2336 if (ssid == NULL) 2337 return NULL; 2338 ssid->id = id; 2339 dl_list_init(&ssid->psk_list); 2340 if (last) 2341 last->next = ssid; 2342 else 2343 config->ssid = ssid; 2344 2345 wpa_config_update_prio_list(config); 2346 2347 return ssid; 2348} 2349 2350 2351/** 2352 * wpa_config_remove_network - Remove a configured network based on id 2353 * @config: Configuration data from wpa_config_read() 2354 * @id: Unique network id to search for 2355 * Returns: 0 on success, or -1 if the network was not found 2356 */ 2357int wpa_config_remove_network(struct wpa_config *config, int id) 2358{ 2359 struct wpa_ssid *ssid, *prev = NULL; 2360 2361 ssid = config->ssid; 2362 while (ssid) { 2363 if (id == ssid->id) 2364 break; 2365 prev = ssid; 2366 ssid = ssid->next; 2367 } 2368 2369 if (ssid == NULL) 2370 return -1; 2371 2372 if (prev) 2373 prev->next = ssid->next; 2374 else 2375 config->ssid = ssid->next; 2376 2377 wpa_config_update_prio_list(config); 2378 wpa_config_free_ssid(ssid); 2379 return 0; 2380} 2381 2382 2383/** 2384 * wpa_config_set_network_defaults - Set network default values 2385 * @ssid: Pointer to network configuration data 2386 */ 2387void wpa_config_set_network_defaults(struct wpa_ssid *ssid) 2388{ 2389 ssid->proto = DEFAULT_PROTO; 2390 ssid->pairwise_cipher = DEFAULT_PAIRWISE; 2391 ssid->group_cipher = DEFAULT_GROUP; 2392 ssid->key_mgmt = DEFAULT_KEY_MGMT; 2393 ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD; 2394#ifdef IEEE8021X_EAPOL 2395 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; 2396 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; 2397 ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE; 2398 ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM; 2399#endif /* IEEE8021X_EAPOL */ 2400#ifdef CONFIG_MESH 2401 ssid->dot11MeshMaxRetries = DEFAULT_MESH_MAX_RETRIES; 2402 ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT; 2403 ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT; 2404 ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT; 2405#endif /* CONFIG_MESH */ 2406#ifdef CONFIG_HT_OVERRIDES 2407 ssid->disable_ht = DEFAULT_DISABLE_HT; 2408 ssid->disable_ht40 = DEFAULT_DISABLE_HT40; 2409 ssid->disable_sgi = DEFAULT_DISABLE_SGI; 2410 ssid->disable_ldpc = DEFAULT_DISABLE_LDPC; 2411 ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU; 2412 ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR; 2413 ssid->ampdu_density = DEFAULT_AMPDU_DENSITY; 2414#endif /* CONFIG_HT_OVERRIDES */ 2415#ifdef CONFIG_VHT_OVERRIDES 2416 ssid->vht_rx_mcs_nss_1 = -1; 2417 ssid->vht_rx_mcs_nss_2 = -1; 2418 ssid->vht_rx_mcs_nss_3 = -1; 2419 ssid->vht_rx_mcs_nss_4 = -1; 2420 ssid->vht_rx_mcs_nss_5 = -1; 2421 ssid->vht_rx_mcs_nss_6 = -1; 2422 ssid->vht_rx_mcs_nss_7 = -1; 2423 ssid->vht_rx_mcs_nss_8 = -1; 2424 ssid->vht_tx_mcs_nss_1 = -1; 2425 ssid->vht_tx_mcs_nss_2 = -1; 2426 ssid->vht_tx_mcs_nss_3 = -1; 2427 ssid->vht_tx_mcs_nss_4 = -1; 2428 ssid->vht_tx_mcs_nss_5 = -1; 2429 ssid->vht_tx_mcs_nss_6 = -1; 2430 ssid->vht_tx_mcs_nss_7 = -1; 2431 ssid->vht_tx_mcs_nss_8 = -1; 2432#endif /* CONFIG_VHT_OVERRIDES */ 2433 ssid->proactive_key_caching = -1; 2434#ifdef CONFIG_IEEE80211W 2435 ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT; 2436#endif /* CONFIG_IEEE80211W */ 2437 ssid->mac_addr = -1; 2438} 2439 2440 2441/** 2442 * wpa_config_set - Set a variable in network configuration 2443 * @ssid: Pointer to network configuration data 2444 * @var: Variable name, e.g., "ssid" 2445 * @value: Variable value 2446 * @line: Line number in configuration file or 0 if not used 2447 * Returns: 0 on success, -1 on failure 2448 * 2449 * This function can be used to set network configuration variables based on 2450 * both the configuration file and management interface input. The value 2451 * parameter must be in the same format as the text-based configuration file is 2452 * using. For example, strings are using double quotation marks. 2453 */ 2454int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, 2455 int line) 2456{ 2457 size_t i; 2458 int ret = 0; 2459 2460 if (ssid == NULL || var == NULL || value == NULL) 2461 return -1; 2462 2463 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2464 const struct parse_data *field = &ssid_fields[i]; 2465 if (os_strcmp(var, field->name) != 0) 2466 continue; 2467 2468 if (field->parser(field, ssid, line, value)) { 2469 if (line) { 2470 wpa_printf(MSG_ERROR, "Line %d: failed to " 2471 "parse %s '%s'.", line, var, value); 2472 } 2473 ret = -1; 2474 } 2475 break; 2476 } 2477 if (i == NUM_SSID_FIELDS) { 2478 if (line) { 2479 wpa_printf(MSG_ERROR, "Line %d: unknown network field " 2480 "'%s'.", line, var); 2481 } 2482 ret = -1; 2483 } 2484 2485 return ret; 2486} 2487 2488 2489int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var, 2490 const char *value) 2491{ 2492 size_t len; 2493 char *buf; 2494 int ret; 2495 2496 len = os_strlen(value); 2497 buf = os_malloc(len + 3); 2498 if (buf == NULL) 2499 return -1; 2500 buf[0] = '"'; 2501 os_memcpy(buf + 1, value, len); 2502 buf[len + 1] = '"'; 2503 buf[len + 2] = '\0'; 2504 ret = wpa_config_set(ssid, var, buf, 0); 2505 os_free(buf); 2506 return ret; 2507} 2508 2509 2510/** 2511 * wpa_config_get_all - Get all options from network configuration 2512 * @ssid: Pointer to network configuration data 2513 * @get_keys: Determines if keys/passwords will be included in returned list 2514 * (if they may be exported) 2515 * Returns: %NULL terminated list of all set keys and their values in the form 2516 * of [key1, val1, key2, val2, ... , NULL] 2517 * 2518 * This function can be used to get list of all configured network properties. 2519 * The caller is responsible for freeing the returned list and all its 2520 * elements. 2521 */ 2522char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys) 2523{ 2524#ifdef NO_CONFIG_WRITE 2525 return NULL; 2526#else /* NO_CONFIG_WRITE */ 2527 const struct parse_data *field; 2528 char *key, *value; 2529 size_t i; 2530 char **props; 2531 int fields_num; 2532 2533 get_keys = get_keys && ssid->export_keys; 2534 2535 props = os_calloc(2 * NUM_SSID_FIELDS + 1, sizeof(char *)); 2536 if (!props) 2537 return NULL; 2538 2539 fields_num = 0; 2540 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2541 field = &ssid_fields[i]; 2542 if (field->key_data && !get_keys) 2543 continue; 2544 value = field->writer(field, ssid); 2545 if (value == NULL) 2546 continue; 2547 if (os_strlen(value) == 0) { 2548 os_free(value); 2549 continue; 2550 } 2551 2552 key = os_strdup(field->name); 2553 if (key == NULL) { 2554 os_free(value); 2555 goto err; 2556 } 2557 2558 props[fields_num * 2] = key; 2559 props[fields_num * 2 + 1] = value; 2560 2561 fields_num++; 2562 } 2563 2564 return props; 2565 2566err: 2567 value = *props; 2568 while (value) 2569 os_free(value++); 2570 os_free(props); 2571 return NULL; 2572#endif /* NO_CONFIG_WRITE */ 2573} 2574 2575 2576#ifndef NO_CONFIG_WRITE 2577/** 2578 * wpa_config_get - Get a variable in network configuration 2579 * @ssid: Pointer to network configuration data 2580 * @var: Variable name, e.g., "ssid" 2581 * Returns: Value of the variable or %NULL on failure 2582 * 2583 * This function can be used to get network configuration variables. The 2584 * returned value is a copy of the configuration variable in text format, i.e,. 2585 * the same format that the text-based configuration file and wpa_config_set() 2586 * are using for the value. The caller is responsible for freeing the returned 2587 * value. 2588 */ 2589char * wpa_config_get(struct wpa_ssid *ssid, const char *var) 2590{ 2591 size_t i; 2592 2593 if (ssid == NULL || var == NULL) 2594 return NULL; 2595 2596 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2597 const struct parse_data *field = &ssid_fields[i]; 2598 if (os_strcmp(var, field->name) == 0) 2599 return field->writer(field, ssid); 2600 } 2601 2602 return NULL; 2603} 2604 2605 2606/** 2607 * wpa_config_get_no_key - Get a variable in network configuration (no keys) 2608 * @ssid: Pointer to network configuration data 2609 * @var: Variable name, e.g., "ssid" 2610 * Returns: Value of the variable or %NULL on failure 2611 * 2612 * This function can be used to get network configuration variable like 2613 * wpa_config_get(). The only difference is that this functions does not expose 2614 * key/password material from the configuration. In case a key/password field 2615 * is requested, the returned value is an empty string or %NULL if the variable 2616 * is not set or "*" if the variable is set (regardless of its value). The 2617 * returned value is a copy of the configuration variable in text format, i.e,. 2618 * the same format that the text-based configuration file and wpa_config_set() 2619 * are using for the value. The caller is responsible for freeing the returned 2620 * value. 2621 */ 2622char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var) 2623{ 2624 size_t i; 2625 2626 if (ssid == NULL || var == NULL) 2627 return NULL; 2628 2629 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2630 const struct parse_data *field = &ssid_fields[i]; 2631 if (os_strcmp(var, field->name) == 0) { 2632 char *res = field->writer(field, ssid); 2633 if (field->key_data) { 2634 if (res && res[0]) { 2635 wpa_printf(MSG_DEBUG, "Do not allow " 2636 "key_data field to be " 2637 "exposed"); 2638 str_clear_free(res); 2639 return os_strdup("*"); 2640 } 2641 2642 os_free(res); 2643 return NULL; 2644 } 2645 return res; 2646 } 2647 } 2648 2649 return NULL; 2650} 2651#endif /* NO_CONFIG_WRITE */ 2652 2653 2654/** 2655 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID 2656 * @ssid: Pointer to network configuration data 2657 * 2658 * This function must be called to update WPA PSK when either SSID or the 2659 * passphrase has changed for the network configuration. 2660 */ 2661void wpa_config_update_psk(struct wpa_ssid *ssid) 2662{ 2663#ifndef CONFIG_NO_PBKDF2 2664 pbkdf2_sha1(ssid->passphrase, ssid->ssid, ssid->ssid_len, 4096, 2665 ssid->psk, PMK_LEN); 2666 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", 2667 ssid->psk, PMK_LEN); 2668 ssid->psk_set = 1; 2669#endif /* CONFIG_NO_PBKDF2 */ 2670} 2671 2672 2673static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred, 2674 const char *value) 2675{ 2676 u8 *proto; 2677 int **port; 2678 int *ports, *nports; 2679 const char *pos; 2680 unsigned int num_ports; 2681 2682 proto = os_realloc_array(cred->req_conn_capab_proto, 2683 cred->num_req_conn_capab + 1, sizeof(u8)); 2684 if (proto == NULL) 2685 return -1; 2686 cred->req_conn_capab_proto = proto; 2687 2688 port = os_realloc_array(cred->req_conn_capab_port, 2689 cred->num_req_conn_capab + 1, sizeof(int *)); 2690 if (port == NULL) 2691 return -1; 2692 cred->req_conn_capab_port = port; 2693 2694 proto[cred->num_req_conn_capab] = atoi(value); 2695 2696 pos = os_strchr(value, ':'); 2697 if (pos == NULL) { 2698 port[cred->num_req_conn_capab] = NULL; 2699 cred->num_req_conn_capab++; 2700 return 0; 2701 } 2702 pos++; 2703 2704 ports = NULL; 2705 num_ports = 0; 2706 2707 while (*pos) { 2708 nports = os_realloc_array(ports, num_ports + 1, sizeof(int)); 2709 if (nports == NULL) { 2710 os_free(ports); 2711 return -1; 2712 } 2713 ports = nports; 2714 ports[num_ports++] = atoi(pos); 2715 2716 pos = os_strchr(pos, ','); 2717 if (pos == NULL) 2718 break; 2719 pos++; 2720 } 2721 2722 nports = os_realloc_array(ports, num_ports + 1, sizeof(int)); 2723 if (nports == NULL) { 2724 os_free(ports); 2725 return -1; 2726 } 2727 ports = nports; 2728 ports[num_ports] = -1; 2729 2730 port[cred->num_req_conn_capab] = ports; 2731 cred->num_req_conn_capab++; 2732 return 0; 2733} 2734 2735 2736int wpa_config_set_cred(struct wpa_cred *cred, const char *var, 2737 const char *value, int line) 2738{ 2739 char *val; 2740 size_t len; 2741 2742 if (os_strcmp(var, "temporary") == 0) { 2743 cred->temporary = atoi(value); 2744 return 0; 2745 } 2746 2747 if (os_strcmp(var, "priority") == 0) { 2748 cred->priority = atoi(value); 2749 return 0; 2750 } 2751 2752 if (os_strcmp(var, "sp_priority") == 0) { 2753 int prio = atoi(value); 2754 if (prio < 0 || prio > 255) 2755 return -1; 2756 cred->sp_priority = prio; 2757 return 0; 2758 } 2759 2760 if (os_strcmp(var, "pcsc") == 0) { 2761 cred->pcsc = atoi(value); 2762 return 0; 2763 } 2764 2765 if (os_strcmp(var, "eap") == 0) { 2766 struct eap_method_type method; 2767 method.method = eap_peer_get_type(value, &method.vendor); 2768 if (method.vendor == EAP_VENDOR_IETF && 2769 method.method == EAP_TYPE_NONE) { 2770 wpa_printf(MSG_ERROR, "Line %d: unknown EAP type '%s' " 2771 "for a credential", line, value); 2772 return -1; 2773 } 2774 os_free(cred->eap_method); 2775 cred->eap_method = os_malloc(sizeof(*cred->eap_method)); 2776 if (cred->eap_method == NULL) 2777 return -1; 2778 os_memcpy(cred->eap_method, &method, sizeof(method)); 2779 return 0; 2780 } 2781 2782 if (os_strcmp(var, "password") == 0 && 2783 os_strncmp(value, "ext:", 4) == 0) { 2784 str_clear_free(cred->password); 2785 cred->password = os_strdup(value); 2786 cred->ext_password = 1; 2787 return 0; 2788 } 2789 2790 if (os_strcmp(var, "update_identifier") == 0) { 2791 cred->update_identifier = atoi(value); 2792 return 0; 2793 } 2794 2795 if (os_strcmp(var, "min_dl_bandwidth_home") == 0) { 2796 cred->min_dl_bandwidth_home = atoi(value); 2797 return 0; 2798 } 2799 2800 if (os_strcmp(var, "min_ul_bandwidth_home") == 0) { 2801 cred->min_ul_bandwidth_home = atoi(value); 2802 return 0; 2803 } 2804 2805 if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0) { 2806 cred->min_dl_bandwidth_roaming = atoi(value); 2807 return 0; 2808 } 2809 2810 if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0) { 2811 cred->min_ul_bandwidth_roaming = atoi(value); 2812 return 0; 2813 } 2814 2815 if (os_strcmp(var, "max_bss_load") == 0) { 2816 cred->max_bss_load = atoi(value); 2817 return 0; 2818 } 2819 2820 if (os_strcmp(var, "req_conn_capab") == 0) 2821 return wpa_config_set_cred_req_conn_capab(cred, value); 2822 2823 if (os_strcmp(var, "ocsp") == 0) { 2824 cred->ocsp = atoi(value); 2825 return 0; 2826 } 2827 2828 if (os_strcmp(var, "sim_num") == 0) { 2829 cred->sim_num = atoi(value); 2830 return 0; 2831 } 2832 2833 val = wpa_config_parse_string(value, &len); 2834 if (val == NULL) { 2835 wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string " 2836 "value '%s'.", line, var, value); 2837 return -1; 2838 } 2839 2840 if (os_strcmp(var, "realm") == 0) { 2841 os_free(cred->realm); 2842 cred->realm = val; 2843 return 0; 2844 } 2845 2846 if (os_strcmp(var, "username") == 0) { 2847 str_clear_free(cred->username); 2848 cred->username = val; 2849 return 0; 2850 } 2851 2852 if (os_strcmp(var, "password") == 0) { 2853 str_clear_free(cred->password); 2854 cred->password = val; 2855 cred->ext_password = 0; 2856 return 0; 2857 } 2858 2859 if (os_strcmp(var, "ca_cert") == 0) { 2860 os_free(cred->ca_cert); 2861 cred->ca_cert = val; 2862 return 0; 2863 } 2864 2865 if (os_strcmp(var, "client_cert") == 0) { 2866 os_free(cred->client_cert); 2867 cred->client_cert = val; 2868 return 0; 2869 } 2870 2871 if (os_strcmp(var, "private_key") == 0) { 2872 os_free(cred->private_key); 2873 cred->private_key = val; 2874 return 0; 2875 } 2876 2877 if (os_strcmp(var, "private_key_passwd") == 0) { 2878 str_clear_free(cred->private_key_passwd); 2879 cred->private_key_passwd = val; 2880 return 0; 2881 } 2882 2883 if (os_strcmp(var, "imsi") == 0) { 2884 os_free(cred->imsi); 2885 cred->imsi = val; 2886 return 0; 2887 } 2888 2889 if (os_strcmp(var, "milenage") == 0) { 2890 str_clear_free(cred->milenage); 2891 cred->milenage = val; 2892 return 0; 2893 } 2894 2895 if (os_strcmp(var, "domain_suffix_match") == 0) { 2896 os_free(cred->domain_suffix_match); 2897 cred->domain_suffix_match = val; 2898 return 0; 2899 } 2900 2901 if (os_strcmp(var, "domain") == 0) { 2902 char **new_domain; 2903 new_domain = os_realloc_array(cred->domain, 2904 cred->num_domain + 1, 2905 sizeof(char *)); 2906 if (new_domain == NULL) { 2907 os_free(val); 2908 return -1; 2909 } 2910 new_domain[cred->num_domain++] = val; 2911 cred->domain = new_domain; 2912 return 0; 2913 } 2914 2915 if (os_strcmp(var, "phase1") == 0) { 2916 os_free(cred->phase1); 2917 cred->phase1 = val; 2918 return 0; 2919 } 2920 2921 if (os_strcmp(var, "phase2") == 0) { 2922 os_free(cred->phase2); 2923 cred->phase2 = val; 2924 return 0; 2925 } 2926 2927 if (os_strcmp(var, "roaming_consortium") == 0) { 2928 if (len < 3 || len > sizeof(cred->roaming_consortium)) { 2929 wpa_printf(MSG_ERROR, "Line %d: invalid " 2930 "roaming_consortium length %d (3..15 " 2931 "expected)", line, (int) len); 2932 os_free(val); 2933 return -1; 2934 } 2935 os_memcpy(cred->roaming_consortium, val, len); 2936 cred->roaming_consortium_len = len; 2937 os_free(val); 2938 return 0; 2939 } 2940 2941 if (os_strcmp(var, "required_roaming_consortium") == 0) { 2942 if (len < 3 || len > sizeof(cred->required_roaming_consortium)) 2943 { 2944 wpa_printf(MSG_ERROR, "Line %d: invalid " 2945 "required_roaming_consortium length %d " 2946 "(3..15 expected)", line, (int) len); 2947 os_free(val); 2948 return -1; 2949 } 2950 os_memcpy(cred->required_roaming_consortium, val, len); 2951 cred->required_roaming_consortium_len = len; 2952 os_free(val); 2953 return 0; 2954 } 2955 2956 if (os_strcmp(var, "excluded_ssid") == 0) { 2957 struct excluded_ssid *e; 2958 2959 if (len > SSID_MAX_LEN) { 2960 wpa_printf(MSG_ERROR, "Line %d: invalid " 2961 "excluded_ssid length %d", line, (int) len); 2962 os_free(val); 2963 return -1; 2964 } 2965 2966 e = os_realloc_array(cred->excluded_ssid, 2967 cred->num_excluded_ssid + 1, 2968 sizeof(struct excluded_ssid)); 2969 if (e == NULL) { 2970 os_free(val); 2971 return -1; 2972 } 2973 cred->excluded_ssid = e; 2974 2975 e = &cred->excluded_ssid[cred->num_excluded_ssid++]; 2976 os_memcpy(e->ssid, val, len); 2977 e->ssid_len = len; 2978 2979 os_free(val); 2980 2981 return 0; 2982 } 2983 2984 if (os_strcmp(var, "roaming_partner") == 0) { 2985 struct roaming_partner *p; 2986 char *pos; 2987 2988 p = os_realloc_array(cred->roaming_partner, 2989 cred->num_roaming_partner + 1, 2990 sizeof(struct roaming_partner)); 2991 if (p == NULL) { 2992 os_free(val); 2993 return -1; 2994 } 2995 cred->roaming_partner = p; 2996 2997 p = &cred->roaming_partner[cred->num_roaming_partner]; 2998 2999 pos = os_strchr(val, ','); 3000 if (pos == NULL) { 3001 os_free(val); 3002 return -1; 3003 } 3004 *pos++ = '\0'; 3005 if (pos - val - 1 >= (int) sizeof(p->fqdn)) { 3006 os_free(val); 3007 return -1; 3008 } 3009 os_memcpy(p->fqdn, val, pos - val); 3010 3011 p->exact_match = 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 p->priority = atoi(pos); 3021 3022 pos = os_strchr(pos, ','); 3023 if (pos == NULL) { 3024 os_free(val); 3025 return -1; 3026 } 3027 *pos++ = '\0'; 3028 3029 if (os_strlen(pos) >= sizeof(p->country)) { 3030 os_free(val); 3031 return -1; 3032 } 3033 os_memcpy(p->country, pos, os_strlen(pos) + 1); 3034 3035 cred->num_roaming_partner++; 3036 os_free(val); 3037 3038 return 0; 3039 } 3040 3041 if (os_strcmp(var, "provisioning_sp") == 0) { 3042 os_free(cred->provisioning_sp); 3043 cred->provisioning_sp = val; 3044 return 0; 3045 } 3046 3047 if (line) { 3048 wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.", 3049 line, var); 3050 } 3051 3052 os_free(val); 3053 3054 return -1; 3055} 3056 3057 3058static char * alloc_int_str(int val) 3059{ 3060 const unsigned int bufsize = 20; 3061 char *buf; 3062 int res; 3063 3064 buf = os_malloc(bufsize); 3065 if (buf == NULL) 3066 return NULL; 3067 res = os_snprintf(buf, bufsize, "%d", val); 3068 if (os_snprintf_error(bufsize, res)) { 3069 os_free(buf); 3070 buf = NULL; 3071 } 3072 return buf; 3073} 3074 3075 3076static char * alloc_strdup(const char *str) 3077{ 3078 if (str == NULL) 3079 return NULL; 3080 return os_strdup(str); 3081} 3082 3083 3084char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) 3085{ 3086 if (os_strcmp(var, "temporary") == 0) 3087 return alloc_int_str(cred->temporary); 3088 3089 if (os_strcmp(var, "priority") == 0) 3090 return alloc_int_str(cred->priority); 3091 3092 if (os_strcmp(var, "sp_priority") == 0) 3093 return alloc_int_str(cred->sp_priority); 3094 3095 if (os_strcmp(var, "pcsc") == 0) 3096 return alloc_int_str(cred->pcsc); 3097 3098 if (os_strcmp(var, "eap") == 0) { 3099 if (!cred->eap_method) 3100 return NULL; 3101 return alloc_strdup(eap_get_name(cred->eap_method[0].vendor, 3102 cred->eap_method[0].method)); 3103 } 3104 3105 if (os_strcmp(var, "update_identifier") == 0) 3106 return alloc_int_str(cred->update_identifier); 3107 3108 if (os_strcmp(var, "min_dl_bandwidth_home") == 0) 3109 return alloc_int_str(cred->min_dl_bandwidth_home); 3110 3111 if (os_strcmp(var, "min_ul_bandwidth_home") == 0) 3112 return alloc_int_str(cred->min_ul_bandwidth_home); 3113 3114 if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0) 3115 return alloc_int_str(cred->min_dl_bandwidth_roaming); 3116 3117 if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0) 3118 return alloc_int_str(cred->min_ul_bandwidth_roaming); 3119 3120 if (os_strcmp(var, "max_bss_load") == 0) 3121 return alloc_int_str(cred->max_bss_load); 3122 3123 if (os_strcmp(var, "req_conn_capab") == 0) { 3124 unsigned int i; 3125 char *buf, *end, *pos; 3126 int ret; 3127 3128 if (!cred->num_req_conn_capab) 3129 return NULL; 3130 3131 buf = os_malloc(4000); 3132 if (buf == NULL) 3133 return NULL; 3134 pos = buf; 3135 end = pos + 4000; 3136 for (i = 0; i < cred->num_req_conn_capab; i++) { 3137 int *ports; 3138 3139 ret = os_snprintf(pos, end - pos, "%s%u", 3140 i > 0 ? "\n" : "", 3141 cred->req_conn_capab_proto[i]); 3142 if (os_snprintf_error(end - pos, ret)) 3143 return buf; 3144 pos += ret; 3145 3146 ports = cred->req_conn_capab_port[i]; 3147 if (ports) { 3148 int j; 3149 for (j = 0; ports[j] != -1; j++) { 3150 ret = os_snprintf(pos, end - pos, 3151 "%s%d", 3152 j > 0 ? "," : ":", 3153 ports[j]); 3154 if (os_snprintf_error(end - pos, ret)) 3155 return buf; 3156 pos += ret; 3157 } 3158 } 3159 } 3160 3161 return buf; 3162 } 3163 3164 if (os_strcmp(var, "ocsp") == 0) 3165 return alloc_int_str(cred->ocsp); 3166 3167 if (os_strcmp(var, "realm") == 0) 3168 return alloc_strdup(cred->realm); 3169 3170 if (os_strcmp(var, "username") == 0) 3171 return alloc_strdup(cred->username); 3172 3173 if (os_strcmp(var, "password") == 0) { 3174 if (!cred->password) 3175 return NULL; 3176 return alloc_strdup("*"); 3177 } 3178 3179 if (os_strcmp(var, "ca_cert") == 0) 3180 return alloc_strdup(cred->ca_cert); 3181 3182 if (os_strcmp(var, "client_cert") == 0) 3183 return alloc_strdup(cred->client_cert); 3184 3185 if (os_strcmp(var, "private_key") == 0) 3186 return alloc_strdup(cred->private_key); 3187 3188 if (os_strcmp(var, "private_key_passwd") == 0) { 3189 if (!cred->private_key_passwd) 3190 return NULL; 3191 return alloc_strdup("*"); 3192 } 3193 3194 if (os_strcmp(var, "imsi") == 0) 3195 return alloc_strdup(cred->imsi); 3196 3197 if (os_strcmp(var, "milenage") == 0) { 3198 if (!(cred->milenage)) 3199 return NULL; 3200 return alloc_strdup("*"); 3201 } 3202 3203 if (os_strcmp(var, "domain_suffix_match") == 0) 3204 return alloc_strdup(cred->domain_suffix_match); 3205 3206 if (os_strcmp(var, "domain") == 0) { 3207 unsigned int i; 3208 char *buf, *end, *pos; 3209 int ret; 3210 3211 if (!cred->num_domain) 3212 return NULL; 3213 3214 buf = os_malloc(4000); 3215 if (buf == NULL) 3216 return NULL; 3217 pos = buf; 3218 end = pos + 4000; 3219 3220 for (i = 0; i < cred->num_domain; i++) { 3221 ret = os_snprintf(pos, end - pos, "%s%s", 3222 i > 0 ? "\n" : "", cred->domain[i]); 3223 if (os_snprintf_error(end - pos, ret)) 3224 return buf; 3225 pos += ret; 3226 } 3227 3228 return buf; 3229 } 3230 3231 if (os_strcmp(var, "phase1") == 0) 3232 return alloc_strdup(cred->phase1); 3233 3234 if (os_strcmp(var, "phase2") == 0) 3235 return alloc_strdup(cred->phase2); 3236 3237 if (os_strcmp(var, "roaming_consortium") == 0) { 3238 size_t buflen; 3239 char *buf; 3240 3241 if (!cred->roaming_consortium_len) 3242 return NULL; 3243 buflen = cred->roaming_consortium_len * 2 + 1; 3244 buf = os_malloc(buflen); 3245 if (buf == NULL) 3246 return NULL; 3247 wpa_snprintf_hex(buf, buflen, cred->roaming_consortium, 3248 cred->roaming_consortium_len); 3249 return buf; 3250 } 3251 3252 if (os_strcmp(var, "required_roaming_consortium") == 0) { 3253 size_t buflen; 3254 char *buf; 3255 3256 if (!cred->required_roaming_consortium_len) 3257 return NULL; 3258 buflen = cred->required_roaming_consortium_len * 2 + 1; 3259 buf = os_malloc(buflen); 3260 if (buf == NULL) 3261 return NULL; 3262 wpa_snprintf_hex(buf, buflen, cred->required_roaming_consortium, 3263 cred->required_roaming_consortium_len); 3264 return buf; 3265 } 3266 3267 if (os_strcmp(var, "excluded_ssid") == 0) { 3268 unsigned int i; 3269 char *buf, *end, *pos; 3270 3271 if (!cred->num_excluded_ssid) 3272 return NULL; 3273 3274 buf = os_malloc(4000); 3275 if (buf == NULL) 3276 return NULL; 3277 pos = buf; 3278 end = pos + 4000; 3279 3280 for (i = 0; i < cred->num_excluded_ssid; i++) { 3281 struct excluded_ssid *e; 3282 int ret; 3283 3284 e = &cred->excluded_ssid[i]; 3285 ret = os_snprintf(pos, end - pos, "%s%s", 3286 i > 0 ? "\n" : "", 3287 wpa_ssid_txt(e->ssid, e->ssid_len)); 3288 if (os_snprintf_error(end - pos, ret)) 3289 return buf; 3290 pos += ret; 3291 } 3292 3293 return buf; 3294 } 3295 3296 if (os_strcmp(var, "roaming_partner") == 0) { 3297 unsigned int i; 3298 char *buf, *end, *pos; 3299 3300 if (!cred->num_roaming_partner) 3301 return NULL; 3302 3303 buf = os_malloc(4000); 3304 if (buf == NULL) 3305 return NULL; 3306 pos = buf; 3307 end = pos + 4000; 3308 3309 for (i = 0; i < cred->num_roaming_partner; i++) { 3310 struct roaming_partner *p; 3311 int ret; 3312 3313 p = &cred->roaming_partner[i]; 3314 ret = os_snprintf(pos, end - pos, "%s%s,%d,%u,%s", 3315 i > 0 ? "\n" : "", 3316 p->fqdn, p->exact_match, p->priority, 3317 p->country); 3318 if (os_snprintf_error(end - pos, ret)) 3319 return buf; 3320 pos += ret; 3321 } 3322 3323 return buf; 3324 } 3325 3326 if (os_strcmp(var, "provisioning_sp") == 0) 3327 return alloc_strdup(cred->provisioning_sp); 3328 3329 return NULL; 3330} 3331 3332 3333struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id) 3334{ 3335 struct wpa_cred *cred; 3336 3337 cred = config->cred; 3338 while (cred) { 3339 if (id == cred->id) 3340 break; 3341 cred = cred->next; 3342 } 3343 3344 return cred; 3345} 3346 3347 3348struct wpa_cred * wpa_config_add_cred(struct wpa_config *config) 3349{ 3350 int id; 3351 struct wpa_cred *cred, *last = NULL; 3352 3353 id = -1; 3354 cred = config->cred; 3355 while (cred) { 3356 if (cred->id > id) 3357 id = cred->id; 3358 last = cred; 3359 cred = cred->next; 3360 } 3361 id++; 3362 3363 cred = os_zalloc(sizeof(*cred)); 3364 if (cred == NULL) 3365 return NULL; 3366 cred->id = id; 3367 cred->sim_num = DEFAULT_USER_SELECTED_SIM; 3368 if (last) 3369 last->next = cred; 3370 else 3371 config->cred = cred; 3372 3373 return cred; 3374} 3375 3376 3377int wpa_config_remove_cred(struct wpa_config *config, int id) 3378{ 3379 struct wpa_cred *cred, *prev = NULL; 3380 3381 cred = config->cred; 3382 while (cred) { 3383 if (id == cred->id) 3384 break; 3385 prev = cred; 3386 cred = cred->next; 3387 } 3388 3389 if (cred == NULL) 3390 return -1; 3391 3392 if (prev) 3393 prev->next = cred->next; 3394 else 3395 config->cred = cred->next; 3396 3397 wpa_config_free_cred(cred); 3398 return 0; 3399} 3400 3401 3402#ifndef CONFIG_NO_CONFIG_BLOBS 3403/** 3404 * wpa_config_get_blob - Get a named configuration blob 3405 * @config: Configuration data from wpa_config_read() 3406 * @name: Name of the blob 3407 * Returns: Pointer to blob data or %NULL if not found 3408 */ 3409const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config, 3410 const char *name) 3411{ 3412 struct wpa_config_blob *blob = config->blobs; 3413 3414 while (blob) { 3415 if (os_strcmp(blob->name, name) == 0) 3416 return blob; 3417 blob = blob->next; 3418 } 3419 return NULL; 3420} 3421 3422 3423/** 3424 * wpa_config_set_blob - Set or add a named configuration blob 3425 * @config: Configuration data from wpa_config_read() 3426 * @blob: New value for the blob 3427 * 3428 * Adds a new configuration blob or replaces the current value of an existing 3429 * blob. 3430 */ 3431void wpa_config_set_blob(struct wpa_config *config, 3432 struct wpa_config_blob *blob) 3433{ 3434 wpa_config_remove_blob(config, blob->name); 3435 blob->next = config->blobs; 3436 config->blobs = blob; 3437} 3438 3439 3440/** 3441 * wpa_config_free_blob - Free blob data 3442 * @blob: Pointer to blob to be freed 3443 */ 3444void wpa_config_free_blob(struct wpa_config_blob *blob) 3445{ 3446 if (blob) { 3447 os_free(blob->name); 3448 bin_clear_free(blob->data, blob->len); 3449 os_free(blob); 3450 } 3451} 3452 3453 3454/** 3455 * wpa_config_remove_blob - Remove a named configuration blob 3456 * @config: Configuration data from wpa_config_read() 3457 * @name: Name of the blob to remove 3458 * Returns: 0 if blob was removed or -1 if blob was not found 3459 */ 3460int wpa_config_remove_blob(struct wpa_config *config, const char *name) 3461{ 3462 struct wpa_config_blob *pos = config->blobs, *prev = NULL; 3463 3464 while (pos) { 3465 if (os_strcmp(pos->name, name) == 0) { 3466 if (prev) 3467 prev->next = pos->next; 3468 else 3469 config->blobs = pos->next; 3470 wpa_config_free_blob(pos); 3471 return 0; 3472 } 3473 prev = pos; 3474 pos = pos->next; 3475 } 3476 3477 return -1; 3478} 3479#endif /* CONFIG_NO_CONFIG_BLOBS */ 3480 3481 3482/** 3483 * wpa_config_alloc_empty - Allocate an empty configuration 3484 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain 3485 * socket 3486 * @driver_param: Driver parameters 3487 * Returns: Pointer to allocated configuration data or %NULL on failure 3488 */ 3489struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, 3490 const char *driver_param) 3491{ 3492 struct wpa_config *config; 3493 const int aCWmin = 4, aCWmax = 10; 3494 const struct hostapd_wmm_ac_params ac_bk = 3495 { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ 3496 const struct hostapd_wmm_ac_params ac_be = 3497 { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ 3498 const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ 3499 { aCWmin - 1, aCWmin, 2, 3000 / 32, 0 }; 3500 const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ 3501 { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 }; 3502 3503 config = os_zalloc(sizeof(*config)); 3504 if (config == NULL) 3505 return NULL; 3506 config->eapol_version = DEFAULT_EAPOL_VERSION; 3507 config->ap_scan = DEFAULT_AP_SCAN; 3508 config->user_mpm = DEFAULT_USER_MPM; 3509 config->max_peer_links = DEFAULT_MAX_PEER_LINKS; 3510 config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY; 3511 config->fast_reauth = DEFAULT_FAST_REAUTH; 3512 config->p2p_go_intent = DEFAULT_P2P_GO_INTENT; 3513 config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS; 3514 config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY; 3515 config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN; 3516 config->p2p_go_ctwindow = DEFAULT_P2P_GO_CTWINDOW; 3517 config->bss_max_count = DEFAULT_BSS_MAX_COUNT; 3518 config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE; 3519 config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT; 3520 config->max_num_sta = DEFAULT_MAX_NUM_STA; 3521 config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE; 3522 config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ; 3523 config->wmm_ac_params[0] = ac_be; 3524 config->wmm_ac_params[1] = ac_bk; 3525 config->wmm_ac_params[2] = ac_vi; 3526 config->wmm_ac_params[3] = ac_vo; 3527 config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY; 3528 config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME; 3529 config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD; 3530 config->cert_in_cb = DEFAULT_CERT_IN_CB; 3531 3532 if (ctrl_interface) 3533 config->ctrl_interface = os_strdup(ctrl_interface); 3534 if (driver_param) 3535 config->driver_param = os_strdup(driver_param); 3536 3537 return config; 3538} 3539 3540 3541#ifndef CONFIG_NO_STDOUT_DEBUG 3542/** 3543 * wpa_config_debug_dump_networks - Debug dump of configured networks 3544 * @config: Configuration data from wpa_config_read() 3545 */ 3546void wpa_config_debug_dump_networks(struct wpa_config *config) 3547{ 3548 int prio; 3549 struct wpa_ssid *ssid; 3550 3551 for (prio = 0; prio < config->num_prio; prio++) { 3552 ssid = config->pssid[prio]; 3553 wpa_printf(MSG_DEBUG, "Priority group %d", 3554 ssid->priority); 3555 while (ssid) { 3556 wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", 3557 ssid->id, 3558 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 3559 ssid = ssid->pnext; 3560 } 3561 } 3562} 3563#endif /* CONFIG_NO_STDOUT_DEBUG */ 3564 3565 3566struct global_parse_data { 3567 char *name; 3568 int (*parser)(const struct global_parse_data *data, 3569 struct wpa_config *config, int line, const char *value); 3570 int (*get)(const char *name, struct wpa_config *config, long offset, 3571 char *buf, size_t buflen, int pretty_print); 3572 void *param1, *param2, *param3; 3573 unsigned int changed_flag; 3574}; 3575 3576 3577static int wpa_global_config_parse_int(const struct global_parse_data *data, 3578 struct wpa_config *config, int line, 3579 const char *pos) 3580{ 3581 int val, *dst; 3582 char *end; 3583 3584 dst = (int *) (((u8 *) config) + (long) data->param1); 3585 val = strtol(pos, &end, 0); 3586 if (*end) { 3587 wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"", 3588 line, pos); 3589 return -1; 3590 } 3591 *dst = val; 3592 3593 wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); 3594 3595 if (data->param2 && *dst < (long) data->param2) { 3596 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " 3597 "min_value=%ld)", line, data->name, *dst, 3598 (long) data->param2); 3599 *dst = (long) data->param2; 3600 return -1; 3601 } 3602 3603 if (data->param3 && *dst > (long) data->param3) { 3604 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " 3605 "max_value=%ld)", line, data->name, *dst, 3606 (long) data->param3); 3607 *dst = (long) data->param3; 3608 return -1; 3609 } 3610 3611 return 0; 3612} 3613 3614 3615static int wpa_global_config_parse_str(const struct global_parse_data *data, 3616 struct wpa_config *config, int line, 3617 const char *pos) 3618{ 3619 size_t len; 3620 char **dst, *tmp; 3621 3622 len = os_strlen(pos); 3623 if (data->param2 && len < (size_t) data->param2) { 3624 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " 3625 "min_len=%ld)", line, data->name, 3626 (unsigned long) len, (long) data->param2); 3627 return -1; 3628 } 3629 3630 if (data->param3 && len > (size_t) data->param3) { 3631 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " 3632 "max_len=%ld)", line, data->name, 3633 (unsigned long) len, (long) data->param3); 3634 return -1; 3635 } 3636 3637 tmp = os_strdup(pos); 3638 if (tmp == NULL) 3639 return -1; 3640 3641 dst = (char **) (((u8 *) config) + (long) data->param1); 3642 os_free(*dst); 3643 *dst = tmp; 3644 wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); 3645 3646 return 0; 3647} 3648 3649 3650static int wpa_config_process_bgscan(const struct global_parse_data *data, 3651 struct wpa_config *config, int line, 3652 const char *pos) 3653{ 3654 size_t len; 3655 char *tmp; 3656 int res; 3657 3658 tmp = wpa_config_parse_string(pos, &len); 3659 if (tmp == NULL) { 3660 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s", 3661 line, data->name); 3662 return -1; 3663 } 3664 3665 res = wpa_global_config_parse_str(data, config, line, tmp); 3666 os_free(tmp); 3667 return res; 3668} 3669 3670 3671static int wpa_global_config_parse_bin(const struct global_parse_data *data, 3672 struct wpa_config *config, int line, 3673 const char *pos) 3674{ 3675 size_t len; 3676 struct wpabuf **dst, *tmp; 3677 3678 len = os_strlen(pos); 3679 if (len & 0x01) 3680 return -1; 3681 3682 tmp = wpabuf_alloc(len / 2); 3683 if (tmp == NULL) 3684 return -1; 3685 3686 if (hexstr2bin(pos, wpabuf_put(tmp, len / 2), len / 2)) { 3687 wpabuf_free(tmp); 3688 return -1; 3689 } 3690 3691 dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1); 3692 wpabuf_free(*dst); 3693 *dst = tmp; 3694 wpa_printf(MSG_DEBUG, "%s", data->name); 3695 3696 return 0; 3697} 3698 3699 3700static int wpa_config_process_freq_list(const struct global_parse_data *data, 3701 struct wpa_config *config, int line, 3702 const char *value) 3703{ 3704 int *freqs; 3705 3706 freqs = wpa_config_parse_int_array(value); 3707 if (freqs == NULL) 3708 return -1; 3709 if (freqs[0] == 0) { 3710 os_free(freqs); 3711 freqs = NULL; 3712 } 3713 os_free(config->freq_list); 3714 config->freq_list = freqs; 3715 return 0; 3716} 3717 3718 3719#ifdef CONFIG_P2P 3720static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, 3721 struct wpa_config *config, int line, 3722 const char *pos) 3723{ 3724 u32 *dst; 3725 struct hostapd_ip_addr addr; 3726 3727 if (hostapd_parse_ip_addr(pos, &addr) < 0) 3728 return -1; 3729 if (addr.af != AF_INET) 3730 return -1; 3731 3732 dst = (u32 *) (((u8 *) config) + (long) data->param1); 3733 os_memcpy(dst, &addr.u.v4.s_addr, 4); 3734 wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name, 3735 WPA_GET_BE32((u8 *) dst)); 3736 3737 return 0; 3738} 3739#endif /* CONFIG_P2P */ 3740 3741 3742static int wpa_config_process_country(const struct global_parse_data *data, 3743 struct wpa_config *config, int line, 3744 const char *pos) 3745{ 3746 if (!pos[0] || !pos[1]) { 3747 wpa_printf(MSG_DEBUG, "Invalid country set"); 3748 return -1; 3749 } 3750 config->country[0] = pos[0]; 3751 config->country[1] = pos[1]; 3752 wpa_printf(MSG_DEBUG, "country='%c%c'", 3753 config->country[0], config->country[1]); 3754 return 0; 3755} 3756 3757 3758static int wpa_config_process_load_dynamic_eap( 3759 const struct global_parse_data *data, struct wpa_config *config, 3760 int line, const char *so) 3761{ 3762 int ret; 3763 wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); 3764 ret = eap_peer_method_load(so); 3765 if (ret == -2) { 3766 wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not " 3767 "reloading."); 3768 } else if (ret) { 3769 wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP " 3770 "method '%s'.", line, so); 3771 return -1; 3772 } 3773 3774 return 0; 3775} 3776 3777 3778#ifdef CONFIG_WPS 3779 3780static int wpa_config_process_uuid(const struct global_parse_data *data, 3781 struct wpa_config *config, int line, 3782 const char *pos) 3783{ 3784 char buf[40]; 3785 if (uuid_str2bin(pos, config->uuid)) { 3786 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); 3787 return -1; 3788 } 3789 uuid_bin2str(config->uuid, buf, sizeof(buf)); 3790 wpa_printf(MSG_DEBUG, "uuid=%s", buf); 3791 return 0; 3792} 3793 3794 3795static int wpa_config_process_device_type( 3796 const struct global_parse_data *data, 3797 struct wpa_config *config, int line, const char *pos) 3798{ 3799 return wps_dev_type_str2bin(pos, config->device_type); 3800} 3801 3802 3803static int wpa_config_process_os_version(const struct global_parse_data *data, 3804 struct wpa_config *config, int line, 3805 const char *pos) 3806{ 3807 if (hexstr2bin(pos, config->os_version, 4)) { 3808 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line); 3809 return -1; 3810 } 3811 wpa_printf(MSG_DEBUG, "os_version=%08x", 3812 WPA_GET_BE32(config->os_version)); 3813 return 0; 3814} 3815 3816 3817static int wpa_config_process_wps_vendor_ext_m1( 3818 const struct global_parse_data *data, 3819 struct wpa_config *config, int line, const char *pos) 3820{ 3821 struct wpabuf *tmp; 3822 int len = os_strlen(pos) / 2; 3823 u8 *p; 3824 3825 if (!len) { 3826 wpa_printf(MSG_ERROR, "Line %d: " 3827 "invalid wps_vendor_ext_m1", line); 3828 return -1; 3829 } 3830 3831 tmp = wpabuf_alloc(len); 3832 if (tmp) { 3833 p = wpabuf_put(tmp, len); 3834 3835 if (hexstr2bin(pos, p, len)) { 3836 wpa_printf(MSG_ERROR, "Line %d: " 3837 "invalid wps_vendor_ext_m1", line); 3838 wpabuf_free(tmp); 3839 return -1; 3840 } 3841 3842 wpabuf_free(config->wps_vendor_ext_m1); 3843 config->wps_vendor_ext_m1 = tmp; 3844 } else { 3845 wpa_printf(MSG_ERROR, "Can not allocate " 3846 "memory for wps_vendor_ext_m1"); 3847 return -1; 3848 } 3849 3850 return 0; 3851} 3852 3853#endif /* CONFIG_WPS */ 3854 3855#ifdef CONFIG_P2P 3856static int wpa_config_process_sec_device_type( 3857 const struct global_parse_data *data, 3858 struct wpa_config *config, int line, const char *pos) 3859{ 3860 int idx; 3861 3862 if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) { 3863 wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type " 3864 "items", line); 3865 return -1; 3866 } 3867 3868 idx = config->num_sec_device_types; 3869 3870 if (wps_dev_type_str2bin(pos, config->sec_device_type[idx])) 3871 return -1; 3872 3873 config->num_sec_device_types++; 3874 return 0; 3875} 3876 3877 3878static int wpa_config_process_p2p_pref_chan( 3879 const struct global_parse_data *data, 3880 struct wpa_config *config, int line, const char *pos) 3881{ 3882 struct p2p_channel *pref = NULL, *n; 3883 unsigned int num = 0; 3884 const char *pos2; 3885 u8 op_class, chan; 3886 3887 /* format: class:chan,class:chan,... */ 3888 3889 while (*pos) { 3890 op_class = atoi(pos); 3891 pos2 = os_strchr(pos, ':'); 3892 if (pos2 == NULL) 3893 goto fail; 3894 pos2++; 3895 chan = atoi(pos2); 3896 3897 n = os_realloc_array(pref, num + 1, 3898 sizeof(struct p2p_channel)); 3899 if (n == NULL) 3900 goto fail; 3901 pref = n; 3902 pref[num].op_class = op_class; 3903 pref[num].chan = chan; 3904 num++; 3905 3906 pos = os_strchr(pos2, ','); 3907 if (pos == NULL) 3908 break; 3909 pos++; 3910 } 3911 3912 os_free(config->p2p_pref_chan); 3913 config->p2p_pref_chan = pref; 3914 config->num_p2p_pref_chan = num; 3915 wpa_hexdump(MSG_DEBUG, "P2P: Preferred class/channel pairs", 3916 (u8 *) config->p2p_pref_chan, 3917 config->num_p2p_pref_chan * sizeof(struct p2p_channel)); 3918 3919 return 0; 3920 3921fail: 3922 os_free(pref); 3923 wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_pref_chan list", line); 3924 return -1; 3925} 3926 3927 3928static int wpa_config_process_p2p_no_go_freq( 3929 const struct global_parse_data *data, 3930 struct wpa_config *config, int line, const char *pos) 3931{ 3932 int ret; 3933 3934 ret = freq_range_list_parse(&config->p2p_no_go_freq, pos); 3935 if (ret < 0) { 3936 wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_no_go_freq", line); 3937 return -1; 3938 } 3939 3940 wpa_printf(MSG_DEBUG, "P2P: p2p_no_go_freq with %u items", 3941 config->p2p_no_go_freq.num); 3942 3943 return 0; 3944} 3945 3946#endif /* CONFIG_P2P */ 3947 3948 3949static int wpa_config_process_hessid( 3950 const struct global_parse_data *data, 3951 struct wpa_config *config, int line, const char *pos) 3952{ 3953 if (hwaddr_aton2(pos, config->hessid) < 0) { 3954 wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'", 3955 line, pos); 3956 return -1; 3957 } 3958 3959 return 0; 3960} 3961 3962 3963static int wpa_config_process_sae_groups( 3964 const struct global_parse_data *data, 3965 struct wpa_config *config, int line, const char *pos) 3966{ 3967 int *groups = wpa_config_parse_int_array(pos); 3968 if (groups == NULL) { 3969 wpa_printf(MSG_ERROR, "Line %d: Invalid sae_groups '%s'", 3970 line, pos); 3971 return -1; 3972 } 3973 3974 os_free(config->sae_groups); 3975 config->sae_groups = groups; 3976 3977 return 0; 3978} 3979 3980 3981static int wpa_config_process_ap_vendor_elements( 3982 const struct global_parse_data *data, 3983 struct wpa_config *config, int line, const char *pos) 3984{ 3985 struct wpabuf *tmp; 3986 int len = os_strlen(pos) / 2; 3987 u8 *p; 3988 3989 if (!len) { 3990 wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements", 3991 line); 3992 return -1; 3993 } 3994 3995 tmp = wpabuf_alloc(len); 3996 if (tmp) { 3997 p = wpabuf_put(tmp, len); 3998 3999 if (hexstr2bin(pos, p, len)) { 4000 wpa_printf(MSG_ERROR, "Line %d: invalid " 4001 "ap_vendor_elements", line); 4002 wpabuf_free(tmp); 4003 return -1; 4004 } 4005 4006 wpabuf_free(config->ap_vendor_elements); 4007 config->ap_vendor_elements = tmp; 4008 } else { 4009 wpa_printf(MSG_ERROR, "Cannot allocate memory for " 4010 "ap_vendor_elements"); 4011 return -1; 4012 } 4013 4014 return 0; 4015} 4016 4017 4018#ifdef CONFIG_CTRL_IFACE 4019static int wpa_config_process_no_ctrl_interface( 4020 const struct global_parse_data *data, 4021 struct wpa_config *config, int line, const char *pos) 4022{ 4023 wpa_printf(MSG_DEBUG, "no_ctrl_interface -> ctrl_interface=NULL"); 4024 os_free(config->ctrl_interface); 4025 config->ctrl_interface = NULL; 4026 return 0; 4027} 4028#endif /* CONFIG_CTRL_IFACE */ 4029 4030 4031static int wpa_config_get_int(const char *name, struct wpa_config *config, 4032 long offset, char *buf, size_t buflen, 4033 int pretty_print) 4034{ 4035 int *val = (int *) (((u8 *) config) + (long) offset); 4036 4037 if (pretty_print) 4038 return os_snprintf(buf, buflen, "%s=%d\n", name, *val); 4039 return os_snprintf(buf, buflen, "%d", *val); 4040} 4041 4042 4043static int wpa_config_get_str(const char *name, struct wpa_config *config, 4044 long offset, char *buf, size_t buflen, 4045 int pretty_print) 4046{ 4047 char **val = (char **) (((u8 *) config) + (long) offset); 4048 int res; 4049 4050 if (pretty_print) 4051 res = os_snprintf(buf, buflen, "%s=%s\n", name, 4052 *val ? *val : "null"); 4053 else if (!*val) 4054 return -1; 4055 else 4056 res = os_snprintf(buf, buflen, "%s", *val); 4057 if (os_snprintf_error(buflen, res)) 4058 res = -1; 4059 4060 return res; 4061} 4062 4063 4064#ifdef CONFIG_P2P 4065static int wpa_config_get_ipv4(const char *name, struct wpa_config *config, 4066 long offset, char *buf, size_t buflen, 4067 int pretty_print) 4068{ 4069 void *val = ((u8 *) config) + (long) offset; 4070 int res; 4071 char addr[INET_ADDRSTRLEN]; 4072 4073 if (!val || !inet_ntop(AF_INET, val, addr, sizeof(addr))) 4074 return -1; 4075 4076 if (pretty_print) 4077 res = os_snprintf(buf, buflen, "%s=%s\n", name, addr); 4078 else 4079 res = os_snprintf(buf, buflen, "%s", addr); 4080 4081 if (os_snprintf_error(buflen, res)) 4082 res = -1; 4083 4084 return res; 4085} 4086#endif /* CONFIG_P2P */ 4087 4088 4089#ifdef OFFSET 4090#undef OFFSET 4091#endif /* OFFSET */ 4092/* OFFSET: Get offset of a variable within the wpa_config structure */ 4093#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v) 4094 4095#define FUNC(f) #f, wpa_config_process_ ## f, NULL, OFFSET(f), NULL, NULL 4096#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL, NULL 4097#define _INT(f) #f, wpa_global_config_parse_int, wpa_config_get_int, OFFSET(f) 4098#define INT(f) _INT(f), NULL, NULL 4099#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max 4100#define _STR(f) #f, wpa_global_config_parse_str, wpa_config_get_str, OFFSET(f) 4101#define STR(f) _STR(f), NULL, NULL 4102#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max 4103#define BIN(f) #f, wpa_global_config_parse_bin, NULL, OFFSET(f), NULL, NULL 4104#define IPV4(f) #f, wpa_global_config_parse_ipv4, wpa_config_get_ipv4, \ 4105 OFFSET(f), NULL, NULL 4106 4107static const struct global_parse_data global_fields[] = { 4108#ifdef CONFIG_CTRL_IFACE 4109 { STR(ctrl_interface), 0 }, 4110 { FUNC_NO_VAR(no_ctrl_interface), 0 }, 4111 { STR(ctrl_interface_group), 0 } /* deprecated */, 4112#endif /* CONFIG_CTRL_IFACE */ 4113#ifdef CONFIG_MACSEC 4114 { INT_RANGE(eapol_version, 1, 3), 0 }, 4115#else /* CONFIG_MACSEC */ 4116 { INT_RANGE(eapol_version, 1, 2), 0 }, 4117#endif /* CONFIG_MACSEC */ 4118 { INT(ap_scan), 0 }, 4119 { FUNC(bgscan), 0 }, 4120#ifdef CONFIG_MESH 4121 { INT(user_mpm), 0 }, 4122 { INT_RANGE(max_peer_links, 0, 255), 0 }, 4123 { INT(mesh_max_inactivity), 0 }, 4124#endif /* CONFIG_MESH */ 4125 { INT(disable_scan_offload), 0 }, 4126 { INT(fast_reauth), 0 }, 4127 { STR(opensc_engine_path), 0 }, 4128 { STR(pkcs11_engine_path), 0 }, 4129 { STR(pkcs11_module_path), 0 }, 4130 { STR(openssl_ciphers), 0 }, 4131 { STR(pcsc_reader), 0 }, 4132 { STR(pcsc_pin), 0 }, 4133 { INT(external_sim), 0 }, 4134 { STR(driver_param), 0 }, 4135 { INT(dot11RSNAConfigPMKLifetime), 0 }, 4136 { INT(dot11RSNAConfigPMKReauthThreshold), 0 }, 4137 { INT(dot11RSNAConfigSATimeout), 0 }, 4138#ifndef CONFIG_NO_CONFIG_WRITE 4139 { INT(update_config), 0 }, 4140#endif /* CONFIG_NO_CONFIG_WRITE */ 4141 { FUNC_NO_VAR(load_dynamic_eap), 0 }, 4142#ifdef CONFIG_WPS 4143 { FUNC(uuid), CFG_CHANGED_UUID }, 4144 { STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN), 4145 CFG_CHANGED_DEVICE_NAME }, 4146 { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING }, 4147 { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING }, 4148 { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING }, 4149 { STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING }, 4150 { FUNC(device_type), CFG_CHANGED_DEVICE_TYPE }, 4151 { FUNC(os_version), CFG_CHANGED_OS_VERSION }, 4152 { STR(config_methods), CFG_CHANGED_CONFIG_METHODS }, 4153 { INT_RANGE(wps_cred_processing, 0, 2), 0 }, 4154 { FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION }, 4155#endif /* CONFIG_WPS */ 4156#ifdef CONFIG_P2P 4157 { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE }, 4158 { INT(p2p_listen_reg_class), 0 }, 4159 { INT(p2p_listen_channel), 0 }, 4160 { INT(p2p_oper_reg_class), CFG_CHANGED_P2P_OPER_CHANNEL }, 4161 { INT(p2p_oper_channel), CFG_CHANGED_P2P_OPER_CHANNEL }, 4162 { INT_RANGE(p2p_go_intent, 0, 15), 0 }, 4163 { STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX }, 4164 { INT_RANGE(persistent_reconnect, 0, 1), 0 }, 4165 { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS }, 4166 { INT(p2p_group_idle), 0 }, 4167 { INT_RANGE(p2p_passphrase_len, 8, 63), 4168 CFG_CHANGED_P2P_PASSPHRASE_LEN }, 4169 { FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN }, 4170 { FUNC(p2p_no_go_freq), CFG_CHANGED_P2P_PREF_CHAN }, 4171 { INT_RANGE(p2p_add_cli_chan, 0, 1), 0 }, 4172 { INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 }, 4173 { INT(p2p_go_ht40), 0 }, 4174 { INT(p2p_go_vht), 0 }, 4175 { INT(p2p_disabled), 0 }, 4176 { INT_RANGE(p2p_go_ctwindow, 0, 127), 0 }, 4177 { INT(p2p_no_group_iface), 0 }, 4178 { INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 }, 4179 { IPV4(ip_addr_go), 0 }, 4180 { IPV4(ip_addr_mask), 0 }, 4181 { IPV4(ip_addr_start), 0 }, 4182 { IPV4(ip_addr_end), 0 }, 4183#endif /* CONFIG_P2P */ 4184 { FUNC(country), CFG_CHANGED_COUNTRY }, 4185 { INT(bss_max_count), 0 }, 4186 { INT(bss_expiration_age), 0 }, 4187 { INT(bss_expiration_scan_count), 0 }, 4188 { INT_RANGE(filter_ssids, 0, 1), 0 }, 4189 { INT_RANGE(filter_rssi, -100, 0), 0 }, 4190 { INT(max_num_sta), 0 }, 4191 { INT_RANGE(disassoc_low_ack, 0, 1), 0 }, 4192#ifdef CONFIG_HS20 4193 { INT_RANGE(hs20, 0, 1), 0 }, 4194#endif /* CONFIG_HS20 */ 4195 { INT_RANGE(interworking, 0, 1), 0 }, 4196 { FUNC(hessid), 0 }, 4197 { INT_RANGE(access_network_type, 0, 15), 0 }, 4198 { INT_RANGE(pbc_in_m1, 0, 1), 0 }, 4199 { STR(autoscan), 0 }, 4200 { INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff), 4201 CFG_CHANGED_NFC_PASSWORD_TOKEN }, 4202 { BIN(wps_nfc_dh_pubkey), CFG_CHANGED_NFC_PASSWORD_TOKEN }, 4203 { BIN(wps_nfc_dh_privkey), CFG_CHANGED_NFC_PASSWORD_TOKEN }, 4204 { BIN(wps_nfc_dev_pw), CFG_CHANGED_NFC_PASSWORD_TOKEN }, 4205 { STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND }, 4206 { INT(p2p_go_max_inactivity), 0 }, 4207 { INT_RANGE(auto_interworking, 0, 1), 0 }, 4208 { INT(okc), 0 }, 4209 { INT(pmf), 0 }, 4210 { FUNC(sae_groups), 0 }, 4211 { INT(dtim_period), 0 }, 4212 { INT(beacon_int), 0 }, 4213 { FUNC(ap_vendor_elements), 0 }, 4214 { INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, 4215 { FUNC(freq_list), 0 }, 4216 { INT(scan_cur_freq), 0 }, 4217 { INT(sched_scan_interval), 0 }, 4218 { INT(tdls_external_control), 0}, 4219 { STR(osu_dir), 0 }, 4220 { STR(wowlan_triggers), 0 }, 4221 { INT(p2p_search_delay), 0}, 4222 { INT(mac_addr), 0 }, 4223 { INT(rand_addr_lifetime), 0 }, 4224 { INT(preassoc_mac_addr), 0 }, 4225 { INT(key_mgmt_offload), 0}, 4226 { INT(passive_scan), 0 }, 4227 { INT(reassoc_same_bss_optim), 0 }, 4228}; 4229 4230#undef FUNC 4231#undef _INT 4232#undef INT 4233#undef INT_RANGE 4234#undef _STR 4235#undef STR 4236#undef STR_RANGE 4237#undef BIN 4238#undef IPV4 4239#define NUM_GLOBAL_FIELDS ARRAY_SIZE(global_fields) 4240 4241 4242int wpa_config_dump_values(struct wpa_config *config, char *buf, size_t buflen) 4243{ 4244 int result = 0; 4245 size_t i; 4246 4247 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 4248 const struct global_parse_data *field = &global_fields[i]; 4249 int tmp; 4250 4251 if (!field->get) 4252 continue; 4253 4254 tmp = field->get(field->name, config, (long) field->param1, 4255 buf, buflen, 1); 4256 if (tmp < 0) 4257 return -1; 4258 buf += tmp; 4259 buflen -= tmp; 4260 result += tmp; 4261 } 4262 return result; 4263} 4264 4265 4266int wpa_config_get_value(const char *name, struct wpa_config *config, 4267 char *buf, size_t buflen) 4268{ 4269 size_t i; 4270 4271 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 4272 const struct global_parse_data *field = &global_fields[i]; 4273 4274 if (os_strcmp(name, field->name) != 0) 4275 continue; 4276 if (!field->get) 4277 break; 4278 return field->get(name, config, (long) field->param1, 4279 buf, buflen, 0); 4280 } 4281 4282 return -1; 4283} 4284 4285 4286int wpa_config_process_global(struct wpa_config *config, char *pos, int line) 4287{ 4288 size_t i; 4289 int ret = 0; 4290 4291 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 4292 const struct global_parse_data *field = &global_fields[i]; 4293 size_t flen = os_strlen(field->name); 4294 if (os_strncmp(pos, field->name, flen) != 0 || 4295 pos[flen] != '=') 4296 continue; 4297 4298 if (field->parser(field, config, line, pos + flen + 1)) { 4299 wpa_printf(MSG_ERROR, "Line %d: failed to " 4300 "parse '%s'.", line, pos); 4301 ret = -1; 4302 } 4303 if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN) 4304 config->wps_nfc_pw_from_config = 1; 4305 config->changed_parameters |= field->changed_flag; 4306 break; 4307 } 4308 if (i == NUM_GLOBAL_FIELDS) { 4309#ifdef CONFIG_AP 4310 if (os_strncmp(pos, "wmm_ac_", 7) == 0) { 4311 char *tmp = os_strchr(pos, '='); 4312 if (tmp == NULL) { 4313 if (line < 0) 4314 return -1; 4315 wpa_printf(MSG_ERROR, "Line %d: invalid line " 4316 "'%s'", line, pos); 4317 return -1; 4318 } 4319 *tmp++ = '\0'; 4320 if (hostapd_config_wmm_ac(config->wmm_ac_params, pos, 4321 tmp)) { 4322 wpa_printf(MSG_ERROR, "Line %d: invalid WMM " 4323 "AC item", line); 4324 return -1; 4325 } 4326 } 4327#endif /* CONFIG_AP */ 4328 if (line < 0) 4329 return -1; 4330 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", 4331 line, pos); 4332 ret = -1; 4333 } 4334 4335 return ret; 4336} 4337