1/* 2 * WPA Supplicant / Configuration backend: Windows registry 3 * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 * 14 * This file implements a configuration backend for Windows registry.. All the 15 * configuration information is stored in the registry and the format for 16 * network configuration fields is same as described in the sample 17 * configuration file, wpa_supplicant.conf. 18 * 19 * Configuration data is in HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs 20 * key. Each configuration profile has its own key under this. In terms of text 21 * files, each profile would map to a separate text file with possibly multiple 22 * networks. Under each profile, there is a networks key that lists all 23 * networks as a subkey. Each network has set of values in the same way as 24 * network block in the configuration file. In addition, blobs subkey has 25 * possible blobs as values. 26 * 27 * HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs\test\networks\0000 28 * ssid="example" 29 * key_mgmt=WPA-PSK 30 */ 31 32#include "includes.h" 33 34#include "common.h" 35#include "config.h" 36 37#ifndef WPA_KEY_ROOT 38#define WPA_KEY_ROOT HKEY_LOCAL_MACHINE 39#endif 40#ifndef WPA_KEY_PREFIX 41#define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant") 42#endif 43 44#ifdef UNICODE 45#define TSTR "%S" 46#else /* UNICODE */ 47#define TSTR "%s" 48#endif /* UNICODE */ 49 50 51static int wpa_config_read_blobs(struct wpa_config *config, HKEY hk) 52{ 53 struct wpa_config_blob *blob; 54 int errors = 0; 55 HKEY bhk; 56 LONG ret; 57 DWORD i; 58 59 ret = RegOpenKeyEx(hk, TEXT("blobs"), 0, KEY_QUERY_VALUE, &bhk); 60 if (ret != ERROR_SUCCESS) { 61 wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config " 62 "blobs key"); 63 return 0; /* assume no blobs */ 64 } 65 66 for (i = 0; ; i++) { 67#define TNAMELEN 255 68 TCHAR name[TNAMELEN]; 69 char data[4096]; 70 DWORD namelen, datalen, type; 71 72 namelen = TNAMELEN; 73 datalen = sizeof(data); 74 ret = RegEnumValue(bhk, i, name, &namelen, NULL, &type, 75 (LPBYTE) data, &datalen); 76 77 if (ret == ERROR_NO_MORE_ITEMS) 78 break; 79 80 if (ret != ERROR_SUCCESS) { 81 wpa_printf(MSG_DEBUG, "RegEnumValue failed: 0x%x", 82 (unsigned int) ret); 83 break; 84 } 85 86 if (namelen >= TNAMELEN) 87 namelen = TNAMELEN - 1; 88 name[namelen] = TEXT('\0'); 89 wpa_unicode2ascii_inplace(name); 90 91 if (datalen >= sizeof(data)) 92 datalen = sizeof(data) - 1; 93 94 wpa_printf(MSG_MSGDUMP, "blob %d: field='%s' len %d", 95 (int) i, name, (int) datalen); 96 97 blob = os_zalloc(sizeof(*blob)); 98 if (blob == NULL) { 99 errors++; 100 break; 101 } 102 blob->name = os_strdup((char *) name); 103 blob->data = os_malloc(datalen); 104 if (blob->name == NULL || blob->data == NULL) { 105 wpa_config_free_blob(blob); 106 errors++; 107 break; 108 } 109 os_memcpy(blob->data, data, datalen); 110 blob->len = datalen; 111 112 wpa_config_set_blob(config, blob); 113 } 114 115 RegCloseKey(bhk); 116 117 return errors ? -1 : 0; 118} 119 120 121static int wpa_config_read_reg_dword(HKEY hk, const TCHAR *name, int *_val) 122{ 123 DWORD val, buflen; 124 LONG ret; 125 126 buflen = sizeof(val); 127 ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) &val, &buflen); 128 if (ret == ERROR_SUCCESS && buflen == sizeof(val)) { 129 wpa_printf(MSG_DEBUG, TSTR "=%d", name, (int) val); 130 *_val = val; 131 return 0; 132 } 133 134 return -1; 135} 136 137 138static char * wpa_config_read_reg_string(HKEY hk, const TCHAR *name) 139{ 140 DWORD buflen; 141 LONG ret; 142 TCHAR *val; 143 144 buflen = 0; 145 ret = RegQueryValueEx(hk, name, NULL, NULL, NULL, &buflen); 146 if (ret != ERROR_SUCCESS) 147 return NULL; 148 val = os_malloc(buflen); 149 if (val == NULL) 150 return NULL; 151 152 ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) val, &buflen); 153 if (ret != ERROR_SUCCESS) { 154 os_free(val); 155 return NULL; 156 } 157 158 wpa_unicode2ascii_inplace(val); 159 wpa_printf(MSG_DEBUG, TSTR "=%s", name, (char *) val); 160 return (char *) val; 161} 162 163 164static int wpa_config_read_global(struct wpa_config *config, HKEY hk) 165{ 166 int errors = 0; 167 168 wpa_config_read_reg_dword(hk, TEXT("ap_scan"), &config->ap_scan); 169 wpa_config_read_reg_dword(hk, TEXT("fast_reauth"), 170 &config->fast_reauth); 171 wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"), 172 &config->dot11RSNAConfigPMKLifetime); 173 wpa_config_read_reg_dword(hk, 174 TEXT("dot11RSNAConfigPMKReauthThreshold"), 175 &config->dot11RSNAConfigPMKReauthThreshold); 176 wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"), 177 &config->dot11RSNAConfigSATimeout); 178 wpa_config_read_reg_dword(hk, TEXT("update_config"), 179 &config->update_config); 180 181 if (wpa_config_read_reg_dword(hk, TEXT("eapol_version"), 182 &config->eapol_version) == 0) { 183 if (config->eapol_version < 1 || 184 config->eapol_version > 2) { 185 wpa_printf(MSG_ERROR, "Invalid EAPOL version (%d)", 186 config->eapol_version); 187 errors++; 188 } 189 } 190 191 config->ctrl_interface = wpa_config_read_reg_string( 192 hk, TEXT("ctrl_interface")); 193 194 return errors ? -1 : 0; 195} 196 197 198static struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw, 199 int id) 200{ 201 HKEY nhk; 202 LONG ret; 203 DWORD i; 204 struct wpa_ssid *ssid; 205 int errors = 0; 206 207 ret = RegOpenKeyEx(hk, netw, 0, KEY_QUERY_VALUE, &nhk); 208 if (ret != ERROR_SUCCESS) { 209 wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config " 210 "network '" TSTR "'", netw); 211 return NULL; 212 } 213 214 wpa_printf(MSG_MSGDUMP, "Start of a new network '" TSTR "'", netw); 215 ssid = os_zalloc(sizeof(*ssid)); 216 if (ssid == NULL) { 217 RegCloseKey(nhk); 218 return NULL; 219 } 220 ssid->id = id; 221 222 wpa_config_set_network_defaults(ssid); 223 224 for (i = 0; ; i++) { 225 TCHAR name[255], data[1024]; 226 DWORD namelen, datalen, type; 227 228 namelen = 255; 229 datalen = sizeof(data); 230 ret = RegEnumValue(nhk, i, name, &namelen, NULL, &type, 231 (LPBYTE) data, &datalen); 232 233 if (ret == ERROR_NO_MORE_ITEMS) 234 break; 235 236 if (ret != ERROR_SUCCESS) { 237 wpa_printf(MSG_ERROR, "RegEnumValue failed: 0x%x", 238 (unsigned int) ret); 239 break; 240 } 241 242 if (namelen >= 255) 243 namelen = 255 - 1; 244 name[namelen] = TEXT('\0'); 245 246 if (datalen >= 1024) 247 datalen = 1024 - 1; 248 data[datalen] = TEXT('\0'); 249 250 wpa_unicode2ascii_inplace(name); 251 wpa_unicode2ascii_inplace(data); 252 if (wpa_config_set(ssid, (char *) name, (char *) data, 0) < 0) 253 errors++; 254 } 255 256 RegCloseKey(nhk); 257 258 if (ssid->passphrase) { 259 if (ssid->psk_set) { 260 wpa_printf(MSG_ERROR, "Both PSK and passphrase " 261 "configured for network '" TSTR "'.", netw); 262 errors++; 263 } 264 wpa_config_update_psk(ssid); 265 } 266 267 if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) { 268 wpa_printf(MSG_ERROR, "WPA-PSK accepted for key management, " 269 "but no PSK configured for network '" TSTR "'.", 270 netw); 271 errors++; 272 } 273 274 if ((ssid->group_cipher & WPA_CIPHER_CCMP) && 275 !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && 276 !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { 277 /* Group cipher cannot be stronger than the pairwise cipher. */ 278 wpa_printf(MSG_DEBUG, "Removed CCMP from group cipher " 279 "list since it was not allowed for pairwise " 280 "cipher for network '" TSTR "'.", netw); 281 ssid->group_cipher &= ~WPA_CIPHER_CCMP; 282 } 283 284 if (errors) { 285 wpa_config_free_ssid(ssid); 286 ssid = NULL; 287 } 288 289 return ssid; 290} 291 292 293static int wpa_config_read_networks(struct wpa_config *config, HKEY hk) 294{ 295 HKEY nhk; 296 struct wpa_ssid *ssid, *tail = NULL, *head = NULL; 297 int errors = 0; 298 LONG ret; 299 DWORD i; 300 301 ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_ENUMERATE_SUB_KEYS, 302 &nhk); 303 if (ret != ERROR_SUCCESS) { 304 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant networks " 305 "registry key"); 306 return -1; 307 } 308 309 for (i = 0; ; i++) { 310 TCHAR name[255]; 311 DWORD namelen; 312 313 namelen = 255; 314 ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL, 315 NULL); 316 317 if (ret == ERROR_NO_MORE_ITEMS) 318 break; 319 320 if (ret != ERROR_SUCCESS) { 321 wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x", 322 (unsigned int) ret); 323 break; 324 } 325 326 if (namelen >= 255) 327 namelen = 255 - 1; 328 name[namelen] = '\0'; 329 330 ssid = wpa_config_read_network(nhk, name, i); 331 if (ssid == NULL) { 332 wpa_printf(MSG_ERROR, "Failed to parse network " 333 "profile '%s'.", name); 334 errors++; 335 continue; 336 } 337 if (head == NULL) { 338 head = tail = ssid; 339 } else { 340 tail->next = ssid; 341 tail = ssid; 342 } 343 if (wpa_config_add_prio_network(config, ssid)) { 344 wpa_printf(MSG_ERROR, "Failed to add network profile " 345 "'%s' to priority list.", name); 346 errors++; 347 continue; 348 } 349 } 350 351 RegCloseKey(nhk); 352 353 config->ssid = head; 354 355 return errors ? -1 : 0; 356} 357 358 359struct wpa_config * wpa_config_read(const char *name) 360{ 361 TCHAR buf[256]; 362 int errors = 0; 363 struct wpa_config *config; 364 HKEY hk; 365 LONG ret; 366 367 config = wpa_config_alloc_empty(NULL, NULL); 368 if (config == NULL) 369 return NULL; 370 wpa_printf(MSG_DEBUG, "Reading configuration profile '%s'", name); 371 372#ifdef UNICODE 373 _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name); 374#else /* UNICODE */ 375 os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name); 376#endif /* UNICODE */ 377 378 ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_QUERY_VALUE, &hk); 379 if (ret != ERROR_SUCCESS) { 380 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant " 381 "configuration registry HKLM\\" TSTR, buf); 382 os_free(config); 383 return NULL; 384 } 385 386 if (wpa_config_read_global(config, hk)) 387 errors++; 388 389 if (wpa_config_read_networks(config, hk)) 390 errors++; 391 392 if (wpa_config_read_blobs(config, hk)) 393 errors++; 394 395 wpa_config_debug_dump_networks(config); 396 397 RegCloseKey(hk); 398 399 if (errors) { 400 wpa_config_free(config); 401 config = NULL; 402 } 403 404 return config; 405} 406 407 408static int wpa_config_write_reg_dword(HKEY hk, const TCHAR *name, int val, 409 int def) 410{ 411 LONG ret; 412 DWORD _val = val; 413 414 if (val == def) { 415 RegDeleteValue(hk, name); 416 return 0; 417 } 418 419 ret = RegSetValueEx(hk, name, 0, REG_DWORD, (LPBYTE) &_val, 420 sizeof(_val)); 421 if (ret != ERROR_SUCCESS) { 422 wpa_printf(MSG_ERROR, "WINREG: Failed to set %s=%d: error %d", 423 name, val, (int) GetLastError()); 424 return -1; 425 } 426 427 return 0; 428} 429 430 431static int wpa_config_write_reg_string(HKEY hk, const char *name, 432 const char *val) 433{ 434 LONG ret; 435 TCHAR *_name, *_val; 436 437 _name = wpa_strdup_tchar(name); 438 if (_name == NULL) 439 return -1; 440 441 if (val == NULL) { 442 RegDeleteValue(hk, _name); 443 os_free(_name); 444 return 0; 445 } 446 447 _val = wpa_strdup_tchar(val); 448 if (_val == NULL) { 449 os_free(_name); 450 return -1; 451 } 452 ret = RegSetValueEx(hk, _name, 0, REG_SZ, (BYTE *) _val, 453 (os_strlen(val) + 1) * sizeof(TCHAR)); 454 if (ret != ERROR_SUCCESS) { 455 wpa_printf(MSG_ERROR, "WINREG: Failed to set %s='%s': " 456 "error %d", name, val, (int) GetLastError()); 457 os_free(_name); 458 os_free(_val); 459 return -1; 460 } 461 462 os_free(_name); 463 os_free(_val); 464 return 0; 465} 466 467 468static int wpa_config_write_global(struct wpa_config *config, HKEY hk) 469{ 470#ifdef CONFIG_CTRL_IFACE 471 wpa_config_write_reg_string(hk, "ctrl_interface", 472 config->ctrl_interface); 473#endif /* CONFIG_CTRL_IFACE */ 474 475 wpa_config_write_reg_dword(hk, TEXT("eapol_version"), 476 config->eapol_version, 477 DEFAULT_EAPOL_VERSION); 478 wpa_config_write_reg_dword(hk, TEXT("ap_scan"), config->ap_scan, 479 DEFAULT_AP_SCAN); 480 wpa_config_write_reg_dword(hk, TEXT("fast_reauth"), 481 config->fast_reauth, DEFAULT_FAST_REAUTH); 482 wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"), 483 config->dot11RSNAConfigPMKLifetime, 0); 484 wpa_config_write_reg_dword(hk, 485 TEXT("dot11RSNAConfigPMKReauthThreshold"), 486 config->dot11RSNAConfigPMKReauthThreshold, 487 0); 488 wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"), 489 config->dot11RSNAConfigSATimeout, 0); 490 wpa_config_write_reg_dword(hk, TEXT("update_config"), 491 config->update_config, 492 0); 493 494 return 0; 495} 496 497 498static int wpa_config_delete_subkeys(HKEY hk, const TCHAR *key) 499{ 500 HKEY nhk; 501 int i, errors = 0; 502 LONG ret; 503 504 ret = RegOpenKeyEx(hk, key, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &nhk); 505 if (ret != ERROR_SUCCESS) { 506 wpa_printf(MSG_DEBUG, "WINREG: Could not open key '" TSTR 507 "' for subkey deletion: error 0x%x (%d)", key, 508 (unsigned int) ret, (int) GetLastError()); 509 return 0; 510 } 511 512 for (i = 0; ; i++) { 513 TCHAR name[255]; 514 DWORD namelen; 515 516 namelen = 255; 517 ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL, 518 NULL); 519 520 if (ret == ERROR_NO_MORE_ITEMS) 521 break; 522 523 if (ret != ERROR_SUCCESS) { 524 wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x (%d)", 525 (unsigned int) ret, (int) GetLastError()); 526 break; 527 } 528 529 if (namelen >= 255) 530 namelen = 255 - 1; 531 name[namelen] = TEXT('\0'); 532 533 ret = RegDeleteKey(nhk, name); 534 if (ret != ERROR_SUCCESS) { 535 wpa_printf(MSG_DEBUG, "RegDeleteKey failed: 0x%x (%d)", 536 (unsigned int) ret, (int) GetLastError()); 537 errors++; 538 } 539 } 540 541 RegCloseKey(nhk); 542 543 return errors ? -1 : 0; 544} 545 546 547static void write_str(HKEY hk, const char *field, struct wpa_ssid *ssid) 548{ 549 char *value = wpa_config_get(ssid, field); 550 if (value == NULL) 551 return; 552 wpa_config_write_reg_string(hk, field, value); 553 os_free(value); 554} 555 556 557static void write_int(HKEY hk, const char *field, int value, int def) 558{ 559 char val[20]; 560 if (value == def) 561 return; 562 os_snprintf(val, sizeof(val), "%d", value); 563 wpa_config_write_reg_string(hk, field, val); 564} 565 566 567static void write_bssid(HKEY hk, struct wpa_ssid *ssid) 568{ 569 char *value = wpa_config_get(ssid, "bssid"); 570 if (value == NULL) 571 return; 572 wpa_config_write_reg_string(hk, "bssid", value); 573 os_free(value); 574} 575 576 577static void write_psk(HKEY hk, struct wpa_ssid *ssid) 578{ 579 char *value = wpa_config_get(ssid, "psk"); 580 if (value == NULL) 581 return; 582 wpa_config_write_reg_string(hk, "psk", value); 583 os_free(value); 584} 585 586 587static void write_proto(HKEY hk, struct wpa_ssid *ssid) 588{ 589 char *value; 590 591 if (ssid->proto == DEFAULT_PROTO) 592 return; 593 594 value = wpa_config_get(ssid, "proto"); 595 if (value == NULL) 596 return; 597 if (value[0]) 598 wpa_config_write_reg_string(hk, "proto", value); 599 os_free(value); 600} 601 602 603static void write_key_mgmt(HKEY hk, struct wpa_ssid *ssid) 604{ 605 char *value; 606 607 if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 608 return; 609 610 value = wpa_config_get(ssid, "key_mgmt"); 611 if (value == NULL) 612 return; 613 if (value[0]) 614 wpa_config_write_reg_string(hk, "key_mgmt", value); 615 os_free(value); 616} 617 618 619static void write_pairwise(HKEY hk, struct wpa_ssid *ssid) 620{ 621 char *value; 622 623 if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 624 return; 625 626 value = wpa_config_get(ssid, "pairwise"); 627 if (value == NULL) 628 return; 629 if (value[0]) 630 wpa_config_write_reg_string(hk, "pairwise", value); 631 os_free(value); 632} 633 634 635static void write_group(HKEY hk, struct wpa_ssid *ssid) 636{ 637 char *value; 638 639 if (ssid->group_cipher == DEFAULT_GROUP) 640 return; 641 642 value = wpa_config_get(ssid, "group"); 643 if (value == NULL) 644 return; 645 if (value[0]) 646 wpa_config_write_reg_string(hk, "group", value); 647 os_free(value); 648} 649 650 651static void write_auth_alg(HKEY hk, struct wpa_ssid *ssid) 652{ 653 char *value; 654 655 if (ssid->auth_alg == 0) 656 return; 657 658 value = wpa_config_get(ssid, "auth_alg"); 659 if (value == NULL) 660 return; 661 if (value[0]) 662 wpa_config_write_reg_string(hk, "auth_alg", value); 663 os_free(value); 664} 665 666 667#ifdef IEEE8021X_EAPOL 668static void write_eap(HKEY hk, struct wpa_ssid *ssid) 669{ 670 char *value; 671 672 value = wpa_config_get(ssid, "eap"); 673 if (value == NULL) 674 return; 675 676 if (value[0]) 677 wpa_config_write_reg_string(hk, "eap", value); 678 os_free(value); 679} 680#endif /* IEEE8021X_EAPOL */ 681 682 683static void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid) 684{ 685 char field[20], *value; 686 687 os_snprintf(field, sizeof(field), "wep_key%d", idx); 688 value = wpa_config_get(ssid, field); 689 if (value) { 690 wpa_config_write_reg_string(hk, field, value); 691 os_free(value); 692 } 693} 694 695 696static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id) 697{ 698 int i, errors = 0; 699 HKEY nhk, netw; 700 LONG ret; 701 TCHAR name[5]; 702 703 ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_CREATE_SUB_KEY, &nhk); 704 if (ret != ERROR_SUCCESS) { 705 wpa_printf(MSG_DEBUG, "WINREG: Could not open networks key " 706 "for subkey addition: error 0x%x (%d)", 707 (unsigned int) ret, (int) GetLastError()); 708 return 0; 709 } 710 711#ifdef UNICODE 712 wsprintf(name, L"%04d", id); 713#else /* UNICODE */ 714 os_snprintf(name, sizeof(name), "%04d", id); 715#endif /* UNICODE */ 716 ret = RegCreateKeyEx(nhk, name, 0, NULL, 0, KEY_WRITE, NULL, &netw, 717 NULL); 718 RegCloseKey(nhk); 719 if (ret != ERROR_SUCCESS) { 720 wpa_printf(MSG_DEBUG, "WINREG: Could not add network key '%s':" 721 " error 0x%x (%d)", 722 name, (unsigned int) ret, (int) GetLastError()); 723 return -1; 724 } 725 726#define STR(t) write_str(netw, #t, ssid) 727#define INT(t) write_int(netw, #t, ssid->t, 0) 728#define INT_DEF(t, def) write_int(netw, #t, ssid->t, def) 729 730 STR(ssid); 731 INT(scan_ssid); 732 write_bssid(netw, ssid); 733 write_psk(netw, ssid); 734 write_proto(netw, ssid); 735 write_key_mgmt(netw, ssid); 736 write_pairwise(netw, ssid); 737 write_group(netw, ssid); 738 write_auth_alg(netw, ssid); 739#ifdef IEEE8021X_EAPOL 740 write_eap(netw, ssid); 741 STR(identity); 742 STR(anonymous_identity); 743 STR(eappsk); 744 STR(nai); 745 STR(password); 746 STR(ca_cert); 747 STR(ca_path); 748 STR(client_cert); 749 STR(private_key); 750 STR(private_key_passwd); 751 STR(dh_file); 752 STR(subject_match); 753 STR(altsubject_match); 754 STR(ca_cert2); 755 STR(ca_path2); 756 STR(client_cert2); 757 STR(private_key2); 758 STR(private_key2_passwd); 759 STR(dh_file2); 760 STR(subject_match2); 761 STR(altsubject_match2); 762 STR(phase1); 763 STR(phase2); 764 STR(pcsc); 765 STR(pin); 766 STR(engine_id); 767 STR(key_id); 768 INT(engine); 769 INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 770#endif /* IEEE8021X_EAPOL */ 771 for (i = 0; i < 4; i++) 772 write_wep_key(netw, i, ssid); 773 INT(wep_tx_keyidx); 774 INT(priority); 775#ifdef IEEE8021X_EAPOL 776 INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 777 STR(pac_file); 778 INT_DEF(fragment_size, DEFAULT_FRAGMENT_SIZE); 779#endif /* IEEE8021X_EAPOL */ 780 INT(mode); 781 INT(proactive_key_caching); 782 INT(disabled); 783 INT(peerkey); 784#ifdef CONFIG_IEEE80211W 785 INT(ieee80211w); 786#endif /* CONFIG_IEEE80211W */ 787 STR(id_str); 788 789#undef STR 790#undef INT 791#undef INT_DEF 792 793 RegCloseKey(netw); 794 795 return errors ? -1 : 0; 796} 797 798 799static int wpa_config_write_blob(HKEY hk, struct wpa_config_blob *blob) 800{ 801 HKEY bhk; 802 LONG ret; 803 TCHAR *name; 804 805 ret = RegCreateKeyEx(hk, TEXT("blobs"), 0, NULL, 0, KEY_WRITE, NULL, 806 &bhk, NULL); 807 if (ret != ERROR_SUCCESS) { 808 wpa_printf(MSG_DEBUG, "WINREG: Could not add blobs key: " 809 "error 0x%x (%d)", 810 (unsigned int) ret, (int) GetLastError()); 811 return -1; 812 } 813 814 name = wpa_strdup_tchar(blob->name); 815 ret = RegSetValueEx(bhk, name, 0, REG_BINARY, blob->data, 816 blob->len); 817 if (ret != ERROR_SUCCESS) { 818 wpa_printf(MSG_ERROR, "WINREG: Failed to set blob %s': " 819 "error 0x%x (%d)", blob->name, (unsigned int) ret, 820 (int) GetLastError()); 821 RegCloseKey(bhk); 822 os_free(name); 823 return -1; 824 } 825 os_free(name); 826 827 RegCloseKey(bhk); 828 829 return 0; 830} 831 832 833int wpa_config_write(const char *name, struct wpa_config *config) 834{ 835 TCHAR buf[256]; 836 HKEY hk; 837 LONG ret; 838 int errors = 0; 839 struct wpa_ssid *ssid; 840 struct wpa_config_blob *blob; 841 int id; 842 843 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 844 845#ifdef UNICODE 846 _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name); 847#else /* UNICODE */ 848 os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name); 849#endif /* UNICODE */ 850 851 ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_SET_VALUE | DELETE, &hk); 852 if (ret != ERROR_SUCCESS) { 853 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant " 854 "configuration registry %s: error %d", buf, 855 (int) GetLastError()); 856 return -1; 857 } 858 859 if (wpa_config_write_global(config, hk)) { 860 wpa_printf(MSG_ERROR, "Failed to write global configuration " 861 "data"); 862 errors++; 863 } 864 865 wpa_config_delete_subkeys(hk, TEXT("networks")); 866 for (ssid = config->ssid, id = 0; ssid; ssid = ssid->next, id++) { 867 if (wpa_config_write_network(hk, ssid, id)) 868 errors++; 869 } 870 871 RegDeleteKey(hk, TEXT("blobs")); 872 for (blob = config->blobs; blob; blob = blob->next) { 873 if (wpa_config_write_blob(hk, blob)) 874 errors++; 875 } 876 877 RegCloseKey(hk); 878 879 wpa_printf(MSG_DEBUG, "Configuration '%s' written %ssuccessfully", 880 name, errors ? "un" : ""); 881 return errors ? -1 : 0; 882} 883