libwinpr-sspi: improve NTLM message debugging
This commit is contained in:
parent
aff78da527
commit
63a3fe70cb
@ -65,6 +65,7 @@ void ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName)
|
||||
GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize);
|
||||
TargetName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameDnsHostname, TargetName, &nSize);
|
||||
CharUpperA(TargetName);
|
||||
}
|
||||
|
||||
context->TargetName.cbBuffer = strlen(TargetName) * 2;
|
||||
|
@ -81,6 +81,13 @@ enum _NTLM_STATE
|
||||
};
|
||||
typedef enum _NTLM_STATE NTLM_STATE;
|
||||
|
||||
struct _NTLM_AV_PAIR
|
||||
{
|
||||
UINT16 AvId;
|
||||
UINT16 AvLen;
|
||||
};
|
||||
typedef struct _NTLM_AV_PAIR NTLM_AV_PAIR;
|
||||
|
||||
struct _AV_PAIR
|
||||
{
|
||||
UINT16 length;
|
||||
@ -136,6 +143,32 @@ struct _NTLM_VERSION_INFO
|
||||
};
|
||||
typedef struct _NTLM_VERSION_INFO NTLM_VERSION_INFO;
|
||||
|
||||
struct _NTLM_RESPONSE
|
||||
{
|
||||
BYTE Response[24];
|
||||
};
|
||||
typedef struct _NTLM_RESPONSE NTLM_RESPONSE;
|
||||
|
||||
struct _NTLMv2_CLIENT_CHALLENGE
|
||||
{
|
||||
UINT8 RespType;
|
||||
UINT8 HiRespType;
|
||||
UINT16 Reserved1;
|
||||
UINT32 Reserved2;
|
||||
BYTE Timestamp[8];
|
||||
BYTE ClientChallenge[8];
|
||||
UINT32 Reserved3;
|
||||
NTLM_AV_PAIR* AvPairs;
|
||||
};
|
||||
typedef struct _NTLMv2_CLIENT_CHALLENGE NTLMv2_CLIENT_CHALLENGE;
|
||||
|
||||
struct _NTLMv2_RESPONSE
|
||||
{
|
||||
BYTE Response[16];
|
||||
NTLMv2_CLIENT_CHALLENGE Challenge;
|
||||
};
|
||||
typedef struct _NTLMv2_RESPONSE NTLMv2_RESPONSE;
|
||||
|
||||
struct _NTLM_MESSAGE_FIELDS
|
||||
{
|
||||
UINT16 Len;
|
||||
@ -169,6 +202,7 @@ struct _NTLM_CHALLENGE_MESSAGE
|
||||
UINT32 MessageType;
|
||||
UINT32 NegotiateFlags;
|
||||
BYTE ServerChallenge[8];
|
||||
BYTE Reserved[8];
|
||||
NTLM_VERSION_INFO Version;
|
||||
NTLM_MESSAGE_FIELDS TargetName;
|
||||
NTLM_MESSAGE_FIELDS TargetInfo;
|
||||
|
@ -43,6 +43,78 @@ const char* const AV_PAIRS_STRINGS[] =
|
||||
"MsvChannelBindings"
|
||||
};
|
||||
|
||||
void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList)
|
||||
{
|
||||
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||
|
||||
pAvPair->AvId = MsvAvEOL;
|
||||
pAvPair->AvLen = 0;
|
||||
}
|
||||
|
||||
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength)
|
||||
{
|
||||
/* size of headers + value lengths + terminating MsvAvEOL AV_PAIR */
|
||||
return (AvPairsCount + 1) * sizeof(NTLM_AV_PAIR) + AvPairsValueLength;
|
||||
}
|
||||
|
||||
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair)
|
||||
{
|
||||
return &((PBYTE) pAvPair)[sizeof(NTLM_AV_PAIR)];
|
||||
}
|
||||
|
||||
int ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair)
|
||||
{
|
||||
return pAvPair->AvLen + sizeof(NTLM_AV_PAIR);
|
||||
}
|
||||
|
||||
NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair)
|
||||
{
|
||||
return (NTLM_AV_PAIR*) ((PBYTE) pAvPair + ntlm_av_pair_get_next_offset(pAvPair));
|
||||
}
|
||||
|
||||
NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, LONG AvPairListSize)
|
||||
{
|
||||
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||
|
||||
if (!pAvPair)
|
||||
return NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (pAvPair->AvId == AvId)
|
||||
return pAvPair;
|
||||
|
||||
if (pAvPair->AvId == MsvAvEOL)
|
||||
return NULL;
|
||||
|
||||
AvPairListSize -= ntlm_av_pair_get_next_offset(pAvPair);
|
||||
|
||||
if (AvPairListSize <= 0)
|
||||
return NULL;
|
||||
|
||||
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_STRING pValue, LONG AvPairListSize)
|
||||
{
|
||||
NTLM_AV_PAIR* pAvPair;
|
||||
|
||||
pAvPair = ntlm_av_pair_get(pAvPairList, MsvAvEOL, AvPairListSize);
|
||||
|
||||
if (!pAvPair)
|
||||
return NULL;
|
||||
|
||||
pAvPair->AvId = AvId;
|
||||
pAvPair->AvLen = pValue->Length;
|
||||
|
||||
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPair), pValue->Buffer, pValue->Length);
|
||||
|
||||
return pAvPair;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input array of AV_PAIRs.\n
|
||||
* AV_PAIR @msdn{cc236646}
|
||||
@ -322,74 +394,65 @@ void ntlm_populate_av_pairs(NTLM_CONTEXT* context)
|
||||
ntlm_output_av_pairs(context, &context->TargetInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate array of AV_PAIRs (server).\n
|
||||
* AV_PAIR @msdn{cc236646}
|
||||
* @param NTLM context
|
||||
*/
|
||||
void ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
|
||||
{
|
||||
char* name;
|
||||
DWORD nSize = 0;
|
||||
|
||||
void ntlm_populate_server_av_pairs(NTLM_CONTEXT* context)
|
||||
GetComputerNameExA(type, NULL, &nSize);
|
||||
name = malloc(nSize);
|
||||
GetComputerNameExA(type, name, &nSize);
|
||||
|
||||
if (type == ComputerNameNetBIOS)
|
||||
CharUpperA(name);
|
||||
|
||||
pName->Length = strlen(name) * 2;
|
||||
pName->Buffer = (PWSTR) malloc(pName->Length);
|
||||
MultiByteToWideChar(CP_ACP, 0, name, strlen(name),
|
||||
(LPWSTR) pName->Buffer, pName->Length / 2);
|
||||
|
||||
pName->MaximumLength = pName->Length;
|
||||
|
||||
free(name);
|
||||
}
|
||||
|
||||
void ntlm_construct_server_target_info(NTLM_CONTEXT* context)
|
||||
{
|
||||
int length;
|
||||
DWORD nSize;
|
||||
AV_PAIRS* av_pairs;
|
||||
char* NbDomainName;
|
||||
char* NbComputerName;
|
||||
char* DnsDomainName;
|
||||
char* DnsComputerName;
|
||||
ULONG AvPairsCount;
|
||||
ULONG AvPairsLength;
|
||||
LONG AvPairListSize;
|
||||
NTLM_AV_PAIR* pAvPairList;
|
||||
UNICODE_STRING NbDomainName;
|
||||
UNICODE_STRING NbComputerName;
|
||||
UNICODE_STRING DnsDomainName;
|
||||
UNICODE_STRING DnsComputerName;
|
||||
UNICODE_STRING Timestamp;
|
||||
|
||||
av_pairs = context->av_pairs;
|
||||
ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS);
|
||||
ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS);
|
||||
ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain);
|
||||
ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname);
|
||||
|
||||
nSize = 0;
|
||||
GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize);
|
||||
NbDomainName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameNetBIOS, NbDomainName, &nSize);
|
||||
CharUpperA(NbDomainName);
|
||||
Timestamp.Buffer = (PWSTR) context->Timestamp;
|
||||
Timestamp.Length = sizeof(context->Timestamp);
|
||||
|
||||
nSize = 0;
|
||||
GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize);
|
||||
NbComputerName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameNetBIOS, NbComputerName, &nSize);
|
||||
CharUpperA(NbComputerName);
|
||||
AvPairsCount = 5;
|
||||
AvPairsLength = NbDomainName.Length + NbComputerName.Length +
|
||||
DnsDomainName.Length + DnsComputerName.Length + 8;
|
||||
|
||||
nSize = 0;
|
||||
GetComputerNameExA(ComputerNameDnsDomain, NULL, &nSize);
|
||||
DnsDomainName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameDnsDomain, DnsDomainName, &nSize);
|
||||
|
||||
nSize = 0;
|
||||
GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize);
|
||||
DnsComputerName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameDnsHostname, DnsComputerName, &nSize);
|
||||
|
||||
av_pairs->NbDomainName.length = strlen(NbDomainName) * 2;
|
||||
av_pairs->NbDomainName.value = (BYTE*) malloc(av_pairs->NbDomainName.length);
|
||||
MultiByteToWideChar(CP_ACP, 0, NbDomainName, strlen(NbDomainName),
|
||||
(LPWSTR) av_pairs->NbDomainName.value, av_pairs->NbDomainName.length / 2);
|
||||
|
||||
av_pairs->NbComputerName.length = strlen(NbDomainName) * 2;
|
||||
av_pairs->NbComputerName.value = (BYTE*) malloc(av_pairs->NbComputerName.length);
|
||||
MultiByteToWideChar(CP_ACP, 0, NbComputerName, strlen(NbComputerName),
|
||||
(LPWSTR) av_pairs->NbComputerName.value, av_pairs->NbComputerName.length / 2);
|
||||
|
||||
av_pairs->DnsDomainName.length = strlen(DnsDomainName) * 2;
|
||||
av_pairs->DnsDomainName.value = (BYTE*) malloc(av_pairs->DnsDomainName.length);
|
||||
MultiByteToWideChar(CP_ACP, 0, DnsDomainName, strlen(DnsDomainName),
|
||||
(LPWSTR) av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length / 2);
|
||||
|
||||
av_pairs->DnsComputerName.length = strlen(DnsComputerName) * 2;
|
||||
av_pairs->DnsComputerName.value = (BYTE*) malloc(av_pairs->DnsComputerName.length);
|
||||
MultiByteToWideChar(CP_ACP, 0, DnsComputerName, strlen(DnsComputerName),
|
||||
(LPWSTR) av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length / 2);
|
||||
|
||||
length = ntlm_compute_av_pairs_length(context) + 4;
|
||||
length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength);
|
||||
sspi_SecBufferAlloc(&context->TargetInfo, length);
|
||||
ntlm_output_av_pairs(context, &context->TargetInfo);
|
||||
|
||||
free(NbDomainName);
|
||||
free(NbComputerName);
|
||||
free(DnsDomainName);
|
||||
free(DnsComputerName);
|
||||
pAvPairList = (NTLM_AV_PAIR*) context->TargetInfo.pvBuffer;
|
||||
AvPairListSize = (ULONG) context->TargetInfo.cbBuffer;
|
||||
|
||||
ntlm_av_pair_list_init(pAvPairList);
|
||||
ntlm_av_pair_add(pAvPairList, MsvAvNbDomainName, &NbDomainName, AvPairListSize);
|
||||
ntlm_av_pair_add(pAvPairList, MsvAvNbComputerName, &NbComputerName, AvPairListSize);
|
||||
ntlm_av_pair_add(pAvPairList, MsvAvDnsDomainName, &DnsDomainName, AvPairListSize);
|
||||
ntlm_av_pair_add(pAvPairList, MsvAvDnsComputerName, &DnsComputerName, AvPairListSize);
|
||||
ntlm_av_pair_add(pAvPairList, MsvAvTimestamp, &Timestamp, AvPairListSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,16 @@
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList);
|
||||
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength);
|
||||
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair);
|
||||
int ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair);
|
||||
NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair);
|
||||
NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, LONG AvPairListSize);
|
||||
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_STRING pValue, LONG AvPairListSize);
|
||||
|
||||
void ntlm_construct_server_target_info(NTLM_CONTEXT* context);
|
||||
|
||||
void ntlm_input_av_pairs(NTLM_CONTEXT* context, PStream s);
|
||||
void ntlm_output_av_pairs(NTLM_CONTEXT* context, PSecBuffer buffer);
|
||||
void ntlm_populate_av_pairs(NTLM_CONTEXT* context);
|
||||
|
@ -56,6 +56,21 @@ void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo)
|
||||
versionInfo->NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read VERSION structure.\n
|
||||
* VERSION @msdn{cc236654}
|
||||
* @param s
|
||||
*/
|
||||
|
||||
void ntlm_read_version_info(PStream s, NTLM_VERSION_INFO* versionInfo)
|
||||
{
|
||||
StreamRead_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */
|
||||
StreamRead_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
|
||||
StreamRead_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */
|
||||
StreamRead(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
|
||||
StreamRead_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */
|
||||
}
|
||||
|
||||
/**
|
||||
* Write VERSION structure.\n
|
||||
* VERSION @msdn{cc236654}
|
||||
@ -64,17 +79,28 @@ void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo)
|
||||
|
||||
void ntlm_write_version_info(PStream s, NTLM_VERSION_INFO* versionInfo)
|
||||
{
|
||||
OSVERSIONINFOA osVersionInfo;
|
||||
StreamWrite_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */
|
||||
StreamWrite_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
|
||||
StreamWrite_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */
|
||||
StreamWrite(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
|
||||
StreamWrite_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */
|
||||
}
|
||||
|
||||
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
||||
/**
|
||||
* Print VERSION structure.\n
|
||||
* VERSION @msdn{cc236654}
|
||||
* @param s
|
||||
*/
|
||||
|
||||
GetVersionExA(&osVersionInfo);
|
||||
|
||||
StreamWrite_UINT8(s, osVersionInfo.dwMajorVersion); /* ProductMajorVersion (1 byte) */
|
||||
StreamWrite_UINT8(s, osVersionInfo.dwMinorVersion); /* ProductMinorVersion (1 byte) */
|
||||
StreamWrite_UINT16(s, osVersionInfo.dwBuildNumber); /* ProductBuild (2 bytes) */
|
||||
StreamZero(s, 3); /* Reserved (3 bytes) */
|
||||
StreamWrite_UINT8(s, NTLMSSP_REVISION_W2K3); /* NTLMRevisionCurrent (1 byte) */
|
||||
void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo)
|
||||
{
|
||||
printf("VERSION =\n{\n");
|
||||
printf("\tProductMajorVersion: %d\n", versionInfo->ProductMajorVersion);
|
||||
printf("\tProductMinorVersion: %d\n", versionInfo->ProductMinorVersion);
|
||||
printf("\tProductBuild: %d\n", versionInfo->ProductBuild);
|
||||
printf("\tReserved: 0x%02X%02X%02X\n", versionInfo->Reserved[0],
|
||||
versionInfo->Reserved[1], versionInfo->Reserved[2]);
|
||||
printf("\tNTLMRevisionCurrent: 0x%02X\n", versionInfo->NTLMRevisionCurrent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,9 @@
|
||||
#include "ntlm_av_pairs.h"
|
||||
|
||||
void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo);
|
||||
void ntlm_read_version_info(PStream s, NTLM_VERSION_INFO* versionInfo);
|
||||
void ntlm_write_version_info(PStream s, NTLM_VERSION_INFO* versionInfo);
|
||||
void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo);
|
||||
|
||||
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context);
|
||||
void ntlm_output_target_name(NTLM_CONTEXT* context);
|
||||
|
@ -187,6 +187,15 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf
|
||||
|
||||
StreamRead_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */
|
||||
|
||||
if (!((message.NegotiateFlags & NTLMSSP_REQUEST_TARGET) &&
|
||||
(message.NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM) &&
|
||||
(message.NegotiateFlags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) &&
|
||||
(message.NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE)))
|
||||
{
|
||||
PStreamFreeDetach(s);
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
}
|
||||
|
||||
context->NegotiateFlags = message.NegotiateFlags;
|
||||
|
||||
/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
|
||||
@ -202,7 +211,7 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf
|
||||
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||
{
|
||||
/* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
|
||||
StreamSeek(s, 8); /* Version (8 bytes) */
|
||||
ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
||||
}
|
||||
|
||||
length = StreamSize(s);
|
||||
@ -322,7 +331,7 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
||||
|
||||
SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
|
||||
{
|
||||
BYTE* p;
|
||||
PBYTE p;
|
||||
PStream s;
|
||||
int length;
|
||||
PBYTE StartOffset;
|
||||
@ -334,6 +343,8 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
|
||||
ZeroMemory(&message, sizeof(message));
|
||||
s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer);
|
||||
|
||||
StartOffset = StreamGetPointer(s);
|
||||
|
||||
ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) &message);
|
||||
|
||||
if (!ntlm_validate_message_header(s, (NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_CHALLENGE))
|
||||
@ -342,60 +353,38 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
}
|
||||
|
||||
StartOffset = StreamGetPointer(s) - 12;
|
||||
|
||||
/* TargetNameFields (8 bytes) */
|
||||
ntlm_read_message_fields(s, &(message.TargetName));
|
||||
|
||||
StreamRead_UINT32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_negotiate_flags(context->NegotiateFlags);
|
||||
#endif
|
||||
StreamRead(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */
|
||||
CopyMemory(context->ServerChallenge, message.ServerChallenge, 8);
|
||||
|
||||
StreamRead(s, context->ServerChallenge, 8); /* ServerChallenge (8 bytes) */
|
||||
StreamSeek(s, 8); /* Reserved (8 bytes), should be ignored */
|
||||
StreamRead(s, message.Reserved, 8); /* Reserved (8 bytes), should be ignored */
|
||||
|
||||
/* TargetInfoFields (8 bytes) */
|
||||
ntlm_read_message_fields(s, &(message.TargetInfo));
|
||||
|
||||
/* only present if NTLMSSP_NEGOTIATE_VERSION is set */
|
||||
|
||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||
{
|
||||
StreamSeek(s, 8); /* Version (8 bytes), can be ignored */
|
||||
}
|
||||
ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
||||
|
||||
/* Payload (variable) */
|
||||
PayloadOffset = StreamGetPointer(s);
|
||||
|
||||
if (message.TargetName.Len > 0)
|
||||
{
|
||||
p = StartOffset + message.TargetName.BufferOffset;
|
||||
sspi_SecBufferAlloc(&context->TargetName, message.TargetName.Len);
|
||||
CopyMemory(context->TargetName.pvBuffer, p, message.TargetName.Len);
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("TargetName (length = %d, offset = %d)\n", message.TargetName.Len, message.TargetName.BufferOffset);
|
||||
winpr_HexDump(context->TargetName.pvBuffer, context->TargetName.cbBuffer);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
ntlm_read_message_fields_buffer(s, &(message.TargetName));
|
||||
|
||||
if (message.TargetInfo.Len > 0)
|
||||
{
|
||||
p = StartOffset + message.TargetInfo.BufferOffset;
|
||||
sspi_SecBufferAlloc(&context->TargetInfo, message.TargetInfo.Len);
|
||||
CopyMemory(context->TargetInfo.pvBuffer, p, message.TargetInfo.Len);
|
||||
ntlm_read_message_fields_buffer(s, &(message.TargetInfo));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("TargetInfo (length = %d, offset = %d)\n", message.TargetInfo.Len, message.TargetInfo.BufferOffset);
|
||||
winpr_HexDump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer);
|
||||
printf("\n");
|
||||
#endif
|
||||
context->TargetInfo.pvBuffer = message.TargetInfo.Buffer;
|
||||
context->TargetInfo.cbBuffer = message.TargetInfo.Len;
|
||||
|
||||
if (context->ntlm_v2)
|
||||
{
|
||||
p = StartOffset + message.TargetInfo.BufferOffset;
|
||||
StreamSetPointer(s, p);
|
||||
ntlm_input_av_pairs(context, s);
|
||||
}
|
||||
@ -410,6 +399,14 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
|
||||
printf("CHALLENGE_MESSAGE (length = %d)\n", length);
|
||||
winpr_HexDump(context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
|
||||
printf("\n");
|
||||
|
||||
ntlm_print_negotiate_flags(context->NegotiateFlags);
|
||||
|
||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||
ntlm_print_version_info(&(message.Version));
|
||||
|
||||
ntlm_print_message_fields(&(message.TargetName), "TargetName");
|
||||
ntlm_print_message_fields(&(message.TargetInfo), "TargetInfo");
|
||||
#endif
|
||||
/* AV_PAIRs */
|
||||
|
||||
@ -508,6 +505,12 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
||||
UINT32 PayloadOffset;
|
||||
NTLM_CHALLENGE_MESSAGE message;
|
||||
|
||||
ZeroMemory(&message, sizeof(message));
|
||||
s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer);
|
||||
|
||||
/* Version */
|
||||
ntlm_get_version_info(&(message.Version));
|
||||
|
||||
/* Server Challenge */
|
||||
ntlm_generate_server_challenge(context);
|
||||
|
||||
@ -515,10 +518,10 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
||||
ntlm_generate_timestamp(context);
|
||||
|
||||
/* TargetInfo */
|
||||
ntlm_populate_server_av_pairs(context);
|
||||
ntlm_construct_server_target_info(context);
|
||||
|
||||
ZeroMemory(&message, sizeof(message));
|
||||
s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer);
|
||||
/* ServerChallenge */
|
||||
CopyMemory(message.ServerChallenge, context->ServerChallenge, 8);
|
||||
|
||||
ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_CHALLENGE);
|
||||
|
||||
@ -530,11 +533,6 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
||||
message.TargetName.Len = (UINT16) context->TargetName.cbBuffer;
|
||||
message.TargetName.Buffer = context->TargetName.pvBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
message.TargetName.Len = 0;
|
||||
message.TargetName.Buffer = NULL;
|
||||
}
|
||||
|
||||
context->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
|
||||
|
||||
@ -543,11 +541,6 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
||||
message.TargetInfo.Len = (UINT16) context->TargetInfo.cbBuffer;
|
||||
message.TargetInfo.Buffer = context->TargetInfo.pvBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
message.TargetInfo.Len = 0;
|
||||
message.TargetInfo.Buffer = NULL;
|
||||
}
|
||||
|
||||
PayloadOffset = 48;
|
||||
|
||||
@ -562,41 +555,22 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
||||
|
||||
StreamWrite_UINT32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */
|
||||
|
||||
StreamWrite(s, context->ServerChallenge, 8); /* ServerChallenge (8 bytes) */
|
||||
StreamZero(s, 8); /* Reserved (8 bytes), should be ignored */
|
||||
StreamWrite(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */
|
||||
StreamWrite(s, message.Reserved, 8); /* Reserved (8 bytes), should be ignored */
|
||||
|
||||
/* TargetInfoFields (8 bytes) */
|
||||
ntlm_write_message_fields(s, &(message.TargetInfo));
|
||||
|
||||
/* only present if NTLMSSP_NEGOTIATE_VERSION is set */
|
||||
|
||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||
{
|
||||
ntlm_get_version_info(&(message.Version));
|
||||
ntlm_write_version_info(s, &(message.Version)); /* Version (8 bytes), can be ignored */
|
||||
}
|
||||
ntlm_write_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
||||
|
||||
/* Payload (variable) */
|
||||
|
||||
if (message.TargetName.Len > 0)
|
||||
{
|
||||
StreamWrite(s, message.TargetName.Buffer, message.TargetName.Len);
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("TargetName (length = %d, offset = %d)\n", message.TargetName.Len, message.TargetName.BufferOffset);
|
||||
winpr_HexDump(message.TargetName.Buffer, message.TargetName.Len);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
if (context->NegotiateFlags & NTLMSSP_REQUEST_TARGET)
|
||||
ntlm_write_message_fields_buffer(s, &(message.TargetName));
|
||||
|
||||
if (message.TargetInfo.Len > 0)
|
||||
{
|
||||
StreamWrite(s, message.TargetInfo.Buffer, message.TargetInfo.Len);
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("TargetInfo (length = %d, offset = %d)\n", message.TargetInfo.Len, message.TargetInfo.BufferOffset);
|
||||
winpr_HexDump(message.TargetInfo.Buffer, message.TargetInfo.Len);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
|
||||
ntlm_write_message_fields_buffer(s, &(message.TargetInfo));
|
||||
|
||||
length = StreamSize(s);
|
||||
buffer->cbBuffer = length;
|
||||
@ -608,6 +582,12 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
||||
printf("CHALLENGE_MESSAGE (length = %d)\n", length);
|
||||
winpr_HexDump(context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
|
||||
printf("\n");
|
||||
|
||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||
ntlm_print_version_info(&(message.Version));
|
||||
|
||||
ntlm_print_message_fields(&(message.TargetName), "TargetName");
|
||||
ntlm_print_message_fields(&(message.TargetInfo), "TargetInfo");
|
||||
#endif
|
||||
|
||||
context->state = NTLM_STATE_AUTHENTICATE;
|
||||
@ -659,57 +639,25 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
||||
StreamRead_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */
|
||||
|
||||
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||
{
|
||||
/* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("Version (length = 8)\n");
|
||||
winpr_HexDump(s->p, 8);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
StreamSeek(s, 8); /* Version (8 bytes) */
|
||||
}
|
||||
ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
||||
|
||||
length = StreamSize(s);
|
||||
sspi_SecBufferAlloc(&context->AuthenticateMessage, length);
|
||||
CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length);
|
||||
buffer->cbBuffer = length;
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("AUTHENTICATE_MESSAGE (length = %d)\n", length);
|
||||
winpr_HexDump(s->data, length);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/* DomainName */
|
||||
ntlm_read_message_fields_buffer(s, &(message.DomainName));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.DomainName), "DomainName");
|
||||
#endif
|
||||
|
||||
/* UserName */
|
||||
ntlm_read_message_fields_buffer(s, &(message.UserName));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.UserName), "UserName");
|
||||
#endif
|
||||
|
||||
/* Workstation */
|
||||
ntlm_read_message_fields_buffer(s, &(message.Workstation));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.Workstation), "Workstation");
|
||||
#endif
|
||||
|
||||
/* LmChallengeResponse */
|
||||
ntlm_read_message_fields_buffer(s, &(message.LmChallengeResponse));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse");
|
||||
#endif
|
||||
|
||||
/* NtChallengeResponse */
|
||||
ntlm_read_message_fields_buffer(s, &(message.NtChallengeResponse));
|
||||
|
||||
@ -720,15 +668,23 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
||||
CopyMemory(context->ClientChallenge, ClientChallengeBuffer, 8);
|
||||
}
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse");
|
||||
#endif
|
||||
|
||||
/* EncryptedRandomSessionKey */
|
||||
ntlm_read_message_fields_buffer(s, &(message.EncryptedRandomSessionKey));
|
||||
CopyMemory(context->EncryptedRandomSessionKey, message.EncryptedRandomSessionKey.Buffer, 16);
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("AUTHENTICATE_MESSAGE (length = %d)\n", length);
|
||||
winpr_HexDump(s->data, length);
|
||||
printf("\n");
|
||||
|
||||
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||
ntlm_print_version_info(&(message.Version));
|
||||
|
||||
ntlm_print_message_fields(&(message.DomainName), "DomainName");
|
||||
ntlm_print_message_fields(&(message.UserName), "UserName");
|
||||
ntlm_print_message_fields(&(message.Workstation), "Workstation");
|
||||
ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse");
|
||||
ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse");
|
||||
ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey");
|
||||
#endif
|
||||
|
||||
@ -941,21 +897,9 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
||||
|
||||
StreamWrite_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_negotiate_flags(message.NegotiateFlags);
|
||||
#endif
|
||||
|
||||
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||
{
|
||||
ntlm_write_version_info(s, &(message.Version));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("Version (length = 8)\n");
|
||||
winpr_HexDump((s->p - 8), 8);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (context->ntlm_v2)
|
||||
{
|
||||
/* Message Integrity Check */
|
||||
@ -966,56 +910,21 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
||||
/* DomainName */
|
||||
ntlm_write_message_fields_buffer(s, &(message.DomainName));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.DomainName), "DomainName");
|
||||
#endif
|
||||
|
||||
/* UserName */
|
||||
ntlm_write_message_fields_buffer(s, &(message.UserName));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.UserName), "UserName");
|
||||
#endif
|
||||
|
||||
/* Workstation */
|
||||
ntlm_write_message_fields_buffer(s, &(message.Workstation));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.Workstation), "Workstation");
|
||||
#endif
|
||||
|
||||
/* LmChallengeResponse */
|
||||
ntlm_write_message_fields_buffer(s, &(message.LmChallengeResponse));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse");
|
||||
#endif
|
||||
|
||||
/* NtChallengeResponse */
|
||||
ntlm_write_message_fields_buffer(s, &(message.NtChallengeResponse));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
if (context->ntlm_v2)
|
||||
{
|
||||
ntlm_print_av_pairs(context);
|
||||
|
||||
printf("targetInfo (length = %d)\n", (int) context->TargetInfo.cbBuffer);
|
||||
winpr_HexDump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse");
|
||||
#endif
|
||||
|
||||
/* EncryptedRandomSessionKey */
|
||||
ntlm_write_message_fields_buffer(s, &(message.EncryptedRandomSessionKey));
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey");
|
||||
#endif
|
||||
|
||||
length = StreamSize(s);
|
||||
sspi_SecBufferAlloc(&context->AuthenticateMessage, length);
|
||||
CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length);
|
||||
@ -1029,18 +938,40 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
||||
s->p = MicOffset;
|
||||
StreamWrite(s, context->MessageIntegrityCheck, 16);
|
||||
s->p = s->data + length;
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("MessageIntegrityCheck (length = 16)\n");
|
||||
winpr_HexDump(MicOffset, 16);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("AUTHENTICATE_MESSAGE (length = %d)\n", length);
|
||||
winpr_HexDump(s->data, length);
|
||||
printf("\n");
|
||||
|
||||
ntlm_print_negotiate_flags(message.NegotiateFlags);
|
||||
|
||||
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||
ntlm_print_version_info(&(message.Version));
|
||||
|
||||
ntlm_print_message_fields(&(message.DomainName), "DomainName");
|
||||
ntlm_print_message_fields(&(message.UserName), "UserName");
|
||||
ntlm_print_message_fields(&(message.Workstation), "Workstation");
|
||||
ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse");
|
||||
ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse");
|
||||
ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey");
|
||||
|
||||
if (context->ntlm_v2)
|
||||
{
|
||||
ntlm_print_av_pairs(context);
|
||||
|
||||
printf("targetInfo (length = %d)\n", (int) context->TargetInfo.cbBuffer);
|
||||
winpr_HexDump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (context->ntlm_v2)
|
||||
{
|
||||
printf("MessageIntegrityCheck (length = 16)\n");
|
||||
winpr_HexDump(MicOffset, 16);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
context->state = NTLM_STATE_FINAL;
|
||||
|
Loading…
Reference in New Issue
Block a user