1 /* 2 * WPA Supplicant / Configuration backend: text file 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 * This file implements a configuration backend for text files. All the 9 * configuration information is stored in a text file that uses a format 10 * described in the sample configuration file, wpa_supplicant.conf. 11 */ 12 13 #include "includes.h" 14 15 #include "common.h" 16 #include "config.h" 17 #include "base64.h" 18 #include "uuid.h" 19 20 21 /** 22 * wpa_config_get_line - Read the next configuration file line 23 * @s: Buffer for the line 24 * @size: The buffer length 25 * @stream: File stream to read from 26 * @line: Pointer to a variable storing the file line number 27 * @_pos: Buffer for the pointer to the beginning of data on the text line or 28 * %NULL if not needed (returned value used instead) 29 * Returns: Pointer to the beginning of data on the text line or %NULL if no 30 * more text lines are available. 31 * 32 * This function reads the next non-empty line from the configuration file and 33 * removes comments. The returned string is guaranteed to be null-terminated. 34 */ 35 static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line, 36 char **_pos) 37 { 38 char *pos, *end, *sstart; 39 40 while (fgets(s, size, stream)) { 41 (*line)++; 42 s[size - 1] = '\0'; 43 pos = s; 44 45 /* Skip white space from the beginning of line. */ 46 while (*pos == ' ' || *pos == '\t' || *pos == '\r') 47 pos++; 48 49 /* Skip comment lines and empty lines */ 50 if (*pos == '#' || *pos == '\n' || *pos == '\0') 51 continue; 52 53 /* 54 * Remove # comments unless they are within a double quoted 55 * string. 56 */ 57 sstart = os_strchr(pos, '"'); 58 if (sstart) 59 sstart = os_strrchr(sstart + 1, '"'); 60 if (!sstart) 61 sstart = pos; 62 end = os_strchr(sstart, '#'); 63 if (end) 64 *end-- = '\0'; 65 else 66 end = pos + os_strlen(pos) - 1; 67 68 /* Remove trailing white space. */ 69 while (end > pos && 70 (*end == '\n' || *end == ' ' || *end == '\t' || 71 *end == '\r')) 72 *end-- = '\0'; 73 74 if (*pos == '\0') 75 continue; 76 77 if (_pos) 78 *_pos = pos; 79 return pos; 80 } 81 82 if (_pos) 83 *_pos = NULL; 84 return NULL; 85 } 86 87 88 static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) 89 { 90 int errors = 0; 91 92 if (ssid->passphrase) { 93 if (ssid->psk_set) { 94 wpa_printf(MSG_ERROR, "Line %d: both PSK and " 95 "passphrase configured.", line); 96 errors++; 97 } 98 wpa_config_update_psk(ssid); 99 } 100 101 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set) { 102 wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key " 103 "management, but no PSK configured.", line); 104 errors++; 105 } 106 107 if ((ssid->group_cipher & WPA_CIPHER_CCMP) && 108 !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && 109 !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { 110 /* Group cipher cannot be stronger than the pairwise cipher. */ 111 wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" 112 " list since it was not allowed for pairwise " 113 "cipher", line); 114 ssid->group_cipher &= ~WPA_CIPHER_CCMP; 115 } 116 117 return errors; 118 } 119 120 121 static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) 122 { 123 struct wpa_ssid *ssid; 124 int errors = 0, end = 0; 125 char buf[256], *pos, *pos2; 126 127 wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", 128 *line); 129 ssid = os_zalloc(sizeof(*ssid)); 130 if (ssid == NULL) 131 return NULL; 132 ssid->id = id; 133 134 wpa_config_set_network_defaults(ssid); 135 136 while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 137 if (os_strcmp(pos, "}") == 0) { 138 end = 1; 139 break; 140 } 141 142 pos2 = os_strchr(pos, '='); 143 if (pos2 == NULL) { 144 wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " 145 "'%s'.", *line, pos); 146 errors++; 147 continue; 148 } 149 150 *pos2++ = '\0'; 151 if (*pos2 == '"') { 152 if (os_strchr(pos2 + 1, '"') == NULL) { 153 wpa_printf(MSG_ERROR, "Line %d: invalid " 154 "quotation '%s'.", *line, pos2); 155 errors++; 156 continue; 157 } 158 } 159 160 if (wpa_config_set(ssid, pos, pos2, *line) < 0) 161 errors++; 162 } 163 164 if (!end) { 165 wpa_printf(MSG_ERROR, "Line %d: network block was not " 166 "terminated properly.", *line); 167 errors++; 168 } 169 170 errors += wpa_config_validate_network(ssid, *line); 171 172 if (errors) { 173 wpa_config_free_ssid(ssid); 174 ssid = NULL; 175 } 176 177 return ssid; 178 } 179 180 181 #ifndef CONFIG_NO_CONFIG_BLOBS 182 static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line, 183 const char *name) 184 { 185 struct wpa_config_blob *blob; 186 char buf[256], *pos; 187 unsigned char *encoded = NULL, *nencoded; 188 int end = 0; 189 size_t encoded_len = 0, len; 190 191 wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'", 192 *line, name); 193 194 while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 195 if (os_strcmp(pos, "}") == 0) { 196 end = 1; 197 break; 198 } 199 200 len = os_strlen(pos); 201 nencoded = os_realloc(encoded, encoded_len + len); 202 if (nencoded == NULL) { 203 wpa_printf(MSG_ERROR, "Line %d: not enough memory for " 204 "blob", *line); 205 os_free(encoded); 206 return NULL; 207 } 208 encoded = nencoded; 209 os_memcpy(encoded + encoded_len, pos, len); 210 encoded_len += len; 211 } 212 213 if (!end) { 214 wpa_printf(MSG_ERROR, "Line %d: blob was not terminated " 215 "properly", *line); 216 os_free(encoded); 217 return NULL; 218 } 219 220 blob = os_zalloc(sizeof(*blob)); 221 if (blob == NULL) { 222 os_free(encoded); 223 return NULL; 224 } 225 blob->name = os_strdup(name); 226 blob->data = base64_decode(encoded, encoded_len, &blob->len); 227 os_free(encoded); 228 229 if (blob->name == NULL || blob->data == NULL) { 230 wpa_config_free_blob(blob); 231 return NULL; 232 } 233 234 return blob; 235 } 236 237 238 static int wpa_config_process_blob(struct wpa_config *config, FILE *f, 239 int *line, char *bname) 240 { 241 char *name_end; 242 struct wpa_config_blob *blob; 243 244 name_end = os_strchr(bname, '='); 245 if (name_end == NULL) { 246 wpa_printf(MSG_ERROR, "Line %d: no blob name terminator", 247 *line); 248 return -1; 249 } 250 *name_end = '\0'; 251 252 blob = wpa_config_read_blob(f, line, bname); 253 if (blob == NULL) { 254 wpa_printf(MSG_ERROR, "Line %d: failed to read blob %s", 255 *line, bname); 256 return -1; 257 } 258 wpa_config_set_blob(config, blob); 259 return 0; 260 } 261 #endif /* CONFIG_NO_CONFIG_BLOBS */ 262 263 264 struct wpa_config * wpa_config_read(const char *name) 265 { 266 FILE *f; 267 char buf[256], *pos; 268 int errors = 0, line = 0; 269 struct wpa_ssid *ssid, *tail = NULL, *head = NULL; 270 struct wpa_config *config; 271 int id = 0; 272 273 config = wpa_config_alloc_empty(NULL, NULL); 274 if (config == NULL) 275 return NULL; 276 wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); 277 f = fopen(name, "r"); 278 if (f == NULL) { 279 os_free(config); 280 return NULL; 281 } 282 283 while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { 284 if (os_strcmp(pos, "network={") == 0) { 285 ssid = wpa_config_read_network(f, &line, id++); 286 if (ssid == NULL) { 287 wpa_printf(MSG_ERROR, "Line %d: failed to " 288 "parse network block.", line); 289 errors++; 290 continue; 291 } 292 if (head == NULL) { 293 head = tail = ssid; 294 } else { 295 tail->next = ssid; 296 tail = ssid; 297 } 298 if (wpa_config_add_prio_network(config, ssid)) { 299 wpa_printf(MSG_ERROR, "Line %d: failed to add " 300 "network block to priority list.", 301 line); 302 errors++; 303 continue; 304 } 305 #ifndef CONFIG_NO_CONFIG_BLOBS 306 } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { 307 if (wpa_config_process_blob(config, f, &line, pos + 12) 308 < 0) { 309 errors++; 310 continue; 311 } 312 #endif /* CONFIG_NO_CONFIG_BLOBS */ 313 } else if (wpa_config_process_global(config, pos, line) < 0) { 314 wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " 315 "line '%s'.", line, pos); 316 errors++; 317 continue; 318 } 319 } 320 321 fclose(f); 322 323 config->ssid = head; 324 wpa_config_debug_dump_networks(config); 325 326 #ifndef WPA_IGNORE_CONFIG_ERRORS 327 if (errors) { 328 wpa_config_free(config); 329 config = NULL; 330 head = NULL; 331 } 332 #endif /* WPA_IGNORE_CONFIG_ERRORS */ 333 334 return config; 335 } 336 337 338 #ifndef CONFIG_NO_CONFIG_WRITE 339 340 static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid) 341 { 342 char *value = wpa_config_get(ssid, field); 343 if (value == NULL) 344 return; 345 fprintf(f, "\t%s=%s\n", field, value); 346 os_free(value); 347 } 348 349 350 static void write_int(FILE *f, const char *field, int value, int def) 351 { 352 if (value == def) 353 return; 354 fprintf(f, "\t%s=%d\n", field, value); 355 } 356 357 358 static void write_bssid(FILE *f, struct wpa_ssid *ssid) 359 { 360 char *value = wpa_config_get(ssid, "bssid"); 361 if (value == NULL) 362 return; 363 fprintf(f, "\tbssid=%s\n", value); 364 os_free(value); 365 } 366 367 368 static void write_psk(FILE *f, struct wpa_ssid *ssid) 369 { 370 char *value = wpa_config_get(ssid, "psk"); 371 if (value == NULL) 372 return; 373 fprintf(f, "\tpsk=%s\n", value); 374 os_free(value); 375 } 376 377 378 static void write_proto(FILE *f, struct wpa_ssid *ssid) 379 { 380 char *value; 381 382 if (ssid->proto == DEFAULT_PROTO) 383 return; 384 385 value = wpa_config_get(ssid, "proto"); 386 if (value == NULL) 387 return; 388 if (value[0]) 389 fprintf(f, "\tproto=%s\n", value); 390 os_free(value); 391 } 392 393 394 static void write_key_mgmt(FILE *f, struct wpa_ssid *ssid) 395 { 396 char *value; 397 398 if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 399 return; 400 401 value = wpa_config_get(ssid, "key_mgmt"); 402 if (value == NULL) 403 return; 404 if (value[0]) 405 fprintf(f, "\tkey_mgmt=%s\n", value); 406 os_free(value); 407 } 408 409 410 static void write_pairwise(FILE *f, struct wpa_ssid *ssid) 411 { 412 char *value; 413 414 if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 415 return; 416 417 value = wpa_config_get(ssid, "pairwise"); 418 if (value == NULL) 419 return; 420 if (value[0]) 421 fprintf(f, "\tpairwise=%s\n", value); 422 os_free(value); 423 } 424 425 426 static void write_group(FILE *f, struct wpa_ssid *ssid) 427 { 428 char *value; 429 430 if (ssid->group_cipher == DEFAULT_GROUP) 431 return; 432 433 value = wpa_config_get(ssid, "group"); 434 if (value == NULL) 435 return; 436 if (value[0]) 437 fprintf(f, "\tgroup=%s\n", value); 438 os_free(value); 439 } 440 441 442 static void write_auth_alg(FILE *f, struct wpa_ssid *ssid) 443 { 444 char *value; 445 446 if (ssid->auth_alg == 0) 447 return; 448 449 value = wpa_config_get(ssid, "auth_alg"); 450 if (value == NULL) 451 return; 452 if (value[0]) 453 fprintf(f, "\tauth_alg=%s\n", value); 454 os_free(value); 455 } 456 457 458 #ifdef IEEE8021X_EAPOL 459 static void write_eap(FILE *f, struct wpa_ssid *ssid) 460 { 461 char *value; 462 463 value = wpa_config_get(ssid, "eap"); 464 if (value == NULL) 465 return; 466 467 if (value[0]) 468 fprintf(f, "\teap=%s\n", value); 469 os_free(value); 470 } 471 #endif /* IEEE8021X_EAPOL */ 472 473 474 static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) 475 { 476 char field[20], *value; 477 int res; 478 479 res = os_snprintf(field, sizeof(field), "wep_key%d", idx); 480 if (res < 0 || (size_t) res >= sizeof(field)) 481 return; 482 value = wpa_config_get(ssid, field); 483 if (value) { 484 fprintf(f, "\t%s=%s\n", field, value); 485 os_free(value); 486 } 487 } 488 489 490 #ifdef CONFIG_P2P 491 static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid) 492 { 493 char *value = wpa_config_get(ssid, "p2p_client_list"); 494 if (value == NULL) 495 return; 496 fprintf(f, "\tp2p_client_list=%s\n", value); 497 os_free(value); 498 } 499 #endif /* CONFIG_P2P */ 500 501 502 static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) 503 { 504 int i; 505 506 #define STR(t) write_str(f, #t, ssid) 507 #define INT(t) write_int(f, #t, ssid->t, 0) 508 #define INTe(t) write_int(f, #t, ssid->eap.t, 0) 509 #define INT_DEF(t, def) write_int(f, #t, ssid->t, def) 510 #define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def) 511 512 STR(ssid); 513 INT(scan_ssid); 514 write_bssid(f, ssid); 515 write_psk(f, ssid); 516 write_proto(f, ssid); 517 write_key_mgmt(f, ssid); 518 write_pairwise(f, ssid); 519 write_group(f, ssid); 520 write_auth_alg(f, ssid); 521 #ifdef IEEE8021X_EAPOL 522 write_eap(f, ssid); 523 STR(identity); 524 STR(anonymous_identity); 525 STR(password); 526 STR(ca_cert); 527 STR(ca_path); 528 STR(client_cert); 529 STR(private_key); 530 STR(private_key_passwd); 531 STR(dh_file); 532 STR(subject_match); 533 STR(altsubject_match); 534 STR(ca_cert2); 535 STR(ca_path2); 536 STR(client_cert2); 537 STR(private_key2); 538 STR(private_key2_passwd); 539 STR(dh_file2); 540 STR(subject_match2); 541 STR(altsubject_match2); 542 STR(phase1); 543 STR(phase2); 544 STR(pcsc); 545 STR(pin); 546 STR(engine_id); 547 STR(key_id); 548 STR(cert_id); 549 STR(ca_cert_id); 550 STR(key2_id); 551 STR(pin2); 552 STR(engine2_id); 553 STR(cert2_id); 554 STR(ca_cert2_id); 555 INTe(engine); 556 INTe(engine2); 557 INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 558 #endif /* IEEE8021X_EAPOL */ 559 for (i = 0; i < 4; i++) 560 write_wep_key(f, i, ssid); 561 INT(wep_tx_keyidx); 562 INT(priority); 563 #ifdef IEEE8021X_EAPOL 564 INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 565 STR(pac_file); 566 INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE); 567 #endif /* IEEE8021X_EAPOL */ 568 INT(mode); 569 INT(proactive_key_caching); 570 INT(disabled); 571 INT(peerkey); 572 #ifdef CONFIG_IEEE80211W 573 INT(ieee80211w); 574 #endif /* CONFIG_IEEE80211W */ 575 STR(id_str); 576 #ifdef CONFIG_P2P 577 write_p2p_client_list(f, ssid); 578 #endif /* CONFIG_P2P */ 579 580 #undef STR 581 #undef INT 582 #undef INT_DEF 583 } 584 585 586 #ifndef CONFIG_NO_CONFIG_BLOBS 587 static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) 588 { 589 unsigned char *encoded; 590 591 encoded = base64_encode(blob->data, blob->len, NULL); 592 if (encoded == NULL) 593 return -1; 594 595 fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded); 596 os_free(encoded); 597 return 0; 598 } 599 #endif /* CONFIG_NO_CONFIG_BLOBS */ 600 601 602 static void wpa_config_write_global(FILE *f, struct wpa_config *config) 603 { 604 #ifdef CONFIG_CTRL_IFACE 605 if (config->ctrl_interface) 606 fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); 607 if (config->ctrl_interface_group) 608 fprintf(f, "ctrl_interface_group=%s\n", 609 config->ctrl_interface_group); 610 #endif /* CONFIG_CTRL_IFACE */ 611 if (config->eapol_version != DEFAULT_EAPOL_VERSION) 612 fprintf(f, "eapol_version=%d\n", config->eapol_version); 613 if (config->ap_scan != DEFAULT_AP_SCAN) 614 fprintf(f, "ap_scan=%d\n", config->ap_scan); 615 if (config->fast_reauth != DEFAULT_FAST_REAUTH) 616 fprintf(f, "fast_reauth=%d\n", config->fast_reauth); 617 if (config->opensc_engine_path) 618 fprintf(f, "opensc_engine_path=%s\n", 619 config->opensc_engine_path); 620 if (config->pkcs11_engine_path) 621 fprintf(f, "pkcs11_engine_path=%s\n", 622 config->pkcs11_engine_path); 623 if (config->pkcs11_module_path) 624 fprintf(f, "pkcs11_module_path=%s\n", 625 config->pkcs11_module_path); 626 if (config->driver_param) 627 fprintf(f, "driver_param=%s\n", config->driver_param); 628 if (config->dot11RSNAConfigPMKLifetime) 629 fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n", 630 config->dot11RSNAConfigPMKLifetime); 631 if (config->dot11RSNAConfigPMKReauthThreshold) 632 fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n", 633 config->dot11RSNAConfigPMKReauthThreshold); 634 if (config->dot11RSNAConfigSATimeout) 635 fprintf(f, "dot11RSNAConfigSATimeout=%d\n", 636 config->dot11RSNAConfigSATimeout); 637 if (config->update_config) 638 fprintf(f, "update_config=%d\n", config->update_config); 639 #ifdef CONFIG_WPS 640 if (!is_nil_uuid(config->uuid)) { 641 char buf[40]; 642 uuid_bin2str(config->uuid, buf, sizeof(buf)); 643 fprintf(f, "uuid=%s\n", buf); 644 } 645 if (config->device_name) 646 fprintf(f, "device_name=%s\n", config->device_name); 647 if (config->manufacturer) 648 fprintf(f, "manufacturer=%s\n", config->manufacturer); 649 if (config->model_name) 650 fprintf(f, "model_name=%s\n", config->model_name); 651 if (config->model_number) 652 fprintf(f, "model_number=%s\n", config->model_number); 653 if (config->serial_number) 654 fprintf(f, "serial_number=%s\n", config->serial_number); 655 { 656 char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; 657 buf = wps_dev_type_bin2str(config->device_type, 658 _buf, sizeof(_buf)); 659 if (os_strcmp(buf, "0-00000000-0") != 0) 660 fprintf(f, "device_type=%s\n", buf); 661 } 662 if (WPA_GET_BE32(config->os_version)) 663 fprintf(f, "os_version=%08x\n", 664 WPA_GET_BE32(config->os_version)); 665 if (config->config_methods) 666 fprintf(f, "config_methods=%s\n", config->config_methods); 667 if (config->wps_cred_processing) 668 fprintf(f, "wps_cred_processing=%d\n", 669 config->wps_cred_processing); 670 #endif /* CONFIG_WPS */ 671 #ifdef CONFIG_P2P 672 if (config->p2p_listen_reg_class) 673 fprintf(f, "p2p_listen_reg_class=%u\n", 674 config->p2p_listen_reg_class); 675 if (config->p2p_listen_channel) 676 fprintf(f, "p2p_listen_channel=%u\n", 677 config->p2p_listen_channel); 678 if (config->p2p_oper_reg_class) 679 fprintf(f, "p2p_oper_reg_class=%u\n", 680 config->p2p_oper_reg_class); 681 if (config->p2p_oper_channel) 682 fprintf(f, "p2p_oper_channel=%u\n", config->p2p_oper_channel); 683 if (config->p2p_go_intent != DEFAULT_P2P_GO_INTENT) 684 fprintf(f, "p2p_go_intent=%u\n", config->p2p_go_intent); 685 if (config->p2p_ssid_postfix) 686 fprintf(f, "p2p_ssid_postfix=%s\n", config->p2p_ssid_postfix); 687 if (config->persistent_reconnect) 688 fprintf(f, "persistent_reconnect=%u\n", 689 config->persistent_reconnect); 690 if (config->p2p_intra_bss != DEFAULT_P2P_INTRA_BSS) 691 fprintf(f, "p2p_intra_bss=%u\n", config->p2p_intra_bss); 692 if (config->p2p_group_idle) 693 fprintf(f, "p2p_group_idle=%u\n", config->p2p_group_idle); 694 #endif /* CONFIG_P2P */ 695 if (config->country[0] && config->country[1]) { 696 fprintf(f, "country=%c%c\n", 697 config->country[0], config->country[1]); 698 } 699 if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT) 700 fprintf(f, "bss_max_count=%u\n", config->bss_max_count); 701 if (config->bss_expiration_age != DEFAULT_BSS_EXPIRATION_AGE) 702 fprintf(f, "bss_expiration_age=%u\n", 703 config->bss_expiration_age); 704 if (config->bss_expiration_scan_count != 705 DEFAULT_BSS_EXPIRATION_SCAN_COUNT) 706 fprintf(f, "bss_expiration_scan_count=%u\n", 707 config->bss_expiration_scan_count); 708 if (config->filter_ssids) 709 fprintf(f, "filter_ssids=%d\n", config->filter_ssids); 710 if (config->max_num_sta != DEFAULT_MAX_NUM_STA) 711 fprintf(f, "max_num_sta=%u\n", config->max_num_sta); 712 if (config->disassoc_low_ack) 713 fprintf(f, "disassoc_low_ack=%u\n", config->disassoc_low_ack); 714 #ifdef CONFIG_INTERWORKING 715 if (config->home_realm) 716 fprintf(f, "home_realm=%s\n", config->home_realm); 717 if (config->home_username) 718 fprintf(f, "home_username=%s\n", config->home_username); 719 if (config->home_password) 720 fprintf(f, "home_password=%s\n", config->home_password); 721 if (config->home_ca_cert) 722 fprintf(f, "home_ca_cert=%s\n", config->home_ca_cert); 723 if (config->home_imsi) 724 fprintf(f, "home_imsi=%s\n", config->home_imsi); 725 if (config->home_milenage) 726 fprintf(f, "home_milenage=%s\n", config->home_milenage); 727 if (config->interworking) 728 fprintf(f, "interworking=%u\n", config->interworking); 729 if (!is_zero_ether_addr(config->hessid)) 730 fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid)); 731 if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE) 732 fprintf(f, "access_network_type=%d\n", 733 config->access_network_type); 734 #endif /* CONFIG_INTERWORKING */ 735 } 736 737 #endif /* CONFIG_NO_CONFIG_WRITE */ 738 739 740 int wpa_config_write(const char *name, struct wpa_config *config) 741 { 742 #ifndef CONFIG_NO_CONFIG_WRITE 743 FILE *f; 744 struct wpa_ssid *ssid; 745 #ifndef CONFIG_NO_CONFIG_BLOBS 746 struct wpa_config_blob *blob; 747 #endif /* CONFIG_NO_CONFIG_BLOBS */ 748 int ret = 0; 749 750 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 751 752 f = fopen(name, "w"); 753 if (f == NULL) { 754 wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name); 755 return -1; 756 } 757 758 wpa_config_write_global(f, config); 759 760 for (ssid = config->ssid; ssid; ssid = ssid->next) { 761 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary) 762 continue; /* do not save temporary networks */ 763 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && 764 !ssid->passphrase) 765 continue; /* do not save invalid network */ 766 fprintf(f, "\nnetwork={\n"); 767 wpa_config_write_network(f, ssid); 768 fprintf(f, "}\n"); 769 } 770 771 #ifndef CONFIG_NO_CONFIG_BLOBS 772 for (blob = config->blobs; blob; blob = blob->next) { 773 ret = wpa_config_write_blob(f, blob); 774 if (ret) 775 break; 776 } 777 #endif /* CONFIG_NO_CONFIG_BLOBS */ 778 779 fclose(f); 780 781 wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", 782 name, ret ? "un" : ""); 783 return ret; 784 #else /* CONFIG_NO_CONFIG_WRITE */ 785 return -1; 786 #endif /* CONFIG_NO_CONFIG_WRITE */ 787 } 788