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