config.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
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 "utils/uuid.h" 19#include "crypto/sha1.h" 20#include "rsn_supp/wpa.h" 21#include "eap_peer/eap.h" 22#include "config.h" 23 24 25#if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE) 26#define NO_CONFIG_WRITE 27#endif 28 29/* 30 * Structure for network configuration parsing. This data is used to implement 31 * a generic parser for each network block variable. The table of configuration 32 * variables is defined below in this file (ssid_fields[]). 33 */ 34struct parse_data { 35 /* Configuration variable name */ 36 char *name; 37 38 /* Parser function for this variable */ 39 int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid, 40 int line, const char *value); 41 42#ifndef NO_CONFIG_WRITE 43 /* Writer function (i.e., to get the variable in text format from 44 * internal presentation). */ 45 char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid); 46#endif /* NO_CONFIG_WRITE */ 47 48 /* Variable specific parameters for the parser. */ 49 void *param1, *param2, *param3, *param4; 50 51 /* 0 = this variable can be included in debug output and ctrl_iface 52 * 1 = this variable contains key/private data and it must not be 53 * included in debug output unless explicitly requested. In 54 * addition, this variable will not be readable through the 55 * ctrl_iface. 56 */ 57 int key_data; 58}; 59 60 61static char * wpa_config_parse_string(const char *value, size_t *len) 62{ 63 if (*value == '"') { 64 const char *pos; 65 char *str; 66 value++; 67 pos = os_strrchr(value, '"'); 68 if (pos == NULL || pos[1] != '\0') 69 return NULL; 70 *len = pos - value; 71 str = os_malloc(*len + 1); 72 if (str == NULL) 73 return NULL; 74 os_memcpy(str, value, *len); 75 str[*len] = '\0'; 76 return str; 77 } else { 78 u8 *str; 79 size_t tlen, hlen = os_strlen(value); 80 if (hlen & 1) 81 return NULL; 82 tlen = hlen / 2; 83 str = os_malloc(tlen + 1); 84 if (str == NULL) 85 return NULL; 86 if (hexstr2bin(value, str, tlen)) { 87 os_free(str); 88 return NULL; 89 } 90 str[tlen] = '\0'; 91 *len = tlen; 92 return (char *) str; 93 } 94} 95 96 97static int wpa_config_parse_str(const struct parse_data *data, 98 struct wpa_ssid *ssid, 99 int line, const char *value) 100{ 101 size_t res_len, *dst_len; 102 char **dst, *tmp; 103 104 if (os_strcmp(value, "NULL") == 0) { 105 wpa_printf(MSG_DEBUG, "Unset configuration string '%s'", 106 data->name); 107 tmp = NULL; 108 res_len = 0; 109 goto set; 110 } 111 112 tmp = wpa_config_parse_string(value, &res_len); 113 if (tmp == NULL) { 114 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.", 115 line, data->name, 116 data->key_data ? "[KEY DATA REMOVED]" : value); 117 return -1; 118 } 119 120 if (data->key_data) { 121 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, 122 (u8 *) tmp, res_len); 123 } else { 124 wpa_hexdump_ascii(MSG_MSGDUMP, data->name, 125 (u8 *) tmp, res_len); 126 } 127 128 if (data->param3 && res_len < (size_t) data->param3) { 129 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " 130 "min_len=%ld)", line, data->name, 131 (unsigned long) res_len, (long) data->param3); 132 os_free(tmp); 133 return -1; 134 } 135 136 if (data->param4 && res_len > (size_t) data->param4) { 137 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " 138 "max_len=%ld)", line, data->name, 139 (unsigned long) res_len, (long) data->param4); 140 os_free(tmp); 141 return -1; 142 } 143 144set: 145 dst = (char **) (((u8 *) ssid) + (long) data->param1); 146 dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2); 147 os_free(*dst); 148 *dst = tmp; 149 if (data->param2) 150 *dst_len = res_len; 151 152 return 0; 153} 154 155 156#ifndef NO_CONFIG_WRITE 157static int is_hex(const u8 *data, size_t len) 158{ 159 size_t i; 160 161 for (i = 0; i < len; i++) { 162 if (data[i] < 32 || data[i] >= 127) 163 return 1; 164 } 165 return 0; 166} 167 168 169static char * wpa_config_write_string_ascii(const u8 *value, size_t len) 170{ 171 char *buf; 172 173 buf = os_malloc(len + 3); 174 if (buf == NULL) 175 return NULL; 176 buf[0] = '"'; 177 os_memcpy(buf + 1, value, len); 178 buf[len + 1] = '"'; 179 buf[len + 2] = '\0'; 180 181 return buf; 182} 183 184 185static char * wpa_config_write_string_hex(const u8 *value, size_t len) 186{ 187 char *buf; 188 189 buf = os_zalloc(2 * len + 1); 190 if (buf == NULL) 191 return NULL; 192 wpa_snprintf_hex(buf, 2 * len + 1, value, len); 193 194 return buf; 195} 196 197 198static char * wpa_config_write_string(const u8 *value, size_t len) 199{ 200 if (value == NULL) 201 return NULL; 202 203 if (is_hex(value, len)) 204 return wpa_config_write_string_hex(value, len); 205 else 206 return wpa_config_write_string_ascii(value, len); 207} 208 209 210static char * wpa_config_write_str(const struct parse_data *data, 211 struct wpa_ssid *ssid) 212{ 213 size_t len; 214 char **src; 215 216 src = (char **) (((u8 *) ssid) + (long) data->param1); 217 if (*src == NULL) 218 return NULL; 219 220 if (data->param2) 221 len = *((size_t *) (((u8 *) ssid) + (long) data->param2)); 222 else 223 len = os_strlen(*src); 224 225 return wpa_config_write_string((const u8 *) *src, len); 226} 227 228#ifdef WPA_UNICODE_SSID 229static char * wpa_config_write_str_unicode(const struct parse_data *data, 230 struct wpa_ssid *ssid) 231{ 232 size_t len; 233 char **src; 234 235 src = (char **) (((u8 *) ssid) + (long) data->param1); 236 if (*src == NULL) 237 return NULL; 238 239 if (data->param2) 240 len = *((size_t *) (((u8 *) ssid) + (long) data->param2)); 241 else 242 len = os_strlen(*src); 243 244 return wpa_config_write_string_ascii((const u8 *) *src, len); 245} 246#endif 247#endif /* NO_CONFIG_WRITE */ 248 249 250static int wpa_config_parse_int(const struct parse_data *data, 251 struct wpa_ssid *ssid, 252 int line, const char *value) 253{ 254 int *dst; 255 256 dst = (int *) (((u8 *) ssid) + (long) data->param1); 257 *dst = atoi(value); 258 wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst); 259 260 if (data->param3 && *dst < (long) data->param3) { 261 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " 262 "min_value=%ld)", line, data->name, *dst, 263 (long) data->param3); 264 *dst = (long) data->param3; 265 return -1; 266 } 267 268 if (data->param4 && *dst > (long) data->param4) { 269 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " 270 "max_value=%ld)", line, data->name, *dst, 271 (long) data->param4); 272 *dst = (long) data->param4; 273 return -1; 274 } 275 276 return 0; 277} 278 279 280#ifndef NO_CONFIG_WRITE 281static char * wpa_config_write_int(const struct parse_data *data, 282 struct wpa_ssid *ssid) 283{ 284 int *src, res; 285 char *value; 286 287 src = (int *) (((u8 *) ssid) + (long) data->param1); 288 289 value = os_malloc(20); 290 if (value == NULL) 291 return NULL; 292 res = os_snprintf(value, 20, "%d", *src); 293 if (res < 0 || res >= 20) { 294 os_free(value); 295 return NULL; 296 } 297 value[20 - 1] = '\0'; 298 return value; 299} 300#endif /* NO_CONFIG_WRITE */ 301 302 303static int wpa_config_parse_bssid(const struct parse_data *data, 304 struct wpa_ssid *ssid, int line, 305 const char *value) 306{ 307 if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 || 308 os_strcmp(value, "any") == 0) { 309 ssid->bssid_set = 0; 310 wpa_printf(MSG_MSGDUMP, "BSSID any"); 311 return 0; 312 } 313 if (hwaddr_aton(value, ssid->bssid)) { 314 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.", 315 line, value); 316 return -1; 317 } 318 ssid->bssid_set = 1; 319 wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN); 320 return 0; 321} 322 323 324#ifndef NO_CONFIG_WRITE 325static char * wpa_config_write_bssid(const struct parse_data *data, 326 struct wpa_ssid *ssid) 327{ 328 char *value; 329 int res; 330 331 if (!ssid->bssid_set) 332 return NULL; 333 334 value = os_malloc(20); 335 if (value == NULL) 336 return NULL; 337 res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid)); 338 if (res < 0 || res >= 20) { 339 os_free(value); 340 return NULL; 341 } 342 value[20 - 1] = '\0'; 343 return value; 344} 345#endif /* NO_CONFIG_WRITE */ 346 347 348static int wpa_config_parse_psk(const struct parse_data *data, 349 struct wpa_ssid *ssid, int line, 350 const char *value) 351{ 352 if (*value == '"') { 353#ifndef CONFIG_NO_PBKDF2 354 const char *pos; 355 size_t len; 356 357 value++; 358 pos = os_strrchr(value, '"'); 359 if (pos) 360 len = pos - value; 361 else 362 len = os_strlen(value); 363 if (len < 8 || len > 63) { 364 wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase " 365 "length %lu (expected: 8..63) '%s'.", 366 line, (unsigned long) len, value); 367 return -1; 368 } 369 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)", 370 (u8 *) value, len); 371 if (ssid->passphrase && os_strlen(ssid->passphrase) == len && 372 os_memcmp(ssid->passphrase, value, len) == 0) 373 return 0; 374 ssid->psk_set = 0; 375 os_free(ssid->passphrase); 376 ssid->passphrase = os_malloc(len + 1); 377 if (ssid->passphrase == NULL) 378 return -1; 379 os_memcpy(ssid->passphrase, value, len); 380 ssid->passphrase[len] = '\0'; 381 return 0; 382#else /* CONFIG_NO_PBKDF2 */ 383 wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not " 384 "supported.", line); 385 return -1; 386#endif /* CONFIG_NO_PBKDF2 */ 387 } 388 389 if (hexstr2bin(value, ssid->psk, PMK_LEN) || 390 value[PMK_LEN * 2] != '\0') { 391 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", 392 line, value); 393 return -1; 394 } 395 396 os_free(ssid->passphrase); 397 ssid->passphrase = NULL; 398 399 ssid->psk_set = 1; 400 wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN); 401 return 0; 402} 403 404 405#ifndef NO_CONFIG_WRITE 406static char * wpa_config_write_psk(const struct parse_data *data, 407 struct wpa_ssid *ssid) 408{ 409 if (ssid->passphrase) 410 return wpa_config_write_string_ascii( 411 (const u8 *) ssid->passphrase, 412 os_strlen(ssid->passphrase)); 413 414 if (ssid->psk_set) 415 return wpa_config_write_string_hex(ssid->psk, PMK_LEN); 416 417 return NULL; 418} 419#endif /* NO_CONFIG_WRITE */ 420 421 422static int wpa_config_parse_proto(const struct parse_data *data, 423 struct wpa_ssid *ssid, int line, 424 const char *value) 425{ 426 int val = 0, last, errors = 0; 427 char *start, *end, *buf; 428 429 buf = os_strdup(value); 430 if (buf == NULL) 431 return -1; 432 start = buf; 433 434 while (*start != '\0') { 435 while (*start == ' ' || *start == '\t') 436 start++; 437 if (*start == '\0') 438 break; 439 end = start; 440 while (*end != ' ' && *end != '\t' && *end != '\0') 441 end++; 442 last = *end == '\0'; 443 *end = '\0'; 444 if (os_strcmp(start, "WPA") == 0) 445 val |= WPA_PROTO_WPA; 446 else if (os_strcmp(start, "RSN") == 0 || 447 os_strcmp(start, "WPA2") == 0) 448 val |= WPA_PROTO_RSN; 449 else { 450 wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'", 451 line, start); 452 errors++; 453 } 454 455 if (last) 456 break; 457 start = end + 1; 458 } 459 os_free(buf); 460 461 if (val == 0) { 462 wpa_printf(MSG_ERROR, 463 "Line %d: no proto values configured.", line); 464 errors++; 465 } 466 467 wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val); 468 ssid->proto = val; 469 return errors ? -1 : 0; 470} 471 472 473#ifndef NO_CONFIG_WRITE 474static char * wpa_config_write_proto(const struct parse_data *data, 475 struct wpa_ssid *ssid) 476{ 477 int first = 1, ret; 478 char *buf, *pos, *end; 479 480 pos = buf = os_zalloc(10); 481 if (buf == NULL) 482 return NULL; 483 end = buf + 10; 484 485 if (ssid->proto & WPA_PROTO_WPA) { 486 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 487 if (ret < 0 || ret >= end - pos) 488 return buf; 489 pos += ret; 490 first = 0; 491 } 492 493 if (ssid->proto & WPA_PROTO_RSN) { 494 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 495 if (ret < 0 || ret >= end - pos) 496 return buf; 497 pos += ret; 498 first = 0; 499 } 500 501 return buf; 502} 503#endif /* NO_CONFIG_WRITE */ 504 505 506static int wpa_config_parse_key_mgmt(const struct parse_data *data, 507 struct wpa_ssid *ssid, int line, 508 const char *value) 509{ 510 int val = 0, last, errors = 0; 511 char *start, *end, *buf; 512 513 buf = os_strdup(value); 514 if (buf == NULL) 515 return -1; 516 start = buf; 517 518 while (*start != '\0') { 519 while (*start == ' ' || *start == '\t') 520 start++; 521 if (*start == '\0') 522 break; 523 end = start; 524 while (*end != ' ' && *end != '\t' && *end != '\0') 525 end++; 526 last = *end == '\0'; 527 *end = '\0'; 528 if (os_strcmp(start, "WPA-PSK") == 0) 529 val |= WPA_KEY_MGMT_PSK; 530 else if (os_strcmp(start, "WPA-EAP") == 0) 531 val |= WPA_KEY_MGMT_IEEE8021X; 532 else if (os_strcmp(start, "IEEE8021X") == 0) 533 val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA; 534 else if (os_strcmp(start, "NONE") == 0) 535 val |= WPA_KEY_MGMT_NONE; 536 else if (os_strcmp(start, "WPA-NONE") == 0) 537 val |= WPA_KEY_MGMT_WPA_NONE; 538#ifdef CONFIG_IEEE80211R 539 else if (os_strcmp(start, "FT-PSK") == 0) 540 val |= WPA_KEY_MGMT_FT_PSK; 541 else if (os_strcmp(start, "FT-EAP") == 0) 542 val |= WPA_KEY_MGMT_FT_IEEE8021X; 543#endif /* CONFIG_IEEE80211R */ 544#ifdef CONFIG_IEEE80211W 545 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) 546 val |= WPA_KEY_MGMT_PSK_SHA256; 547 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) 548 val |= WPA_KEY_MGMT_IEEE8021X_SHA256; 549#endif /* CONFIG_IEEE80211W */ 550#ifdef CONFIG_WPS 551 else if (os_strcmp(start, "WPS") == 0) 552 val |= WPA_KEY_MGMT_WPS; 553#endif /* CONFIG_WPS */ 554 else { 555 wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", 556 line, start); 557 errors++; 558 } 559 560 if (last) 561 break; 562 start = end + 1; 563 } 564 os_free(buf); 565 566 if (val == 0) { 567 wpa_printf(MSG_ERROR, 568 "Line %d: no key_mgmt values configured.", line); 569 errors++; 570 } 571 572 wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val); 573 ssid->key_mgmt = val; 574 return errors ? -1 : 0; 575} 576 577 578#ifndef NO_CONFIG_WRITE 579static char * wpa_config_write_key_mgmt(const struct parse_data *data, 580 struct wpa_ssid *ssid) 581{ 582 char *buf, *pos, *end; 583 int ret; 584 585 pos = buf = os_zalloc(50); 586 if (buf == NULL) 587 return NULL; 588 end = buf + 50; 589 590 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { 591 ret = os_snprintf(pos, end - pos, "%sWPA-PSK", 592 pos == buf ? "" : " "); 593 if (ret < 0 || ret >= end - pos) { 594 end[-1] = '\0'; 595 return buf; 596 } 597 pos += ret; 598 } 599 600 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 601 ret = os_snprintf(pos, end - pos, "%sWPA-EAP", 602 pos == buf ? "" : " "); 603 if (ret < 0 || ret >= end - pos) { 604 end[-1] = '\0'; 605 return buf; 606 } 607 pos += ret; 608 } 609 610 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 611 ret = os_snprintf(pos, end - pos, "%sIEEE8021X", 612 pos == buf ? "" : " "); 613 if (ret < 0 || ret >= end - pos) { 614 end[-1] = '\0'; 615 return buf; 616 } 617 pos += ret; 618 } 619 620 if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) { 621 ret = os_snprintf(pos, end - pos, "%sNONE", 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_WPA_NONE) { 631 ret = os_snprintf(pos, end - pos, "%sWPA-NONE", 632 pos == buf ? "" : " "); 633 if (ret < 0 || ret >= end - pos) { 634 end[-1] = '\0'; 635 return buf; 636 } 637 pos += ret; 638 } 639 640#ifdef CONFIG_IEEE80211R 641 if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) 642 pos += os_snprintf(pos, end - pos, "%sFT-PSK", 643 pos == buf ? "" : " "); 644 645 if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 646 pos += os_snprintf(pos, end - pos, "%sFT-EAP", 647 pos == buf ? "" : " "); 648#endif /* CONFIG_IEEE80211R */ 649 650#ifdef CONFIG_IEEE80211W 651 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 652 pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256", 653 pos == buf ? "" : " "); 654 655 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 656 pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256", 657 pos == buf ? "" : " "); 658#endif /* CONFIG_IEEE80211W */ 659 660#ifdef CONFIG_WPS 661 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) 662 pos += os_snprintf(pos, end - pos, "%sWPS", 663 pos == buf ? "" : " "); 664#endif /* CONFIG_WPS */ 665 666 return buf; 667} 668#endif /* NO_CONFIG_WRITE */ 669 670 671static int wpa_config_parse_cipher(int line, const char *value) 672{ 673 int val = 0, last; 674 char *start, *end, *buf; 675 676 buf = os_strdup(value); 677 if (buf == NULL) 678 return -1; 679 start = buf; 680 681 while (*start != '\0') { 682 while (*start == ' ' || *start == '\t') 683 start++; 684 if (*start == '\0') 685 break; 686 end = start; 687 while (*end != ' ' && *end != '\t' && *end != '\0') 688 end++; 689 last = *end == '\0'; 690 *end = '\0'; 691 if (os_strcmp(start, "CCMP") == 0) 692 val |= WPA_CIPHER_CCMP; 693 else if (os_strcmp(start, "TKIP") == 0) 694 val |= WPA_CIPHER_TKIP; 695 else if (os_strcmp(start, "WEP104") == 0) 696 val |= WPA_CIPHER_WEP104; 697 else if (os_strcmp(start, "WEP40") == 0) 698 val |= WPA_CIPHER_WEP40; 699 else if (os_strcmp(start, "NONE") == 0) 700 val |= WPA_CIPHER_NONE; 701 else { 702 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", 703 line, start); 704 os_free(buf); 705 return -1; 706 } 707 708 if (last) 709 break; 710 start = end + 1; 711 } 712 os_free(buf); 713 714 if (val == 0) { 715 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", 716 line); 717 return -1; 718 } 719 return val; 720} 721 722 723#ifndef NO_CONFIG_WRITE 724static char * wpa_config_write_cipher(int cipher) 725{ 726 char *buf, *pos, *end; 727 int ret; 728 729 pos = buf = os_zalloc(50); 730 if (buf == NULL) 731 return NULL; 732 end = buf + 50; 733 734 if (cipher & WPA_CIPHER_CCMP) { 735 ret = os_snprintf(pos, end - pos, "%sCCMP", 736 pos == buf ? "" : " "); 737 if (ret < 0 || ret >= end - pos) { 738 end[-1] = '\0'; 739 return buf; 740 } 741 pos += ret; 742 } 743 744 if (cipher & WPA_CIPHER_TKIP) { 745 ret = os_snprintf(pos, end - pos, "%sTKIP", 746 pos == buf ? "" : " "); 747 if (ret < 0 || ret >= end - pos) { 748 end[-1] = '\0'; 749 return buf; 750 } 751 pos += ret; 752 } 753 754 if (cipher & WPA_CIPHER_WEP104) { 755 ret = os_snprintf(pos, end - pos, "%sWEP104", 756 pos == buf ? "" : " "); 757 if (ret < 0 || ret >= end - pos) { 758 end[-1] = '\0'; 759 return buf; 760 } 761 pos += ret; 762 } 763 764 if (cipher & WPA_CIPHER_WEP40) { 765 ret = os_snprintf(pos, end - pos, "%sWEP40", 766 pos == buf ? "" : " "); 767 if (ret < 0 || ret >= end - pos) { 768 end[-1] = '\0'; 769 return buf; 770 } 771 pos += ret; 772 } 773 774 if (cipher & WPA_CIPHER_NONE) { 775 ret = os_snprintf(pos, end - pos, "%sNONE", 776 pos == buf ? "" : " "); 777 if (ret < 0 || ret >= end - pos) { 778 end[-1] = '\0'; 779 return buf; 780 } 781 pos += ret; 782 } 783 784 return buf; 785} 786#endif /* NO_CONFIG_WRITE */ 787 788 789static int wpa_config_parse_pairwise(const struct parse_data *data, 790 struct wpa_ssid *ssid, int line, 791 const char *value) 792{ 793 int val; 794 val = wpa_config_parse_cipher(line, value); 795 if (val == -1) 796 return -1; 797 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) { 798 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher " 799 "(0x%x).", line, val); 800 return -1; 801 } 802 803 wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val); 804 ssid->pairwise_cipher = val; 805 return 0; 806} 807 808 809#ifndef NO_CONFIG_WRITE 810static char * wpa_config_write_pairwise(const struct parse_data *data, 811 struct wpa_ssid *ssid) 812{ 813 return wpa_config_write_cipher(ssid->pairwise_cipher); 814} 815#endif /* NO_CONFIG_WRITE */ 816 817 818static int wpa_config_parse_group(const struct parse_data *data, 819 struct wpa_ssid *ssid, int line, 820 const char *value) 821{ 822 int val; 823 val = wpa_config_parse_cipher(line, value); 824 if (val == -1) 825 return -1; 826 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 | 827 WPA_CIPHER_WEP40)) { 828 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher " 829 "(0x%x).", line, val); 830 return -1; 831 } 832 833 wpa_printf(MSG_MSGDUMP, "group: 0x%x", val); 834 ssid->group_cipher = val; 835 return 0; 836} 837 838 839#ifndef NO_CONFIG_WRITE 840static char * wpa_config_write_group(const struct parse_data *data, 841 struct wpa_ssid *ssid) 842{ 843 return wpa_config_write_cipher(ssid->group_cipher); 844} 845#endif /* NO_CONFIG_WRITE */ 846 847 848static int wpa_config_parse_auth_alg(const struct parse_data *data, 849 struct wpa_ssid *ssid, int line, 850 const char *value) 851{ 852 int val = 0, last, errors = 0; 853 char *start, *end, *buf; 854 855 buf = os_strdup(value); 856 if (buf == NULL) 857 return -1; 858 start = buf; 859 860 while (*start != '\0') { 861 while (*start == ' ' || *start == '\t') 862 start++; 863 if (*start == '\0') 864 break; 865 end = start; 866 while (*end != ' ' && *end != '\t' && *end != '\0') 867 end++; 868 last = *end == '\0'; 869 *end = '\0'; 870 if (os_strcmp(start, "OPEN") == 0) 871 val |= WPA_AUTH_ALG_OPEN; 872 else if (os_strcmp(start, "SHARED") == 0) 873 val |= WPA_AUTH_ALG_SHARED; 874 else if (os_strcmp(start, "LEAP") == 0) 875 val |= WPA_AUTH_ALG_LEAP; 876 else { 877 wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'", 878 line, start); 879 errors++; 880 } 881 882 if (last) 883 break; 884 start = end + 1; 885 } 886 os_free(buf); 887 888 if (val == 0) { 889 wpa_printf(MSG_ERROR, 890 "Line %d: no auth_alg values configured.", line); 891 errors++; 892 } 893 894 wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val); 895 ssid->auth_alg = val; 896 return errors ? -1 : 0; 897} 898 899 900#ifndef NO_CONFIG_WRITE 901static char * wpa_config_write_auth_alg(const struct parse_data *data, 902 struct wpa_ssid *ssid) 903{ 904 char *buf, *pos, *end; 905 int ret; 906 907 pos = buf = os_zalloc(30); 908 if (buf == NULL) 909 return NULL; 910 end = buf + 30; 911 912 if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) { 913 ret = os_snprintf(pos, end - pos, "%sOPEN", 914 pos == buf ? "" : " "); 915 if (ret < 0 || ret >= end - pos) { 916 end[-1] = '\0'; 917 return buf; 918 } 919 pos += ret; 920 } 921 922 if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) { 923 ret = os_snprintf(pos, end - pos, "%sSHARED", 924 pos == buf ? "" : " "); 925 if (ret < 0 || ret >= end - pos) { 926 end[-1] = '\0'; 927 return buf; 928 } 929 pos += ret; 930 } 931 932 if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) { 933 ret = os_snprintf(pos, end - pos, "%sLEAP", 934 pos == buf ? "" : " "); 935 if (ret < 0 || ret >= end - pos) { 936 end[-1] = '\0'; 937 return buf; 938 } 939 pos += ret; 940 } 941 942 return buf; 943} 944#endif /* NO_CONFIG_WRITE */ 945 946 947static int * wpa_config_parse_freqs(const struct parse_data *data, 948 struct wpa_ssid *ssid, int line, 949 const char *value) 950{ 951 int *freqs; 952 size_t used, len; 953 const char *pos; 954 955 used = 0; 956 len = 10; 957 freqs = os_zalloc((len + 1) * sizeof(int)); 958 if (freqs == NULL) 959 return NULL; 960 961 pos = value; 962 while (pos) { 963 while (*pos == ' ') 964 pos++; 965 if (used == len) { 966 int *n; 967 size_t i; 968 n = os_realloc(freqs, (len * 2 + 1) * sizeof(int)); 969 if (n == NULL) { 970 os_free(freqs); 971 return NULL; 972 } 973 for (i = len; i <= len * 2; i++) 974 n[i] = 0; 975 freqs = n; 976 len *= 2; 977 } 978 979 freqs[used] = atoi(pos); 980 if (freqs[used] == 0) 981 break; 982 used++; 983 pos = os_strchr(pos + 1, ' '); 984 } 985 986 return freqs; 987} 988 989 990static int wpa_config_parse_scan_freq(const struct parse_data *data, 991 struct wpa_ssid *ssid, int line, 992 const char *value) 993{ 994 int *freqs; 995 996 freqs = wpa_config_parse_freqs(data, ssid, line, value); 997 if (freqs == NULL) 998 return -1; 999 os_free(ssid->scan_freq); 1000 ssid->scan_freq = freqs; 1001 1002 return 0; 1003} 1004 1005 1006static int wpa_config_parse_freq_list(const struct parse_data *data, 1007 struct wpa_ssid *ssid, int line, 1008 const char *value) 1009{ 1010 int *freqs; 1011 1012 freqs = wpa_config_parse_freqs(data, ssid, line, value); 1013 if (freqs == NULL) 1014 return -1; 1015 os_free(ssid->freq_list); 1016 ssid->freq_list = freqs; 1017 1018 return 0; 1019} 1020 1021 1022#ifndef NO_CONFIG_WRITE 1023static char * wpa_config_write_freqs(const struct parse_data *data, 1024 const int *freqs) 1025{ 1026 char *buf, *pos, *end; 1027 int i, ret; 1028 size_t count; 1029 1030 if (freqs == NULL) 1031 return NULL; 1032 1033 count = 0; 1034 for (i = 0; freqs[i]; i++) 1035 count++; 1036 1037 pos = buf = os_zalloc(10 * count + 1); 1038 if (buf == NULL) 1039 return NULL; 1040 end = buf + 10 * count + 1; 1041 1042 for (i = 0; freqs[i]; i++) { 1043 ret = os_snprintf(pos, end - pos, "%s%u", 1044 i == 0 ? "" : " ", freqs[i]); 1045 if (ret < 0 || ret >= end - pos) { 1046 end[-1] = '\0'; 1047 return buf; 1048 } 1049 pos += ret; 1050 } 1051 1052 return buf; 1053} 1054 1055 1056static char * wpa_config_write_scan_freq(const struct parse_data *data, 1057 struct wpa_ssid *ssid) 1058{ 1059 return wpa_config_write_freqs(data, ssid->scan_freq); 1060} 1061 1062 1063static char * wpa_config_write_freq_list(const struct parse_data *data, 1064 struct wpa_ssid *ssid) 1065{ 1066 return wpa_config_write_freqs(data, ssid->freq_list); 1067} 1068#endif /* NO_CONFIG_WRITE */ 1069 1070 1071#ifdef IEEE8021X_EAPOL 1072static int wpa_config_parse_eap(const struct parse_data *data, 1073 struct wpa_ssid *ssid, int line, 1074 const char *value) 1075{ 1076 int last, errors = 0; 1077 char *start, *end, *buf; 1078 struct eap_method_type *methods = NULL, *tmp; 1079 size_t num_methods = 0; 1080 1081 buf = os_strdup(value); 1082 if (buf == NULL) 1083 return -1; 1084 start = buf; 1085 1086 while (*start != '\0') { 1087 while (*start == ' ' || *start == '\t') 1088 start++; 1089 if (*start == '\0') 1090 break; 1091 end = start; 1092 while (*end != ' ' && *end != '\t' && *end != '\0') 1093 end++; 1094 last = *end == '\0'; 1095 *end = '\0'; 1096 tmp = methods; 1097 methods = os_realloc(methods, 1098 (num_methods + 1) * sizeof(*methods)); 1099 if (methods == NULL) { 1100 os_free(tmp); 1101 os_free(buf); 1102 return -1; 1103 } 1104 methods[num_methods].method = eap_peer_get_type( 1105 start, &methods[num_methods].vendor); 1106 if (methods[num_methods].vendor == EAP_VENDOR_IETF && 1107 methods[num_methods].method == EAP_TYPE_NONE) { 1108 wpa_printf(MSG_ERROR, "Line %d: unknown EAP method " 1109 "'%s'", line, start); 1110 wpa_printf(MSG_ERROR, "You may need to add support for" 1111 " this EAP method during wpa_supplicant\n" 1112 "build time configuration.\n" 1113 "See README for more information."); 1114 errors++; 1115 } else if (methods[num_methods].vendor == EAP_VENDOR_IETF && 1116 methods[num_methods].method == EAP_TYPE_LEAP) 1117 ssid->leap++; 1118 else 1119 ssid->non_leap++; 1120 num_methods++; 1121 if (last) 1122 break; 1123 start = end + 1; 1124 } 1125 os_free(buf); 1126 1127 tmp = methods; 1128 methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods)); 1129 if (methods == NULL) { 1130 os_free(tmp); 1131 return -1; 1132 } 1133 methods[num_methods].vendor = EAP_VENDOR_IETF; 1134 methods[num_methods].method = EAP_TYPE_NONE; 1135 num_methods++; 1136 1137 wpa_hexdump(MSG_MSGDUMP, "eap methods", 1138 (u8 *) methods, num_methods * sizeof(*methods)); 1139 ssid->eap.eap_methods = methods; 1140 return errors ? -1 : 0; 1141} 1142 1143 1144static char * wpa_config_write_eap(const struct parse_data *data, 1145 struct wpa_ssid *ssid) 1146{ 1147 int i, ret; 1148 char *buf, *pos, *end; 1149 const struct eap_method_type *eap_methods = ssid->eap.eap_methods; 1150 const char *name; 1151 1152 if (eap_methods == NULL) 1153 return NULL; 1154 1155 pos = buf = os_zalloc(100); 1156 if (buf == NULL) 1157 return NULL; 1158 end = buf + 100; 1159 1160 for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF || 1161 eap_methods[i].method != EAP_TYPE_NONE; i++) { 1162 name = eap_get_name(eap_methods[i].vendor, 1163 eap_methods[i].method); 1164 if (name) { 1165 ret = os_snprintf(pos, end - pos, "%s%s", 1166 pos == buf ? "" : " ", name); 1167 if (ret < 0 || ret >= end - pos) 1168 break; 1169 pos += ret; 1170 } 1171 } 1172 1173 end[-1] = '\0'; 1174 1175 return buf; 1176} 1177 1178 1179static int wpa_config_parse_password(const struct parse_data *data, 1180 struct wpa_ssid *ssid, int line, 1181 const char *value) 1182{ 1183 u8 *hash; 1184 1185 if (os_strcmp(value, "NULL") == 0) { 1186 wpa_printf(MSG_DEBUG, "Unset configuration string 'password'"); 1187 os_free(ssid->eap.password); 1188 ssid->eap.password = NULL; 1189 ssid->eap.password_len = 0; 1190 return 0; 1191 } 1192 1193 if (os_strncmp(value, "hash:", 5) != 0) { 1194 char *tmp; 1195 size_t res_len; 1196 1197 tmp = wpa_config_parse_string(value, &res_len); 1198 if (tmp == NULL) { 1199 wpa_printf(MSG_ERROR, "Line %d: failed to parse " 1200 "password.", line); 1201 return -1; 1202 } 1203 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, 1204 (u8 *) tmp, res_len); 1205 1206 os_free(ssid->eap.password); 1207 ssid->eap.password = (u8 *) tmp; 1208 ssid->eap.password_len = res_len; 1209 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; 1210 1211 return 0; 1212 } 1213 1214 1215 /* NtPasswordHash: hash:<32 hex digits> */ 1216 if (os_strlen(value + 5) != 2 * 16) { 1217 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length " 1218 "(expected 32 hex digits)", line); 1219 return -1; 1220 } 1221 1222 hash = os_malloc(16); 1223 if (hash == NULL) 1224 return -1; 1225 1226 if (hexstr2bin(value + 5, hash, 16)) { 1227 os_free(hash); 1228 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line); 1229 return -1; 1230 } 1231 1232 wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16); 1233 1234 os_free(ssid->eap.password); 1235 ssid->eap.password = hash; 1236 ssid->eap.password_len = 16; 1237 ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH; 1238 1239 return 0; 1240} 1241 1242 1243static char * wpa_config_write_password(const struct parse_data *data, 1244 struct wpa_ssid *ssid) 1245{ 1246 char *buf; 1247 1248 if (ssid->eap.password == NULL) 1249 return NULL; 1250 1251 if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) { 1252 return wpa_config_write_string( 1253 ssid->eap.password, ssid->eap.password_len); 1254 } 1255 1256 buf = os_malloc(5 + 32 + 1); 1257 if (buf == NULL) 1258 return NULL; 1259 1260 os_memcpy(buf, "hash:", 5); 1261 wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16); 1262 1263 return buf; 1264} 1265#endif /* IEEE8021X_EAPOL */ 1266 1267 1268static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, 1269 const char *value, int idx) 1270{ 1271 char *buf, title[20]; 1272 int res; 1273 1274 buf = wpa_config_parse_string(value, len); 1275 if (buf == NULL) { 1276 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.", 1277 line, idx, value); 1278 return -1; 1279 } 1280 if (*len > MAX_WEP_KEY_LEN) { 1281 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.", 1282 line, idx, value); 1283 os_free(buf); 1284 return -1; 1285 } 1286 os_memcpy(key, buf, *len); 1287 os_free(buf); 1288 res = os_snprintf(title, sizeof(title), "wep_key%d", idx); 1289 if (res >= 0 && (size_t) res < sizeof(title)) 1290 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len); 1291 return 0; 1292} 1293 1294 1295static int wpa_config_parse_wep_key0(const struct parse_data *data, 1296 struct wpa_ssid *ssid, int line, 1297 const char *value) 1298{ 1299 return wpa_config_parse_wep_key(ssid->wep_key[0], 1300 &ssid->wep_key_len[0], line, 1301 value, 0); 1302} 1303 1304 1305static int wpa_config_parse_wep_key1(const struct parse_data *data, 1306 struct wpa_ssid *ssid, int line, 1307 const char *value) 1308{ 1309 return wpa_config_parse_wep_key(ssid->wep_key[1], 1310 &ssid->wep_key_len[1], line, 1311 value, 1); 1312} 1313 1314 1315static int wpa_config_parse_wep_key2(const struct parse_data *data, 1316 struct wpa_ssid *ssid, int line, 1317 const char *value) 1318{ 1319 return wpa_config_parse_wep_key(ssid->wep_key[2], 1320 &ssid->wep_key_len[2], line, 1321 value, 2); 1322} 1323 1324 1325static int wpa_config_parse_wep_key3(const struct parse_data *data, 1326 struct wpa_ssid *ssid, int line, 1327 const char *value) 1328{ 1329 return wpa_config_parse_wep_key(ssid->wep_key[3], 1330 &ssid->wep_key_len[3], line, 1331 value, 3); 1332} 1333 1334 1335#ifndef NO_CONFIG_WRITE 1336static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx) 1337{ 1338 if (ssid->wep_key_len[idx] == 0) 1339 return NULL; 1340 return wpa_config_write_string(ssid->wep_key[idx], 1341 ssid->wep_key_len[idx]); 1342} 1343 1344 1345static char * wpa_config_write_wep_key0(const struct parse_data *data, 1346 struct wpa_ssid *ssid) 1347{ 1348 return wpa_config_write_wep_key(ssid, 0); 1349} 1350 1351 1352static char * wpa_config_write_wep_key1(const struct parse_data *data, 1353 struct wpa_ssid *ssid) 1354{ 1355 return wpa_config_write_wep_key(ssid, 1); 1356} 1357 1358 1359static char * wpa_config_write_wep_key2(const struct parse_data *data, 1360 struct wpa_ssid *ssid) 1361{ 1362 return wpa_config_write_wep_key(ssid, 2); 1363} 1364 1365 1366static char * wpa_config_write_wep_key3(const struct parse_data *data, 1367 struct wpa_ssid *ssid) 1368{ 1369 return wpa_config_write_wep_key(ssid, 3); 1370} 1371#endif /* NO_CONFIG_WRITE */ 1372 1373 1374#ifdef CONFIG_P2P 1375 1376static int wpa_config_parse_p2p_client_list(const struct parse_data *data, 1377 struct wpa_ssid *ssid, int line, 1378 const char *value) 1379{ 1380 const char *pos; 1381 u8 *buf, *n, addr[ETH_ALEN]; 1382 size_t count; 1383 1384 buf = NULL; 1385 count = 0; 1386 1387 pos = value; 1388 while (pos && *pos) { 1389 while (*pos == ' ') 1390 pos++; 1391 1392 if (hwaddr_aton(pos, addr)) { 1393 wpa_printf(MSG_ERROR, "Line %d: Invalid " 1394 "p2p_client_list address '%s'.", 1395 line, value); 1396 /* continue anyway */ 1397 } else { 1398 n = os_realloc(buf, (count + 1) * ETH_ALEN); 1399 if (n == NULL) { 1400 os_free(buf); 1401 return -1; 1402 } 1403 buf = n; 1404 os_memcpy(buf + count * ETH_ALEN, addr, ETH_ALEN); 1405 count++; 1406 wpa_hexdump(MSG_MSGDUMP, "p2p_client_list", 1407 addr, ETH_ALEN); 1408 } 1409 1410 pos = os_strchr(pos, ' '); 1411 } 1412 1413 os_free(ssid->p2p_client_list); 1414 ssid->p2p_client_list = buf; 1415 ssid->num_p2p_clients = count; 1416 1417 return 0; 1418} 1419 1420 1421#ifndef NO_CONFIG_WRITE 1422static char * wpa_config_write_p2p_client_list(const struct parse_data *data, 1423 struct wpa_ssid *ssid) 1424{ 1425 char *value, *end, *pos; 1426 int res; 1427 size_t i; 1428 1429 if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0) 1430 return NULL; 1431 1432 value = os_malloc(20 * ssid->num_p2p_clients); 1433 if (value == NULL) 1434 return NULL; 1435 pos = value; 1436 end = value + 20 * ssid->num_p2p_clients; 1437 1438 for (i = 0; i < ssid->num_p2p_clients; i++) { 1439 res = os_snprintf(pos, end - pos, MACSTR " ", 1440 MAC2STR(ssid->p2p_client_list + 1441 i * ETH_ALEN)); 1442 if (res < 0 || res >= end - pos) { 1443 os_free(value); 1444 return NULL; 1445 } 1446 pos += res; 1447 } 1448 1449 if (pos > value) 1450 pos[-1] = '\0'; 1451 1452 return value; 1453} 1454#endif /* NO_CONFIG_WRITE */ 1455 1456#endif /* CONFIG_P2P */ 1457 1458/* Helper macros for network block parser */ 1459 1460#ifdef OFFSET 1461#undef OFFSET 1462#endif /* OFFSET */ 1463/* OFFSET: Get offset of a variable within the wpa_ssid structure */ 1464#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v) 1465 1466/* STR: Define a string variable for an ASCII string; f = field name */ 1467#ifdef NO_CONFIG_WRITE 1468#define _STR(f) #f, wpa_config_parse_str, OFFSET(f) 1469#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f) 1470#else /* NO_CONFIG_WRITE */ 1471#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f) 1472#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f) 1473#endif /* NO_CONFIG_WRITE */ 1474#define STR(f) _STR(f), NULL, NULL, NULL, 0 1475#define STRe(f) _STRe(f), NULL, NULL, NULL, 0 1476#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1 1477#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1 1478 1479/* STR_LEN: Define a string variable with a separate variable for storing the 1480 * data length. Unlike STR(), this can be used to store arbitrary binary data 1481 * (i.e., even nul termination character). */ 1482#define _STR_LEN(f) _STR(f), OFFSET(f ## _len) 1483#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len) 1484#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0 1485#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0 1486#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1 1487 1488/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length 1489 * explicitly specified. */ 1490#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max) 1491#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0 1492#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1 1493 1494#ifdef NO_CONFIG_WRITE 1495#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0 1496#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0 1497#else /* NO_CONFIG_WRITE */ 1498#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 1499 OFFSET(f), (void *) 0 1500#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 1501 OFFSET(eap.f), (void *) 0 1502#ifdef WPA_UNICODE_SSID 1503/* STR_* variants that do not force conversion to ASCII */ 1504#define _STR_UNICODE(f) #f, wpa_config_parse_str, wpa_config_write_str_unicode, OFFSET(f) 1505#define STR_UNICODE(f) _STR_UNICODE(f), NULL, NULL, NULL, 0 1506#define _STR_LEN_UNICODE(f) _STR_UNICODE(f), OFFSET(f ## _len) 1507#define STR_LEN_UNICODE(f) _STR_LEN_UNICODE(f), NULL, NULL, 0 1508#define _STR_RANGE_UNICODE(f, min, max) _STR_LEN_UNICODE(f), (void *) (min), (void *) (max) 1509#define STR_RANGE_UNICODE(f, min, max) _STR_RANGE_UNICODE(f, min, max), 0 1510#endif 1511#endif /* NO_CONFIG_WRITE */ 1512 1513/* INT: Define an integer variable */ 1514#define INT(f) _INT(f), NULL, NULL, 0 1515#define INTe(f) _INTe(f), NULL, NULL, 0 1516 1517/* INT_RANGE: Define an integer variable with allowed value range */ 1518#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0 1519 1520/* FUNC: Define a configuration variable that uses a custom function for 1521 * parsing and writing the value. */ 1522#ifdef NO_CONFIG_WRITE 1523#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL 1524#else /* NO_CONFIG_WRITE */ 1525#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \ 1526 NULL, NULL, NULL, NULL 1527#endif /* NO_CONFIG_WRITE */ 1528#define FUNC(f) _FUNC(f), 0 1529#define FUNC_KEY(f) _FUNC(f), 1 1530 1531/* 1532 * Table of network configuration variables. This table is used to parse each 1533 * network configuration variable, e.g., each line in wpa_supplicant.conf file 1534 * that is inside a network block. 1535 * 1536 * This table is generated using the helper macros defined above and with 1537 * generous help from the C pre-processor. The field name is stored as a string 1538 * into .name and for STR and INT types, the offset of the target buffer within 1539 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar 1540 * offset to the field containing the length of the configuration variable. 1541 * .param3 and .param4 can be used to mark the allowed range (length for STR 1542 * and value for INT). 1543 * 1544 * For each configuration line in wpa_supplicant.conf, the parser goes through 1545 * this table and select the entry that matches with the field name. The parser 1546 * function (.parser) is then called to parse the actual value of the field. 1547 * 1548 * This kind of mechanism makes it easy to add new configuration parameters, 1549 * since only one line needs to be added into this table and into the 1550 * struct wpa_ssid definition if the new variable is either a string or 1551 * integer. More complex types will need to use their own parser and writer 1552 * functions. 1553 */ 1554static const struct parse_data ssid_fields[] = { 1555#ifdef WPA_UNICODE_SSID 1556 { STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) }, 1557#else 1558 { STR_RANGE(ssid, 0, MAX_SSID_LEN) }, 1559#endif 1560 { INT_RANGE(scan_ssid, 0, 1) }, 1561 { FUNC(bssid) }, 1562 { FUNC_KEY(psk) }, 1563 { FUNC(proto) }, 1564 { FUNC(key_mgmt) }, 1565 { FUNC(pairwise) }, 1566 { FUNC(group) }, 1567 { FUNC(auth_alg) }, 1568 { FUNC(scan_freq) }, 1569 { FUNC(freq_list) }, 1570#ifdef IEEE8021X_EAPOL 1571 { FUNC(eap) }, 1572 { STR_LENe(identity) }, 1573 { STR_LENe(anonymous_identity) }, 1574 { FUNC_KEY(password) }, 1575 { STRe(ca_cert) }, 1576 { STRe(ca_path) }, 1577 { STRe(client_cert) }, 1578 { STRe(private_key) }, 1579 { STR_KEYe(private_key_passwd) }, 1580 { STRe(dh_file) }, 1581 { STRe(subject_match) }, 1582 { STRe(altsubject_match) }, 1583 { STRe(ca_cert2) }, 1584 { STRe(ca_path2) }, 1585 { STRe(client_cert2) }, 1586 { STRe(private_key2) }, 1587 { STR_KEYe(private_key2_passwd) }, 1588 { STRe(dh_file2) }, 1589 { STRe(subject_match2) }, 1590 { STRe(altsubject_match2) }, 1591 { STRe(phase1) }, 1592 { STRe(phase2) }, 1593 { STRe(pcsc) }, 1594 { STR_KEYe(pin) }, 1595 { STRe(engine_id) }, 1596 { STRe(key_id) }, 1597 { STRe(cert_id) }, 1598 { STRe(ca_cert_id) }, 1599 { STR_KEYe(pin2) }, 1600 { STRe(engine2_id) }, 1601 { STRe(key2_id) }, 1602 { STRe(cert2_id) }, 1603 { STRe(ca_cert2_id) }, 1604 { INTe(engine) }, 1605 { INTe(engine2) }, 1606 { INT(eapol_flags) }, 1607#endif /* IEEE8021X_EAPOL */ 1608 { FUNC_KEY(wep_key0) }, 1609 { FUNC_KEY(wep_key1) }, 1610 { FUNC_KEY(wep_key2) }, 1611 { FUNC_KEY(wep_key3) }, 1612 { INT(wep_tx_keyidx) }, 1613 { INT(priority) }, 1614#ifdef IEEE8021X_EAPOL 1615 { INT(eap_workaround) }, 1616 { STRe(pac_file) }, 1617 { INTe(fragment_size) }, 1618#endif /* IEEE8021X_EAPOL */ 1619 { INT_RANGE(mode, 0, 4) }, 1620 { INT_RANGE(proactive_key_caching, 0, 1) }, 1621 { INT_RANGE(disabled, 0, 2) }, 1622 { STR(id_str) }, 1623#ifdef CONFIG_IEEE80211W 1624 { INT_RANGE(ieee80211w, 0, 2) }, 1625#endif /* CONFIG_IEEE80211W */ 1626 { INT_RANGE(peerkey, 0, 1) }, 1627 { INT_RANGE(mixed_cell, 0, 1) }, 1628 { INT_RANGE(frequency, 0, 10000) }, 1629 { INT(wpa_ptk_rekey) }, 1630 { STR(bgscan) }, 1631#ifdef CONFIG_P2P 1632 { FUNC(p2p_client_list) }, 1633#endif /* CONFIG_P2P */ 1634}; 1635 1636#ifdef WPA_UNICODE_SSID 1637#undef _STR_UNICODE 1638#undef STR_UNICODE 1639#undef _STR_LEN_UNICODE 1640#undef STR_LEN_UNICODE 1641#undef _STR_RANGE_UNICODE 1642#undef STR_RANGE_UNICODE 1643#endif 1644 1645#undef OFFSET 1646#undef _STR 1647#undef STR 1648#undef STR_KEY 1649#undef _STR_LEN 1650#undef STR_LEN 1651#undef STR_LEN_KEY 1652#undef _STR_RANGE 1653#undef STR_RANGE 1654#undef STR_RANGE_KEY 1655#undef _INT 1656#undef INT 1657#undef INT_RANGE 1658#undef _FUNC 1659#undef FUNC 1660#undef FUNC_KEY 1661#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0])) 1662 1663 1664/** 1665 * wpa_config_add_prio_network - Add a network to priority lists 1666 * @config: Configuration data from wpa_config_read() 1667 * @ssid: Pointer to the network configuration to be added to the list 1668 * Returns: 0 on success, -1 on failure 1669 * 1670 * This function is used to add a network block to the priority list of 1671 * networks. This must be called for each network when reading in the full 1672 * configuration. In addition, this can be used indirectly when updating 1673 * priorities by calling wpa_config_update_prio_list(). 1674 */ 1675int wpa_config_add_prio_network(struct wpa_config *config, 1676 struct wpa_ssid *ssid) 1677{ 1678 int prio; 1679 struct wpa_ssid *prev, **nlist; 1680 1681 /* 1682 * Add to an existing priority list if one is available for the 1683 * configured priority level for this network. 1684 */ 1685 for (prio = 0; prio < config->num_prio; prio++) { 1686 prev = config->pssid[prio]; 1687 if (prev->priority == ssid->priority) { 1688 while (prev->pnext) 1689 prev = prev->pnext; 1690 prev->pnext = ssid; 1691 return 0; 1692 } 1693 } 1694 1695 /* First network for this priority - add a new priority list */ 1696 nlist = os_realloc(config->pssid, 1697 (config->num_prio + 1) * sizeof(struct wpa_ssid *)); 1698 if (nlist == NULL) 1699 return -1; 1700 1701 for (prio = 0; prio < config->num_prio; prio++) { 1702 if (nlist[prio]->priority < ssid->priority) 1703 break; 1704 } 1705 1706 os_memmove(&nlist[prio + 1], &nlist[prio], 1707 (config->num_prio - prio) * sizeof(struct wpa_ssid *)); 1708 1709 nlist[prio] = ssid; 1710 config->num_prio++; 1711 config->pssid = nlist; 1712 1713 return 0; 1714} 1715 1716 1717/** 1718 * wpa_config_update_prio_list - Update network priority list 1719 * @config: Configuration data from wpa_config_read() 1720 * Returns: 0 on success, -1 on failure 1721 * 1722 * This function is called to update the priority list of networks in the 1723 * configuration when a network is being added or removed. This is also called 1724 * if a priority for a network is changed. 1725 */ 1726int wpa_config_update_prio_list(struct wpa_config *config) 1727{ 1728 struct wpa_ssid *ssid; 1729 int ret = 0; 1730 1731 os_free(config->pssid); 1732 config->pssid = NULL; 1733 config->num_prio = 0; 1734 1735 ssid = config->ssid; 1736 while (ssid) { 1737 ssid->pnext = NULL; 1738 if (wpa_config_add_prio_network(config, ssid) < 0) 1739 ret = -1; 1740 ssid = ssid->next; 1741 } 1742 1743 return ret; 1744} 1745 1746 1747#ifdef IEEE8021X_EAPOL 1748static void eap_peer_config_free(struct eap_peer_config *eap) 1749{ 1750 os_free(eap->eap_methods); 1751 os_free(eap->identity); 1752 os_free(eap->anonymous_identity); 1753 os_free(eap->password); 1754 os_free(eap->ca_cert); 1755 os_free(eap->ca_path); 1756 os_free(eap->client_cert); 1757 os_free(eap->private_key); 1758 os_free(eap->private_key_passwd); 1759 os_free(eap->dh_file); 1760 os_free(eap->subject_match); 1761 os_free(eap->altsubject_match); 1762 os_free(eap->ca_cert2); 1763 os_free(eap->ca_path2); 1764 os_free(eap->client_cert2); 1765 os_free(eap->private_key2); 1766 os_free(eap->private_key2_passwd); 1767 os_free(eap->dh_file2); 1768 os_free(eap->subject_match2); 1769 os_free(eap->altsubject_match2); 1770 os_free(eap->phase1); 1771 os_free(eap->phase2); 1772 os_free(eap->pcsc); 1773 os_free(eap->pin); 1774 os_free(eap->engine_id); 1775 os_free(eap->key_id); 1776 os_free(eap->cert_id); 1777 os_free(eap->ca_cert_id); 1778 os_free(eap->key2_id); 1779 os_free(eap->cert2_id); 1780 os_free(eap->ca_cert2_id); 1781 os_free(eap->pin2); 1782 os_free(eap->engine2_id); 1783 os_free(eap->otp); 1784 os_free(eap->pending_req_otp); 1785 os_free(eap->pac_file); 1786 os_free(eap->new_password); 1787} 1788#endif /* IEEE8021X_EAPOL */ 1789 1790 1791/** 1792 * wpa_config_free_ssid - Free network/ssid configuration data 1793 * @ssid: Configuration data for the network 1794 * 1795 * This function frees all resources allocated for the network configuration 1796 * data. 1797 */ 1798void wpa_config_free_ssid(struct wpa_ssid *ssid) 1799{ 1800 os_free(ssid->ssid); 1801 os_free(ssid->passphrase); 1802#ifdef IEEE8021X_EAPOL 1803 eap_peer_config_free(&ssid->eap); 1804#endif /* IEEE8021X_EAPOL */ 1805 os_free(ssid->id_str); 1806 os_free(ssid->scan_freq); 1807 os_free(ssid->freq_list); 1808 os_free(ssid->bgscan); 1809 os_free(ssid->p2p_client_list); 1810 os_free(ssid); 1811} 1812 1813 1814/** 1815 * wpa_config_free - Free configuration data 1816 * @config: Configuration data from wpa_config_read() 1817 * 1818 * This function frees all resources allocated for the configuration data by 1819 * wpa_config_read(). 1820 */ 1821void wpa_config_free(struct wpa_config *config) 1822{ 1823#ifndef CONFIG_NO_CONFIG_BLOBS 1824 struct wpa_config_blob *blob, *prevblob; 1825#endif /* CONFIG_NO_CONFIG_BLOBS */ 1826 struct wpa_ssid *ssid, *prev = NULL; 1827 1828 ssid = config->ssid; 1829 while (ssid) { 1830 prev = ssid; 1831 ssid = ssid->next; 1832 wpa_config_free_ssid(prev); 1833 } 1834 1835#ifndef CONFIG_NO_CONFIG_BLOBS 1836 blob = config->blobs; 1837 prevblob = NULL; 1838 while (blob) { 1839 prevblob = blob; 1840 blob = blob->next; 1841 wpa_config_free_blob(prevblob); 1842 } 1843#endif /* CONFIG_NO_CONFIG_BLOBS */ 1844 1845 os_free(config->ctrl_interface); 1846 os_free(config->ctrl_interface_group); 1847 os_free(config->opensc_engine_path); 1848 os_free(config->pkcs11_engine_path); 1849 os_free(config->pkcs11_module_path); 1850 os_free(config->driver_param); 1851 os_free(config->device_name); 1852 os_free(config->manufacturer); 1853 os_free(config->model_name); 1854 os_free(config->model_number); 1855 os_free(config->serial_number); 1856 os_free(config->config_methods); 1857 os_free(config->p2p_ssid_postfix); 1858 os_free(config->pssid); 1859 os_free(config->home_realm); 1860 os_free(config->home_username); 1861 os_free(config->home_password); 1862 os_free(config->home_ca_cert); 1863 os_free(config->home_imsi); 1864 os_free(config->home_milenage); 1865 os_free(config); 1866} 1867 1868 1869/** 1870 * wpa_config_foreach_network - Iterate over each configured network 1871 * @config: Configuration data from wpa_config_read() 1872 * @func: Callback function to process each network 1873 * @arg: Opaque argument to pass to callback function 1874 * 1875 * Iterate over the set of configured networks calling the specified 1876 * function for each item. We guard against callbacks removing the 1877 * supplied network. 1878 */ 1879void wpa_config_foreach_network(struct wpa_config *config, 1880 void (*func)(void *, struct wpa_ssid *), 1881 void *arg) 1882{ 1883 struct wpa_ssid *ssid, *next; 1884 1885 ssid = config->ssid; 1886 while (ssid) { 1887 next = ssid->next; 1888 func(arg, ssid); 1889 ssid = next; 1890 } 1891} 1892 1893 1894/** 1895 * wpa_config_get_network - Get configured network based on id 1896 * @config: Configuration data from wpa_config_read() 1897 * @id: Unique network id to search for 1898 * Returns: Network configuration or %NULL if not found 1899 */ 1900struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id) 1901{ 1902 struct wpa_ssid *ssid; 1903 1904 ssid = config->ssid; 1905 while (ssid) { 1906 if (id == ssid->id) 1907 break; 1908 ssid = ssid->next; 1909 } 1910 1911 return ssid; 1912} 1913 1914 1915/** 1916 * wpa_config_add_network - Add a new network with empty configuration 1917 * @config: Configuration data from wpa_config_read() 1918 * Returns: The new network configuration or %NULL if operation failed 1919 */ 1920struct wpa_ssid * wpa_config_add_network(struct wpa_config *config) 1921{ 1922 int id; 1923 struct wpa_ssid *ssid, *last = NULL; 1924 1925 id = -1; 1926 ssid = config->ssid; 1927 while (ssid) { 1928 if (ssid->id > id) 1929 id = ssid->id; 1930 last = ssid; 1931 ssid = ssid->next; 1932 } 1933 id++; 1934 1935 ssid = os_zalloc(sizeof(*ssid)); 1936 if (ssid == NULL) 1937 return NULL; 1938 ssid->id = id; 1939 if (last) 1940 last->next = ssid; 1941 else 1942 config->ssid = ssid; 1943 1944 wpa_config_update_prio_list(config); 1945 1946 return ssid; 1947} 1948 1949 1950/** 1951 * wpa_config_remove_network - Remove a configured network based on id 1952 * @config: Configuration data from wpa_config_read() 1953 * @id: Unique network id to search for 1954 * Returns: 0 on success, or -1 if the network was not found 1955 */ 1956int wpa_config_remove_network(struct wpa_config *config, int id) 1957{ 1958 struct wpa_ssid *ssid, *prev = NULL; 1959 1960 ssid = config->ssid; 1961 while (ssid) { 1962 if (id == ssid->id) 1963 break; 1964 prev = ssid; 1965 ssid = ssid->next; 1966 } 1967 1968 if (ssid == NULL) 1969 return -1; 1970 1971 if (prev) 1972 prev->next = ssid->next; 1973 else 1974 config->ssid = ssid->next; 1975 1976 wpa_config_update_prio_list(config); 1977 wpa_config_free_ssid(ssid); 1978 return 0; 1979} 1980 1981 1982/** 1983 * wpa_config_set_network_defaults - Set network default values 1984 * @ssid: Pointer to network configuration data 1985 */ 1986void wpa_config_set_network_defaults(struct wpa_ssid *ssid) 1987{ 1988 ssid->proto = DEFAULT_PROTO; 1989 ssid->pairwise_cipher = DEFAULT_PAIRWISE; 1990 ssid->group_cipher = DEFAULT_GROUP; 1991 ssid->key_mgmt = DEFAULT_KEY_MGMT; 1992#ifdef IEEE8021X_EAPOL 1993 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; 1994 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; 1995 ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE; 1996#endif /* IEEE8021X_EAPOL */ 1997} 1998 1999 2000/** 2001 * wpa_config_set - Set a variable in network configuration 2002 * @ssid: Pointer to network configuration data 2003 * @var: Variable name, e.g., "ssid" 2004 * @value: Variable value 2005 * @line: Line number in configuration file or 0 if not used 2006 * Returns: 0 on success, -1 on failure 2007 * 2008 * This function can be used to set network configuration variables based on 2009 * both the configuration file and management interface input. The value 2010 * parameter must be in the same format as the text-based configuration file is 2011 * using. For example, strings are using double quotation marks. 2012 */ 2013int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, 2014 int line) 2015{ 2016 size_t i; 2017 int ret = 0; 2018 2019 if (ssid == NULL || var == NULL || value == NULL) 2020 return -1; 2021 2022 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2023 const struct parse_data *field = &ssid_fields[i]; 2024 if (os_strcmp(var, field->name) != 0) 2025 continue; 2026 2027 if (field->parser(field, ssid, line, value)) { 2028 if (line) { 2029 wpa_printf(MSG_ERROR, "Line %d: failed to " 2030 "parse %s '%s'.", line, var, value); 2031 } 2032 ret = -1; 2033 } 2034 break; 2035 } 2036 if (i == NUM_SSID_FIELDS) { 2037 if (line) { 2038 wpa_printf(MSG_ERROR, "Line %d: unknown network field " 2039 "'%s'.", line, var); 2040 } 2041 ret = -1; 2042 } 2043 2044 return ret; 2045} 2046 2047 2048int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var, 2049 const char *value) 2050{ 2051 size_t len; 2052 char *buf; 2053 int ret; 2054 2055 len = os_strlen(value); 2056 buf = os_malloc(len + 3); 2057 if (buf == NULL) 2058 return -1; 2059 buf[0] = '"'; 2060 os_memcpy(buf + 1, value, len); 2061 buf[len + 1] = '"'; 2062 buf[len + 2] = '\0'; 2063 ret = wpa_config_set(ssid, var, buf, 0); 2064 os_free(buf); 2065 return ret; 2066} 2067 2068 2069/** 2070 * wpa_config_get_all - Get all options from network configuration 2071 * @ssid: Pointer to network configuration data 2072 * @get_keys: Determines if keys/passwords will be included in returned list 2073 * (if they may be exported) 2074 * Returns: %NULL terminated list of all set keys and their values in the form 2075 * of [key1, val1, key2, val2, ... , NULL] 2076 * 2077 * This function can be used to get list of all configured network properties. 2078 * The caller is responsible for freeing the returned list and all its 2079 * elements. 2080 */ 2081char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys) 2082{ 2083 const struct parse_data *field; 2084 char *key, *value; 2085 size_t i; 2086 char **props; 2087 int fields_num; 2088 2089 get_keys = get_keys && ssid->export_keys; 2090 2091 props = os_zalloc(sizeof(char *) * ((2 * NUM_SSID_FIELDS) + 1)); 2092 if (!props) 2093 return NULL; 2094 2095 fields_num = 0; 2096 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2097 field = &ssid_fields[i]; 2098 if (field->key_data && !get_keys) 2099 continue; 2100 value = field->writer(field, ssid); 2101 if (value == NULL) 2102 continue; 2103 if (os_strlen(value) == 0) { 2104 os_free(value); 2105 continue; 2106 } 2107 2108 key = os_strdup(field->name); 2109 if (key == NULL) { 2110 os_free(value); 2111 goto err; 2112 } 2113 2114 props[fields_num * 2] = key; 2115 props[fields_num * 2 + 1] = value; 2116 2117 fields_num++; 2118 } 2119 2120 return props; 2121 2122err: 2123 value = *props; 2124 while (value) 2125 os_free(value++); 2126 os_free(props); 2127 return NULL; 2128} 2129 2130 2131#ifndef NO_CONFIG_WRITE 2132/** 2133 * wpa_config_get - Get a variable in network configuration 2134 * @ssid: Pointer to network configuration data 2135 * @var: Variable name, e.g., "ssid" 2136 * Returns: Value of the variable or %NULL on failure 2137 * 2138 * This function can be used to get network configuration variables. The 2139 * returned value is a copy of the configuration variable in text format, i.e,. 2140 * the same format that the text-based configuration file and wpa_config_set() 2141 * are using for the value. The caller is responsible for freeing the returned 2142 * value. 2143 */ 2144char * wpa_config_get(struct wpa_ssid *ssid, const char *var) 2145{ 2146 size_t i; 2147 2148 if (ssid == NULL || var == NULL) 2149 return NULL; 2150 2151 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2152 const struct parse_data *field = &ssid_fields[i]; 2153 if (os_strcmp(var, field->name) == 0) 2154 return field->writer(field, ssid); 2155 } 2156 2157 return NULL; 2158} 2159 2160 2161/** 2162 * wpa_config_get_no_key - Get a variable in network configuration (no keys) 2163 * @ssid: Pointer to network configuration data 2164 * @var: Variable name, e.g., "ssid" 2165 * Returns: Value of the variable or %NULL on failure 2166 * 2167 * This function can be used to get network configuration variable like 2168 * wpa_config_get(). The only difference is that this functions does not expose 2169 * key/password material from the configuration. In case a key/password field 2170 * is requested, the returned value is an empty string or %NULL if the variable 2171 * is not set or "*" if the variable is set (regardless of its value). The 2172 * returned value is a copy of the configuration variable in text format, i.e,. 2173 * the same format that the text-based configuration file and wpa_config_set() 2174 * are using for the value. The caller is responsible for freeing the returned 2175 * value. 2176 */ 2177char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var) 2178{ 2179 size_t i; 2180 2181 if (ssid == NULL || var == NULL) 2182 return NULL; 2183 2184 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2185 const struct parse_data *field = &ssid_fields[i]; 2186 if (os_strcmp(var, field->name) == 0) { 2187 char *res = field->writer(field, ssid); 2188 if (field->key_data) { 2189 if (res && res[0]) { 2190 wpa_printf(MSG_DEBUG, "Do not allow " 2191 "key_data field to be " 2192 "exposed"); 2193 os_free(res); 2194 return os_strdup("*"); 2195 } 2196 2197 os_free(res); 2198 return NULL; 2199 } 2200 return res; 2201 } 2202 } 2203 2204 return NULL; 2205} 2206#endif /* NO_CONFIG_WRITE */ 2207 2208 2209/** 2210 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID 2211 * @ssid: Pointer to network configuration data 2212 * 2213 * This function must be called to update WPA PSK when either SSID or the 2214 * passphrase has changed for the network configuration. 2215 */ 2216void wpa_config_update_psk(struct wpa_ssid *ssid) 2217{ 2218#ifndef CONFIG_NO_PBKDF2 2219 pbkdf2_sha1(ssid->passphrase, 2220 (char *) ssid->ssid, ssid->ssid_len, 4096, 2221 ssid->psk, PMK_LEN); 2222 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", 2223 ssid->psk, PMK_LEN); 2224 ssid->psk_set = 1; 2225#endif /* CONFIG_NO_PBKDF2 */ 2226} 2227 2228 2229#ifndef CONFIG_NO_CONFIG_BLOBS 2230/** 2231 * wpa_config_get_blob - Get a named configuration blob 2232 * @config: Configuration data from wpa_config_read() 2233 * @name: Name of the blob 2234 * Returns: Pointer to blob data or %NULL if not found 2235 */ 2236const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config, 2237 const char *name) 2238{ 2239 struct wpa_config_blob *blob = config->blobs; 2240 2241 while (blob) { 2242 if (os_strcmp(blob->name, name) == 0) 2243 return blob; 2244 blob = blob->next; 2245 } 2246 return NULL; 2247} 2248 2249 2250/** 2251 * wpa_config_set_blob - Set or add a named configuration blob 2252 * @config: Configuration data from wpa_config_read() 2253 * @blob: New value for the blob 2254 * 2255 * Adds a new configuration blob or replaces the current value of an existing 2256 * blob. 2257 */ 2258void wpa_config_set_blob(struct wpa_config *config, 2259 struct wpa_config_blob *blob) 2260{ 2261 wpa_config_remove_blob(config, blob->name); 2262 blob->next = config->blobs; 2263 config->blobs = blob; 2264} 2265 2266 2267/** 2268 * wpa_config_free_blob - Free blob data 2269 * @blob: Pointer to blob to be freed 2270 */ 2271void wpa_config_free_blob(struct wpa_config_blob *blob) 2272{ 2273 if (blob) { 2274 os_free(blob->name); 2275 os_free(blob->data); 2276 os_free(blob); 2277 } 2278} 2279 2280 2281/** 2282 * wpa_config_remove_blob - Remove a named configuration blob 2283 * @config: Configuration data from wpa_config_read() 2284 * @name: Name of the blob to remove 2285 * Returns: 0 if blob was removed or -1 if blob was not found 2286 */ 2287int wpa_config_remove_blob(struct wpa_config *config, const char *name) 2288{ 2289 struct wpa_config_blob *pos = config->blobs, *prev = NULL; 2290 2291 while (pos) { 2292 if (os_strcmp(pos->name, name) == 0) { 2293 if (prev) 2294 prev->next = pos->next; 2295 else 2296 config->blobs = pos->next; 2297 wpa_config_free_blob(pos); 2298 return 0; 2299 } 2300 prev = pos; 2301 pos = pos->next; 2302 } 2303 2304 return -1; 2305} 2306#endif /* CONFIG_NO_CONFIG_BLOBS */ 2307 2308 2309/** 2310 * wpa_config_alloc_empty - Allocate an empty configuration 2311 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain 2312 * socket 2313 * @driver_param: Driver parameters 2314 * Returns: Pointer to allocated configuration data or %NULL on failure 2315 */ 2316struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, 2317 const char *driver_param) 2318{ 2319 struct wpa_config *config; 2320 2321 config = os_zalloc(sizeof(*config)); 2322 if (config == NULL) 2323 return NULL; 2324 config->eapol_version = DEFAULT_EAPOL_VERSION; 2325 config->ap_scan = DEFAULT_AP_SCAN; 2326 config->fast_reauth = DEFAULT_FAST_REAUTH; 2327 config->p2p_go_intent = DEFAULT_P2P_GO_INTENT; 2328 config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS; 2329 config->bss_max_count = DEFAULT_BSS_MAX_COUNT; 2330 config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE; 2331 config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT; 2332 config->max_num_sta = DEFAULT_MAX_NUM_STA; 2333 config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE; 2334 2335 if (ctrl_interface) 2336 config->ctrl_interface = os_strdup(ctrl_interface); 2337 if (driver_param) 2338 config->driver_param = os_strdup(driver_param); 2339 2340 return config; 2341} 2342 2343 2344#ifndef CONFIG_NO_STDOUT_DEBUG 2345/** 2346 * wpa_config_debug_dump_networks - Debug dump of configured networks 2347 * @config: Configuration data from wpa_config_read() 2348 */ 2349void wpa_config_debug_dump_networks(struct wpa_config *config) 2350{ 2351 int prio; 2352 struct wpa_ssid *ssid; 2353 2354 for (prio = 0; prio < config->num_prio; prio++) { 2355 ssid = config->pssid[prio]; 2356 wpa_printf(MSG_DEBUG, "Priority group %d", 2357 ssid->priority); 2358 while (ssid) { 2359 wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", 2360 ssid->id, 2361 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 2362 ssid = ssid->pnext; 2363 } 2364 } 2365} 2366#endif /* CONFIG_NO_STDOUT_DEBUG */ 2367 2368 2369struct global_parse_data { 2370 char *name; 2371 int (*parser)(const struct global_parse_data *data, 2372 struct wpa_config *config, int line, const char *value); 2373 void *param1, *param2, *param3; 2374 unsigned int changed_flag; 2375}; 2376 2377 2378static int wpa_global_config_parse_int(const struct global_parse_data *data, 2379 struct wpa_config *config, int line, 2380 const char *pos) 2381{ 2382 int *dst; 2383 dst = (int *) (((u8 *) config) + (long) data->param1); 2384 *dst = atoi(pos); 2385 wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); 2386 2387 if (data->param2 && *dst < (long) data->param2) { 2388 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " 2389 "min_value=%ld)", line, data->name, *dst, 2390 (long) data->param2); 2391 *dst = (long) data->param2; 2392 return -1; 2393 } 2394 2395 if (data->param3 && *dst > (long) data->param3) { 2396 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " 2397 "max_value=%ld)", line, data->name, *dst, 2398 (long) data->param3); 2399 *dst = (long) data->param3; 2400 return -1; 2401 } 2402 2403 return 0; 2404} 2405 2406 2407static int wpa_global_config_parse_str(const struct global_parse_data *data, 2408 struct wpa_config *config, int line, 2409 const char *pos) 2410{ 2411 size_t len; 2412 char **dst, *tmp; 2413 2414 len = os_strlen(pos); 2415 if (data->param2 && len < (size_t) data->param2) { 2416 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " 2417 "min_len=%ld)", line, data->name, 2418 (unsigned long) len, (long) data->param2); 2419 return -1; 2420 } 2421 2422 if (data->param3 && len > (size_t) data->param3) { 2423 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " 2424 "max_len=%ld)", line, data->name, 2425 (unsigned long) len, (long) data->param3); 2426 return -1; 2427 } 2428 2429 tmp = os_strdup(pos); 2430 if (tmp == NULL) 2431 return -1; 2432 2433 dst = (char **) (((u8 *) config) + (long) data->param1); 2434 os_free(*dst); 2435 *dst = tmp; 2436 wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); 2437 2438 return 0; 2439} 2440 2441 2442static int wpa_config_process_country(const struct global_parse_data *data, 2443 struct wpa_config *config, int line, 2444 const char *pos) 2445{ 2446 if (!pos[0] || !pos[1]) { 2447 wpa_printf(MSG_DEBUG, "Invalid country set"); 2448 return -1; 2449 } 2450 config->country[0] = pos[0]; 2451 config->country[1] = pos[1]; 2452 wpa_printf(MSG_DEBUG, "country='%c%c'", 2453 config->country[0], config->country[1]); 2454 return 0; 2455} 2456 2457 2458static int wpa_config_process_load_dynamic_eap( 2459 const struct global_parse_data *data, struct wpa_config *config, 2460 int line, const char *so) 2461{ 2462 int ret; 2463 wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); 2464 ret = eap_peer_method_load(so); 2465 if (ret == -2) { 2466 wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not " 2467 "reloading."); 2468 } else if (ret) { 2469 wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP " 2470 "method '%s'.", line, so); 2471 return -1; 2472 } 2473 2474 return 0; 2475} 2476 2477 2478#ifdef CONFIG_WPS 2479 2480static int wpa_config_process_uuid(const struct global_parse_data *data, 2481 struct wpa_config *config, int line, 2482 const char *pos) 2483{ 2484 char buf[40]; 2485 if (uuid_str2bin(pos, config->uuid)) { 2486 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); 2487 return -1; 2488 } 2489 uuid_bin2str(config->uuid, buf, sizeof(buf)); 2490 wpa_printf(MSG_DEBUG, "uuid=%s", buf); 2491 return 0; 2492} 2493 2494 2495static int wpa_config_process_device_type( 2496 const struct global_parse_data *data, 2497 struct wpa_config *config, int line, const char *pos) 2498{ 2499 return wps_dev_type_str2bin(pos, config->device_type); 2500} 2501 2502 2503static int wpa_config_process_os_version(const struct global_parse_data *data, 2504 struct wpa_config *config, int line, 2505 const char *pos) 2506{ 2507 if (hexstr2bin(pos, config->os_version, 4)) { 2508 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line); 2509 return -1; 2510 } 2511 wpa_printf(MSG_DEBUG, "os_version=%08x", 2512 WPA_GET_BE32(config->os_version)); 2513 return 0; 2514} 2515 2516#endif /* CONFIG_WPS */ 2517 2518#ifdef CONFIG_P2P 2519static int wpa_config_process_sec_device_type( 2520 const struct global_parse_data *data, 2521 struct wpa_config *config, int line, const char *pos) 2522{ 2523 int idx; 2524 2525 if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) { 2526 wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type " 2527 "items", line); 2528 return -1; 2529 } 2530 2531 idx = config->num_sec_device_types; 2532 2533 if (wps_dev_type_str2bin(pos, config->sec_device_type[idx])) 2534 return -1; 2535 2536 config->num_sec_device_types++; 2537 return 0; 2538} 2539#endif /* CONFIG_P2P */ 2540 2541 2542static int wpa_config_process_hessid( 2543 const struct global_parse_data *data, 2544 struct wpa_config *config, int line, const char *pos) 2545{ 2546 if (hwaddr_aton2(pos, config->hessid) < 0) { 2547 wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'", 2548 line, pos); 2549 return -1; 2550 } 2551 2552 return 0; 2553} 2554 2555 2556#ifdef OFFSET 2557#undef OFFSET 2558#endif /* OFFSET */ 2559/* OFFSET: Get offset of a variable within the wpa_config structure */ 2560#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v) 2561 2562#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL 2563#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL 2564#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f) 2565#define INT(f) _INT(f), NULL, NULL 2566#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max 2567#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f) 2568#define STR(f) _STR(f), NULL, NULL 2569#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max 2570 2571static const struct global_parse_data global_fields[] = { 2572#ifdef CONFIG_CTRL_IFACE 2573 { STR(ctrl_interface), 0 }, 2574 { STR(ctrl_interface_group), 0 } /* deprecated */, 2575#endif /* CONFIG_CTRL_IFACE */ 2576 { INT_RANGE(eapol_version, 1, 2), 0 }, 2577 { INT(ap_scan), 0 }, 2578 { INT(fast_reauth), 0 }, 2579 { STR(opensc_engine_path), 0 }, 2580 { STR(pkcs11_engine_path), 0 }, 2581 { STR(pkcs11_module_path), 0 }, 2582 { STR(driver_param), 0 }, 2583 { INT(dot11RSNAConfigPMKLifetime), 0 }, 2584 { INT(dot11RSNAConfigPMKReauthThreshold), 0 }, 2585 { INT(dot11RSNAConfigSATimeout), 0 }, 2586#ifndef CONFIG_NO_CONFIG_WRITE 2587 { INT(update_config), 0 }, 2588#endif /* CONFIG_NO_CONFIG_WRITE */ 2589 { FUNC_NO_VAR(load_dynamic_eap), 0 }, 2590#ifdef CONFIG_WPS 2591 { FUNC(uuid), CFG_CHANGED_UUID }, 2592 { STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME }, 2593 { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING }, 2594 { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING }, 2595 { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING }, 2596 { STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING }, 2597 { FUNC(device_type), CFG_CHANGED_DEVICE_TYPE }, 2598 { FUNC(os_version), CFG_CHANGED_OS_VERSION }, 2599 { STR(config_methods), CFG_CHANGED_CONFIG_METHODS }, 2600 { INT_RANGE(wps_cred_processing, 0, 2), 0 }, 2601#endif /* CONFIG_WPS */ 2602#ifdef CONFIG_P2P 2603 { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE }, 2604 { INT(p2p_listen_reg_class), 0 }, 2605 { INT(p2p_listen_channel), 0 }, 2606 { INT(p2p_oper_reg_class), 0 }, 2607 { INT(p2p_oper_channel), 0 }, 2608 { INT_RANGE(p2p_go_intent, 0, 15), 0 }, 2609 { STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX }, 2610 { INT_RANGE(persistent_reconnect, 0, 1), 0 }, 2611 { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS }, 2612 { INT(p2p_group_idle), 0 }, 2613#endif /* CONFIG_P2P */ 2614 { FUNC(country), CFG_CHANGED_COUNTRY }, 2615 { INT(bss_max_count), 0 }, 2616 { INT(bss_expiration_age), 0 }, 2617 { INT(bss_expiration_scan_count), 0 }, 2618 { INT_RANGE(filter_ssids, 0, 1), 0 }, 2619 { INT(max_num_sta), 0 }, 2620 { INT_RANGE(disassoc_low_ack, 0, 1), 0 }, 2621 { STR(home_realm), 0 }, 2622 { STR(home_username), 0 }, 2623 { STR(home_password), 0 }, 2624 { STR(home_ca_cert), 0 }, 2625 { STR(home_imsi), 0 }, 2626 { STR(home_milenage), 0 }, 2627 { INT_RANGE(interworking, 0, 1), 0 }, 2628 { FUNC(hessid), 0 }, 2629 { INT_RANGE(access_network_type, 0, 15), 0 } 2630}; 2631 2632#undef FUNC 2633#undef _INT 2634#undef INT 2635#undef INT_RANGE 2636#undef _STR 2637#undef STR 2638#undef STR_RANGE 2639#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0])) 2640 2641 2642int wpa_config_process_global(struct wpa_config *config, char *pos, int line) 2643{ 2644 size_t i; 2645 int ret = 0; 2646 2647 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 2648 const struct global_parse_data *field = &global_fields[i]; 2649 size_t flen = os_strlen(field->name); 2650 if (os_strncmp(pos, field->name, flen) != 0 || 2651 pos[flen] != '=') 2652 continue; 2653 2654 if (field->parser(field, config, line, pos + flen + 1)) { 2655 wpa_printf(MSG_ERROR, "Line %d: failed to " 2656 "parse '%s'.", line, pos); 2657 ret = -1; 2658 } 2659 config->changed_parameters |= field->changed_flag; 2660 break; 2661 } 2662 if (i == NUM_GLOBAL_FIELDS) { 2663 if (line < 0) 2664 return -1; 2665 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", 2666 line, pos); 2667 ret = -1; 2668 } 2669 2670 return ret; 2671} 2672