/*++ 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 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; }