libwinpr-sspi: add proper detection of MIC in server-side NLA
This commit is contained in:
parent
63a3fe70cb
commit
bf559e37eb
@ -86,9 +86,9 @@ NTLM_CONTEXT* ntlm_ContextNew()
|
|||||||
|
|
||||||
if (context != NULL)
|
if (context != NULL)
|
||||||
{
|
{
|
||||||
context->ntlm_v2 = FALSE;
|
context->ntlm_v2 = TRUE;
|
||||||
context->NegotiateFlags = 0;
|
context->NegotiateFlags = 0;
|
||||||
context->SendVersionInfo = 0;
|
context->SendVersionInfo = TRUE;
|
||||||
context->LmCompatibilityLevel = 3;
|
context->LmCompatibilityLevel = 3;
|
||||||
context->state = NTLM_STATE_INITIAL;
|
context->state = NTLM_STATE_INITIAL;
|
||||||
context->SuppressExtendedProtection = 1;
|
context->SuppressExtendedProtection = 1;
|
||||||
|
@ -126,12 +126,16 @@ enum _AV_ID
|
|||||||
};
|
};
|
||||||
typedef enum _AV_ID AV_ID;
|
typedef enum _AV_ID AV_ID;
|
||||||
|
|
||||||
#define WINDOWS_MAJOR_VERSION_5 0x05
|
#define MSV_AV_FLAGS_AUTHENTICATION_CONSTRAINED 0x00000001
|
||||||
#define WINDOWS_MAJOR_VERSION_6 0x06
|
#define MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK 0x00000002
|
||||||
#define WINDOWS_MINOR_VERSION_0 0x00
|
#define MSV_AV_FLAGS_TARGET_SPN_UNTRUSTED_SOURCE 0x00000004
|
||||||
#define WINDOWS_MINOR_VERSION_1 0x01
|
|
||||||
#define WINDOWS_MINOR_VERSION_2 0x02
|
#define WINDOWS_MAJOR_VERSION_5 0x05
|
||||||
#define NTLMSSP_REVISION_W2K3 0x0F
|
#define WINDOWS_MAJOR_VERSION_6 0x06
|
||||||
|
#define WINDOWS_MINOR_VERSION_0 0x00
|
||||||
|
#define WINDOWS_MINOR_VERSION_1 0x01
|
||||||
|
#define WINDOWS_MINOR_VERSION_2 0x02
|
||||||
|
#define NTLMSSP_REVISION_W2K3 0x0F
|
||||||
|
|
||||||
struct _NTLM_VERSION_INFO
|
struct _NTLM_VERSION_INFO
|
||||||
{
|
{
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "ntlm_av_pairs.h"
|
#include "ntlm_av_pairs.h"
|
||||||
|
|
||||||
const char* const AV_PAIRS_STRINGS[] =
|
const char* const AV_PAIR_STRINGS[] =
|
||||||
{
|
{
|
||||||
"MsvAvEOL",
|
"MsvAvEOL",
|
||||||
"MsvAvNbComputerName",
|
"MsvAvNbComputerName",
|
||||||
@ -51,6 +51,47 @@ void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList)
|
|||||||
pAvPair->AvLen = 0;
|
pAvPair->AvLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList)
|
||||||
|
{
|
||||||
|
ULONG length;
|
||||||
|
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||||
|
|
||||||
|
if (!pAvPair)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (pAvPair->AvId != MsvAvEOL)
|
||||||
|
{
|
||||||
|
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
length = (pAvPair - pAvPairList) + sizeof(NTLM_AV_PAIR);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList)
|
||||||
|
{
|
||||||
|
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||||
|
|
||||||
|
if (!pAvPair)
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf("AV_PAIRs =\n{\n");
|
||||||
|
|
||||||
|
while (pAvPair->AvId != MsvAvEOL)
|
||||||
|
{
|
||||||
|
printf("\t%s AvId: %d AvLen: %d\n",
|
||||||
|
AV_PAIR_STRINGS[pAvPair->AvId],
|
||||||
|
pAvPair->AvId, pAvPair->AvLen);
|
||||||
|
|
||||||
|
winpr_HexDump(ntlm_av_pair_get_value_pointer(pAvPair), pAvPair->AvLen);
|
||||||
|
|
||||||
|
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength)
|
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength)
|
||||||
{
|
{
|
||||||
/* size of headers + value lengths + terminating MsvAvEOL AV_PAIR */
|
/* size of headers + value lengths + terminating MsvAvEOL AV_PAIR */
|
||||||
@ -72,7 +113,7 @@ 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));
|
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* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, AV_ID AvId)
|
||||||
{
|
{
|
||||||
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||||
|
|
||||||
@ -87,11 +128,6 @@ NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, LONG AvPai
|
|||||||
if (pAvPair->AvId == MsvAvEOL)
|
if (pAvPair->AvId == MsvAvEOL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
AvPairListSize -= ntlm_av_pair_get_next_offset(pAvPair);
|
|
||||||
|
|
||||||
if (AvPairListSize <= 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +138,7 @@ NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_S
|
|||||||
{
|
{
|
||||||
NTLM_AV_PAIR* pAvPair;
|
NTLM_AV_PAIR* pAvPair;
|
||||||
|
|
||||||
pAvPair = ntlm_av_pair_get(pAvPairList, MsvAvEOL, AvPairListSize);
|
pAvPair = ntlm_av_pair_get(pAvPairList, MsvAvEOL);
|
||||||
|
|
||||||
if (!pAvPair)
|
if (!pAvPair)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -207,7 +243,7 @@ void ntlm_input_av_pairs(NTLM_CONTEXT* context, PStream s)
|
|||||||
|
|
||||||
#ifdef WITH_DEBUG_NTLM
|
#ifdef WITH_DEBUG_NTLM
|
||||||
if (AvId < 10)
|
if (AvId < 10)
|
||||||
printf("\tAvId: %s, AvLen: %d\n", AV_PAIRS_STRINGS[AvId], AvLen);
|
printf("\tAvId: %s, AvLen: %d\n", AV_PAIR_STRINGS[AvId], AvLen);
|
||||||
else
|
else
|
||||||
printf("\tAvId: %s, AvLen: %d\n", "Unknown", AvLen);
|
printf("\tAvId: %s, AvLen: %d\n", "Unknown", AvLen);
|
||||||
|
|
||||||
|
@ -25,11 +25,13 @@
|
|||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList);
|
void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList);
|
||||||
|
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList);
|
||||||
|
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList);
|
||||||
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength);
|
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength);
|
||||||
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair);
|
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair);
|
||||||
int ntlm_av_pair_get_next_offset(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_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_get(NTLM_AV_PAIR* pAvPairList, AV_ID AvId);
|
||||||
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_STRING pValue, 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_construct_server_target_info(NTLM_CONTEXT* context);
|
||||||
|
@ -103,6 +103,51 @@ void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo)
|
|||||||
printf("\tNTLMRevisionCurrent: 0x%02X\n", versionInfo->NTLMRevisionCurrent);
|
printf("\tNTLMRevisionCurrent: 0x%02X\n", versionInfo->NTLMRevisionCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ntlm_read_ntlm_v2_client_challenge(PStream s, NTLMv2_CLIENT_CHALLENGE* challenge)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
StreamRead_UINT8(s, challenge->RespType);
|
||||||
|
StreamRead_UINT8(s, challenge->HiRespType);
|
||||||
|
StreamRead_UINT16(s, challenge->Reserved1);
|
||||||
|
StreamRead_UINT32(s, challenge->Reserved2);
|
||||||
|
StreamRead(s, challenge->Timestamp, 8);
|
||||||
|
StreamRead(s, challenge->ClientChallenge, 8);
|
||||||
|
StreamRead_UINT32(s, challenge->Reserved3);
|
||||||
|
|
||||||
|
size = StreamRemainingSize(s);
|
||||||
|
challenge->AvPairs = (NTLM_AV_PAIR*) malloc(size);
|
||||||
|
StreamRead(s, challenge->AvPairs, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ntlm_write_ntlm_v2_client_challenge(PStream s, NTLMv2_CLIENT_CHALLENGE* challenge)
|
||||||
|
{
|
||||||
|
ULONG length;
|
||||||
|
|
||||||
|
StreamWrite_UINT8(s, challenge->RespType);
|
||||||
|
StreamWrite_UINT8(s, challenge->HiRespType);
|
||||||
|
StreamWrite_UINT16(s, challenge->Reserved1);
|
||||||
|
StreamWrite_UINT32(s, challenge->Reserved2);
|
||||||
|
StreamWrite(s, challenge->Timestamp, 8);
|
||||||
|
StreamWrite(s, challenge->ClientChallenge, 8);
|
||||||
|
StreamWrite_UINT32(s, challenge->Reserved3);
|
||||||
|
|
||||||
|
length = ntlm_av_pair_list_length(challenge->AvPairs);
|
||||||
|
StreamWrite(s, challenge->AvPairs, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ntlm_read_ntlm_v2_response(PStream s, NTLMv2_RESPONSE* response)
|
||||||
|
{
|
||||||
|
StreamRead(s, response->Response, 16);
|
||||||
|
ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ntlm_write_ntlm_v2_response(PStream s, NTLMv2_RESPONSE* response)
|
||||||
|
{
|
||||||
|
StreamWrite(s, response->Response, 16);
|
||||||
|
ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output Restriction_Encoding.\n
|
* Output Restriction_Encoding.\n
|
||||||
* Restriction_Encoding @msdn{cc236647}
|
* Restriction_Encoding @msdn{cc236647}
|
||||||
|
@ -29,6 +29,9 @@ void ntlm_read_version_info(PStream s, NTLM_VERSION_INFO* versionInfo);
|
|||||||
void ntlm_write_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_print_version_info(NTLM_VERSION_INFO* versionInfo);
|
||||||
|
|
||||||
|
void ntlm_read_ntlm_v2_response(PStream s, NTLMv2_RESPONSE* response);
|
||||||
|
void ntlm_write_ntlm_v2_response(PStream s, NTLMv2_RESPONSE* response);
|
||||||
|
|
||||||
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context);
|
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context);
|
||||||
void ntlm_output_target_name(NTLM_CONTEXT* context);
|
void ntlm_output_target_name(NTLM_CONTEXT* context);
|
||||||
void ntlm_output_channel_bindings(NTLM_CONTEXT* context);
|
void ntlm_output_channel_bindings(NTLM_CONTEXT* context);
|
||||||
|
@ -209,10 +209,7 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf
|
|||||||
ntlm_read_message_fields(s, &(message.Workstation));
|
ntlm_read_message_fields(s, &(message.Workstation));
|
||||||
|
|
||||||
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
{
|
|
||||||
/* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
|
|
||||||
ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
||||||
}
|
|
||||||
|
|
||||||
length = StreamSize(s);
|
length = StreamSize(s);
|
||||||
buffer->cbBuffer = length;
|
buffer->cbBuffer = length;
|
||||||
@ -225,6 +222,11 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf
|
|||||||
printf("NEGOTIATE_MESSAGE (length = %d)\n", length);
|
printf("NEGOTIATE_MESSAGE (length = %d)\n", length);
|
||||||
winpr_HexDump(s->data, length);
|
winpr_HexDump(s->data, length);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
ntlm_print_negotiate_flags(message.NegotiateFlags);
|
||||||
|
|
||||||
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
|
ntlm_print_version_info(&(message.Version));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
context->state = NTLM_STATE_CHALLENGE;
|
context->state = NTLM_STATE_CHALLENGE;
|
||||||
@ -245,9 +247,6 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
|
|
||||||
ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_NEGOTIATE);
|
ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_NEGOTIATE);
|
||||||
|
|
||||||
/* Message Header (12 bytes) */
|
|
||||||
ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*) &message);
|
|
||||||
|
|
||||||
if (context->ntlm_v2)
|
if (context->ntlm_v2)
|
||||||
{
|
{
|
||||||
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
|
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
|
||||||
@ -275,6 +274,9 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
|
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
|
ntlm_get_version_info(&(message.Version));
|
||||||
|
|
||||||
if (context->confidentiality)
|
if (context->confidentiality)
|
||||||
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
|
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
|
||||||
|
|
||||||
@ -283,6 +285,9 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
|
|
||||||
context->NegotiateFlags = message.NegotiateFlags;
|
context->NegotiateFlags = message.NegotiateFlags;
|
||||||
|
|
||||||
|
/* Message Header (12 bytes) */
|
||||||
|
ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*) &message);
|
||||||
|
|
||||||
StreamWrite_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */
|
StreamWrite_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */
|
||||||
|
|
||||||
/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
|
/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
|
||||||
@ -296,19 +301,8 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
ntlm_write_message_fields(s, &(message.Workstation));
|
ntlm_write_message_fields(s, &(message.Workstation));
|
||||||
|
|
||||||
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
{
|
|
||||||
/* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
|
|
||||||
|
|
||||||
ntlm_get_version_info(&(message.Version));
|
|
||||||
ntlm_write_version_info(s, &(message.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
|
|
||||||
}
|
|
||||||
|
|
||||||
length = StreamSize(s);
|
length = StreamSize(s);
|
||||||
buffer->cbBuffer = length;
|
buffer->cbBuffer = length;
|
||||||
|
|
||||||
@ -320,6 +314,9 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
printf("NEGOTIATE_MESSAGE (length = %d)\n", length);
|
printf("NEGOTIATE_MESSAGE (length = %d)\n", length);
|
||||||
winpr_HexDump(s->data, length);
|
winpr_HexDump(s->data, length);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
|
ntlm_print_version_info(&(message.Version));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
context->state = NTLM_STATE_CHALLENGE;
|
context->state = NTLM_STATE_CHALLENGE;
|
||||||
@ -523,20 +520,22 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
/* ServerChallenge */
|
/* ServerChallenge */
|
||||||
CopyMemory(message.ServerChallenge, context->ServerChallenge, 8);
|
CopyMemory(message.ServerChallenge, context->ServerChallenge, 8);
|
||||||
|
|
||||||
|
message.NegotiateFlags = context->NegotiateFlags;
|
||||||
|
|
||||||
ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_CHALLENGE);
|
ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_CHALLENGE);
|
||||||
|
|
||||||
/* Message Header (12 bytes) */
|
/* Message Header (12 bytes) */
|
||||||
ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*) &message);
|
ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*) &message);
|
||||||
|
|
||||||
if (context->NegotiateFlags & NTLMSSP_REQUEST_TARGET)
|
if (message.NegotiateFlags & NTLMSSP_REQUEST_TARGET)
|
||||||
{
|
{
|
||||||
message.TargetName.Len = (UINT16) context->TargetName.cbBuffer;
|
message.TargetName.Len = (UINT16) context->TargetName.cbBuffer;
|
||||||
message.TargetName.Buffer = context->TargetName.pvBuffer;
|
message.TargetName.Buffer = context->TargetName.pvBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
context->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
|
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
|
||||||
|
|
||||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
|
||||||
{
|
{
|
||||||
message.TargetInfo.Len = (UINT16) context->TargetInfo.cbBuffer;
|
message.TargetInfo.Len = (UINT16) context->TargetInfo.cbBuffer;
|
||||||
message.TargetInfo.Buffer = context->TargetInfo.pvBuffer;
|
message.TargetInfo.Buffer = context->TargetInfo.pvBuffer;
|
||||||
@ -544,7 +543,7 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
|
|
||||||
PayloadOffset = 48;
|
PayloadOffset = 48;
|
||||||
|
|
||||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
PayloadOffset += 8;
|
PayloadOffset += 8;
|
||||||
|
|
||||||
message.TargetName.BufferOffset = PayloadOffset;
|
message.TargetName.BufferOffset = PayloadOffset;
|
||||||
@ -553,7 +552,7 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
/* TargetNameFields (8 bytes) */
|
/* TargetNameFields (8 bytes) */
|
||||||
ntlm_write_message_fields(s, &(message.TargetName));
|
ntlm_write_message_fields(s, &(message.TargetName));
|
||||||
|
|
||||||
StreamWrite_UINT32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */
|
StreamWrite_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */
|
||||||
|
|
||||||
StreamWrite(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */
|
StreamWrite(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */
|
||||||
StreamWrite(s, message.Reserved, 8); /* Reserved (8 bytes), should be ignored */
|
StreamWrite(s, message.Reserved, 8); /* Reserved (8 bytes), should be ignored */
|
||||||
@ -561,15 +560,15 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
/* TargetInfoFields (8 bytes) */
|
/* TargetInfoFields (8 bytes) */
|
||||||
ntlm_write_message_fields(s, &(message.TargetInfo));
|
ntlm_write_message_fields(s, &(message.TargetInfo));
|
||||||
|
|
||||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
ntlm_write_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
ntlm_write_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
||||||
|
|
||||||
/* Payload (variable) */
|
/* Payload (variable) */
|
||||||
|
|
||||||
if (context->NegotiateFlags & NTLMSSP_REQUEST_TARGET)
|
if (message.NegotiateFlags & NTLMSSP_REQUEST_TARGET)
|
||||||
ntlm_write_message_fields_buffer(s, &(message.TargetName));
|
ntlm_write_message_fields_buffer(s, &(message.TargetName));
|
||||||
|
|
||||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
|
||||||
ntlm_write_message_fields_buffer(s, &(message.TargetInfo));
|
ntlm_write_message_fields_buffer(s, &(message.TargetInfo));
|
||||||
|
|
||||||
length = StreamSize(s);
|
length = StreamSize(s);
|
||||||
@ -583,7 +582,9 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
|
|||||||
winpr_HexDump(context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
|
winpr_HexDump(context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
ntlm_print_negotiate_flags(message.NegotiateFlags);
|
||||||
|
|
||||||
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
ntlm_print_version_info(&(message.Version));
|
ntlm_print_version_info(&(message.Version));
|
||||||
|
|
||||||
ntlm_print_message_fields(&(message.TargetName), "TargetName");
|
ntlm_print_message_fields(&(message.TargetName), "TargetName");
|
||||||
@ -601,6 +602,9 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
|||||||
{
|
{
|
||||||
PStream s;
|
PStream s;
|
||||||
int length;
|
int length;
|
||||||
|
UINT32 flags = 0;
|
||||||
|
NTLMv2_RESPONSE response;
|
||||||
|
UINT32 PayloadBufferOffset;
|
||||||
NTLM_AUTHENTICATE_MESSAGE message;
|
NTLM_AUTHENTICATE_MESSAGE message;
|
||||||
|
|
||||||
ZeroMemory(&message, sizeof(message));
|
ZeroMemory(&message, sizeof(message));
|
||||||
@ -641,10 +645,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
|||||||
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */
|
||||||
|
|
||||||
length = StreamSize(s);
|
PayloadBufferOffset = StreamGetOffset(s);
|
||||||
sspi_SecBufferAlloc(&context->AuthenticateMessage, length);
|
|
||||||
CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length);
|
|
||||||
buffer->cbBuffer = length;
|
|
||||||
|
|
||||||
/* DomainName */
|
/* DomainName */
|
||||||
ntlm_read_message_fields_buffer(s, &(message.DomainName));
|
ntlm_read_message_fields_buffer(s, &(message.DomainName));
|
||||||
@ -663,15 +664,40 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
|||||||
|
|
||||||
if (message.NtChallengeResponse.Len > 0)
|
if (message.NtChallengeResponse.Len > 0)
|
||||||
{
|
{
|
||||||
BYTE* ClientChallengeBuffer;
|
NTLM_AV_PAIR* AvFlags;
|
||||||
ClientChallengeBuffer = message.NtChallengeResponse.Buffer + 32;
|
|
||||||
CopyMemory(context->ClientChallenge, ClientChallengeBuffer, 8);
|
PStream s = PStreamAllocAttach(message.NtChallengeResponse.Buffer, message.NtChallengeResponse.Len);
|
||||||
|
ntlm_read_ntlm_v2_response(s, &response);
|
||||||
|
PStreamFreeDetach(s);
|
||||||
|
|
||||||
|
CopyMemory(context->ClientChallenge, response.Challenge.ClientChallenge, 8);
|
||||||
|
|
||||||
|
AvFlags = ntlm_av_pair_get(response.Challenge.AvPairs, MsvAvFlags);
|
||||||
|
|
||||||
|
if (AvFlags != NULL)
|
||||||
|
flags = *((UINT32*) ntlm_av_pair_get_value_pointer(AvFlags));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EncryptedRandomSessionKey */
|
/* EncryptedRandomSessionKey */
|
||||||
ntlm_read_message_fields_buffer(s, &(message.EncryptedRandomSessionKey));
|
ntlm_read_message_fields_buffer(s, &(message.EncryptedRandomSessionKey));
|
||||||
CopyMemory(context->EncryptedRandomSessionKey, message.EncryptedRandomSessionKey.Buffer, 16);
|
CopyMemory(context->EncryptedRandomSessionKey, message.EncryptedRandomSessionKey.Buffer, 16);
|
||||||
|
|
||||||
|
StreamSetOffset(s, PayloadBufferOffset);
|
||||||
|
|
||||||
|
if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
|
||||||
|
{
|
||||||
|
StreamRead(s, message.MessageIntegrityCheck, 16);
|
||||||
|
PayloadBufferOffset += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move to end of stream, incorrectly assumes the EncryptedRandomSessionKey buffer is last */
|
||||||
|
StreamSetOffset(s, message.EncryptedRandomSessionKey.BufferOffset + message.EncryptedRandomSessionKey.Len);
|
||||||
|
|
||||||
|
length = StreamSize(s);
|
||||||
|
sspi_SecBufferAlloc(&context->AuthenticateMessage, length);
|
||||||
|
CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length);
|
||||||
|
buffer->cbBuffer = length;
|
||||||
|
|
||||||
#ifdef WITH_DEBUG_NTLM
|
#ifdef WITH_DEBUG_NTLM
|
||||||
printf("AUTHENTICATE_MESSAGE (length = %d)\n", length);
|
printf("AUTHENTICATE_MESSAGE (length = %d)\n", length);
|
||||||
winpr_HexDump(s->data, length);
|
winpr_HexDump(s->data, length);
|
||||||
@ -686,6 +712,14 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
|||||||
ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse");
|
ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse");
|
||||||
ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse");
|
ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse");
|
||||||
ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey");
|
ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey");
|
||||||
|
|
||||||
|
ntlm_print_av_pair_list(response.Challenge.AvPairs);
|
||||||
|
|
||||||
|
if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
|
||||||
|
{
|
||||||
|
printf("MessageIntegrityCheck:\n");
|
||||||
|
winpr_HexDump(message.MessageIntegrityCheck, 16);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (message.UserName.Len > 0)
|
if (message.UserName.Len > 0)
|
||||||
@ -835,9 +869,15 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
|||||||
if (context->ntlm_v2 < 1)
|
if (context->ntlm_v2 < 1)
|
||||||
message.Workstation.Len = 0;
|
message.Workstation.Len = 0;
|
||||||
|
|
||||||
|
if (message.Workstation.Len > 0)
|
||||||
|
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
|
||||||
|
|
||||||
message.DomainName.Len = (UINT16) context->identity.DomainLength * 2;
|
message.DomainName.Len = (UINT16) context->identity.DomainLength * 2;
|
||||||
message.DomainName.Buffer = (BYTE*) context->identity.Domain;
|
message.DomainName.Buffer = (BYTE*) context->identity.Domain;
|
||||||
|
|
||||||
|
if (message.DomainName.Len > 0)
|
||||||
|
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
|
||||||
|
|
||||||
message.UserName.Len = (UINT16) context->identity.UserLength * 2;
|
message.UserName.Len = (UINT16) context->identity.UserLength * 2;
|
||||||
message.UserName.Buffer = (BYTE*) context->identity.User;
|
message.UserName.Buffer = (BYTE*) context->identity.User;
|
||||||
|
|
||||||
@ -853,10 +893,10 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
|
|||||||
if (context->confidentiality)
|
if (context->confidentiality)
|
||||||
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
|
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
|
||||||
|
|
||||||
|
PayloadBufferOffset = 64;
|
||||||
|
|
||||||
if (context->ntlm_v2)
|
if (context->ntlm_v2)
|
||||||
PayloadBufferOffset = 80; /* starting buffer offset */
|
PayloadBufferOffset += 16; /* Message Integrity Check */
|
||||||
else
|
|
||||||
PayloadBufferOffset = 64; /* starting buffer offset */
|
|
||||||
|
|
||||||
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
|
||||||
PayloadBufferOffset += 8;
|
PayloadBufferOffset += 8;
|
||||||
|
Loading…
Reference in New Issue
Block a user