BOOL WINAPI SSPLogonUser(LPTSTR szDomain, LPTSTR szUser, LPTSTR szPassword, PSECURITY_DESCRIPTOR psdSD, PBOOL isAuthenticated, PDWORD pdwAccessGranted) // returns bitmask with accessrights { AUTH_SEQ asServer = {0}; AUTH_SEQ asClient = {0}; BOOL fDone = FALSE; BOOL fResult = FALSE; DWORD cbOut = 0; DWORD cbIn = 0; DWORD cbMaxToken = 0; PVOID pClientBuf = NULL; PVOID pServerBuf = NULL; PSecPkgInfo pSPI = NULL; HMODULE hModule = NULL; SEC_WINNT_AUTH_IDENTITY ai; __try { hModule = LoadSecurityDll(); if (!hModule) __leave; // Get max token size fn._QuerySecurityPackageInfo(_T("NTLM"), &pSPI); cbMaxToken = pSPI->cbMaxToken; // Allocate buffers for client and server messages pClientBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken); pServerBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken); // Initialize auth identity structure // Marscha 2004: Seems to work with szDomain = "" or even szDomain = "anyDomain", // but I found no MS documentation for this 'feature'. ZeroMemory(&ai, sizeof(ai)); #if defined(UNICODE) || defined(_UNICODE) ai.Domain = (unsigned short *)szDomain; ai.DomainLength = lstrlen(szDomain); ai.User = (unsigned short *)szUser; ai.UserLength = lstrlen(szUser); ai.Password = (unsigned short *)szPassword; ai.PasswordLength = lstrlen(szPassword); ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; #else ai.Domain = (unsigned char *)szDomain; ai.DomainLength = lstrlen(szDomain); ai.User = (unsigned char *)szUser; ai.UserLength = lstrlen(szUser); ai.Password = (unsigned char *)szPassword; ai.PasswordLength = lstrlen(szPassword); ai.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; #endif // Prepare client message (negotiate) . cbOut = cbMaxToken; if (!GenClientContext(&asClient, &ai, NULL, 0, pClientBuf, &cbOut, &fDone)) __leave; // Prepare server message (challenge) . cbIn = cbOut; cbOut = cbMaxToken; if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut, &fDone)) __leave; // Most likely failure: AcceptServerContext fails with SEC_E_LOGON_DENIED // in the case of bad szUser or szPassword. // Unexpected Result: Logon will succeed if you pass in a bad szUser and // the guest account is enabled in the specified domain. // Prepare client message (authenticate) . cbIn = cbOut; cbOut = cbMaxToken; if (!GenClientContext(&asClient, &ai, pServerBuf, cbIn, pClientBuf, &cbOut, &fDone)) __leave; // Prepare server message (authentication) . cbIn = cbOut; cbOut = cbMaxToken; if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut, &fDone)) __leave; *isAuthenticated = TRUE; // Check authorization if (IsImpersonationAllowed()) { if (ImpersonateAndCheckAccess(&(asServer.hctxt), psdSD, pdwAccessGranted)) fResult = TRUE; } else { // Todo: Make alternative access check if (ImpersonateAndCheckAccess(&(asServer.hctxt), psdSD, pdwAccessGranted)) fResult = TRUE; } } __finally { // Clean up resources if (pSPI) fn._FreeContextBuffer(pSPI); if (asClient.fHaveCtxtHandle) fn._DeleteSecurityContext(&asClient.hctxt); if (asClient.fHaveCredHandle) fn._FreeCredentialsHandle(&asClient.hcred); if (asServer.fHaveCtxtHandle) fn._DeleteSecurityContext(&asServer.hctxt); if (asServer.fHaveCredHandle) fn._FreeCredentialsHandle(&asServer.hcred); if (hModule) UnloadSecurityDll(hModule); HeapFree(GetProcessHeap(), 0, pClientBuf); HeapFree(GetProcessHeap(), 0, pServerBuf); SecureZeroMemory(&ai, sizeof(ai)); } return fResult; }
BOOL WINAPI SSPLogonUser(LPTSTR szDomain, LPTSTR szUser, LPTSTR szPassword) { AUTH_SEQ asServer = {0}; AUTH_SEQ asClient = {0}; BOOL fDone = FALSE; BOOL fResult = FALSE; DWORD cbOut = 0; DWORD cbIn = 0; DWORD cbMaxToken = 0; PVOID pClientBuf = NULL; PVOID pServerBuf = NULL; PSecPkgInfo pSPI = NULL; HMODULE hModule = NULL; SEC_WINNT_AUTH_IDENTITY ai; __try { hModule = LoadSecurityDll(); if (!hModule) __leave; // Get max token size _QuerySecurityPackageInfo(_T("NTLM"), &pSPI); cbMaxToken = pSPI->cbMaxToken; _FreeContextBuffer(pSPI); // Allocate buffers for client and server messages pClientBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken); pServerBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken); // Initialize auth identity structure ZeroMemory(&ai, sizeof(ai)); #if defined(UNICODE) || defined(_UNICODE) ai.Domain = szDomain; ai.DomainLength = lstrlen(szDomain); ai.User = szUser; ai.UserLength = lstrlen(szUser); ai.Password = szPassword; ai.PasswordLength = lstrlen(szPassword); ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; #else ai.Domain = (unsigned char *)szDomain; ai.DomainLength = lstrlen(szDomain); ai.User = (unsigned char *)szUser; ai.UserLength = lstrlen(szUser); ai.Password = (unsigned char *)szPassword; ai.PasswordLength = lstrlen(szPassword); ai.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; #endif // Prepare client message (negotiate) . cbOut = cbMaxToken; if (!GenClientContext(&asClient, &ai, NULL, 0, pClientBuf, &cbOut, &fDone)) __leave; // Prepare server message (challenge) . cbIn = cbOut; cbOut = cbMaxToken; if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut, &fDone)) __leave; // Most likely failure: AcceptServerContext fails with SEC_E_LOGON_DENIED // in the case of bad szUser or szPassword. // Unexpected Result: Logon will succeed if you pass in a bad szUser and // the guest account is enabled in the specified domain. // Prepare client message (authenticate) . cbIn = cbOut; cbOut = cbMaxToken; if (!GenClientContext(&asClient, &ai, pServerBuf, cbIn, pClientBuf, &cbOut, &fDone)) __leave; // Prepare server message (authentication) . cbIn = cbOut; cbOut = cbMaxToken; if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut, &fDone)) __leave; fResult = TRUE; } __finally { // Clean up resources if (asClient.fHaveCtxtHandle) _DeleteSecurityContext(&asClient.hctxt); if (asClient.fHaveCredHandle) _FreeCredentialsHandle(&asClient.hcred); if (asServer.fHaveCtxtHandle) _DeleteSecurityContext(&asServer.hctxt); if (asServer.fHaveCredHandle) _FreeCredentialsHandle(&asServer.hcred); if (hModule) UnloadSecurityDll(hModule); HeapFree(GetProcessHeap(), 0, pClientBuf); HeapFree(GetProcessHeap(), 0, pServerBuf); } return fResult; }
HMODULE LoadSecurityDll() { HMODULE hModule; BOOL fAllFunctionsLoaded = FALSE; TCHAR lpszDLL[MAX_PATH]; OSVERSIONINFO VerInfo; _AcceptSecurityContext = NULL; _AcquireCredentialsHandle = NULL; _CompleteAuthToken = NULL; _DeleteSecurityContext = NULL; _FreeContextBuffer = NULL; _FreeCredentialsHandle = NULL; _InitializeSecurityContext = NULL; _QuerySecurityPackageInfo = NULL; // // Find out which security DLL to use, depending on // whether we are on NT or Win95 or 2000 or XP or .NET Server // We have to use security.dll on Windows NT 4.0. // All other operating systems, we have to use Secur32.dll // VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (!GetVersionEx (&VerInfo)) // If this fails, something has gone wrong { return FALSE; } if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && VerInfo.dwMajorVersion == 4 && VerInfo.dwMinorVersion == 0) { lstrcpy (lpszDLL, _T("security.dll")); } else { lstrcpy (lpszDLL, _T("secur32.dll")); } hModule = LoadLibrary(lpszDLL); if (!hModule) return NULL; __try { _AcceptSecurityContext = (ACCEPT_SECURITY_CONTEXT_FN) GetProcAddress(hModule, "AcceptSecurityContext"); if (!_AcceptSecurityContext) __leave; #ifdef UNICODE _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(hModule, "AcquireCredentialsHandleW"); #else _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(hModule, "AcquireCredentialsHandleA"); #endif if (!_AcquireCredentialsHandle) __leave; // CompleteAuthToken is not present on Windows 9x Secur32.dll // Do not check for the availablity of the function if it is NULL; _CompleteAuthToken = (COMPLETE_AUTH_TOKEN_FN) GetProcAddress(hModule, "CompleteAuthToken"); _DeleteSecurityContext = (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(hModule, "DeleteSecurityContext"); if (!_DeleteSecurityContext) __leave; _FreeContextBuffer = (FREE_CONTEXT_BUFFER_FN) GetProcAddress(hModule, "FreeContextBuffer"); if (!_FreeContextBuffer) __leave; _FreeCredentialsHandle = (FREE_CREDENTIALS_HANDLE_FN) GetProcAddress(hModule, "FreeCredentialsHandle"); if (!_FreeCredentialsHandle) __leave; #ifdef UNICODE _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(hModule, "InitializeSecurityContextW"); #else _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(hModule, "InitializeSecurityContextA"); #endif if (!_InitializeSecurityContext) __leave; #ifdef UNICODE _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN) GetProcAddress(hModule, "QuerySecurityPackageInfoW"); #else _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN) GetProcAddress(hModule, "QuerySecurityPackageInfoA"); #endif if (!_QuerySecurityPackageInfo) __leave; fAllFunctionsLoaded = TRUE; } __finally { if (!fAllFunctionsLoaded) { UnloadSecurityDll(hModule); hModule = NULL; } } return hModule; }
HMODULE LoadSecurityDll(int mode, char * SSP_Package) { TCHAR lpszDLL[MAX_PATH]; OSVERSIONINFO VerInfo; PSecPkgInfo pSPI = NULL; /* * Find out which security DLL to use, depending on * whether we are on NT or 2000 or XP or 2003 Server * We have to use security.dll on Windows NT 4.0. * All other operating systems, we have to use Secur32.dll */ hModule = NULL; if ((mode != SSP_BASIC) && (mode != SSP_NTLM)) return hModule; NTLM_mode = mode; VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (!GetVersionEx (&VerInfo)) { /* If this fails, something has gone wrong */ return hModule; } if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && VerInfo.dwMajorVersion == 4 && VerInfo.dwMinorVersion == 0) { lstrcpy (lpszDLL, _T(WINNT_SECURITY_DLL)); } else { lstrcpy (lpszDLL, _T(WIN2K_SECURITY_DLL)); } hModule = LoadLibrary(lpszDLL); if (!hModule) return hModule; _AcceptSecurityContext = (ACCEPT_SECURITY_CONTEXT_FN) GetProcAddress(hModule, "AcceptSecurityContext"); if (!_AcceptSecurityContext) { UnloadSecurityDll(); hModule = NULL; return hModule; } #ifdef UNICODE _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(hModule, "AcquireCredentialsHandleW"); #else _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(hModule, "AcquireCredentialsHandleA"); #endif if (!_AcquireCredentialsHandle) { UnloadSecurityDll(); hModule = NULL; return hModule; } _CompleteAuthToken = (COMPLETE_AUTH_TOKEN_FN) GetProcAddress(hModule, "CompleteAuthToken"); if (!_CompleteAuthToken) { UnloadSecurityDll(); hModule = NULL; return hModule; } _DeleteSecurityContext = (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(hModule, "DeleteSecurityContext"); if (!_DeleteSecurityContext) { UnloadSecurityDll(); hModule = NULL; return hModule; } _FreeContextBuffer = (FREE_CONTEXT_BUFFER_FN) GetProcAddress(hModule, "FreeContextBuffer"); if (!_FreeContextBuffer) { UnloadSecurityDll(); hModule = NULL; return hModule; } _FreeCredentialsHandle = (FREE_CREDENTIALS_HANDLE_FN) GetProcAddress(hModule, "FreeCredentialsHandle"); if (!_FreeCredentialsHandle) { UnloadSecurityDll(); hModule = NULL; return hModule; } #ifdef UNICODE _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(hModule, "InitializeSecurityContextW"); #else _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(hModule, "InitializeSecurityContextA"); #endif if (!_InitializeSecurityContext) { UnloadSecurityDll(); hModule = NULL; return hModule; } #ifdef UNICODE _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN) GetProcAddress(hModule, "QuerySecurityPackageInfoW"); #else _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN) GetProcAddress(hModule, "QuerySecurityPackageInfoA"); #endif if (!_QuerySecurityPackageInfo) { UnloadSecurityDll(); hModule = NULL; } #ifdef UNICODE _QueryContextAttributes = (QUERY_CONTEXT_ATTRIBUTES_FN_W) GetProcAddress(hModule, "QueryContextAttributesW"); #else _QueryContextAttributes = (QUERY_CONTEXT_ATTRIBUTES_FN_A) GetProcAddress(hModule, "QueryContextAttributesA"); #endif if (!_QueryContextAttributes) { UnloadSecurityDll(); hModule = NULL; } /* Get max token size */ _QuerySecurityPackageInfo((SEC_CHAR*)_T(SSP_Package), &pSPI); cbMaxToken = pSPI->cbMaxToken; _FreeContextBuffer(pSPI); /* Allocate buffers for client and server messages */ pClientBuf = xcalloc(cbMaxToken, sizeof(char)); pServerBuf = xcalloc(cbMaxToken, sizeof(char)); SSP_Package_InUse = xstrdup(SSP_Package); return hModule; }