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