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