From bf559e37ebcedb95ac62223961f683c46e61e38b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 1 Jul 2012 17:05:31 -0400 Subject: [PATCH] libwinpr-sspi: add proper detection of MIC in server-side NLA --- winpr/sspi/NTLM/ntlm.c | 4 +- winpr/sspi/NTLM/ntlm.h | 16 +++-- winpr/sspi/NTLM/ntlm_av_pairs.c | 54 ++++++++++++--- winpr/sspi/NTLM/ntlm_av_pairs.h | 4 +- winpr/sspi/NTLM/ntlm_compute.c | 45 +++++++++++++ winpr/sspi/NTLM/ntlm_compute.h | 3 + winpr/sspi/NTLM/ntlm_message.c | 112 ++++++++++++++++++++++---------- 7 files changed, 184 insertions(+), 54 deletions(-) diff --git a/winpr/sspi/NTLM/ntlm.c b/winpr/sspi/NTLM/ntlm.c index 487e8c448..791bb50d8 100644 --- a/winpr/sspi/NTLM/ntlm.c +++ b/winpr/sspi/NTLM/ntlm.c @@ -86,9 +86,9 @@ NTLM_CONTEXT* ntlm_ContextNew() if (context != NULL) { - context->ntlm_v2 = FALSE; + context->ntlm_v2 = TRUE; context->NegotiateFlags = 0; - context->SendVersionInfo = 0; + context->SendVersionInfo = TRUE; context->LmCompatibilityLevel = 3; context->state = NTLM_STATE_INITIAL; context->SuppressExtendedProtection = 1; diff --git a/winpr/sspi/NTLM/ntlm.h b/winpr/sspi/NTLM/ntlm.h index 097de9ae1..bdd801455 100644 --- a/winpr/sspi/NTLM/ntlm.h +++ b/winpr/sspi/NTLM/ntlm.h @@ -126,12 +126,16 @@ enum _AV_ID }; typedef enum _AV_ID AV_ID; -#define WINDOWS_MAJOR_VERSION_5 0x05 -#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 +#define MSV_AV_FLAGS_AUTHENTICATION_CONSTRAINED 0x00000001 +#define MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK 0x00000002 +#define MSV_AV_FLAGS_TARGET_SPN_UNTRUSTED_SOURCE 0x00000004 + +#define WINDOWS_MAJOR_VERSION_5 0x05 +#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 { diff --git a/winpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/sspi/NTLM/ntlm_av_pairs.c index e246d4653..5abe81b4b 100644 --- a/winpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/sspi/NTLM/ntlm_av_pairs.c @@ -28,7 +28,7 @@ #include "ntlm_av_pairs.h" -const char* const AV_PAIRS_STRINGS[] = +const char* const AV_PAIR_STRINGS[] = { "MsvAvEOL", "MsvAvNbComputerName", @@ -51,6 +51,47 @@ void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList) 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) { /* 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)); } -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; @@ -87,11 +128,6 @@ NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, LONG AvPai 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); } @@ -102,7 +138,7 @@ NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_S { NTLM_AV_PAIR* pAvPair; - pAvPair = ntlm_av_pair_get(pAvPairList, MsvAvEOL, AvPairListSize); + pAvPair = ntlm_av_pair_get(pAvPairList, MsvAvEOL); if (!pAvPair) return NULL; @@ -207,7 +243,7 @@ void ntlm_input_av_pairs(NTLM_CONTEXT* context, PStream s) #ifdef WITH_DEBUG_NTLM 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 printf("\tAvId: %s, AvLen: %d\n", "Unknown", AvLen); diff --git a/winpr/sspi/NTLM/ntlm_av_pairs.h b/winpr/sspi/NTLM/ntlm_av_pairs.h index d4ed2426e..2ce615c0f 100644 --- a/winpr/sspi/NTLM/ntlm_av_pairs.h +++ b/winpr/sspi/NTLM/ntlm_av_pairs.h @@ -25,11 +25,13 @@ #include 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); 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_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); void ntlm_construct_server_target_info(NTLM_CONTEXT* context); diff --git a/winpr/sspi/NTLM/ntlm_compute.c b/winpr/sspi/NTLM/ntlm_compute.c index e4f730363..a2078156f 100644 --- a/winpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/sspi/NTLM/ntlm_compute.c @@ -103,6 +103,51 @@ void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo) 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 * Restriction_Encoding @msdn{cc236647} diff --git a/winpr/sspi/NTLM/ntlm_compute.h b/winpr/sspi/NTLM/ntlm_compute.h index 7fa5b7094..75740a10c 100644 --- a/winpr/sspi/NTLM/ntlm_compute.h +++ b/winpr/sspi/NTLM/ntlm_compute.h @@ -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_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_target_name(NTLM_CONTEXT* context); void ntlm_output_channel_bindings(NTLM_CONTEXT* context); diff --git a/winpr/sspi/NTLM/ntlm_message.c b/winpr/sspi/NTLM/ntlm_message.c index 3964b5d06..2108d04a9 100644 --- a/winpr/sspi/NTLM/ntlm_message.c +++ b/winpr/sspi/NTLM/ntlm_message.c @@ -209,10 +209,7 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf ntlm_read_message_fields(s, &(message.Workstation)); if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */ - } length = StreamSize(s); buffer->cbBuffer = length; @@ -225,6 +222,11 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf printf("NEGOTIATE_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)); #endif 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); - /* Message Header (12 bytes) */ - ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*) &message); - if (context->ntlm_v2) { message.NegotiateFlags |= NTLMSSP_NEGOTIATE_56; @@ -275,6 +274,9 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; } + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_get_version_info(&(message.Version)); + if (context->confidentiality) message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; @@ -283,6 +285,9 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu 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) */ /* 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)); 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)); -#ifdef WITH_DEBUG_NTLM - printf("Version (length = 8)\n"); - winpr_HexDump((s->p - 8), 8); - printf("\n"); -#endif - } - length = StreamSize(s); buffer->cbBuffer = length; @@ -320,6 +314,9 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu printf("NEGOTIATE_MESSAGE (length = %d)\n", length); winpr_HexDump(s->data, length); printf("\n"); + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); #endif context->state = NTLM_STATE_CHALLENGE; @@ -523,20 +520,22 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu /* ServerChallenge */ CopyMemory(message.ServerChallenge, context->ServerChallenge, 8); + message.NegotiateFlags = context->NegotiateFlags; + ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_CHALLENGE); /* Message Header (12 bytes) */ 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.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.Buffer = context->TargetInfo.pvBuffer; @@ -544,7 +543,7 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu PayloadOffset = 48; - if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) PayloadOffset += 8; message.TargetName.BufferOffset = PayloadOffset; @@ -553,7 +552,7 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu /* TargetNameFields (8 bytes) */ 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.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) */ 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) */ /* Payload (variable) */ - if (context->NegotiateFlags & NTLMSSP_REQUEST_TARGET) + if (message.NegotiateFlags & NTLMSSP_REQUEST_TARGET) 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)); 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); 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_message_fields(&(message.TargetName), "TargetName"); @@ -601,6 +602,9 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer { PStream s; int length; + UINT32 flags = 0; + NTLMv2_RESPONSE response; + UINT32 PayloadBufferOffset; NTLM_AUTHENTICATE_MESSAGE message; ZeroMemory(&message, sizeof(message)); @@ -641,10 +645,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) 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; + PayloadBufferOffset = StreamGetOffset(s); /* 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) { - BYTE* ClientChallengeBuffer; - ClientChallengeBuffer = message.NtChallengeResponse.Buffer + 32; - CopyMemory(context->ClientChallenge, ClientChallengeBuffer, 8); + NTLM_AV_PAIR* AvFlags; + + 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 */ ntlm_read_message_fields_buffer(s, &(message.EncryptedRandomSessionKey)); 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 printf("AUTHENTICATE_MESSAGE (length = %d)\n", 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.NtChallengeResponse), "NtChallengeResponse"); 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 if (message.UserName.Len > 0) @@ -835,9 +869,15 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer if (context->ntlm_v2 < 1) 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.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.Buffer = (BYTE*) context->identity.User; @@ -853,10 +893,10 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer if (context->confidentiality) message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; + PayloadBufferOffset = 64; + if (context->ntlm_v2) - PayloadBufferOffset = 80; /* starting buffer offset */ - else - PayloadBufferOffset = 64; /* starting buffer offset */ + PayloadBufferOffset += 16; /* Message Integrity Check */ if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) PayloadBufferOffset += 8;