1/* 2 * WPA Supplicant / Configuration parser and common functions 3 * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "includes.h" 16 17#include "common.h" 18#include "wpa.h" 19#include "sha1.h" 20#include "eap_peer/eap.h" 21#include "config.h" 22 23 24#if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE) 25#define NO_CONFIG_WRITE 26#endif 27 28/* 29 * Structure for network configuration parsing. This data is used to implement 30 * a generic parser for each network block variable. The table of configuration 31 * variables is defined below in this file (ssid_fields[]). 32 */ 33struct parse_data { 34 /* Configuration variable name */ 35 char *name; 36 37 /* Parser function for this variable */ 38 int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid, 39 int line, const char *value); 40 41#ifndef NO_CONFIG_WRITE 42 /* Writer function (i.e., to get the variable in text format from 43 * internal presentation). */ 44 char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid); 45#endif /* NO_CONFIG_WRITE */ 46 47 /* Variable specific parameters for the parser. */ 48 void *param1, *param2, *param3, *param4; 49 50 /* 0 = this variable can be included in debug output and ctrl_iface 51 * 1 = this variable contains key/private data and it must not be 52 * included in debug output unless explicitly requested. In 53 * addition, this variable will not be readable through the 54 * ctrl_iface. 55 */ 56 int key_data; 57}; 58 59 60static char * wpa_config_parse_string(const char *value, size_t *len) 61{ 62 if (*value == '"') { 63 const char *pos; 64 char *str; 65 value++; 66 pos = os_strrchr(value, '"'); 67 if (pos == NULL || pos[1] != '\0') 68 return NULL; 69 *len = pos - value; 70 str = os_malloc(*len + 1); 71 if (str == NULL) 72 return NULL; 73 os_memcpy(str, value, *len); 74 str[*len] = '\0'; 75 return str; 76 } else { 77 u8 *str; 78 size_t tlen, hlen = os_strlen(value); 79 if (hlen & 1) 80 return NULL; 81 tlen = hlen / 2; 82 str = os_malloc(tlen + 1); 83 if (str == NULL) 84 return NULL; 85 if (hexstr2bin(value, str, tlen)) { 86 os_free(str); 87 return NULL; 88 } 89 str[tlen] = '\0'; 90 *len = tlen; 91 return (char *) str; 92 } 93} 94 95 96static int wpa_config_parse_str(const struct parse_data *data, 97 struct wpa_ssid *ssid, 98 int line, const char *value) 99{ 100 size_t res_len, *dst_len; 101 char **dst, *tmp; 102 103 if (os_strcmp(value, "NULL") == 0) { 104 wpa_printf(MSG_DEBUG, "Unset configuration string '%s'", 105 data->name); 106 tmp = NULL; 107 res_len = 0; 108 goto set; 109 } 110 111 tmp = wpa_config_parse_string(value, &res_len); 112 if (tmp == NULL) { 113 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.", 114 line, data->name, 115 data->key_data ? "[KEY DATA REMOVED]" : value); 116 return -1; 117 } 118 119 if (data->key_data) { 120 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, 121 (u8 *) tmp, res_len); 122 } else { 123 wpa_hexdump_ascii(MSG_MSGDUMP, data->name, 124 (u8 *) tmp, res_len); 125 } 126 127 if (data->param3 && res_len < (size_t) data->param3) { 128 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " 129 "min_len=%ld)", line, data->name, 130 (unsigned long) res_len, (long) data->param3); 131 os_free(tmp); 132 return -1; 133 } 134 135 if (data->param4 && res_len > (size_t) data->param4) { 136 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " 137 "max_len=%ld)", line, data->name, 138 (unsigned long) res_len, (long) data->param4); 139 os_free(tmp); 140 return -1; 141 } 142 143set: 144 dst = (char **) (((u8 *) ssid) + (long) data->param1); 145 dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2); 146 os_free(*dst); 147 *dst = tmp; 148 if (data->param2) 149 *dst_len = res_len; 150 151 return 0; 152} 153 154 155#ifndef NO_CONFIG_WRITE 156static int is_hex(const u8 *data, size_t len) 157{ 158 size_t i; 159 160 for (i = 0; i < len; i++) { 161 if (data[i] < 32 || data[i] >= 127) 162 return 1; 163 } 164 return 0; 165} 166 167 168static char * wpa_config_write_string_ascii(const u8 *value, size_t len) 169{ 170 char *buf; 171 172 buf = os_malloc(len + 3); 173 if (buf == NULL) 174 return NULL; 175 buf[0] = '"'; 176 os_memcpy(buf + 1, value, len); 177 buf[len + 1] = '"'; 178 buf[len + 2] = '\0'; 179 180 return buf; 181} 182 183 184static char * wpa_config_write_string_hex(const u8 *value, size_t len) 185{ 186 char *buf; 187 188 buf = os_zalloc(2 * len + 1); 189 if (buf == NULL) 190 return NULL; 191 wpa_snprintf_hex(buf, 2 * len + 1, value, len); 192 193 return buf; 194} 195 196 197static char * wpa_config_write_string(const u8 *value, size_t len) 198{ 199 if (value == NULL) 200 return NULL; 201 202 if (is_hex(value, len)) 203 return wpa_config_write_string_hex(value, len); 204 else 205 return wpa_config_write_string_ascii(value, len); 206} 207 208 209static char * wpa_config_write_str(const struct parse_data *data, 210 struct wpa_ssid *ssid) 211{ 212 size_t len; 213 char **src; 214 215 src = (char **) (((u8 *) ssid) + (long) data->param1); 216 if (*src == NULL) 217 return NULL; 218 219 if (data->param2) 220 len = *((size_t *) (((u8 *) ssid) + (long) data->param2)); 221 else 222 len = os_strlen(*src); 223 224 return wpa_config_write_string((const u8 *) *src, len); 225} 226#endif /* NO_CONFIG_WRITE */ 227 228 229static int wpa_config_parse_int(const struct parse_data *data, 230 struct wpa_ssid *ssid, 231 int line, const char *value) 232{ 233 int *dst; 234 235 dst = (int *) (((u8 *) ssid) + (long) data->param1); 236 *dst = atoi(value); 237 wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst); 238 239 if (data->param3 && *dst < (long) data->param3) { 240 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " 241 "min_value=%ld)", line, data->name, *dst, 242 (long) data->param3); 243 *dst = (long) data->param3; 244 return -1; 245 } 246 247 if (data->param4 && *dst > (long) data->param4) { 248 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " 249 "max_value=%ld)", line, data->name, *dst, 250 (long) data->param4); 251 *dst = (long) data->param4; 252 return -1; 253 } 254 255 return 0; 256} 257 258 259#ifndef NO_CONFIG_WRITE 260static char * wpa_config_write_int(const struct parse_data *data, 261 struct wpa_ssid *ssid) 262{ 263 int *src, res; 264 char *value; 265 266 src = (int *) (((u8 *) ssid) + (long) data->param1); 267 268 value = os_malloc(20); 269 if (value == NULL) 270 return NULL; 271 res = os_snprintf(value, 20, "%d", *src); 272 if (res < 0 || res >= 20) { 273 os_free(value); 274 return NULL; 275 } 276 value[20 - 1] = '\0'; 277 return value; 278} 279#endif /* NO_CONFIG_WRITE */ 280 281 282static int wpa_config_parse_bssid(const struct parse_data *data, 283 struct wpa_ssid *ssid, int line, 284 const char *value) 285{ 286 if (hwaddr_aton(value, ssid->bssid)) { 287 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.", 288 line, value); 289 return -1; 290 } 291 ssid->bssid_set = 1; 292 wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN); 293 return 0; 294} 295 296 297#ifndef NO_CONFIG_WRITE 298static char * wpa_config_write_bssid(const struct parse_data *data, 299 struct wpa_ssid *ssid) 300{ 301 char *value; 302 int res; 303 304 if (!ssid->bssid_set) 305 return NULL; 306 307 value = os_malloc(20); 308 if (value == NULL) 309 return NULL; 310 res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid)); 311 if (res < 0 || res >= 20) { 312 os_free(value); 313 return NULL; 314 } 315 value[20 - 1] = '\0'; 316 return value; 317} 318#endif /* NO_CONFIG_WRITE */ 319 320 321static int wpa_config_parse_psk(const struct parse_data *data, 322 struct wpa_ssid *ssid, int line, 323 const char *value) 324{ 325 if (*value == '"') { 326#ifndef CONFIG_NO_PBKDF2 327 const char *pos; 328 size_t len; 329 330 value++; 331 pos = os_strrchr(value, '"'); 332 if (pos) 333 len = pos - value; 334 else 335 len = os_strlen(value); 336 if (len < 8 || len > 63) { 337 wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase " 338 "length %lu (expected: 8..63) '%s'.", 339 line, (unsigned long) len, value); 340 return -1; 341 } 342 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)", 343 (u8 *) value, len); 344 if (ssid->passphrase && os_strlen(ssid->passphrase) == len && 345 os_memcmp(ssid->passphrase, value, len) == 0) 346 return 0; 347 ssid->psk_set = 0; 348 os_free(ssid->passphrase); 349 ssid->passphrase = os_malloc(len + 1); 350 if (ssid->passphrase == NULL) 351 return -1; 352 os_memcpy(ssid->passphrase, value, len); 353 ssid->passphrase[len] = '\0'; 354 return 0; 355#else /* CONFIG_NO_PBKDF2 */ 356 wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not " 357 "supported.", line); 358 return -1; 359#endif /* CONFIG_NO_PBKDF2 */ 360 } 361 362 if (hexstr2bin(value, ssid->psk, PMK_LEN) || 363 value[PMK_LEN * 2] != '\0') { 364 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", 365 line, value); 366 return -1; 367 } 368 369 os_free(ssid->passphrase); 370 ssid->passphrase = NULL; 371 372 ssid->psk_set = 1; 373 wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN); 374 return 0; 375} 376 377 378#ifndef NO_CONFIG_WRITE 379static char * wpa_config_write_psk(const struct parse_data *data, 380 struct wpa_ssid *ssid) 381{ 382 if (ssid->passphrase) 383 return wpa_config_write_string_ascii( 384 (const u8 *) ssid->passphrase, 385 os_strlen(ssid->passphrase)); 386 387 if (ssid->psk_set) 388 return wpa_config_write_string_hex(ssid->psk, PMK_LEN); 389 390 return NULL; 391} 392#endif /* NO_CONFIG_WRITE */ 393 394 395static int wpa_config_parse_proto(const struct parse_data *data, 396 struct wpa_ssid *ssid, int line, 397 const char *value) 398{ 399 int val = 0, last, errors = 0; 400 char *start, *end, *buf; 401 402 buf = os_strdup(value); 403 if (buf == NULL) 404 return -1; 405 start = buf; 406 407 while (*start != '\0') { 408 while (*start == ' ' || *start == '\t') 409 start++; 410 if (*start == '\0') 411 break; 412 end = start; 413 while (*end != ' ' && *end != '\t' && *end != '\0') 414 end++; 415 last = *end == '\0'; 416 *end = '\0'; 417 if (os_strcmp(start, "WPA") == 0) 418 val |= WPA_PROTO_WPA; 419 else if (os_strcmp(start, "RSN") == 0 || 420 os_strcmp(start, "WPA2") == 0) 421 val |= WPA_PROTO_RSN; 422 else { 423 wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'", 424 line, start); 425 errors++; 426 } 427 428 if (last) 429 break; 430 start = end + 1; 431 } 432 os_free(buf); 433 434 if (val == 0) { 435 wpa_printf(MSG_ERROR, 436 "Line %d: no proto values configured.", line); 437 errors++; 438 } 439 440 wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val); 441 ssid->proto = val; 442 return errors ? -1 : 0; 443} 444 445 446#ifndef NO_CONFIG_WRITE 447static char * wpa_config_write_proto(const struct parse_data *data, 448 struct wpa_ssid *ssid) 449{ 450 int first = 1, ret; 451 char *buf, *pos, *end; 452 453 pos = buf = os_zalloc(10); 454 if (buf == NULL) 455 return NULL; 456 end = buf + 10; 457 458 if (ssid->proto & WPA_PROTO_WPA) { 459 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 460 if (ret < 0 || ret >= end - pos) 461 return buf; 462 pos += ret; 463 first = 0; 464 } 465 466 if (ssid->proto & WPA_PROTO_RSN) { 467 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 468 if (ret < 0 || ret >= end - pos) 469 return buf; 470 pos += ret; 471 first = 0; 472 } 473 474 return buf; 475} 476#endif /* NO_CONFIG_WRITE */ 477 478 479static int wpa_config_parse_key_mgmt(const struct parse_data *data, 480 struct wpa_ssid *ssid, int line, 481 const char *value) 482{ 483 int val = 0, last, errors = 0; 484 char *start, *end, *buf; 485 486 buf = os_strdup(value); 487 if (buf == NULL) 488 return -1; 489 start = buf; 490 491 while (*start != '\0') { 492 while (*start == ' ' || *start == '\t') 493 start++; 494 if (*start == '\0') 495 break; 496 end = start; 497 while (*end != ' ' && *end != '\t' && *end != '\0') 498 end++; 499 last = *end == '\0'; 500 *end = '\0'; 501 if (os_strcmp(start, "WPA-PSK") == 0) 502 val |= WPA_KEY_MGMT_PSK; 503 else if (os_strcmp(start, "WPA-EAP") == 0) 504 val |= WPA_KEY_MGMT_IEEE8021X; 505 else if (os_strcmp(start, "IEEE8021X") == 0) 506 val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA; 507 else if (os_strcmp(start, "NONE") == 0) 508 val |= WPA_KEY_MGMT_NONE; 509 else if (os_strcmp(start, "WPA-NONE") == 0) 510 val |= WPA_KEY_MGMT_WPA_NONE; 511#ifdef CONFIG_IEEE80211R 512 else if (os_strcmp(start, "FT-PSK") == 0) 513 val |= WPA_KEY_MGMT_FT_PSK; 514 else if (os_strcmp(start, "FT-EAP") == 0) 515 val |= WPA_KEY_MGMT_FT_IEEE8021X; 516#endif /* CONFIG_IEEE80211R */ 517#ifdef CONFIG_IEEE80211W 518 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) 519 val |= WPA_KEY_MGMT_PSK_SHA256; 520 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) 521 val |= WPA_KEY_MGMT_IEEE8021X_SHA256; 522#endif /* CONFIG_IEEE80211W */ 523#ifdef CONFIG_WPS 524 else if (os_strcmp(start, "WPS") == 0) 525 val |= WPA_KEY_MGMT_WPS; 526#endif /* CONFIG_WPS */ 527 else { 528 wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", 529 line, start); 530 errors++; 531 } 532 533 if (last) 534 break; 535 start = end + 1; 536 } 537 os_free(buf); 538 539 if (val == 0) { 540 wpa_printf(MSG_ERROR, 541 "Line %d: no key_mgmt values configured.", line); 542 errors++; 543 } 544 545 wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val); 546 ssid->key_mgmt = val; 547 return errors ? -1 : 0; 548} 549 550 551#ifndef NO_CONFIG_WRITE 552static char * wpa_config_write_key_mgmt(const struct parse_data *data, 553 struct wpa_ssid *ssid) 554{ 555 char *buf, *pos, *end; 556 int ret; 557 558 pos = buf = os_zalloc(50); 559 if (buf == NULL) 560 return NULL; 561 end = buf + 50; 562 563 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { 564 ret = os_snprintf(pos, end - pos, "%sWPA-PSK", 565 pos == buf ? "" : " "); 566 if (ret < 0 || ret >= end - pos) { 567 end[-1] = '\0'; 568 return buf; 569 } 570 pos += ret; 571 } 572 573 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 574 ret = os_snprintf(pos, end - pos, "%sWPA-EAP", 575 pos == buf ? "" : " "); 576 if (ret < 0 || ret >= end - pos) { 577 end[-1] = '\0'; 578 return buf; 579 } 580 pos += ret; 581 } 582 583 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 584 ret = os_snprintf(pos, end - pos, "%sIEEE8021X", 585 pos == buf ? "" : " "); 586 if (ret < 0 || ret >= end - pos) { 587 end[-1] = '\0'; 588 return buf; 589 } 590 pos += ret; 591 } 592 593 if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) { 594 ret = os_snprintf(pos, end - pos, "%sNONE", 595 pos == buf ? "" : " "); 596 if (ret < 0 || ret >= end - pos) { 597 end[-1] = '\0'; 598 return buf; 599 } 600 pos += ret; 601 } 602 603 if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 604 ret = os_snprintf(pos, end - pos, "%sWPA-NONE", 605 pos == buf ? "" : " "); 606 if (ret < 0 || ret >= end - pos) { 607 end[-1] = '\0'; 608 return buf; 609 } 610 pos += ret; 611 } 612 613#ifdef CONFIG_IEEE80211R 614 if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) 615 pos += os_snprintf(pos, end - pos, "%sFT-PSK", 616 pos == buf ? "" : " "); 617 618 if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 619 pos += os_snprintf(pos, end - pos, "%sFT-EAP", 620 pos == buf ? "" : " "); 621#endif /* CONFIG_IEEE80211R */ 622 623#ifdef CONFIG_IEEE80211W 624 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 625 pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256", 626 pos == buf ? "" : " "); 627 628 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 629 pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256", 630 pos == buf ? "" : " "); 631#endif /* CONFIG_IEEE80211W */ 632 633#ifdef CONFIG_WPS 634 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) 635 pos += os_snprintf(pos, end - pos, "%sWPS", 636 pos == buf ? "" : " "); 637#endif /* CONFIG_WPS */ 638 639 return buf; 640} 641#endif /* NO_CONFIG_WRITE */ 642 643 644static int wpa_config_parse_cipher(int line, const char *value) 645{ 646 int val = 0, last; 647 char *start, *end, *buf; 648 649 buf = os_strdup(value); 650 if (buf == NULL) 651 return -1; 652 start = buf; 653 654 while (*start != '\0') { 655 while (*start == ' ' || *start == '\t') 656 start++; 657 if (*start == '\0') 658 break; 659 end = start; 660 while (*end != ' ' && *end != '\t' && *end != '\0') 661 end++; 662 last = *end == '\0'; 663 *end = '\0'; 664 if (os_strcmp(start, "CCMP") == 0) 665 val |= WPA_CIPHER_CCMP; 666 else if (os_strcmp(start, "TKIP") == 0) 667 val |= WPA_CIPHER_TKIP; 668 else if (os_strcmp(start, "WEP104") == 0) 669 val |= WPA_CIPHER_WEP104; 670 else if (os_strcmp(start, "WEP40") == 0) 671 val |= WPA_CIPHER_WEP40; 672 else if (os_strcmp(start, "NONE") == 0) 673 val |= WPA_CIPHER_NONE; 674 else { 675 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", 676 line, start); 677 os_free(buf); 678 return -1; 679 } 680 681 if (last) 682 break; 683 start = end + 1; 684 } 685 os_free(buf); 686 687 if (val == 0) { 688 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", 689 line); 690 return -1; 691 } 692 return val; 693} 694 695 696#ifndef NO_CONFIG_WRITE 697static char * wpa_config_write_cipher(int cipher) 698{ 699 char *buf, *pos, *end; 700 int ret; 701 702 pos = buf = os_zalloc(50); 703 if (buf == NULL) 704 return NULL; 705 end = buf + 50; 706 707 if (cipher & WPA_CIPHER_CCMP) { 708 ret = os_snprintf(pos, end - pos, "%sCCMP", 709 pos == buf ? "" : " "); 710 if (ret < 0 || ret >= end - pos) { 711 end[-1] = '\0'; 712 return buf; 713 } 714 pos += ret; 715 } 716 717 if (cipher & WPA_CIPHER_TKIP) { 718 ret = os_snprintf(pos, end - pos, "%sTKIP", 719 pos == buf ? "" : " "); 720 if (ret < 0 || ret >= end - pos) { 721 end[-1] = '\0'; 722 return buf; 723 } 724 pos += ret; 725 } 726 727 if (cipher & WPA_CIPHER_WEP104) { 728 ret = os_snprintf(pos, end - pos, "%sWEP104", 729 pos == buf ? "" : " "); 730 if (ret < 0 || ret >= end - pos) { 731 end[-1] = '\0'; 732 return buf; 733 } 734 pos += ret; 735 } 736 737 if (cipher & WPA_CIPHER_WEP40) { 738 ret = os_snprintf(pos, end - pos, "%sWEP40", 739 pos == buf ? "" : " "); 740 if (ret < 0 || ret >= end - pos) { 741 end[-1] = '\0'; 742 return buf; 743 } 744 pos += ret; 745 } 746 747 if (cipher & WPA_CIPHER_NONE) { 748 ret = os_snprintf(pos, end - pos, "%sNONE", 749 pos == buf ? "" : " "); 750 if (ret < 0 || ret >= end - pos) { 751 end[-1] = '\0'; 752 return buf; 753 } 754 pos += ret; 755 } 756 757 return buf; 758} 759#endif /* NO_CONFIG_WRITE */ 760 761 762static int wpa_config_parse_pairwise(const struct parse_data *data, 763 struct wpa_ssid *ssid, int line, 764 const char *value) 765{ 766 int val; 767 val = wpa_config_parse_cipher(line, value); 768 if (val == -1) 769 return -1; 770 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) { 771 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher " 772 "(0x%x).", line, val); 773 return -1; 774 } 775 776 wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val); 777 ssid->pairwise_cipher = val; 778 return 0; 779} 780 781 782#ifndef NO_CONFIG_WRITE 783static char * wpa_config_write_pairwise(const struct parse_data *data, 784 struct wpa_ssid *ssid) 785{ 786 return wpa_config_write_cipher(ssid->pairwise_cipher); 787} 788#endif /* NO_CONFIG_WRITE */ 789 790 791static int wpa_config_parse_group(const struct parse_data *data, 792 struct wpa_ssid *ssid, int line, 793 const char *value) 794{ 795 int val; 796 val = wpa_config_parse_cipher(line, value); 797 if (val == -1) 798 return -1; 799 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 | 800 WPA_CIPHER_WEP40)) { 801 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher " 802 "(0x%x).", line, val); 803 return -1; 804 } 805 806 wpa_printf(MSG_MSGDUMP, "group: 0x%x", val); 807 ssid->group_cipher = val; 808 return 0; 809} 810 811 812#ifndef NO_CONFIG_WRITE 813static char * wpa_config_write_group(const struct parse_data *data, 814 struct wpa_ssid *ssid) 815{ 816 return wpa_config_write_cipher(ssid->group_cipher); 817} 818#endif /* NO_CONFIG_WRITE */ 819 820 821static int wpa_config_parse_auth_alg(const struct parse_data *data, 822 struct wpa_ssid *ssid, int line, 823 const char *value) 824{ 825 int val = 0, last, errors = 0; 826 char *start, *end, *buf; 827 828 buf = os_strdup(value); 829 if (buf == NULL) 830 return -1; 831 start = buf; 832 833 while (*start != '\0') { 834 while (*start == ' ' || *start == '\t') 835 start++; 836 if (*start == '\0') 837 break; 838 end = start; 839 while (*end != ' ' && *end != '\t' && *end != '\0') 840 end++; 841 last = *end == '\0'; 842 *end = '\0'; 843 if (os_strcmp(start, "OPEN") == 0) 844 val |= WPA_AUTH_ALG_OPEN; 845 else if (os_strcmp(start, "SHARED") == 0) 846 val |= WPA_AUTH_ALG_SHARED; 847 else if (os_strcmp(start, "LEAP") == 0) 848 val |= WPA_AUTH_ALG_LEAP; 849 else { 850 wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'", 851 line, start); 852 errors++; 853 } 854 855 if (last) 856 break; 857 start = end + 1; 858 } 859 os_free(buf); 860 861 if (val == 0) { 862 wpa_printf(MSG_ERROR, 863 "Line %d: no auth_alg values configured.", line); 864 errors++; 865 } 866 867 wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val); 868 ssid->auth_alg = val; 869 return errors ? -1 : 0; 870} 871 872 873#ifndef NO_CONFIG_WRITE 874static char * wpa_config_write_auth_alg(const struct parse_data *data, 875 struct wpa_ssid *ssid) 876{ 877 char *buf, *pos, *end; 878 int ret; 879 880 pos = buf = os_zalloc(30); 881 if (buf == NULL) 882 return NULL; 883 end = buf + 30; 884 885 if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) { 886 ret = os_snprintf(pos, end - pos, "%sOPEN", 887 pos == buf ? "" : " "); 888 if (ret < 0 || ret >= end - pos) { 889 end[-1] = '\0'; 890 return buf; 891 } 892 pos += ret; 893 } 894 895 if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) { 896 ret = os_snprintf(pos, end - pos, "%sSHARED", 897 pos == buf ? "" : " "); 898 if (ret < 0 || ret >= end - pos) { 899 end[-1] = '\0'; 900 return buf; 901 } 902 pos += ret; 903 } 904 905 if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) { 906 ret = os_snprintf(pos, end - pos, "%sLEAP", 907 pos == buf ? "" : " "); 908 if (ret < 0 || ret >= end - pos) { 909 end[-1] = '\0'; 910 return buf; 911 } 912 pos += ret; 913 } 914 915 return buf; 916} 917#endif /* NO_CONFIG_WRITE */ 918 919 920#ifdef IEEE8021X_EAPOL 921static int wpa_config_parse_eap(const struct parse_data *data, 922 struct wpa_ssid *ssid, int line, 923 const char *value) 924{ 925 int last, errors = 0; 926 char *start, *end, *buf; 927 struct eap_method_type *methods = NULL, *tmp; 928 size_t num_methods = 0; 929 930 buf = os_strdup(value); 931 if (buf == NULL) 932 return -1; 933 start = buf; 934 935 while (*start != '\0') { 936 while (*start == ' ' || *start == '\t') 937 start++; 938 if (*start == '\0') 939 break; 940 end = start; 941 while (*end != ' ' && *end != '\t' && *end != '\0') 942 end++; 943 last = *end == '\0'; 944 *end = '\0'; 945 tmp = methods; 946 methods = os_realloc(methods, 947 (num_methods + 1) * sizeof(*methods)); 948 if (methods == NULL) { 949 os_free(tmp); 950 os_free(buf); 951 return -1; 952 } 953 methods[num_methods].method = eap_peer_get_type( 954 start, &methods[num_methods].vendor); 955 if (methods[num_methods].vendor == EAP_VENDOR_IETF && 956 methods[num_methods].method == EAP_TYPE_NONE) { 957 wpa_printf(MSG_ERROR, "Line %d: unknown EAP method " 958 "'%s'", line, start); 959 wpa_printf(MSG_ERROR, "You may need to add support for" 960 " this EAP method during wpa_supplicant\n" 961 "build time configuration.\n" 962 "See README for more information."); 963 errors++; 964 } else if (methods[num_methods].vendor == EAP_VENDOR_IETF && 965 methods[num_methods].method == EAP_TYPE_LEAP) 966 ssid->leap++; 967 else 968 ssid->non_leap++; 969 num_methods++; 970 if (last) 971 break; 972 start = end + 1; 973 } 974 os_free(buf); 975 976 tmp = methods; 977 methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods)); 978 if (methods == NULL) { 979 os_free(tmp); 980 return -1; 981 } 982 methods[num_methods].vendor = EAP_VENDOR_IETF; 983 methods[num_methods].method = EAP_TYPE_NONE; 984 num_methods++; 985 986 wpa_hexdump(MSG_MSGDUMP, "eap methods", 987 (u8 *) methods, num_methods * sizeof(*methods)); 988 ssid->eap.eap_methods = methods; 989 return errors ? -1 : 0; 990} 991 992 993#ifndef NO_CONFIG_WRITE 994static char * wpa_config_write_eap(const struct parse_data *data, 995 struct wpa_ssid *ssid) 996{ 997 int i, ret; 998 char *buf, *pos, *end; 999 const struct eap_method_type *eap_methods = ssid->eap.eap_methods; 1000 const char *name; 1001 1002 if (eap_methods == NULL) 1003 return NULL; 1004 1005 pos = buf = os_zalloc(100); 1006 if (buf == NULL) 1007 return NULL; 1008 end = buf + 100; 1009 1010 for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF || 1011 eap_methods[i].method != EAP_TYPE_NONE; i++) { 1012 name = eap_get_name(eap_methods[i].vendor, 1013 eap_methods[i].method); 1014 if (name) { 1015 ret = os_snprintf(pos, end - pos, "%s%s", 1016 pos == buf ? "" : " ", name); 1017 if (ret < 0 || ret >= end - pos) 1018 break; 1019 pos += ret; 1020 } 1021 } 1022 1023 end[-1] = '\0'; 1024 1025 return buf; 1026} 1027#endif 1028 1029 1030static int wpa_config_parse_password(const struct parse_data *data, 1031 struct wpa_ssid *ssid, int line, 1032 const char *value) 1033{ 1034 u8 *hash; 1035 1036 if (os_strcmp(value, "NULL") == 0) { 1037 wpa_printf(MSG_DEBUG, "Unset configuration string 'password'"); 1038 os_free(ssid->eap.password); 1039 ssid->eap.password = NULL; 1040 ssid->eap.password_len = 0; 1041 return 0; 1042 } 1043 1044 if (os_strncmp(value, "hash:", 5) != 0) { 1045 char *tmp; 1046 size_t res_len; 1047 1048 tmp = wpa_config_parse_string(value, &res_len); 1049 if (tmp == NULL) { 1050 wpa_printf(MSG_ERROR, "Line %d: failed to parse " 1051 "password.", line); 1052 return -1; 1053 } 1054 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, 1055 (u8 *) tmp, res_len); 1056 1057 os_free(ssid->eap.password); 1058 ssid->eap.password = (u8 *) tmp; 1059 ssid->eap.password_len = res_len; 1060 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; 1061 1062 return 0; 1063 } 1064 1065 1066 /* NtPasswordHash: hash:<32 hex digits> */ 1067 if (os_strlen(value + 5) != 2 * 16) { 1068 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length " 1069 "(expected 32 hex digits)", line); 1070 return -1; 1071 } 1072 1073 hash = os_malloc(16); 1074 if (hash == NULL) 1075 return -1; 1076 1077 if (hexstr2bin(value + 5, hash, 16)) { 1078 os_free(hash); 1079 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line); 1080 return -1; 1081 } 1082 1083 wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16); 1084 1085 os_free(ssid->eap.password); 1086 ssid->eap.password = hash; 1087 ssid->eap.password_len = 16; 1088 ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH; 1089 1090 return 0; 1091} 1092 1093 1094#ifndef NO_CONFIG_WRITE 1095static char * wpa_config_write_password(const struct parse_data *data, 1096 struct wpa_ssid *ssid) 1097{ 1098 char *buf; 1099 1100 if (ssid->eap.password == NULL) 1101 return NULL; 1102 1103 if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) { 1104 return wpa_config_write_string( 1105 ssid->eap.password, ssid->eap.password_len); 1106 } 1107 1108 buf = os_malloc(5 + 32 + 1); 1109 if (buf == NULL) 1110 return NULL; 1111 1112 os_memcpy(buf, "hash:", 5); 1113 wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16); 1114 1115 return buf; 1116} 1117#endif 1118#endif /* IEEE8021X_EAPOL */ 1119 1120 1121static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, 1122 const char *value, int idx) 1123{ 1124 char *buf, title[20]; 1125 int res; 1126 1127 buf = wpa_config_parse_string(value, len); 1128 if (buf == NULL) { 1129 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.", 1130 line, idx, value); 1131 return -1; 1132 } 1133 if (*len > MAX_WEP_KEY_LEN) { 1134 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.", 1135 line, idx, value); 1136 os_free(buf); 1137 return -1; 1138 } 1139 os_memcpy(key, buf, *len); 1140 os_free(buf); 1141 res = os_snprintf(title, sizeof(title), "wep_key%d", idx); 1142 if (res >= 0 && (size_t) res < sizeof(title)) 1143 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len); 1144 return 0; 1145} 1146 1147 1148static int wpa_config_parse_wep_key0(const struct parse_data *data, 1149 struct wpa_ssid *ssid, int line, 1150 const char *value) 1151{ 1152 return wpa_config_parse_wep_key(ssid->wep_key[0], 1153 &ssid->wep_key_len[0], line, 1154 value, 0); 1155} 1156 1157 1158static int wpa_config_parse_wep_key1(const struct parse_data *data, 1159 struct wpa_ssid *ssid, int line, 1160 const char *value) 1161{ 1162 return wpa_config_parse_wep_key(ssid->wep_key[1], 1163 &ssid->wep_key_len[1], line, 1164 value, 1); 1165} 1166 1167 1168static int wpa_config_parse_wep_key2(const struct parse_data *data, 1169 struct wpa_ssid *ssid, int line, 1170 const char *value) 1171{ 1172 return wpa_config_parse_wep_key(ssid->wep_key[2], 1173 &ssid->wep_key_len[2], line, 1174 value, 2); 1175} 1176 1177 1178static int wpa_config_parse_wep_key3(const struct parse_data *data, 1179 struct wpa_ssid *ssid, int line, 1180 const char *value) 1181{ 1182 return wpa_config_parse_wep_key(ssid->wep_key[3], 1183 &ssid->wep_key_len[3], line, 1184 value, 3); 1185} 1186 1187 1188#ifndef NO_CONFIG_WRITE 1189static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx) 1190{ 1191 if (ssid->wep_key_len[idx] == 0) 1192 return NULL; 1193 return wpa_config_write_string(ssid->wep_key[idx], 1194 ssid->wep_key_len[idx]); 1195} 1196 1197 1198static char * wpa_config_write_wep_key0(const struct parse_data *data, 1199 struct wpa_ssid *ssid) 1200{ 1201 return wpa_config_write_wep_key(ssid, 0); 1202} 1203 1204 1205static char * wpa_config_write_wep_key1(const struct parse_data *data, 1206 struct wpa_ssid *ssid) 1207{ 1208 return wpa_config_write_wep_key(ssid, 1); 1209} 1210 1211 1212static char * wpa_config_write_wep_key2(const struct parse_data *data, 1213 struct wpa_ssid *ssid) 1214{ 1215 return wpa_config_write_wep_key(ssid, 2); 1216} 1217 1218 1219static char * wpa_config_write_wep_key3(const struct parse_data *data, 1220 struct wpa_ssid *ssid) 1221{ 1222 return wpa_config_write_wep_key(ssid, 3); 1223} 1224#endif /* NO_CONFIG_WRITE */ 1225 1226 1227/* Helper macros for network block parser */ 1228 1229#ifdef OFFSET 1230#undef OFFSET 1231#endif /* OFFSET */ 1232/* OFFSET: Get offset of a variable within the wpa_ssid structure */ 1233#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v) 1234 1235/* STR: Define a string variable for an ASCII string; f = field name */ 1236#ifdef NO_CONFIG_WRITE 1237#define _STR(f) #f, wpa_config_parse_str, OFFSET(f) 1238#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f) 1239#else /* NO_CONFIG_WRITE */ 1240#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f) 1241#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f) 1242#endif /* NO_CONFIG_WRITE */ 1243#define STR(f) _STR(f), NULL, NULL, NULL, 0 1244#define STRe(f) _STRe(f), NULL, NULL, NULL, 0 1245#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1 1246#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1 1247 1248/* STR_LEN: Define a string variable with a separate variable for storing the 1249 * data length. Unlike STR(), this can be used to store arbitrary binary data 1250 * (i.e., even nul termination character). */ 1251#define _STR_LEN(f) _STR(f), OFFSET(f ## _len) 1252#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len) 1253#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0 1254#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0 1255#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1 1256 1257/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length 1258 * explicitly specified. */ 1259#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max) 1260#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0 1261#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1 1262 1263#ifdef NO_CONFIG_WRITE 1264#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0 1265#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0 1266#else /* NO_CONFIG_WRITE */ 1267#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 1268 OFFSET(f), (void *) 0 1269#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 1270 OFFSET(eap.f), (void *) 0 1271#endif /* NO_CONFIG_WRITE */ 1272 1273/* INT: Define an integer variable */ 1274#define INT(f) _INT(f), NULL, NULL, 0 1275#define INTe(f) _INTe(f), NULL, NULL, 0 1276 1277/* INT_RANGE: Define an integer variable with allowed value range */ 1278#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0 1279 1280/* FUNC: Define a configuration variable that uses a custom function for 1281 * parsing and writing the value. */ 1282#ifdef NO_CONFIG_WRITE 1283#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL 1284#else /* NO_CONFIG_WRITE */ 1285#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \ 1286 NULL, NULL, NULL, NULL 1287#endif /* NO_CONFIG_WRITE */ 1288#define FUNC(f) _FUNC(f), 0 1289#define FUNC_KEY(f) _FUNC(f), 1 1290 1291/* 1292 * Table of network configuration variables. This table is used to parse each 1293 * network configuration variable, e.g., each line in wpa_supplicant.conf file 1294 * that is inside a network block. 1295 * 1296 * This table is generated using the helper macros defined above and with 1297 * generous help from the C pre-processor. The field name is stored as a string 1298 * into .name and for STR and INT types, the offset of the target buffer within 1299 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar 1300 * offset to the field containing the length of the configuration variable. 1301 * .param3 and .param4 can be used to mark the allowed range (length for STR 1302 * and value for INT). 1303 * 1304 * For each configuration line in wpa_supplicant.conf, the parser goes through 1305 * this table and select the entry that matches with the field name. The parser 1306 * function (.parser) is then called to parse the actual value of the field. 1307 * 1308 * This kind of mechanism makes it easy to add new configuration parameters, 1309 * since only one line needs to be added into this table and into the 1310 * struct wpa_ssid definition if the new variable is either a string or 1311 * integer. More complex types will need to use their own parser and writer 1312 * functions. 1313 */ 1314static const struct parse_data ssid_fields[] = { 1315 { STR_RANGE(ssid, 0, MAX_SSID_LEN) }, 1316 { INT_RANGE(scan_ssid, 0, 1) }, 1317 { FUNC(bssid) }, 1318 { FUNC_KEY(psk) }, 1319 { FUNC(proto) }, 1320 { FUNC(key_mgmt) }, 1321 { FUNC(pairwise) }, 1322 { FUNC(group) }, 1323 { FUNC(auth_alg) }, 1324#ifdef IEEE8021X_EAPOL 1325 { FUNC(eap) }, 1326 { STR_LENe(identity) }, 1327 { STR_LENe(anonymous_identity) }, 1328 { FUNC_KEY(password) }, 1329 { STRe(ca_cert) }, 1330 { STRe(ca_path) }, 1331 { STRe(client_cert) }, 1332 { STRe(private_key) }, 1333 { STR_KEYe(private_key_passwd) }, 1334 { STRe(dh_file) }, 1335 { STRe(subject_match) }, 1336 { STRe(altsubject_match) }, 1337 { STRe(ca_cert2) }, 1338 { STRe(ca_path2) }, 1339 { STRe(client_cert2) }, 1340 { STRe(private_key2) }, 1341 { STR_KEYe(private_key2_passwd) }, 1342 { STRe(dh_file2) }, 1343 { STRe(subject_match2) }, 1344 { STRe(altsubject_match2) }, 1345 { STRe(phase1) }, 1346 { STRe(phase2) }, 1347 { STRe(pcsc) }, 1348 { STR_KEYe(pin) }, 1349 { STRe(engine_id) }, 1350 { STRe(key_id) }, 1351 { STRe(cert_id) }, 1352 { STRe(ca_cert_id) }, 1353 { STR_KEYe(pin2) }, 1354 { STRe(engine2_id) }, 1355 { STRe(key2_id) }, 1356 { STRe(cert2_id) }, 1357 { STRe(ca_cert2_id) }, 1358 { INTe(engine) }, 1359 { INTe(engine2) }, 1360 { INT(eapol_flags) }, 1361#endif /* IEEE8021X_EAPOL */ 1362 { FUNC_KEY(wep_key0) }, 1363 { FUNC_KEY(wep_key1) }, 1364 { FUNC_KEY(wep_key2) }, 1365 { FUNC_KEY(wep_key3) }, 1366 { INT(wep_tx_keyidx) }, 1367 { INT(priority) }, 1368#ifdef IEEE8021X_EAPOL 1369 { INT(eap_workaround) }, 1370 { STRe(pac_file) }, 1371 { INTe(fragment_size) }, 1372#endif /* IEEE8021X_EAPOL */ 1373 { INT_RANGE(mode, 0, 1) }, 1374 { INT_RANGE(proactive_key_caching, 0, 1) }, 1375 { INT_RANGE(disabled, 0, 1) }, 1376 { STR(id_str) }, 1377#ifdef CONFIG_IEEE80211W 1378 { INT_RANGE(ieee80211w, 0, 2) }, 1379#endif /* CONFIG_IEEE80211W */ 1380 { INT_RANGE(peerkey, 0, 1) }, 1381 { INT_RANGE(mixed_cell, 0, 1) }, 1382 { INT_RANGE(frequency, 0, 10000) }, 1383 { INT(wpa_ptk_rekey) } 1384}; 1385 1386#undef OFFSET 1387#undef _STR 1388#undef STR 1389#undef STR_KEY 1390#undef _STR_LEN 1391#undef STR_LEN 1392#undef STR_LEN_KEY 1393#undef _STR_RANGE 1394#undef STR_RANGE 1395#undef STR_RANGE_KEY 1396#undef _INT 1397#undef INT 1398#undef INT_RANGE 1399#undef _FUNC 1400#undef FUNC 1401#undef FUNC_KEY 1402#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0])) 1403 1404 1405/** 1406 * wpa_config_add_prio_network - Add a network to priority lists 1407 * @config: Configuration data from wpa_config_read() 1408 * @ssid: Pointer to the network configuration to be added to the list 1409 * Returns: 0 on success, -1 on failure 1410 * 1411 * This function is used to add a network block to the priority list of 1412 * networks. This must be called for each network when reading in the full 1413 * configuration. In addition, this can be used indirectly when updating 1414 * priorities by calling wpa_config_update_prio_list(). 1415 */ 1416int wpa_config_add_prio_network(struct wpa_config *config, 1417 struct wpa_ssid *ssid) 1418{ 1419 int prio; 1420 struct wpa_ssid *prev, **nlist; 1421 1422 /* 1423 * Add to an existing priority list if one is available for the 1424 * configured priority level for this network. 1425 */ 1426 for (prio = 0; prio < config->num_prio; prio++) { 1427 prev = config->pssid[prio]; 1428 if (prev->priority == ssid->priority) { 1429 while (prev->pnext) 1430 prev = prev->pnext; 1431 prev->pnext = ssid; 1432 return 0; 1433 } 1434 } 1435 1436 /* First network for this priority - add a new priority list */ 1437 nlist = os_realloc(config->pssid, 1438 (config->num_prio + 1) * sizeof(struct wpa_ssid *)); 1439 if (nlist == NULL) 1440 return -1; 1441 1442 for (prio = 0; prio < config->num_prio; prio++) { 1443 if (nlist[prio]->priority < ssid->priority) 1444 break; 1445 } 1446 1447 os_memmove(&nlist[prio + 1], &nlist[prio], 1448 (config->num_prio - prio) * sizeof(struct wpa_ssid *)); 1449 1450 nlist[prio] = ssid; 1451 config->num_prio++; 1452 config->pssid = nlist; 1453 1454 return 0; 1455} 1456 1457 1458/** 1459 * wpa_config_update_prio_list - Update network priority list 1460 * @config: Configuration data from wpa_config_read() 1461 * Returns: 0 on success, -1 on failure 1462 * 1463 * This function is called to update the priority list of networks in the 1464 * configuration when a network is being added or removed. This is also called 1465 * if a priority for a network is changed. 1466 */ 1467static int wpa_config_update_prio_list(struct wpa_config *config) 1468{ 1469 struct wpa_ssid *ssid; 1470 int ret = 0; 1471 1472 os_free(config->pssid); 1473 config->pssid = NULL; 1474 config->num_prio = 0; 1475 1476 ssid = config->ssid; 1477 while (ssid) { 1478 ssid->pnext = NULL; 1479 if (wpa_config_add_prio_network(config, ssid) < 0) 1480 ret = -1; 1481 ssid = ssid->next; 1482 } 1483 1484 return ret; 1485} 1486 1487 1488#ifdef IEEE8021X_EAPOL 1489static void eap_peer_config_free(struct eap_peer_config *eap) 1490{ 1491 os_free(eap->eap_methods); 1492 os_free(eap->identity); 1493 os_free(eap->anonymous_identity); 1494 os_free(eap->password); 1495 os_free(eap->ca_cert); 1496 os_free(eap->ca_path); 1497 os_free(eap->client_cert); 1498 os_free(eap->private_key); 1499 os_free(eap->private_key_passwd); 1500 os_free(eap->dh_file); 1501 os_free(eap->subject_match); 1502 os_free(eap->altsubject_match); 1503 os_free(eap->ca_cert2); 1504 os_free(eap->ca_path2); 1505 os_free(eap->client_cert2); 1506 os_free(eap->private_key2); 1507 os_free(eap->private_key2_passwd); 1508 os_free(eap->dh_file2); 1509 os_free(eap->subject_match2); 1510 os_free(eap->altsubject_match2); 1511 os_free(eap->phase1); 1512 os_free(eap->phase2); 1513 os_free(eap->pcsc); 1514 os_free(eap->pin); 1515 os_free(eap->engine_id); 1516 os_free(eap->key_id); 1517 os_free(eap->cert_id); 1518 os_free(eap->ca_cert_id); 1519 os_free(eap->key2_id); 1520 os_free(eap->cert2_id); 1521 os_free(eap->ca_cert2_id); 1522 os_free(eap->pin2); 1523 os_free(eap->engine2_id); 1524 os_free(eap->otp); 1525 os_free(eap->pending_req_otp); 1526 os_free(eap->pac_file); 1527 os_free(eap->new_password); 1528} 1529#endif /* IEEE8021X_EAPOL */ 1530 1531 1532/** 1533 * wpa_config_free_ssid - Free network/ssid configuration data 1534 * @ssid: Configuration data for the network 1535 * 1536 * This function frees all resources allocated for the network configuration 1537 * data. 1538 */ 1539void wpa_config_free_ssid(struct wpa_ssid *ssid) 1540{ 1541 os_free(ssid->ssid); 1542 os_free(ssid->passphrase); 1543#ifdef IEEE8021X_EAPOL 1544 eap_peer_config_free(&ssid->eap); 1545#endif /* IEEE8021X_EAPOL */ 1546 os_free(ssid->id_str); 1547 os_free(ssid); 1548} 1549 1550 1551/** 1552 * wpa_config_free - Free configuration data 1553 * @config: Configuration data from wpa_config_read() 1554 * 1555 * This function frees all resources allocated for the configuration data by 1556 * wpa_config_read(). 1557 */ 1558void wpa_config_free(struct wpa_config *config) 1559{ 1560#ifndef CONFIG_NO_CONFIG_BLOBS 1561 struct wpa_config_blob *blob, *prevblob; 1562#endif /* CONFIG_NO_CONFIG_BLOBS */ 1563 struct wpa_ssid *ssid, *prev = NULL; 1564 ssid = config->ssid; 1565 while (ssid) { 1566 prev = ssid; 1567 ssid = ssid->next; 1568 wpa_config_free_ssid(prev); 1569 } 1570 1571#ifndef CONFIG_NO_CONFIG_BLOBS 1572 blob = config->blobs; 1573 prevblob = NULL; 1574 while (blob) { 1575 prevblob = blob; 1576 blob = blob->next; 1577 wpa_config_free_blob(prevblob); 1578 } 1579#endif /* CONFIG_NO_CONFIG_BLOBS */ 1580 1581 os_free(config->ctrl_interface); 1582 os_free(config->ctrl_interface_group); 1583#ifdef EAP_TLS_OPENSSL 1584 os_free(config->opensc_engine_path); 1585 os_free(config->pkcs11_engine_path); 1586 os_free(config->pkcs11_module_path); 1587#endif /* EAP_TLS_OPENSSL */ 1588 os_free(config->driver_param); 1589 os_free(config->device_name); 1590 os_free(config->manufacturer); 1591 os_free(config->model_name); 1592 os_free(config->model_number); 1593 os_free(config->serial_number); 1594 os_free(config->device_type); 1595 os_free(config->pssid); 1596 os_free(config); 1597} 1598 1599 1600/** 1601 * wpa_config_get_network - Get configured network based on id 1602 * @config: Configuration data from wpa_config_read() 1603 * @id: Unique network id to search for 1604 * Returns: Network configuration or %NULL if not found 1605 */ 1606struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id) 1607{ 1608 struct wpa_ssid *ssid; 1609 1610 ssid = config->ssid; 1611 while (ssid) { 1612 if (id == ssid->id) 1613 break; 1614 ssid = ssid->next; 1615 } 1616 1617 return ssid; 1618} 1619 1620 1621/** 1622 * wpa_config_add_network - Add a new network with empty configuration 1623 * @config: Configuration data from wpa_config_read() 1624 * Returns: The new network configuration or %NULL if operation failed 1625 */ 1626struct wpa_ssid * wpa_config_add_network(struct wpa_config *config) 1627{ 1628 int id; 1629 struct wpa_ssid *ssid, *last = NULL; 1630 1631 id = -1; 1632 ssid = config->ssid; 1633 while (ssid) { 1634 if (ssid->id > id) 1635 id = ssid->id; 1636 last = ssid; 1637 ssid = ssid->next; 1638 } 1639 id++; 1640 1641 ssid = os_zalloc(sizeof(*ssid)); 1642 if (ssid == NULL) 1643 return NULL; 1644 ssid->id = id; 1645 if (last) 1646 last->next = ssid; 1647 else 1648 config->ssid = ssid; 1649 1650 wpa_config_update_prio_list(config); 1651 1652 return ssid; 1653} 1654 1655 1656/** 1657 * wpa_config_remove_network - Remove a configured network based on id 1658 * @config: Configuration data from wpa_config_read() 1659 * @id: Unique network id to search for 1660 * Returns: 0 on success, or -1 if the network was not found 1661 */ 1662int wpa_config_remove_network(struct wpa_config *config, int id) 1663{ 1664 struct wpa_ssid *ssid, *prev = NULL; 1665 1666 ssid = config->ssid; 1667 while (ssid) { 1668 if (id == ssid->id) 1669 break; 1670 prev = ssid; 1671 ssid = ssid->next; 1672 } 1673 1674 if (ssid == NULL) 1675 return -1; 1676 1677 if (prev) 1678 prev->next = ssid->next; 1679 else 1680 config->ssid = ssid->next; 1681 1682 wpa_config_update_prio_list(config); 1683 wpa_config_free_ssid(ssid); 1684 return 0; 1685} 1686 1687 1688/** 1689 * wpa_config_set_network_defaults - Set network default values 1690 * @ssid: Pointer to network configuration data 1691 */ 1692void wpa_config_set_network_defaults(struct wpa_ssid *ssid) 1693{ 1694 ssid->proto = DEFAULT_PROTO; 1695 ssid->pairwise_cipher = DEFAULT_PAIRWISE; 1696 ssid->group_cipher = DEFAULT_GROUP; 1697 ssid->key_mgmt = DEFAULT_KEY_MGMT; 1698#ifdef IEEE8021X_EAPOL 1699 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; 1700 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; 1701 ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE; 1702#endif /* IEEE8021X_EAPOL */ 1703} 1704 1705 1706/** 1707 * wpa_config_set - Set a variable in network configuration 1708 * @ssid: Pointer to network configuration data 1709 * @var: Variable name, e.g., "ssid" 1710 * @value: Variable value 1711 * @line: Line number in configuration file or 0 if not used 1712 * Returns: 0 on success, -1 on failure 1713 * 1714 * This function can be used to set network configuration variables based on 1715 * both the configuration file and management interface input. The value 1716 * parameter must be in the same format as the text-based configuration file is 1717 * using. For example, strings are using double quotation marks. 1718 */ 1719int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, 1720 int line) 1721{ 1722 size_t i; 1723 int ret = 0; 1724 1725 if (ssid == NULL || var == NULL || value == NULL) 1726 return -1; 1727 1728 for (i = 0; i < NUM_SSID_FIELDS; i++) { 1729 const struct parse_data *field = &ssid_fields[i]; 1730 if (os_strcmp(var, field->name) != 0) 1731 continue; 1732 1733 if (field->parser(field, ssid, line, value)) { 1734 if (line) { 1735 wpa_printf(MSG_ERROR, "Line %d: failed to " 1736 "parse %s '%s'.", line, var, value); 1737 } 1738 ret = -1; 1739 } 1740 break; 1741 } 1742 if (i == NUM_SSID_FIELDS) { 1743 if (line) { 1744 wpa_printf(MSG_ERROR, "Line %d: unknown network field " 1745 "'%s'.", line, var); 1746 } 1747 ret = -1; 1748 } 1749 1750 return ret; 1751} 1752 1753 1754#ifndef NO_CONFIG_WRITE 1755/** 1756 * wpa_config_get - Get a variable in network configuration 1757 * @ssid: Pointer to network configuration data 1758 * @var: Variable name, e.g., "ssid" 1759 * Returns: Value of the variable or %NULL on failure 1760 * 1761 * This function can be used to get network configuration variables. The 1762 * returned value is a copy of the configuration variable in text format, i.e,. 1763 * the same format that the text-based configuration file and wpa_config_set() 1764 * are using for the value. The caller is responsible for freeing the returned 1765 * value. 1766 */ 1767char * wpa_config_get(struct wpa_ssid *ssid, const char *var) 1768{ 1769 size_t i; 1770 1771 if (ssid == NULL || var == NULL) 1772 return NULL; 1773 1774 for (i = 0; i < NUM_SSID_FIELDS; i++) { 1775 const struct parse_data *field = &ssid_fields[i]; 1776 if (os_strcmp(var, field->name) == 0) 1777 return field->writer(field, ssid); 1778 } 1779 1780 return NULL; 1781} 1782 1783 1784/** 1785 * wpa_config_get_no_key - Get a variable in network configuration (no keys) 1786 * @ssid: Pointer to network configuration data 1787 * @var: Variable name, e.g., "ssid" 1788 * Returns: Value of the variable or %NULL on failure 1789 * 1790 * This function can be used to get network configuration variable like 1791 * wpa_config_get(). The only difference is that this functions does not expose 1792 * key/password material from the configuration. In case a key/password field 1793 * is requested, the returned value is an empty string or %NULL if the variable 1794 * is not set or "*" if the variable is set (regardless of its value). The 1795 * returned value is a copy of the configuration variable in text format, i.e,. 1796 * the same format that the text-based configuration file and wpa_config_set() 1797 * are using for the value. The caller is responsible for freeing the returned 1798 * value. 1799 */ 1800char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var) 1801{ 1802 size_t i; 1803 1804 if (ssid == NULL || var == NULL) 1805 return NULL; 1806 1807 for (i = 0; i < NUM_SSID_FIELDS; i++) { 1808 const struct parse_data *field = &ssid_fields[i]; 1809 if (os_strcmp(var, field->name) == 0) { 1810 char *res = field->writer(field, ssid); 1811 if (field->key_data) { 1812 if (res && res[0]) { 1813 wpa_printf(MSG_DEBUG, "Do not allow " 1814 "key_data field to be " 1815 "exposed"); 1816 os_free(res); 1817 return os_strdup("*"); 1818 } 1819 1820 os_free(res); 1821 return NULL; 1822 } 1823 return res; 1824 } 1825 } 1826 1827 return NULL; 1828} 1829#endif /* NO_CONFIG_WRITE */ 1830 1831 1832/** 1833 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID 1834 * @ssid: Pointer to network configuration data 1835 * 1836 * This function must be called to update WPA PSK when either SSID or the 1837 * passphrase has changed for the network configuration. 1838 */ 1839void wpa_config_update_psk(struct wpa_ssid *ssid) 1840{ 1841#ifndef CONFIG_NO_PBKDF2 1842 pbkdf2_sha1(ssid->passphrase, 1843 (char *) ssid->ssid, ssid->ssid_len, 4096, 1844 ssid->psk, PMK_LEN); 1845 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", 1846 ssid->psk, PMK_LEN); 1847 ssid->psk_set = 1; 1848#endif /* CONFIG_NO_PBKDF2 */ 1849} 1850 1851 1852#ifndef CONFIG_NO_CONFIG_BLOBS 1853/** 1854 * wpa_config_get_blob - Get a named configuration blob 1855 * @config: Configuration data from wpa_config_read() 1856 * @name: Name of the blob 1857 * Returns: Pointer to blob data or %NULL if not found 1858 */ 1859const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config, 1860 const char *name) 1861{ 1862 struct wpa_config_blob *blob = config->blobs; 1863 1864 while (blob) { 1865 if (os_strcmp(blob->name, name) == 0) 1866 return blob; 1867 blob = blob->next; 1868 } 1869 return NULL; 1870} 1871 1872 1873/** 1874 * wpa_config_set_blob - Set or add a named configuration blob 1875 * @config: Configuration data from wpa_config_read() 1876 * @blob: New value for the blob 1877 * 1878 * Adds a new configuration blob or replaces the current value of an existing 1879 * blob. 1880 */ 1881void wpa_config_set_blob(struct wpa_config *config, 1882 struct wpa_config_blob *blob) 1883{ 1884 wpa_config_remove_blob(config, blob->name); 1885 blob->next = config->blobs; 1886 config->blobs = blob; 1887} 1888 1889 1890/** 1891 * wpa_config_free_blob - Free blob data 1892 * @blob: Pointer to blob to be freed 1893 */ 1894void wpa_config_free_blob(struct wpa_config_blob *blob) 1895{ 1896 if (blob) { 1897 os_free(blob->name); 1898 os_free(blob->data); 1899 os_free(blob); 1900 } 1901} 1902 1903 1904/** 1905 * wpa_config_remove_blob - Remove a named configuration blob 1906 * @config: Configuration data from wpa_config_read() 1907 * @name: Name of the blob to remove 1908 * Returns: 0 if blob was removed or -1 if blob was not found 1909 */ 1910int wpa_config_remove_blob(struct wpa_config *config, const char *name) 1911{ 1912 struct wpa_config_blob *pos = config->blobs, *prev = NULL; 1913 1914 while (pos) { 1915 if (os_strcmp(pos->name, name) == 0) { 1916 if (prev) 1917 prev->next = pos->next; 1918 else 1919 config->blobs = pos->next; 1920 wpa_config_free_blob(pos); 1921 return 0; 1922 } 1923 prev = pos; 1924 pos = pos->next; 1925 } 1926 1927 return -1; 1928} 1929#endif /* CONFIG_NO_CONFIG_BLOBS */ 1930 1931 1932/** 1933 * wpa_config_alloc_empty - Allocate an empty configuration 1934 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain 1935 * socket 1936 * @driver_param: Driver parameters 1937 * Returns: Pointer to allocated configuration data or %NULL on failure 1938 */ 1939struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, 1940 const char *driver_param) 1941{ 1942 struct wpa_config *config; 1943 1944 config = os_zalloc(sizeof(*config)); 1945 if (config == NULL) 1946 return NULL; 1947 config->eapol_version = DEFAULT_EAPOL_VERSION; 1948 config->ap_scan = DEFAULT_AP_SCAN; 1949 config->fast_reauth = DEFAULT_FAST_REAUTH; 1950 1951 if (ctrl_interface) 1952 config->ctrl_interface = os_strdup(ctrl_interface); 1953 if (driver_param) 1954 config->driver_param = os_strdup(driver_param); 1955 1956 return config; 1957} 1958 1959 1960#ifndef CONFIG_NO_STDOUT_DEBUG 1961/** 1962 * wpa_config_debug_dump_networks - Debug dump of configured networks 1963 * @config: Configuration data from wpa_config_read() 1964 */ 1965void wpa_config_debug_dump_networks(struct wpa_config *config) 1966{ 1967 int prio; 1968 struct wpa_ssid *ssid; 1969 1970 for (prio = 0; prio < config->num_prio; prio++) { 1971 ssid = config->pssid[prio]; 1972 wpa_printf(MSG_DEBUG, "Priority group %d", 1973 ssid->priority); 1974 while (ssid) { 1975 wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", 1976 ssid->id, 1977 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 1978 ssid = ssid->pnext; 1979 } 1980 } 1981} 1982#endif /* CONFIG_NO_STDOUT_DEBUG */ 1983