1 /* 2 * WPA Supplicant / Configuration backend: text file 3 * Copyright (c) 2003-2012, 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 #include "p2p/p2p.h" 20 #include "eap_peer/eap_methods.h" 21 #include "eap_peer/eap.h" 22 23 #ifdef ANDROID 24 #include <sys/stat.h> 25 #endif 26 27 static int newline_terminated(const char *buf, size_t buflen) 28 { 29 size_t len = os_strlen(buf); 30 if (len == 0) 31 return 0; 32 if (len == buflen - 1 && buf[buflen - 1] != '\r' && 33 buf[len - 1] != '\n') 34 return 0; 35 return 1; 36 } 37 38 39 static void skip_line_end(FILE *stream) 40 { 41 char buf[100]; 42 while (fgets(buf, sizeof(buf), stream)) { 43 buf[sizeof(buf) - 1] = '\0'; 44 if (newline_terminated(buf, sizeof(buf))) 45 return; 46 } 47 } 48 49 50 /** 51 * wpa_config_get_line - Read the next configuration file line 52 * @s: Buffer for the line 53 * @size: The buffer length 54 * @stream: File stream to read from 55 * @line: Pointer to a variable storing the file line number 56 * @_pos: Buffer for the pointer to the beginning of data on the text line or 57 * %NULL if not needed (returned value used instead) 58 * Returns: Pointer to the beginning of data on the text line or %NULL if no 59 * more text lines are available. 60 * 61 * This function reads the next non-empty line from the configuration file and 62 * removes comments. The returned string is guaranteed to be null-terminated. 63 */ 64 static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line, 65 char **_pos) 66 { 67 char *pos, *end, *sstart; 68 69 while (fgets(s, size, stream)) { 70 (*line)++; 71 s[size - 1] = '\0'; 72 if (!newline_terminated(s, size)) { 73 /* 74 * The line was truncated - skip rest of it to avoid 75 * confusing error messages. 76 */ 77 wpa_printf(MSG_INFO, "Long line in configuration file " 78 "truncated"); 79 skip_line_end(stream); 80 } 81 pos = s; 82 83 /* Skip white space from the beginning of line. */ 84 while (*pos == ' ' || *pos == '\t' || *pos == '\r') 85 pos++; 86 87 /* Skip comment lines and empty lines */ 88 if (*pos == '#' || *pos == '\n' || *pos == '\0') 89 continue; 90 91 /* 92 * Remove # comments unless they are within a double quoted 93 * string. 94 */ 95 sstart = os_strchr(pos, '"'); 96 if (sstart) 97 sstart = os_strrchr(sstart + 1, '"'); 98 if (!sstart) 99 sstart = pos; 100 end = os_strchr(sstart, '#'); 101 if (end) 102 *end-- = '\0'; 103 else 104 end = pos + os_strlen(pos) - 1; 105 106 /* Remove trailing white space. */ 107 while (end > pos && 108 (*end == '\n' || *end == ' ' || *end == '\t' || 109 *end == '\r')) 110 *end-- = '\0'; 111 112 if (*pos == '\0') 113 continue; 114 115 if (_pos) 116 *_pos = pos; 117 return pos; 118 } 119 120 if (_pos) 121 *_pos = NULL; 122 return NULL; 123 } 124 125 126 static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) 127 { 128 int errors = 0; 129 130 if (ssid->passphrase) { 131 if (ssid->psk_set) { 132 wpa_printf(MSG_ERROR, "Line %d: both PSK and " 133 "passphrase configured.", line); 134 errors++; 135 } 136 wpa_config_update_psk(ssid); 137 } 138 139 if ((ssid->group_cipher & WPA_CIPHER_CCMP) && 140 !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && 141 !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { 142 /* Group cipher cannot be stronger than the pairwise cipher. */ 143 wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" 144 " list since it was not allowed for pairwise " 145 "cipher", line); 146 ssid->group_cipher &= ~WPA_CIPHER_CCMP; 147 } 148 149 return errors; 150 } 151 152 153 static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) 154 { 155 struct wpa_ssid *ssid; 156 int errors = 0, end = 0; 157 char buf[2000], *pos, *pos2; 158 159 wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", 160 *line); 161 ssid = os_zalloc(sizeof(*ssid)); 162 if (ssid == NULL) 163 return NULL; 164 dl_list_init(&ssid->psk_list); 165 ssid->id = id; 166 167 wpa_config_set_network_defaults(ssid); 168 169 while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 170 if (os_strcmp(pos, "}") == 0) { 171 end = 1; 172 break; 173 } 174 175 pos2 = os_strchr(pos, '='); 176 if (pos2 == NULL) { 177 wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " 178 "'%s'.", *line, pos); 179 errors++; 180 continue; 181 } 182 183 *pos2++ = '\0'; 184 if (*pos2 == '"') { 185 if (os_strchr(pos2 + 1, '"') == NULL) { 186 wpa_printf(MSG_ERROR, "Line %d: invalid " 187 "quotation '%s'.", *line, pos2); 188 errors++; 189 continue; 190 } 191 } 192 193 if (wpa_config_set(ssid, pos, pos2, *line) < 0) 194 errors++; 195 } 196 197 if (!end) { 198 wpa_printf(MSG_ERROR, "Line %d: network block was not " 199 "terminated properly.", *line); 200 errors++; 201 } 202 203 errors += wpa_config_validate_network(ssid, *line); 204 205 if (errors) { 206 wpa_config_free_ssid(ssid); 207 ssid = NULL; 208 } 209 210 return ssid; 211 } 212 213 214 static struct wpa_cred * wpa_config_read_cred(FILE *f, int *line, int id) 215 { 216 struct wpa_cred *cred; 217 int errors = 0, end = 0; 218 char buf[256], *pos, *pos2; 219 220 wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new cred block", *line); 221 cred = os_zalloc(sizeof(*cred)); 222 if (cred == NULL) 223 return NULL; 224 cred->id = id; 225 cred->sim_num = DEFAULT_USER_SELECTED_SIM; 226 227 while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 228 if (os_strcmp(pos, "}") == 0) { 229 end = 1; 230 break; 231 } 232 233 pos2 = os_strchr(pos, '='); 234 if (pos2 == NULL) { 235 wpa_printf(MSG_ERROR, "Line %d: Invalid cred line " 236 "'%s'.", *line, pos); 237 errors++; 238 continue; 239 } 240 241 *pos2++ = '\0'; 242 if (*pos2 == '"') { 243 if (os_strchr(pos2 + 1, '"') == NULL) { 244 wpa_printf(MSG_ERROR, "Line %d: invalid " 245 "quotation '%s'.", *line, pos2); 246 errors++; 247 continue; 248 } 249 } 250 251 if (wpa_config_set_cred(cred, pos, pos2, *line) < 0) 252 errors++; 253 } 254 255 if (!end) { 256 wpa_printf(MSG_ERROR, "Line %d: cred block was not " 257 "terminated properly.", *line); 258 errors++; 259 } 260 261 if (errors) { 262 wpa_config_free_cred(cred); 263 cred = NULL; 264 } 265 266 return cred; 267 } 268 269 270 #ifndef CONFIG_NO_CONFIG_BLOBS 271 static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line, 272 const char *name) 273 { 274 struct wpa_config_blob *blob; 275 char buf[256], *pos; 276 unsigned char *encoded = NULL, *nencoded; 277 int end = 0; 278 size_t encoded_len = 0, len; 279 280 wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'", 281 *line, name); 282 283 while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 284 if (os_strcmp(pos, "}") == 0) { 285 end = 1; 286 break; 287 } 288 289 len = os_strlen(pos); 290 nencoded = os_realloc(encoded, encoded_len + len); 291 if (nencoded == NULL) { 292 wpa_printf(MSG_ERROR, "Line %d: not enough memory for " 293 "blob", *line); 294 os_free(encoded); 295 return NULL; 296 } 297 encoded = nencoded; 298 os_memcpy(encoded + encoded_len, pos, len); 299 encoded_len += len; 300 } 301 302 if (!end) { 303 wpa_printf(MSG_ERROR, "Line %d: blob was not terminated " 304 "properly", *line); 305 os_free(encoded); 306 return NULL; 307 } 308 309 blob = os_zalloc(sizeof(*blob)); 310 if (blob == NULL) { 311 os_free(encoded); 312 return NULL; 313 } 314 blob->name = os_strdup(name); 315 blob->data = base64_decode(encoded, encoded_len, &blob->len); 316 os_free(encoded); 317 318 if (blob->name == NULL || blob->data == NULL) { 319 wpa_config_free_blob(blob); 320 return NULL; 321 } 322 323 return blob; 324 } 325 326 327 static int wpa_config_process_blob(struct wpa_config *config, FILE *f, 328 int *line, char *bname) 329 { 330 char *name_end; 331 struct wpa_config_blob *blob; 332 333 name_end = os_strchr(bname, '='); 334 if (name_end == NULL) { 335 wpa_printf(MSG_ERROR, "Line %d: no blob name terminator", 336 *line); 337 return -1; 338 } 339 *name_end = '\0'; 340 341 blob = wpa_config_read_blob(f, line, bname); 342 if (blob == NULL) { 343 wpa_printf(MSG_ERROR, "Line %d: failed to read blob %s", 344 *line, bname); 345 return -1; 346 } 347 wpa_config_set_blob(config, blob); 348 return 0; 349 } 350 #endif /* CONFIG_NO_CONFIG_BLOBS */ 351 352 353 struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp) 354 { 355 FILE *f; 356 char buf[512], *pos; 357 int errors = 0, line = 0; 358 struct wpa_ssid *ssid, *tail, *head; 359 struct wpa_cred *cred, *cred_tail, *cred_head; 360 struct wpa_config *config; 361 int id = 0; 362 int cred_id = 0; 363 364 if (name == NULL) 365 return NULL; 366 if (cfgp) 367 config = cfgp; 368 else 369 config = wpa_config_alloc_empty(NULL, NULL); 370 if (config == NULL) { 371 wpa_printf(MSG_ERROR, "Failed to allocate config file " 372 "structure"); 373 return NULL; 374 } 375 tail = head = config->ssid; 376 while (tail && tail->next) 377 tail = tail->next; 378 cred_tail = cred_head = config->cred; 379 while (cred_tail && cred_tail->next) 380 cred_tail = cred_tail->next; 381 382 wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); 383 f = fopen(name, "r"); 384 if (f == NULL) { 385 wpa_printf(MSG_ERROR, "Failed to open config file '%s', " 386 "error: %s", name, strerror(errno)); 387 os_free(config); 388 return NULL; 389 } 390 391 while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { 392 if (os_strcmp(pos, "network={") == 0) { 393 ssid = wpa_config_read_network(f, &line, id++); 394 if (ssid == NULL) { 395 wpa_printf(MSG_ERROR, "Line %d: failed to " 396 "parse network block.", line); 397 errors++; 398 continue; 399 } 400 if (head == NULL) { 401 head = tail = ssid; 402 } else { 403 tail->next = ssid; 404 tail = ssid; 405 } 406 if (wpa_config_add_prio_network(config, ssid)) { 407 wpa_printf(MSG_ERROR, "Line %d: failed to add " 408 "network block to priority list.", 409 line); 410 errors++; 411 continue; 412 } 413 } else if (os_strcmp(pos, "cred={") == 0) { 414 cred = wpa_config_read_cred(f, &line, cred_id++); 415 if (cred == NULL) { 416 wpa_printf(MSG_ERROR, "Line %d: failed to " 417 "parse cred block.", line); 418 errors++; 419 continue; 420 } 421 if (cred_head == NULL) { 422 cred_head = cred_tail = cred; 423 } else { 424 cred_tail->next = cred; 425 cred_tail = cred; 426 } 427 #ifndef CONFIG_NO_CONFIG_BLOBS 428 } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { 429 if (wpa_config_process_blob(config, f, &line, pos + 12) 430 < 0) { 431 wpa_printf(MSG_ERROR, "Line %d: failed to " 432 "process blob.", line); 433 errors++; 434 continue; 435 } 436 #endif /* CONFIG_NO_CONFIG_BLOBS */ 437 } else if (wpa_config_process_global(config, pos, line) < 0) { 438 wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " 439 "line '%s'.", line, pos); 440 errors++; 441 continue; 442 } 443 } 444 445 fclose(f); 446 447 config->ssid = head; 448 wpa_config_debug_dump_networks(config); 449 config->cred = cred_head; 450 451 #ifndef WPA_IGNORE_CONFIG_ERRORS 452 if (errors) { 453 wpa_config_free(config); 454 config = NULL; 455 head = NULL; 456 } 457 #endif /* WPA_IGNORE_CONFIG_ERRORS */ 458 459 return config; 460 } 461 462 463 #ifndef CONFIG_NO_CONFIG_WRITE 464 465 static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid) 466 { 467 char *value = wpa_config_get(ssid, field); 468 if (value == NULL) 469 return; 470 fprintf(f, "\t%s=%s\n", field, value); 471 os_free(value); 472 } 473 474 475 static void write_int(FILE *f, const char *field, int value, int def) 476 { 477 if (value == def) 478 return; 479 fprintf(f, "\t%s=%d\n", field, value); 480 } 481 482 483 static void write_bssid(FILE *f, struct wpa_ssid *ssid) 484 { 485 char *value = wpa_config_get(ssid, "bssid"); 486 if (value == NULL) 487 return; 488 fprintf(f, "\tbssid=%s\n", value); 489 os_free(value); 490 } 491 492 493 static void write_psk(FILE *f, struct wpa_ssid *ssid) 494 { 495 char *value = wpa_config_get(ssid, "psk"); 496 if (value == NULL) 497 return; 498 fprintf(f, "\tpsk=%s\n", value); 499 os_free(value); 500 } 501 502 503 static void write_proto(FILE *f, struct wpa_ssid *ssid) 504 { 505 char *value; 506 507 if (ssid->proto == DEFAULT_PROTO) 508 return; 509 510 value = wpa_config_get(ssid, "proto"); 511 if (value == NULL) 512 return; 513 if (value[0]) 514 fprintf(f, "\tproto=%s\n", value); 515 os_free(value); 516 } 517 518 519 static void write_key_mgmt(FILE *f, struct wpa_ssid *ssid) 520 { 521 char *value; 522 523 if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 524 return; 525 526 value = wpa_config_get(ssid, "key_mgmt"); 527 if (value == NULL) 528 return; 529 if (value[0]) 530 fprintf(f, "\tkey_mgmt=%s\n", value); 531 os_free(value); 532 } 533 534 535 static void write_pairwise(FILE *f, struct wpa_ssid *ssid) 536 { 537 char *value; 538 539 if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 540 return; 541 542 value = wpa_config_get(ssid, "pairwise"); 543 if (value == NULL) 544 return; 545 if (value[0]) 546 fprintf(f, "\tpairwise=%s\n", value); 547 os_free(value); 548 } 549 550 551 static void write_group(FILE *f, struct wpa_ssid *ssid) 552 { 553 char *value; 554 555 if (ssid->group_cipher == DEFAULT_GROUP) 556 return; 557 558 value = wpa_config_get(ssid, "group"); 559 if (value == NULL) 560 return; 561 if (value[0]) 562 fprintf(f, "\tgroup=%s\n", value); 563 os_free(value); 564 } 565 566 567 static void write_auth_alg(FILE *f, struct wpa_ssid *ssid) 568 { 569 char *value; 570 571 if (ssid->auth_alg == 0) 572 return; 573 574 value = wpa_config_get(ssid, "auth_alg"); 575 if (value == NULL) 576 return; 577 if (value[0]) 578 fprintf(f, "\tauth_alg=%s\n", value); 579 os_free(value); 580 } 581 582 583 #ifdef IEEE8021X_EAPOL 584 static void write_eap(FILE *f, struct wpa_ssid *ssid) 585 { 586 char *value; 587 588 value = wpa_config_get(ssid, "eap"); 589 if (value == NULL) 590 return; 591 592 if (value[0]) 593 fprintf(f, "\teap=%s\n", value); 594 os_free(value); 595 } 596 #endif /* IEEE8021X_EAPOL */ 597 598 599 static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) 600 { 601 char field[20], *value; 602 int res; 603 604 res = os_snprintf(field, sizeof(field), "wep_key%d", idx); 605 if (res < 0 || (size_t) res >= sizeof(field)) 606 return; 607 value = wpa_config_get(ssid, field); 608 if (value) { 609 fprintf(f, "\t%s=%s\n", field, value); 610 os_free(value); 611 } 612 } 613 614 615 #ifdef CONFIG_P2P 616 617 static void write_go_p2p_dev_addr(FILE *f, struct wpa_ssid *ssid) 618 { 619 char *value = wpa_config_get(ssid, "go_p2p_dev_addr"); 620 if (value == NULL) 621 return; 622 fprintf(f, "\tgo_p2p_dev_addr=%s\n", value); 623 os_free(value); 624 } 625 626 static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid) 627 { 628 char *value = wpa_config_get(ssid, "p2p_client_list"); 629 if (value == NULL) 630 return; 631 fprintf(f, "\tp2p_client_list=%s\n", value); 632 os_free(value); 633 } 634 635 636 static void write_psk_list(FILE *f, struct wpa_ssid *ssid) 637 { 638 struct psk_list_entry *psk; 639 char hex[32 * 2 + 1]; 640 641 dl_list_for_each(psk, &ssid->psk_list, struct psk_list_entry, list) { 642 wpa_snprintf_hex(hex, sizeof(hex), psk->psk, sizeof(psk->psk)); 643 fprintf(f, "\tpsk_list=%s" MACSTR "-%s\n", 644 psk->p2p ? "P2P-" : "", MAC2STR(psk->addr), hex); 645 } 646 } 647 648 #endif /* CONFIG_P2P */ 649 650 651 static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) 652 { 653 int i; 654 655 #define STR(t) write_str(f, #t, ssid) 656 #define INT(t) write_int(f, #t, ssid->t, 0) 657 #define INTe(t) write_int(f, #t, ssid->eap.t, 0) 658 #define INT_DEF(t, def) write_int(f, #t, ssid->t, def) 659 #define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def) 660 661 STR(ssid); 662 INT(scan_ssid); 663 write_bssid(f, ssid); 664 write_psk(f, ssid); 665 write_proto(f, ssid); 666 write_key_mgmt(f, ssid); 667 INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD); 668 write_pairwise(f, ssid); 669 write_group(f, ssid); 670 write_auth_alg(f, ssid); 671 STR(bgscan); 672 STR(autoscan); 673 STR(scan_freq); 674 #ifdef IEEE8021X_EAPOL 675 write_eap(f, ssid); 676 STR(identity); 677 STR(anonymous_identity); 678 STR(password); 679 STR(ca_cert); 680 STR(ca_path); 681 STR(client_cert); 682 STR(private_key); 683 STR(private_key_passwd); 684 STR(dh_file); 685 STR(subject_match); 686 STR(altsubject_match); 687 STR(domain_suffix_match); 688 STR(ca_cert2); 689 STR(ca_path2); 690 STR(client_cert2); 691 STR(private_key2); 692 STR(private_key2_passwd); 693 STR(dh_file2); 694 STR(subject_match2); 695 STR(altsubject_match2); 696 STR(domain_suffix_match2); 697 STR(phase1); 698 STR(phase2); 699 STR(pcsc); 700 STR(pin); 701 STR(engine_id); 702 STR(key_id); 703 STR(cert_id); 704 STR(ca_cert_id); 705 STR(key2_id); 706 STR(pin2); 707 STR(engine2_id); 708 STR(cert2_id); 709 STR(ca_cert2_id); 710 INTe(engine); 711 INTe(engine2); 712 INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 713 #endif /* IEEE8021X_EAPOL */ 714 for (i = 0; i < 4; i++) 715 write_wep_key(f, i, ssid); 716 INT(wep_tx_keyidx); 717 INT(priority); 718 #ifdef IEEE8021X_EAPOL 719 INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 720 STR(pac_file); 721 INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE); 722 INTe(ocsp); 723 INT_DEFe(sim_num, DEFAULT_USER_SELECTED_SIM); 724 #endif /* IEEE8021X_EAPOL */ 725 INT(mode); 726 INT(frequency); 727 write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1); 728 INT(disabled); 729 INT(peerkey); 730 #ifdef CONFIG_IEEE80211W 731 write_int(f, "ieee80211w", ssid->ieee80211w, 732 MGMT_FRAME_PROTECTION_DEFAULT); 733 #endif /* CONFIG_IEEE80211W */ 734 STR(id_str); 735 #ifdef CONFIG_P2P 736 write_go_p2p_dev_addr(f, ssid); 737 write_p2p_client_list(f, ssid); 738 write_psk_list(f, ssid); 739 #endif /* CONFIG_P2P */ 740 INT(dtim_period); 741 INT(beacon_int); 742 #ifdef CONFIG_MACSEC 743 INT(macsec_policy); 744 #endif /* CONFIG_MACSEC */ 745 #ifdef CONFIG_HS20 746 INT(update_identifier); 747 #endif /* CONFIG_HS20 */ 748 write_int(f, "mac_addr", ssid->mac_addr, -1); 749 750 #undef STR 751 #undef INT 752 #undef INT_DEF 753 } 754 755 756 static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) 757 { 758 size_t i; 759 760 if (cred->priority) 761 fprintf(f, "\tpriority=%d\n", cred->priority); 762 if (cred->pcsc) 763 fprintf(f, "\tpcsc=%d\n", cred->pcsc); 764 if (cred->realm) 765 fprintf(f, "\trealm=\"%s\"\n", cred->realm); 766 if (cred->username) 767 fprintf(f, "\tusername=\"%s\"\n", cred->username); 768 if (cred->password && cred->ext_password) 769 fprintf(f, "\tpassword=ext:%s\n", cred->password); 770 else if (cred->password) 771 fprintf(f, "\tpassword=\"%s\"\n", cred->password); 772 if (cred->ca_cert) 773 fprintf(f, "\tca_cert=\"%s\"\n", cred->ca_cert); 774 if (cred->client_cert) 775 fprintf(f, "\tclient_cert=\"%s\"\n", cred->client_cert); 776 if (cred->private_key) 777 fprintf(f, "\tprivate_key=\"%s\"\n", cred->private_key); 778 if (cred->private_key_passwd) 779 fprintf(f, "\tprivate_key_passwd=\"%s\"\n", 780 cred->private_key_passwd); 781 if (cred->imsi) 782 fprintf(f, "\timsi=\"%s\"\n", cred->imsi); 783 if (cred->milenage) 784 fprintf(f, "\tmilenage=\"%s\"\n", cred->milenage); 785 for (i = 0; i < cred->num_domain; i++) 786 fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]); 787 if (cred->domain_suffix_match) 788 fprintf(f, "\tdomain_suffix_match=\"%s\"\n", 789 cred->domain_suffix_match); 790 if (cred->roaming_consortium_len) { 791 fprintf(f, "\troaming_consortium="); 792 for (i = 0; i < cred->roaming_consortium_len; i++) 793 fprintf(f, "%02x", cred->roaming_consortium[i]); 794 fprintf(f, "\n"); 795 } 796 if (cred->eap_method) { 797 const char *name; 798 name = eap_get_name(cred->eap_method[0].vendor, 799 cred->eap_method[0].method); 800 if (name) 801 fprintf(f, "\teap=%s\n", name); 802 } 803 if (cred->phase1) 804 fprintf(f, "\tphase1=\"%s\"\n", cred->phase1); 805 if (cred->phase2) 806 fprintf(f, "\tphase2=\"%s\"\n", cred->phase2); 807 if (cred->excluded_ssid) { 808 size_t j; 809 for (i = 0; i < cred->num_excluded_ssid; i++) { 810 struct excluded_ssid *e = &cred->excluded_ssid[i]; 811 fprintf(f, "\texcluded_ssid="); 812 for (j = 0; j < e->ssid_len; j++) 813 fprintf(f, "%02x", e->ssid[j]); 814 fprintf(f, "\n"); 815 } 816 } 817 if (cred->roaming_partner) { 818 for (i = 0; i < cred->num_roaming_partner; i++) { 819 struct roaming_partner *p = &cred->roaming_partner[i]; 820 fprintf(f, "\troaming_partner=\"%s,%d,%u,%s\"\n", 821 p->fqdn, p->exact_match, p->priority, 822 p->country); 823 } 824 } 825 if (cred->update_identifier) 826 fprintf(f, "\tupdate_identifier=%d\n", cred->update_identifier); 827 828 if (cred->provisioning_sp) 829 fprintf(f, "\tprovisioning_sp=\"%s\"\n", cred->provisioning_sp); 830 if (cred->sp_priority) 831 fprintf(f, "\tsp_priority=%d\n", cred->sp_priority); 832 833 if (cred->min_dl_bandwidth_home) 834 fprintf(f, "\tmin_dl_bandwidth_home=%u\n", 835 cred->min_dl_bandwidth_home); 836 if (cred->min_ul_bandwidth_home) 837 fprintf(f, "\tmin_ul_bandwidth_home=%u\n", 838 cred->min_ul_bandwidth_home); 839 if (cred->min_dl_bandwidth_roaming) 840 fprintf(f, "\tmin_dl_bandwidth_roaming=%u\n", 841 cred->min_dl_bandwidth_roaming); 842 if (cred->min_ul_bandwidth_roaming) 843 fprintf(f, "\tmin_ul_bandwidth_roaming=%u\n", 844 cred->min_ul_bandwidth_roaming); 845 846 if (cred->max_bss_load) 847 fprintf(f, "\tmax_bss_load=%u\n", 848 cred->max_bss_load); 849 850 if (cred->ocsp) 851 fprintf(f, "\tocsp=%d\n", cred->ocsp); 852 853 if (cred->num_req_conn_capab) { 854 for (i = 0; i < cred->num_req_conn_capab; i++) { 855 int *ports; 856 857 fprintf(f, "\treq_conn_capab=%u", 858 cred->req_conn_capab_proto[i]); 859 ports = cred->req_conn_capab_port[i]; 860 if (ports) { 861 int j; 862 for (j = 0; ports[j] != -1; j++) { 863 fprintf(f, "%s%d", j > 0 ? "," : ":", 864 ports[j]); 865 } 866 } 867 fprintf(f, "\n"); 868 } 869 } 870 871 if (cred->required_roaming_consortium_len) { 872 fprintf(f, "\trequired_roaming_consortium="); 873 for (i = 0; i < cred->required_roaming_consortium_len; i++) 874 fprintf(f, "%02x", 875 cred->required_roaming_consortium[i]); 876 fprintf(f, "\n"); 877 } 878 879 if (cred->sim_num != DEFAULT_USER_SELECTED_SIM) 880 fprintf(f, "\tsim_num=%d\n", cred->sim_num); 881 } 882 883 884 #ifndef CONFIG_NO_CONFIG_BLOBS 885 static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) 886 { 887 unsigned char *encoded; 888 889 encoded = base64_encode(blob->data, blob->len, NULL); 890 if (encoded == NULL) 891 return -1; 892 893 fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded); 894 os_free(encoded); 895 return 0; 896 } 897 #endif /* CONFIG_NO_CONFIG_BLOBS */ 898 899 900 static void write_global_bin(FILE *f, const char *field, 901 const struct wpabuf *val) 902 { 903 size_t i; 904 const u8 *pos; 905 906 if (val == NULL) 907 return; 908 909 fprintf(f, "%s=", field); 910 pos = wpabuf_head(val); 911 for (i = 0; i < wpabuf_len(val); i++) 912 fprintf(f, "%02X", *pos++); 913 fprintf(f, "\n"); 914 } 915 916 917 static void wpa_config_write_global(FILE *f, struct wpa_config *config) 918 { 919 #ifdef CONFIG_CTRL_IFACE 920 if (config->ctrl_interface) 921 fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); 922 if (config->ctrl_interface_group) 923 fprintf(f, "ctrl_interface_group=%s\n", 924 config->ctrl_interface_group); 925 #endif /* CONFIG_CTRL_IFACE */ 926 if (config->eapol_version != DEFAULT_EAPOL_VERSION) 927 fprintf(f, "eapol_version=%d\n", config->eapol_version); 928 if (config->ap_scan != DEFAULT_AP_SCAN) 929 fprintf(f, "ap_scan=%d\n", config->ap_scan); 930 if (config->disable_scan_offload) 931 fprintf(f, "disable_scan_offload=%d\n", 932 config->disable_scan_offload); 933 if (config->fast_reauth != DEFAULT_FAST_REAUTH) 934 fprintf(f, "fast_reauth=%d\n", config->fast_reauth); 935 if (config->opensc_engine_path) 936 fprintf(f, "opensc_engine_path=%s\n", 937 config->opensc_engine_path); 938 if (config->pkcs11_engine_path) 939 fprintf(f, "pkcs11_engine_path=%s\n", 940 config->pkcs11_engine_path); 941 if (config->pkcs11_module_path) 942 fprintf(f, "pkcs11_module_path=%s\n", 943 config->pkcs11_module_path); 944 if (config->pcsc_reader) 945 fprintf(f, "pcsc_reader=%s\n", config->pcsc_reader); 946 if (config->pcsc_pin) 947 fprintf(f, "pcsc_pin=%s\n", config->pcsc_pin); 948 if (config->driver_param) 949 fprintf(f, "driver_param=%s\n", config->driver_param); 950 if (config->dot11RSNAConfigPMKLifetime) 951 fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n", 952 config->dot11RSNAConfigPMKLifetime); 953 if (config->dot11RSNAConfigPMKReauthThreshold) 954 fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n", 955 config->dot11RSNAConfigPMKReauthThreshold); 956 if (config->dot11RSNAConfigSATimeout) 957 fprintf(f, "dot11RSNAConfigSATimeout=%d\n", 958 config->dot11RSNAConfigSATimeout); 959 if (config->update_config) 960 fprintf(f, "update_config=%d\n", config->update_config); 961 #ifdef CONFIG_WPS 962 if (!is_nil_uuid(config->uuid)) { 963 char buf[40]; 964 uuid_bin2str(config->uuid, buf, sizeof(buf)); 965 fprintf(f, "uuid=%s\n", buf); 966 } 967 if (config->device_name) 968 fprintf(f, "device_name=%s\n", config->device_name); 969 if (config->manufacturer) 970 fprintf(f, "manufacturer=%s\n", config->manufacturer); 971 if (config->model_name) 972 fprintf(f, "model_name=%s\n", config->model_name); 973 if (config->model_number) 974 fprintf(f, "model_number=%s\n", config->model_number); 975 if (config->serial_number) 976 fprintf(f, "serial_number=%s\n", config->serial_number); 977 { 978 char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; 979 buf = wps_dev_type_bin2str(config->device_type, 980 _buf, sizeof(_buf)); 981 if (os_strcmp(buf, "0-00000000-0") != 0) 982 fprintf(f, "device_type=%s\n", buf); 983 } 984 if (WPA_GET_BE32(config->os_version)) 985 fprintf(f, "os_version=%08x\n", 986 WPA_GET_BE32(config->os_version)); 987 if (config->config_methods) 988 fprintf(f, "config_methods=%s\n", config->config_methods); 989 if (config->wps_cred_processing) 990 fprintf(f, "wps_cred_processing=%d\n", 991 config->wps_cred_processing); 992 if (config->wps_vendor_ext_m1) { 993 int i, len = wpabuf_len(config->wps_vendor_ext_m1); 994 const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1); 995 if (len > 0) { 996 fprintf(f, "wps_vendor_ext_m1="); 997 for (i = 0; i < len; i++) 998 fprintf(f, "%02x", *p++); 999 fprintf(f, "\n"); 1000 } 1001 } 1002 #endif /* CONFIG_WPS */ 1003 #ifdef CONFIG_P2P 1004 if (config->p2p_listen_reg_class) 1005 fprintf(f, "p2p_listen_reg_class=%u\n", 1006 config->p2p_listen_reg_class); 1007 if (config->p2p_listen_channel) 1008 fprintf(f, "p2p_listen_channel=%u\n", 1009 config->p2p_listen_channel); 1010 if (config->p2p_oper_reg_class) 1011 fprintf(f, "p2p_oper_reg_class=%u\n", 1012 config->p2p_oper_reg_class); 1013 if (config->p2p_oper_channel) 1014 fprintf(f, "p2p_oper_channel=%u\n", config->p2p_oper_channel); 1015 if (config->p2p_go_intent != DEFAULT_P2P_GO_INTENT) 1016 fprintf(f, "p2p_go_intent=%u\n", config->p2p_go_intent); 1017 if (config->p2p_ssid_postfix) 1018 fprintf(f, "p2p_ssid_postfix=%s\n", config->p2p_ssid_postfix); 1019 if (config->persistent_reconnect) 1020 fprintf(f, "persistent_reconnect=%u\n", 1021 config->persistent_reconnect); 1022 if (config->p2p_intra_bss != DEFAULT_P2P_INTRA_BSS) 1023 fprintf(f, "p2p_intra_bss=%u\n", config->p2p_intra_bss); 1024 if (config->p2p_group_idle) 1025 fprintf(f, "p2p_group_idle=%u\n", config->p2p_group_idle); 1026 if (config->p2p_passphrase_len) 1027 fprintf(f, "p2p_passphrase_len=%u\n", 1028 config->p2p_passphrase_len); 1029 if (config->p2p_pref_chan) { 1030 unsigned int i; 1031 fprintf(f, "p2p_pref_chan="); 1032 for (i = 0; i < config->num_p2p_pref_chan; i++) { 1033 fprintf(f, "%s%u:%u", i > 0 ? "," : "", 1034 config->p2p_pref_chan[i].op_class, 1035 config->p2p_pref_chan[i].chan); 1036 } 1037 fprintf(f, "\n"); 1038 } 1039 if (config->p2p_no_go_freq.num) { 1040 char *val = freq_range_list_str(&config->p2p_no_go_freq); 1041 if (val) { 1042 fprintf(f, "p2p_no_go_freq=%s\n", val); 1043 os_free(val); 1044 } 1045 } 1046 if (config->p2p_add_cli_chan) 1047 fprintf(f, "p2p_add_cli_chan=%d\n", config->p2p_add_cli_chan); 1048 if (config->p2p_optimize_listen_chan != 1049 DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN) 1050 fprintf(f, "p2p_optimize_listen_chan=%d\n", 1051 config->p2p_optimize_listen_chan); 1052 if (config->p2p_go_ht40) 1053 fprintf(f, "p2p_go_ht40=%u\n", config->p2p_go_ht40); 1054 if (config->p2p_go_vht) 1055 fprintf(f, "p2p_go_vht=%u\n", config->p2p_go_vht); 1056 if (config->p2p_disabled) 1057 fprintf(f, "p2p_disabled=%u\n", config->p2p_disabled); 1058 if (config->p2p_no_group_iface) 1059 fprintf(f, "p2p_no_group_iface=%u\n", 1060 config->p2p_no_group_iface); 1061 if (config->p2p_ignore_shared_freq) 1062 fprintf(f, "p2p_ignore_shared_freq=%u\n", 1063 config->p2p_ignore_shared_freq); 1064 #endif /* CONFIG_P2P */ 1065 if (config->country[0] && config->country[1]) { 1066 fprintf(f, "country=%c%c\n", 1067 config->country[0], config->country[1]); 1068 } 1069 if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT) 1070 fprintf(f, "bss_max_count=%u\n", config->bss_max_count); 1071 if (config->bss_expiration_age != DEFAULT_BSS_EXPIRATION_AGE) 1072 fprintf(f, "bss_expiration_age=%u\n", 1073 config->bss_expiration_age); 1074 if (config->bss_expiration_scan_count != 1075 DEFAULT_BSS_EXPIRATION_SCAN_COUNT) 1076 fprintf(f, "bss_expiration_scan_count=%u\n", 1077 config->bss_expiration_scan_count); 1078 if (config->filter_ssids) 1079 fprintf(f, "filter_ssids=%d\n", config->filter_ssids); 1080 if (config->max_num_sta != DEFAULT_MAX_NUM_STA) 1081 fprintf(f, "max_num_sta=%u\n", config->max_num_sta); 1082 if (config->disassoc_low_ack) 1083 fprintf(f, "disassoc_low_ack=%u\n", config->disassoc_low_ack); 1084 #ifdef CONFIG_HS20 1085 if (config->hs20) 1086 fprintf(f, "hs20=1\n"); 1087 #endif /* CONFIG_HS20 */ 1088 #ifdef CONFIG_INTERWORKING 1089 if (config->interworking) 1090 fprintf(f, "interworking=%u\n", config->interworking); 1091 if (!is_zero_ether_addr(config->hessid)) 1092 fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid)); 1093 if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE) 1094 fprintf(f, "access_network_type=%d\n", 1095 config->access_network_type); 1096 #endif /* CONFIG_INTERWORKING */ 1097 if (config->pbc_in_m1) 1098 fprintf(f, "pbc_in_m1=%u\n", config->pbc_in_m1); 1099 if (config->wps_nfc_pw_from_config) { 1100 if (config->wps_nfc_dev_pw_id) 1101 fprintf(f, "wps_nfc_dev_pw_id=%d\n", 1102 config->wps_nfc_dev_pw_id); 1103 write_global_bin(f, "wps_nfc_dh_pubkey", 1104 config->wps_nfc_dh_pubkey); 1105 write_global_bin(f, "wps_nfc_dh_privkey", 1106 config->wps_nfc_dh_privkey); 1107 write_global_bin(f, "wps_nfc_dev_pw", config->wps_nfc_dev_pw); 1108 } 1109 1110 if (config->ext_password_backend) 1111 fprintf(f, "ext_password_backend=%s\n", 1112 config->ext_password_backend); 1113 if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY) 1114 fprintf(f, "p2p_go_max_inactivity=%d\n", 1115 config->p2p_go_max_inactivity); 1116 if (config->auto_interworking) 1117 fprintf(f, "auto_interworking=%d\n", 1118 config->auto_interworking); 1119 if (config->okc) 1120 fprintf(f, "okc=%d\n", config->okc); 1121 if (config->pmf) 1122 fprintf(f, "pmf=%d\n", config->pmf); 1123 if (config->dtim_period) 1124 fprintf(f, "dtim_period=%d\n", config->dtim_period); 1125 if (config->beacon_int) 1126 fprintf(f, "beacon_int=%d\n", config->beacon_int); 1127 1128 if (config->sae_groups) { 1129 int i; 1130 fprintf(f, "sae_groups="); 1131 for (i = 0; config->sae_groups[i] >= 0; i++) { 1132 fprintf(f, "%s%d", i > 0 ? " " : "", 1133 config->sae_groups[i]); 1134 } 1135 fprintf(f, "\n"); 1136 } 1137 1138 if (config->ap_vendor_elements) { 1139 int i, len = wpabuf_len(config->ap_vendor_elements); 1140 const u8 *p = wpabuf_head_u8(config->ap_vendor_elements); 1141 if (len > 0) { 1142 fprintf(f, "ap_vendor_elements="); 1143 for (i = 0; i < len; i++) 1144 fprintf(f, "%02x", *p++); 1145 fprintf(f, "\n"); 1146 } 1147 } 1148 1149 if (config->ignore_old_scan_res) 1150 fprintf(f, "ignore_old_scan_res=%d\n", 1151 config->ignore_old_scan_res); 1152 1153 if (config->freq_list && config->freq_list[0]) { 1154 int i; 1155 fprintf(f, "freq_list="); 1156 for (i = 0; config->freq_list[i]; i++) { 1157 fprintf(f, "%s%u", i > 0 ? " " : "", 1158 config->freq_list[i]); 1159 } 1160 fprintf(f, "\n"); 1161 } 1162 if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) 1163 fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); 1164 1165 if (config->sched_scan_interval) 1166 fprintf(f, "sched_scan_interval=%u\n", 1167 config->sched_scan_interval); 1168 1169 if (config->external_sim) 1170 fprintf(f, "external_sim=%d\n", config->external_sim); 1171 1172 if (config->tdls_external_control) 1173 fprintf(f, "tdls_external_control=%d\n", 1174 config->tdls_external_control); 1175 1176 if (config->wowlan_triggers) 1177 fprintf(f, "wowlan_triggers=%s\n", 1178 config->wowlan_triggers); 1179 1180 if (config->bgscan) 1181 fprintf(f, "bgscan=\"%s\"\n", config->bgscan); 1182 1183 if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY) 1184 fprintf(f, "p2p_search_delay=%u\n", 1185 config->p2p_search_delay); 1186 1187 if (config->mac_addr) 1188 fprintf(f, "mac_addr=%d\n", config->mac_addr); 1189 1190 if (config->rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME) 1191 fprintf(f, "rand_addr_lifetime=%u\n", 1192 config->rand_addr_lifetime); 1193 1194 if (config->preassoc_mac_addr) 1195 fprintf(f, "preassoc_mac_addr=%d\n", config->preassoc_mac_addr); 1196 } 1197 1198 #endif /* CONFIG_NO_CONFIG_WRITE */ 1199 1200 1201 int wpa_config_write(const char *name, struct wpa_config *config) 1202 { 1203 #ifndef CONFIG_NO_CONFIG_WRITE 1204 FILE *f; 1205 struct wpa_ssid *ssid; 1206 struct wpa_cred *cred; 1207 #ifndef CONFIG_NO_CONFIG_BLOBS 1208 struct wpa_config_blob *blob; 1209 #endif /* CONFIG_NO_CONFIG_BLOBS */ 1210 int ret = 0; 1211 int tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */ 1212 char *tmp_name = os_malloc(tmp_len); 1213 1214 if (tmp_name == NULL) 1215 tmp_name = (char *)name; 1216 else 1217 os_snprintf(tmp_name, tmp_len, "%s.tmp", name); 1218 1219 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", tmp_name); 1220 1221 f = fopen(tmp_name, "w"); 1222 if (f == NULL) { 1223 wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", tmp_name); 1224 if (tmp_name != name) 1225 os_free(tmp_name); 1226 return -1; 1227 } 1228 1229 wpa_config_write_global(f, config); 1230 1231 for (cred = config->cred; cred; cred = cred->next) { 1232 if (cred->temporary) 1233 continue; 1234 fprintf(f, "\ncred={\n"); 1235 wpa_config_write_cred(f, cred); 1236 fprintf(f, "}\n"); 1237 } 1238 1239 for (ssid = config->ssid; ssid; ssid = ssid->next) { 1240 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary) 1241 continue; /* do not save temporary networks */ 1242 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && 1243 !ssid->passphrase) 1244 continue; /* do not save invalid network */ 1245 fprintf(f, "\nnetwork={\n"); 1246 wpa_config_write_network(f, ssid); 1247 fprintf(f, "}\n"); 1248 } 1249 1250 #ifndef CONFIG_NO_CONFIG_BLOBS 1251 for (blob = config->blobs; blob; blob = blob->next) { 1252 ret = wpa_config_write_blob(f, blob); 1253 if (ret) 1254 break; 1255 } 1256 #endif /* CONFIG_NO_CONFIG_BLOBS */ 1257 1258 fclose(f); 1259 1260 if (tmp_name != name) { 1261 int chmod_ret = 0; 1262 #ifdef ANDROID 1263 chmod_ret = chmod(tmp_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 1264 #endif 1265 if (chmod_ret != 0 || rename(tmp_name, name) != 0) 1266 ret = -1; 1267 1268 os_free(tmp_name); 1269 } 1270 1271 wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", 1272 name, ret ? "un" : ""); 1273 return ret; 1274 #else /* CONFIG_NO_CONFIG_WRITE */ 1275 return -1; 1276 #endif /* CONFIG_NO_CONFIG_WRITE */ 1277 } 1278