1 /* 2 * WPA Supplicant / Configuration backend: Windows registry 3 * Copyright (c) 2003-2019, 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 24 HKEY_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 50 static 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 119 static 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 136 static 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 163 static 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 181 static 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 201 static 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 wpa_config_read_reg_dword(hk, TEXT("wps_cred_add_sae"), 259 &config->wps_cred_add_sae); 260 #endif /* CONFIG_WPS */ 261 #ifdef CONFIG_P2P 262 config->p2p_ssid_postfix = wpa_config_read_reg_string( 263 hk, TEXT("p2p_ssid_postfix")); 264 wpa_config_read_reg_dword(hk, TEXT("p2p_group_idle"), 265 (int *) &config->p2p_group_idle); 266 #endif /* CONFIG_P2P */ 267 268 wpa_config_read_reg_dword(hk, TEXT("bss_max_count"), 269 (int *) &config->bss_max_count); 270 wpa_config_read_reg_dword(hk, TEXT("filter_ssids"), 271 &config->filter_ssids); 272 wpa_config_read_reg_dword(hk, TEXT("max_num_sta"), 273 (int *) &config->max_num_sta); 274 wpa_config_read_reg_dword(hk, TEXT("disassoc_low_ack"), 275 (int *) &config->disassoc_low_ack); 276 277 wpa_config_read_reg_dword(hk, TEXT("okc"), &config->okc); 278 wpa_config_read_reg_dword(hk, TEXT("pmf"), &val); 279 config->pmf = val; 280 if (wpa_config_read_reg_dword(hk, TEXT("extended_key_id"), 281 &val) == 0) { 282 if (val < 0 || val > 1) { 283 wpa_printf(MSG_ERROR, 284 "Invalid Extended Key ID setting (%d)", val); 285 errors++; 286 } 287 config->extended_key_id = val; 288 } 289 290 return errors ? -1 : 0; 291 } 292 293 294 static struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw, 295 int id) 296 { 297 HKEY nhk; 298 LONG ret; 299 DWORD i; 300 struct wpa_ssid *ssid; 301 int errors = 0; 302 303 ret = RegOpenKeyEx(hk, netw, 0, KEY_QUERY_VALUE, &nhk); 304 if (ret != ERROR_SUCCESS) { 305 wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config " 306 "network '" TSTR "'", netw); 307 return NULL; 308 } 309 310 wpa_printf(MSG_MSGDUMP, "Start of a new network '" TSTR "'", netw); 311 ssid = os_zalloc(sizeof(*ssid)); 312 if (ssid == NULL) { 313 RegCloseKey(nhk); 314 return NULL; 315 } 316 dl_list_init(&ssid->psk_list); 317 ssid->id = id; 318 319 wpa_config_set_network_defaults(ssid); 320 321 for (i = 0; ; i++) { 322 TCHAR name[255], data[1024]; 323 DWORD namelen, datalen, type; 324 325 namelen = 255; 326 datalen = sizeof(data); 327 ret = RegEnumValue(nhk, i, name, &namelen, NULL, &type, 328 (LPBYTE) data, &datalen); 329 330 if (ret == ERROR_NO_MORE_ITEMS) 331 break; 332 333 if (ret != ERROR_SUCCESS) { 334 wpa_printf(MSG_ERROR, "RegEnumValue failed: 0x%x", 335 (unsigned int) ret); 336 break; 337 } 338 339 if (namelen >= 255) 340 namelen = 255 - 1; 341 name[namelen] = TEXT('\0'); 342 343 if (datalen >= 1024) 344 datalen = 1024 - 1; 345 data[datalen] = TEXT('\0'); 346 347 wpa_unicode2ascii_inplace(name); 348 wpa_unicode2ascii_inplace(data); 349 if (wpa_config_set(ssid, (char *) name, (char *) data, 0) < 0) 350 errors++; 351 } 352 353 RegCloseKey(nhk); 354 355 if (ssid->passphrase) { 356 if (ssid->psk_set) { 357 wpa_printf(MSG_ERROR, "Both PSK and passphrase " 358 "configured for network '" TSTR "'.", netw); 359 errors++; 360 } 361 wpa_config_update_psk(ssid); 362 } 363 364 if ((ssid->group_cipher & WPA_CIPHER_CCMP) && 365 !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && 366 !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { 367 /* Group cipher cannot be stronger than the pairwise cipher. */ 368 wpa_printf(MSG_DEBUG, "Removed CCMP from group cipher " 369 "list since it was not allowed for pairwise " 370 "cipher for network '" TSTR "'.", netw); 371 ssid->group_cipher &= ~WPA_CIPHER_CCMP; 372 } 373 374 if (errors) { 375 wpa_config_free_ssid(ssid); 376 ssid = NULL; 377 } 378 379 return ssid; 380 } 381 382 383 static int wpa_config_read_networks(struct wpa_config *config, HKEY hk) 384 { 385 HKEY nhk; 386 struct wpa_ssid *ssid, *tail = NULL, *head = NULL; 387 int errors = 0; 388 LONG ret; 389 DWORD i; 390 391 ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_ENUMERATE_SUB_KEYS, 392 &nhk); 393 if (ret != ERROR_SUCCESS) { 394 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant networks " 395 "registry key"); 396 return -1; 397 } 398 399 for (i = 0; ; i++) { 400 TCHAR name[255]; 401 DWORD namelen; 402 403 namelen = 255; 404 ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL, 405 NULL); 406 407 if (ret == ERROR_NO_MORE_ITEMS) 408 break; 409 410 if (ret != ERROR_SUCCESS) { 411 wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x", 412 (unsigned int) ret); 413 break; 414 } 415 416 if (namelen >= 255) 417 namelen = 255 - 1; 418 name[namelen] = '\0'; 419 420 ssid = wpa_config_read_network(nhk, name, i); 421 if (ssid == NULL) { 422 wpa_printf(MSG_ERROR, "Failed to parse network " 423 "profile '%s'.", name); 424 errors++; 425 continue; 426 } 427 if (head == NULL) { 428 head = tail = ssid; 429 } else { 430 tail->next = ssid; 431 tail = ssid; 432 } 433 if (wpa_config_add_prio_network(config, ssid)) { 434 wpa_printf(MSG_ERROR, "Failed to add network profile " 435 "'%s' to priority list.", name); 436 errors++; 437 continue; 438 } 439 } 440 441 RegCloseKey(nhk); 442 443 config->ssid = head; 444 445 return errors ? -1 : 0; 446 } 447 448 449 struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp) 450 { 451 TCHAR buf[256]; 452 int errors = 0; 453 struct wpa_config *config; 454 HKEY hk; 455 LONG ret; 456 457 if (name == NULL) 458 return NULL; 459 if (cfgp) 460 config = cfgp; 461 else 462 config = wpa_config_alloc_empty(NULL, NULL); 463 if (config == NULL) 464 return NULL; 465 wpa_printf(MSG_DEBUG, "Reading configuration profile '%s'", name); 466 467 #ifdef UNICODE 468 _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name); 469 #else /* UNICODE */ 470 os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name); 471 #endif /* UNICODE */ 472 473 ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_QUERY_VALUE, &hk); 474 if (ret != ERROR_SUCCESS) { 475 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant " 476 "configuration registry HKLM\\" TSTR, buf); 477 os_free(config); 478 return NULL; 479 } 480 481 if (wpa_config_read_global(config, hk)) 482 errors++; 483 484 if (wpa_config_read_networks(config, hk)) 485 errors++; 486 487 if (wpa_config_read_blobs(config, hk)) 488 errors++; 489 490 wpa_config_debug_dump_networks(config); 491 492 RegCloseKey(hk); 493 494 if (errors) { 495 wpa_config_free(config); 496 config = NULL; 497 } 498 499 return config; 500 } 501 502 503 static int wpa_config_write_reg_dword(HKEY hk, const TCHAR *name, int val, 504 int def) 505 { 506 LONG ret; 507 DWORD _val = val; 508 509 if (val == def) { 510 RegDeleteValue(hk, name); 511 return 0; 512 } 513 514 ret = RegSetValueEx(hk, name, 0, REG_DWORD, (LPBYTE) &_val, 515 sizeof(_val)); 516 if (ret != ERROR_SUCCESS) { 517 wpa_printf(MSG_ERROR, "WINREG: Failed to set %s=%d: error %d", 518 name, val, (int) GetLastError()); 519 return -1; 520 } 521 522 return 0; 523 } 524 525 526 static int wpa_config_write_reg_string(HKEY hk, const char *name, 527 const char *val) 528 { 529 LONG ret; 530 TCHAR *_name, *_val; 531 532 _name = wpa_strdup_tchar(name); 533 if (_name == NULL) 534 return -1; 535 536 if (val == NULL) { 537 RegDeleteValue(hk, _name); 538 os_free(_name); 539 return 0; 540 } 541 542 _val = wpa_strdup_tchar(val); 543 if (_val == NULL) { 544 os_free(_name); 545 return -1; 546 } 547 ret = RegSetValueEx(hk, _name, 0, REG_SZ, (BYTE *) _val, 548 (os_strlen(val) + 1) * sizeof(TCHAR)); 549 if (ret != ERROR_SUCCESS) { 550 wpa_printf(MSG_ERROR, "WINREG: Failed to set %s='%s': " 551 "error %d", name, val, (int) GetLastError()); 552 os_free(_name); 553 os_free(_val); 554 return -1; 555 } 556 557 os_free(_name); 558 os_free(_val); 559 return 0; 560 } 561 562 563 static int wpa_config_write_global(struct wpa_config *config, HKEY hk) 564 { 565 #ifdef CONFIG_CTRL_IFACE 566 wpa_config_write_reg_string(hk, "ctrl_interface", 567 config->ctrl_interface); 568 #endif /* CONFIG_CTRL_IFACE */ 569 570 wpa_config_write_reg_dword(hk, TEXT("eapol_version"), 571 config->eapol_version, 572 DEFAULT_EAPOL_VERSION); 573 wpa_config_write_reg_dword(hk, TEXT("ap_scan"), config->ap_scan, 574 DEFAULT_AP_SCAN); 575 wpa_config_write_reg_dword(hk, TEXT("fast_reauth"), 576 config->fast_reauth, DEFAULT_FAST_REAUTH); 577 wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"), 578 config->dot11RSNAConfigPMKLifetime, 0); 579 wpa_config_write_reg_dword(hk, 580 TEXT("dot11RSNAConfigPMKReauthThreshold"), 581 config->dot11RSNAConfigPMKReauthThreshold, 582 0); 583 wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"), 584 config->dot11RSNAConfigSATimeout, 0); 585 wpa_config_write_reg_dword(hk, TEXT("update_config"), 586 config->update_config, 587 0); 588 #ifdef CONFIG_WPS 589 if (!is_nil_uuid(config->uuid)) { 590 char buf[40]; 591 uuid_bin2str(config->uuid, buf, sizeof(buf)); 592 wpa_config_write_reg_string(hk, "uuid", buf); 593 } 594 wpa_config_write_reg_dword(hk, TEXT("auto_uuid"), config->auto_uuid, 595 0); 596 wpa_config_write_reg_string(hk, "device_name", config->device_name); 597 wpa_config_write_reg_string(hk, "manufacturer", config->manufacturer); 598 wpa_config_write_reg_string(hk, "model_name", config->model_name); 599 wpa_config_write_reg_string(hk, "model_number", config->model_number); 600 wpa_config_write_reg_string(hk, "serial_number", 601 config->serial_number); 602 { 603 char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; 604 buf = wps_dev_type_bin2str(config->device_type, 605 _buf, sizeof(_buf)); 606 wpa_config_write_reg_string(hk, "device_type", buf); 607 } 608 wpa_config_write_reg_string(hk, "config_methods", 609 config->config_methods); 610 if (WPA_GET_BE32(config->os_version)) { 611 char vbuf[10]; 612 os_snprintf(vbuf, sizeof(vbuf), "%08x", 613 WPA_GET_BE32(config->os_version)); 614 wpa_config_write_reg_string(hk, "os_version", vbuf); 615 } 616 wpa_config_write_reg_dword(hk, TEXT("wps_cred_processing"), 617 config->wps_cred_processing, 0); 618 wpa_config_write_reg_dword(hk, TEXT("wps_cred_add_sae"), 619 config->wps_cred_add_sae, 0); 620 #endif /* CONFIG_WPS */ 621 #ifdef CONFIG_P2P 622 wpa_config_write_reg_string(hk, "p2p_ssid_postfix", 623 config->p2p_ssid_postfix); 624 wpa_config_write_reg_dword(hk, TEXT("p2p_group_idle"), 625 config->p2p_group_idle, 0); 626 #endif /* CONFIG_P2P */ 627 628 wpa_config_write_reg_dword(hk, TEXT("bss_max_count"), 629 config->bss_max_count, 630 DEFAULT_BSS_MAX_COUNT); 631 wpa_config_write_reg_dword(hk, TEXT("filter_ssids"), 632 config->filter_ssids, 0); 633 wpa_config_write_reg_dword(hk, TEXT("max_num_sta"), 634 config->max_num_sta, DEFAULT_MAX_NUM_STA); 635 wpa_config_write_reg_dword(hk, TEXT("ap_isolate"), 636 config->ap_isolate, DEFAULT_AP_ISOLATE); 637 wpa_config_write_reg_dword(hk, TEXT("disassoc_low_ack"), 638 config->disassoc_low_ack, 0); 639 640 wpa_config_write_reg_dword(hk, TEXT("okc"), config->okc, 0); 641 wpa_config_write_reg_dword(hk, TEXT("pmf"), config->pmf, 0); 642 643 wpa_config_write_reg_dword(hk, TEXT("external_sim"), 644 config->external_sim, 0); 645 646 return 0; 647 } 648 649 650 static int wpa_config_delete_subkeys(HKEY hk, const TCHAR *key) 651 { 652 HKEY nhk; 653 int i, errors = 0; 654 LONG ret; 655 656 ret = RegOpenKeyEx(hk, key, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &nhk); 657 if (ret != ERROR_SUCCESS) { 658 wpa_printf(MSG_DEBUG, "WINREG: Could not open key '" TSTR 659 "' for subkey deletion: error 0x%x (%d)", key, 660 (unsigned int) ret, (int) GetLastError()); 661 return 0; 662 } 663 664 for (i = 0; ; i++) { 665 TCHAR name[255]; 666 DWORD namelen; 667 668 namelen = 255; 669 ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL, 670 NULL); 671 672 if (ret == ERROR_NO_MORE_ITEMS) 673 break; 674 675 if (ret != ERROR_SUCCESS) { 676 wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x (%d)", 677 (unsigned int) ret, (int) GetLastError()); 678 break; 679 } 680 681 if (namelen >= 255) 682 namelen = 255 - 1; 683 name[namelen] = TEXT('\0'); 684 685 ret = RegDeleteKey(nhk, name); 686 if (ret != ERROR_SUCCESS) { 687 wpa_printf(MSG_DEBUG, "RegDeleteKey failed: 0x%x (%d)", 688 (unsigned int) ret, (int) GetLastError()); 689 errors++; 690 } 691 } 692 693 RegCloseKey(nhk); 694 695 return errors ? -1 : 0; 696 } 697 698 699 static void write_str(HKEY hk, const char *field, struct wpa_ssid *ssid) 700 { 701 char *value = wpa_config_get(ssid, field); 702 if (value == NULL) 703 return; 704 wpa_config_write_reg_string(hk, field, value); 705 os_free(value); 706 } 707 708 709 static void write_int(HKEY hk, const char *field, int value, int def) 710 { 711 char val[20]; 712 if (value == def) 713 return; 714 os_snprintf(val, sizeof(val), "%d", value); 715 wpa_config_write_reg_string(hk, field, val); 716 } 717 718 719 static void write_bssid(HKEY hk, struct wpa_ssid *ssid) 720 { 721 char *value = wpa_config_get(ssid, "bssid"); 722 if (value == NULL) 723 return; 724 wpa_config_write_reg_string(hk, "bssid", value); 725 os_free(value); 726 } 727 728 729 static void write_psk(HKEY hk, struct wpa_ssid *ssid) 730 { 731 char *value = wpa_config_get(ssid, "psk"); 732 if (value == NULL) 733 return; 734 wpa_config_write_reg_string(hk, "psk", value); 735 os_free(value); 736 } 737 738 739 static void write_proto(HKEY hk, struct wpa_ssid *ssid) 740 { 741 char *value; 742 743 if (ssid->proto == DEFAULT_PROTO) 744 return; 745 746 value = wpa_config_get(ssid, "proto"); 747 if (value == NULL) 748 return; 749 if (value[0]) 750 wpa_config_write_reg_string(hk, "proto", value); 751 os_free(value); 752 } 753 754 755 static void write_key_mgmt(HKEY hk, struct wpa_ssid *ssid) 756 { 757 char *value; 758 759 if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 760 return; 761 762 value = wpa_config_get(ssid, "key_mgmt"); 763 if (value == NULL) 764 return; 765 if (value[0]) 766 wpa_config_write_reg_string(hk, "key_mgmt", value); 767 os_free(value); 768 } 769 770 771 static void write_pairwise(HKEY hk, struct wpa_ssid *ssid) 772 { 773 char *value; 774 775 if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 776 return; 777 778 value = wpa_config_get(ssid, "pairwise"); 779 if (value == NULL) 780 return; 781 if (value[0]) 782 wpa_config_write_reg_string(hk, "pairwise", value); 783 os_free(value); 784 } 785 786 787 static void write_group(HKEY hk, struct wpa_ssid *ssid) 788 { 789 char *value; 790 791 if (ssid->group_cipher == DEFAULT_GROUP) 792 return; 793 794 value = wpa_config_get(ssid, "group"); 795 if (value == NULL) 796 return; 797 if (value[0]) 798 wpa_config_write_reg_string(hk, "group", value); 799 os_free(value); 800 } 801 802 803 static void write_auth_alg(HKEY hk, struct wpa_ssid *ssid) 804 { 805 char *value; 806 807 if (ssid->auth_alg == 0) 808 return; 809 810 value = wpa_config_get(ssid, "auth_alg"); 811 if (value == NULL) 812 return; 813 if (value[0]) 814 wpa_config_write_reg_string(hk, "auth_alg", value); 815 os_free(value); 816 } 817 818 819 #ifdef IEEE8021X_EAPOL 820 static void write_eap(HKEY hk, struct wpa_ssid *ssid) 821 { 822 char *value; 823 824 value = wpa_config_get(ssid, "eap"); 825 if (value == NULL) 826 return; 827 828 if (value[0]) 829 wpa_config_write_reg_string(hk, "eap", value); 830 os_free(value); 831 } 832 #endif /* IEEE8021X_EAPOL */ 833 834 835 #ifdef CONFIG_WEP 836 static void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid) 837 { 838 char field[20], *value; 839 840 os_snprintf(field, sizeof(field), "wep_key%d", idx); 841 value = wpa_config_get(ssid, field); 842 if (value) { 843 wpa_config_write_reg_string(hk, field, value); 844 os_free(value); 845 } 846 } 847 #endif /* CONFIG_WEP */ 848 849 850 static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id) 851 { 852 int errors = 0; 853 HKEY nhk, netw; 854 LONG ret; 855 TCHAR name[5]; 856 857 ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_CREATE_SUB_KEY, &nhk); 858 if (ret != ERROR_SUCCESS) { 859 wpa_printf(MSG_DEBUG, "WINREG: Could not open networks key " 860 "for subkey addition: error 0x%x (%d)", 861 (unsigned int) ret, (int) GetLastError()); 862 return 0; 863 } 864 865 #ifdef UNICODE 866 wsprintf(name, L"%04d", id); 867 #else /* UNICODE */ 868 os_snprintf(name, sizeof(name), "%04d", id); 869 #endif /* UNICODE */ 870 ret = RegCreateKeyEx(nhk, name, 0, NULL, 0, KEY_WRITE, NULL, &netw, 871 NULL); 872 RegCloseKey(nhk); 873 if (ret != ERROR_SUCCESS) { 874 wpa_printf(MSG_DEBUG, "WINREG: Could not add network key '%s':" 875 " error 0x%x (%d)", 876 name, (unsigned int) ret, (int) GetLastError()); 877 return -1; 878 } 879 880 #define STR(t) write_str(netw, #t, ssid) 881 #define INT(t) write_int(netw, #t, ssid->t, 0) 882 #define INTe(t, m) write_int(netw, #t, ssid->eap.m, 0) 883 #define INT_DEF(t, def) write_int(netw, #t, ssid->t, def) 884 #define INT_DEFe(t, m, def) write_int(netw, #t, ssid->eap.m, def) 885 886 STR(ssid); 887 INT(scan_ssid); 888 write_bssid(netw, ssid); 889 write_psk(netw, ssid); 890 STR(sae_password); 891 STR(sae_password_id); 892 write_proto(netw, ssid); 893 write_key_mgmt(netw, ssid); 894 write_pairwise(netw, ssid); 895 write_group(netw, ssid); 896 write_auth_alg(netw, ssid); 897 #ifdef IEEE8021X_EAPOL 898 write_eap(netw, ssid); 899 STR(identity); 900 STR(anonymous_identity); 901 STR(imsi_identity); 902 STR(password); 903 STR(ca_cert); 904 STR(ca_path); 905 STR(client_cert); 906 STR(private_key); 907 STR(private_key_passwd); 908 STR(dh_file); 909 STR(subject_match); 910 STR(check_cert_subject); 911 STR(altsubject_match); 912 STR(ca_cert2); 913 STR(ca_path2); 914 STR(client_cert2); 915 STR(private_key2); 916 STR(private_key2_passwd); 917 STR(dh_file2); 918 STR(subject_match2); 919 STR(check_cert_subject2); 920 STR(altsubject_match2); 921 STR(phase1); 922 STR(phase2); 923 STR(pcsc); 924 STR(pin); 925 STR(engine_id); 926 STR(key_id); 927 STR(cert_id); 928 STR(ca_cert_id); 929 STR(key2_id); 930 STR(pin2); 931 STR(engine2_id); 932 STR(cert2_id); 933 STR(ca_cert2_id); 934 INTe(engine, cert.engine); 935 INTe(engine2, phase2_cert.engine); 936 INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 937 #endif /* IEEE8021X_EAPOL */ 938 #ifdef CONFIG_WEP 939 { 940 int i; 941 942 for (i = 0; i < 4; i++) 943 write_wep_key(netw, i, ssid); 944 INT(wep_tx_keyidx); 945 } 946 #endif /* CONFIG_WEP */ 947 INT(priority); 948 #ifdef IEEE8021X_EAPOL 949 INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 950 STR(pac_file); 951 INT_DEFe(fragment_size, fragment_size, DEFAULT_FRAGMENT_SIZE); 952 #endif /* IEEE8021X_EAPOL */ 953 INT(mode); 954 write_int(netw, "proactive_key_caching", ssid->proactive_key_caching, 955 -1); 956 INT(disabled); 957 write_int(netw, "ieee80211w", ssid->ieee80211w, 958 MGMT_FRAME_PROTECTION_DEFAULT); 959 STR(id_str); 960 #ifdef CONFIG_HS20 961 INT(update_identifier); 962 #endif /* CONFIG_HS20 */ 963 INT(group_rekey); 964 INT(ft_eap_pmksa_caching); 965 966 #undef STR 967 #undef INT 968 #undef INT_DEF 969 970 RegCloseKey(netw); 971 972 return errors ? -1 : 0; 973 } 974 975 976 static int wpa_config_write_blob(HKEY hk, struct wpa_config_blob *blob) 977 { 978 HKEY bhk; 979 LONG ret; 980 TCHAR *name; 981 982 ret = RegCreateKeyEx(hk, TEXT("blobs"), 0, NULL, 0, KEY_WRITE, NULL, 983 &bhk, NULL); 984 if (ret != ERROR_SUCCESS) { 985 wpa_printf(MSG_DEBUG, "WINREG: Could not add blobs key: " 986 "error 0x%x (%d)", 987 (unsigned int) ret, (int) GetLastError()); 988 return -1; 989 } 990 991 name = wpa_strdup_tchar(blob->name); 992 ret = RegSetValueEx(bhk, name, 0, REG_BINARY, blob->data, 993 blob->len); 994 if (ret != ERROR_SUCCESS) { 995 wpa_printf(MSG_ERROR, "WINREG: Failed to set blob %s': " 996 "error 0x%x (%d)", blob->name, (unsigned int) ret, 997 (int) GetLastError()); 998 RegCloseKey(bhk); 999 os_free(name); 1000 return -1; 1001 } 1002 os_free(name); 1003 1004 RegCloseKey(bhk); 1005 1006 return 0; 1007 } 1008 1009 1010 int wpa_config_write(const char *name, struct wpa_config *config) 1011 { 1012 TCHAR buf[256]; 1013 HKEY hk; 1014 LONG ret; 1015 int errors = 0; 1016 struct wpa_ssid *ssid; 1017 struct wpa_config_blob *blob; 1018 int id; 1019 1020 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 1021 1022 #ifdef UNICODE 1023 _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name); 1024 #else /* UNICODE */ 1025 os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name); 1026 #endif /* UNICODE */ 1027 1028 ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_SET_VALUE | DELETE, &hk); 1029 if (ret != ERROR_SUCCESS) { 1030 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant " 1031 "configuration registry %s: error %d", buf, 1032 (int) GetLastError()); 1033 return -1; 1034 } 1035 1036 if (wpa_config_write_global(config, hk)) { 1037 wpa_printf(MSG_ERROR, "Failed to write global configuration " 1038 "data"); 1039 errors++; 1040 } 1041 1042 wpa_config_delete_subkeys(hk, TEXT("networks")); 1043 for (ssid = config->ssid, id = 0; ssid; ssid = ssid->next, id++) { 1044 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS) 1045 continue; /* do not save temporary WPS networks */ 1046 if (wpa_config_write_network(hk, ssid, id)) 1047 errors++; 1048 } 1049 1050 RegDeleteKey(hk, TEXT("blobs")); 1051 for (blob = config->blobs; blob; blob = blob->next) { 1052 if (wpa_config_write_blob(hk, blob)) 1053 errors++; 1054 } 1055 1056 RegCloseKey(hk); 1057 1058 wpa_printf(MSG_DEBUG, "Configuration '%s' written %ssuccessfully", 1059 name, errors ? "un" : ""); 1060 return errors ? -1 : 0; 1061 } 1062