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