config_winreg.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson/* 256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * WPA Supplicant / Configuration backend: Windows registry 356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> 456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * This program is free software; you can redistribute it and/or modify 656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * it under the terms of the GNU General Public License version 2 as 756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * published by the Free Software Foundation. 856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Alternatively, this software may be distributed under the terms of BSD 1056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * license. 1156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 1256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * See README and COPYING for more details. 1356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 1456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * This file implements a configuration backend for Windows registry. All the 1556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * configuration information is stored in the registry and the format for 1656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * network configuration fields is same as described in the sample 1756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * configuration file, wpa_supplicant.conf. 1856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 1956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Configuration data is in 2056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * \a HKEY_LOCAL_MACHINE\\SOFTWARE\\%wpa_supplicant\\configs 2156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * key. Each configuration profile has its own key under this. In terms of text 2256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * files, each profile would map to a separate text file with possibly multiple 2356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * networks. Under each profile, there is a networks key that lists all 2456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * networks as a subkey. Each network has set of values in the same way as 2556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * network block in the configuration file. In addition, blobs subkey has 2656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * possible blobs as values. 2756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 2856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Example network configuration block: 2956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * \verbatim 3056ed4167b942ec265f9cee70ac4d71d10b3835ceBen DodsonHKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs\test\networks\0000 3156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ssid="example" 3256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson key_mgmt=WPA-PSK 3356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson\endverbatim 3456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 3556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 3656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#include "includes.h" 3756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 3856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#include "common.h" 3956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#include "uuid.h" 4056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#include "config.h" 4156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 4256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifndef WPA_KEY_ROOT 4356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#define WPA_KEY_ROOT HKEY_LOCAL_MACHINE 4456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif 4556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifndef WPA_KEY_PREFIX 4656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant") 4756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif 4856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 4956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifdef UNICODE 5056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#define TSTR "%S" 5156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#else /* UNICODE */ 5256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#define TSTR "%s" 5356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif /* UNICODE */ 5456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_read_blobs(struct wpa_config *config, HKEY hk) 5756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 5856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson struct wpa_config_blob *blob; 5956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int errors = 0; 6056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson HKEY bhk; 6156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LONG ret; 6256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD i; 6356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 6456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegOpenKeyEx(hk, TEXT("blobs"), 0, KEY_QUERY_VALUE, &bhk); 6556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 6656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config " 6756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "blobs key"); 6856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; /* assume no blobs */ 6956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 7056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 7156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson for (i = 0; ; i++) { 7256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#define TNAMELEN 255 7356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson TCHAR name[TNAMELEN]; 7456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char data[4096]; 7556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD namelen, datalen, type; 7656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 7756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson namelen = TNAMELEN; 7856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson datalen = sizeof(data); 7956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegEnumValue(bhk, i, name, &namelen, NULL, &type, 8056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (LPBYTE) data, &datalen); 8156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 8256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret == ERROR_NO_MORE_ITEMS) 8356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 8456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 8556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 8656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, "RegEnumValue failed: 0x%x", 8756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (unsigned int) ret); 8856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 8956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 9056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 9156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (namelen >= TNAMELEN) 9256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson namelen = TNAMELEN - 1; 9356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson name[namelen] = TEXT('\0'); 9456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_unicode2ascii_inplace(name); 9556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 9656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (datalen >= sizeof(data)) 9756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson datalen = sizeof(data) - 1; 9856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 9956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_MSGDUMP, "blob %d: field='%s' len %d", 10056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (int) i, name, (int) datalen); 10156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 10256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson blob = os_zalloc(sizeof(*blob)); 10356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (blob == NULL) { 10456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 10556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 10656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 10756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson blob->name = os_strdup((char *) name); 10856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson blob->data = os_malloc(datalen); 10956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (blob->name == NULL || blob->data == NULL) { 11056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_free_blob(blob); 11156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 11256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 11356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 11456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_memcpy(blob->data, data, datalen); 11556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson blob->len = datalen; 11656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 11756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_set_blob(config, blob); 11856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 11956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 12056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson RegCloseKey(bhk); 12156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 12256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return errors ? -1 : 0; 12356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 12456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 12556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 12656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_read_reg_dword(HKEY hk, const TCHAR *name, int *_val) 12756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 12856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD val, buflen; 12956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LONG ret; 13056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 13156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson buflen = sizeof(val); 13256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) &val, &buflen); 13356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret == ERROR_SUCCESS && buflen == sizeof(val)) { 13456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, TSTR "=%d", name, (int) val); 13556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson *_val = val; 13656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; 13756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 13856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 13956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return -1; 14056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 14156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 14256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 14356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic char * wpa_config_read_reg_string(HKEY hk, const TCHAR *name) 14456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 14556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD buflen; 14656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LONG ret; 14756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson TCHAR *val; 14856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 14956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson buflen = 0; 15056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegQueryValueEx(hk, name, NULL, NULL, NULL, &buflen); 15156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) 15256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return NULL; 15356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson val = os_malloc(buflen); 15456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (val == NULL) 15556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return NULL; 15656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 15756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) val, &buflen); 15856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 15956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(val); 16056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return NULL; 16156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 16256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 16356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_unicode2ascii_inplace(val); 16456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, TSTR "=%s", name, (char *) val); 16556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return (char *) val; 16656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 16756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 16856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 16956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifdef CONFIG_WPS 17056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_read_global_uuid(struct wpa_config *config, HKEY hk) 17156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 17256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *str; 17356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int ret = 0; 17456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 17556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson str = wpa_config_read_reg_string(hk, TEXT("uuid")); 17656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (str == NULL) 17756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; 17856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 17956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (uuid_str2bin(str, config->uuid)) 18056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = -1; 18156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 18256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(str); 18356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 18456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return ret; 18556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 18656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 18756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 18856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_read_global_os_version(struct wpa_config *config, 18956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson HKEY hk) 19056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 19156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *str; 19256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int ret = 0; 19356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 19456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson str = wpa_config_read_reg_string(hk, TEXT("os_version")); 19556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (str == NULL) 19656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; 19756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 19856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (hexstr2bin(str, config->os_version, 4)) 19956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = -1; 20056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(str); 20256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return ret; 20456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 20556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif /* CONFIG_WPS */ 20656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_read_global(struct wpa_config *config, HKEY hk) 20956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 21056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int errors = 0; 21156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 21256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("ap_scan"), &config->ap_scan); 21356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("fast_reauth"), 21456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson &config->fast_reauth); 21556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"), 21656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (int *) &config->dot11RSNAConfigPMKLifetime); 21756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, 21856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson TEXT("dot11RSNAConfigPMKReauthThreshold"), 21956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (int *) 22056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson &config->dot11RSNAConfigPMKReauthThreshold); 22156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"), 22256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (int *) &config->dot11RSNAConfigSATimeout); 22356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("update_config"), 22456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson &config->update_config); 22556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 22656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (wpa_config_read_reg_dword(hk, TEXT("eapol_version"), 22756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson &config->eapol_version) == 0) { 22856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (config->eapol_version < 1 || 22956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->eapol_version > 2) { 23056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "Invalid EAPOL version (%d)", 23156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->eapol_version); 23256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 23356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 23456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 23556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 23656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->ctrl_interface = wpa_config_read_reg_string( 23756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson hk, TEXT("ctrl_interface")); 23856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 23956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifdef CONFIG_WPS 24056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (wpa_config_read_global_uuid(config, hk)) 24156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 24256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->device_name = wpa_config_read_reg_string( 24356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson hk, TEXT("device_name")); 24456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->manufacturer = wpa_config_read_reg_string( 24556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson hk, TEXT("manufacturer")); 24656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->model_name = wpa_config_read_reg_string( 24756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson hk, TEXT("model_name")); 24856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->serial_number = wpa_config_read_reg_string( 24956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson hk, TEXT("serial_number")); 25056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson { 25156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *t = wpa_config_read_reg_string( 25256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson hk, TEXT("device_type")); 25356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (t && wps_dev_type_str2bin(t, config->device_type)) 25456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 25556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(t); 25656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 25756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->config_methods = wpa_config_read_reg_string( 25856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson hk, TEXT("config_methods")); 25956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (wpa_config_read_global_os_version(config, hk)) 26056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 26156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("wps_cred_processing"), 26256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson &config->wps_cred_processing); 26356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif /* CONFIG_WPS */ 26456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifdef CONFIG_P2P 26556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->p2p_ssid_postfix = wpa_config_read_reg_string( 26656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson hk, TEXT("p2p_ssid_postfix")); 26756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("p2p_group_idle"), 26856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (int *) &config->p2p_group_idle); 26956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif /* CONFIG_P2P */ 27056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 27156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("bss_max_count"), 27256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (int *) &config->bss_max_count); 27356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("filter_ssids"), 27456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson &config->filter_ssids); 27556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("max_num_sta"), 27656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (int *) &config->max_num_sta); 27756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_read_reg_dword(hk, TEXT("disassoc_low_ack"), 27856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (int *) &config->disassoc_low_ack); 27956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 28056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return errors ? -1 : 0; 28156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 28256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 28356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 28456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw, 28556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int id) 28656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 28756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson HKEY nhk; 28856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LONG ret; 28956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD i; 29056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson struct wpa_ssid *ssid; 29156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int errors = 0; 29256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 29356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegOpenKeyEx(hk, netw, 0, KEY_QUERY_VALUE, &nhk); 29456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 29556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config " 29656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "network '" TSTR "'", netw); 29756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return NULL; 29856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 29956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 30056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_MSGDUMP, "Start of a new network '" TSTR "'", netw); 30156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ssid = os_zalloc(sizeof(*ssid)); 30256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ssid == NULL) { 30356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson RegCloseKey(nhk); 30456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return NULL; 30556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 30656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ssid->id = id; 30756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 30856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_set_network_defaults(ssid); 30956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 31056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson for (i = 0; ; i++) { 31156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson TCHAR name[255], data[1024]; 31256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD namelen, datalen, type; 31356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 31456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson namelen = 255; 31556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson datalen = sizeof(data); 31656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegEnumValue(nhk, i, name, &namelen, NULL, &type, 31756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (LPBYTE) data, &datalen); 31856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 31956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret == ERROR_NO_MORE_ITEMS) 32056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 32156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 32256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 32356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "RegEnumValue failed: 0x%x", 32456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (unsigned int) ret); 32556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 32656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 32756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 32856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (namelen >= 255) 32956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson namelen = 255 - 1; 33056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson name[namelen] = TEXT('\0'); 33156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 33256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (datalen >= 1024) 33356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson datalen = 1024 - 1; 33456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson data[datalen] = TEXT('\0'); 33556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 33656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_unicode2ascii_inplace(name); 33756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_unicode2ascii_inplace(data); 33856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (wpa_config_set(ssid, (char *) name, (char *) data, 0) < 0) 33956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 34056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 34156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 34256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson RegCloseKey(nhk); 34356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 34456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ssid->passphrase) { 34556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ssid->psk_set) { 34656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "Both PSK and passphrase " 34756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "configured for network '" TSTR "'.", netw); 34856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 34956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 35056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_update_psk(ssid); 35156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 35256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 35356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set) { 35456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "WPA-PSK accepted for key management, " 35556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "but no PSK configured for network '" TSTR "'.", 35656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson netw); 35756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 35856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 35956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 36056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if ((ssid->group_cipher & WPA_CIPHER_CCMP) && 36156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && 36256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { 36356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /* Group cipher cannot be stronger than the pairwise cipher. */ 36456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, "Removed CCMP from group cipher " 36556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "list since it was not allowed for pairwise " 36656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "cipher for network '" TSTR "'.", netw); 36756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ssid->group_cipher &= ~WPA_CIPHER_CCMP; 36856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 36956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 37056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (errors) { 37156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_free_ssid(ssid); 37256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ssid = NULL; 37356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 37456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 37556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return ssid; 37656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 37756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 37856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 37956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_read_networks(struct wpa_config *config, HKEY hk) 38056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 38156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson HKEY nhk; 38256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson struct wpa_ssid *ssid, *tail = NULL, *head = NULL; 38356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int errors = 0; 38456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LONG ret; 38556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD i; 38656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 38756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_ENUMERATE_SUB_KEYS, 38856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson &nhk); 38956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 39056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "Could not open wpa_supplicant networks " 39156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "registry key"); 39256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return -1; 39356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 39456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 39556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson for (i = 0; ; i++) { 39656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson TCHAR name[255]; 39756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD namelen; 39856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 39956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson namelen = 255; 40056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL, 40156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson NULL); 40256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 40356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret == ERROR_NO_MORE_ITEMS) 40456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 40556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 40656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 40756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x", 40856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (unsigned int) ret); 40956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 41056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 41156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 41256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (namelen >= 255) 41356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson namelen = 255 - 1; 41456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson name[namelen] = '\0'; 41556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 41656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ssid = wpa_config_read_network(nhk, name, i); 41756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ssid == NULL) { 41856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "Failed to parse network " 41956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "profile '%s'.", name); 42056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 42156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson continue; 42256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 42356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (head == NULL) { 42456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson head = tail = ssid; 42556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } else { 42656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson tail->next = ssid; 42756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson tail = ssid; 42856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 42956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (wpa_config_add_prio_network(config, ssid)) { 43056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "Failed to add network profile " 43156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "'%s' to priority list.", name); 43256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 43356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson continue; 43456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 43556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 43656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 43756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson RegCloseKey(nhk); 43856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 43956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->ssid = head; 44056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 44156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return errors ? -1 : 0; 44256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 44356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 44456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 44556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstruct wpa_config * wpa_config_read(const char *name) 44656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 44756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson TCHAR buf[256]; 44856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int errors = 0; 44956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson struct wpa_config *config; 45056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson HKEY hk; 45156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LONG ret; 45256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 45356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config = wpa_config_alloc_empty(NULL, NULL); 45456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (config == NULL) 45556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return NULL; 45656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, "Reading configuration profile '%s'", name); 45756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 45856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifdef UNICODE 45956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name); 46056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#else /* UNICODE */ 46156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name); 46256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif /* UNICODE */ 46356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 46456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_QUERY_VALUE, &hk); 46556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 46656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "Could not open wpa_supplicant " 46756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "configuration registry HKLM\\" TSTR, buf); 46856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(config); 46956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return NULL; 47056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 47156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 47256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (wpa_config_read_global(config, hk)) 47356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 47456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 47556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (wpa_config_read_networks(config, hk)) 47656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 47756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 47856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (wpa_config_read_blobs(config, hk)) 47956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 48056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 48156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_debug_dump_networks(config); 48256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 48356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson RegCloseKey(hk); 48456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 48556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (errors) { 48656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_free(config); 48756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config = NULL; 48856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 48956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 49056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return config; 49156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 49256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 49356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 49456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_write_reg_dword(HKEY hk, const TCHAR *name, int val, 49556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int def) 49656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 49756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LONG ret; 49856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD _val = val; 49956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 50056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (val == def) { 50156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson RegDeleteValue(hk, name); 50256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; 50356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 50456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 50556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegSetValueEx(hk, name, 0, REG_DWORD, (LPBYTE) &_val, 50656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson sizeof(_val)); 50756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 50856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "WINREG: Failed to set %s=%d: error %d", 50956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson name, val, (int) GetLastError()); 51056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return -1; 51156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 51256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 51356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; 51456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 51556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 51656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 51756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_write_reg_string(HKEY hk, const char *name, 51856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson const char *val) 51956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 52056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LONG ret; 52156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson TCHAR *_name, *_val; 52256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 52356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson _name = wpa_strdup_tchar(name); 52456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (_name == NULL) 52556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return -1; 52656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 52756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (val == NULL) { 52856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson RegDeleteValue(hk, _name); 52956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(_name); 53056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; 53156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 53256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 53356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson _val = wpa_strdup_tchar(val); 53456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (_val == NULL) { 53556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(_name); 53656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return -1; 53756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 53856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegSetValueEx(hk, _name, 0, REG_SZ, (BYTE *) _val, 53956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (os_strlen(val) + 1) * sizeof(TCHAR)); 54056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 54156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_ERROR, "WINREG: Failed to set %s='%s': " 54256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "error %d", name, val, (int) GetLastError()); 54356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(_name); 54456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(_val); 54556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return -1; 54656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 54756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 54856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(_name); 54956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(_val); 55056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; 55156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 55256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 55356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 55456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_write_global(struct wpa_config *config, HKEY hk) 55556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 55656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifdef CONFIG_CTRL_IFACE 55756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "ctrl_interface", 55856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->ctrl_interface); 55956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif /* CONFIG_CTRL_IFACE */ 56056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 56156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("eapol_version"), 56256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->eapol_version, 56356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DEFAULT_EAPOL_VERSION); 56456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("ap_scan"), config->ap_scan, 56556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DEFAULT_AP_SCAN); 56656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("fast_reauth"), 56756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->fast_reauth, DEFAULT_FAST_REAUTH); 56856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"), 56956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->dot11RSNAConfigPMKLifetime, 0); 57056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, 57156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson TEXT("dot11RSNAConfigPMKReauthThreshold"), 57256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->dot11RSNAConfigPMKReauthThreshold, 57356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 0); 57456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"), 57556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->dot11RSNAConfigSATimeout, 0); 57656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("update_config"), 57756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->update_config, 57856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 0); 57956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifdef CONFIG_WPS 58056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (!is_nil_uuid(config->uuid)) { 58156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char buf[40]; 58256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson uuid_bin2str(config->uuid, buf, sizeof(buf)); 58356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "uuid", buf); 58456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 58556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "device_name", config->device_name); 58656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "manufacturer", config->manufacturer); 58756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "model_name", config->model_name); 58856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "model_number", config->model_number); 58956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "serial_number", 59056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->serial_number); 59156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson { 59256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; 59356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson buf = wps_dev_type_bin2str(config->device_type, 59456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson _buf, sizeof(_buf)); 59556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "device_type", buf); 59656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 59756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "config_methods", 59856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->config_methods); 59956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (WPA_GET_BE32(config->os_version)) { 60056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char vbuf[10]; 60156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_snprintf(vbuf, sizeof(vbuf), "%08x", 60256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson WPA_GET_BE32(config->os_version)); 60356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "os_version", vbuf); 60456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 60556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("wps_cred_processing"), 60656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->wps_cred_processing, 0); 60756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif /* CONFIG_WPS */ 60856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifdef CONFIG_P2P 60956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "p2p_ssid_postfix", 61056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->p2p_ssid_postfix); 61156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("p2p_group_idle"), 61256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->p2p_group_idle, 0); 61356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif /* CONFIG_P2P */ 61456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 61556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("bss_max_count"), 61656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->bss_max_count, 61756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DEFAULT_BSS_MAX_COUNT); 61856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("filter_ssids"), 61956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->filter_ssids, 0); 62056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("max_num_sta"), 62156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->max_num_sta, DEFAULT_MAX_NUM_STA); 62256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_dword(hk, TEXT("disassoc_low_ack"), 62356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson config->disassoc_low_ack, 0); 62456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 62556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; 62656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 62756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 62856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 62956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic int wpa_config_delete_subkeys(HKEY hk, const TCHAR *key) 63056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 63156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson HKEY nhk; 63256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson int i, errors = 0; 63356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LONG ret; 63456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 63556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegOpenKeyEx(hk, key, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &nhk); 63656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 63756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, "WINREG: Could not open key '" TSTR 63856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "' for subkey deletion: error 0x%x (%d)", key, 63956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (unsigned int) ret, (int) GetLastError()); 64056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return 0; 64156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 64256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 64356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson for (i = 0; ; i++) { 64456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson TCHAR name[255]; 64556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DWORD namelen; 64656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 64756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson namelen = 255; 64856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL, 64956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson NULL); 65056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 65156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret == ERROR_NO_MORE_ITEMS) 65256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 65356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 65456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 65556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x (%d)", 65656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (unsigned int) ret, (int) GetLastError()); 65756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson break; 65856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 65956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 66056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (namelen >= 255) 66156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson namelen = 255 - 1; 66256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson name[namelen] = TEXT('\0'); 66356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 66456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ret = RegDeleteKey(nhk, name); 66556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ret != ERROR_SUCCESS) { 66656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_printf(MSG_DEBUG, "RegDeleteKey failed: 0x%x (%d)", 66756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson (unsigned int) ret, (int) GetLastError()); 66856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson errors++; 66956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 67056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 67156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 67256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson RegCloseKey(nhk); 67356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 67456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return errors ? -1 : 0; 67556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 67656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 67756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 67856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_str(HKEY hk, const char *field, struct wpa_ssid *ssid) 67956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 68056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *value = wpa_config_get(ssid, field); 68156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == NULL) 68256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 68356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, field, value); 68456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(value); 68556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 68656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 68756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 68856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_int(HKEY hk, const char *field, int value, int def) 68956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 69056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char val[20]; 69156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == def) 69256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 69356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_snprintf(val, sizeof(val), "%d", value); 69456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, field, val); 69556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 69656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 69756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 69856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_bssid(HKEY hk, struct wpa_ssid *ssid) 69956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 70056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *value = wpa_config_get(ssid, "bssid"); 70156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == NULL) 70256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 70356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "bssid", value); 70456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(value); 70556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 70656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 70756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 70856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_psk(HKEY hk, struct wpa_ssid *ssid) 70956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 71056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *value = wpa_config_get(ssid, "psk"); 71156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == NULL) 71256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 71356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "psk", value); 71456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(value); 71556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 71656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 71756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 71856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_proto(HKEY hk, struct wpa_ssid *ssid) 71956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 72056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *value; 72156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 72256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ssid->proto == DEFAULT_PROTO) 72356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 72456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 72556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson value = wpa_config_get(ssid, "proto"); 72656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == NULL) 72756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 72856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value[0]) 72956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "proto", value); 73056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(value); 73156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 73256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 73356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 73456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_key_mgmt(HKEY hk, struct wpa_ssid *ssid) 73556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 73656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *value; 73756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 73856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 73956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 74056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 74156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson value = wpa_config_get(ssid, "key_mgmt"); 74256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == NULL) 74356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 74456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value[0]) 74556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "key_mgmt", value); 74656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(value); 74756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 74856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 74956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 75056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_pairwise(HKEY hk, struct wpa_ssid *ssid) 75156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 75256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *value; 75356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 75456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 75556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 75656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 75756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson value = wpa_config_get(ssid, "pairwise"); 75856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == NULL) 75956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 76056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value[0]) 76156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "pairwise", value); 76256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(value); 76356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 76456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 76556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 76656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_group(HKEY hk, struct wpa_ssid *ssid) 76756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 76856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *value; 76956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 77056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ssid->group_cipher == DEFAULT_GROUP) 77156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 77256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 77356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson value = wpa_config_get(ssid, "group"); 77456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == NULL) 77556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 77656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value[0]) 77756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "group", value); 77856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(value); 77956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 78056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 78156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 78256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_auth_alg(HKEY hk, struct wpa_ssid *ssid) 78356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 78456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *value; 78556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 78656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ssid->auth_alg == 0) 78756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 78856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 78956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson value = wpa_config_get(ssid, "auth_alg"); 79056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == NULL) 79156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 79256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value[0]) 79356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "auth_alg", value); 79456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(value); 79556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 79656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 79756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 79856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#ifdef IEEE8021X_EAPOL 79956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_eap(HKEY hk, struct wpa_ssid *ssid) 80056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 80156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson char *value; 80256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 80356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson value = wpa_config_get(ssid, "eap"); 80456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value == NULL) 80556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 80656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 80756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (value[0]) 80856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson wpa_config_write_reg_string(hk, "eap", value); 80956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson os_free(value); 81056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 81156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson#endif /* IEEE8021X_EAPOL */ 81256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 81356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 81456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonstatic void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid) 81556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson{ 816 char field[20], *value; 817 818 os_snprintf(field, sizeof(field), "wep_key%d", idx); 819 value = wpa_config_get(ssid, field); 820 if (value) { 821 wpa_config_write_reg_string(hk, field, value); 822 os_free(value); 823 } 824} 825 826 827static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id) 828{ 829 int i, errors = 0; 830 HKEY nhk, netw; 831 LONG ret; 832 TCHAR name[5]; 833 834 ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_CREATE_SUB_KEY, &nhk); 835 if (ret != ERROR_SUCCESS) { 836 wpa_printf(MSG_DEBUG, "WINREG: Could not open networks key " 837 "for subkey addition: error 0x%x (%d)", 838 (unsigned int) ret, (int) GetLastError()); 839 return 0; 840 } 841 842#ifdef UNICODE 843 wsprintf(name, L"%04d", id); 844#else /* UNICODE */ 845 os_snprintf(name, sizeof(name), "%04d", id); 846#endif /* UNICODE */ 847 ret = RegCreateKeyEx(nhk, name, 0, NULL, 0, KEY_WRITE, NULL, &netw, 848 NULL); 849 RegCloseKey(nhk); 850 if (ret != ERROR_SUCCESS) { 851 wpa_printf(MSG_DEBUG, "WINREG: Could not add network key '%s':" 852 " error 0x%x (%d)", 853 name, (unsigned int) ret, (int) GetLastError()); 854 return -1; 855 } 856 857#define STR(t) write_str(netw, #t, ssid) 858#define INT(t) write_int(netw, #t, ssid->t, 0) 859#define INTe(t) write_int(netw, #t, ssid->eap.t, 0) 860#define INT_DEF(t, def) write_int(netw, #t, ssid->t, def) 861#define INT_DEFe(t, def) write_int(netw, #t, ssid->eap.t, def) 862 863 STR(ssid); 864 INT(scan_ssid); 865 write_bssid(netw, ssid); 866 write_psk(netw, ssid); 867 write_proto(netw, ssid); 868 write_key_mgmt(netw, ssid); 869 write_pairwise(netw, ssid); 870 write_group(netw, ssid); 871 write_auth_alg(netw, ssid); 872#ifdef IEEE8021X_EAPOL 873 write_eap(netw, ssid); 874 STR(identity); 875 STR(anonymous_identity); 876 STR(password); 877 STR(ca_cert); 878 STR(ca_path); 879 STR(client_cert); 880 STR(private_key); 881 STR(private_key_passwd); 882 STR(dh_file); 883 STR(subject_match); 884 STR(altsubject_match); 885 STR(ca_cert2); 886 STR(ca_path2); 887 STR(client_cert2); 888 STR(private_key2); 889 STR(private_key2_passwd); 890 STR(dh_file2); 891 STR(subject_match2); 892 STR(altsubject_match2); 893 STR(phase1); 894 STR(phase2); 895 STR(pcsc); 896 STR(pin); 897 STR(engine_id); 898 STR(key_id); 899 STR(cert_id); 900 STR(ca_cert_id); 901 STR(key2_id); 902 STR(pin2); 903 STR(engine2_id); 904 STR(cert2_id); 905 STR(ca_cert2_id); 906 INTe(engine); 907 INTe(engine2); 908 INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 909#endif /* IEEE8021X_EAPOL */ 910 for (i = 0; i < 4; i++) 911 write_wep_key(netw, i, ssid); 912 INT(wep_tx_keyidx); 913 INT(priority); 914#ifdef IEEE8021X_EAPOL 915 INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 916 STR(pac_file); 917 INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE); 918#endif /* IEEE8021X_EAPOL */ 919 INT(mode); 920 INT(proactive_key_caching); 921 INT(disabled); 922 INT(peerkey); 923#ifdef CONFIG_IEEE80211W 924 INT(ieee80211w); 925#endif /* CONFIG_IEEE80211W */ 926 STR(id_str); 927 928#undef STR 929#undef INT 930#undef INT_DEF 931 932 RegCloseKey(netw); 933 934 return errors ? -1 : 0; 935} 936 937 938static int wpa_config_write_blob(HKEY hk, struct wpa_config_blob *blob) 939{ 940 HKEY bhk; 941 LONG ret; 942 TCHAR *name; 943 944 ret = RegCreateKeyEx(hk, TEXT("blobs"), 0, NULL, 0, KEY_WRITE, NULL, 945 &bhk, NULL); 946 if (ret != ERROR_SUCCESS) { 947 wpa_printf(MSG_DEBUG, "WINREG: Could not add blobs key: " 948 "error 0x%x (%d)", 949 (unsigned int) ret, (int) GetLastError()); 950 return -1; 951 } 952 953 name = wpa_strdup_tchar(blob->name); 954 ret = RegSetValueEx(bhk, name, 0, REG_BINARY, blob->data, 955 blob->len); 956 if (ret != ERROR_SUCCESS) { 957 wpa_printf(MSG_ERROR, "WINREG: Failed to set blob %s': " 958 "error 0x%x (%d)", blob->name, (unsigned int) ret, 959 (int) GetLastError()); 960 RegCloseKey(bhk); 961 os_free(name); 962 return -1; 963 } 964 os_free(name); 965 966 RegCloseKey(bhk); 967 968 return 0; 969} 970 971 972int wpa_config_write(const char *name, struct wpa_config *config) 973{ 974 TCHAR buf[256]; 975 HKEY hk; 976 LONG ret; 977 int errors = 0; 978 struct wpa_ssid *ssid; 979 struct wpa_config_blob *blob; 980 int id; 981 982 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 983 984#ifdef UNICODE 985 _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name); 986#else /* UNICODE */ 987 os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name); 988#endif /* UNICODE */ 989 990 ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_SET_VALUE | DELETE, &hk); 991 if (ret != ERROR_SUCCESS) { 992 wpa_printf(MSG_ERROR, "Could not open wpa_supplicant " 993 "configuration registry %s: error %d", buf, 994 (int) GetLastError()); 995 return -1; 996 } 997 998 if (wpa_config_write_global(config, hk)) { 999 wpa_printf(MSG_ERROR, "Failed to write global configuration " 1000 "data"); 1001 errors++; 1002 } 1003 1004 wpa_config_delete_subkeys(hk, TEXT("networks")); 1005 for (ssid = config->ssid, id = 0; ssid; ssid = ssid->next, id++) { 1006 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS) 1007 continue; /* do not save temporary WPS networks */ 1008 if (wpa_config_write_network(hk, ssid, id)) 1009 errors++; 1010 } 1011 1012 RegDeleteKey(hk, TEXT("blobs")); 1013 for (blob = config->blobs; blob; blob = blob->next) { 1014 if (wpa_config_write_blob(hk, blob)) 1015 errors++; 1016 } 1017 1018 RegCloseKey(hk); 1019 1020 wpa_printf(MSG_DEBUG, "Configuration '%s' written %ssuccessfully", 1021 name, errors ? "un" : ""); 1022 return errors ? -1 : 0; 1023} 1024