You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
401 lines
11 KiB
401 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
init.c
|
|
|
|
Abstract:
|
|
|
|
Dll initialization for sspi digest package.
|
|
|
|
Author:
|
|
|
|
Adriaan Canter (adriaanc) 01-Aug-1998
|
|
|
|
--*/
|
|
|
|
#include "include.hxx"
|
|
#include "digestui.hxx"
|
|
#include "resource.h"
|
|
|
|
//
|
|
// Downlevel delay load support (we forward to shlwapi)
|
|
//
|
|
#include <delayimp.h>
|
|
|
|
PfnDliHook __pfnDliFailureHook;
|
|
|
|
// Serializes access to all globals in module
|
|
CRITICAL_SECTION DllCritSect;
|
|
|
|
// Per process credential cache.
|
|
CCredCache *g_pCache = NULL;
|
|
|
|
// Per process cache init flag
|
|
BOOL g_fCredCacheInit = FALSE;
|
|
|
|
// Global module handle.
|
|
HMODULE g_hModule = NULL;
|
|
|
|
// Global handle to shlwapi.
|
|
HMODULE g_hShlwapi = NULL;
|
|
|
|
// Status of cred persist services on machine.
|
|
DWORD g_dwCredPersistAvail = CRED_PERSIST_UNKNOWN;
|
|
|
|
DWORD_PTR g_pHeap = NULL;
|
|
|
|
//--------------------------------------------------------------------
|
|
// DigestServicesExist
|
|
//--------------------------------------------------------------------
|
|
BOOL DigestServicesExist()
|
|
{
|
|
INIT_SECURITY_INTERFACE addrProcISI = NULL;
|
|
PSecurityFunctionTable pFuncTbl = NULL;
|
|
|
|
PSecPkgInfoA pSecPkgInfo;
|
|
SECURITY_STATUS ssResult;
|
|
DWORD cPackages;
|
|
|
|
OSVERSIONINFO VerInfo;
|
|
CHAR szDLL[MAX_PATH];
|
|
HINSTANCE hSecLib;
|
|
|
|
BOOL fDigest = FALSE;
|
|
|
|
// Get the OS version.
|
|
VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
|
|
GetVersionEx (&VerInfo);
|
|
|
|
// Load the appropriate dll.
|
|
if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
|
lstrcpy (szDLL, SSP_SPM_NT_DLL);
|
|
else if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
|
lstrcpy (szDLL, SSP_SPM_WIN95_DLL);
|
|
else
|
|
goto exit;
|
|
|
|
hSecLib = LoadLibrary (szDLL);
|
|
if (!hSecLib)
|
|
goto exit;
|
|
|
|
// Get the dispatch table.
|
|
addrProcISI = (INIT_SECURITY_INTERFACE) GetProcAddress( hSecLib,
|
|
SECURITY_ENTRYPOINT_ANSI);
|
|
pFuncTbl = (*addrProcISI)();
|
|
|
|
if (!pFuncTbl)
|
|
goto exit;
|
|
|
|
// Enumerate security pkgs and determine if digest is installed.
|
|
ssResult = (*(pFuncTbl->EnumerateSecurityPackagesA))(&cPackages, &pSecPkgInfo);
|
|
|
|
if (ssResult == SEC_E_OK)
|
|
{
|
|
for (DWORD i = 0; i < cPackages; i++)
|
|
{
|
|
if (lstrcmpi(pSecPkgInfo[i].Name, "Digest") == 0)
|
|
{
|
|
fDigest = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
exit:
|
|
return fDigest;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// DLLInstall
|
|
//--------------------------------------------------------------------
|
|
STDAPI
|
|
DllInstall
|
|
(
|
|
IN BOOL bInstall, // Install or Uninstall
|
|
IN LPCWSTR pwStr
|
|
)
|
|
{
|
|
HKEY hKey;
|
|
DWORD dwError, dwRegDisp, cbSP = MAX_PATH;
|
|
CHAR *ptr, *ptrNext, szSP[MAX_PATH];
|
|
BOOL bHKLM = FALSE;
|
|
|
|
// Determine if full install (provide client digest sspi svcs)
|
|
// or just passport install (server pkg delegating to client)
|
|
if (!pwStr || !*pwStr || (!wcscmp(pwStr, L"HKLM")))
|
|
{
|
|
bHKLM = TRUE;
|
|
}
|
|
|
|
// Add "digest.dll" to comma delimited Service Providers list in
|
|
// HKLM\System\CurrentControlSet\Control\SecurityProviders only if
|
|
// no digest security providers currently exist.
|
|
if (bInstall && bHKLM && !DigestServicesExist())
|
|
{
|
|
// Open or create SecurityProviders key.
|
|
dwError = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
|
SECURITY_PROVIDERS_REG_KEY, 0, NULL,
|
|
0, KEY_READ | KEY_WRITE, NULL, &hKey, &dwRegDisp);
|
|
|
|
// Successfully opened/created key.
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
cbSP = MAX_PATH;
|
|
dwError = RegQueryValueEx(hKey, SECURITY_PROVIDERS_SZ,
|
|
NULL, NULL, (LPBYTE) szSP, &cbSP);
|
|
|
|
// SecurityProviders value might not be
|
|
// found which is ok since we will create it.
|
|
if (dwError == ERROR_SUCCESS || dwError == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
// Value not found same as value existed but no string.
|
|
if (dwError == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
ptr = NULL;
|
|
cbSP = 0;
|
|
}
|
|
// Otherwise if value found -> check if "digest.dll" exists.
|
|
else
|
|
{
|
|
// We can use the handy FindToken from the CParams object
|
|
// to determine if a token occurs in a comma delmited list.
|
|
if (!CParams::FindToken(szSP, cbSP, "digest.dll",
|
|
sizeof("digest.dll") - 1, &ptr))
|
|
{
|
|
ptr = NULL;
|
|
}
|
|
}
|
|
|
|
// Only add "digest.dll" if doesn't already exist.
|
|
if (!ptr)
|
|
{
|
|
// If we found value/data append "digest.dll"
|
|
if (cbSP > 1)
|
|
strcat(szSP, ", digest.dll");
|
|
|
|
// Otherwise "digest.dll" is only data
|
|
else
|
|
memcpy(szSP, "digest.dll", sizeof("digest.dll"));
|
|
|
|
// Write the value back.
|
|
dwError = RegSetValueEx(hKey, SECURITY_PROVIDERS_SZ, 0,
|
|
REG_SZ, (LPBYTE) szSP, strlen(szSP));
|
|
}
|
|
}
|
|
|
|
// Close SecurityProviders reg key.
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
// Remove "digest.dll" from the comma delimited Service Providers list in
|
|
// HKLM\System\CurrentControlSet\Control\SecurityProviders
|
|
if (!bInstall && bHKLM)
|
|
{
|
|
// Open the Security Providers reg key.
|
|
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
SECURITY_PROVIDERS_REG_KEY, NULL, KEY_READ | KEY_WRITE, &hKey);
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
// Get the SecurityProviders value data string.
|
|
dwError = RegQueryValueEx(hKey, SECURITY_PROVIDERS_SZ,
|
|
NULL, NULL, (LPBYTE) szSP, &cbSP);
|
|
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
// Only remove "digest.dll" if exists.
|
|
if (!CParams::FindToken(szSP, cbSP, "digest.dll",
|
|
sizeof("digest.dll") - 1, &ptr))
|
|
{
|
|
ptr = NULL;
|
|
}
|
|
|
|
if (ptr)
|
|
{
|
|
// Point to next item in list, might be '\0'
|
|
ptrNext = ptr + sizeof("digest.dll") - 1;
|
|
|
|
// Digest.dll is only entry.
|
|
if ((ptr == szSP) && cbSP == sizeof("digest.dll"))
|
|
{
|
|
*szSP = '\0';
|
|
}
|
|
// "digest.dll" is last entry.
|
|
else if (*ptrNext == '\0')
|
|
{
|
|
*(ptr - (sizeof (", ") - 1)) = '\0';
|
|
}
|
|
else if (*ptrNext == ',' && *(ptrNext+1) == ' ')
|
|
{
|
|
ptrNext+=2;
|
|
memcpy(ptr, ptrNext, (size_t)(cbSP - (ptrNext - szSP)));
|
|
}
|
|
|
|
dwError = RegSetValueEx(hKey, SECURITY_PROVIDERS_SZ, 0,
|
|
REG_SZ, (LPBYTE) szSP, *szSP ? strlen(szSP) : 1);
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// MakeFullAccessSA
|
|
//--------------------------------------------------------------------
|
|
|
|
//Commenting this function as it doesn't seem to be used anywhere in the sources
|
|
/*
|
|
SECURITY_ATTRIBUTES *MakeFullAccessSA (void)
|
|
{
|
|
static SECURITY_ATTRIBUTES sa;
|
|
static BYTE SDBuf[SECURITY_DESCRIPTOR_MIN_LENGTH];
|
|
|
|
// Don't bother on Win95/Win98 which don't support security.
|
|
OSVERSIONINFO versionInfo;
|
|
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
|
|
if (!GetVersionEx(&versionInfo)
|
|
|| (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS))
|
|
return NULL;
|
|
|
|
// Create a security descriptor with ACE to allow full access to all.
|
|
SECURITY_DESCRIPTOR* pSD = (SECURITY_DESCRIPTOR*) SDBuf;
|
|
if (!InitializeSecurityDescriptor (pSD, SECURITY_DESCRIPTOR_REVISION))
|
|
return NULL;
|
|
if (!SetSecurityDescriptorDacl (pSD, TRUE, NULL, FALSE))
|
|
return NULL;
|
|
|
|
// Initialize the security attributes.
|
|
sa.nLength = sizeof(sa);
|
|
sa.lpSecurityDescriptor = pSD;
|
|
sa.bInheritHandle = TRUE;
|
|
return &sa;
|
|
}*/
|
|
//--------------------------------------------------------------------
|
|
// NewString
|
|
//--------------------------------------------------------------------
|
|
LPSTR NewString(LPSTR szString)
|
|
{
|
|
if (!szString)
|
|
return NULL;
|
|
DWORD cbString = strlen(szString);
|
|
|
|
LPSTR szNew = new CHAR[cbString+1];
|
|
if (!szNew)
|
|
{
|
|
DIGEST_ASSERT(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(szNew, szString, cbString+1);
|
|
return szNew;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// InitGlobals
|
|
//--------------------------------------------------------------------
|
|
BOOL InitGlobals()
|
|
{
|
|
// Return success if we've already
|
|
// initialized.
|
|
if (g_fCredCacheInit)
|
|
return TRUE;
|
|
|
|
// Serialize per-process calls.
|
|
LOCK_GLOBALS();
|
|
|
|
// Recheck global flag in the case
|
|
// the cache was initialized while
|
|
// this thread was descheduled.
|
|
if (g_fCredCacheInit)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Global cred persist status.
|
|
g_dwCredPersistAvail = CRED_PERSIST_UNKNOWN;
|
|
|
|
// Create the credential cache.
|
|
g_pCache = new CCredCache();
|
|
|
|
if (!g_pCache || g_pCache->GetStatus() != ERROR_SUCCESS)
|
|
{
|
|
g_fCredCacheInit = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
g_fCredCacheInit = TRUE;
|
|
|
|
exit:
|
|
UNLOCK_GLOBALS();
|
|
|
|
return g_fCredCacheInit;
|
|
}
|
|
|
|
void SetupDelayloadErrorHandler()
|
|
{
|
|
__pfnDliFailureHook = (PfnDliHook)GetProcAddress(GetModuleHandleA("shlwapi.dll"), "DelayLoadFailureHook");
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// DllMain
|
|
//--------------------------------------------------------------------
|
|
#if defined(__cplusplus)
|
|
extern "C"
|
|
#endif
|
|
BOOL
|
|
WINAPI
|
|
DllMain(
|
|
IN PVOID DllHandle,
|
|
IN ULONG Reason,
|
|
IN PCONTEXT Context OPTIONAL
|
|
)
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(Context);
|
|
UNREFERENCED_PARAMETER(DllHandle );
|
|
|
|
switch (Reason)
|
|
{
|
|
// Process attach.
|
|
case DLL_PROCESS_ATTACH:
|
|
{
|
|
|
|
// BUGBUG - DislableThreadLibraryCalls and
|
|
// don't do any work.
|
|
g_hModule = (HMODULE) DllHandle;
|
|
InitializeCriticalSection( &DllCritSect );
|
|
SetupDelayloadErrorHandler();
|
|
|
|
if ((hDigest = CreateMutex (NULL,
|
|
FALSE,
|
|
NULL)) == NULL)
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
}
|
|
|
|
// Process detatch.
|
|
// Deinitialize the credential cache.
|
|
// Delete the critical section.
|
|
case DLL_PROCESS_DETACH:
|
|
{
|
|
if (g_pCache)
|
|
delete g_pCache;
|
|
|
|
DeleteCriticalSection( &DllCritSect );
|
|
CloseHandle (hDigest);
|
|
break;
|
|
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|