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