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