$search
00001 /* 00002 * WPA Supplicant / Configuration backend: Windows registry 00003 * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 * 00014 * This file implements a configuration backend for Windows registry. All the 00015 * configuration information is stored in the registry and the format for 00016 * network configuration fields is same as described in the sample 00017 * configuration file, wpa_supplicant.conf. 00018 * 00019 * Configuration data is in 00020 * \a HKEY_LOCAL_MACHINE\\SOFTWARE\\%wpa_supplicant\\configs 00021 * key. Each configuration profile has its own key under this. In terms of text 00022 * files, each profile would map to a separate text file with possibly multiple 00023 * networks. Under each profile, there is a networks key that lists all 00024 * networks as a subkey. Each network has set of values in the same way as 00025 * network block in the configuration file. In addition, blobs subkey has 00026 * possible blobs as values. 00027 * 00028 * Example network configuration block: 00029 * \verbatim 00030 HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs\test\networks\0000 00031 ssid="example" 00032 key_mgmt=WPA-PSK 00033 \endverbatim 00034 */ 00035 00036 #include "includes.h" 00037 00038 #include "common.h" 00039 #include "uuid.h" 00040 #include "config.h" 00041 00042 #ifndef WPA_KEY_ROOT 00043 #define WPA_KEY_ROOT HKEY_LOCAL_MACHINE 00044 #endif 00045 #ifndef WPA_KEY_PREFIX 00046 #define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant") 00047 #endif 00048 00049 #ifdef UNICODE 00050 #define TSTR "%S" 00051 #else /* UNICODE */ 00052 #define TSTR "%s" 00053 #endif /* UNICODE */ 00054 00055 00056 static int wpa_config_read_blobs(struct wpa_config *config, HKEY hk) 00057 { 00058 struct wpa_config_blob *blob; 00059 int errors = 0; 00060 HKEY bhk; 00061 LONG ret; 00062 DWORD i; 00063 00064 ret = RegOpenKeyEx(hk, TEXT("blobs"), 0, KEY_QUERY_VALUE, &bhk); 00065 if (ret != ERROR_SUCCESS) { 00066 wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config " 00067 "blobs key"); 00068 return 0; /* assume no blobs */ 00069 } 00070 00071 for (i = 0; ; i++) { 00072 #define TNAMELEN 255 00073 TCHAR name[TNAMELEN]; 00074 char data[4096]; 00075 DWORD namelen, datalen, type; 00076 00077 namelen = TNAMELEN; 00078 datalen = sizeof(data); 00079 ret = RegEnumValue(bhk, i, name, &namelen, NULL, &type, 00080 (LPBYTE) data, &datalen); 00081 00082 if (ret == ERROR_NO_MORE_ITEMS) 00083 break; 00084 00085 if (ret != ERROR_SUCCESS) { 00086 wpa_printf(MSG_DEBUG, "RegEnumValue failed: 0x%x", 00087 (unsigned int) ret); 00088 break; 00089 } 00090 00091 if (namelen >= TNAMELEN) 00092 namelen = TNAMELEN - 1; 00093 name[namelen] = TEXT('\0'); 00094 wpa_unicode2ascii_inplace(name); 00095 00096 if (datalen >= sizeof(data)) 00097 datalen = sizeof(data) - 1; 00098 00099 wpa_printf(MSG_MSGDUMP, "blob %d: field='%s' len %d", 00100 (int) i, name, (int) datalen); 00101 00102 blob = os_zalloc(sizeof(*blob)); 00103 if (blob == NULL) { 00104 errors++; 00105 break; 00106 } 00107 blob->name = os_strdup((char *) name); 00108 blob->data = os_malloc(datalen); 00109 if (blob->name == NULL || blob->data == NULL) { 00110 wpa_config_free_blob(blob); 00111 errors++; 00112 break; 00113 } 00114 os_memcpy(blob->data, data, datalen); 00115 blob->len = datalen; 00116 00117 wpa_config_set_blob(config, blob); 00118 } 00119 00120 RegCloseKey(bhk); 00121 00122 return errors ? -1 : 0; 00123 } 00124 00125 00126 static int wpa_config_read_reg_dword(HKEY hk, const TCHAR *name, int *_val) 00127 { 00128 DWORD val, buflen; 00129 LONG ret; 00130 00131 buflen = sizeof(val); 00132 ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) &val, &buflen); 00133 if (ret == ERROR_SUCCESS && buflen == sizeof(val)) { 00134 wpa_printf(MSG_DEBUG, TSTR "=%d", name, (int) val); 00135 *_val = val; 00136 return 0; 00137 } 00138 00139 return -1; 00140 } 00141 00142 00143 static char * wpa_config_read_reg_string(HKEY hk, const TCHAR *name) 00144 { 00145 DWORD buflen; 00146 LONG ret; 00147 TCHAR *val; 00148 00149 buflen = 0; 00150 ret = RegQueryValueEx(hk, name, NULL, NULL, NULL, &buflen); 00151 if (ret != ERROR_SUCCESS) 00152 return NULL; 00153 val = os_malloc(buflen); 00154 if (val == NULL) 00155 return NULL; 00156 00157 ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) val, &buflen); 00158 if (ret != ERROR_SUCCESS) { 00159 os_free(val); 00160 return NULL; 00161 } 00162 00163 wpa_unicode2ascii_inplace(val); 00164 wpa_printf(MSG_DEBUG, TSTR "=%s", name, (char *) val); 00165 return (char *) val; 00166 } 00167 00168 00169 #ifdef CONFIG_WPS 00170 static int wpa_config_read_global_uuid(struct wpa_config *config, HKEY hk) 00171 { 00172 char *str; 00173 int ret = 0; 00174 00175 str = wpa_config_read_reg_string(hk, TEXT("uuid")); 00176 if (str == NULL) 00177 return 0; 00178 00179 if (uuid_str2bin(str, config->uuid)) 00180 ret = -1; 00181 00182 os_free(str); 00183 00184 return ret; 00185 } 00186 00187 00188 static int wpa_config_read_global_os_version(struct wpa_config *config, 00189 HKEY hk) 00190 { 00191 char *str; 00192 int ret = 0; 00193 00194 str = wpa_config_read_reg_string(hk, TEXT("os_version")); 00195 if (str == NULL) 00196 return 0; 00197 00198 if (hexstr2bin(str, config->os_version, 4)) 00199 ret = -1; 00200 00201 os_free(str); 00202 00203 return ret; 00204 } 00205 #endif /* CONFIG_WPS */ 00206 00207 00208 static int wpa_config_read_global(struct wpa_config *config, HKEY hk) 00209 { 00210 int errors = 0; 00211 00212 wpa_config_read_reg_dword(hk, TEXT("ap_scan"), &config->ap_scan); 00213 wpa_config_read_reg_dword(hk, TEXT("fast_reauth"), 00214 &config->fast_reauth); 00215 wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"), 00216 (int *) &config->dot11RSNAConfigPMKLifetime); 00217 wpa_config_read_reg_dword(hk, 00218 TEXT("dot11RSNAConfigPMKReauthThreshold"), 00219 (int *) 00220 &config->dot11RSNAConfigPMKReauthThreshold); 00221 wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"), 00222 (int *) &config->dot11RSNAConfigSATimeout); 00223 wpa_config_read_reg_dword(hk, TEXT("update_config"), 00224 &config->update_config); 00225 00226 if (wpa_config_read_reg_dword(hk, TEXT("eapol_version"), 00227 &config->eapol_version) == 0) { 00228 if (config->eapol_version < 1 || 00229 config->eapol_version > 2) { 00230 wpa_printf(MSG_ERROR, "Invalid EAPOL version (%d)", 00231 config->eapol_version); 00232 errors++; 00233 } 00234 } 00235 00236 config->ctrl_interface = wpa_config_read_reg_string( 00237 hk, TEXT("ctrl_interface")); 00238 00239 #ifdef CONFIG_WPS 00240 if (wpa_config_read_global_uuid(config, hk)) 00241 errors++; 00242 config->device_name = wpa_config_read_reg_string( 00243 hk, TEXT("device_name")); 00244 config->manufacturer = wpa_config_read_reg_string( 00245 hk, TEXT("manufacturer")); 00246 config->model_name = wpa_config_read_reg_string( 00247 hk, TEXT("model_name")); 00248 config->serial_number = wpa_config_read_reg_string( 00249 hk, TEXT("serial_number")); 00250 config->device_type = wpa_config_read_reg_string( 00251 hk, TEXT("device_type")); 00252 config->config_methods = wpa_config_read_reg_string( 00253 hk, TEXT("config_methods")); 00254 if (wpa_config_read_global_os_version(config, hk)) 00255 errors++; 00256 wpa_config_read_reg_dword(hk, TEXT("wps_cred_processing"), 00257 &config->wps_cred_processing); 00258 #endif /* CONFIG_WPS */ 00259 00260 wpa_config_read_reg_dword(hk, TEXT("bss_max_count"), 00261 &config->bss_max_count); 00262 wpa_config_read_reg_dword(hk, TEXT("filter_ssids"), 00263 &config->filter_ssids); 00264 00265 return errors ? -1 : 0; 00266 } 00267 00268 00269 static struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw, 00270 int id) 00271 { 00272 HKEY nhk; 00273 LONG ret; 00274 DWORD i; 00275 struct wpa_ssid *ssid; 00276 int errors = 0; 00277 00278 ret = RegOpenKeyEx(hk, netw, 0, KEY_QUERY_VALUE, &nhk); 00279 if (ret != ERROR_SUCCESS) { 00280 wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config " 00281 "network '" TSTR "'", netw); 00282 return NULL; 00283 } 00284 00285 wpa_printf(MSG_MSGDUMP, "Start of a new network '" TSTR "'", netw); 00286 ssid = os_zalloc(sizeof(*ssid)); 00287 if (ssid == NULL) { 00288 RegCloseKey(nhk); 00289 return NULL; 00290 } 00291 ssid->id = id; 00292 00293 wpa_config_set_network_defaults(ssid); 00294 00295 for (i = 0; ; i++) { 00296 TCHAR name[255], data[1024]; 00297 DWORD namelen, datalen, type; 00298 00299 namelen = 255; 00300 datalen = sizeof(data); 00301 ret = RegEnumValue(nhk, i, name, &namelen, NULL, &type, 00302 (LPBYTE) data, &datalen); 00303 00304 if (ret == ERROR_NO_MORE_ITEMS) 00305 break; 00306 00307 if (ret != ERROR_SUCCESS) { 00308 wpa_printf(MSG_ERROR, "RegEnumValue failed: 0x%x", 00309 (unsigned int) ret); 00310 break; 00311 } 00312 00313 if (namelen >= 255) 00314 namelen = 255 - 1; 00315 name[namelen] = TEXT('\0'); 00316 00317 if (datalen >= 1024) 00318 datalen = 1024 - 1; 00319 data[datalen] = TEXT('\0'); 00320 00321 wpa_unicode2ascii_inplace(name); 00322 wpa_unicode2ascii_inplace(data); 00323 if (wpa_config_set(ssid, (char *) name, (char *) data, 0) < 0) 00324 errors++; 00325 } 00326 00327 RegCloseKey(nhk); 00328 00329 if (ssid->passphrase) { 00330 if (ssid->psk_set) { 00331 wpa_printf(MSG_ERROR, "Both PSK and passphrase " 00332 "configured for network '" TSTR "'.", netw); 00333 errors++; 00334 } 00335 wpa_config_update_psk(ssid); 00336 } 00337 00338 if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | 00339 WPA_KEY_MGMT_PSK_SHA256)) && 00340 !ssid->psk_set) { 00341 wpa_printf(MSG_ERROR, "WPA-PSK accepted for key management, " 00342 "but no PSK configured for network '" TSTR "'.", 00343 netw); 00344 errors++; 00345 } 00346 00347 if ((ssid->group_cipher & WPA_CIPHER_CCMP) && 00348 !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && 00349 !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { 00350 /* Group cipher cannot be stronger than the pairwise cipher. */ 00351 wpa_printf(MSG_DEBUG, "Removed CCMP from group cipher " 00352 "list since it was not allowed for pairwise " 00353 "cipher for network '" TSTR "'.", netw); 00354 ssid->group_cipher &= ~WPA_CIPHER_CCMP; 00355 } 00356 00357 if (errors) { 00358 wpa_config_free_ssid(ssid); 00359 ssid = NULL; 00360 } 00361 00362 return ssid; 00363 } 00364 00365 00366 static int wpa_config_read_networks(struct wpa_config *config, HKEY hk) 00367 { 00368 HKEY nhk; 00369 struct wpa_ssid *ssid, *tail = NULL, *head = NULL; 00370 int errors = 0; 00371 LONG ret; 00372 DWORD i; 00373 00374 ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_ENUMERATE_SUB_KEYS, 00375 &nhk); 00376 if (ret != ERROR_SUCCESS) { 00377 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant networks " 00378 "registry key"); 00379 return -1; 00380 } 00381 00382 for (i = 0; ; i++) { 00383 TCHAR name[255]; 00384 DWORD namelen; 00385 00386 namelen = 255; 00387 ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL, 00388 NULL); 00389 00390 if (ret == ERROR_NO_MORE_ITEMS) 00391 break; 00392 00393 if (ret != ERROR_SUCCESS) { 00394 wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x", 00395 (unsigned int) ret); 00396 break; 00397 } 00398 00399 if (namelen >= 255) 00400 namelen = 255 - 1; 00401 name[namelen] = '\0'; 00402 00403 ssid = wpa_config_read_network(nhk, name, i); 00404 if (ssid == NULL) { 00405 wpa_printf(MSG_ERROR, "Failed to parse network " 00406 "profile '%s'.", name); 00407 errors++; 00408 continue; 00409 } 00410 if (head == NULL) { 00411 head = tail = ssid; 00412 } else { 00413 tail->next = ssid; 00414 tail = ssid; 00415 } 00416 if (wpa_config_add_prio_network(config, ssid)) { 00417 wpa_printf(MSG_ERROR, "Failed to add network profile " 00418 "'%s' to priority list.", name); 00419 errors++; 00420 continue; 00421 } 00422 } 00423 00424 RegCloseKey(nhk); 00425 00426 config->ssid = head; 00427 00428 return errors ? -1 : 0; 00429 } 00430 00431 00432 struct wpa_config * wpa_config_read(const char *name) 00433 { 00434 TCHAR buf[256]; 00435 int errors = 0; 00436 struct wpa_config *config; 00437 HKEY hk; 00438 LONG ret; 00439 00440 config = wpa_config_alloc_empty(NULL, NULL); 00441 if (config == NULL) 00442 return NULL; 00443 wpa_printf(MSG_DEBUG, "Reading configuration profile '%s'", name); 00444 00445 #ifdef UNICODE 00446 _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name); 00447 #else /* UNICODE */ 00448 os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name); 00449 #endif /* UNICODE */ 00450 00451 ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_QUERY_VALUE, &hk); 00452 if (ret != ERROR_SUCCESS) { 00453 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant " 00454 "configuration registry HKLM\\" TSTR, buf); 00455 os_free(config); 00456 return NULL; 00457 } 00458 00459 if (wpa_config_read_global(config, hk)) 00460 errors++; 00461 00462 if (wpa_config_read_networks(config, hk)) 00463 errors++; 00464 00465 if (wpa_config_read_blobs(config, hk)) 00466 errors++; 00467 00468 wpa_config_debug_dump_networks(config); 00469 00470 RegCloseKey(hk); 00471 00472 if (errors) { 00473 wpa_config_free(config); 00474 config = NULL; 00475 } 00476 00477 return config; 00478 } 00479 00480 00481 static int wpa_config_write_reg_dword(HKEY hk, const TCHAR *name, int val, 00482 int def) 00483 { 00484 LONG ret; 00485 DWORD _val = val; 00486 00487 if (val == def) { 00488 RegDeleteValue(hk, name); 00489 return 0; 00490 } 00491 00492 ret = RegSetValueEx(hk, name, 0, REG_DWORD, (LPBYTE) &_val, 00493 sizeof(_val)); 00494 if (ret != ERROR_SUCCESS) { 00495 wpa_printf(MSG_ERROR, "WINREG: Failed to set %s=%d: error %d", 00496 name, val, (int) GetLastError()); 00497 return -1; 00498 } 00499 00500 return 0; 00501 } 00502 00503 00504 static int wpa_config_write_reg_string(HKEY hk, const char *name, 00505 const char *val) 00506 { 00507 LONG ret; 00508 TCHAR *_name, *_val; 00509 00510 _name = wpa_strdup_tchar(name); 00511 if (_name == NULL) 00512 return -1; 00513 00514 if (val == NULL) { 00515 RegDeleteValue(hk, _name); 00516 os_free(_name); 00517 return 0; 00518 } 00519 00520 _val = wpa_strdup_tchar(val); 00521 if (_val == NULL) { 00522 os_free(_name); 00523 return -1; 00524 } 00525 ret = RegSetValueEx(hk, _name, 0, REG_SZ, (BYTE *) _val, 00526 (os_strlen(val) + 1) * sizeof(TCHAR)); 00527 if (ret != ERROR_SUCCESS) { 00528 wpa_printf(MSG_ERROR, "WINREG: Failed to set %s='%s': " 00529 "error %d", name, val, (int) GetLastError()); 00530 os_free(_name); 00531 os_free(_val); 00532 return -1; 00533 } 00534 00535 os_free(_name); 00536 os_free(_val); 00537 return 0; 00538 } 00539 00540 00541 static int wpa_config_write_global(struct wpa_config *config, HKEY hk) 00542 { 00543 #ifdef CONFIG_CTRL_IFACE 00544 wpa_config_write_reg_string(hk, "ctrl_interface", 00545 config->ctrl_interface); 00546 #endif /* CONFIG_CTRL_IFACE */ 00547 00548 wpa_config_write_reg_dword(hk, TEXT("eapol_version"), 00549 config->eapol_version, 00550 DEFAULT_EAPOL_VERSION); 00551 wpa_config_write_reg_dword(hk, TEXT("ap_scan"), config->ap_scan, 00552 DEFAULT_AP_SCAN); 00553 wpa_config_write_reg_dword(hk, TEXT("fast_reauth"), 00554 config->fast_reauth, DEFAULT_FAST_REAUTH); 00555 wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"), 00556 config->dot11RSNAConfigPMKLifetime, 0); 00557 wpa_config_write_reg_dword(hk, 00558 TEXT("dot11RSNAConfigPMKReauthThreshold"), 00559 config->dot11RSNAConfigPMKReauthThreshold, 00560 0); 00561 wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"), 00562 config->dot11RSNAConfigSATimeout, 0); 00563 wpa_config_write_reg_dword(hk, TEXT("update_config"), 00564 config->update_config, 00565 0); 00566 #ifdef CONFIG_WPS 00567 if (!is_nil_uuid(config->uuid)) { 00568 char buf[40]; 00569 uuid_bin2str(config->uuid, buf, sizeof(buf)); 00570 wpa_config_write_reg_string(hk, "uuid", buf); 00571 } 00572 wpa_config_write_reg_string(hk, "device_name", config->device_name); 00573 wpa_config_write_reg_string(hk, "manufacturer", config->manufacturer); 00574 wpa_config_write_reg_string(hk, "model_name", config->model_name); 00575 wpa_config_write_reg_string(hk, "model_number", config->model_number); 00576 wpa_config_write_reg_string(hk, "serial_number", 00577 config->serial_number); 00578 wpa_config_write_reg_string(hk, "device_type", config->device_type); 00579 wpa_config_write_reg_string(hk, "config_methods", 00580 config->config_methods); 00581 if (WPA_GET_BE32(config->os_version)) { 00582 char vbuf[10]; 00583 os_snprintf(vbuf, sizeof(vbuf), "%08x", 00584 WPA_GET_BE32(config->os_version)); 00585 wpa_config_write_reg_string(hk, "os_version", vbuf); 00586 } 00587 wpa_config_write_reg_dword(hk, TEXT("wps_cred_processing"), 00588 config->wps_cred_processing, 0); 00589 #endif /* CONFIG_WPS */ 00590 00591 wpa_config_write_reg_dword(hk, TEXT("bss_max_count"), 00592 config->bss_max_count, 00593 DEFAULT_BSS_MAX_COUNT); 00594 wpa_config_write_reg_dword(hk, TEXT("filter_ssids"), 00595 config->filter_ssids, 0); 00596 00597 return 0; 00598 } 00599 00600 00601 static int wpa_config_delete_subkeys(HKEY hk, const TCHAR *key) 00602 { 00603 HKEY nhk; 00604 int i, errors = 0; 00605 LONG ret; 00606 00607 ret = RegOpenKeyEx(hk, key, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &nhk); 00608 if (ret != ERROR_SUCCESS) { 00609 wpa_printf(MSG_DEBUG, "WINREG: Could not open key '" TSTR 00610 "' for subkey deletion: error 0x%x (%d)", key, 00611 (unsigned int) ret, (int) GetLastError()); 00612 return 0; 00613 } 00614 00615 for (i = 0; ; i++) { 00616 TCHAR name[255]; 00617 DWORD namelen; 00618 00619 namelen = 255; 00620 ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL, 00621 NULL); 00622 00623 if (ret == ERROR_NO_MORE_ITEMS) 00624 break; 00625 00626 if (ret != ERROR_SUCCESS) { 00627 wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x (%d)", 00628 (unsigned int) ret, (int) GetLastError()); 00629 break; 00630 } 00631 00632 if (namelen >= 255) 00633 namelen = 255 - 1; 00634 name[namelen] = TEXT('\0'); 00635 00636 ret = RegDeleteKey(nhk, name); 00637 if (ret != ERROR_SUCCESS) { 00638 wpa_printf(MSG_DEBUG, "RegDeleteKey failed: 0x%x (%d)", 00639 (unsigned int) ret, (int) GetLastError()); 00640 errors++; 00641 } 00642 } 00643 00644 RegCloseKey(nhk); 00645 00646 return errors ? -1 : 0; 00647 } 00648 00649 00650 static void write_str(HKEY hk, const char *field, struct wpa_ssid *ssid) 00651 { 00652 char *value = wpa_config_get(ssid, field); 00653 if (value == NULL) 00654 return; 00655 wpa_config_write_reg_string(hk, field, value); 00656 os_free(value); 00657 } 00658 00659 00660 static void write_int(HKEY hk, const char *field, int value, int def) 00661 { 00662 char val[20]; 00663 if (value == def) 00664 return; 00665 os_snprintf(val, sizeof(val), "%d", value); 00666 wpa_config_write_reg_string(hk, field, val); 00667 } 00668 00669 00670 static void write_bssid(HKEY hk, struct wpa_ssid *ssid) 00671 { 00672 char *value = wpa_config_get(ssid, "bssid"); 00673 if (value == NULL) 00674 return; 00675 wpa_config_write_reg_string(hk, "bssid", value); 00676 os_free(value); 00677 } 00678 00679 00680 static void write_psk(HKEY hk, struct wpa_ssid *ssid) 00681 { 00682 char *value = wpa_config_get(ssid, "psk"); 00683 if (value == NULL) 00684 return; 00685 wpa_config_write_reg_string(hk, "psk", value); 00686 os_free(value); 00687 } 00688 00689 00690 static void write_proto(HKEY hk, struct wpa_ssid *ssid) 00691 { 00692 char *value; 00693 00694 if (ssid->proto == DEFAULT_PROTO) 00695 return; 00696 00697 value = wpa_config_get(ssid, "proto"); 00698 if (value == NULL) 00699 return; 00700 if (value[0]) 00701 wpa_config_write_reg_string(hk, "proto", value); 00702 os_free(value); 00703 } 00704 00705 00706 static void write_key_mgmt(HKEY hk, struct wpa_ssid *ssid) 00707 { 00708 char *value; 00709 00710 if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 00711 return; 00712 00713 value = wpa_config_get(ssid, "key_mgmt"); 00714 if (value == NULL) 00715 return; 00716 if (value[0]) 00717 wpa_config_write_reg_string(hk, "key_mgmt", value); 00718 os_free(value); 00719 } 00720 00721 00722 static void write_pairwise(HKEY hk, struct wpa_ssid *ssid) 00723 { 00724 char *value; 00725 00726 if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 00727 return; 00728 00729 value = wpa_config_get(ssid, "pairwise"); 00730 if (value == NULL) 00731 return; 00732 if (value[0]) 00733 wpa_config_write_reg_string(hk, "pairwise", value); 00734 os_free(value); 00735 } 00736 00737 00738 static void write_group(HKEY hk, struct wpa_ssid *ssid) 00739 { 00740 char *value; 00741 00742 if (ssid->group_cipher == DEFAULT_GROUP) 00743 return; 00744 00745 value = wpa_config_get(ssid, "group"); 00746 if (value == NULL) 00747 return; 00748 if (value[0]) 00749 wpa_config_write_reg_string(hk, "group", value); 00750 os_free(value); 00751 } 00752 00753 00754 static void write_auth_alg(HKEY hk, struct wpa_ssid *ssid) 00755 { 00756 char *value; 00757 00758 if (ssid->auth_alg == 0) 00759 return; 00760 00761 value = wpa_config_get(ssid, "auth_alg"); 00762 if (value == NULL) 00763 return; 00764 if (value[0]) 00765 wpa_config_write_reg_string(hk, "auth_alg", value); 00766 os_free(value); 00767 } 00768 00769 00770 #ifdef IEEE8021X_EAPOL 00771 static void write_eap(HKEY hk, struct wpa_ssid *ssid) 00772 { 00773 char *value; 00774 00775 value = wpa_config_get(ssid, "eap"); 00776 if (value == NULL) 00777 return; 00778 00779 if (value[0]) 00780 wpa_config_write_reg_string(hk, "eap", value); 00781 os_free(value); 00782 } 00783 #endif /* IEEE8021X_EAPOL */ 00784 00785 00786 static void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid) 00787 { 00788 char field[20], *value; 00789 00790 os_snprintf(field, sizeof(field), "wep_key%d", idx); 00791 value = wpa_config_get(ssid, field); 00792 if (value) { 00793 wpa_config_write_reg_string(hk, field, value); 00794 os_free(value); 00795 } 00796 } 00797 00798 00799 static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id) 00800 { 00801 int i, errors = 0; 00802 HKEY nhk, netw; 00803 LONG ret; 00804 TCHAR name[5]; 00805 00806 ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_CREATE_SUB_KEY, &nhk); 00807 if (ret != ERROR_SUCCESS) { 00808 wpa_printf(MSG_DEBUG, "WINREG: Could not open networks key " 00809 "for subkey addition: error 0x%x (%d)", 00810 (unsigned int) ret, (int) GetLastError()); 00811 return 0; 00812 } 00813 00814 #ifdef UNICODE 00815 wsprintf(name, L"%04d", id); 00816 #else /* UNICODE */ 00817 os_snprintf(name, sizeof(name), "%04d", id); 00818 #endif /* UNICODE */ 00819 ret = RegCreateKeyEx(nhk, name, 0, NULL, 0, KEY_WRITE, NULL, &netw, 00820 NULL); 00821 RegCloseKey(nhk); 00822 if (ret != ERROR_SUCCESS) { 00823 wpa_printf(MSG_DEBUG, "WINREG: Could not add network key '%s':" 00824 " error 0x%x (%d)", 00825 name, (unsigned int) ret, (int) GetLastError()); 00826 return -1; 00827 } 00828 00829 #define STR(t) write_str(netw, #t, ssid) 00830 #define INT(t) write_int(netw, #t, ssid->t, 0) 00831 #define INTe(t) write_int(netw, #t, ssid->eap.t, 0) 00832 #define INT_DEF(t, def) write_int(netw, #t, ssid->t, def) 00833 #define INT_DEFe(t, def) write_int(netw, #t, ssid->eap.t, def) 00834 00835 STR(ssid); 00836 INT(scan_ssid); 00837 write_bssid(netw, ssid); 00838 write_psk(netw, ssid); 00839 write_proto(netw, ssid); 00840 write_key_mgmt(netw, ssid); 00841 write_pairwise(netw, ssid); 00842 write_group(netw, ssid); 00843 write_auth_alg(netw, ssid); 00844 #ifdef IEEE8021X_EAPOL 00845 write_eap(netw, ssid); 00846 STR(identity); 00847 STR(anonymous_identity); 00848 STR(password); 00849 STR(ca_cert); 00850 STR(ca_path); 00851 STR(client_cert); 00852 STR(private_key); 00853 STR(private_key_passwd); 00854 STR(dh_file); 00855 STR(subject_match); 00856 STR(altsubject_match); 00857 STR(ca_cert2); 00858 STR(ca_path2); 00859 STR(client_cert2); 00860 STR(private_key2); 00861 STR(private_key2_passwd); 00862 STR(dh_file2); 00863 STR(subject_match2); 00864 STR(altsubject_match2); 00865 STR(phase1); 00866 STR(phase2); 00867 STR(pcsc); 00868 STR(pin); 00869 STR(engine_id); 00870 STR(key_id); 00871 STR(cert_id); 00872 STR(ca_cert_id); 00873 STR(key2_id); 00874 STR(pin2); 00875 STR(engine2_id); 00876 STR(cert2_id); 00877 STR(ca_cert2_id); 00878 INTe(engine); 00879 INTe(engine2); 00880 INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 00881 #endif /* IEEE8021X_EAPOL */ 00882 for (i = 0; i < 4; i++) 00883 write_wep_key(netw, i, ssid); 00884 INT(wep_tx_keyidx); 00885 INT(priority); 00886 #ifdef IEEE8021X_EAPOL 00887 INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 00888 STR(pac_file); 00889 INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE); 00890 #endif /* IEEE8021X_EAPOL */ 00891 INT(mode); 00892 INT(proactive_key_caching); 00893 INT(disabled); 00894 INT(peerkey); 00895 #ifdef CONFIG_IEEE80211W 00896 INT(ieee80211w); 00897 #endif /* CONFIG_IEEE80211W */ 00898 STR(id_str); 00899 00900 #undef STR 00901 #undef INT 00902 #undef INT_DEF 00903 00904 RegCloseKey(netw); 00905 00906 return errors ? -1 : 0; 00907 } 00908 00909 00910 static int wpa_config_write_blob(HKEY hk, struct wpa_config_blob *blob) 00911 { 00912 HKEY bhk; 00913 LONG ret; 00914 TCHAR *name; 00915 00916 ret = RegCreateKeyEx(hk, TEXT("blobs"), 0, NULL, 0, KEY_WRITE, NULL, 00917 &bhk, NULL); 00918 if (ret != ERROR_SUCCESS) { 00919 wpa_printf(MSG_DEBUG, "WINREG: Could not add blobs key: " 00920 "error 0x%x (%d)", 00921 (unsigned int) ret, (int) GetLastError()); 00922 return -1; 00923 } 00924 00925 name = wpa_strdup_tchar(blob->name); 00926 ret = RegSetValueEx(bhk, name, 0, REG_BINARY, blob->data, 00927 blob->len); 00928 if (ret != ERROR_SUCCESS) { 00929 wpa_printf(MSG_ERROR, "WINREG: Failed to set blob %s': " 00930 "error 0x%x (%d)", blob->name, (unsigned int) ret, 00931 (int) GetLastError()); 00932 RegCloseKey(bhk); 00933 os_free(name); 00934 return -1; 00935 } 00936 os_free(name); 00937 00938 RegCloseKey(bhk); 00939 00940 return 0; 00941 } 00942 00943 00944 int wpa_config_write(const char *name, struct wpa_config *config) 00945 { 00946 TCHAR buf[256]; 00947 HKEY hk; 00948 LONG ret; 00949 int errors = 0; 00950 struct wpa_ssid *ssid; 00951 struct wpa_config_blob *blob; 00952 int id; 00953 00954 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 00955 00956 #ifdef UNICODE 00957 _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name); 00958 #else /* UNICODE */ 00959 os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name); 00960 #endif /* UNICODE */ 00961 00962 ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_SET_VALUE | DELETE, &hk); 00963 if (ret != ERROR_SUCCESS) { 00964 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant " 00965 "configuration registry %s: error %d", buf, 00966 (int) GetLastError()); 00967 return -1; 00968 } 00969 00970 if (wpa_config_write_global(config, hk)) { 00971 wpa_printf(MSG_ERROR, "Failed to write global configuration " 00972 "data"); 00973 errors++; 00974 } 00975 00976 wpa_config_delete_subkeys(hk, TEXT("networks")); 00977 for (ssid = config->ssid, id = 0; ssid; ssid = ssid->next, id++) { 00978 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS) 00979 continue; /* do not save temporary WPS networks */ 00980 if (wpa_config_write_network(hk, ssid, id)) 00981 errors++; 00982 } 00983 00984 RegDeleteKey(hk, TEXT("blobs")); 00985 for (blob = config->blobs; blob; blob = blob->next) { 00986 if (wpa_config_write_blob(hk, blob)) 00987 errors++; 00988 } 00989 00990 RegCloseKey(hk); 00991 00992 wpa_printf(MSG_DEBUG, "Configuration '%s' written %ssuccessfully", 00993 name, errors ? "un" : ""); 00994 return errors ? -1 : 0; 00995 }