config.c revision c5da5d2e24c1148757b2493dc351c4adec48360d
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/* Helper macros for network block parser */ 1375 1376#ifdef OFFSET 1377#undef OFFSET 1378#endif /* OFFSET */ 1379/* OFFSET: Get offset of a variable within the wpa_ssid structure */ 1380#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v) 1381 1382/* STR: Define a string variable for an ASCII string; f = field name */ 1383#ifdef NO_CONFIG_WRITE 1384#define _STR(f) #f, wpa_config_parse_str, OFFSET(f) 1385#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f) 1386#else /* NO_CONFIG_WRITE */ 1387#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f) 1388#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f) 1389#endif /* NO_CONFIG_WRITE */ 1390#define STR(f) _STR(f), NULL, NULL, NULL, 0 1391#define STRe(f) _STRe(f), NULL, NULL, NULL, 0 1392#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1 1393#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1 1394 1395/* STR_LEN: Define a string variable with a separate variable for storing the 1396 * data length. Unlike STR(), this can be used to store arbitrary binary data 1397 * (i.e., even nul termination character). */ 1398#define _STR_LEN(f) _STR(f), OFFSET(f ## _len) 1399#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len) 1400#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0 1401#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0 1402#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1 1403 1404/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length 1405 * explicitly specified. */ 1406#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max) 1407#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0 1408#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1 1409 1410#ifdef NO_CONFIG_WRITE 1411#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0 1412#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0 1413#else /* NO_CONFIG_WRITE */ 1414#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 1415 OFFSET(f), (void *) 0 1416#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 1417 OFFSET(eap.f), (void *) 0 1418#ifdef WPA_UNICODE_SSID 1419/* STR_* variants that do not force conversion to ASCII */ 1420#define _STR_UNICODE(f) #f, wpa_config_parse_str, wpa_config_write_str_unicode, OFFSET(f) 1421#define STR_UNICODE(f) _STR_UNICODE(f), NULL, NULL, NULL, 0 1422#define _STR_LEN_UNICODE(f) _STR_UNICODE(f), OFFSET(f ## _len) 1423#define STR_LEN_UNICODE(f) _STR_LEN_UNICODE(f), NULL, NULL, 0 1424#define _STR_RANGE_UNICODE(f, min, max) _STR_LEN_UNICODE(f), (void *) (min), (void *) (max) 1425#define STR_RANGE_UNICODE(f, min, max) _STR_RANGE_UNICODE(f, min, max), 0 1426#endif 1427#endif /* NO_CONFIG_WRITE */ 1428 1429/* INT: Define an integer variable */ 1430#define INT(f) _INT(f), NULL, NULL, 0 1431#define INTe(f) _INTe(f), NULL, NULL, 0 1432 1433/* INT_RANGE: Define an integer variable with allowed value range */ 1434#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0 1435 1436/* FUNC: Define a configuration variable that uses a custom function for 1437 * parsing and writing the value. */ 1438#ifdef NO_CONFIG_WRITE 1439#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL 1440#else /* NO_CONFIG_WRITE */ 1441#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \ 1442 NULL, NULL, NULL, NULL 1443#endif /* NO_CONFIG_WRITE */ 1444#define FUNC(f) _FUNC(f), 0 1445#define FUNC_KEY(f) _FUNC(f), 1 1446 1447/* 1448 * Table of network configuration variables. This table is used to parse each 1449 * network configuration variable, e.g., each line in wpa_supplicant.conf file 1450 * that is inside a network block. 1451 * 1452 * This table is generated using the helper macros defined above and with 1453 * generous help from the C pre-processor. The field name is stored as a string 1454 * into .name and for STR and INT types, the offset of the target buffer within 1455 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar 1456 * offset to the field containing the length of the configuration variable. 1457 * .param3 and .param4 can be used to mark the allowed range (length for STR 1458 * and value for INT). 1459 * 1460 * For each configuration line in wpa_supplicant.conf, the parser goes through 1461 * this table and select the entry that matches with the field name. The parser 1462 * function (.parser) is then called to parse the actual value of the field. 1463 * 1464 * This kind of mechanism makes it easy to add new configuration parameters, 1465 * since only one line needs to be added into this table and into the 1466 * struct wpa_ssid definition if the new variable is either a string or 1467 * integer. More complex types will need to use their own parser and writer 1468 * functions. 1469 */ 1470static const struct parse_data ssid_fields[] = { 1471#ifdef WPA_UNICODE_SSID 1472 { STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) }, 1473#else 1474 { STR_RANGE(ssid, 0, MAX_SSID_LEN) }, 1475#endif 1476 { INT_RANGE(scan_ssid, 0, 1) }, 1477 { FUNC(bssid) }, 1478 { FUNC_KEY(psk) }, 1479 { FUNC(proto) }, 1480 { FUNC(key_mgmt) }, 1481 { FUNC(pairwise) }, 1482 { FUNC(group) }, 1483 { FUNC(auth_alg) }, 1484 { FUNC(scan_freq) }, 1485 { FUNC(freq_list) }, 1486#ifdef IEEE8021X_EAPOL 1487 { FUNC(eap) }, 1488 { STR_LENe(identity) }, 1489 { STR_LENe(anonymous_identity) }, 1490 { FUNC_KEY(password) }, 1491 { STRe(ca_cert) }, 1492 { STRe(ca_path) }, 1493 { STRe(client_cert) }, 1494 { STRe(private_key) }, 1495 { STR_KEYe(private_key_passwd) }, 1496 { STRe(dh_file) }, 1497 { STRe(subject_match) }, 1498 { STRe(altsubject_match) }, 1499 { STRe(ca_cert2) }, 1500 { STRe(ca_path2) }, 1501 { STRe(client_cert2) }, 1502 { STRe(private_key2) }, 1503 { STR_KEYe(private_key2_passwd) }, 1504 { STRe(dh_file2) }, 1505 { STRe(subject_match2) }, 1506 { STRe(altsubject_match2) }, 1507 { STRe(phase1) }, 1508 { STRe(phase2) }, 1509 { STRe(pcsc) }, 1510 { STR_KEYe(pin) }, 1511 { STRe(engine_id) }, 1512 { STRe(key_id) }, 1513 { STRe(cert_id) }, 1514 { STRe(ca_cert_id) }, 1515 { STR_KEYe(pin2) }, 1516 { STRe(engine2_id) }, 1517 { STRe(key2_id) }, 1518 { STRe(cert2_id) }, 1519 { STRe(ca_cert2_id) }, 1520 { INTe(engine) }, 1521 { INTe(engine2) }, 1522 { INT(eapol_flags) }, 1523#endif /* IEEE8021X_EAPOL */ 1524 { FUNC_KEY(wep_key0) }, 1525 { FUNC_KEY(wep_key1) }, 1526 { FUNC_KEY(wep_key2) }, 1527 { FUNC_KEY(wep_key3) }, 1528 { INT(wep_tx_keyidx) }, 1529 { INT(priority) }, 1530#ifdef IEEE8021X_EAPOL 1531 { INT(eap_workaround) }, 1532 { STRe(pac_file) }, 1533 { INTe(fragment_size) }, 1534#endif /* IEEE8021X_EAPOL */ 1535 { INT_RANGE(mode, 0, 4) }, 1536 { INT_RANGE(proactive_key_caching, 0, 1) }, 1537 { INT_RANGE(disabled, 0, 2) }, 1538 { STR(id_str) }, 1539#ifdef CONFIG_IEEE80211W 1540 { INT_RANGE(ieee80211w, 0, 2) }, 1541#endif /* CONFIG_IEEE80211W */ 1542 { INT_RANGE(peerkey, 0, 1) }, 1543 { INT_RANGE(mixed_cell, 0, 1) }, 1544 { INT_RANGE(frequency, 0, 10000) }, 1545 { INT(wpa_ptk_rekey) }, 1546 { STR(bgscan) }, 1547}; 1548 1549#ifdef WPA_UNICODE_SSID 1550#undef _STR_UNICODE 1551#undef STR_UNICODE 1552#undef _STR_LEN_UNICODE 1553#undef STR_LEN_UNICODE 1554#undef _STR_RANGE_UNICODE 1555#undef STR_RANGE_UNICODE 1556#endif 1557 1558#undef OFFSET 1559#undef _STR 1560#undef STR 1561#undef STR_KEY 1562#undef _STR_LEN 1563#undef STR_LEN 1564#undef STR_LEN_KEY 1565#undef _STR_RANGE 1566#undef STR_RANGE 1567#undef STR_RANGE_KEY 1568#undef _INT 1569#undef INT 1570#undef INT_RANGE 1571#undef _FUNC 1572#undef FUNC 1573#undef FUNC_KEY 1574#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0])) 1575 1576 1577/** 1578 * wpa_config_add_prio_network - Add a network to priority lists 1579 * @config: Configuration data from wpa_config_read() 1580 * @ssid: Pointer to the network configuration to be added to the list 1581 * Returns: 0 on success, -1 on failure 1582 * 1583 * This function is used to add a network block to the priority list of 1584 * networks. This must be called for each network when reading in the full 1585 * configuration. In addition, this can be used indirectly when updating 1586 * priorities by calling wpa_config_update_prio_list(). 1587 */ 1588int wpa_config_add_prio_network(struct wpa_config *config, 1589 struct wpa_ssid *ssid) 1590{ 1591 int prio; 1592 struct wpa_ssid *prev, **nlist; 1593 1594 /* 1595 * Add to an existing priority list if one is available for the 1596 * configured priority level for this network. 1597 */ 1598 for (prio = 0; prio < config->num_prio; prio++) { 1599 prev = config->pssid[prio]; 1600 if (prev->priority == ssid->priority) { 1601 while (prev->pnext) 1602 prev = prev->pnext; 1603 prev->pnext = ssid; 1604 return 0; 1605 } 1606 } 1607 1608 /* First network for this priority - add a new priority list */ 1609 nlist = os_realloc(config->pssid, 1610 (config->num_prio + 1) * sizeof(struct wpa_ssid *)); 1611 if (nlist == NULL) 1612 return -1; 1613 1614 for (prio = 0; prio < config->num_prio; prio++) { 1615 if (nlist[prio]->priority < ssid->priority) 1616 break; 1617 } 1618 1619 os_memmove(&nlist[prio + 1], &nlist[prio], 1620 (config->num_prio - prio) * sizeof(struct wpa_ssid *)); 1621 1622 nlist[prio] = ssid; 1623 config->num_prio++; 1624 config->pssid = nlist; 1625 1626 return 0; 1627} 1628 1629 1630/** 1631 * wpa_config_update_prio_list - Update network priority list 1632 * @config: Configuration data from wpa_config_read() 1633 * Returns: 0 on success, -1 on failure 1634 * 1635 * This function is called to update the priority list of networks in the 1636 * configuration when a network is being added or removed. This is also called 1637 * if a priority for a network is changed. 1638 */ 1639int wpa_config_update_prio_list(struct wpa_config *config) 1640{ 1641 struct wpa_ssid *ssid; 1642 int ret = 0; 1643 1644 os_free(config->pssid); 1645 config->pssid = NULL; 1646 config->num_prio = 0; 1647 1648 ssid = config->ssid; 1649 while (ssid) { 1650 ssid->pnext = NULL; 1651 if (wpa_config_add_prio_network(config, ssid) < 0) 1652 ret = -1; 1653 ssid = ssid->next; 1654 } 1655 1656 return ret; 1657} 1658 1659 1660#ifdef IEEE8021X_EAPOL 1661static void eap_peer_config_free(struct eap_peer_config *eap) 1662{ 1663 os_free(eap->eap_methods); 1664 os_free(eap->identity); 1665 os_free(eap->anonymous_identity); 1666 os_free(eap->password); 1667 os_free(eap->ca_cert); 1668 os_free(eap->ca_path); 1669 os_free(eap->client_cert); 1670 os_free(eap->private_key); 1671 os_free(eap->private_key_passwd); 1672 os_free(eap->dh_file); 1673 os_free(eap->subject_match); 1674 os_free(eap->altsubject_match); 1675 os_free(eap->ca_cert2); 1676 os_free(eap->ca_path2); 1677 os_free(eap->client_cert2); 1678 os_free(eap->private_key2); 1679 os_free(eap->private_key2_passwd); 1680 os_free(eap->dh_file2); 1681 os_free(eap->subject_match2); 1682 os_free(eap->altsubject_match2); 1683 os_free(eap->phase1); 1684 os_free(eap->phase2); 1685 os_free(eap->pcsc); 1686 os_free(eap->pin); 1687 os_free(eap->engine_id); 1688 os_free(eap->key_id); 1689 os_free(eap->cert_id); 1690 os_free(eap->ca_cert_id); 1691 os_free(eap->key2_id); 1692 os_free(eap->cert2_id); 1693 os_free(eap->ca_cert2_id); 1694 os_free(eap->pin2); 1695 os_free(eap->engine2_id); 1696 os_free(eap->otp); 1697 os_free(eap->pending_req_otp); 1698 os_free(eap->pac_file); 1699 os_free(eap->new_password); 1700} 1701#endif /* IEEE8021X_EAPOL */ 1702 1703 1704/** 1705 * wpa_config_free_ssid - Free network/ssid configuration data 1706 * @ssid: Configuration data for the network 1707 * 1708 * This function frees all resources allocated for the network configuration 1709 * data. 1710 */ 1711void wpa_config_free_ssid(struct wpa_ssid *ssid) 1712{ 1713 os_free(ssid->ssid); 1714 os_free(ssid->passphrase); 1715#ifdef IEEE8021X_EAPOL 1716 eap_peer_config_free(&ssid->eap); 1717#endif /* IEEE8021X_EAPOL */ 1718 os_free(ssid->id_str); 1719 os_free(ssid->scan_freq); 1720 os_free(ssid->freq_list); 1721 os_free(ssid->bgscan); 1722 os_free(ssid); 1723} 1724 1725 1726/** 1727 * wpa_config_free - Free configuration data 1728 * @config: Configuration data from wpa_config_read() 1729 * 1730 * This function frees all resources allocated for the configuration data by 1731 * wpa_config_read(). 1732 */ 1733void wpa_config_free(struct wpa_config *config) 1734{ 1735#ifndef CONFIG_NO_CONFIG_BLOBS 1736 struct wpa_config_blob *blob, *prevblob; 1737#endif /* CONFIG_NO_CONFIG_BLOBS */ 1738 struct wpa_ssid *ssid, *prev = NULL; 1739 1740 ssid = config->ssid; 1741 while (ssid) { 1742 prev = ssid; 1743 ssid = ssid->next; 1744 wpa_config_free_ssid(prev); 1745 } 1746 1747#ifndef CONFIG_NO_CONFIG_BLOBS 1748 blob = config->blobs; 1749 prevblob = NULL; 1750 while (blob) { 1751 prevblob = blob; 1752 blob = blob->next; 1753 wpa_config_free_blob(prevblob); 1754 } 1755#endif /* CONFIG_NO_CONFIG_BLOBS */ 1756 1757 os_free(config->ctrl_interface); 1758 os_free(config->ctrl_interface_group); 1759 os_free(config->opensc_engine_path); 1760 os_free(config->pkcs11_engine_path); 1761 os_free(config->pkcs11_module_path); 1762 os_free(config->driver_param); 1763 os_free(config->device_name); 1764 os_free(config->manufacturer); 1765 os_free(config->model_name); 1766 os_free(config->model_number); 1767 os_free(config->serial_number); 1768 os_free(config->config_methods); 1769 os_free(config->p2p_ssid_postfix); 1770 os_free(config->pssid); 1771 os_free(config); 1772} 1773 1774 1775/** 1776 * wpa_config_foreach_network - Iterate over each configured network 1777 * @config: Configuration data from wpa_config_read() 1778 * @func: Callback function to process each network 1779 * @arg: Opaque argument to pass to callback function 1780 * 1781 * Iterate over the set of configured networks calling the specified 1782 * function for each item. We guard against callbacks removing the 1783 * supplied network. 1784 */ 1785void wpa_config_foreach_network(struct wpa_config *config, 1786 void (*func)(void *, struct wpa_ssid *), 1787 void *arg) 1788{ 1789 struct wpa_ssid *ssid, *next; 1790 1791 ssid = config->ssid; 1792 while (ssid) { 1793 next = ssid->next; 1794 func(arg, ssid); 1795 ssid = next; 1796 } 1797} 1798 1799 1800/** 1801 * wpa_config_get_network - Get configured network based on id 1802 * @config: Configuration data from wpa_config_read() 1803 * @id: Unique network id to search for 1804 * Returns: Network configuration or %NULL if not found 1805 */ 1806struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id) 1807{ 1808 struct wpa_ssid *ssid; 1809 1810 ssid = config->ssid; 1811 while (ssid) { 1812 if (id == ssid->id) 1813 break; 1814 ssid = ssid->next; 1815 } 1816 1817 return ssid; 1818} 1819 1820 1821/** 1822 * wpa_config_add_network - Add a new network with empty configuration 1823 * @config: Configuration data from wpa_config_read() 1824 * Returns: The new network configuration or %NULL if operation failed 1825 */ 1826struct wpa_ssid * wpa_config_add_network(struct wpa_config *config) 1827{ 1828 int id; 1829 struct wpa_ssid *ssid, *last = NULL; 1830 1831 id = -1; 1832 ssid = config->ssid; 1833 while (ssid) { 1834 if (ssid->id > id) 1835 id = ssid->id; 1836 last = ssid; 1837 ssid = ssid->next; 1838 } 1839 id++; 1840 1841 ssid = os_zalloc(sizeof(*ssid)); 1842 if (ssid == NULL) 1843 return NULL; 1844 ssid->id = id; 1845 if (last) 1846 last->next = ssid; 1847 else 1848 config->ssid = ssid; 1849 1850 wpa_config_update_prio_list(config); 1851 1852 return ssid; 1853} 1854 1855 1856/** 1857 * wpa_config_remove_network - Remove a configured network based on id 1858 * @config: Configuration data from wpa_config_read() 1859 * @id: Unique network id to search for 1860 * Returns: 0 on success, or -1 if the network was not found 1861 */ 1862int wpa_config_remove_network(struct wpa_config *config, int id) 1863{ 1864 struct wpa_ssid *ssid, *prev = NULL; 1865 1866 ssid = config->ssid; 1867 while (ssid) { 1868 if (id == ssid->id) 1869 break; 1870 prev = ssid; 1871 ssid = ssid->next; 1872 } 1873 1874 if (ssid == NULL) 1875 return -1; 1876 1877 if (prev) 1878 prev->next = ssid->next; 1879 else 1880 config->ssid = ssid->next; 1881 1882 wpa_config_update_prio_list(config); 1883 wpa_config_free_ssid(ssid); 1884 return 0; 1885} 1886 1887 1888/** 1889 * wpa_config_set_network_defaults - Set network default values 1890 * @ssid: Pointer to network configuration data 1891 */ 1892void wpa_config_set_network_defaults(struct wpa_ssid *ssid) 1893{ 1894 ssid->proto = DEFAULT_PROTO; 1895 ssid->pairwise_cipher = DEFAULT_PAIRWISE; 1896 ssid->group_cipher = DEFAULT_GROUP; 1897 ssid->key_mgmt = DEFAULT_KEY_MGMT; 1898#ifdef IEEE8021X_EAPOL 1899 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; 1900 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; 1901 ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE; 1902#endif /* IEEE8021X_EAPOL */ 1903} 1904 1905 1906/** 1907 * wpa_config_set - Set a variable in network configuration 1908 * @ssid: Pointer to network configuration data 1909 * @var: Variable name, e.g., "ssid" 1910 * @value: Variable value 1911 * @line: Line number in configuration file or 0 if not used 1912 * Returns: 0 on success, -1 on failure 1913 * 1914 * This function can be used to set network configuration variables based on 1915 * both the configuration file and management interface input. The value 1916 * parameter must be in the same format as the text-based configuration file is 1917 * using. For example, strings are using double quotation marks. 1918 */ 1919int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, 1920 int line) 1921{ 1922 size_t i; 1923 int ret = 0; 1924 1925 if (ssid == NULL || var == NULL || value == NULL) 1926 return -1; 1927 1928 for (i = 0; i < NUM_SSID_FIELDS; i++) { 1929 const struct parse_data *field = &ssid_fields[i]; 1930 if (os_strcmp(var, field->name) != 0) 1931 continue; 1932 1933 if (field->parser(field, ssid, line, value)) { 1934 if (line) { 1935 wpa_printf(MSG_ERROR, "Line %d: failed to " 1936 "parse %s '%s'.", line, var, value); 1937 } 1938 ret = -1; 1939 } 1940 break; 1941 } 1942 if (i == NUM_SSID_FIELDS) { 1943 if (line) { 1944 wpa_printf(MSG_ERROR, "Line %d: unknown network field " 1945 "'%s'.", line, var); 1946 } 1947 ret = -1; 1948 } 1949 1950 return ret; 1951} 1952 1953 1954/** 1955 * wpa_config_get_all - Get all options from network configuration 1956 * @ssid: Pointer to network configuration data 1957 * @get_keys: Determines if keys/passwords will be included in returned list 1958 * (if they may be exported) 1959 * Returns: %NULL terminated list of all set keys and their values in the form 1960 * of [key1, val1, key2, val2, ... , NULL] 1961 * 1962 * This function can be used to get list of all configured network properties. 1963 * The caller is responsible for freeing the returned list and all its 1964 * elements. 1965 */ 1966char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys) 1967{ 1968 const struct parse_data *field; 1969 char *key, *value; 1970 size_t i; 1971 char **props; 1972 int fields_num; 1973 1974 get_keys = get_keys && ssid->export_keys; 1975 1976 props = os_zalloc(sizeof(char *) * ((2 * NUM_SSID_FIELDS) + 1)); 1977 if (!props) 1978 return NULL; 1979 1980 fields_num = 0; 1981 for (i = 0; i < NUM_SSID_FIELDS; i++) { 1982 field = &ssid_fields[i]; 1983 if (field->key_data && !get_keys) 1984 continue; 1985 value = field->writer(field, ssid); 1986 if (value == NULL) 1987 continue; 1988 if (os_strlen(value) == 0) { 1989 os_free(value); 1990 continue; 1991 } 1992 1993 key = os_strdup(field->name); 1994 if (key == NULL) { 1995 os_free(value); 1996 goto err; 1997 } 1998 1999 props[fields_num * 2] = key; 2000 props[fields_num * 2 + 1] = value; 2001 2002 fields_num++; 2003 } 2004 2005 return props; 2006 2007err: 2008 value = *props; 2009 while (value) 2010 os_free(value++); 2011 os_free(props); 2012 return NULL; 2013} 2014 2015 2016#ifndef NO_CONFIG_WRITE 2017/** 2018 * wpa_config_get - Get a variable in network configuration 2019 * @ssid: Pointer to network configuration data 2020 * @var: Variable name, e.g., "ssid" 2021 * Returns: Value of the variable or %NULL on failure 2022 * 2023 * This function can be used to get network configuration variables. The 2024 * returned value is a copy of the configuration variable in text format, i.e,. 2025 * the same format that the text-based configuration file and wpa_config_set() 2026 * are using for the value. The caller is responsible for freeing the returned 2027 * value. 2028 */ 2029char * wpa_config_get(struct wpa_ssid *ssid, const char *var) 2030{ 2031 size_t i; 2032 2033 if (ssid == NULL || var == NULL) 2034 return NULL; 2035 2036 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2037 const struct parse_data *field = &ssid_fields[i]; 2038 if (os_strcmp(var, field->name) == 0) 2039 return field->writer(field, ssid); 2040 } 2041 2042 return NULL; 2043} 2044 2045 2046/** 2047 * wpa_config_get_no_key - Get a variable in network configuration (no keys) 2048 * @ssid: Pointer to network configuration data 2049 * @var: Variable name, e.g., "ssid" 2050 * Returns: Value of the variable or %NULL on failure 2051 * 2052 * This function can be used to get network configuration variable like 2053 * wpa_config_get(). The only difference is that this functions does not expose 2054 * key/password material from the configuration. In case a key/password field 2055 * is requested, the returned value is an empty string or %NULL if the variable 2056 * is not set or "*" if the variable is set (regardless of its value). The 2057 * returned value is a copy of the configuration variable in text format, i.e,. 2058 * the same format that the text-based configuration file and wpa_config_set() 2059 * are using for the value. The caller is responsible for freeing the returned 2060 * value. 2061 */ 2062char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var) 2063{ 2064 size_t i; 2065 2066 if (ssid == NULL || var == NULL) 2067 return NULL; 2068 2069 for (i = 0; i < NUM_SSID_FIELDS; i++) { 2070 const struct parse_data *field = &ssid_fields[i]; 2071 if (os_strcmp(var, field->name) == 0) { 2072 char *res = field->writer(field, ssid); 2073 if (field->key_data) { 2074 if (res && res[0]) { 2075 wpa_printf(MSG_DEBUG, "Do not allow " 2076 "key_data field to be " 2077 "exposed"); 2078 os_free(res); 2079 return os_strdup("*"); 2080 } 2081 2082 os_free(res); 2083 return NULL; 2084 } 2085 return res; 2086 } 2087 } 2088 2089 return NULL; 2090} 2091#endif /* NO_CONFIG_WRITE */ 2092 2093 2094/** 2095 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID 2096 * @ssid: Pointer to network configuration data 2097 * 2098 * This function must be called to update WPA PSK when either SSID or the 2099 * passphrase has changed for the network configuration. 2100 */ 2101void wpa_config_update_psk(struct wpa_ssid *ssid) 2102{ 2103#ifndef CONFIG_NO_PBKDF2 2104 pbkdf2_sha1(ssid->passphrase, 2105 (char *) ssid->ssid, ssid->ssid_len, 4096, 2106 ssid->psk, PMK_LEN); 2107 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", 2108 ssid->psk, PMK_LEN); 2109 ssid->psk_set = 1; 2110#endif /* CONFIG_NO_PBKDF2 */ 2111} 2112 2113 2114#ifndef CONFIG_NO_CONFIG_BLOBS 2115/** 2116 * wpa_config_get_blob - Get a named configuration blob 2117 * @config: Configuration data from wpa_config_read() 2118 * @name: Name of the blob 2119 * Returns: Pointer to blob data or %NULL if not found 2120 */ 2121const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config, 2122 const char *name) 2123{ 2124 struct wpa_config_blob *blob = config->blobs; 2125 2126 while (blob) { 2127 if (os_strcmp(blob->name, name) == 0) 2128 return blob; 2129 blob = blob->next; 2130 } 2131 return NULL; 2132} 2133 2134 2135/** 2136 * wpa_config_set_blob - Set or add a named configuration blob 2137 * @config: Configuration data from wpa_config_read() 2138 * @blob: New value for the blob 2139 * 2140 * Adds a new configuration blob or replaces the current value of an existing 2141 * blob. 2142 */ 2143void wpa_config_set_blob(struct wpa_config *config, 2144 struct wpa_config_blob *blob) 2145{ 2146 wpa_config_remove_blob(config, blob->name); 2147 blob->next = config->blobs; 2148 config->blobs = blob; 2149} 2150 2151 2152/** 2153 * wpa_config_free_blob - Free blob data 2154 * @blob: Pointer to blob to be freed 2155 */ 2156void wpa_config_free_blob(struct wpa_config_blob *blob) 2157{ 2158 if (blob) { 2159 os_free(blob->name); 2160 os_free(blob->data); 2161 os_free(blob); 2162 } 2163} 2164 2165 2166/** 2167 * wpa_config_remove_blob - Remove a named configuration blob 2168 * @config: Configuration data from wpa_config_read() 2169 * @name: Name of the blob to remove 2170 * Returns: 0 if blob was removed or -1 if blob was not found 2171 */ 2172int wpa_config_remove_blob(struct wpa_config *config, const char *name) 2173{ 2174 struct wpa_config_blob *pos = config->blobs, *prev = NULL; 2175 2176 while (pos) { 2177 if (os_strcmp(pos->name, name) == 0) { 2178 if (prev) 2179 prev->next = pos->next; 2180 else 2181 config->blobs = pos->next; 2182 wpa_config_free_blob(pos); 2183 return 0; 2184 } 2185 prev = pos; 2186 pos = pos->next; 2187 } 2188 2189 return -1; 2190} 2191#endif /* CONFIG_NO_CONFIG_BLOBS */ 2192 2193 2194/** 2195 * wpa_config_alloc_empty - Allocate an empty configuration 2196 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain 2197 * socket 2198 * @driver_param: Driver parameters 2199 * Returns: Pointer to allocated configuration data or %NULL on failure 2200 */ 2201struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, 2202 const char *driver_param) 2203{ 2204 struct wpa_config *config; 2205 2206 config = os_zalloc(sizeof(*config)); 2207 if (config == NULL) 2208 return NULL; 2209 config->eapol_version = DEFAULT_EAPOL_VERSION; 2210 config->ap_scan = DEFAULT_AP_SCAN; 2211 config->fast_reauth = DEFAULT_FAST_REAUTH; 2212 config->p2p_go_intent = DEFAULT_P2P_GO_INTENT; 2213 config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS; 2214 config->bss_max_count = DEFAULT_BSS_MAX_COUNT; 2215 config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE; 2216 config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT; 2217 config->max_num_sta = DEFAULT_MAX_NUM_STA; 2218 2219 if (ctrl_interface) 2220 config->ctrl_interface = os_strdup(ctrl_interface); 2221 if (driver_param) 2222 config->driver_param = os_strdup(driver_param); 2223 2224 return config; 2225} 2226 2227 2228#ifndef CONFIG_NO_STDOUT_DEBUG 2229/** 2230 * wpa_config_debug_dump_networks - Debug dump of configured networks 2231 * @config: Configuration data from wpa_config_read() 2232 */ 2233void wpa_config_debug_dump_networks(struct wpa_config *config) 2234{ 2235 int prio; 2236 struct wpa_ssid *ssid; 2237 2238 for (prio = 0; prio < config->num_prio; prio++) { 2239 ssid = config->pssid[prio]; 2240 wpa_printf(MSG_DEBUG, "Priority group %d", 2241 ssid->priority); 2242 while (ssid) { 2243 wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", 2244 ssid->id, 2245 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 2246 ssid = ssid->pnext; 2247 } 2248 } 2249} 2250#endif /* CONFIG_NO_STDOUT_DEBUG */ 2251 2252 2253struct global_parse_data { 2254 char *name; 2255 int (*parser)(const struct global_parse_data *data, 2256 struct wpa_config *config, int line, const char *value); 2257 void *param1, *param2, *param3; 2258 unsigned int changed_flag; 2259}; 2260 2261 2262static int wpa_global_config_parse_int(const struct global_parse_data *data, 2263 struct wpa_config *config, int line, 2264 const char *pos) 2265{ 2266 int *dst; 2267 dst = (int *) (((u8 *) config) + (long) data->param1); 2268 *dst = atoi(pos); 2269 wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); 2270 2271 if (data->param2 && *dst < (long) data->param2) { 2272 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " 2273 "min_value=%ld)", line, data->name, *dst, 2274 (long) data->param2); 2275 *dst = (long) data->param2; 2276 return -1; 2277 } 2278 2279 if (data->param3 && *dst > (long) data->param3) { 2280 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " 2281 "max_value=%ld)", line, data->name, *dst, 2282 (long) data->param3); 2283 *dst = (long) data->param3; 2284 return -1; 2285 } 2286 2287 return 0; 2288} 2289 2290 2291static int wpa_global_config_parse_str(const struct global_parse_data *data, 2292 struct wpa_config *config, int line, 2293 const char *pos) 2294{ 2295 size_t len; 2296 char **dst, *tmp; 2297 2298 len = os_strlen(pos); 2299 if (data->param2 && len < (size_t) data->param2) { 2300 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " 2301 "min_len=%ld)", line, data->name, 2302 (unsigned long) len, (long) data->param2); 2303 return -1; 2304 } 2305 2306 if (data->param3 && len > (size_t) data->param3) { 2307 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " 2308 "max_len=%ld)", line, data->name, 2309 (unsigned long) len, (long) data->param3); 2310 return -1; 2311 } 2312 2313 tmp = os_strdup(pos); 2314 if (tmp == NULL) 2315 return -1; 2316 2317 dst = (char **) (((u8 *) config) + (long) data->param1); 2318 os_free(*dst); 2319 *dst = tmp; 2320 wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); 2321 2322 return 0; 2323} 2324 2325 2326static int wpa_config_process_country(const struct global_parse_data *data, 2327 struct wpa_config *config, int line, 2328 const char *pos) 2329{ 2330 if (!pos[0] || !pos[1]) { 2331 wpa_printf(MSG_DEBUG, "Invalid country set"); 2332 return -1; 2333 } 2334 config->country[0] = pos[0]; 2335 config->country[1] = pos[1]; 2336 wpa_printf(MSG_DEBUG, "country='%c%c'", 2337 config->country[0], config->country[1]); 2338 return 0; 2339} 2340 2341 2342static int wpa_config_process_load_dynamic_eap( 2343 const struct global_parse_data *data, struct wpa_config *config, 2344 int line, const char *so) 2345{ 2346 int ret; 2347 wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); 2348 ret = eap_peer_method_load(so); 2349 if (ret == -2) { 2350 wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not " 2351 "reloading."); 2352 } else if (ret) { 2353 wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP " 2354 "method '%s'.", line, so); 2355 return -1; 2356 } 2357 2358 return 0; 2359} 2360 2361 2362#ifdef CONFIG_WPS 2363 2364static int wpa_config_process_uuid(const struct global_parse_data *data, 2365 struct wpa_config *config, int line, 2366 const char *pos) 2367{ 2368 char buf[40]; 2369 if (uuid_str2bin(pos, config->uuid)) { 2370 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); 2371 return -1; 2372 } 2373 uuid_bin2str(config->uuid, buf, sizeof(buf)); 2374 wpa_printf(MSG_DEBUG, "uuid=%s", buf); 2375 return 0; 2376} 2377 2378 2379static int wpa_config_process_device_type( 2380 const struct global_parse_data *data, 2381 struct wpa_config *config, int line, const char *pos) 2382{ 2383 return wps_dev_type_str2bin(pos, config->device_type); 2384} 2385 2386 2387static int wpa_config_process_os_version(const struct global_parse_data *data, 2388 struct wpa_config *config, int line, 2389 const char *pos) 2390{ 2391 if (hexstr2bin(pos, config->os_version, 4)) { 2392 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line); 2393 return -1; 2394 } 2395 wpa_printf(MSG_DEBUG, "os_version=%08x", 2396 WPA_GET_BE32(config->os_version)); 2397 return 0; 2398} 2399 2400#endif /* CONFIG_WPS */ 2401 2402#ifdef CONFIG_P2P 2403static int wpa_config_process_sec_device_type( 2404 const struct global_parse_data *data, 2405 struct wpa_config *config, int line, const char *pos) 2406{ 2407 int idx; 2408 2409 if (config->num_sec_device_types >= MAX_SEC_DEVICE_TYPES) { 2410 wpa_printf(MSG_ERROR, "Line %d: too many sec_device_type " 2411 "items", line); 2412 return -1; 2413 } 2414 2415 idx = config->num_sec_device_types; 2416 2417 if (wps_dev_type_str2bin(pos, config->sec_device_type[idx])) 2418 return -1; 2419 2420 config->num_sec_device_types++; 2421 return 0; 2422} 2423#endif /* CONFIG_P2P */ 2424 2425 2426#ifdef OFFSET 2427#undef OFFSET 2428#endif /* OFFSET */ 2429/* OFFSET: Get offset of a variable within the wpa_config structure */ 2430#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v) 2431 2432#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL 2433#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL 2434#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f) 2435#define INT(f) _INT(f), NULL, NULL 2436#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max 2437#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f) 2438#define STR(f) _STR(f), NULL, NULL 2439#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max 2440 2441static const struct global_parse_data global_fields[] = { 2442#ifdef CONFIG_CTRL_IFACE 2443 { STR(ctrl_interface), 0 }, 2444 { STR(ctrl_interface_group), 0 } /* deprecated */, 2445#endif /* CONFIG_CTRL_IFACE */ 2446 { INT_RANGE(eapol_version, 1, 2), 0 }, 2447 { INT(ap_scan), 0 }, 2448 { INT(fast_reauth), 0 }, 2449 { STR(opensc_engine_path), 0 }, 2450 { STR(pkcs11_engine_path), 0 }, 2451 { STR(pkcs11_module_path), 0 }, 2452 { STR(driver_param), 0 }, 2453 { INT(dot11RSNAConfigPMKLifetime), 0 }, 2454 { INT(dot11RSNAConfigPMKReauthThreshold), 0 }, 2455 { INT(dot11RSNAConfigSATimeout), 0 }, 2456#ifndef CONFIG_NO_CONFIG_WRITE 2457 { INT(update_config), 0 }, 2458#endif /* CONFIG_NO_CONFIG_WRITE */ 2459 { FUNC_NO_VAR(load_dynamic_eap), 0 }, 2460#ifdef CONFIG_WPS 2461 { FUNC(uuid), CFG_CHANGED_UUID }, 2462 { STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME }, 2463 { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING }, 2464 { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING }, 2465 { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING }, 2466 { STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING }, 2467 { FUNC(device_type), CFG_CHANGED_DEVICE_TYPE }, 2468 { FUNC(os_version), CFG_CHANGED_OS_VERSION }, 2469 { STR(config_methods), CFG_CHANGED_CONFIG_METHODS }, 2470 { INT_RANGE(wps_cred_processing, 0, 2), 0 }, 2471#endif /* CONFIG_WPS */ 2472#ifdef CONFIG_P2P 2473 { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE }, 2474 { INT(p2p_listen_reg_class), 0 }, 2475 { INT(p2p_listen_channel), 0 }, 2476 { INT(p2p_oper_reg_class), 0 }, 2477 { INT(p2p_oper_channel), 0 }, 2478 { INT_RANGE(p2p_go_intent, 0, 15), 0 }, 2479 { STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX }, 2480 { INT_RANGE(persistent_reconnect, 0, 1), 0 }, 2481 { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS }, 2482 { INT(p2p_group_idle), 0 }, 2483#endif /* CONFIG_P2P */ 2484 { FUNC(country), CFG_CHANGED_COUNTRY }, 2485 { INT(bss_max_count), 0 }, 2486 { INT(bss_expiration_age), 0 }, 2487 { INT(bss_expiration_scan_count), 0 }, 2488 { INT_RANGE(filter_ssids, 0, 1), 0 }, 2489 { INT(max_num_sta), 0 }, 2490 { INT_RANGE(disassoc_low_ack, 0, 1), 0 } 2491}; 2492 2493#undef FUNC 2494#undef _INT 2495#undef INT 2496#undef INT_RANGE 2497#undef _STR 2498#undef STR 2499#undef STR_RANGE 2500#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0])) 2501 2502 2503int wpa_config_process_global(struct wpa_config *config, char *pos, int line) 2504{ 2505 size_t i; 2506 int ret = 0; 2507 2508 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 2509 const struct global_parse_data *field = &global_fields[i]; 2510 size_t flen = os_strlen(field->name); 2511 if (os_strncmp(pos, field->name, flen) != 0 || 2512 pos[flen] != '=') 2513 continue; 2514 2515 if (field->parser(field, config, line, pos + flen + 1)) { 2516 wpa_printf(MSG_ERROR, "Line %d: failed to " 2517 "parse '%s'.", line, pos); 2518 ret = -1; 2519 } 2520 config->changed_parameters |= field->changed_flag; 2521 break; 2522 } 2523 if (i == NUM_GLOBAL_FIELDS) { 2524 if (line < 0) 2525 return -1; 2526 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", 2527 line, pos); 2528 ret = -1; 2529 } 2530 2531 return ret; 2532} 2533