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