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