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