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 #ifdef EAP_TLS_OPENSSL 438 { STR(opensc_engine_path) }, 439 { STR(pkcs11_engine_path) }, 440 { STR(pkcs11_module_path) }, 441 #endif /* EAP_TLS_OPENSSL */ 442 { STR(driver_param) }, 443 { INT(dot11RSNAConfigPMKLifetime) }, 444 { INT(dot11RSNAConfigPMKReauthThreshold) }, 445 { INT(dot11RSNAConfigSATimeout) }, 446 #ifndef CONFIG_NO_CONFIG_WRITE 447 { INT(update_config) }, 448 #endif /* CONFIG_NO_CONFIG_WRITE */ 449 { FUNC_NO_VAR(load_dynamic_eap) }, 450 #ifdef CONFIG_WPS 451 { FUNC(uuid) }, 452 { STR_RANGE(device_name, 0, 32) }, 453 { STR_RANGE(manufacturer, 0, 64) }, 454 { STR_RANGE(model_name, 0, 32) }, 455 { STR_RANGE(model_number, 0, 32) }, 456 { STR_RANGE(serial_number, 0, 32) }, 457 { STR(device_type) }, 458 { FUNC(os_version) }, 459 { INT_RANGE(wps_cred_processing, 0, 2) }, 460 #endif /* CONFIG_WPS */ 461 { FUNC(country) } 462 }; 463 464 #undef FUNC 465 #undef _INT 466 #undef INT 467 #undef INT_RANGE 468 #undef _STR 469 #undef STR 470 #undef STR_RANGE 471 #define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0])) 472 473 474 static int wpa_config_process_global(struct wpa_config *config, char *pos, 475 int line) 476 { 477 size_t i; 478 int ret = 0; 479 480 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 481 const struct global_parse_data *field = &global_fields[i]; 482 size_t flen = os_strlen(field->name); 483 if (os_strncmp(pos, field->name, flen) != 0 || 484 pos[flen] != '=') 485 continue; 486 487 if (field->parser(field, config, line, pos + flen + 1)) { 488 wpa_printf(MSG_ERROR, "Line %d: failed to " 489 "parse '%s'.", line, pos); 490 ret = -1; 491 } 492 break; 493 } 494 if (i == NUM_GLOBAL_FIELDS) { 495 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", 496 line, pos); 497 ret = -1; 498 } 499 500 return ret; 501 } 502 503 504 struct wpa_config * wpa_config_read(const char *name) 505 { 506 FILE *f; 507 char buf[256], *pos; 508 int errors = 0, line = 0; 509 struct wpa_ssid *ssid, *tail = NULL, *head = NULL; 510 struct wpa_config *config; 511 int id = 0; 512 513 config = wpa_config_alloc_empty(NULL, NULL); 514 if (config == NULL) 515 return NULL; 516 wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); 517 f = fopen(name, "r"); 518 if (f == NULL) { 519 os_free(config); 520 return NULL; 521 } 522 523 while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { 524 if (os_strcmp(pos, "network={") == 0) { 525 ssid = wpa_config_read_network(f, &line, id++); 526 if (ssid == NULL) { 527 wpa_printf(MSG_ERROR, "Line %d: failed to " 528 "parse network block.", line); 529 errors++; 530 continue; 531 } 532 if (head == NULL) { 533 head = tail = ssid; 534 } else { 535 tail->next = ssid; 536 tail = ssid; 537 } 538 if (wpa_config_add_prio_network(config, ssid)) { 539 wpa_printf(MSG_ERROR, "Line %d: failed to add " 540 "network block to priority list.", 541 line); 542 errors++; 543 continue; 544 } 545 #ifndef CONFIG_NO_CONFIG_BLOBS 546 } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { 547 if (wpa_config_process_blob(config, f, &line, pos + 12) 548 < 0) { 549 errors++; 550 continue; 551 } 552 #endif /* CONFIG_NO_CONFIG_BLOBS */ 553 } else if (wpa_config_process_global(config, pos, line) < 0) { 554 wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " 555 "line '%s'.", line, pos); 556 errors++; 557 continue; 558 } 559 } 560 561 fclose(f); 562 563 config->ssid = head; 564 wpa_config_debug_dump_networks(config); 565 566 if (errors) { 567 wpa_config_free(config); 568 config = NULL; 569 head = NULL; 570 } 571 572 return config; 573 } 574 575 576 #ifndef CONFIG_NO_CONFIG_WRITE 577 578 static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid) 579 { 580 char *value = wpa_config_get(ssid, field); 581 if (value == NULL) 582 return; 583 fprintf(f, "\t%s=%s\n", field, value); 584 os_free(value); 585 } 586 587 588 static void write_int(FILE *f, const char *field, int value, int def) 589 { 590 if (value == def) 591 return; 592 fprintf(f, "\t%s=%d\n", field, value); 593 } 594 595 596 static void write_bssid(FILE *f, struct wpa_ssid *ssid) 597 { 598 char *value = wpa_config_get(ssid, "bssid"); 599 if (value == NULL) 600 return; 601 fprintf(f, "\tbssid=%s\n", value); 602 os_free(value); 603 } 604 605 606 static void write_psk(FILE *f, struct wpa_ssid *ssid) 607 { 608 char *value = wpa_config_get(ssid, "psk"); 609 if (value == NULL) 610 return; 611 fprintf(f, "\tpsk=%s\n", value); 612 os_free(value); 613 } 614 615 616 static void write_proto(FILE *f, struct wpa_ssid *ssid) 617 { 618 char *value; 619 620 if (ssid->proto == DEFAULT_PROTO) 621 return; 622 623 value = wpa_config_get(ssid, "proto"); 624 if (value == NULL) 625 return; 626 if (value[0]) 627 fprintf(f, "\tproto=%s\n", value); 628 os_free(value); 629 } 630 631 632 static void write_key_mgmt(FILE *f, struct wpa_ssid *ssid) 633 { 634 char *value; 635 636 if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 637 return; 638 639 value = wpa_config_get(ssid, "key_mgmt"); 640 if (value == NULL) 641 return; 642 if (value[0]) 643 fprintf(f, "\tkey_mgmt=%s\n", value); 644 os_free(value); 645 } 646 647 648 static void write_pairwise(FILE *f, struct wpa_ssid *ssid) 649 { 650 char *value; 651 652 if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 653 return; 654 655 value = wpa_config_get(ssid, "pairwise"); 656 if (value == NULL) 657 return; 658 if (value[0]) 659 fprintf(f, "\tpairwise=%s\n", value); 660 os_free(value); 661 } 662 663 664 static void write_group(FILE *f, struct wpa_ssid *ssid) 665 { 666 char *value; 667 668 if (ssid->group_cipher == DEFAULT_GROUP) 669 return; 670 671 value = wpa_config_get(ssid, "group"); 672 if (value == NULL) 673 return; 674 if (value[0]) 675 fprintf(f, "\tgroup=%s\n", value); 676 os_free(value); 677 } 678 679 680 static void write_auth_alg(FILE *f, struct wpa_ssid *ssid) 681 { 682 char *value; 683 684 if (ssid->auth_alg == 0) 685 return; 686 687 value = wpa_config_get(ssid, "auth_alg"); 688 if (value == NULL) 689 return; 690 if (value[0]) 691 fprintf(f, "\tauth_alg=%s\n", value); 692 os_free(value); 693 } 694 695 696 #ifdef IEEE8021X_EAPOL 697 static void write_eap(FILE *f, struct wpa_ssid *ssid) 698 { 699 char *value; 700 701 value = wpa_config_get(ssid, "eap"); 702 if (value == NULL) 703 return; 704 705 if (value[0]) 706 fprintf(f, "\teap=%s\n", value); 707 os_free(value); 708 } 709 #endif /* IEEE8021X_EAPOL */ 710 711 712 static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) 713 { 714 char field[20], *value; 715 int res; 716 717 res = os_snprintf(field, sizeof(field), "wep_key%d", idx); 718 if (res < 0 || (size_t) res >= sizeof(field)) 719 return; 720 value = wpa_config_get(ssid, field); 721 if (value) { 722 fprintf(f, "\t%s=%s\n", field, value); 723 os_free(value); 724 } 725 } 726 727 728 static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) 729 { 730 int i; 731 732 #define STR(t) write_str(f, #t, ssid) 733 #define INT(t) write_int(f, #t, ssid->t, 0) 734 #define INTe(t) write_int(f, #t, ssid->eap.t, 0) 735 #define INT_DEF(t, def) write_int(f, #t, ssid->t, def) 736 #define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def) 737 738 STR(ssid); 739 INT(scan_ssid); 740 write_bssid(f, ssid); 741 write_psk(f, ssid); 742 write_proto(f, ssid); 743 write_key_mgmt(f, ssid); 744 write_pairwise(f, ssid); 745 write_group(f, ssid); 746 write_auth_alg(f, ssid); 747 #ifdef IEEE8021X_EAPOL 748 write_eap(f, ssid); 749 STR(identity); 750 STR(anonymous_identity); 751 STR(password); 752 STR(ca_cert); 753 STR(ca_path); 754 STR(client_cert); 755 STR(private_key); 756 STR(private_key_passwd); 757 STR(dh_file); 758 STR(subject_match); 759 STR(altsubject_match); 760 STR(ca_cert2); 761 STR(ca_path2); 762 STR(client_cert2); 763 STR(private_key2); 764 STR(private_key2_passwd); 765 STR(dh_file2); 766 STR(subject_match2); 767 STR(altsubject_match2); 768 STR(phase1); 769 STR(phase2); 770 STR(pcsc); 771 STR(pin); 772 STR(engine_id); 773 STR(key_id); 774 STR(cert_id); 775 STR(ca_cert_id); 776 STR(key2_id); 777 STR(pin2); 778 STR(engine2_id); 779 STR(cert2_id); 780 STR(ca_cert2_id); 781 INTe(engine); 782 INTe(engine2); 783 INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 784 #endif /* IEEE8021X_EAPOL */ 785 for (i = 0; i < 4; i++) 786 write_wep_key(f, i, ssid); 787 INT(wep_tx_keyidx); 788 INT(priority); 789 #ifdef IEEE8021X_EAPOL 790 INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 791 STR(pac_file); 792 INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE); 793 #endif /* IEEE8021X_EAPOL */ 794 INT(mode); 795 INT(proactive_key_caching); 796 INT(disabled); 797 INT(peerkey); 798 #ifdef CONFIG_IEEE80211W 799 INT(ieee80211w); 800 #endif /* CONFIG_IEEE80211W */ 801 STR(id_str); 802 803 #undef STR 804 #undef INT 805 #undef INT_DEF 806 } 807 808 809 #ifndef CONFIG_NO_CONFIG_BLOBS 810 static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) 811 { 812 unsigned char *encoded; 813 814 encoded = base64_encode(blob->data, blob->len, NULL); 815 if (encoded == NULL) 816 return -1; 817 818 fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded); 819 os_free(encoded); 820 return 0; 821 } 822 #endif /* CONFIG_NO_CONFIG_BLOBS */ 823 824 825 static void wpa_config_write_global(FILE *f, struct wpa_config *config) 826 { 827 #ifdef CONFIG_CTRL_IFACE 828 if (config->ctrl_interface) 829 fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); 830 if (config->ctrl_interface_group) 831 fprintf(f, "ctrl_interface_group=%s\n", 832 config->ctrl_interface_group); 833 #endif /* CONFIG_CTRL_IFACE */ 834 if (config->eapol_version != DEFAULT_EAPOL_VERSION) 835 fprintf(f, "eapol_version=%d\n", config->eapol_version); 836 if (config->ap_scan != DEFAULT_AP_SCAN) 837 fprintf(f, "ap_scan=%d\n", config->ap_scan); 838 if (config->fast_reauth != DEFAULT_FAST_REAUTH) 839 fprintf(f, "fast_reauth=%d\n", config->fast_reauth); 840 #ifdef EAP_TLS_OPENSSL 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 #endif /* EAP_TLS_OPENSSL */ 851 if (config->driver_param) 852 fprintf(f, "driver_param=%s\n", config->driver_param); 853 if (config->dot11RSNAConfigPMKLifetime) 854 fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n", 855 config->dot11RSNAConfigPMKLifetime); 856 if (config->dot11RSNAConfigPMKReauthThreshold) 857 fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n", 858 config->dot11RSNAConfigPMKReauthThreshold); 859 if (config->dot11RSNAConfigSATimeout) 860 fprintf(f, "dot11RSNAConfigSATimeout=%d\n", 861 config->dot11RSNAConfigSATimeout); 862 if (config->update_config) 863 fprintf(f, "update_config=%d\n", config->update_config); 864 #ifdef CONFIG_WPS 865 if (!is_nil_uuid(config->uuid)) { 866 char buf[40]; 867 uuid_bin2str(config->uuid, buf, sizeof(buf)); 868 fprintf(f, "uuid=%s\n", buf); 869 } 870 if (config->device_name) 871 fprintf(f, "device_name=%s\n", config->device_name); 872 if (config->manufacturer) 873 fprintf(f, "manufacturer=%s\n", config->manufacturer); 874 if (config->model_name) 875 fprintf(f, "model_name=%s\n", config->model_name); 876 if (config->model_number) 877 fprintf(f, "model_number=%s\n", config->model_number); 878 if (config->serial_number) 879 fprintf(f, "serial_number=%s\n", config->serial_number); 880 if (config->device_type) 881 fprintf(f, "device_type=%s\n", config->device_type); 882 if (WPA_GET_BE32(config->os_version)) 883 fprintf(f, "os_version=%08x\n", 884 WPA_GET_BE32(config->os_version)); 885 if (config->wps_cred_processing) 886 fprintf(f, "wps_cred_processing=%d\n", 887 config->wps_cred_processing); 888 #endif /* CONFIG_WPS */ 889 if (config->country[0] && config->country[1]) { 890 fprintf(f, "country=%c%c\n", 891 config->country[0], config->country[1]); 892 } 893 } 894 895 #endif /* CONFIG_NO_CONFIG_WRITE */ 896 897 898 int wpa_config_write(const char *name, struct wpa_config *config) 899 { 900 #ifndef CONFIG_NO_CONFIG_WRITE 901 FILE *f; 902 struct wpa_ssid *ssid; 903 #ifndef CONFIG_NO_CONFIG_BLOBS 904 struct wpa_config_blob *blob; 905 #endif /* CONFIG_NO_CONFIG_BLOBS */ 906 int ret = 0; 907 908 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 909 910 f = fopen(name, "w"); 911 if (f == NULL) { 912 wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name); 913 return -1; 914 } 915 916 wpa_config_write_global(f, config); 917 918 for (ssid = config->ssid; ssid; ssid = ssid->next) { 919 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS) 920 continue; /* do not save temporary WPS networks */ 921 fprintf(f, "\nnetwork={\n"); 922 wpa_config_write_network(f, ssid); 923 fprintf(f, "}\n"); 924 } 925 926 #ifndef CONFIG_NO_CONFIG_BLOBS 927 for (blob = config->blobs; blob; blob = blob->next) { 928 ret = wpa_config_write_blob(f, blob); 929 if (ret) 930 break; 931 } 932 #endif /* CONFIG_NO_CONFIG_BLOBS */ 933 934 fclose(f); 935 936 wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", 937 name, ret ? "un" : ""); 938 return ret; 939 #else /* CONFIG_NO_CONFIG_WRITE */ 940 return -1; 941 #endif /* CONFIG_NO_CONFIG_WRITE */ 942 } 943