/*++ Copyright (c) 2001 Microsoft Corporation All rights reserved Module Name: sspiutils.cxx Abstract: sspiutils Author: Larry Zhu (LZhu) December 1, 2001 Created Environment: User Mode -Win32 Revision History: --*/ #include "precomp.hxx" #pragma hdrstop #include "sspiutils.hxx" #include #include HRESULT AcquireCredHandle( IN OPTIONAL PSTR pszPrincipal, IN OPTIONAL LUID* pLogonID, IN PSTR pszPackageName, IN OPTIONAL VOID* pAuthData, IN ULONG fCredentialUse, OUT CredHandle* phCred ) { THResult hRetval = S_OK; CredHandle hCred; TimeStamp Lifetime = {0}; TimeStamp CurrentTime = {0}; SecPkgCredentials_NamesA CredNames = {0}; TPrivilege* pPriv = NULL; DebugPrintf(SSPI_LOG, "AcquireCredHandle pszPrincipal %s, pszPackageName %s, " "fCredentialUse %#x, pLogonID %p, pAuthData %p\n", pszPrincipal, pszPackageName, fCredentialUse, pLogonID, pAuthData); SecInvalidateHandle(&hCred); SecInvalidateHandle(phCred); if (pLogonID) { DebugPrintf(SSPI_LOG, "LogonId %#x:%#x\n", pLogonID->HighPart, pLogonID->LowPart); pPriv = new TPrivilege(SE_TCB_PRIVILEGE, TRUE); hRetval DBGCHK = pPriv ? pPriv->Validate() : E_OUTOFMEMORY; } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = AcquireCredentialsHandleA( pszPrincipal, // NULL pszPackageName, fCredentialUse, // SECPKG_CRED_INBOUND, pLogonID, // NULL pAuthData, // ServerAuthIdentity, NULL, // GetKey NULL, // value to pass to GetKey &hCred, &Lifetime ); } if (pPriv) { delete pPriv; } if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "CredHandle: %#x:%#x\n", hCred.dwUpper, hCred.dwLower); DebugPrintSysTimeAsLocalTime(SSPI_LOG, "Lifetime", &Lifetime); GetSystemTimeAsFileTime((PFILETIME) &CurrentTime); DebugPrintSysTimeAsLocalTime(SSPI_LOG, "Current Time", &CurrentTime); DBGCFG1(hRetval, SEC_E_UNSUPPORTED_FUNCTION); hRetval DBGCHK = QueryCredentialsAttributesA( &hCred, SECPKG_CRED_ATTR_NAMES, &CredNames ); if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryCredentialsAttributesA does not support SECPKG_CRED_ATTR_NAMES\n"); } } if (SUCCEEDED(hRetval)) { *phCred = hCred; SecInvalidateHandle(&hCred); DebugPrintf(SSPI_LOG, "Credential names: %s\n", CredNames.sUserName); } THResult hr; if (CredNames.sUserName) { hr DBGCHK = FreeContextBuffer(CredNames.sUserName); } if (SecIsValidHandle(&hCred)) { hr DBGCHK = FreeCredentialsHandle(&hCred); } return hRetval; } VOID GetAuthdata( IN OPTIONAL PCTSTR pszUserName, IN OPTIONAL PCTSTR pszDomainName, IN OPTIONAL PCTSTR pszPassword, OUT SEC_WINNT_AUTH_IDENTITY* pAuthData ) { #if defined(UNICODE) || defined(_UNICODE) pAuthData->Domain = (WCHAR*) pszDomainName; pAuthData->DomainLength = pszDomainName ? lstrlen(pszDomainName) : 0; pAuthData->Password = (WCHAR*) pszPassword; pAuthData->PasswordLength = pszPassword ? lstrlen(pszPassword) : 0; pAuthData->User = (WCHAR*) pszUserName; pAuthData->UserLength = pszUserName ? lstrlen(pszUserName) : 0; #else pAuthData->Domain = (UCHAR*) pszDomainName; pAuthData->DomainLength = pszDomainName ? lstrlen(pszDomainName) : 0; pAuthData->Password = (UCHAR*) pszPassword; pAuthData->PasswordLength = pszPassword ? lstrlen(pszPassword) : 0; pAuthData->User = (UCHAR*) pszUserName; pAuthData->UserLength = pszUserName ? lstrlen(pszUserName) : 0; #endif pAuthData->Flags = (sizeof(TCHAR) == sizeof(WCHAR)) ? SEC_WINNT_AUTH_IDENTITY_UNICODE : SEC_WINNT_AUTH_IDENTITY_ANSI; } VOID GetAuthdataExA( IN OPTIONAL PCSTR pszUserName, IN OPTIONAL PCSTR pszDomainName, IN OPTIONAL PCSTR pszPassword, IN OPTIONAL PCSTR pszPackageList, OUT SEC_WINNT_AUTH_IDENTITY_EXA* pAuthDataEx ) { DebugPrintf(SSPI_LOG, "GetAuthdataExW pszUserName %s, pszDomainName %s, pszPassword %s, pszPackageList %s\n", pszUserName, pszDomainName, pszPassword, pszPackageList); pAuthDataEx->Version = SEC_WINNT_AUTH_IDENTITY_VERSION; pAuthDataEx->Length = sizeof(SEC_WINNT_AUTH_IDENTITY_EXA); pAuthDataEx->Domain = (UCHAR*) pszDomainName; pAuthDataEx->DomainLength = pszDomainName ? strlen(pszDomainName) : 0; pAuthDataEx->Password = (UCHAR*) pszPassword; pAuthDataEx->PasswordLength = pszPassword ? strlen(pszPassword) : 0; pAuthDataEx->User = (UCHAR*) pszUserName; pAuthDataEx->UserLength = pszUserName ? strlen(pszUserName) : 0; pAuthDataEx->PackageList = (UCHAR*) pszPackageList; pAuthDataEx->PackageListLength = pszPackageList ? strlen(pszPackageList) : 0; pAuthDataEx->Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; } VOID GetAuthdataExW( IN OPTIONAL PCWSTR pszUserName, IN OPTIONAL PCWSTR pszDomainName, IN OPTIONAL PCWSTR pszPassword, IN OPTIONAL PCWSTR pszPackageList, OUT SEC_WINNT_AUTH_IDENTITY_EXW* pAuthDataEx ) { DebugPrintf(SSPI_LOG, "GetAuthdataExW pszUserName %ws, pszDomainName %ws, pszPassword %ws, pszPackageList %ws\n", pszUserName, pszDomainName, pszPassword, pszPackageList); pAuthDataEx->Version = SEC_WINNT_AUTH_IDENTITY_VERSION; pAuthDataEx->Length = sizeof(SEC_WINNT_AUTH_IDENTITY_EXW); pAuthDataEx->Domain = (WCHAR*) pszDomainName; pAuthDataEx->DomainLength = pszDomainName ? wcslen(pszDomainName) : 0; pAuthDataEx->Password = (WCHAR*) pszPassword; pAuthDataEx->PasswordLength = pszPassword ? wcslen(pszPassword) : 0; pAuthDataEx->User = (WCHAR*) pszUserName; pAuthDataEx->UserLength = pszUserName ? wcslen(pszUserName) : 0; pAuthDataEx->PackageList = (WCHAR*) pszPackageList; pAuthDataEx->PackageListLength = pszPackageList ? wcslen(pszPackageList) : 0; pAuthDataEx->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; } HRESULT GetAuthdataWMarshalled( IN OPTIONAL PCWSTR pszUserName, IN OPTIONAL PCWSTR pszDomainName, IN OPTIONAL PCWSTR pszPassword, OUT SEC_WINNT_AUTH_IDENTITY_W** ppAuthData ) { THResult hRetval; PUCHAR pWhere = NULL; ULONG cbCredSize = ( ((pszUserName != NULL) ? wcslen(pszUserName) + 1 : 0) + ((pszDomainName != NULL) ? wcslen(pszDomainName) + 1 : 0) + ((pszPassword != NULL) ? wcslen(pszPassword) + 1 : 0) ) * sizeof(WCHAR) + ROUND_UP_COUNT(sizeof(SEC_WINNT_AUTH_IDENTITY_W), sizeof(ULONG_PTR)); *ppAuthData = (PSEC_WINNT_AUTH_IDENTITY_W) new CHAR[cbCredSize]; hRetval DBGCHK = (*ppAuthData) ? S_OK : E_OUTOFMEMORY; if (SUCCEEDED(hRetval)) { RtlZeroMemory((*ppAuthData), cbCredSize); pWhere = (PUCHAR) ((*ppAuthData) + 1); if (pszUserName != NULL) { (*ppAuthData)->UserLength = wcslen(pszUserName); (*ppAuthData)->User = (PWSTR) pWhere; RtlCopyMemory( pWhere, pszUserName, (*ppAuthData)->UserLength * sizeof(WCHAR) ); pWhere += ((*ppAuthData)->UserLength + 1) * sizeof(WCHAR); } if (pszDomainName != NULL) { (*ppAuthData)->DomainLength = wcslen(pszDomainName); (*ppAuthData)->Domain = (PWSTR) pWhere; RtlCopyMemory( pWhere, pszDomainName, (*ppAuthData)->DomainLength * sizeof(WCHAR) ); pWhere += ((*ppAuthData)->DomainLength + 1) * sizeof(WCHAR); } if (pszPassword != NULL) { (*ppAuthData)->PasswordLength = wcslen(pszPassword); (*ppAuthData)->Password = (PWSTR) pWhere; RtlCopyMemory( pWhere, pszPassword, (*ppAuthData)->PasswordLength * sizeof(WCHAR) ); pWhere += ((*ppAuthData)->PasswordLength + 1) * sizeof(WCHAR); } (*ppAuthData)->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE | SEC_WINNT_AUTH_IDENTITY_MARSHALLED; } return hRetval; } HRESULT GetAuthdataExWMarshalled( IN OPTIONAL PCWSTR pszUserName, IN OPTIONAL PCWSTR pszDomainName, IN OPTIONAL PCWSTR pszPassword, IN OPTIONAL PCWSTR pszPackageList, OUT SEC_WINNT_AUTH_IDENTITY_EXW** ppAuthData ) { THResult hRetval; PUCHAR pWhere = NULL; ULONG cbCredSize = ( ((pszUserName != NULL) ? wcslen(pszUserName) + 1 : 0) + ((pszDomainName != NULL) ? wcslen(pszDomainName) + 1 : 0) + ((pszPassword != NULL) ? wcslen(pszPassword) + 1 : 0) + ((pszPackageList != NULL) ? wcslen(pszPackageList) + 1 : 0) ) * sizeof(WCHAR) + ROUND_UP_COUNT(sizeof(SEC_WINNT_AUTH_IDENTITY_EXW), sizeof(ULONG_PTR)); *ppAuthData = (PSEC_WINNT_AUTH_IDENTITY_EXW) new CHAR[cbCredSize]; hRetval DBGCHK = (*ppAuthData) ? S_OK : E_OUTOFMEMORY; if (SUCCEEDED(hRetval)) { RtlZeroMemory((*ppAuthData), cbCredSize); (*ppAuthData)->Version = SEC_WINNT_AUTH_IDENTITY_VERSION; (*ppAuthData)->Length = sizeof(SEC_WINNT_AUTH_IDENTITY_EXW); pWhere = (PUCHAR) ((*ppAuthData) + 1); if (pszUserName != NULL) { (*ppAuthData)->UserLength = wcslen(pszUserName); (*ppAuthData)->User = (PWSTR) pWhere; RtlCopyMemory( pWhere, pszUserName, (*ppAuthData)->UserLength * sizeof(WCHAR) ); pWhere += ((*ppAuthData)->UserLength + 1) * sizeof(WCHAR); } if (pszDomainName != NULL) { (*ppAuthData)->DomainLength = wcslen(pszDomainName); (*ppAuthData)->Domain = (PWSTR) pWhere; RtlCopyMemory( pWhere, pszDomainName, (*ppAuthData)->DomainLength * sizeof(WCHAR) ); pWhere += ((*ppAuthData)->DomainLength + 1) * sizeof(WCHAR); } if (pszPassword != NULL) { (*ppAuthData)->PasswordLength = wcslen(pszPassword); (*ppAuthData)->Password = (PWSTR) pWhere; RtlCopyMemory( pWhere, pszPassword, (*ppAuthData)->PasswordLength * sizeof(WCHAR) ); pWhere += ((*ppAuthData)->PasswordLength + 1) * sizeof(WCHAR); } if (pszPackageList != NULL) { (*ppAuthData)->PackageListLength = wcslen(pszPackageList); (*ppAuthData)->PackageList = (PWSTR) pWhere; RtlCopyMemory( pWhere, pszPackageList, (*ppAuthData)->PackageListLength * sizeof(WCHAR) ); pWhere += ((*ppAuthData)->PackageListLength + 1) * sizeof(WCHAR); } (*ppAuthData)->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE | SEC_WINNT_AUTH_IDENTITY_MARSHALLED; } return hRetval; } NTSTATUS GetCredHandle( IN OPTIONAL PTSTR pszPrincipal, IN OPTIONAL LUID* pLogonID, IN PTSTR pszPackageName, IN OPTIONAL VOID* pAuthData, IN ULONG fCredentialUse, OUT CredHandle* phCred ) { TNtStatus Status = STATUS_SUCCESS; CredHandle hCred; TimeStamp Lifetime = {0}; TimeStamp CurrentTime = {0}; SecPkgCredentials_Names CredNames = {0}; TPrivilege* pPriv = NULL; SspiPrint(SSPI_LOG, TEXT("GetCredHandle pszPrincipal %s, pszPackageName %s, ") TEXT("fCredentialUse %#x, pLogonID %p, pAuthData %p\n"), pszPrincipal, pszPackageName, fCredentialUse, pLogonID, pAuthData); SecInvalidateHandle(&hCred); SecInvalidateHandle(phCred); if (pLogonID) { SspiPrint(SSPI_LOG, TEXT("LogonId %#x:%#x\n"), pLogonID->HighPart, pLogonID->LowPart); pPriv = new TPrivilege(SE_TCB_PRIVILEGE, TRUE); Status DBGCHK = pPriv ? pPriv->Validate() : E_OUTOFMEMORY; } if (NT_SUCCESS(Status)) { Status DBGCHK = AcquireCredentialsHandle( pszPrincipal, // NULL pszPackageName, fCredentialUse, // SECPKG_CRED_INBOUND, pLogonID, // NULL pAuthData, // ServerAuthIdentity, NULL, // GetKey NULL, // value to pass to GetKey &hCred, &Lifetime ); } if (pPriv) { delete pPriv; } if (NT_SUCCESS(Status)) { SspiPrint(SSPI_LOG, TEXT("CredHandle: %#x:%#x\n"), hCred.dwUpper, hCred.dwLower); SspiPrintSysTimeAsLocalTime(SSPI_LOG, TEXT("Lifetime"), &Lifetime); GetSystemTimeAsFileTime((PFILETIME) &CurrentTime); SspiPrintSysTimeAsLocalTime(SSPI_LOG, TEXT("Current Time"), &CurrentTime); DBGCFG1(Status, SEC_E_UNSUPPORTED_FUNCTION); Status DBGCHK = QueryCredentialsAttributes( &hCred, SECPKG_CRED_ATTR_NAMES, &CredNames ); if (SEC_E_UNSUPPORTED_FUNCTION == (NTSTATUS) Status) { Status DBGCHK = STATUS_SUCCESS; DebugPrintf(SSPI_WARN, "QueryCredentialsAttributesA does not support SECPKG_CRED_ATTR_NAMES\n"); } } if (NT_SUCCESS(Status)) { SspiPrint(SSPI_LOG, TEXT("Credential names: %s\n"), CredNames.sUserName); *phCred = hCred; SecInvalidateHandle(&hCred); } THResult hr; if (CredNames.sUserName) { hr DBGCHK = FreeContextBuffer(CredNames.sUserName); } if (SecIsValidHandle(&hCred)) { hr DBGCHK = FreeCredentialsHandle(&hCred); } return Status; } HRESULT CheckSecurityContextHandle( IN PCtxtHandle phCtxt ) { THResult hRetval = S_OK; LARGE_INTEGER CurrentTime = {0}; SecPkgContext_NativeNamesA NativeNamesA = {0}; SecPkgContext_DceInfo ContextDceInfo = {0}; SecPkgContext_Lifespan ContextLifespan = {0}; SecPkgContext_PackageInfoA ContextPackageInfo = {0}; SecPkgContext_NegotiationInfoA NegotiationInfo = {0}; SecPkgContext_Sizes ContextSizes = {0}; SecPkgContext_Flags ContextFlags = {0}; SecPkgContext_KeyInfoA KeyInfo = {0}; SecPkgContext_NamesA ContextNames = {0}; SecPkgContext_TargetInformation TargetInfo = {0}; SecPkgContext_SessionKey SessionKey = {0}; SecPkgContext_UserFlags UserFlags = {0}; DBGCFG1(hRetval, SEC_E_UNSUPPORTED_FUNCTION); // // Query as many attributes as possible // hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_SIZES, &ContextSizes ); if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "SECPKG_ATTR_SIZES cbBlockSize %#x, cbMaxSignature %#x, " "cbMaxToken %#x, cbSecurityTrailer %#x\n", ContextSizes.cbBlockSize, ContextSizes.cbMaxSignature, ContextSizes.cbMaxToken, ContextSizes.cbSecurityTrailer); hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_FLAGS, &ContextFlags ); } if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "SECPKG_ATTR_FLAGS %#x\n", ContextFlags.Flags); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_FLAGS\n"); } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_KEY_INFO, &KeyInfo ); } if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "SECPKG_ATTR_KEY_INFO EncryptAlgorithm %#x, KeySize %#x, " "sEncryptAlgorithmName %s, SignatureAlgorithm %#x, sSignatureAlgorithmName %s\n", KeyInfo.EncryptAlgorithm, KeyInfo.KeySize, KeyInfo.sEncryptAlgorithmName, KeyInfo.SignatureAlgorithm, KeyInfo.sSignatureAlgorithmName); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_KEY_INFO\n"); } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_NAMES, &ContextNames ); } if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "SECPKG_ATTR_NAMES sUserName %s\n", ContextNames.sUserName); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_NAMES\n"); } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_NATIVE_NAMES, &NativeNamesA ); } if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "SECPKG_ATTR_NATIVE_NAMES sClientName %s, sServerName %s\n", NativeNamesA.sClientName, NativeNamesA.sServerName); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_NATIVE_NAMES\n"); } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_DCE_INFO, &ContextDceInfo ); } if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "SECPKG_ATTR_DCE_INFO: AuthzSvc %#x, pPAC %ws\n", ContextDceInfo.AuthzSvc, ContextDceInfo.pPac); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_DCE_INFO\n"); } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_LIFESPAN, &ContextLifespan ); } if (SUCCEEDED(hRetval)) { DebugPrintLocalTime(SSPI_LOG, "SECPKG_ATTR_LIFESPAN Start", &ContextLifespan.tsStart); DebugPrintLocalTime(SSPI_LOG, "SECPKG_ATTR_LIFESPAN Expiry", &ContextLifespan.tsExpiry); GetSystemTimeAsFileTime((PFILETIME) &CurrentTime); DebugPrintSysTimeAsLocalTime(SSPI_LOG, "Current Time", &CurrentTime); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_LIFESPAN\n"); } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_PACKAGE_INFO, &ContextPackageInfo ); } if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "SECPKG_ATTR_PACKAGE_INFO cbMaxToken %#x, Comment %s, fCapabilities %#x, " "Name %s, wRPCID %#x, wVersion %#x\n", ContextPackageInfo.PackageInfo->cbMaxToken, ContextPackageInfo.PackageInfo->Comment, ContextPackageInfo.PackageInfo->fCapabilities, ContextPackageInfo.PackageInfo->Name, ContextPackageInfo.PackageInfo->wRPCID, ContextPackageInfo.PackageInfo->wVersion); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_PACKAGE_INFO\n"); } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_NEGOTIATION_INFO, &NegotiationInfo ); } if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "SECPKG_ATTR_NEGOTIATION_INFO cbMaxToken %#x, Comment %s, fCapabilities %#x, " "Name %s, wRPCID %#x, wVersion %#x, NegotiationState %#x\n", NegotiationInfo.PackageInfo->cbMaxToken, NegotiationInfo.PackageInfo->Comment, NegotiationInfo.PackageInfo->fCapabilities, NegotiationInfo.PackageInfo->Name, NegotiationInfo.PackageInfo->wRPCID, NegotiationInfo.PackageInfo->wVersion, NegotiationInfo.NegotiationState); } else if (STATUS_NOT_SUPPORTED == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; SspiPrint(SSPI_WARN, TEXT("QueryContextAttributes does not support SECPKG_ATTR_NEGOTIATION_INFO\n")); } if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_TARGET_INFORMATION, &TargetInfo ); } if (SUCCEEDED(hRetval)) { DebugPrintHex(SSPI_LOG, "SECPKG_ATTR_TARGET_INFORMATION", TargetInfo.MarshalledTargetInfoLength, TargetInfo.MarshalledTargetInfo); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_TARGET_INFORMATION\n"); } #if 0 SECPKG_ATTR_SESSION_KEY is Kernel mode only if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_SESSION_KEY, &SessionKey ); } if (SUCCEEDED(hRetval)) { DebugPrintHex(SSPI_LOG, "SECPKG_ATTR_SESSION_KEY", SessionKey.SessionKeyLength, SessionKey.SessionKey); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_SESSION_KEY\n"); } #endif if (SUCCEEDED(hRetval)) { hRetval DBGCHK = QueryContextAttributesA( phCtxt, SECPKG_ATTR_USER_FLAGS, &UserFlags ); } if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "SECPKG_ATTR_USER_FLAGS UserFlags %#x\n", UserFlags.UserFlags); } else if (SEC_E_UNSUPPORTED_FUNCTION == (HRESULT) hRetval) { hRetval DBGCHK = S_OK; DebugPrintf(SSPI_WARN, "QueryContextAttributesA does not support SECPKG_ATTR_SESSION_KEY\n"); } THResult hr; if (TargetInfo.MarshalledTargetInfo) { hr DBGCHK = FreeContextBuffer(TargetInfo.MarshalledTargetInfo); } if (SessionKey.SessionKeyLength) { hr DBGCHK = FreeContextBuffer(SessionKey.SessionKey); } if (NativeNamesA.sClientName != NULL) { hr DBGCHK = FreeContextBuffer(NativeNamesA.sClientName); } if (NativeNamesA.sServerName != NULL) { hr DBGCHK = FreeContextBuffer(NativeNamesA.sServerName); } if (ContextNames.sUserName) { hr DBGCHK = FreeContextBuffer(ContextNames.sUserName); } if (ContextPackageInfo.PackageInfo) { hr DBGCHK = FreeContextBuffer(ContextPackageInfo.PackageInfo); } if (NegotiationInfo.PackageInfo) { hr DBGCHK = FreeContextBuffer(NegotiationInfo.PackageInfo); } if (ContextDceInfo.pPac) { hr DBGCHK = FreeContextBuffer(ContextDceInfo.pPac); } return hRetval; } MSV1_0_AV_PAIR* SspAvlInit( IN VOID* pAvList ) { MSV1_0_AV_PAIR* pAvPair; pAvPair = (MSV1_0_AV_PAIR*) pAvList; if (!pAvPair) { return NULL; } pAvPair->AvId = MsvAvEOL; pAvPair->AvLen = 0; return pAvPair; } MSV1_0_AV_PAIR* SspAvlAdd( IN MSV1_0_AV_PAIR* pAvList, IN MSV1_0_AVID AvId, IN OPTIONAL UNICODE_STRING* pString, IN ULONG cAvList ) { MSV1_0_AV_PAIR* pCurPair; if ((NULL == pString) || (0 == pString->Length) || (NULL == pString->Buffer)) { return NULL; } // // find the EOL // pCurPair = SspAvlGet(pAvList, MsvAvEOL, cAvList); if (pCurPair == NULL) { return NULL; } // // check for enough space in the av list buffer, then append the new AvPair // (assume the buffer is long enough!) // if ( (((UCHAR*) pCurPair) - ((UCHAR*)pAvList)) + sizeof(MSV1_0_AV_PAIR) * 2 + pString->Length > cAvList) { return NULL; } pCurPair->AvId = (USHORT) AvId; pCurPair->AvLen = (USHORT) pString->Length; RtlCopyMemory(pCurPair + 1, pString->Buffer, pCurPair->AvLen); // // top it off with a new EOL // pCurPair = (MSV1_0_AV_PAIR*) ((UCHAR*) pCurPair + sizeof(MSV1_0_AV_PAIR) + pCurPair->AvLen); pCurPair->AvId = MsvAvEOL; pCurPair->AvLen = 0; return pCurPair; } MSV1_0_AV_PAIR* SspAvlGet( IN MSV1_0_AV_PAIR* pAvList, IN MSV1_0_AVID AvId, IN ULONG cAvList ) { MSV1_0_AV_PAIR* pAvPair; pAvPair = pAvList; while (TRUE) { if (pAvPair->AvId == AvId) { return pAvPair; } if (pAvPair->AvId == MsvAvEOL) { return NULL; } cAvList -= (pAvPair->AvLen + sizeof(MSV1_0_AV_PAIR)); if (cAvList <= 0) { return NULL; } pAvPair = (MSV1_0_AV_PAIR*) ((UCHAR*) pAvPair + pAvPair->AvLen + sizeof(MSV1_0_AV_PAIR)); } } ULONG SspAvlLen( IN MSV1_0_AV_PAIR* pAvList, IN ULONG cAvList ) { MSV1_0_AV_PAIR* pCurPair; // // find the EOL // pCurPair = SspAvlGet(pAvList, MsvAvEOL, cAvList); if (pCurPair == NULL) { return 0; } // // compute length (not forgetting the EOL pair) // return (ULONG)(((UCHAR*) pCurPair - (UCHAR*) pAvList) + sizeof(MSV1_0_AV_PAIR)); } NTSTATUS CreateTargetInfo( IN UNICODE_STRING* pTargetName, OUT STRING* pTargetInfo ) { UNICODE_STRING DomainName = {0}; UNICODE_STRING ServerName = {0}; ULONG i = 0; MSV1_0_AV_PAIR* pAV; // // check length of name to make sure it fits in my buffer // if (pTargetName->Length > (DNS_MAX_NAME_LENGTH + CNLEN + 2) * sizeof(WCHAR)) { return STATUS_INVALID_PARAMETER; } // // init AV list in temp buffer // pAV = SspAvlInit(pTargetInfo->Buffer); if (!pAV) { return STATUS_INVALID_PARAMETER; } // // see if there's a NULL in the middle of the server name that indicates // that it's really a domain name followed by a server name // DomainName = *pTargetName; for (i = 0; i < (DomainName.Length / sizeof(WCHAR)); i++) { if (DomainName.Buffer[i] == L'\0') { // // take length of domain name without the NULL // DomainName.Length = (USHORT) i * sizeof(WCHAR); // // adjust server name and length to point after the domain name // ServerName.Length = (USHORT) (pTargetName->Length - (i + 1) * sizeof(WCHAR)); ServerName.Buffer = pTargetName->Buffer + (i + 1); break; } } // // strip off possible trailing null after the server name // for (i = 0; i < (ServerName.Length / sizeof(WCHAR)); i++) { if (ServerName.Buffer[i] == L'\0') { ServerName.Length = (USHORT) i * sizeof(WCHAR); break; } } // // put both names in the AV list (if both exist) // if (!SspAvlAdd(pAV, MsvAvNbDomainName, &DomainName, pTargetInfo->MaximumLength)) { return STATUS_INVALID_PARAMETER; } if ((ServerName.Length > 0) && !SspAvlAdd(pAV, MsvAvNbComputerName, &ServerName, pTargetInfo->MaximumLength)) { return STATUS_INVALID_PARAMETER; } // // make the request point at AV list instead of names. // pTargetInfo->Length = (USHORT) SspAvlLen(pAV, pTargetInfo->MaximumLength); pTargetInfo->Buffer = (CHAR*) pAV; return STATUS_SUCCESS; } NTSTATUS GetTargetInfo( IN ULONG TargetFlags, IN BOOLEAN bForceGuest, IN OPTIONAL UNICODE_STRING* pDnsDomainName, IN OPTIONAL UNICODE_STRING* pDnsComputerName, IN OPTIONAL UNICODE_STRING* pDnsTreeName, IN OPTIONAL UNICODE_STRING* pTargetName, IN OPTIONAL UNICODE_STRING* pComputerName, OUT UNICODE_STRING* pTargetInfo ) { TNtStatus Status; PMSV1_0_AV_PAIR pAV = NULL; ULONG cbAV = 0; ULONG AvFlags = 0; UNICODE_STRING* pDnsTargetName = NULL; if (TargetFlags == NTLMSSP_TARGET_TYPE_DOMAIN ) { pDnsTargetName = pDnsDomainName; } else { pDnsTargetName = pDnsComputerName; } cbAV = ( pTargetInfo ? pTargetName->Length : 0 ) + ( pComputerName ? pComputerName->Length : 0 ) + ( pDnsComputerName ? pDnsComputerName->Length : 0 ) + ( pDnsTargetName ? pDnsTargetName->Length : 0 ) + ( pDnsTreeName ? pDnsTreeName->Length : 0) + sizeof( AvFlags ) + (sizeof( MSV1_0_AV_PAIR ) * 6) + sizeof( MSV1_0_AV_PAIR); pTargetInfo->Buffer = new WCHAR[cbAV]; Status DBGCHK = pTargetInfo->Buffer ? STATUS_SUCCESS : STATUS_NO_MEMORY; if (NT_SUCCESS(Status)) { RtlZeroMemory(pTargetInfo->Buffer, cbAV); pAV = SspAvlInit(pTargetInfo->Buffer); SspAvlAdd( pAV, MsvAvNbDomainName, pTargetName, cbAV ); SspAvlAdd( pAV, MsvAvNbComputerName, pComputerName, cbAV ); SspAvlAdd( pAV, MsvAvDnsDomainName, pDnsTargetName, cbAV ); SspAvlAdd( pAV, MsvAvDnsComputerName, pDnsComputerName, cbAV ); SspAvlAdd( pAV, MsvAvDnsTreeName, pDnsTreeName, cbAV ); // // add in AvFlags into TargetInfo, if applicable. // if (bForceGuest) { AvFlags |= MSV1_0_AV_FLAG_FORCE_GUEST; } if (AvFlags) { UNICODE_STRING AvString; AvString.Buffer = (PWSTR)&AvFlags; AvString.Length = sizeof( AvFlags ); AvString.MaximumLength = AvString.Length; SspAvlAdd( pAV, MsvAvFlags, &AvString, cbAV ); } pTargetInfo->MaximumLength = pTargetInfo->Length = (USHORT) SspAvlLen(pAV, cbAV); } return Status; } NTSTATUS SspConvertRelativeToAbsolute( IN VOID* pMessageBase, IN ULONG cbMessageSize, IN STRING32* pStringToRelocate, IN BOOLEAN AlignToWchar, IN BOOLEAN AllowNullString, OUT STRING* pOutputString ) { ULONG Offset; // // If the buffer is allowed to be null, // check that special case. // if (AllowNullString && (pStringToRelocate->Length == 0)) { pOutputString->MaximumLength = pOutputString->Length = pStringToRelocate->Length; pOutputString->Buffer = NULL; return STATUS_SUCCESS; } // // Ensure the string in entirely within the message. // Offset = (ULONG)pStringToRelocate->Buffer; if (Offset >= cbMessageSize || Offset + pStringToRelocate->Length > cbMessageSize) { return STATUS_INVALID_PARAMETER; } // // Ensure the buffer is properly aligned. // if ( AlignToWchar && (!COUNT_IS_ALIGNED(Offset, ALIGN_WCHAR) || !COUNT_IS_ALIGNED(pStringToRelocate->Length, ALIGN_WCHAR)) ) { return STATUS_INVALID_PARAMETER; } // // Finally make the pointer absolute. // pOutputString->Buffer = (CHAR*)(pMessageBase) + Offset; pOutputString->MaximumLength = pOutputString->Length = pStringToRelocate->Length ; return STATUS_SUCCESS; } VOID SspCopyStringAsString32( IN VOID* pMessageBuffer, IN OPTIONAL STRING* pInString, IN OUT UCHAR** ppWhere, OUT STRING32* pOutString32 ) { // // Copy the data to the Buffer // if (pInString && pInString->Buffer != NULL) { RtlCopyMemory(*ppWhere, pInString->Buffer, pInString->Length); } // // Build a descriptor to the newly copied data // pOutString32->Length = pOutString32->MaximumLength = pInString ? pInString->Length : 0; pOutString32->Buffer = (ULONG)(*ppWhere - (UCHAR*)(pMessageBuffer)); // // Update Where to point past the copied data // *ppWhere += pInString ? pInString->Length : 0; } HRESULT IsContinueNeeded( IN HRESULT hr ) { if (SEC_E_OK == hr) { return S_FALSE; } else if ((SEC_I_CONTINUE_NEEDED == hr) || (SEC_I_COMPLETE_AND_CONTINUE == hr)) { return S_OK; } else { return hr; } } HRESULT IsCompleteNeeded( IN HRESULT hr ) { if (SEC_E_OK == hr) { return S_FALSE; } else if ((SEC_I_COMPLETE_NEEDED == hr) || (SEC_I_COMPLETE_AND_CONTINUE == hr)) { return S_OK; } else { return hr; } } HRESULT CheckSecurityPackage( IN OPTIONAL PCSTR pszPackageName ) { THResult hRetval = S_OK; ULONG cPackages = 0; PSecPkgInfoA pPackageInfo = NULL; hRetval DBGCHK = EnumerateSecurityPackagesA(&cPackages, &pPackageInfo); if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "PackageCount: %d\n", cPackages); for (ULONG Index = 0; Index < cPackages ; Index++ ) { DebugPrintf(SSPI_LOG, "*********Package %d:*************\n", Index); DebugPrintf(SSPI_LOG, "Name: %s Comment: %s\n", pPackageInfo[Index].Name, pPackageInfo[Index].Comment ); DebugPrintf(SSPI_LOG, "Cap: %#x Version: %#x RPCid: %#x MaxToken: %#x\n\n", pPackageInfo[Index].fCapabilities, pPackageInfo[Index].wVersion, pPackageInfo[Index].wRPCID, pPackageInfo[Index].cbMaxToken); } } THResult hr; if (pPackageInfo) { hr DBGCHK = FreeContextBuffer(pPackageInfo); pPackageInfo = NULL; } if (SUCCEEDED(hRetval) && pszPackageName) { hRetval DBGCHK = QuerySecurityPackageInfoA((SEC_CHAR *)pszPackageName, &pPackageInfo); if (SUCCEEDED(hRetval)) { DebugPrintf(SSPI_LOG, "Name: %s Comment: %s\n", pPackageInfo->Name, pPackageInfo->Comment ); DebugPrintf(SSPI_LOG, "Cap: %#x Version: %#x RPCid: %#x MaxToken: %#x\n\n", pPackageInfo->fCapabilities, pPackageInfo->wVersion, pPackageInfo->wRPCID, pPackageInfo->cbMaxToken); } } if (pPackageInfo) { hr DBGCHK = FreeContextBuffer(pPackageInfo); } return hRetval; } HRESULT SetProcessOptions( IN HANDLE hLsa, IN ULONG MsvPackageId, IN ULONG ProcessOptions ) { THResult hRetval = E_FAIL; MSV1_0_SETPROCESSOPTION_REQUEST OptionsRequest; PVOID pResponse = NULL; ULONG cbResponse = 0; NTSTATUS ProtocolStatus = STATUS_UNSUCCESSFUL; RtlZeroMemory(&OptionsRequest, sizeof(OptionsRequest)); OptionsRequest.MessageType = (MSV1_0_PROTOCOL_MESSAGE_TYPE) MsV1_0SetProcessOption; OptionsRequest.ProcessOptions = ProcessOptions; // MSV1_0_OPTION_ALLOW_BLANK_PASSWORD | MSV1_0_OPTION_DISABLE_ADMIN_LOCKOUT OptionsRequest.DisableOptions = FALSE; SspiPrint(SSPI_LOG, TEXT("SetProcessOptions %#x, PackageId %#x\n"), ProcessOptions, MsvPackageId); hRetval DBGCHK = LsaCallAuthenticationPackage( hLsa, MsvPackageId, &OptionsRequest, sizeof(OptionsRequest), &pResponse, &cbResponse, &ProtocolStatus ); if (NT_SUCCESS(hRetval)) { hRetval DBGCHK = ProtocolStatus; } return hRetval; }