1 /* 2 * WPA Supplicant / Configuration backend: text file 3 * Copyright (c) 2003-2008, Jouni Malinen <j (at) 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 * This file implements a configuration backend for text files. All the 15 * configuration information is stored in a text file that uses a format 16 * described in the sample configuration file, wpa_supplicant.conf. 17 */ 18 19 #include "includes.h" 20 21 #include "common.h" 22 #include "config.h" 23 #include "base64.h" 24 #include "uuid.h" 25 #include "eap_peer/eap_methods.h" 26 27 #include <sys/stat.h> 28 29 30 /** 31 * wpa_config_get_line - Read the next configuration file line 32 * @s: Buffer for the line 33 * @size: The buffer length 34 * @stream: File stream to read from 35 * @line: Pointer to a variable storing the file line number 36 * @_pos: Buffer for the pointer to the beginning of data on the text line or 37 * %NULL if not needed (returned value used instead) 38 * Returns: Pointer to the beginning of data on the text line or %NULL if no 39 * more text lines are available. 40 * 41 * This function reads the next non-empty line from the configuration file and 42 * removes comments. The returned string is guaranteed to be null-terminated. 43 */ 44 static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line, 45 char **_pos) 46 { 47 char *pos, *end, *sstart; 48 49 while (fgets(s, size, stream)) { 50 (*line)++; 51 s[size - 1] = '\0'; 52 pos = s; 53 54 /* Skip white space from the beginning of line. */ 55 while (*pos == ' ' || *pos == '\t' || *pos == '\r') 56 pos++; 57 58 /* Skip comment lines and empty lines */ 59 if (*pos == '#' || *pos == '\n' || *pos == '\0') 60 continue; 61 62 /* 63 * Remove # comments unless they are within a double quoted 64 * string. 65 */ 66 sstart = os_strchr(pos, '"'); 67 if (sstart) 68 sstart = os_strrchr(sstart + 1, '"'); 69 if (!sstart) 70 sstart = pos; 71 end = os_strchr(sstart, '#'); 72 if (end) 73 *end-- = '\0'; 74 else 75 end = pos + os_strlen(pos) - 1; 76 77 /* Remove trailing white space. */ 78 while (end > pos && 79 (*end == '\n' || *end == ' ' || *end == '\t' || 80 *end == '\r')) 81 *end-- = '\0'; 82 83 if (*pos == '\0') 84 continue; 85 86 if (_pos) 87 *_pos = pos; 88 return pos; 89 } 90 91 if (_pos) 92 *_pos = NULL; 93 return NULL; 94 } 95 96 97 static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) 98 { 99 int errors = 0; 100 101 if (ssid->passphrase) { 102 if (ssid->psk_set) { 103 wpa_printf(MSG_ERROR, "Line %d: both PSK and " 104 "passphrase configured.", line); 105 errors++; 106 } 107 wpa_config_update_psk(ssid); 108 } 109 110 if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | 111 WPA_KEY_MGMT_PSK_SHA256)) && 112 !ssid->psk_set) { 113 wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key " 114 "management, but no PSK configured.", line); 115 errors++; 116 } 117 118 if ((ssid->group_cipher & WPA_CIPHER_CCMP) && 119 !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && 120 !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { 121 /* Group cipher cannot be stronger than the pairwise cipher. */ 122 wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" 123 " list since it was not allowed for pairwise " 124 "cipher", line); 125 ssid->group_cipher &= ~WPA_CIPHER_CCMP; 126 } 127 128 return errors; 129 } 130 131 132 static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) 133 { 134 struct wpa_ssid *ssid; 135 int errors = 0, end = 0; 136 char buf[256], *pos, *pos2; 137 138 wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", 139 *line); 140 ssid = os_zalloc(sizeof(*ssid)); 141 if (ssid == NULL) 142 return NULL; 143 ssid->id = id; 144 145 wpa_config_set_network_defaults(ssid); 146 147 while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 148 if (os_strcmp(pos, "}") == 0) { 149 end = 1; 150 break; 151 } 152 153 pos2 = os_strchr(pos, '='); 154 if (pos2 == NULL) { 155 wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " 156 "'%s'.", *line, pos); 157 errors++; 158 continue; 159 } 160 161 *pos2++ = '\0'; 162 if (*pos2 == '"') { 163 if (os_strchr(pos2 + 1, '"') == NULL) { 164 wpa_printf(MSG_ERROR, "Line %d: invalid " 165 "quotation '%s'.", *line, pos2); 166 errors++; 167 continue; 168 } 169 } 170 171 if (wpa_config_set(ssid, pos, pos2, *line) < 0) 172 errors++; 173 } 174 175 if (!end) { 176 wpa_printf(MSG_ERROR, "Line %d: network block was not " 177 "terminated properly.", *line); 178 errors++; 179 } 180 181 errors += wpa_config_validate_network(ssid, *line); 182 183 if (errors) { 184 wpa_config_free_ssid(ssid); 185 ssid = NULL; 186 } 187 188 return ssid; 189 } 190 191 192 #ifndef CONFIG_NO_CONFIG_BLOBS 193 static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line, 194 const char *name) 195 { 196 struct wpa_config_blob *blob; 197 char buf[256], *pos; 198 unsigned char *encoded = NULL, *nencoded; 199 int end = 0; 200 size_t encoded_len = 0, len; 201 202 wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'", 203 *line, name); 204 205 while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 206 if (os_strcmp(pos, "}") == 0) { 207 end = 1; 208 break; 209 } 210 211 len = os_strlen(pos); 212 nencoded = os_realloc(encoded, encoded_len + len); 213 if (nencoded == NULL) { 214 wpa_printf(MSG_ERROR, "Line %d: not enough memory for " 215 "blob", *line); 216 os_free(encoded); 217 return NULL; 218 } 219 encoded = nencoded; 220 os_memcpy(encoded + encoded_len, pos, len); 221 encoded_len += len; 222 } 223 224 if (!end) { 225 wpa_printf(MSG_ERROR, "Line %d: blob was not terminated " 226 "properly", *line); 227 os_free(encoded); 228 return NULL; 229 } 230 231 blob = os_zalloc(sizeof(*blob)); 232 if (blob == NULL) { 233 os_free(encoded); 234 return NULL; 235 } 236 blob->name = os_strdup(name); 237 blob->data = base64_decode(encoded, encoded_len, &blob->len); 238 os_free(encoded); 239 240 if (blob->name == NULL || blob->data == NULL) { 241 wpa_config_free_blob(blob); 242 return NULL; 243 } 244 245 return blob; 246 } 247 248 249 static int wpa_config_process_blob(struct wpa_config *config, FILE *f, 250 int *line, char *bname) 251 { 252 char *name_end; 253 struct wpa_config_blob *blob; 254 255 name_end = os_strchr(bname, '='); 256 if (name_end == NULL) { 257 wpa_printf(MSG_ERROR, "Line %d: no blob name terminator", 258 *line); 259 return -1; 260 } 261 *name_end = '\0'; 262 263 blob = wpa_config_read_blob(f, line, bname); 264 if (blob == NULL) { 265 wpa_printf(MSG_ERROR, "Line %d: failed to read blob %s", 266 *line, bname); 267 return -1; 268 } 269 wpa_config_set_blob(config, blob); 270 return 0; 271 } 272 #endif /* CONFIG_NO_CONFIG_BLOBS */ 273 274 275 struct global_parse_data { 276 char *name; 277 int (*parser)(const struct global_parse_data *data, 278 struct wpa_config *config, int line, const char *value); 279 void *param1, *param2, *param3; 280 }; 281 282 283 static int wpa_config_parse_int(const struct global_parse_data *data, 284 struct wpa_config *config, int line, 285 const char *pos) 286 { 287 int *dst; 288 dst = (int *) (((u8 *) config) + (long) data->param1); 289 *dst = atoi(pos); 290 wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); 291 292 if (data->param2 && *dst < (long) data->param2) { 293 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " 294 "min_value=%ld)", line, data->name, *dst, 295 (long) data->param2); 296 *dst = (long) data->param2; 297 return -1; 298 } 299 300 if (data->param3 && *dst > (long) data->param3) { 301 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " 302 "max_value=%ld)", line, data->name, *dst, 303 (long) data->param3); 304 *dst = (long) data->param3; 305 return -1; 306 } 307 308 return 0; 309 } 310 311 312 static int wpa_config_parse_str(const struct global_parse_data *data, 313 struct wpa_config *config, int line, 314 const char *pos) 315 { 316 size_t len; 317 char **dst, *tmp; 318 319 len = os_strlen(pos); 320 if (data->param2 && len < (size_t) data->param2) { 321 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " 322 "min_len=%ld)", line, data->name, 323 (unsigned long) len, (long) data->param2); 324 return -1; 325 } 326 327 if (data->param3 && len > (size_t) data->param3) { 328 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " 329 "max_len=%ld)", line, data->name, 330 (unsigned long) len, (long) data->param3); 331 return -1; 332 } 333 334 tmp = os_strdup(pos); 335 if (tmp == NULL) 336 return -1; 337 338 dst = (char **) (((u8 *) config) + (long) data->param1); 339 os_free(*dst); 340 *dst = tmp; 341 wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); 342 343 return 0; 344 } 345 346 347 static int wpa_config_process_country(const struct global_parse_data *data, 348 struct wpa_config *config, int line, 349 const char *pos) 350 { 351 if (!pos[0] || !pos[1]) { 352 wpa_printf(MSG_DEBUG, "Invalid country set"); 353 return -1; 354 } 355 config->country[0] = pos[0]; 356 config->country[1] = pos[1]; 357 wpa_printf(MSG_DEBUG, "country='%c%c'", 358 config->country[0], config->country[1]); 359 return 0; 360 } 361 362 363 static int wpa_config_process_load_dynamic_eap( 364 const struct global_parse_data *data, struct wpa_config *config, 365 int line, const char *so) 366 { 367 int ret; 368 wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); 369 ret = eap_peer_method_load(so); 370 if (ret == -2) { 371 wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not " 372 "reloading."); 373 } else if (ret) { 374 wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP " 375 "method '%s'.", line, so); 376 return -1; 377 } 378 379 return 0; 380 } 381 382 383 #ifdef CONFIG_WPS 384 385 static int wpa_config_process_uuid(const struct global_parse_data *data, 386 struct wpa_config *config, int line, 387 const char *pos) 388 { 389 char buf[40]; 390 if (uuid_str2bin(pos, config->uuid)) { 391 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); 392 return -1; 393 } 394 uuid_bin2str(config->uuid, buf, sizeof(buf)); 395 wpa_printf(MSG_DEBUG, "uuid=%s", buf); 396 return 0; 397 } 398 399 400 static int wpa_config_process_os_version(const struct global_parse_data *data, 401 struct wpa_config *config, int line, 402 const char *pos) 403 { 404 if (hexstr2bin(pos, config->os_version, 4)) { 405 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line); 406 return -1; 407 } 408 wpa_printf(MSG_DEBUG, "os_version=%08x", 409 WPA_GET_BE32(config->os_version)); 410 return 0; 411 } 412 413 #endif /* CONFIG_WPS */ 414 415 416 #ifdef OFFSET 417 #undef OFFSET 418 #endif /* OFFSET */ 419 /* OFFSET: Get offset of a variable within the wpa_config structure */ 420 #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v) 421 422 #define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL 423 #define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL 424 #define _INT(f) #f, wpa_config_parse_int, OFFSET(f) 425 #define INT(f) _INT(f), NULL, NULL 426 #define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max 427 #define _STR(f) #f, wpa_config_parse_str, OFFSET(f) 428 #define STR(f) _STR(f), NULL, NULL 429 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max 430 431 static const struct global_parse_data global_fields[] = { 432 #ifdef CONFIG_CTRL_IFACE 433 { STR(ctrl_interface) }, 434 { STR(ctrl_interface_group) } /* deprecated */, 435 #endif /* CONFIG_CTRL_IFACE */ 436 { INT_RANGE(eapol_version, 1, 2) }, 437 { INT(ap_scan) }, 438 { INT(fast_reauth) }, 439 #ifdef EAP_TLS_OPENSSL 440 { STR(opensc_engine_path) }, 441 { STR(pkcs11_engine_path) }, 442 { STR(pkcs11_module_path) }, 443 #endif /* EAP_TLS_OPENSSL */ 444 { STR(driver_param) }, 445 { INT(dot11RSNAConfigPMKLifetime) }, 446 { INT(dot11RSNAConfigPMKReauthThreshold) }, 447 { INT(dot11RSNAConfigSATimeout) }, 448 #ifndef CONFIG_NO_CONFIG_WRITE 449 { INT(update_config) }, 450 #endif /* CONFIG_NO_CONFIG_WRITE */ 451 { FUNC_NO_VAR(load_dynamic_eap) }, 452 #ifdef CONFIG_WPS 453 { FUNC(uuid) }, 454 { STR_RANGE(device_name, 0, 32) }, 455 { STR_RANGE(manufacturer, 0, 64) }, 456 { STR_RANGE(model_name, 0, 32) }, 457 { STR_RANGE(model_number, 0, 32) }, 458 { STR_RANGE(serial_number, 0, 32) }, 459 { STR(device_type) }, 460 { FUNC(os_version) }, 461 { INT_RANGE(wps_cred_processing, 0, 2) }, 462 #endif /* CONFIG_WPS */ 463 { FUNC(country) } 464 }; 465 466 #undef FUNC 467 #undef _INT 468 #undef INT 469 #undef INT_RANGE 470 #undef _STR 471 #undef STR 472 #undef STR_RANGE 473 #define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0])) 474 475 476 static int wpa_config_process_global(struct wpa_config *config, char *pos, 477 int line) 478 { 479 size_t i; 480 int ret = 0; 481 482 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 483 const struct global_parse_data *field = &global_fields[i]; 484 size_t flen = os_strlen(field->name); 485 if (os_strncmp(pos, field->name, flen) != 0 || 486 pos[flen] != '=') 487 continue; 488 489 if (field->parser(field, config, line, pos + flen + 1)) { 490 wpa_printf(MSG_ERROR, "Line %d: failed to " 491 "parse '%s'.", line, pos); 492 ret = -1; 493 } 494 break; 495 } 496 if (i == NUM_GLOBAL_FIELDS) { 497 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", 498 line, pos); 499 ret = -1; 500 } 501 502 return ret; 503 } 504 505 506 struct wpa_config * wpa_config_read(const char *name) 507 { 508 FILE *f; 509 char buf[256], *pos; 510 int errors = 0, line = 0; 511 struct wpa_ssid *ssid, *tail = NULL, *head = NULL; 512 struct wpa_config *config; 513 int id = 0; 514 515 config = wpa_config_alloc_empty(NULL, NULL); 516 if (config == NULL) 517 return NULL; 518 wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); 519 f = fopen(name, "r"); 520 if (f == NULL) { 521 os_free(config); 522 return NULL; 523 } 524 525 /* When creating the config file, give group read/write access 526 * to allow backup and restoring the file. 527 */ 528 chmod(name, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); 529 530 while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { 531 if (os_strcmp(pos, "network={") == 0) { 532 ssid = wpa_config_read_network(f, &line, id++); 533 if (ssid == NULL) { 534 wpa_printf(MSG_ERROR, "Line %d: failed to " 535 "parse network block.", line); 536 #ifndef WPA_IGNORE_CONFIG_ERRORS 537 errors++; 538 #endif 539 continue; 540 } 541 if (head == NULL) { 542 head = tail = ssid; 543 } else { 544 tail->next = ssid; 545 tail = ssid; 546 } 547 if (wpa_config_add_prio_network(config, ssid)) { 548 wpa_printf(MSG_ERROR, "Line %d: failed to add " 549 "network block to priority list.", 550 line); 551 errors++; 552 continue; 553 } 554 #ifndef CONFIG_NO_CONFIG_BLOBS 555 } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { 556 if (wpa_config_process_blob(config, f, &line, pos + 12) 557 < 0) { 558 errors++; 559 continue; 560 } 561 #endif /* CONFIG_NO_CONFIG_BLOBS */ 562 } else if (wpa_config_process_global(config, pos, line) < 0) { 563 wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " 564 "line '%s'.", line, pos); 565 errors++; 566 continue; 567 } 568 } 569 570 fclose(f); 571 572 config->ssid = head; 573 wpa_config_debug_dump_networks(config); 574 575 #ifndef WPA_IGNORE_CONFIG_ERRORS 576 if (errors) { 577 wpa_config_free(config); 578 config = NULL; 579 head = NULL; 580 } 581 #endif 582 583 return config; 584 } 585 586 587 #ifndef CONFIG_NO_CONFIG_WRITE 588 589 static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid) 590 { 591 char *value = wpa_config_get(ssid, field); 592 if (value == NULL) 593 return; 594 fprintf(f, "\t%s=%s\n", field, value); 595 os_free(value); 596 } 597 598 599 static void write_int(FILE *f, const char *field, int value, int def) 600 { 601 if (value == def) 602 return; 603 fprintf(f, "\t%s=%d\n", field, value); 604 } 605 606 607 static void write_bssid(FILE *f, struct wpa_ssid *ssid) 608 { 609 char *value = wpa_config_get(ssid, "bssid"); 610 if (value == NULL) 611 return; 612 fprintf(f, "\tbssid=%s\n", value); 613 os_free(value); 614 } 615 616 617 static void write_psk(FILE *f, struct wpa_ssid *ssid) 618 { 619 char *value = wpa_config_get(ssid, "psk"); 620 if (value == NULL) 621 return; 622 fprintf(f, "\tpsk=%s\n", value); 623 os_free(value); 624 } 625 626 627 static void write_proto(FILE *f, struct wpa_ssid *ssid) 628 { 629 char *value; 630 631 if (ssid->proto == DEFAULT_PROTO) 632 return; 633 634 value = wpa_config_get(ssid, "proto"); 635 if (value == NULL) 636 return; 637 if (value[0]) 638 fprintf(f, "\tproto=%s\n", value); 639 os_free(value); 640 } 641 642 643 static void write_key_mgmt(FILE *f, struct wpa_ssid *ssid) 644 { 645 char *value; 646 647 if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 648 return; 649 650 value = wpa_config_get(ssid, "key_mgmt"); 651 if (value == NULL) 652 return; 653 if (value[0]) 654 fprintf(f, "\tkey_mgmt=%s\n", value); 655 os_free(value); 656 } 657 658 659 static void write_pairwise(FILE *f, struct wpa_ssid *ssid) 660 { 661 char *value; 662 663 if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 664 return; 665 666 value = wpa_config_get(ssid, "pairwise"); 667 if (value == NULL) 668 return; 669 if (value[0]) 670 fprintf(f, "\tpairwise=%s\n", value); 671 os_free(value); 672 } 673 674 675 static void write_group(FILE *f, struct wpa_ssid *ssid) 676 { 677 char *value; 678 679 if (ssid->group_cipher == DEFAULT_GROUP) 680 return; 681 682 value = wpa_config_get(ssid, "group"); 683 if (value == NULL) 684 return; 685 if (value[0]) 686 fprintf(f, "\tgroup=%s\n", value); 687 os_free(value); 688 } 689 690 691 static void write_auth_alg(FILE *f, struct wpa_ssid *ssid) 692 { 693 char *value; 694 695 if (ssid->auth_alg == 0) 696 return; 697 698 value = wpa_config_get(ssid, "auth_alg"); 699 if (value == NULL) 700 return; 701 if (value[0]) 702 fprintf(f, "\tauth_alg=%s\n", value); 703 os_free(value); 704 } 705 706 707 #ifdef IEEE8021X_EAPOL 708 static void write_eap(FILE *f, struct wpa_ssid *ssid) 709 { 710 char *value; 711 712 value = wpa_config_get(ssid, "eap"); 713 if (value == NULL) 714 return; 715 716 if (value[0]) 717 fprintf(f, "\teap=%s\n", value); 718 os_free(value); 719 } 720 #endif /* IEEE8021X_EAPOL */ 721 722 723 static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) 724 { 725 char field[20], *value; 726 int res; 727 728 res = os_snprintf(field, sizeof(field), "wep_key%d", idx); 729 if (res < 0 || (size_t) res >= sizeof(field)) 730 return; 731 value = wpa_config_get(ssid, field); 732 if (value) { 733 fprintf(f, "\t%s=%s\n", field, value); 734 os_free(value); 735 } 736 } 737 738 739 static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) 740 { 741 int i; 742 743 #define STR(t) write_str(f, #t, ssid) 744 #define INT(t) write_int(f, #t, ssid->t, 0) 745 #define INTe(t) write_int(f, #t, ssid->eap.t, 0) 746 #define INT_DEF(t, def) write_int(f, #t, ssid->t, def) 747 #define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def) 748 749 STR(ssid); 750 INT(scan_ssid); 751 write_bssid(f, ssid); 752 write_psk(f, ssid); 753 write_proto(f, ssid); 754 write_key_mgmt(f, ssid); 755 write_pairwise(f, ssid); 756 write_group(f, ssid); 757 write_auth_alg(f, ssid); 758 #ifdef IEEE8021X_EAPOL 759 write_eap(f, ssid); 760 STR(identity); 761 STR(anonymous_identity); 762 STR(password); 763 STR(ca_cert); 764 STR(ca_path); 765 STR(client_cert); 766 STR(private_key); 767 STR(private_key_passwd); 768 STR(dh_file); 769 STR(subject_match); 770 STR(altsubject_match); 771 STR(ca_cert2); 772 STR(ca_path2); 773 STR(client_cert2); 774 STR(private_key2); 775 STR(private_key2_passwd); 776 STR(dh_file2); 777 STR(subject_match2); 778 STR(altsubject_match2); 779 STR(phase1); 780 STR(phase2); 781 STR(pcsc); 782 STR(pin); 783 STR(engine_id); 784 STR(key_id); 785 STR(cert_id); 786 STR(ca_cert_id); 787 STR(key2_id); 788 STR(pin2); 789 STR(engine2_id); 790 STR(cert2_id); 791 STR(ca_cert2_id); 792 INTe(engine); 793 INTe(engine2); 794 INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 795 #endif /* IEEE8021X_EAPOL */ 796 for (i = 0; i < 4; i++) 797 write_wep_key(f, i, ssid); 798 INT(wep_tx_keyidx); 799 INT(priority); 800 #ifdef IEEE8021X_EAPOL 801 INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 802 STR(pac_file); 803 INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE); 804 #endif /* IEEE8021X_EAPOL */ 805 INT(mode); 806 INT(proactive_key_caching); 807 INT(disabled); 808 INT(peerkey); 809 #ifdef CONFIG_IEEE80211W 810 INT(ieee80211w); 811 #endif /* CONFIG_IEEE80211W */ 812 STR(id_str); 813 814 #undef STR 815 #undef INT 816 #undef INT_DEF 817 } 818 819 820 #ifndef CONFIG_NO_CONFIG_BLOBS 821 static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) 822 { 823 unsigned char *encoded; 824 825 encoded = base64_encode(blob->data, blob->len, NULL); 826 if (encoded == NULL) 827 return -1; 828 829 fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded); 830 os_free(encoded); 831 return 0; 832 } 833 #endif /* CONFIG_NO_CONFIG_BLOBS */ 834 835 836 static void wpa_config_write_global(FILE *f, struct wpa_config *config) 837 { 838 #ifdef CONFIG_CTRL_IFACE 839 if (config->ctrl_interface) 840 fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); 841 if (config->ctrl_interface_group) 842 fprintf(f, "ctrl_interface_group=%s\n", 843 config->ctrl_interface_group); 844 #endif /* CONFIG_CTRL_IFACE */ 845 if (config->eapol_version != DEFAULT_EAPOL_VERSION) 846 fprintf(f, "eapol_version=%d\n", config->eapol_version); 847 if (config->ap_scan != DEFAULT_AP_SCAN) 848 fprintf(f, "ap_scan=%d\n", config->ap_scan); 849 if (config->fast_reauth != DEFAULT_FAST_REAUTH) 850 fprintf(f, "fast_reauth=%d\n", config->fast_reauth); 851 #ifdef EAP_TLS_OPENSSL 852 if (config->opensc_engine_path) 853 fprintf(f, "opensc_engine_path=%s\n", 854 config->opensc_engine_path); 855 if (config->pkcs11_engine_path) 856 fprintf(f, "pkcs11_engine_path=%s\n", 857 config->pkcs11_engine_path); 858 if (config->pkcs11_module_path) 859 fprintf(f, "pkcs11_module_path=%s\n", 860 config->pkcs11_module_path); 861 #endif /* EAP_TLS_OPENSSL */ 862 if (config->driver_param) 863 fprintf(f, "driver_param=%s\n", config->driver_param); 864 if (config->dot11RSNAConfigPMKLifetime) 865 fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n", 866 config->dot11RSNAConfigPMKLifetime); 867 if (config->dot11RSNAConfigPMKReauthThreshold) 868 fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n", 869 config->dot11RSNAConfigPMKReauthThreshold); 870 if (config->dot11RSNAConfigSATimeout) 871 fprintf(f, "dot11RSNAConfigSATimeout=%d\n", 872 config->dot11RSNAConfigSATimeout); 873 if (config->update_config) 874 fprintf(f, "update_config=%d\n", config->update_config); 875 #ifdef CONFIG_WPS 876 if (!is_nil_uuid(config->uuid)) { 877 char buf[40]; 878 uuid_bin2str(config->uuid, buf, sizeof(buf)); 879 fprintf(f, "uuid=%s\n", buf); 880 } 881 if (config->device_name) 882 fprintf(f, "device_name=%s\n", config->device_name); 883 if (config->manufacturer) 884 fprintf(f, "manufacturer=%s\n", config->manufacturer); 885 if (config->model_name) 886 fprintf(f, "model_name=%s\n", config->model_name); 887 if (config->model_number) 888 fprintf(f, "model_number=%s\n", config->model_number); 889 if (config->serial_number) 890 fprintf(f, "serial_number=%s\n", config->serial_number); 891 if (config->device_type) 892 fprintf(f, "device_type=%s\n", config->device_type); 893 if (WPA_GET_BE32(config->os_version)) 894 fprintf(f, "os_version=%08x\n", 895 WPA_GET_BE32(config->os_version)); 896 if (config->wps_cred_processing) 897 fprintf(f, "wps_cred_processing=%d\n", 898 config->wps_cred_processing); 899 #endif /* CONFIG_WPS */ 900 if (config->country[0] && config->country[1]) { 901 fprintf(f, "country=%c%c\n", 902 config->country[0], config->country[1]); 903 } 904 } 905 906 #endif /* CONFIG_NO_CONFIG_WRITE */ 907 908 909 int wpa_config_write(const char *name, struct wpa_config *config) 910 { 911 #ifndef CONFIG_NO_CONFIG_WRITE 912 FILE *f; 913 struct wpa_ssid *ssid; 914 #ifndef CONFIG_NO_CONFIG_BLOBS 915 struct wpa_config_blob *blob; 916 #endif /* CONFIG_NO_CONFIG_BLOBS */ 917 int ret = 0; 918 919 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 920 921 f = fopen(name, "w"); 922 if (f == NULL) { 923 wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name); 924 return -1; 925 } 926 927 wpa_config_write_global(f, config); 928 929 for (ssid = config->ssid; ssid; ssid = ssid->next) { 930 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS) 931 continue; /* do not save temporary WPS networks */ 932 fprintf(f, "\nnetwork={\n"); 933 wpa_config_write_network(f, ssid); 934 fprintf(f, "}\n"); 935 } 936 937 #ifndef CONFIG_NO_CONFIG_BLOBS 938 for (blob = config->blobs; blob; blob = blob->next) { 939 ret = wpa_config_write_blob(f, blob); 940 if (ret) 941 break; 942 } 943 #endif /* CONFIG_NO_CONFIG_BLOBS */ 944 945 fclose(f); 946 947 wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", 948 name, ret ? "un" : ""); 949 return ret; 950 #else /* CONFIG_NO_CONFIG_WRITE */ 951 return -1; 952 #endif /* CONFIG_NO_CONFIG_WRITE */ 953 } 954