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