18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / Configuration backend: Windows registry
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This file implements a configuration backend for Windows registry. All the
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration information is stored in the registry and the format for
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * network configuration fields is same as described in the sample
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration file, wpa_supplicant.conf.
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Configuration data is in
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * \a HKEY_LOCAL_MACHINE\\SOFTWARE\\%wpa_supplicant\\configs
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * key. Each configuration profile has its own key under this. In terms of text
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * files, each profile would map to a separate text file with possibly multiple
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * networks. Under each profile, there is a networks key that lists all
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * networks as a subkey. Each network has set of values in the same way as
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * network block in the configuration file. In addition, blobs subkey has
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * possible blobs as values.
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Example network configuration block:
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * \verbatim
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtHKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs\test\networks\0000
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   ssid="example"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   key_mgmt=WPA-PSK
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt\endverbatim
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "uuid.h"
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef WPA_KEY_ROOT
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define WPA_KEY_ROOT HKEY_LOCAL_MACHINE
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef WPA_KEY_PREFIX
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant")
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TSTR "%S"
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TSTR "%s"
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_read_blobs(struct wpa_config *config, HKEY hk)
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config_blob *blob;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int errors = 0;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY bhk;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD i;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegOpenKeyEx(hk, TEXT("blobs"), 0, KEY_QUERY_VALUE, &bhk);
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config "
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "blobs key");
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* assume no blobs */
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TNAMELEN 255
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		TCHAR name[TNAMELEN];
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char data[4096];
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DWORD namelen, datalen, type;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		namelen = TNAMELEN;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		datalen = sizeof(data);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegEnumValue(bhk, i, name, &namelen, NULL, &type,
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (LPBYTE) data, &datalen);
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret == ERROR_NO_MORE_ITEMS)
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "RegEnumValue failed: 0x%x",
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned int) ret);
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (namelen >= TNAMELEN)
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			namelen = TNAMELEN - 1;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[namelen] = TEXT('\0');
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_unicode2ascii_inplace(name);
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (datalen >= sizeof(data))
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			datalen = sizeof(data) - 1;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_MSGDUMP, "blob %d: field='%s' len %d",
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) i, name, (int) datalen);
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		blob = os_zalloc(sizeof(*blob));
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (blob == NULL) {
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		blob->name = os_strdup((char *) name);
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		blob->data = os_malloc(datalen);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (blob->name == NULL || blob->data == NULL) {
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_config_free_blob(blob);
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(blob->data, data, datalen);
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		blob->len = datalen;
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_set_blob(config, blob);
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(bhk);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_read_reg_dword(HKEY hk, const TCHAR *name, int *_val)
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD val, buflen;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buflen = sizeof(val);
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) &val, &buflen);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, TSTR "=%d", name, (int) val);
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*_val = val;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_config_read_reg_string(HKEY hk, const TCHAR *name)
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD buflen;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR *val;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buflen = 0;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegQueryValueEx(hk, name, NULL, NULL, NULL, &buflen);
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS)
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	val = os_malloc(buflen);
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val == NULL)
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) val, &buflen);
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(val);
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_unicode2ascii_inplace(val);
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, TSTR "=%s", name, (char *) val);
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return (char *) val;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_read_global_uuid(struct wpa_config *config, HKEY hk)
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *str;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	str = wpa_config_read_reg_string(hk, TEXT("uuid"));
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (str == NULL)
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (uuid_str2bin(str, config->uuid))
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -1;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(str);
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_read_global_os_version(struct wpa_config *config,
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     HKEY hk)
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *str;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	str = wpa_config_read_reg_string(hk, TEXT("os_version"));
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (str == NULL)
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(str, config->os_version, 4))
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -1;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(str);
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_read_global(struct wpa_config *config, HKEY hk)
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int errors = 0;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("ap_scan"), &config->ap_scan);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("fast_reauth"),
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  &config->fast_reauth);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"),
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (int *) &config->dot11RSNAConfigPMKLifetime);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk,
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  TEXT("dot11RSNAConfigPMKReauthThreshold"),
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (int *)
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  &config->dot11RSNAConfigPMKReauthThreshold);
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"),
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (int *) &config->dot11RSNAConfigSATimeout);
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("update_config"),
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  &config->update_config);
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_config_read_reg_dword(hk, TEXT("eapol_version"),
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      &config->eapol_version) == 0) {
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (config->eapol_version < 1 ||
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    config->eapol_version > 2) {
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Invalid EAPOL version (%d)",
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->eapol_version);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->ctrl_interface = wpa_config_read_reg_string(
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hk, TEXT("ctrl_interface"));
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_config_read_global_uuid(config, hk))
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->device_name = wpa_config_read_reg_string(
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hk, TEXT("device_name"));
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->manufacturer = wpa_config_read_reg_string(
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hk, TEXT("manufacturer"));
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->model_name = wpa_config_read_reg_string(
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hk, TEXT("model_name"));
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->serial_number = wpa_config_read_reg_string(
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hk, TEXT("serial_number"));
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *t = wpa_config_read_reg_string(
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hk, TEXT("device_type"));
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (t && wps_dev_type_str2bin(t, config->device_type))
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(t);
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->config_methods = wpa_config_read_reg_string(
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hk, TEXT("config_methods"));
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_config_read_global_os_version(config, hk))
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("wps_cred_processing"),
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  &config->wps_cred_processing);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->p2p_ssid_postfix = wpa_config_read_reg_string(
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hk, TEXT("p2p_ssid_postfix"));
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("p2p_group_idle"),
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (int *) &config->p2p_group_idle);
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("bss_max_count"),
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (int *) &config->bss_max_count);
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("filter_ssids"),
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  &config->filter_ssids);
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("max_num_sta"),
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (int *) &config->max_num_sta);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("disassoc_low_ack"),
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (int *) &config->disassoc_low_ack);
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw,
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 int id)
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY nhk;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD i;
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int errors = 0;
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegOpenKeyEx(hk, netw, 0, KEY_QUERY_VALUE, &nhk);
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config "
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "network '" TSTR "'", netw);
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Start of a new network '" TSTR "'", netw);
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = os_zalloc(sizeof(*ssid));
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL) {
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RegCloseKey(nhk);
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->id = id;
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_set_network_defaults(ssid);
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		TCHAR name[255], data[1024];
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DWORD namelen, datalen, type;
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		namelen = 255;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		datalen = sizeof(data);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegEnumValue(nhk, i, name, &namelen, NULL, &type,
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (LPBYTE) data, &datalen);
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret == ERROR_NO_MORE_ITEMS)
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "RegEnumValue failed: 0x%x",
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned int) ret);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (namelen >= 255)
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			namelen = 255 - 1;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[namelen] = TEXT('\0');
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (datalen >= 1024)
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			datalen = 1024 - 1;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data[datalen] = TEXT('\0');
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_unicode2ascii_inplace(name);
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_unicode2ascii_inplace(data);
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_config_set(ssid, (char *) name, (char *) data, 0) < 0)
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(nhk);
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->passphrase) {
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid->psk_set) {
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Both PSK and passphrase "
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "configured for network '" TSTR "'.", netw);
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_update_psk(ssid);
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set) {
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "WPA-PSK accepted for key management, "
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "but no PSK configured for network '" TSTR "'.",
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   netw);
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) {
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Group cipher cannot be stronger than the pairwise cipher. */
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Removed CCMP from group cipher "
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "list since it was not allowed for pairwise "
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "cipher for network '" TSTR "'.", netw);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->group_cipher &= ~WPA_CIPHER_CCMP;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (errors) {
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_free_ssid(ssid);
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = NULL;
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ssid;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_read_networks(struct wpa_config *config, HKEY hk)
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY nhk;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int errors = 0;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD i;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_ENUMERATE_SUB_KEYS,
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   &nhk);
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Could not open wpa_supplicant networks "
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "registry key");
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		TCHAR name[255];
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DWORD namelen;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		namelen = 255;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL,
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   NULL);
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret == ERROR_NO_MORE_ITEMS)
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x",
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned int) ret);
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (namelen >= 255)
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			namelen = 255 - 1;
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[namelen] = '\0';
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = wpa_config_read_network(nhk, name, i);
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid == NULL) {
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to parse network "
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "profile '%s'.", name);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (head == NULL) {
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			head = tail = ssid;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tail->next = ssid;
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tail = ssid;
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_config_add_prio_network(config, ssid)) {
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to add network profile "
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "'%s' to priority list.", name);
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(nhk);
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->ssid = head;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_config * wpa_config_read(const char *name)
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR buf[256];
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int errors = 0;
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config *config;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY hk;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config = wpa_config_alloc_empty(NULL, NULL);
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Reading configuration profile '%s'", name);
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name);
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name);
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_QUERY_VALUE, &hk);
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Could not open wpa_supplicant "
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "configuration registry HKLM\\" TSTR, buf);
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(config);
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_config_read_global(config, hk))
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_config_read_networks(config, hk))
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_config_read_blobs(config, hk))
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_debug_dump_networks(config);
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(hk);
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (errors) {
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_free(config);
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config = NULL;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config;
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_write_reg_dword(HKEY hk, const TCHAR *name, int val,
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      int def)
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD _val = val;
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val == def) {
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RegDeleteValue(hk, name);
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegSetValueEx(hk, name, 0, REG_DWORD, (LPBYTE) &_val,
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sizeof(_val));
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "WINREG: Failed to set %s=%d: error %d",
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   name, val, (int) GetLastError());
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_write_reg_string(HKEY hk, const char *name,
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const char *val)
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR *_name, *_val;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_name = wpa_strdup_tchar(name);
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_name == NULL)
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (val == NULL) {
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RegDeleteValue(hk, _name);
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_name);
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_val = wpa_strdup_tchar(val);
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_val == NULL) {
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_name);
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegSetValueEx(hk, _name, 0, REG_SZ, (BYTE *) _val,
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    (os_strlen(val) + 1) * sizeof(TCHAR));
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "WINREG: Failed to set %s='%s': "
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "error %d", name, val, (int) GetLastError());
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_name);
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_val);
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(_name);
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(_val);
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_write_global(struct wpa_config *config, HKEY hk)
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "ctrl_interface",
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    config->ctrl_interface);
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("eapol_version"),
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->eapol_version,
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   DEFAULT_EAPOL_VERSION);
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("ap_scan"), config->ap_scan,
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   DEFAULT_AP_SCAN);
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("fast_reauth"),
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->fast_reauth, DEFAULT_FAST_REAUTH);
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"),
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->dot11RSNAConfigPMKLifetime, 0);
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk,
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TEXT("dot11RSNAConfigPMKReauthThreshold"),
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->dot11RSNAConfigPMKReauthThreshold,
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   0);
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"),
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->dot11RSNAConfigSATimeout, 0);
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("update_config"),
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->update_config,
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   0);
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!is_nil_uuid(config->uuid)) {
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char buf[40];
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		uuid_bin2str(config->uuid, buf, sizeof(buf));
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, "uuid", buf);
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "device_name", config->device_name);
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "manufacturer", config->manufacturer);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "model_name", config->model_name);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "model_number", config->model_number);
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "serial_number",
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    config->serial_number);
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char _buf[WPS_DEV_TYPE_BUFSIZE], *buf;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = wps_dev_type_bin2str(config->device_type,
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   _buf, sizeof(_buf));
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, "device_type", buf);
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "config_methods",
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    config->config_methods);
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WPA_GET_BE32(config->os_version)) {
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char vbuf[10];
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(vbuf, sizeof(vbuf), "%08x",
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    WPA_GET_BE32(config->os_version));
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, "os_version", vbuf);
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("wps_cred_processing"),
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->wps_cred_processing, 0);
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "p2p_ssid_postfix",
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    config->p2p_ssid_postfix);
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("p2p_group_idle"),
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->p2p_group_idle, 0);
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("bss_max_count"),
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->bss_max_count,
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   DEFAULT_BSS_MAX_COUNT);
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("filter_ssids"),
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->filter_ssids, 0);
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("max_num_sta"),
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->max_num_sta, DEFAULT_MAX_NUM_STA);
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("disassoc_low_ack"),
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   config->disassoc_low_ack, 0);
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_delete_subkeys(HKEY hk, const TCHAR *key)
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY nhk;
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, errors = 0;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegOpenKeyEx(hk, key, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &nhk);
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WINREG: Could not open key '" TSTR
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "' for subkey deletion: error 0x%x (%d)", key,
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned int) ret, (int) GetLastError());
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		TCHAR name[255];
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DWORD namelen;
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		namelen = 255;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL,
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   NULL);
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret == ERROR_NO_MORE_ITEMS)
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x (%d)",
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned int) ret, (int) GetLastError());
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (namelen >= 255)
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			namelen = 255 - 1;
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[namelen] = TEXT('\0');
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegDeleteKey(nhk, name);
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "RegDeleteKey failed: 0x%x (%d)",
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned int) ret, (int) GetLastError());
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(nhk);
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_str(HKEY hk, const char *field, struct wpa_ssid *ssid)
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value = wpa_config_get(ssid, field);
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, field, value);
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(value);
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_int(HKEY hk, const char *field, int value, int def)
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char val[20];
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == def)
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(val, sizeof(val), "%d", value);
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, field, val);
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_bssid(HKEY hk, struct wpa_ssid *ssid)
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value = wpa_config_get(ssid, "bssid");
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "bssid", value);
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(value);
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_psk(HKEY hk, struct wpa_ssid *ssid)
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value = wpa_config_get(ssid, "psk");
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_write_reg_string(hk, "psk", value);
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(value);
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_proto(HKEY hk, struct wpa_ssid *ssid)
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->proto == DEFAULT_PROTO)
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = wpa_config_get(ssid, "proto");
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value[0])
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, "proto", value);
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(value);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_key_mgmt(HKEY hk, struct wpa_ssid *ssid)
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value;
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = wpa_config_get(ssid, "key_mgmt");
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value[0])
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, "key_mgmt", value);
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(value);
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_pairwise(HKEY hk, struct wpa_ssid *ssid)
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value;
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->pairwise_cipher == DEFAULT_PAIRWISE)
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = wpa_config_get(ssid, "pairwise");
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value[0])
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, "pairwise", value);
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(value);
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_group(HKEY hk, struct wpa_ssid *ssid)
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value;
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->group_cipher == DEFAULT_GROUP)
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = wpa_config_get(ssid, "group");
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value[0])
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, "group", value);
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(value);
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_auth_alg(HKEY hk, struct wpa_ssid *ssid)
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value;
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->auth_alg == 0)
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = wpa_config_get(ssid, "auth_alg");
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value[0])
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, "auth_alg", value);
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(value);
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_eap(HKEY hk, struct wpa_ssid *ssid)
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *value;
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = wpa_config_get(ssid, "eap");
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value == NULL)
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value[0])
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, "eap", value);
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(value);
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid)
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char field[20], *value;
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(field, sizeof(field), "wep_key%d", idx);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	value = wpa_config_get(ssid, field);
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (value) {
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write_reg_string(hk, field, value);
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(value);
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id)
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, errors = 0;
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY nhk, netw;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR name[5];
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_CREATE_SUB_KEY, &nhk);
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WINREG: Could not open networks key "
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "for subkey addition: error 0x%x (%d)",
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned int) ret, (int) GetLastError());
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wsprintf(name, L"%04d", id);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(name, sizeof(name), "%04d", id);
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegCreateKeyEx(nhk, name, 0, NULL, 0, KEY_WRITE, NULL, &netw,
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL);
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(nhk);
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WINREG: Could not add network key '%s':"
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " error 0x%x (%d)",
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   name, (unsigned int) ret, (int) GetLastError());
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STR(t) write_str(netw, #t, ssid)
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INT(t) write_int(netw, #t, ssid->t, 0)
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTe(t) write_int(netw, #t, ssid->eap.t, 0)
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INT_DEF(t, def) write_int(netw, #t, ssid->t, def)
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INT_DEFe(t, def) write_int(netw, #t, ssid->eap.t, def)
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(ssid);
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT(scan_ssid);
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	write_bssid(netw, ssid);
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	write_psk(netw, ssid);
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	write_proto(netw, ssid);
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	write_key_mgmt(netw, ssid);
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	write_pairwise(netw, ssid);
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	write_group(netw, ssid);
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	write_auth_alg(netw, ssid);
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	write_eap(netw, ssid);
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(identity);
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(anonymous_identity);
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(password);
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(ca_cert);
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(ca_path);
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(client_cert);
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(private_key);
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(private_key_passwd);
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(dh_file);
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(subject_match);
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(altsubject_match);
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(ca_cert2);
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(ca_path2);
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(client_cert2);
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(private_key2);
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(private_key2_passwd);
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(dh_file2);
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(subject_match2);
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(altsubject_match2);
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(phase1);
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(phase2);
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(pcsc);
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(pin);
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(engine_id);
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(key_id);
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(cert_id);
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(ca_cert_id);
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(key2_id);
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(pin2);
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(engine2_id);
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(cert2_id);
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(ca_cert2_id);
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INTe(engine);
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INTe(engine2);
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 4; i++)
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		write_wep_key(netw, i, ssid);
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT(wep_tx_keyidx);
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT(priority);
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(pac_file);
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE);
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT(mode);
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT(proactive_key_caching);
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT(disabled);
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT(peerkey);
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT(ieee80211w);
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	STR(id_str);
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef STR
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef INT
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef INT_DEF
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(netw);
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_config_write_blob(HKEY hk, struct wpa_config_blob *blob)
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY bhk;
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR *name;
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegCreateKeyEx(hk, TEXT("blobs"), 0, NULL, 0, KEY_WRITE, NULL,
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     &bhk, NULL);
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WINREG: Could not add blobs key: "
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "error 0x%x (%d)",
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned int) ret, (int) GetLastError());
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	name = wpa_strdup_tchar(blob->name);
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegSetValueEx(bhk, name, 0, REG_BINARY, blob->data,
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    blob->len);
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "WINREG: Failed to set blob %s': "
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "error 0x%x (%d)", blob->name, (unsigned int) ret,
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RegCloseKey(bhk);
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(name);
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(name);
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(bhk);
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_config_write(const char *name, struct wpa_config *config)
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR buf[256];
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY hk;
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int errors = 0;
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config_blob *blob;
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int id;
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name);
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name);
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_SET_VALUE | DELETE, &hk);
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Could not open wpa_supplicant "
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "configuration registry %s: error %d", buf,
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_config_write_global(config, hk)) {
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to write global configuration "
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "data");
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		errors++;
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_delete_subkeys(hk, TEXT("networks"));
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (ssid = config->ssid, id = 0; ssid; ssid = ssid->next, id++) {
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue; /* do not save temporary WPS networks */
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_config_write_network(hk, ssid, id))
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegDeleteKey(hk, TEXT("blobs"));
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (blob = config->blobs; blob; blob = blob->next) {
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_config_write_blob(hk, blob))
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			errors++;
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(hk);
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Configuration '%s' written %ssuccessfully",
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   name, errors ? "un" : "");
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return errors ? -1 : 0;
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1018