427 lines
9.0 KiB
C++
427 lines
9.0 KiB
C++
/*++
|
||
|
||
Copyright (c) 1994 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
secinit.cxx
|
||
|
||
Abstract:
|
||
|
||
Contains load function for security.dll on NT and secur32.dll on win95
|
||
Also handles WinTrust.dll function loading.
|
||
|
||
Author:
|
||
|
||
Sophia Chung (sophiac) 6-Feb-1996
|
||
|
||
Environment:
|
||
|
||
User Mode - Win32
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
#include <wininetp.h>
|
||
|
||
//
|
||
// InitializationLock - protects against multiple threads loading security.dll
|
||
// (secur32.dll) and entry points
|
||
//
|
||
|
||
CCritSec InitializationSecLock;
|
||
|
||
HCRYPTPROV GlobalFortezzaCryptProv;
|
||
|
||
//
|
||
// GlobalSecFuncTable - Pointer to Global Structure of Pointers that are used
|
||
// for storing the entry points into the SCHANNEL.dll
|
||
//
|
||
|
||
PSecurityFunctionTable GlobalSecFuncTable = NULL;
|
||
|
||
//
|
||
// pWinVerifyTrust - Pointer to Entry Point in WINTRUST.DLL
|
||
//
|
||
|
||
WIN_VERIFY_TRUST_FN pWinVerifyTrust;
|
||
WT_HELPER_PROV_DATA_FROM_STATE_DATA_FN pWTHelperProvDataFromStateData;
|
||
|
||
//
|
||
// hSecurity - NULL when security.dll/secur32.dll is not loaded
|
||
//
|
||
|
||
HINSTANCE hSecurity = NULL;
|
||
|
||
//
|
||
// hWinTrust - NULL when WinTrust DLL is not loaded.
|
||
//
|
||
|
||
HINSTANCE hWinTrust = NULL;
|
||
|
||
HCERTSTORE g_hMyCertStore = NULL;
|
||
|
||
BOOL g_bFortezzaInstalled = FALSE;
|
||
BOOL g_bCheckedForFortezza = FALSE;
|
||
|
||
CRYPT_INSTALL_DEFAULT_CONTEXT_FN g_CryptInstallDefaultContext = NULL;
|
||
CRYPT_UNINSTALL_DEFAULT_CONTEXT_FN g_CryptUninstallDefaultContext = NULL;
|
||
CERT_FIND_CHAIN_IN_STORE_FN g_CertFindChainInStore = NULL;
|
||
CERT_FREE_CERTIFICATE_CHAIN_FN g_CertFreeCertificateChain = NULL;
|
||
|
||
|
||
DWORD
|
||
LoadWinTrust(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function loads the WinTrust.DLL and binds a pointer to a function
|
||
that is needed in the WinTrust DLL.
|
||
|
||
Arguments:
|
||
|
||
NONE.
|
||
|
||
Return Value:
|
||
|
||
WINDOWS Error Code.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD error = ERROR_SUCCESS;
|
||
|
||
if (!LOCK_SECURITY())
|
||
{
|
||
return ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
|
||
if( hWinTrust == NULL )
|
||
{
|
||
LPSTR lpszDllFileName = WINTRUST_DLLNAME;
|
||
pWinVerifyTrust = NULL;
|
||
|
||
//
|
||
// Load the DLL
|
||
//
|
||
|
||
hWinTrust = LoadLibrary(lpszDllFileName);
|
||
|
||
if ( hWinTrust )
|
||
{
|
||
pWinVerifyTrust = (WIN_VERIFY_TRUST_FN)
|
||
GetProcAddress(hWinTrust, WIN_VERIFY_TRUST_NAME);
|
||
pWTHelperProvDataFromStateData = (WT_HELPER_PROV_DATA_FROM_STATE_DATA_FN)
|
||
GetProcAddress(hWinTrust, WT_HELPER_PROV_DATA_FROM_STATE_DATA_NAME);
|
||
}
|
||
|
||
|
||
if ( !hWinTrust || !pWinVerifyTrust )
|
||
{
|
||
error = GetLastError();
|
||
|
||
if ( error == ERROR_SUCCESS )
|
||
{
|
||
error = ERROR_WINHTTP_INTERNAL_ERROR;
|
||
}
|
||
}
|
||
}
|
||
|
||
INET_ASSERT(pWinVerifyTrust);
|
||
|
||
|
||
if ( error != ERROR_SUCCESS )
|
||
{
|
||
if (hWinTrust)
|
||
{
|
||
FreeLibrary(hWinTrust);
|
||
hWinTrust = NULL;
|
||
}
|
||
}
|
||
|
||
UNLOCK_SECURITY();
|
||
|
||
return error;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
SecurityInitialize(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function initializes the global lock required for the security
|
||
pkgs.
|
||
|
||
Arguments:
|
||
|
||
NONE.
|
||
|
||
Return Value:
|
||
|
||
WINDOWS Error Code.
|
||
|
||
--*/
|
||
{
|
||
return InitializationSecLock.Init();
|
||
}
|
||
|
||
VOID
|
||
SecurityTerminate(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function Deletes the global lock required for the security
|
||
pkgs.
|
||
|
||
Arguments:
|
||
|
||
NONE.
|
||
|
||
Return Value:
|
||
|
||
WINDOWS Error Code.
|
||
|
||
--*/
|
||
{
|
||
InitializationSecLock.FreeLock();
|
||
}
|
||
|
||
|
||
VOID
|
||
UnloadSecurity(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function terminates the global data required for the security
|
||
pkgs and dynamically unloads security APIs from security.dll (NT)
|
||
or secur32.dll (WIN95).
|
||
|
||
Arguments:
|
||
|
||
NONE.
|
||
|
||
Return Value:
|
||
|
||
WINDOWS Error Code.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD i;
|
||
|
||
if (!LOCK_SECURITY())
|
||
{
|
||
INET_ASSERT(FALSE);
|
||
return;
|
||
}
|
||
|
||
//
|
||
// free all security pkg credential handles
|
||
//
|
||
|
||
for (i = 0; SecProviders[i].pszName != NULL; i++) {
|
||
if (SecProviders[i].fEnabled) {
|
||
if (SecProviders[i].pCertCtxt == NULL && !IsCredClear(SecProviders[i].hCreds)) {
|
||
// Beta1 Hack. Because of some circular dependency between dlls
|
||
// both crypt32 and schannel's PROCESS_DETACH gets called before wininet.
|
||
// This is catastrophic if we have a cert context attached to the credentials
|
||
// handle. In this case we will just leak the handle since the process is dying
|
||
// anyway. We really need to fix this.
|
||
WRAP_REVERT_USER_VOID(g_FreeCredentialsHandle,
|
||
(&SecProviders[i].hCreds));
|
||
}
|
||
}
|
||
#if 0 // See comments above.
|
||
if (SecProviders[i].pCertCtxt != NULL) {
|
||
CertFreeCertificateContext(SecProviders[i].pCertCtxt);
|
||
SecProviders[i].pCertCtxt = NULL;
|
||
}
|
||
#endif
|
||
|
||
}
|
||
|
||
//
|
||
// close cert store. Protect against fault if DLL already unloaded
|
||
//
|
||
|
||
if (g_hMyCertStore != NULL)
|
||
{
|
||
SAFE_WRAP_REVERT_USER_VOID(CertCloseStore,
|
||
(g_hMyCertStore, CERT_CLOSE_STORE_FORCE_FLAG));
|
||
g_hMyCertStore = NULL;
|
||
}
|
||
|
||
// IMPORTANT : Don't free GlobalFortezzaCryptProv. When we free the cert context
|
||
// from the SecProviders[] array above it gets freed automatically.
|
||
if (GlobalFortezzaCryptProv != NULL)
|
||
{
|
||
GlobalFortezzaCryptProv = NULL;
|
||
}
|
||
|
||
|
||
//
|
||
// unload dll
|
||
//
|
||
|
||
if (hSecurity != NULL) {
|
||
FreeLibrary(hSecurity);
|
||
hSecurity = NULL;
|
||
}
|
||
|
||
UNLOCK_SECURITY();
|
||
|
||
}
|
||
|
||
|
||
DWORD
|
||
LoadSecurity(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function dynamically loads security APIs from security.dll (NT)
|
||
or secur32.dll (WIN95).
|
||
|
||
Arguments:
|
||
|
||
NONE.
|
||
|
||
Return Value:
|
||
|
||
WINDOWS Error Code.
|
||
--*/
|
||
{
|
||
DWORD Error = ERROR_SUCCESS;
|
||
INITSECURITYINTERFACE pfInitSecurityInterface = NULL;
|
||
|
||
if (!LOCK_SECURITY())
|
||
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
||
if (g_hMyCertStore == NULL)
|
||
{
|
||
|
||
//
|
||
// CRYPT32.DLL is delayloaded. Need SEH in case it fails.
|
||
//
|
||
// Don't worry about an error, because not supporting
|
||
// client auth shouldn't stop us from scenarios
|
||
// which do not require it as part of the SSL handshake.
|
||
//
|
||
|
||
SAFE_WRAP_REVERT_USER(CertOpenSystemStore, (0, "MY"), g_hMyCertStore);
|
||
|
||
}
|
||
if (Error == ERROR_SUCCESS)
|
||
{
|
||
Error = LoadWinTrust();
|
||
}
|
||
if ( Error != ERROR_SUCCESS )
|
||
{
|
||
goto quit;
|
||
}
|
||
|
||
if( hSecurity != NULL )
|
||
{
|
||
goto quit;
|
||
}
|
||
|
||
//
|
||
// load dll.
|
||
//
|
||
|
||
//
|
||
// This is better for performance. Rather than call through
|
||
// SSPI, we go right to the DLL doing the work.
|
||
//
|
||
|
||
hSecurity = LoadLibrary( "schannel" );
|
||
|
||
if ( hSecurity == NULL ) {
|
||
Error = GetLastError();
|
||
goto quit;
|
||
}
|
||
|
||
//
|
||
// get function addresses.
|
||
//
|
||
|
||
#ifdef UNICODE
|
||
pfInitSecurityInterface =
|
||
(INITSECURITYINTERFACE) GetProcAddress( hSecurity,
|
||
"InitSecurityInterfaceW" );
|
||
#else
|
||
pfInitSecurityInterface =
|
||
(INITSECURITYINTERFACE) GetProcAddress( hSecurity,
|
||
"InitSecurityInterfaceA" );
|
||
#endif
|
||
|
||
|
||
if ( pfInitSecurityInterface == NULL )
|
||
{
|
||
Error = GetLastError();
|
||
goto quit;
|
||
}
|
||
|
||
|
||
GlobalSecFuncTable = (SecurityFunctionTable*) ((*pfInitSecurityInterface) ());
|
||
|
||
if ( GlobalSecFuncTable == NULL ) {
|
||
Error = GetLastError(); // BUGBUG does this work?
|
||
goto quit;
|
||
}
|
||
|
||
HMODULE hCrypt32;
|
||
hCrypt32 = GetModuleHandle("crypt32");
|
||
|
||
INET_ASSERT(hCrypt32 != NULL);
|
||
|
||
// We don't error out here because not finding these entry points
|
||
// just affects Fortezza. The rest will still work fine.
|
||
if (hCrypt32)
|
||
{
|
||
g_CryptInstallDefaultContext = (CRYPT_INSTALL_DEFAULT_CONTEXT_FN)
|
||
GetProcAddress(hCrypt32, CRYPT_INSTALL_DEFAULT_CONTEXT_NAME);
|
||
|
||
g_CryptUninstallDefaultContext = (CRYPT_UNINSTALL_DEFAULT_CONTEXT_FN)
|
||
GetProcAddress(hCrypt32, CRYPT_UNINSTALL_DEFAULT_CONTEXT_NAME);
|
||
|
||
g_CertFindChainInStore = (CERT_FIND_CHAIN_IN_STORE_FN)
|
||
GetProcAddress(hCrypt32, CERT_FIND_CHAIN_IN_STORE_NAME);
|
||
|
||
g_CertFreeCertificateChain = (CERT_FREE_CERTIFICATE_CHAIN_FN)
|
||
GetProcAddress(hCrypt32, CERT_FREE_CERTIFICATE_CHAIN_NAME);
|
||
}
|
||
|
||
quit:
|
||
|
||
if ( Error != ERROR_SUCCESS )
|
||
{
|
||
FreeLibrary( hSecurity );
|
||
hSecurity = NULL;
|
||
}
|
||
|
||
UNLOCK_SECURITY();
|
||
|
||
return( Error );
|
||
}
|
||
|
||
|