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