388 lines
11 KiB
C++
388 lines
11 KiB
C++
/*++
|
||
|
||
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"
|
||
|
||
// 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;
|
||
}
|
||
|
||
|
||
//--------------------------------------------------------------------
|
||
// 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 );
|
||
|
||
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;
|
||
}
|
||
|