1245 lines
38 KiB
C++
1245 lines
38 KiB
C++
|
//+-----------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation 1992 - 1996
|
||
|
//
|
||
|
// File: kerbwow.cxx
|
||
|
//
|
||
|
// Contents: Code for 32-64 bit interop for the Kerberos package
|
||
|
//
|
||
|
//
|
||
|
// History: 25-Oct-2000 JSchwart Created
|
||
|
//
|
||
|
//------------------------------------------------------------------------
|
||
|
|
||
|
#include <kerb.hxx>
|
||
|
#include <kerbp.h>
|
||
|
|
||
|
#ifdef _WIN64
|
||
|
|
||
|
#ifdef DEBUG_SUPPORT
|
||
|
static TCHAR THIS_FILE[]=TEXT(__FILE__);
|
||
|
#endif
|
||
|
|
||
|
#define FILENO FILENO_KERBWOW
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// WOW versions of public Kerberos logon buffer structures. These MUST
|
||
|
// be kept in sync with their public counterparts!
|
||
|
//
|
||
|
|
||
|
typedef struct _KERB_INTERACTIVE_LOGON_WOW64
|
||
|
{
|
||
|
KERB_LOGON_SUBMIT_TYPE MessageType;
|
||
|
UNICODE_STRING_WOW64 LogonDomainName;
|
||
|
UNICODE_STRING_WOW64 UserName;
|
||
|
UNICODE_STRING_WOW64 Password;
|
||
|
}
|
||
|
KERB_INTERACTIVE_LOGON_WOW64, *PKERB_INTERACTIVE_LOGON_WOW64;
|
||
|
|
||
|
|
||
|
typedef struct _KERB_INTERACTIVE_UNLOCK_LOGON_WOW64
|
||
|
{
|
||
|
KERB_INTERACTIVE_LOGON_WOW64 Logon;
|
||
|
LUID LogonId;
|
||
|
}
|
||
|
KERB_INTERACTIVE_UNLOCK_LOGON_WOW64, *PKERB_INTERACTIVE_UNLOCK_LOGON_WOW64;
|
||
|
|
||
|
|
||
|
typedef struct _KERB_SMART_CARD_LOGON_WOW64
|
||
|
{
|
||
|
KERB_LOGON_SUBMIT_TYPE MessageType;
|
||
|
UNICODE_STRING_WOW64 Pin;
|
||
|
ULONG CspDataLength;
|
||
|
ULONG CspData;
|
||
|
}
|
||
|
KERB_SMART_CARD_LOGON_WOW64, *PKERB_SMART_CARD_LOGON_WOW64;
|
||
|
|
||
|
|
||
|
typedef struct _KERB_SMART_CARD_UNLOCK_LOGON_WOW64
|
||
|
{
|
||
|
KERB_SMART_CARD_LOGON_WOW64 Logon;
|
||
|
LUID LogonId;
|
||
|
}
|
||
|
KERB_SMART_CARD_UNLOCK_LOGON_WOW64, *PKERB_SMART_CARD_UNLOCK_LOGON_WOW64;
|
||
|
|
||
|
|
||
|
typedef struct _KERB_TICKET_LOGON_WOW64
|
||
|
{
|
||
|
KERB_LOGON_SUBMIT_TYPE MessageType;
|
||
|
ULONG Flags;
|
||
|
ULONG ServiceTicketLength;
|
||
|
ULONG TicketGrantingTicketLength;
|
||
|
ULONG ServiceTicket;
|
||
|
ULONG TicketGrantingTicket;
|
||
|
}
|
||
|
KERB_TICKET_LOGON_WOW64, *PKERB_TICKET_LOGON_WOW64;
|
||
|
|
||
|
typedef struct _KERB_TICKET_UNLOCK_LOGON_WOW64
|
||
|
{
|
||
|
KERB_TICKET_LOGON_WOW64 Logon;
|
||
|
LUID LogonId;
|
||
|
}
|
||
|
KERB_TICKET_UNLOCK_LOGON_WOW64, *PKERB_TICKET_UNLOCK_LOGON_WOW64;
|
||
|
|
||
|
|
||
|
//
|
||
|
// WOW versions of public Kerberos profile buffer structures. These MUST
|
||
|
// be kept in sync with their public counterparts!
|
||
|
//
|
||
|
|
||
|
typedef struct _KERB_INTERACTIVE_PROFILE_WOW64
|
||
|
{
|
||
|
KERB_PROFILE_BUFFER_TYPE MessageType;
|
||
|
USHORT LogonCount;
|
||
|
USHORT BadPasswordCount;
|
||
|
LARGE_INTEGER LogonTime;
|
||
|
LARGE_INTEGER LogoffTime;
|
||
|
LARGE_INTEGER KickOffTime;
|
||
|
LARGE_INTEGER PasswordLastSet;
|
||
|
LARGE_INTEGER PasswordCanChange;
|
||
|
LARGE_INTEGER PasswordMustChange;
|
||
|
UNICODE_STRING_WOW64 LogonScript;
|
||
|
UNICODE_STRING_WOW64 HomeDirectory;
|
||
|
UNICODE_STRING_WOW64 FullName;
|
||
|
UNICODE_STRING_WOW64 ProfilePath;
|
||
|
UNICODE_STRING_WOW64 HomeDirectoryDrive;
|
||
|
UNICODE_STRING_WOW64 LogonServer;
|
||
|
ULONG UserFlags;
|
||
|
}
|
||
|
KERB_INTERACTIVE_PROFILE_WOW64, *PKERB_INTERACTIVE_PROFILE_WOW64;
|
||
|
|
||
|
typedef struct _KERB_SMART_CARD_PROFILE_WOW64
|
||
|
{
|
||
|
KERB_INTERACTIVE_PROFILE_WOW64 Profile;
|
||
|
ULONG CertificateSize;
|
||
|
ULONG CertificateData;
|
||
|
}
|
||
|
KERB_SMART_CARD_PROFILE_WOW64, *PKERB_SMART_CARD_PROFILE_WOW64;
|
||
|
|
||
|
typedef struct KERB_CRYPTO_KEY_WOW64
|
||
|
{
|
||
|
LONG KeyType;
|
||
|
ULONG Length;
|
||
|
ULONG Value;
|
||
|
}
|
||
|
KERB_CRYPTO_KEY_WOW64, *PKERB_CRYPTO_KEY_WOW64;
|
||
|
|
||
|
typedef struct _KERB_TICKET_PROFILE_WOW64
|
||
|
{
|
||
|
KERB_INTERACTIVE_PROFILE_WOW64 Profile;
|
||
|
KERB_CRYPTO_KEY_WOW64 SessionKey;
|
||
|
}
|
||
|
KERB_TICKET_PROFILE_WOW64, *PKERB_TICKET_PROFILE_WOW64;
|
||
|
|
||
|
typedef struct _KERB_INTERNAL_NAME_WOW64
|
||
|
{
|
||
|
SHORT NameType;
|
||
|
USHORT NameCount;
|
||
|
UNICODE_STRING_WOW64 Names[ANYSIZE_ARRAY];
|
||
|
}
|
||
|
KERB_INTERNAL_NAME_WOW64, *PKERB_INTERNAL_NAME_WOW64;
|
||
|
|
||
|
typedef struct _KERB_EXTERNAL_NAME_WOW64
|
||
|
{
|
||
|
SHORT NameType;
|
||
|
USHORT NameCount;
|
||
|
UNICODE_STRING_WOW64 Names[ANYSIZE_ARRAY];
|
||
|
}
|
||
|
KERB_EXTERNAL_NAME_WOW64, *PKERB_EXTERNAL_NAME_WOW64;
|
||
|
|
||
|
typedef struct _KERB_EXTERNAL_TICKET_WOW64
|
||
|
{
|
||
|
ULONG ServiceName;
|
||
|
ULONG TargetName;
|
||
|
ULONG ClientName;
|
||
|
UNICODE_STRING_WOW64 DomainName;
|
||
|
UNICODE_STRING_WOW64 TargetDomainName;
|
||
|
UNICODE_STRING_WOW64 AltTargetDomainName;
|
||
|
KERB_CRYPTO_KEY_WOW64 SessionKey;
|
||
|
ULONG TicketFlags;
|
||
|
ULONG Flags;
|
||
|
LARGE_INTEGER KeyExpirationTime;
|
||
|
LARGE_INTEGER StartTime;
|
||
|
LARGE_INTEGER EndTime;
|
||
|
LARGE_INTEGER RenewUntil;
|
||
|
LARGE_INTEGER TimeSkew;
|
||
|
ULONG EncodedTicketSize;
|
||
|
ULONG EncodedTicket;
|
||
|
}
|
||
|
KERB_EXTERNAL_TICKET_WOW64, *PKERB_EXTERNAL_TICKET_WOW64;
|
||
|
|
||
|
typedef struct _KERB_EXTERNAL_TICKET_EX_WOW64
|
||
|
{
|
||
|
PKERB_EXTERNAL_NAME_WOW64 ClientName;
|
||
|
PKERB_EXTERNAL_NAME_WOW64 ServiceName;
|
||
|
PKERB_EXTERNAL_NAME_WOW64 TargetName;
|
||
|
UNICODE_STRING_WOW64 ClientRealm;
|
||
|
UNICODE_STRING_WOW64 ServerRealm;
|
||
|
UNICODE_STRING_WOW64 TargetDomainName;
|
||
|
UNICODE_STRING_WOW64 AltTargetDomainName;
|
||
|
KERB_CRYPTO_KEY_WOW64 SessionKey;
|
||
|
ULONG TicketFlags;
|
||
|
ULONG Flags;
|
||
|
LARGE_INTEGER KeyExpirationTime;
|
||
|
LARGE_INTEGER StartTime;
|
||
|
LARGE_INTEGER EndTime;
|
||
|
LARGE_INTEGER RenewUntil;
|
||
|
LARGE_INTEGER TimeSkew;
|
||
|
PKERB_NET_ADDRESSES TicketAddresses;
|
||
|
PKERB_AUTH_DATA AuthorizationData;
|
||
|
_KERB_EXTERNAL_TICKET_EX_WOW64 * SecondTicket;
|
||
|
ULONG EncodedTicketSize;
|
||
|
PUCHAR EncodedTicket;
|
||
|
}
|
||
|
KERB_EXTERNAL_TICKET_EX_WOW64, *PKERB_EXTERNAL_TICKET_EX_WOW64;
|
||
|
|
||
|
|
||
|
#define RELOCATE_WOW_UNICODE_STRING(WOWString, NativeString, Offset) \
|
||
|
NativeString.Length = WOWString.Length; \
|
||
|
NativeString.MaximumLength = WOWString.MaximumLength; \
|
||
|
NativeString.Buffer = (LPWSTR) ((LPBYTE) UlongToPtr(WOWString.Buffer) + Offset);
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: KerbPutWOWString
|
||
|
//
|
||
|
// Synopsis: Copies a UNICODE_STRING into a buffer
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: InputString - String to 'put'
|
||
|
// OutputString - Receives 'put' string
|
||
|
// Offset - Difference in addresses of local and client buffers.
|
||
|
// Where - Location in local buffer to place string.
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Notes: This code is (effectively) duplicated in
|
||
|
// KerbPutString. Make sure any changes
|
||
|
// made here are applied there as well.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
VOID
|
||
|
KerbPutWOWString(
|
||
|
IN PUNICODE_STRING InputString,
|
||
|
OUT PUNICODE_STRING_WOW64 OutputString,
|
||
|
IN LONG_PTR Offset,
|
||
|
IN OUT PBYTE * Where
|
||
|
)
|
||
|
{
|
||
|
OutputString->Length = OutputString->MaximumLength = InputString->Length;
|
||
|
OutputString->Buffer = PtrToUlong (*Where + Offset);
|
||
|
RtlCopyMemory(
|
||
|
*Where,
|
||
|
InputString->Buffer,
|
||
|
InputString->Length
|
||
|
);
|
||
|
*Where += InputString->Length;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: KerbPutWOWKdcName
|
||
|
//
|
||
|
// Synopsis: Copies a Kdc name to a buffer
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Notes: This code is (effectively) duplicated in
|
||
|
// KerbPutKdcName. Make sure any changes
|
||
|
// made here are applied there as well.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
VOID
|
||
|
KerbPutWOWKdcName(
|
||
|
IN PKERB_INTERNAL_NAME InputName,
|
||
|
OUT PULONG OutputName,
|
||
|
IN LONG_PTR Offset,
|
||
|
IN OUT PBYTE * Where
|
||
|
)
|
||
|
{
|
||
|
ULONG Index;
|
||
|
PKERB_INTERNAL_NAME_WOW64 LocalName = (PKERB_INTERNAL_NAME_WOW64) *Where;
|
||
|
|
||
|
if (!ARGUMENT_PRESENT(InputName))
|
||
|
{
|
||
|
*OutputName = NULL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
*Where += sizeof(KERB_INTERNAL_NAME_WOW64) - sizeof(UNICODE_STRING_WOW64) +
|
||
|
InputName->NameCount * sizeof(UNICODE_STRING_WOW64);
|
||
|
|
||
|
LocalName->NameType = InputName->NameType;
|
||
|
LocalName->NameCount = InputName->NameCount;
|
||
|
|
||
|
for (Index = 0; Index < InputName->NameCount ; Index++ )
|
||
|
{
|
||
|
LocalName->Names[Index].Length =
|
||
|
LocalName->Names[Index].MaximumLength =
|
||
|
InputName->Names[Index].Length;
|
||
|
|
||
|
LocalName->Names[Index].Buffer = PtrToUlong(*Where + Offset);
|
||
|
|
||
|
RtlCopyMemory(*Where,
|
||
|
InputName->Names[Index].Buffer,
|
||
|
InputName->Names[Index].Length);
|
||
|
|
||
|
*Where += InputName->Names[Index].Length;
|
||
|
}
|
||
|
|
||
|
*Where = (PBYTE) ROUND_UP_POINTER(*Where, sizeof(ULONG));
|
||
|
|
||
|
*OutputName = PtrToUlong((PBYTE) LocalName + Offset);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: KerbPutKdcNameAsWOWString
|
||
|
//
|
||
|
// Synopsis: Copies a KERB_INTERNAL_NAME into a buffer
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: InputString - String to 'put'
|
||
|
// OutputString - Receives 'put' string
|
||
|
// Offset - Difference in addresses of local and client buffers.
|
||
|
// Where - Location in local buffer to place string.
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Notes: This code is (effectively) duplicated in
|
||
|
// KerbPutKdcNameAsString. Make sure any
|
||
|
// changes made here are applied there as well.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
VOID
|
||
|
KerbPutKdcNameAsWOWString(
|
||
|
IN PKERB_INTERNAL_NAME InputName,
|
||
|
OUT PUNICODE_STRING_WOW64 OutputName,
|
||
|
IN LONG_PTR Offset,
|
||
|
IN OUT PBYTE * Where
|
||
|
)
|
||
|
{
|
||
|
USHORT Index;
|
||
|
|
||
|
OutputName->Buffer = PtrToUlong (*Where + Offset);
|
||
|
OutputName->Length = 0;
|
||
|
OutputName->MaximumLength = 0;
|
||
|
|
||
|
for (Index = 0; Index < InputName->NameCount ; Index++ )
|
||
|
{
|
||
|
RtlCopyMemory(
|
||
|
*Where,
|
||
|
InputName->Names[Index].Buffer,
|
||
|
InputName->Names[Index].Length
|
||
|
);
|
||
|
*Where += InputName->Names[Index].Length;
|
||
|
OutputName->Length += InputName->Names[Index].Length;
|
||
|
if (Index == (InputName->NameCount - 1))
|
||
|
{
|
||
|
*((LPWSTR) *Where) = L'\0';
|
||
|
OutputName->MaximumLength = OutputName->Length + sizeof(WCHAR);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*((LPWSTR) *Where) = L'/';
|
||
|
OutputName->Length += sizeof(WCHAR);
|
||
|
}
|
||
|
*Where += sizeof(WCHAR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: KerbPutWOWClientString
|
||
|
//
|
||
|
// Synopsis: Copies a string into a buffer that will be copied to the
|
||
|
// 32-bit client's address space
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: Where - Location in local buffer to place string.
|
||
|
// Delta - Difference in addresses of local and client buffers.
|
||
|
// OutString - Receives 'put' string
|
||
|
// InString - String to 'put'
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Notes: This code is (effectively) duplicated in
|
||
|
// KerbPutClientString. Make sure any changes
|
||
|
// made here are applied there as well.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
VOID
|
||
|
KerbPutWOWClientString(
|
||
|
IN OUT PUCHAR * Where,
|
||
|
IN LONG_PTR Delta,
|
||
|
IN PUNICODE_STRING_WOW64 OutString,
|
||
|
IN PUNICODE_STRING InString
|
||
|
)
|
||
|
{
|
||
|
if (InString->Length == 0)
|
||
|
{
|
||
|
OutString->Buffer = 0;
|
||
|
OutString->Length = OutString->MaximumLength = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RtlCopyMemory(*Where,
|
||
|
InString->Buffer,
|
||
|
InString->Length);
|
||
|
|
||
|
OutString->Buffer = PtrToUlong(*Where + Delta);
|
||
|
OutString->Length = InString->Length;
|
||
|
*Where += InString->Length;
|
||
|
*(LPWSTR) (*Where) = L'\0';
|
||
|
*Where += sizeof(WCHAR);
|
||
|
OutString->MaximumLength = OutString->Length + sizeof(WCHAR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: KerbWOWNameLength
|
||
|
//
|
||
|
// Synopsis: returns length in bytes of variable portion
|
||
|
// of KERB_INTERNAL_NAME
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Notes: This code is (effectively) duplicated in
|
||
|
// KerbNameLength. Make sure any changes
|
||
|
// made here are applied there as well.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
ULONG
|
||
|
KerbWOWNameLength(
|
||
|
IN PKERB_INTERNAL_NAME Name
|
||
|
)
|
||
|
{
|
||
|
ULONG Length = 0;
|
||
|
ULONG Index;
|
||
|
|
||
|
if (!ARGUMENT_PRESENT(Name))
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Length = sizeof(KERB_INTERNAL_NAME_WOW64)
|
||
|
- sizeof(UNICODE_STRING_WOW64)
|
||
|
+ Name->NameCount * sizeof(UNICODE_STRING_WOW64);
|
||
|
|
||
|
for (Index = 0; Index < Name->NameCount ;Index++ )
|
||
|
{
|
||
|
Length += Name->Names[Index].Length;
|
||
|
}
|
||
|
|
||
|
Length = ROUND_UP_COUNT(Length, sizeof(ULONG));
|
||
|
|
||
|
return Length;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: KerbConvertWOWLogonBuffer
|
||
|
//
|
||
|
// Synopsis: Converts logon buffers passed in from WOW clients to 64-bit
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: ProtocolSubmitBuffer -- original 32-bit logon buffer
|
||
|
// pSubmitBufferSize -- size of the 32-bit logon buffer
|
||
|
// MessageType -- format of the logon buffer
|
||
|
// ppTempSubmitBuffer -- filled in with the converted buffer
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Notes: This routine allocates the converted buffer and returns it
|
||
|
// on success. It is the caller's responsibility to free it.
|
||
|
//
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS
|
||
|
KerbConvertWOWLogonBuffer(
|
||
|
IN PVOID ProtocolSubmitBuffer,
|
||
|
IN PVOID ClientBufferBase,
|
||
|
IN OUT PULONG pSubmitBufferSize,
|
||
|
IN KERB_LOGON_SUBMIT_TYPE MessageType,
|
||
|
OUT PVOID *ppTempSubmitBuffer
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
PVOID pTempBuffer = NULL;
|
||
|
ULONG dwBufferSize = *pSubmitBufferSize;
|
||
|
|
||
|
switch (MessageType)
|
||
|
{
|
||
|
case KerbInteractiveLogon:
|
||
|
case KerbWorkstationUnlockLogon:
|
||
|
{
|
||
|
PKERB_INTERACTIVE_LOGON Logon;
|
||
|
PKERB_INTERACTIVE_LOGON_WOW64 LogonWOW;
|
||
|
DWORD dwOffset;
|
||
|
DWORD dwWOWOffset;
|
||
|
|
||
|
//
|
||
|
// Scale up the size and add on 3 PVOIDs for the worst-case
|
||
|
// scenario to align the three embedded UNICODE_STRINGs
|
||
|
//
|
||
|
|
||
|
dwBufferSize += sizeof(KERB_INTERACTIVE_LOGON)
|
||
|
- sizeof(KERB_INTERACTIVE_LOGON_WOW64);
|
||
|
|
||
|
if (dwBufferSize < sizeof(KERB_INTERACTIVE_LOGON))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR,
|
||
|
"Submit buffer to logon too small: %d. %ws, line %d\n",
|
||
|
dwBufferSize,
|
||
|
THIS_FILE,
|
||
|
__LINE__));
|
||
|
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pTempBuffer = KerbAllocate(dwBufferSize);
|
||
|
|
||
|
if (pTempBuffer == NULL)
|
||
|
{
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Logon = (PKERB_INTERACTIVE_LOGON) pTempBuffer;
|
||
|
LogonWOW = (PKERB_INTERACTIVE_LOGON_WOW64) ProtocolSubmitBuffer;
|
||
|
|
||
|
Logon->MessageType = LogonWOW->MessageType;
|
||
|
|
||
|
dwOffset = sizeof(KERB_INTERACTIVE_LOGON);
|
||
|
dwWOWOffset = sizeof(KERB_INTERACTIVE_LOGON_WOW64);
|
||
|
|
||
|
if (MessageType == KerbWorkstationUnlockLogon)
|
||
|
{
|
||
|
if (dwBufferSize < sizeof(KERB_INTERACTIVE_UNLOCK_LOGON))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR,
|
||
|
"Submit buffer to logon too small: %d. %ws, line %d\n",
|
||
|
dwBufferSize,
|
||
|
THIS_FILE,
|
||
|
__LINE__));
|
||
|
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// One additional field for this type (a LUID)
|
||
|
//
|
||
|
|
||
|
PKERB_INTERACTIVE_UNLOCK_LOGON Unlock;
|
||
|
PKERB_INTERACTIVE_UNLOCK_LOGON_WOW64 UnlockWOW;
|
||
|
|
||
|
Unlock = (PKERB_INTERACTIVE_UNLOCK_LOGON) pTempBuffer;
|
||
|
UnlockWOW = (PKERB_INTERACTIVE_UNLOCK_LOGON_WOW64) ProtocolSubmitBuffer;
|
||
|
|
||
|
Unlock->LogonId = UnlockWOW->LogonId;
|
||
|
|
||
|
dwOffset = sizeof(KERB_INTERACTIVE_UNLOCK_LOGON);
|
||
|
dwWOWOffset = sizeof(KERB_INTERACTIVE_UNLOCK_LOGON_WOW64);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the variable-length data
|
||
|
//
|
||
|
|
||
|
RtlCopyMemory((LPBYTE) Logon + dwOffset,
|
||
|
(LPBYTE) LogonWOW + dwWOWOffset,
|
||
|
*pSubmitBufferSize - dwWOWOffset);
|
||
|
|
||
|
//
|
||
|
// Set up the pointers in the native struct
|
||
|
//
|
||
|
|
||
|
RELOCATE_WOW_UNICODE_STRING(LogonWOW->LogonDomainName,
|
||
|
Logon->LogonDomainName,
|
||
|
dwOffset - dwWOWOffset);
|
||
|
|
||
|
RELOCATE_WOW_UNICODE_STRING(LogonWOW->UserName,
|
||
|
Logon->UserName,
|
||
|
dwOffset - dwWOWOffset);
|
||
|
|
||
|
RELOCATE_WOW_UNICODE_STRING(LogonWOW->Password,
|
||
|
Logon->Password,
|
||
|
dwOffset - dwWOWOffset);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case KerbSmartCardLogon:
|
||
|
case KerbSmartCardUnlockLogon:
|
||
|
{
|
||
|
PKERB_SMART_CARD_LOGON Logon;
|
||
|
PKERB_SMART_CARD_LOGON_WOW64 LogonWOW;
|
||
|
DWORD dwOffset;
|
||
|
DWORD dwWOWOffset;
|
||
|
|
||
|
//
|
||
|
// Scale up the size and add on 2 PVOIDs for the worst-case
|
||
|
// scenario to align the embedded UNICODE_STRING and CspData
|
||
|
//
|
||
|
|
||
|
dwBufferSize += sizeof(KERB_SMART_CARD_LOGON)
|
||
|
- sizeof(KERB_SMART_CARD_LOGON_WOW64);
|
||
|
|
||
|
if (dwBufferSize < sizeof(KERB_SMART_CARD_LOGON))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR,
|
||
|
"Submit buffer to logon too small: %d. %ws, line %d\n",
|
||
|
dwBufferSize,
|
||
|
THIS_FILE,
|
||
|
__LINE__));
|
||
|
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pTempBuffer = KerbAllocate(dwBufferSize);
|
||
|
|
||
|
if (pTempBuffer == NULL)
|
||
|
{
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Logon = (PKERB_SMART_CARD_LOGON) pTempBuffer;
|
||
|
LogonWOW = (PKERB_SMART_CARD_LOGON_WOW64) ProtocolSubmitBuffer;
|
||
|
|
||
|
Logon->MessageType = LogonWOW->MessageType;
|
||
|
Logon->CspDataLength = LogonWOW->CspDataLength;
|
||
|
|
||
|
dwOffset = sizeof(KERB_SMART_CARD_LOGON);
|
||
|
dwWOWOffset = sizeof(KERB_SMART_CARD_LOGON_WOW64);
|
||
|
|
||
|
if (MessageType == KerbSmartCardUnlockLogon)
|
||
|
{
|
||
|
if (dwBufferSize < sizeof(KERB_SMART_CARD_UNLOCK_LOGON))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR,
|
||
|
"Submit buffer to logon too small: %d. %ws, line %d\n",
|
||
|
dwBufferSize,
|
||
|
THIS_FILE,
|
||
|
__LINE__));
|
||
|
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// One additional field for this type (a LUID)
|
||
|
//
|
||
|
|
||
|
PKERB_SMART_CARD_UNLOCK_LOGON Unlock;
|
||
|
PKERB_SMART_CARD_UNLOCK_LOGON_WOW64 UnlockWOW;
|
||
|
|
||
|
Unlock = (PKERB_SMART_CARD_UNLOCK_LOGON) pTempBuffer;
|
||
|
UnlockWOW = (PKERB_SMART_CARD_UNLOCK_LOGON_WOW64) ProtocolSubmitBuffer;
|
||
|
|
||
|
Unlock->LogonId = UnlockWOW->LogonId;
|
||
|
|
||
|
dwOffset = sizeof(KERB_SMART_CARD_UNLOCK_LOGON);
|
||
|
dwWOWOffset = sizeof(KERB_SMART_CARD_UNLOCK_LOGON_WOW64);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the variable-length data
|
||
|
//
|
||
|
|
||
|
RtlCopyMemory((LPBYTE) Logon + dwOffset,
|
||
|
(LPBYTE) LogonWOW + dwWOWOffset,
|
||
|
*pSubmitBufferSize - dwWOWOffset);
|
||
|
|
||
|
//
|
||
|
// Set up the pointers in the native struct
|
||
|
//
|
||
|
|
||
|
RELOCATE_WOW_UNICODE_STRING(LogonWOW->Pin,
|
||
|
Logon->Pin,
|
||
|
dwOffset - dwWOWOffset);
|
||
|
|
||
|
Logon->CspData = (PUCHAR) ((LPBYTE) UlongToPtr(LogonWOW->CspData) + (dwOffset - dwWOWOffset));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case KerbTicketLogon:
|
||
|
case KerbTicketUnlockLogon:
|
||
|
{
|
||
|
PKERB_TICKET_LOGON Logon;
|
||
|
PKERB_TICKET_LOGON_WOW64 LogonWOW;
|
||
|
DWORD dwOffset;
|
||
|
DWORD dwWOWOffset;
|
||
|
|
||
|
//
|
||
|
// Scale up the size and add on 2 PVOIDs for the worst-case
|
||
|
// scenario to align the two embedded pointers
|
||
|
//
|
||
|
|
||
|
dwBufferSize += sizeof(KERB_TICKET_LOGON)
|
||
|
- sizeof(KERB_TICKET_LOGON_WOW64);
|
||
|
|
||
|
if (dwBufferSize < sizeof(KERB_TICKET_LOGON))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR,
|
||
|
"Submit buffer to logon too small: %d. %ws, line %d\n",
|
||
|
dwBufferSize,
|
||
|
THIS_FILE,
|
||
|
__LINE__));
|
||
|
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pTempBuffer = KerbAllocate(dwBufferSize);
|
||
|
|
||
|
if (pTempBuffer == NULL)
|
||
|
{
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Logon = (PKERB_TICKET_LOGON) pTempBuffer;
|
||
|
LogonWOW = (PKERB_TICKET_LOGON_WOW64) ProtocolSubmitBuffer;
|
||
|
|
||
|
Logon->MessageType = LogonWOW->MessageType;
|
||
|
Logon->Flags = LogonWOW->Flags;
|
||
|
Logon->ServiceTicketLength = LogonWOW->ServiceTicketLength;
|
||
|
Logon->TicketGrantingTicketLength = LogonWOW->TicketGrantingTicketLength;
|
||
|
|
||
|
dwOffset = sizeof(KERB_TICKET_LOGON);
|
||
|
dwWOWOffset = sizeof(KERB_TICKET_LOGON_WOW64);
|
||
|
|
||
|
if (MessageType == KerbTicketUnlockLogon)
|
||
|
{
|
||
|
if (dwBufferSize < sizeof(KERB_TICKET_UNLOCK_LOGON))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR,
|
||
|
"Submit buffer to logon too small: %d. %ws, line %d\n",
|
||
|
dwBufferSize,
|
||
|
THIS_FILE,
|
||
|
__LINE__));
|
||
|
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// One additional field for this type (a LUID)
|
||
|
//
|
||
|
|
||
|
PKERB_TICKET_UNLOCK_LOGON Unlock;
|
||
|
PKERB_TICKET_UNLOCK_LOGON_WOW64 UnlockWOW;
|
||
|
|
||
|
Unlock = (PKERB_TICKET_UNLOCK_LOGON) pTempBuffer;
|
||
|
UnlockWOW = (PKERB_TICKET_UNLOCK_LOGON_WOW64) ProtocolSubmitBuffer;
|
||
|
|
||
|
Unlock->LogonId = UnlockWOW->LogonId;
|
||
|
|
||
|
dwOffset = sizeof(KERB_TICKET_UNLOCK_LOGON);
|
||
|
dwWOWOffset = sizeof(KERB_TICKET_UNLOCK_LOGON_WOW64);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the variable-length data
|
||
|
//
|
||
|
|
||
|
RtlCopyMemory((LPBYTE) Logon + dwOffset,
|
||
|
(LPBYTE) LogonWOW + dwWOWOffset,
|
||
|
*pSubmitBufferSize - dwWOWOffset);
|
||
|
|
||
|
//
|
||
|
// Set up the pointers in the native struct
|
||
|
//
|
||
|
|
||
|
Logon->ServiceTicket = (PUCHAR) ((LPBYTE) UlongToPtr(LogonWOW->ServiceTicket)
|
||
|
+ (dwOffset - dwWOWOffset));
|
||
|
|
||
|
Logon->TicketGrantingTicket = (PUCHAR) ((LPBYTE) UlongToPtr(LogonWOW->TicketGrantingTicket)
|
||
|
+ (dwOffset - dwWOWOffset));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
|
||
|
DebugLog((DEB_ERROR,
|
||
|
"Invalid info class to logon: %d. %ws, line %d\n",
|
||
|
MessageType,
|
||
|
THIS_FILE,
|
||
|
__LINE__));
|
||
|
|
||
|
Status = STATUS_INVALID_INFO_CLASS;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
*pSubmitBufferSize = dwBufferSize;
|
||
|
*ppTempSubmitBuffer = pTempBuffer;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
ASSERT(!NT_SUCCESS(Status));
|
||
|
|
||
|
if (pTempBuffer)
|
||
|
{
|
||
|
KerbFree(pTempBuffer);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: KerbAllocateInteractiveWOWProfile
|
||
|
//
|
||
|
// Synopsis: This allocates and fills in the interactive profile for
|
||
|
// a WOW64 client.
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
|
||
|
//
|
||
|
// Notes: This code is (effectively) duplicated in
|
||
|
// KerbAllocateInteractiveBuffer. Make sure any
|
||
|
// changes made here are applied there as well.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
KerbAllocateInteractiveWOWBuffer(
|
||
|
OUT PKERB_INTERACTIVE_PROFILE *ProfileBuffer,
|
||
|
OUT PULONG ProfileBufferSize,
|
||
|
IN PNETLOGON_VALIDATION_SAM_INFO3 UserInfo,
|
||
|
IN PKERB_LOGON_SESSION LogonSession,
|
||
|
IN OPTIONAL PKERB_ENCRYPTED_TICKET LogonTicket,
|
||
|
IN OPTIONAL PKERB_INTERACTIVE_LOGON KerbLogonInfo,
|
||
|
IN PUCHAR *pClientBufferBase,
|
||
|
IN BOOLEAN BuildSmartCardProfile,
|
||
|
IN BOOLEAN BuildTicketProfile
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
PKERB_INTERACTIVE_PROFILE_WOW64 LocalProfileBuffer = NULL;
|
||
|
PKERB_SMART_CARD_PROFILE_WOW64 SmartCardProfile = NULL;
|
||
|
PKERB_TICKET_PROFILE_WOW64 TicketProfile = NULL;
|
||
|
LONG_PTR Delta = 0;
|
||
|
PUCHAR Where = NULL;
|
||
|
|
||
|
if (BuildSmartCardProfile)
|
||
|
{
|
||
|
*ProfileBufferSize = sizeof(KERB_SMART_CARD_PROFILE_WOW64) +
|
||
|
LogonSession->PrimaryCredentials.PublicKeyCreds->CertContext->cbCertEncoded;
|
||
|
}
|
||
|
else if (BuildTicketProfile)
|
||
|
{
|
||
|
*ProfileBufferSize = sizeof(KERB_TICKET_PROFILE_WOW64) +
|
||
|
LogonTicket->key.keyvalue.length;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ProfileBufferSize = sizeof(KERB_INTERACTIVE_PROFILE_WOW64);
|
||
|
}
|
||
|
|
||
|
*ProfileBufferSize +=
|
||
|
UserInfo->LogonScript.Length + sizeof(WCHAR) +
|
||
|
UserInfo->HomeDirectory.Length + sizeof(WCHAR) +
|
||
|
UserInfo->HomeDirectoryDrive.Length + sizeof(WCHAR) +
|
||
|
UserInfo->FullName.Length + sizeof(WCHAR) +
|
||
|
UserInfo->ProfilePath.Length + sizeof(WCHAR) +
|
||
|
UserInfo->LogonServer.Length + sizeof(WCHAR);
|
||
|
|
||
|
LocalProfileBuffer = (PKERB_INTERACTIVE_PROFILE_WOW64) KerbAllocate(*ProfileBufferSize);
|
||
|
|
||
|
if (LocalProfileBuffer == NULL)
|
||
|
{
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Status = LsaFunctions->AllocateClientBuffer(
|
||
|
NULL,
|
||
|
*ProfileBufferSize,
|
||
|
(PVOID *) pClientBufferBase
|
||
|
);
|
||
|
|
||
|
if ( !NT_SUCCESS( Status ) )
|
||
|
{
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Delta = (LONG_PTR) (*pClientBufferBase - (PUCHAR) LocalProfileBuffer) ;
|
||
|
|
||
|
//
|
||
|
// Don't walk over smart card data
|
||
|
//
|
||
|
|
||
|
if (BuildSmartCardProfile)
|
||
|
{
|
||
|
Where = (PUCHAR) ((PKERB_SMART_CARD_PROFILE_WOW64) LocalProfileBuffer + 1);
|
||
|
}
|
||
|
else if (BuildTicketProfile)
|
||
|
{
|
||
|
Where = (PUCHAR) ((PKERB_TICKET_PROFILE_WOW64) LocalProfileBuffer + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Where = (PUCHAR) (LocalProfileBuffer + 1);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the scalar fields into the profile buffer.
|
||
|
//
|
||
|
|
||
|
LocalProfileBuffer->MessageType = KerbInteractiveProfile;
|
||
|
LocalProfileBuffer->LogonCount = UserInfo->LogonCount;
|
||
|
LocalProfileBuffer->BadPasswordCount= UserInfo->BadPasswordCount;
|
||
|
OLD_TO_NEW_LARGE_INTEGER( UserInfo->LogonTime,
|
||
|
LocalProfileBuffer->LogonTime );
|
||
|
OLD_TO_NEW_LARGE_INTEGER( UserInfo->LogoffTime,
|
||
|
LocalProfileBuffer->LogoffTime );
|
||
|
OLD_TO_NEW_LARGE_INTEGER( UserInfo->KickOffTime,
|
||
|
LocalProfileBuffer->KickOffTime );
|
||
|
OLD_TO_NEW_LARGE_INTEGER( UserInfo->PasswordLastSet,
|
||
|
LocalProfileBuffer->PasswordLastSet );
|
||
|
OLD_TO_NEW_LARGE_INTEGER( UserInfo->PasswordCanChange,
|
||
|
LocalProfileBuffer->PasswordCanChange );
|
||
|
OLD_TO_NEW_LARGE_INTEGER( UserInfo->PasswordMustChange,
|
||
|
LocalProfileBuffer->PasswordMustChange );
|
||
|
LocalProfileBuffer->UserFlags = UserInfo->UserFlags;
|
||
|
|
||
|
//
|
||
|
// Copy the Unicode strings into the profile buffer.
|
||
|
//
|
||
|
|
||
|
KerbPutWOWClientString(&Where,
|
||
|
Delta,
|
||
|
&LocalProfileBuffer->LogonScript,
|
||
|
&UserInfo->LogonScript );
|
||
|
|
||
|
KerbPutWOWClientString(&Where,
|
||
|
Delta,
|
||
|
&LocalProfileBuffer->HomeDirectory,
|
||
|
&UserInfo->HomeDirectory );
|
||
|
|
||
|
KerbPutWOWClientString(&Where,
|
||
|
Delta,
|
||
|
&LocalProfileBuffer->HomeDirectoryDrive,
|
||
|
&UserInfo->HomeDirectoryDrive );
|
||
|
|
||
|
KerbPutWOWClientString(&Where,
|
||
|
Delta,
|
||
|
&LocalProfileBuffer->FullName,
|
||
|
&UserInfo->FullName );
|
||
|
|
||
|
KerbPutWOWClientString(&Where,
|
||
|
Delta,
|
||
|
&LocalProfileBuffer->ProfilePath,
|
||
|
&UserInfo->ProfilePath );
|
||
|
|
||
|
KerbPutWOWClientString(&Where,
|
||
|
Delta,
|
||
|
&LocalProfileBuffer->LogonServer,
|
||
|
&UserInfo->LogonServer );
|
||
|
|
||
|
if (BuildSmartCardProfile)
|
||
|
{
|
||
|
LocalProfileBuffer->MessageType = KerbSmartCardProfile;
|
||
|
SmartCardProfile = (PKERB_SMART_CARD_PROFILE_WOW64) LocalProfileBuffer;
|
||
|
SmartCardProfile->CertificateSize = LogonSession->PrimaryCredentials.PublicKeyCreds->CertContext->cbCertEncoded;
|
||
|
SmartCardProfile->CertificateData = PtrToUlong(Where + Delta);
|
||
|
|
||
|
RtlCopyMemory(Where,
|
||
|
LogonSession->PrimaryCredentials.PublicKeyCreds->CertContext->pbCertEncoded,
|
||
|
SmartCardProfile->CertificateSize);
|
||
|
|
||
|
Where += SmartCardProfile->CertificateSize;
|
||
|
}
|
||
|
else if (BuildTicketProfile)
|
||
|
{
|
||
|
LocalProfileBuffer->MessageType = KerbTicketProfile;
|
||
|
TicketProfile = (PKERB_TICKET_PROFILE_WOW64) LocalProfileBuffer;
|
||
|
|
||
|
//
|
||
|
// If the key is exportable or we are domestic, return the key
|
||
|
//
|
||
|
|
||
|
if (KerbGlobalStrongEncryptionPermitted || KerbIsKeyExportable(&LogonTicket->key))
|
||
|
{
|
||
|
TicketProfile->SessionKey.KeyType = LogonTicket->key.keytype;
|
||
|
TicketProfile->SessionKey.Length = LogonTicket->key.keyvalue.length;
|
||
|
TicketProfile->SessionKey.Value = PtrToUlong(Where + Delta);
|
||
|
|
||
|
RtlCopyMemory(Where,
|
||
|
LogonTicket->key.keyvalue.value,
|
||
|
LogonTicket->key.keyvalue.length);
|
||
|
|
||
|
Where += TicketProfile->SessionKey.Length;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
LsaFunctions->FreeClientBuffer(NULL, *pClientBufferBase);
|
||
|
|
||
|
if (LocalProfileBuffer != NULL)
|
||
|
{
|
||
|
KerbFree(LocalProfileBuffer);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ProfileBuffer = (PKERB_INTERACTIVE_PROFILE) LocalProfileBuffer;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: KerbPackExternalWOWTicket
|
||
|
//
|
||
|
// Synopsis: This allocates and fills in the external ticket for
|
||
|
// a WOW64 client.
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
|
||
|
//
|
||
|
// Notes: This code is (effectively) duplicated in
|
||
|
// KerbPackExternalTicket. Make sure any
|
||
|
// changes made here are applied there as well.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS
|
||
|
KerbPackExternalWOWTicket(
|
||
|
IN PKERB_TICKET_CACHE_ENTRY pCacheEntry,
|
||
|
IN PKERB_MESSAGE_BUFFER pEncodedTicket,
|
||
|
OUT PKERB_EXTERNAL_TICKET *pTicketResponse,
|
||
|
OUT PBYTE *pClientTicketResponse,
|
||
|
OUT PULONG pTicketSize
|
||
|
)
|
||
|
{
|
||
|
PKERB_EXTERNAL_TICKET_WOW64 TicketResponseWOW = NULL;
|
||
|
PBYTE ClientTicketResponseWOW = NULL;
|
||
|
ULONG ulTicketSize;
|
||
|
ULONG Offset;
|
||
|
PUCHAR Where;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
ulTicketSize = sizeof(KERB_EXTERNAL_TICKET_WOW64) +
|
||
|
pCacheEntry->DomainName.Length +
|
||
|
pCacheEntry->TargetDomainName.Length +
|
||
|
pCacheEntry->AltTargetDomainName.Length +
|
||
|
pCacheEntry->SessionKey.keyvalue.length +
|
||
|
KerbWOWNameLength(pCacheEntry->ServiceName) +
|
||
|
KerbWOWNameLength(pCacheEntry->TargetName) +
|
||
|
KerbWOWNameLength(pCacheEntry->ClientName) +
|
||
|
pEncodedTicket->BufferSize;
|
||
|
|
||
|
//
|
||
|
// Now allocate two copies of the structure - one in our process,
|
||
|
// one in the client's process. We then build the structure in our
|
||
|
// process but with pointer valid in the client's process
|
||
|
//
|
||
|
|
||
|
TicketResponseWOW = (PKERB_EXTERNAL_TICKET_WOW64) KerbAllocate(ulTicketSize);
|
||
|
|
||
|
if (TicketResponseWOW == NULL)
|
||
|
{
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Status = LsaFunctions->AllocateClientBuffer(NULL,
|
||
|
ulTicketSize,
|
||
|
(PVOID *) &ClientTicketResponseWOW);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Offset = (ULONG) (ClientTicketResponseWOW - (PBYTE) TicketResponseWOW);
|
||
|
|
||
|
Where = ((PUCHAR) (TicketResponseWOW + 1));
|
||
|
|
||
|
//
|
||
|
// Copy the non-pointer fields
|
||
|
//
|
||
|
|
||
|
TicketResponseWOW->TicketFlags = pCacheEntry->TicketFlags;
|
||
|
TicketResponseWOW->Flags = 0;
|
||
|
TicketResponseWOW->KeyExpirationTime = pCacheEntry->KeyExpirationTime;
|
||
|
TicketResponseWOW->StartTime = pCacheEntry->StartTime;
|
||
|
TicketResponseWOW->EndTime = pCacheEntry->EndTime;
|
||
|
TicketResponseWOW->RenewUntil = pCacheEntry->RenewUntil;
|
||
|
TicketResponseWOW->TimeSkew = pCacheEntry->TimeSkew;
|
||
|
TicketResponseWOW->SessionKey.KeyType = pCacheEntry->SessionKey.keytype;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Copy the structure to the client's address space
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// These are 32-bit PVOID (i.e., ULONG) aligned
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Make sure the two name types are the same
|
||
|
//
|
||
|
|
||
|
DsysAssert(sizeof(KERB_INTERNAL_NAME_WOW64) == sizeof(KERB_EXTERNAL_NAME_WOW64));
|
||
|
DsysAssert(FIELD_OFFSET(KERB_INTERNAL_NAME_WOW64,NameType) == FIELD_OFFSET(KERB_EXTERNAL_NAME_WOW64,NameType));
|
||
|
DsysAssert(FIELD_OFFSET(KERB_INTERNAL_NAME_WOW64,NameCount) == FIELD_OFFSET(KERB_EXTERNAL_NAME_WOW64,NameCount));
|
||
|
DsysAssert(FIELD_OFFSET(KERB_INTERNAL_NAME_WOW64,Names) == FIELD_OFFSET(KERB_EXTERNAL_NAME_WOW64,Names));
|
||
|
|
||
|
KerbPutWOWKdcName(pCacheEntry->ServiceName,
|
||
|
&TicketResponseWOW->ServiceName,
|
||
|
Offset,
|
||
|
&Where);
|
||
|
|
||
|
KerbPutWOWKdcName(pCacheEntry->TargetName,
|
||
|
&TicketResponseWOW->TargetName,
|
||
|
Offset,
|
||
|
&Where);
|
||
|
|
||
|
KerbPutWOWKdcName(pCacheEntry->ClientName,
|
||
|
&TicketResponseWOW->ClientName,
|
||
|
Offset,
|
||
|
&Where);
|
||
|
|
||
|
//
|
||
|
// From here on, they are WCHAR aligned
|
||
|
//
|
||
|
|
||
|
KerbPutWOWString(&pCacheEntry->DomainName,
|
||
|
&TicketResponseWOW->DomainName,
|
||
|
Offset,
|
||
|
&Where);
|
||
|
|
||
|
KerbPutWOWString(&pCacheEntry->TargetDomainName,
|
||
|
&TicketResponseWOW->TargetDomainName,
|
||
|
Offset,
|
||
|
&Where);
|
||
|
|
||
|
KerbPutWOWString(&pCacheEntry->AltTargetDomainName,
|
||
|
&TicketResponseWOW->AltTargetDomainName,
|
||
|
Offset,
|
||
|
&Where);
|
||
|
|
||
|
//
|
||
|
// And from here they are BYTE aligned
|
||
|
//
|
||
|
|
||
|
TicketResponseWOW->SessionKey.Value = PtrToUlong(Where + Offset);
|
||
|
|
||
|
RtlCopyMemory(Where,
|
||
|
pCacheEntry->SessionKey.keyvalue.value,
|
||
|
pCacheEntry->SessionKey.keyvalue.length);
|
||
|
|
||
|
Where += pCacheEntry->SessionKey.keyvalue.length;
|
||
|
|
||
|
TicketResponseWOW->SessionKey.Length = pCacheEntry->SessionKey.keyvalue.length;
|
||
|
|
||
|
TicketResponseWOW->EncodedTicketSize = pEncodedTicket->BufferSize;
|
||
|
TicketResponseWOW->EncodedTicket = PtrToUlong(Where + Offset);
|
||
|
|
||
|
RtlCopyMemory(Where,
|
||
|
pEncodedTicket->Buffer,
|
||
|
pEncodedTicket->BufferSize);
|
||
|
|
||
|
Where += pEncodedTicket->BufferSize;
|
||
|
|
||
|
DsysAssert(Where - ((PUCHAR) TicketResponseWOW) == (LONG_PTR) ulTicketSize);
|
||
|
|
||
|
*pTicketResponse = (PKERB_EXTERNAL_TICKET) TicketResponseWOW;
|
||
|
*pClientTicketResponse = ClientTicketResponseWOW;
|
||
|
*pTicketSize = ulTicketSize;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (TicketResponseWOW != NULL)
|
||
|
{
|
||
|
KerbFree(TicketResponseWOW);
|
||
|
}
|
||
|
|
||
|
if (ClientTicketResponseWOW != NULL)
|
||
|
{
|
||
|
LsaFunctions->FreeClientBuffer(NULL, ClientTicketResponseWOW);
|
||
|
}
|
||
|
|
||
|
*pTicketResponse = NULL;
|
||
|
*pClientTicketResponse = NULL;
|
||
|
*pTicketSize = 0;
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
#endif // _WIN64
|