782 lines
21 KiB
C
782 lines
21 KiB
C
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 2000.
|
|
//
|
|
// File: spreg.c
|
|
//
|
|
// Contents: Schannel registry management routines.
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 11-24-97 jbanes Enabled TLS
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <sslp.h>
|
|
#include "spreg.h"
|
|
|
|
HKEY g_hkBase = NULL;
|
|
HANDLE g_hParamEvent = NULL;
|
|
HANDLE g_hWait = NULL;
|
|
|
|
HKEY g_hkFipsBase = NULL;
|
|
HANDLE g_hFipsParamEvent = NULL;
|
|
HANDLE g_hFipsWait = NULL;
|
|
|
|
BOOL g_fManualCredValidation = MANUAL_CRED_VALIDATION_SETTING;
|
|
BOOL g_PctClientDisabledByDefault = PCT_CLIENT_DISABLED_SETTING;
|
|
BOOL g_Ssl2ClientDisabledByDefault = SSL2_CLIENT_DISABLED_SETTING;
|
|
|
|
DWORD g_dwEventLogging = DEFAULT_EVENT_LOGGING_SETTING;
|
|
DWORD g_ProtEnabled = DEFAULT_ENABLED_PROTOCOLS_SETTING;
|
|
|
|
BOOL g_fFipsMode = FALSE;
|
|
BOOL g_fFranceLocale = FALSE;
|
|
|
|
typedef struct enamap
|
|
{
|
|
TCHAR *pKey;
|
|
DWORD Mask;
|
|
} enamap;
|
|
|
|
enamap g_ProtMap[] =
|
|
{
|
|
{SP_REG_KEY_UNIHELLO TEXT("\\") SP_REG_KEY_CLIENT, SP_PROT_UNI_CLIENT},
|
|
{SP_REG_KEY_UNIHELLO TEXT("\\") SP_REG_KEY_SERVER, SP_PROT_UNI_SERVER},
|
|
{SP_REG_KEY_PCT1 TEXT("\\") SP_REG_KEY_CLIENT, SP_PROT_PCT1_CLIENT},
|
|
{SP_REG_KEY_PCT1 TEXT("\\") SP_REG_KEY_SERVER, SP_PROT_PCT1_SERVER},
|
|
{SP_REG_KEY_SSL2 TEXT("\\") SP_REG_KEY_CLIENT, SP_PROT_SSL2_CLIENT},
|
|
{SP_REG_KEY_SSL2 TEXT("\\") SP_REG_KEY_SERVER, SP_PROT_SSL2_SERVER},
|
|
{SP_REG_KEY_SSL3 TEXT("\\") SP_REG_KEY_CLIENT, SP_PROT_SSL3_CLIENT},
|
|
{SP_REG_KEY_SSL3 TEXT("\\") SP_REG_KEY_SERVER, SP_PROT_SSL3_SERVER},
|
|
{SP_REG_KEY_TLS1 TEXT("\\") SP_REG_KEY_CLIENT, SP_PROT_TLS1_CLIENT},
|
|
{SP_REG_KEY_TLS1 TEXT("\\") SP_REG_KEY_SERVER, SP_PROT_TLS1_SERVER}
|
|
};
|
|
|
|
VOID
|
|
SslWatchParamKey(
|
|
PVOID pCtxt,
|
|
BOOLEAN fWaitStatus);
|
|
|
|
VOID
|
|
FipsWatchParamKey(
|
|
PVOID pCtxt,
|
|
BOOLEAN fWaitStatus);
|
|
|
|
BOOL
|
|
SslReadRegOptions(
|
|
BOOL fFirstTime);
|
|
|
|
BOOL SPLoadRegOptions(void)
|
|
{
|
|
g_hParamEvent = CreateEvent(NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
SslWatchParamKey(g_hParamEvent, FALSE);
|
|
|
|
g_hFipsParamEvent = CreateEvent(NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
FipsWatchParamKey(g_hFipsParamEvent, FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void SPUnloadRegOptions(void)
|
|
{
|
|
if (NULL != g_hWait)
|
|
{
|
|
RtlDeregisterWait(g_hWait);
|
|
g_hWait = NULL;
|
|
}
|
|
|
|
if(NULL != g_hkBase)
|
|
{
|
|
RegCloseKey(g_hkBase);
|
|
}
|
|
|
|
if(NULL != g_hParamEvent)
|
|
{
|
|
CloseHandle(g_hParamEvent);
|
|
}
|
|
|
|
if (NULL != g_hFipsWait)
|
|
{
|
|
RtlDeregisterWait(g_hFipsWait);
|
|
g_hFipsWait = NULL;
|
|
}
|
|
|
|
if(NULL != g_hkFipsBase)
|
|
{
|
|
RegCloseKey(g_hkFipsBase);
|
|
}
|
|
|
|
if(NULL != g_hFipsParamEvent)
|
|
{
|
|
CloseHandle(g_hFipsParamEvent);
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
ReadRegistrySetting(
|
|
HKEY hReadKey,
|
|
HKEY hWriteKey,
|
|
LPCTSTR pszValueName,
|
|
DWORD * pdwValue,
|
|
DWORD dwDefaultValue)
|
|
{
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
DWORD dwOriginalValue = *pdwValue;
|
|
|
|
dwSize = sizeof(DWORD);
|
|
if(RegQueryValueEx(hReadKey,
|
|
pszValueName,
|
|
NULL,
|
|
&dwType,
|
|
(PUCHAR)pdwValue,
|
|
&dwSize) != STATUS_SUCCESS)
|
|
{
|
|
*pdwValue = dwDefaultValue;
|
|
|
|
if(hWriteKey)
|
|
{
|
|
RegSetValueEx(hWriteKey,
|
|
pszValueName,
|
|
0,
|
|
REG_DWORD,
|
|
(PUCHAR)pdwValue,
|
|
sizeof(DWORD));
|
|
}
|
|
}
|
|
|
|
return (dwOriginalValue != *pdwValue);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Name: SslWatchParamKey
|
|
//
|
|
// Synopsis: Sets RegNotifyChangeKeyValue() on param key, initializes
|
|
// debug level, then utilizes thread pool to wait on
|
|
// changes to this registry key. Enables dynamic debug
|
|
// level changes, as this function will also be callback
|
|
// if registry key modified.
|
|
//
|
|
// Arguments: pCtxt is actually a HANDLE to an event. This event
|
|
// will be triggered when key is modified.
|
|
//
|
|
// Notes: .
|
|
//
|
|
VOID
|
|
SslWatchParamKey(
|
|
PVOID pCtxt,
|
|
BOOLEAN fWaitStatus)
|
|
{
|
|
NTSTATUS Status;
|
|
LONG lRes = ERROR_SUCCESS;
|
|
BOOL fFirstTime = FALSE;
|
|
DWORD disp;
|
|
|
|
if(g_hkBase == NULL)
|
|
{
|
|
// First time we've been called.
|
|
Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
|
SP_REG_KEY_BASE,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&g_hkBase,
|
|
&disp);
|
|
if(Status)
|
|
{
|
|
DebugLog((DEB_WARN,"Failed to open SCHANNEL key: 0x%x\n", Status));
|
|
return;
|
|
}
|
|
|
|
fFirstTime = TRUE;
|
|
}
|
|
|
|
if(pCtxt != NULL)
|
|
{
|
|
if (NULL != g_hWait)
|
|
{
|
|
Status = RtlDeregisterWait(g_hWait);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
DebugLog((DEB_WARN, "Failed to Deregister wait on registry key: 0x%x\n", Status));
|
|
goto Reregister;
|
|
}
|
|
}
|
|
|
|
lRes = RegNotifyChangeKeyValue(
|
|
g_hkBase,
|
|
TRUE,
|
|
REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
|
|
(HANDLE)pCtxt,
|
|
TRUE);
|
|
|
|
if (ERROR_SUCCESS != lRes)
|
|
{
|
|
DebugLog((DEB_ERROR,"Debug RegNotify setup failed: 0x%x\n", lRes));
|
|
// we're tanked now. No further notifications, so get this one
|
|
}
|
|
}
|
|
|
|
SslReadRegOptions(fFirstTime);
|
|
|
|
#if DBG
|
|
InitDebugSupport(g_hkBase);
|
|
#endif
|
|
|
|
Reregister:
|
|
|
|
if(pCtxt != NULL)
|
|
{
|
|
Status = RtlRegisterWait(&g_hWait,
|
|
(HANDLE)pCtxt,
|
|
SslWatchParamKey,
|
|
(HANDLE)pCtxt,
|
|
INFINITE,
|
|
WT_EXECUTEINPERSISTENTIOTHREAD|
|
|
WT_EXECUTEONLYONCE);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Name: FipsWatchParamKey
|
|
//
|
|
// Synopsis: Sets RegNotifyChangeKeyValue() on param key, initializes
|
|
// debug level, then utilizes thread pool to wait on
|
|
// changes to this registry key. Enables dynamic debug
|
|
// level changes, as this function will also be callback
|
|
// if registry key modified.
|
|
//
|
|
// Arguments: pCtxt is actually a HANDLE to an event. This event
|
|
// will be triggered when key is modified.
|
|
//
|
|
// Notes: .
|
|
//
|
|
VOID
|
|
FipsWatchParamKey(
|
|
PVOID pCtxt,
|
|
BOOLEAN fWaitStatus)
|
|
{
|
|
NTSTATUS Status;
|
|
LONG lRes = ERROR_SUCCESS;
|
|
DWORD disp;
|
|
|
|
if(g_hkFipsBase == NULL)
|
|
{
|
|
// First time we've been called.
|
|
Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
|
SP_REG_FIPS_BASE_KEY,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&g_hkFipsBase,
|
|
&disp);
|
|
if(Status)
|
|
{
|
|
DebugLog((DEB_WARN,"Failed to open FIPS key: 0x%x\n", Status));
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(pCtxt != NULL)
|
|
{
|
|
if (NULL != g_hFipsWait)
|
|
{
|
|
Status = RtlDeregisterWait(g_hFipsWait);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
DebugLog((DEB_WARN, "Failed to Deregister wait on registry key: 0x%x\n", Status));
|
|
goto Reregister;
|
|
}
|
|
}
|
|
|
|
lRes = RegNotifyChangeKeyValue(
|
|
g_hkFipsBase,
|
|
TRUE,
|
|
REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
|
|
(HANDLE)pCtxt,
|
|
TRUE);
|
|
|
|
if (ERROR_SUCCESS != lRes)
|
|
{
|
|
DebugLog((DEB_ERROR,"Debug RegNotify setup failed: 0x%x\n", lRes));
|
|
// we're tanked now. No further notifications, so get this one
|
|
}
|
|
}
|
|
|
|
SslReadRegOptions(FALSE);
|
|
|
|
Reregister:
|
|
|
|
if(pCtxt != NULL)
|
|
{
|
|
Status = RtlRegisterWait(&g_hFipsWait,
|
|
(HANDLE)pCtxt,
|
|
FipsWatchParamKey,
|
|
(HANDLE)pCtxt,
|
|
INFINITE,
|
|
WT_EXECUTEINPERSISTENTIOTHREAD|
|
|
WT_EXECUTEONLYONCE);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
SslReadRegOptions(
|
|
BOOL fFirstTime)
|
|
{
|
|
DWORD err;
|
|
DWORD dwType;
|
|
DWORD fVal;
|
|
DWORD dwSize;
|
|
DWORD dwValue;
|
|
HKEY hKey;
|
|
HKEY hWriteKey;
|
|
DWORD disp;
|
|
HKEY hSubKey;
|
|
DWORD i;
|
|
HKEY hkProtocols = NULL;
|
|
HKEY hkCiphers = NULL;
|
|
HKEY hkHashes = NULL;
|
|
HKEY hkKeyExch = NULL;
|
|
BOOL fFipsMode = FALSE;
|
|
BOOL fSettingsChanged = FALSE;
|
|
DWORD dwOriginalValue;
|
|
|
|
DebugLog((DEB_TRACE,"Load configuration parameters from registry.\n"));
|
|
|
|
|
|
// "FipsAlgorithmPolicy"
|
|
ReadRegistrySetting(
|
|
g_hkFipsBase,
|
|
0,
|
|
SP_REG_FIPS_POLICY,
|
|
&dwValue,
|
|
0);
|
|
if(dwValue == 1)
|
|
{
|
|
fFipsMode = TRUE;
|
|
}
|
|
if(fFipsMode != g_fFipsMode)
|
|
{
|
|
g_fFipsMode = fFipsMode;
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// Read top-level configuration options.
|
|
//
|
|
|
|
// Open top-level key that has write access.
|
|
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
SP_REG_KEY_BASE,
|
|
0,
|
|
KEY_READ | KEY_SET_VALUE,
|
|
&hWriteKey) != STATUS_SUCCESS)
|
|
{
|
|
hWriteKey = 0;
|
|
}
|
|
|
|
// "EventLogging"
|
|
if(ReadRegistrySetting(
|
|
g_hkBase,
|
|
hWriteKey,
|
|
SP_REG_VAL_EVENTLOG,
|
|
&g_dwEventLogging,
|
|
DEFAULT_EVENT_LOGGING_SETTING))
|
|
{
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
|
|
// "ManualCredValidation"
|
|
if(ReadRegistrySetting(
|
|
g_hkBase,
|
|
0,
|
|
SP_REG_VAL_MANUAL_CRED_VALIDATION,
|
|
&g_fManualCredValidation,
|
|
MANUAL_CRED_VALIDATION_SETTING))
|
|
{
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
|
|
// "ClientCacheTime"
|
|
if(ReadRegistrySetting(
|
|
g_hkBase,
|
|
0,
|
|
SP_REG_VAL_CLIENT_CACHE_TIME,
|
|
&SchannelCache.dwClientLifespan,
|
|
SP_CACHE_CLIENT_LIFESPAN))
|
|
{
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
|
|
// "ServerCacheTime"
|
|
if(ReadRegistrySetting(
|
|
g_hkBase,
|
|
0,
|
|
SP_REG_VAL_SERVER_CACHE_TIME,
|
|
&SchannelCache.dwServerLifespan,
|
|
SP_CACHE_SERVER_LIFESPAN))
|
|
{
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
|
|
// "MaximumCacheSize"
|
|
if(ReadRegistrySetting(
|
|
g_hkBase,
|
|
0,
|
|
SP_REG_VAL_MAXUMUM_CACHE_SIZE,
|
|
&SchannelCache.dwMaximumEntries,
|
|
SP_MAXIMUM_CACHE_ELEMENTS))
|
|
{
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
|
|
if(fFirstTime)
|
|
{
|
|
SchannelCache.dwCacheSize = SchannelCache.dwMaximumEntries;
|
|
}
|
|
|
|
// "MultipleProcessClientCache"
|
|
if(ReadRegistrySetting(
|
|
g_hkBase,
|
|
0,
|
|
SP_REG_VAL_MULTI_PROC_CLIENT_CACHE,
|
|
&g_fMultipleProcessClientCache,
|
|
FALSE))
|
|
{
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
|
|
if(hWriteKey)
|
|
{
|
|
RegCloseKey(hWriteKey);
|
|
hWriteKey = 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Enable/Disable Protocols
|
|
//
|
|
|
|
if(fFipsMode)
|
|
{
|
|
// Disable everything except TLS.
|
|
g_ProtEnabled = SP_PROT_TLS1;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwProtEnabled = DEFAULT_ENABLED_PROTOCOLS_SETTING;
|
|
|
|
err = RegCreateKeyEx( g_hkBase,
|
|
SP_REG_KEY_PROTOCOL,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&hkProtocols,
|
|
&disp);
|
|
|
|
if(err == ERROR_SUCCESS)
|
|
{
|
|
for(i=0; i < (sizeof(g_ProtMap)/sizeof(enamap)); i++)
|
|
{
|
|
if(g_ProtMap[i].Mask & SP_PROT_PCT1)
|
|
{
|
|
if(g_fFranceLocale)
|
|
{
|
|
// Don't allow PCT to be enabled in France.
|
|
continue;
|
|
}
|
|
}
|
|
|
|
err = RegCreateKeyEx( hkProtocols,
|
|
g_ProtMap[i].pKey,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&hKey,
|
|
&disp);
|
|
if(!err)
|
|
{
|
|
dwSize = sizeof(DWORD);
|
|
err = RegQueryValueEx(hKey, SP_REG_VAL_ENABLED, NULL, &dwType, (PUCHAR)&fVal, &dwSize);
|
|
|
|
if(!err)
|
|
{
|
|
if(fVal)
|
|
{
|
|
dwProtEnabled |= g_ProtMap[i].Mask;
|
|
}
|
|
else
|
|
{
|
|
dwProtEnabled &= ~g_ProtMap[i].Mask;
|
|
}
|
|
}
|
|
|
|
if(g_ProtMap[i].Mask & SP_PROT_PCT1_CLIENT)
|
|
{
|
|
// "DisabledByDefault"
|
|
ReadRegistrySetting(
|
|
hKey,
|
|
0,
|
|
SP_REG_VAL_DISABLED_BY_DEFAULT,
|
|
&g_PctClientDisabledByDefault,
|
|
PCT_CLIENT_DISABLED_SETTING);
|
|
}
|
|
if(g_ProtMap[i].Mask & SP_PROT_SSL2_CLIENT)
|
|
{
|
|
// "DisabledByDefault"
|
|
ReadRegistrySetting(
|
|
hKey,
|
|
0,
|
|
SP_REG_VAL_DISABLED_BY_DEFAULT,
|
|
&g_Ssl2ClientDisabledByDefault,
|
|
SSL2_CLIENT_DISABLED_SETTING);
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkProtocols);
|
|
}
|
|
|
|
if(g_ProtEnabled != dwProtEnabled)
|
|
{
|
|
g_ProtEnabled = dwProtEnabled;
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Enable/Disable Ciphers
|
|
//
|
|
|
|
if(fFipsMode)
|
|
{
|
|
// Disable everything except 3DES.
|
|
for(i=0; i < g_cAvailableCiphers; i++)
|
|
{
|
|
if(g_AvailableCiphers[i].aiCipher != CALG_3DES)
|
|
{
|
|
g_AvailableCiphers[i].fProtocol = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err = RegCreateKeyEx( g_hkBase,
|
|
SP_REG_KEY_CIPHERS,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&hkCiphers,
|
|
&disp);
|
|
|
|
if(err == ERROR_SUCCESS)
|
|
{
|
|
for(i=0; i < g_cAvailableCiphers; i++)
|
|
{
|
|
dwOriginalValue = g_AvailableCiphers[i].fProtocol;
|
|
|
|
g_AvailableCiphers[i].fProtocol = g_AvailableCiphers[i].fDefault;
|
|
fVal = g_AvailableCiphers[i].fDefault;
|
|
err = RegCreateKeyExA( hkCiphers,
|
|
g_AvailableCiphers[i].szName,
|
|
0,
|
|
"",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&hKey,
|
|
&disp);
|
|
if(!err)
|
|
{
|
|
dwSize = sizeof(DWORD);
|
|
err = RegQueryValueEx(hKey, SP_REG_VAL_ENABLED, NULL, &dwType, (PUCHAR)&fVal, &dwSize);
|
|
|
|
if(err)
|
|
{
|
|
fVal = g_AvailableCiphers[i].fDefault;
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
g_AvailableCiphers[i].fProtocol &= fVal;
|
|
|
|
if(g_AvailableCiphers[i].fProtocol != dwOriginalValue)
|
|
{
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkCiphers);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Enable/Disable Hashes
|
|
//
|
|
|
|
err = RegCreateKeyEx( g_hkBase,
|
|
SP_REG_KEY_HASHES,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&hkHashes,
|
|
&disp);
|
|
|
|
if(err == ERROR_SUCCESS)
|
|
{
|
|
for(i = 0; i < g_cAvailableHashes; i++)
|
|
{
|
|
dwOriginalValue = g_AvailableHashes[i].fProtocol;
|
|
|
|
g_AvailableHashes[i].fProtocol = g_AvailableHashes[i].fDefault;
|
|
fVal = g_AvailableHashes[i].fDefault;
|
|
err = RegCreateKeyExA( hkHashes,
|
|
g_AvailableHashes[i].szName,
|
|
0,
|
|
"",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&hKey,
|
|
&disp);
|
|
if(!err)
|
|
{
|
|
dwSize = sizeof(DWORD);
|
|
err = RegQueryValueEx(hKey, SP_REG_VAL_ENABLED, NULL, &dwType, (PUCHAR)&fVal, &dwSize);
|
|
|
|
if(err)
|
|
{
|
|
fVal = g_AvailableHashes[i].fDefault;
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
g_AvailableHashes[i].fProtocol &= fVal;
|
|
|
|
if(dwOriginalValue != g_AvailableHashes[i].fProtocol)
|
|
{
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkHashes);
|
|
}
|
|
|
|
|
|
//
|
|
// Enable/Disable Key Exchange algs.
|
|
//
|
|
|
|
if(fFipsMode)
|
|
{
|
|
// Disable everything except RSA.
|
|
for(i=0; i < g_cAvailableExch; i++)
|
|
{
|
|
if(g_AvailableExch[i].aiExch != CALG_RSA_KEYX &&
|
|
g_AvailableExch[i].aiExch != CALG_RSA_SIGN)
|
|
{
|
|
g_AvailableExch[i].fProtocol = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err = RegCreateKeyEx( g_hkBase,
|
|
SP_REG_KEY_KEYEXCH,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&hkKeyExch,
|
|
&disp);
|
|
|
|
if(err == ERROR_SUCCESS)
|
|
{
|
|
for(i = 0; i < g_cAvailableExch; i++)
|
|
{
|
|
dwOriginalValue = g_AvailableExch[i].fProtocol;
|
|
|
|
g_AvailableExch[i].fProtocol = g_AvailableExch[i].fDefault;
|
|
fVal = g_AvailableExch[i].fDefault;
|
|
err = RegCreateKeyExA( hkKeyExch,
|
|
g_AvailableExch[i].szName,
|
|
0,
|
|
"",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&hKey,
|
|
&disp);
|
|
if(!err)
|
|
{
|
|
dwSize = sizeof(DWORD);
|
|
err = RegQueryValueEx(hKey, SP_REG_VAL_ENABLED, NULL, &dwType, (PUCHAR)&fVal, &dwSize);
|
|
|
|
if(err)
|
|
{
|
|
fVal = g_AvailableExch[i].fDefault;
|
|
}
|
|
g_AvailableExch[i].fProtocol &= fVal;
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if(dwOriginalValue != g_AvailableExch[i].fProtocol)
|
|
{
|
|
fSettingsChanged = TRUE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkKeyExch);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Purge the session cache.
|
|
//
|
|
|
|
if(g_fCacheInitialized && fSettingsChanged)
|
|
{
|
|
SPCachePurgeEntries(NULL,
|
|
0,
|
|
NULL,
|
|
SSL_PURGE_CLIENT_ALL_ENTRIES |
|
|
SSL_PURGE_SERVER_ALL_ENTRIES);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|