Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1366 lines
38 KiB

/*++
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 <ntlmsp.h>
#include <tchar.h>
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;
}