config_file.c revision d30ac604c9f6da71a0dd7f46d25be05a2a62cfbb
1/* 2 * WPA Supplicant / Configuration backend: text file 3 * Copyright (c) 2003-2012, Jouni Malinen <j@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 24static 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 36static 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 */ 61static 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 123static 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 150static 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 211static 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 268static 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 324static 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 350struct 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 462static 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 472static 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 480static 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 490static 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 500static 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 516static 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 532static 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 548static 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 564static 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 581static 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 596static 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 614static 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 623static 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 633static 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 648static 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 743#undef STR 744#undef INT 745#undef INT_DEF 746} 747 748 749static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) 750{ 751 size_t i; 752 753 if (cred->priority) 754 fprintf(f, "\tpriority=%d\n", cred->priority); 755 if (cred->pcsc) 756 fprintf(f, "\tpcsc=%d\n", cred->pcsc); 757 if (cred->realm) 758 fprintf(f, "\trealm=\"%s\"\n", cred->realm); 759 if (cred->username) 760 fprintf(f, "\tusername=\"%s\"\n", cred->username); 761 if (cred->password && cred->ext_password) 762 fprintf(f, "\tpassword=ext:%s\n", cred->password); 763 else if (cred->password) 764 fprintf(f, "\tpassword=\"%s\"\n", cred->password); 765 if (cred->ca_cert) 766 fprintf(f, "\tca_cert=\"%s\"\n", cred->ca_cert); 767 if (cred->client_cert) 768 fprintf(f, "\tclient_cert=\"%s\"\n", cred->client_cert); 769 if (cred->private_key) 770 fprintf(f, "\tprivate_key=\"%s\"\n", cred->private_key); 771 if (cred->private_key_passwd) 772 fprintf(f, "\tprivate_key_passwd=\"%s\"\n", 773 cred->private_key_passwd); 774 if (cred->imsi) 775 fprintf(f, "\timsi=\"%s\"\n", cred->imsi); 776 if (cred->milenage) 777 fprintf(f, "\tmilenage=\"%s\"\n", cred->milenage); 778 for (i = 0; i < cred->num_domain; i++) 779 fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]); 780 if (cred->domain_suffix_match) 781 fprintf(f, "\tdomain_suffix_match=\"%s\"\n", 782 cred->domain_suffix_match); 783 if (cred->roaming_consortium_len) { 784 fprintf(f, "\troaming_consortium="); 785 for (i = 0; i < cred->roaming_consortium_len; i++) 786 fprintf(f, "%02x", cred->roaming_consortium[i]); 787 fprintf(f, "\n"); 788 } 789 if (cred->eap_method) { 790 const char *name; 791 name = eap_get_name(cred->eap_method[0].vendor, 792 cred->eap_method[0].method); 793 if (name) 794 fprintf(f, "\teap=%s\n", name); 795 } 796 if (cred->phase1) 797 fprintf(f, "\tphase1=\"%s\"\n", cred->phase1); 798 if (cred->phase2) 799 fprintf(f, "\tphase2=\"%s\"\n", cred->phase2); 800 if (cred->excluded_ssid) { 801 size_t j; 802 for (i = 0; i < cred->num_excluded_ssid; i++) { 803 struct excluded_ssid *e = &cred->excluded_ssid[i]; 804 fprintf(f, "\texcluded_ssid="); 805 for (j = 0; j < e->ssid_len; j++) 806 fprintf(f, "%02x", e->ssid[j]); 807 fprintf(f, "\n"); 808 } 809 } 810 if (cred->roaming_partner) { 811 for (i = 0; i < cred->num_roaming_partner; i++) { 812 struct roaming_partner *p = &cred->roaming_partner[i]; 813 fprintf(f, "\troaming_partner=\"%s,%d,%u,%s\"\n", 814 p->fqdn, p->exact_match, p->priority, 815 p->country); 816 } 817 } 818 if (cred->update_identifier) 819 fprintf(f, "\tupdate_identifier=%d\n", cred->update_identifier); 820 821 if (cred->provisioning_sp) 822 fprintf(f, "\tprovisioning_sp=\"%s\"\n", cred->provisioning_sp); 823 if (cred->sp_priority) 824 fprintf(f, "\tsp_priority=%d\n", cred->sp_priority); 825 826 if (cred->min_dl_bandwidth_home) 827 fprintf(f, "\tmin_dl_bandwidth_home=%u\n", 828 cred->min_dl_bandwidth_home); 829 if (cred->min_ul_bandwidth_home) 830 fprintf(f, "\tmin_ul_bandwidth_home=%u\n", 831 cred->min_ul_bandwidth_home); 832 if (cred->min_dl_bandwidth_roaming) 833 fprintf(f, "\tmin_dl_bandwidth_roaming=%u\n", 834 cred->min_dl_bandwidth_roaming); 835 if (cred->min_ul_bandwidth_roaming) 836 fprintf(f, "\tmin_ul_bandwidth_roaming=%u\n", 837 cred->min_ul_bandwidth_roaming); 838 839 if (cred->max_bss_load) 840 fprintf(f, "\tmax_bss_load=%u\n", 841 cred->max_bss_load); 842 843 if (cred->ocsp) 844 fprintf(f, "\tocsp=%d\n", cred->ocsp); 845 846 if (cred->num_req_conn_capab) { 847 for (i = 0; i < cred->num_req_conn_capab; i++) { 848 int *ports; 849 850 fprintf(f, "\treq_conn_capab=%u", 851 cred->req_conn_capab_proto[i]); 852 ports = cred->req_conn_capab_port[i]; 853 if (ports) { 854 int j; 855 for (j = 0; ports[j] != -1; j++) { 856 fprintf(f, "%s%d", j > 0 ? "," : ":", 857 ports[j]); 858 } 859 } 860 fprintf(f, "\n"); 861 } 862 } 863 864 if (cred->required_roaming_consortium_len) { 865 fprintf(f, "\trequired_roaming_consortium="); 866 for (i = 0; i < cred->required_roaming_consortium_len; i++) 867 fprintf(f, "%02x", 868 cred->required_roaming_consortium[i]); 869 fprintf(f, "\n"); 870 } 871 872 if (cred->sim_num != DEFAULT_USER_SELECTED_SIM) 873 fprintf(f, "\tsim_num=%d\n", cred->sim_num); 874} 875 876 877#ifndef CONFIG_NO_CONFIG_BLOBS 878static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) 879{ 880 unsigned char *encoded; 881 882 encoded = base64_encode(blob->data, blob->len, NULL); 883 if (encoded == NULL) 884 return -1; 885 886 fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded); 887 os_free(encoded); 888 return 0; 889} 890#endif /* CONFIG_NO_CONFIG_BLOBS */ 891 892 893static void write_global_bin(FILE *f, const char *field, 894 const struct wpabuf *val) 895{ 896 size_t i; 897 const u8 *pos; 898 899 if (val == NULL) 900 return; 901 902 fprintf(f, "%s=", field); 903 pos = wpabuf_head(val); 904 for (i = 0; i < wpabuf_len(val); i++) 905 fprintf(f, "%02X", *pos++); 906 fprintf(f, "\n"); 907} 908 909 910static void wpa_config_write_global(FILE *f, struct wpa_config *config) 911{ 912#ifdef CONFIG_CTRL_IFACE 913 if (config->ctrl_interface) 914 fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); 915 if (config->ctrl_interface_group) 916 fprintf(f, "ctrl_interface_group=%s\n", 917 config->ctrl_interface_group); 918#endif /* CONFIG_CTRL_IFACE */ 919 if (config->eapol_version != DEFAULT_EAPOL_VERSION) 920 fprintf(f, "eapol_version=%d\n", config->eapol_version); 921 if (config->ap_scan != DEFAULT_AP_SCAN) 922 fprintf(f, "ap_scan=%d\n", config->ap_scan); 923 if (config->disable_scan_offload) 924 fprintf(f, "disable_scan_offload=%d\n", 925 config->disable_scan_offload); 926 if (config->fast_reauth != DEFAULT_FAST_REAUTH) 927 fprintf(f, "fast_reauth=%d\n", config->fast_reauth); 928 if (config->opensc_engine_path) 929 fprintf(f, "opensc_engine_path=%s\n", 930 config->opensc_engine_path); 931 if (config->pkcs11_engine_path) 932 fprintf(f, "pkcs11_engine_path=%s\n", 933 config->pkcs11_engine_path); 934 if (config->pkcs11_module_path) 935 fprintf(f, "pkcs11_module_path=%s\n", 936 config->pkcs11_module_path); 937 if (config->pcsc_reader) 938 fprintf(f, "pcsc_reader=%s\n", config->pcsc_reader); 939 if (config->pcsc_pin) 940 fprintf(f, "pcsc_pin=%s\n", config->pcsc_pin); 941 if (config->driver_param) 942 fprintf(f, "driver_param=%s\n", config->driver_param); 943 if (config->dot11RSNAConfigPMKLifetime) 944 fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n", 945 config->dot11RSNAConfigPMKLifetime); 946 if (config->dot11RSNAConfigPMKReauthThreshold) 947 fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n", 948 config->dot11RSNAConfigPMKReauthThreshold); 949 if (config->dot11RSNAConfigSATimeout) 950 fprintf(f, "dot11RSNAConfigSATimeout=%d\n", 951 config->dot11RSNAConfigSATimeout); 952 if (config->update_config) 953 fprintf(f, "update_config=%d\n", config->update_config); 954#ifdef CONFIG_WPS 955 if (!is_nil_uuid(config->uuid)) { 956 char buf[40]; 957 uuid_bin2str(config->uuid, buf, sizeof(buf)); 958 fprintf(f, "uuid=%s\n", buf); 959 } 960 if (config->device_name) 961 fprintf(f, "device_name=%s\n", config->device_name); 962 if (config->manufacturer) 963 fprintf(f, "manufacturer=%s\n", config->manufacturer); 964 if (config->model_name) 965 fprintf(f, "model_name=%s\n", config->model_name); 966 if (config->model_number) 967 fprintf(f, "model_number=%s\n", config->model_number); 968 if (config->serial_number) 969 fprintf(f, "serial_number=%s\n", config->serial_number); 970 { 971 char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; 972 buf = wps_dev_type_bin2str(config->device_type, 973 _buf, sizeof(_buf)); 974 if (os_strcmp(buf, "0-00000000-0") != 0) 975 fprintf(f, "device_type=%s\n", buf); 976 } 977 if (WPA_GET_BE32(config->os_version)) 978 fprintf(f, "os_version=%08x\n", 979 WPA_GET_BE32(config->os_version)); 980 if (config->config_methods) 981 fprintf(f, "config_methods=%s\n", config->config_methods); 982 if (config->wps_cred_processing) 983 fprintf(f, "wps_cred_processing=%d\n", 984 config->wps_cred_processing); 985 if (config->wps_vendor_ext_m1) { 986 int i, len = wpabuf_len(config->wps_vendor_ext_m1); 987 const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1); 988 if (len > 0) { 989 fprintf(f, "wps_vendor_ext_m1="); 990 for (i = 0; i < len; i++) 991 fprintf(f, "%02x", *p++); 992 fprintf(f, "\n"); 993 } 994 } 995#endif /* CONFIG_WPS */ 996#ifdef CONFIG_P2P 997 if (config->p2p_listen_reg_class) 998 fprintf(f, "p2p_listen_reg_class=%u\n", 999 config->p2p_listen_reg_class); 1000 if (config->p2p_listen_channel) 1001 fprintf(f, "p2p_listen_channel=%u\n", 1002 config->p2p_listen_channel); 1003 if (config->p2p_oper_reg_class) 1004 fprintf(f, "p2p_oper_reg_class=%u\n", 1005 config->p2p_oper_reg_class); 1006 if (config->p2p_oper_channel) 1007 fprintf(f, "p2p_oper_channel=%u\n", config->p2p_oper_channel); 1008 if (config->p2p_go_intent != DEFAULT_P2P_GO_INTENT) 1009 fprintf(f, "p2p_go_intent=%u\n", config->p2p_go_intent); 1010 if (config->p2p_ssid_postfix) 1011 fprintf(f, "p2p_ssid_postfix=%s\n", config->p2p_ssid_postfix); 1012 if (config->persistent_reconnect) 1013 fprintf(f, "persistent_reconnect=%u\n", 1014 config->persistent_reconnect); 1015 if (config->p2p_intra_bss != DEFAULT_P2P_INTRA_BSS) 1016 fprintf(f, "p2p_intra_bss=%u\n", config->p2p_intra_bss); 1017 if (config->p2p_group_idle) 1018 fprintf(f, "p2p_group_idle=%u\n", config->p2p_group_idle); 1019 if (config->p2p_passphrase_len) 1020 fprintf(f, "p2p_passphrase_len=%u\n", 1021 config->p2p_passphrase_len); 1022 if (config->p2p_pref_chan) { 1023 unsigned int i; 1024 fprintf(f, "p2p_pref_chan="); 1025 for (i = 0; i < config->num_p2p_pref_chan; i++) { 1026 fprintf(f, "%s%u:%u", i > 0 ? "," : "", 1027 config->p2p_pref_chan[i].op_class, 1028 config->p2p_pref_chan[i].chan); 1029 } 1030 fprintf(f, "\n"); 1031 } 1032 if (config->p2p_no_go_freq.num) { 1033 char *val = freq_range_list_str(&config->p2p_no_go_freq); 1034 if (val) { 1035 fprintf(f, "p2p_no_go_freq=%s\n", val); 1036 os_free(val); 1037 } 1038 } 1039 if (config->p2p_add_cli_chan) 1040 fprintf(f, "p2p_add_cli_chan=%d\n", config->p2p_add_cli_chan); 1041 if (config->p2p_optimize_listen_chan != 1042 DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN) 1043 fprintf(f, "p2p_optimize_listen_chan=%d\n", 1044 config->p2p_optimize_listen_chan); 1045 if (config->p2p_go_ht40) 1046 fprintf(f, "p2p_go_ht40=%u\n", config->p2p_go_ht40); 1047 if (config->p2p_go_vht) 1048 fprintf(f, "p2p_go_vht=%u\n", config->p2p_go_vht); 1049 if (config->p2p_disabled) 1050 fprintf(f, "p2p_disabled=%u\n", config->p2p_disabled); 1051 if (config->p2p_no_group_iface) 1052 fprintf(f, "p2p_no_group_iface=%u\n", 1053 config->p2p_no_group_iface); 1054 if (config->p2p_ignore_shared_freq) 1055 fprintf(f, "p2p_ignore_shared_freq=%u\n", 1056 config->p2p_ignore_shared_freq); 1057#endif /* CONFIG_P2P */ 1058 if (config->country[0] && config->country[1]) { 1059 fprintf(f, "country=%c%c\n", 1060 config->country[0], config->country[1]); 1061 } 1062 if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT) 1063 fprintf(f, "bss_max_count=%u\n", config->bss_max_count); 1064 if (config->bss_expiration_age != DEFAULT_BSS_EXPIRATION_AGE) 1065 fprintf(f, "bss_expiration_age=%u\n", 1066 config->bss_expiration_age); 1067 if (config->bss_expiration_scan_count != 1068 DEFAULT_BSS_EXPIRATION_SCAN_COUNT) 1069 fprintf(f, "bss_expiration_scan_count=%u\n", 1070 config->bss_expiration_scan_count); 1071 if (config->filter_ssids) 1072 fprintf(f, "filter_ssids=%d\n", config->filter_ssids); 1073 if (config->max_num_sta != DEFAULT_MAX_NUM_STA) 1074 fprintf(f, "max_num_sta=%u\n", config->max_num_sta); 1075 if (config->disassoc_low_ack) 1076 fprintf(f, "disassoc_low_ack=%u\n", config->disassoc_low_ack); 1077#ifdef CONFIG_HS20 1078 if (config->hs20) 1079 fprintf(f, "hs20=1\n"); 1080#endif /* CONFIG_HS20 */ 1081#ifdef CONFIG_INTERWORKING 1082 if (config->interworking) 1083 fprintf(f, "interworking=%u\n", config->interworking); 1084 if (!is_zero_ether_addr(config->hessid)) 1085 fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid)); 1086 if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE) 1087 fprintf(f, "access_network_type=%d\n", 1088 config->access_network_type); 1089#endif /* CONFIG_INTERWORKING */ 1090 if (config->pbc_in_m1) 1091 fprintf(f, "pbc_in_m1=%u\n", config->pbc_in_m1); 1092 if (config->wps_nfc_pw_from_config) { 1093 if (config->wps_nfc_dev_pw_id) 1094 fprintf(f, "wps_nfc_dev_pw_id=%d\n", 1095 config->wps_nfc_dev_pw_id); 1096 write_global_bin(f, "wps_nfc_dh_pubkey", 1097 config->wps_nfc_dh_pubkey); 1098 write_global_bin(f, "wps_nfc_dh_privkey", 1099 config->wps_nfc_dh_privkey); 1100 write_global_bin(f, "wps_nfc_dev_pw", config->wps_nfc_dev_pw); 1101 } 1102 1103 if (config->ext_password_backend) 1104 fprintf(f, "ext_password_backend=%s\n", 1105 config->ext_password_backend); 1106 if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY) 1107 fprintf(f, "p2p_go_max_inactivity=%d\n", 1108 config->p2p_go_max_inactivity); 1109 if (config->auto_interworking) 1110 fprintf(f, "auto_interworking=%d\n", 1111 config->auto_interworking); 1112 if (config->okc) 1113 fprintf(f, "okc=%d\n", config->okc); 1114 if (config->pmf) 1115 fprintf(f, "pmf=%d\n", config->pmf); 1116 if (config->dtim_period) 1117 fprintf(f, "dtim_period=%d\n", config->dtim_period); 1118 if (config->beacon_int) 1119 fprintf(f, "beacon_int=%d\n", config->beacon_int); 1120 1121 if (config->sae_groups) { 1122 int i; 1123 fprintf(f, "sae_groups="); 1124 for (i = 0; config->sae_groups[i] >= 0; i++) { 1125 fprintf(f, "%s%d", i > 0 ? " " : "", 1126 config->sae_groups[i]); 1127 } 1128 fprintf(f, "\n"); 1129 } 1130 1131 if (config->ap_vendor_elements) { 1132 int i, len = wpabuf_len(config->ap_vendor_elements); 1133 const u8 *p = wpabuf_head_u8(config->ap_vendor_elements); 1134 if (len > 0) { 1135 fprintf(f, "ap_vendor_elements="); 1136 for (i = 0; i < len; i++) 1137 fprintf(f, "%02x", *p++); 1138 fprintf(f, "\n"); 1139 } 1140 } 1141 1142 if (config->ignore_old_scan_res) 1143 fprintf(f, "ignore_old_scan_res=%d\n", 1144 config->ignore_old_scan_res); 1145 1146 if (config->freq_list && config->freq_list[0]) { 1147 int i; 1148 fprintf(f, "freq_list="); 1149 for (i = 0; config->freq_list[i]; i++) { 1150 fprintf(f, "%s%u", i > 0 ? " " : "", 1151 config->freq_list[i]); 1152 } 1153 fprintf(f, "\n"); 1154 } 1155 if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) 1156 fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); 1157 1158 if (config->sched_scan_interval) 1159 fprintf(f, "sched_scan_interval=%u\n", 1160 config->sched_scan_interval); 1161 1162 if (config->external_sim) 1163 fprintf(f, "external_sim=%d\n", config->external_sim); 1164 1165 if (config->tdls_external_control) 1166 fprintf(f, "tdls_external_control=%d\n", 1167 config->tdls_external_control); 1168 1169 if (config->wowlan_triggers) 1170 fprintf(f, "wowlan_triggers=\"%s\"\n", 1171 config->wowlan_triggers); 1172 1173 if (config->bgscan) 1174 fprintf(f, "bgscan=\"%s\"\n", config->bgscan); 1175 1176 if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY) 1177 fprintf(f, "p2p_search_delay=%u\n", 1178 config->p2p_search_delay); 1179} 1180 1181#endif /* CONFIG_NO_CONFIG_WRITE */ 1182 1183 1184int wpa_config_write(const char *name, struct wpa_config *config) 1185{ 1186#ifndef CONFIG_NO_CONFIG_WRITE 1187 FILE *f; 1188 struct wpa_ssid *ssid; 1189 struct wpa_cred *cred; 1190#ifndef CONFIG_NO_CONFIG_BLOBS 1191 struct wpa_config_blob *blob; 1192#endif /* CONFIG_NO_CONFIG_BLOBS */ 1193 int ret = 0; 1194 1195 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 1196 1197 f = fopen(name, "w"); 1198 if (f == NULL) { 1199 wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name); 1200 return -1; 1201 } 1202 1203 wpa_config_write_global(f, config); 1204 1205 for (cred = config->cred; cred; cred = cred->next) { 1206 if (cred->temporary) 1207 continue; 1208 fprintf(f, "\ncred={\n"); 1209 wpa_config_write_cred(f, cred); 1210 fprintf(f, "}\n"); 1211 } 1212 1213 for (ssid = config->ssid; ssid; ssid = ssid->next) { 1214 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary) 1215 continue; /* do not save temporary networks */ 1216 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && 1217 !ssid->passphrase) 1218 continue; /* do not save invalid network */ 1219 fprintf(f, "\nnetwork={\n"); 1220 wpa_config_write_network(f, ssid); 1221 fprintf(f, "}\n"); 1222 } 1223 1224#ifndef CONFIG_NO_CONFIG_BLOBS 1225 for (blob = config->blobs; blob; blob = blob->next) { 1226 ret = wpa_config_write_blob(f, blob); 1227 if (ret) 1228 break; 1229 } 1230#endif /* CONFIG_NO_CONFIG_BLOBS */ 1231 1232 fclose(f); 1233 1234 wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", 1235 name, ret ? "un" : ""); 1236 return ret; 1237#else /* CONFIG_NO_CONFIG_WRITE */ 1238 return -1; 1239#endif /* CONFIG_NO_CONFIG_WRITE */ 1240} 1241