20#include <winpr/config.h>
26#include <winpr/assert.h>
27#include <winpr/print.h>
28#include <winpr/stream.h>
29#include <winpr/sysinfo.h>
31#include "ntlm_compute.h"
33#include "ntlm_message.h"
36#define TAG WINPR_TAG("sspi.NTLM")
38#define NTLM_CheckAndLogRequiredCapacity(tag, s, nmemb, what) \
39 Stream_CheckAndLogRequiredCapacityEx(tag, WLOG_WARN, s, nmemb, 1, "%s(%s:%" PRIuz ") " what, \
40 __func__, __FILE__, (size_t)__LINE__)
42static const char NTLM_SIGNATURE[8] = {
'N',
'T',
'L',
'M',
'S',
'S',
'P',
'\0' };
46const char* ntlm_get_negotiate_string(UINT32 flag)
48 if (flag & NTLMSSP_NEGOTIATE_56)
49 return "NTLMSSP_NEGOTIATE_56";
50 if (flag & NTLMSSP_NEGOTIATE_KEY_EXCH)
51 return "NTLMSSP_NEGOTIATE_KEY_EXCH";
52 if (flag & NTLMSSP_NEGOTIATE_128)
53 return "NTLMSSP_NEGOTIATE_128";
54 if (flag & NTLMSSP_RESERVED1)
55 return "NTLMSSP_RESERVED1";
56 if (flag & NTLMSSP_RESERVED2)
57 return "NTLMSSP_RESERVED2";
58 if (flag & NTLMSSP_RESERVED3)
59 return "NTLMSSP_RESERVED3";
60 if (flag & NTLMSSP_NEGOTIATE_VERSION)
61 return "NTLMSSP_NEGOTIATE_VERSION";
62 if (flag & NTLMSSP_RESERVED4)
63 return "NTLMSSP_RESERVED4";
64 if (flag & NTLMSSP_NEGOTIATE_TARGET_INFO)
65 return "NTLMSSP_NEGOTIATE_TARGET_INFO";
66 if (flag & NTLMSSP_REQUEST_NON_NT_SESSION_KEY)
67 return "NTLMSSP_REQUEST_NON_NT_SESSION_KEY";
68 if (flag & NTLMSSP_RESERVED5)
69 return "NTLMSSP_RESERVED5";
70 if (flag & NTLMSSP_NEGOTIATE_IDENTIFY)
71 return "NTLMSSP_NEGOTIATE_IDENTIFY";
72 if (flag & NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY)
73 return "NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY";
74 if (flag & NTLMSSP_RESERVED6)
75 return "NTLMSSP_RESERVED6";
76 if (flag & NTLMSSP_TARGET_TYPE_SERVER)
77 return "NTLMSSP_TARGET_TYPE_SERVER";
78 if (flag & NTLMSSP_TARGET_TYPE_DOMAIN)
79 return "NTLMSSP_TARGET_TYPE_DOMAIN";
80 if (flag & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
81 return "NTLMSSP_NEGOTIATE_ALWAYS_SIGN";
82 if (flag & NTLMSSP_RESERVED7)
83 return "NTLMSSP_RESERVED7";
84 if (flag & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED)
85 return "NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED";
86 if (flag & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED)
87 return "NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED";
88 if (flag & NTLMSSP_NEGOTIATE_ANONYMOUS)
89 return "NTLMSSP_NEGOTIATE_ANONYMOUS";
90 if (flag & NTLMSSP_RESERVED8)
91 return "NTLMSSP_RESERVED8";
92 if (flag & NTLMSSP_NEGOTIATE_NTLM)
93 return "NTLMSSP_NEGOTIATE_NTLM";
94 if (flag & NTLMSSP_RESERVED9)
95 return "NTLMSSP_RESERVED9";
96 if (flag & NTLMSSP_NEGOTIATE_LM_KEY)
97 return "NTLMSSP_NEGOTIATE_LM_KEY";
98 if (flag & NTLMSSP_NEGOTIATE_DATAGRAM)
99 return "NTLMSSP_NEGOTIATE_DATAGRAM";
100 if (flag & NTLMSSP_NEGOTIATE_SEAL)
101 return "NTLMSSP_NEGOTIATE_SEAL";
102 if (flag & NTLMSSP_NEGOTIATE_SIGN)
103 return "NTLMSSP_NEGOTIATE_SIGN";
104 if (flag & NTLMSSP_RESERVED10)
105 return "NTLMSSP_RESERVED10";
106 if (flag & NTLMSSP_REQUEST_TARGET)
107 return "NTLMSSP_REQUEST_TARGET";
108 if (flag & NTLMSSP_NEGOTIATE_OEM)
109 return "NTLMSSP_NEGOTIATE_OEM";
110 if (flag & NTLMSSP_NEGOTIATE_UNICODE)
111 return "NTLMSSP_NEGOTIATE_UNICODE";
112 return "NTLMSSP_NEGOTIATE_UNKNOWN";
115#if defined(WITH_DEBUG_NTLM)
118 WINPR_ASSERT(fields);
121 WLog_VRB(TAG,
"%s (Len: %" PRIu16
" MaxLen: %" PRIu16
" BufferOffset: %" PRIu32
")", name,
122 fields->Len, fields->MaxLen, fields->BufferOffset);
125 winpr_HexDump(TAG, WLOG_TRACE, fields->Buffer, fields->Len);
128static void ntlm_print_negotiate_flags(UINT32 flags)
130 WLog_VRB(TAG,
"negotiateFlags \"0x%08" PRIX32
"\"", flags);
132 for (
int i = 31; i >= 0; i--)
134 if ((flags >> i) & 1)
136 const char* str = ntlm_get_negotiate_string(1u << i);
137 WLog_VRB(TAG,
"\t%s (%d),", str, (31 - i));
142static void ntlm_print_negotiate_message(
const SecBuffer* NegotiateMessage,
145 WINPR_ASSERT(NegotiateMessage);
146 WINPR_ASSERT(message);
148 WLog_VRB(TAG,
"NEGOTIATE_MESSAGE (length = %" PRIu32
")", NegotiateMessage->cbBuffer);
149 winpr_HexDump(TAG, WLOG_TRACE, NegotiateMessage->pvBuffer, NegotiateMessage->cbBuffer);
150 ntlm_print_negotiate_flags(message->NegotiateFlags);
152 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
153 ntlm_print_version_info(&(message->Version));
156static void ntlm_print_challenge_message(
const SecBuffer* ChallengeMessage,
160 WINPR_ASSERT(ChallengeMessage);
161 WINPR_ASSERT(message);
163 WLog_VRB(TAG,
"CHALLENGE_MESSAGE (length = %" PRIu32
")", ChallengeMessage->cbBuffer);
164 winpr_HexDump(TAG, WLOG_TRACE, ChallengeMessage->pvBuffer, ChallengeMessage->cbBuffer);
165 ntlm_print_negotiate_flags(message->NegotiateFlags);
167 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
168 ntlm_print_version_info(&(message->Version));
170 ntlm_print_message_fields(&(message->TargetName),
"TargetName");
171 ntlm_print_message_fields(&(message->TargetInfo),
"TargetInfo");
173 if (ChallengeTargetInfo && (ChallengeTargetInfo->cbBuffer > 0))
175 WLog_VRB(TAG,
"ChallengeTargetInfo (%" PRIu32
"):", ChallengeTargetInfo->cbBuffer);
176 ntlm_print_av_pair_list(ChallengeTargetInfo->pvBuffer, ChallengeTargetInfo->cbBuffer);
180static void ntlm_print_authenticate_message(
const SecBuffer* AuthenticateMessage,
184 WINPR_ASSERT(AuthenticateMessage);
185 WINPR_ASSERT(message);
187 WLog_VRB(TAG,
"AUTHENTICATE_MESSAGE (length = %" PRIu32
")", AuthenticateMessage->cbBuffer);
188 winpr_HexDump(TAG, WLOG_TRACE, AuthenticateMessage->pvBuffer, AuthenticateMessage->cbBuffer);
189 ntlm_print_negotiate_flags(message->NegotiateFlags);
191 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
192 ntlm_print_version_info(&(message->Version));
194 if (AuthenticateTargetInfo && (AuthenticateTargetInfo->cbBuffer > 0))
196 WLog_VRB(TAG,
"AuthenticateTargetInfo (%" PRIu32
"):", AuthenticateTargetInfo->cbBuffer);
197 ntlm_print_av_pair_list(AuthenticateTargetInfo->pvBuffer, AuthenticateTargetInfo->cbBuffer);
200 ntlm_print_message_fields(&(message->DomainName),
"DomainName");
201 ntlm_print_message_fields(&(message->UserName),
"UserName");
202 ntlm_print_message_fields(&(message->Workstation),
"Workstation");
203 ntlm_print_message_fields(&(message->LmChallengeResponse),
"LmChallengeResponse");
204 ntlm_print_message_fields(&(message->NtChallengeResponse),
"NtChallengeResponse");
205 ntlm_print_message_fields(&(message->EncryptedRandomSessionKey),
"EncryptedRandomSessionKey");
207 if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
209 WLog_VRB(TAG,
"MessageIntegrityCheck (length = 16)");
210 winpr_HexDump(TAG, WLOG_TRACE, message->MessageIntegrityCheck,
211 sizeof(message->MessageIntegrityCheck));
215static void ntlm_print_authentication_complete(
const NTLM_CONTEXT* context)
217 WINPR_ASSERT(context);
219 WLog_VRB(TAG,
"ClientChallenge");
220 winpr_HexDump(TAG, WLOG_TRACE, context->ClientChallenge, 8);
221 WLog_VRB(TAG,
"ServerChallenge");
222 winpr_HexDump(TAG, WLOG_TRACE, context->ServerChallenge, 8);
223 WLog_VRB(TAG,
"SessionBaseKey");
224 winpr_HexDump(TAG, WLOG_TRACE, context->SessionBaseKey, 16);
225 WLog_VRB(TAG,
"KeyExchangeKey");
226 winpr_HexDump(TAG, WLOG_TRACE, context->KeyExchangeKey, 16);
227 WLog_VRB(TAG,
"ExportedSessionKey");
228 winpr_HexDump(TAG, WLOG_TRACE, context->ExportedSessionKey, 16);
229 WLog_VRB(TAG,
"RandomSessionKey");
230 winpr_HexDump(TAG, WLOG_TRACE, context->RandomSessionKey, 16);
231 WLog_VRB(TAG,
"ClientSigningKey");
232 winpr_HexDump(TAG, WLOG_TRACE, context->ClientSigningKey, 16);
233 WLog_VRB(TAG,
"ClientSealingKey");
234 winpr_HexDump(TAG, WLOG_TRACE, context->ClientSealingKey, 16);
235 WLog_VRB(TAG,
"ServerSigningKey");
236 winpr_HexDump(TAG, WLOG_TRACE, context->ServerSigningKey, 16);
237 WLog_VRB(TAG,
"ServerSealingKey");
238 winpr_HexDump(TAG, WLOG_TRACE, context->ServerSealingKey, 16);
239 WLog_VRB(TAG,
"Timestamp");
240 winpr_HexDump(TAG, WLOG_TRACE, context->Timestamp, 8);
247 WINPR_ASSERT(header);
249 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
252 Stream_Read(s, header->Signature, 8);
253 Stream_Read_UINT32(s, header->MessageType);
255 if (strncmp((
char*)header->Signature, NTLM_SIGNATURE, 8) != 0)
257 char Signature[
sizeof(header->Signature) * 3 + 1] = WINPR_C_ARRAY_INIT;
258 winpr_BinToHexStringBuffer(header->Signature,
sizeof(header->Signature), Signature,
259 sizeof(Signature), TRUE);
261 WLog_ERR(TAG,
"NTLM_MESSAGE_HEADER Invalid signature, got %s, expected %s", Signature,
266 if (header->MessageType != expected)
268 WLog_ERR(TAG,
"NTLM_MESSAGE_HEADER Invalid message type, got %s, expected %s",
269 ntlm_message_type_string(header->MessageType), ntlm_message_type_string(expected));
279 WINPR_ASSERT(header);
281 if (!NTLM_CheckAndLogRequiredCapacity(TAG, s,
sizeof(NTLM_SIGNATURE) + 4ull,
282 "NTLM_MESSAGE_HEADER::header"))
285 Stream_Write(s, header->Signature,
sizeof(NTLM_SIGNATURE));
286 Stream_Write_UINT32(s, header->MessageType);
293 WINPR_ASSERT(header);
295 CopyMemory(header->Signature, NTLM_SIGNATURE,
sizeof(NTLM_SIGNATURE));
296 header->MessageType = MessageType;
303 WINPR_ASSERT(fields);
305 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
308 ntlm_free_message_fields_buffer(fields);
310 Stream_Read_UINT16(s, fields->Len);
311 Stream_Read_UINT16(s, fields->MaxLen);
312 Stream_Read_UINT32(s, fields->BufferOffset);
320 WINPR_ASSERT(fields);
322 MaxLen = fields->MaxLen;
323 if (fields->MaxLen < 1)
324 MaxLen = fields->Len;
326 if (!NTLM_CheckAndLogRequiredCapacity(TAG, (s), 8,
"NTLM_MESSAGE_FIELDS::header"))
329 Stream_Write_UINT16(s, fields->Len);
330 Stream_Write_UINT16(s, MaxLen);
331 Stream_Write_UINT32(s, fields->BufferOffset);
338 WINPR_ASSERT(fields);
340 ntlm_free_message_fields_buffer(fields);
343 const size_t offset = 1ull * fields->BufferOffset + fields->Len;
345 if (fields->BufferOffset > UINT32_MAX - fields->Len)
348 "NTLM_MESSAGE_FIELDS::BufferOffset %" PRIu32
349 " too large, maximum allowed is %" PRIu32,
350 fields->BufferOffset, UINT32_MAX - fields->Len);
354 if (offset > Stream_Length(s))
357 "NTLM_MESSAGE_FIELDS::Buffer offset %" PRIuz
" beyond received data %" PRIuz,
358 offset, Stream_Length(s));
362 fields->Buffer = (PBYTE)malloc(fields->Len);
366 WLog_ERR(TAG,
"NTLM_MESSAGE_FIELDS::Buffer allocation of %" PRIu16
"bytes failed",
371 if (!Stream_SetPosition(s, fields->BufferOffset))
373 ntlm_free_message_fields_buffer(fields);
376 Stream_Read(s, fields->Buffer, fields->Len);
385 WINPR_ASSERT(fields);
389 if (!Stream_SetPosition(s, fields->BufferOffset))
391 if (!NTLM_CheckAndLogRequiredCapacity(TAG, (s), fields->Len,
"NTLM_MESSAGE_FIELDS::Len"))
394 Stream_Write(s, fields->Buffer, fields->Len);
405 free(fields->Buffer);
408 fields->Buffer =
nullptr;
409 fields->BufferOffset = 0;
414static BOOL ntlm_read_negotiate_flags(
wStream* s, UINT32* flags, UINT32 required,
const char* name)
416 UINT32 NegotiateFlags = 0;
417 char buffer[1024] = WINPR_C_ARRAY_INIT;
422 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
425 Stream_Read_UINT32(s, NegotiateFlags);
427 if ((NegotiateFlags & required) != required)
429 WLog_ERR(TAG,
"%s::NegotiateFlags invalid flags 0x08%" PRIx32
", 0x%08" PRIx32
" required",
430 name, NegotiateFlags, required);
434 WLog_DBG(TAG,
"Read flags %s",
435 ntlm_negotiate_flags_string(buffer, ARRAYSIZE(buffer), NegotiateFlags));
436 *flags = NegotiateFlags;
440static BOOL ntlm_write_negotiate_flags(
wStream* s, UINT32 flags,
const char* name)
442 char buffer[1024] = WINPR_C_ARRAY_INIT;
446 if (!Stream_CheckAndLogRequiredCapacityEx(TAG, WLOG_WARN, s, 4ull, 1ull,
447 "%s(%s:%" PRIuz
") %s::NegotiateFlags", __func__,
448 __FILE__, (
size_t)__LINE__, name))
451 WLog_DBG(TAG,
"Write flags %s", ntlm_negotiate_flags_string(buffer, ARRAYSIZE(buffer), flags));
452 Stream_Write_UINT32(s, flags);
456static BOOL ntlm_read_message_integrity_check(
wStream* s,
size_t* offset, BYTE* data,
size_t size,
457 WINPR_ATTR_UNUSED
const char* name)
460 WINPR_ASSERT(offset);
462 WINPR_ASSERT(size == WINPR_MD5_DIGEST_LENGTH);
465 *offset = Stream_GetPosition(s);
467 if (!Stream_CheckAndLogRequiredLength(TAG, s, size))
470 Stream_Read(s, data, size);
474static BOOL ntlm_write_message_integrity_check(
wStream* s,
size_t offset,
const BYTE* data,
475 size_t size, WINPR_ATTR_UNUSED
const char* name)
479 WINPR_ASSERT(size == WINPR_MD5_DIGEST_LENGTH);
482 const size_t pos = Stream_GetPosition(s);
484 if (!NTLM_CheckAndLogRequiredCapacity(TAG, s, offset,
"MessageIntegrityCheck::offset"))
487 if (!Stream_SetPosition(s, offset))
489 if (!NTLM_CheckAndLogRequiredCapacity(TAG, s, size,
"MessageIntegrityCheck::size"))
492 Stream_Write(s, data, size);
493 return Stream_SetPosition(s, pos);
498 wStream sbuffer = WINPR_C_ARRAY_INIT;
502 WINPR_ASSERT(context);
503 WINPR_ASSERT(buffer);
506 WINPR_ASSERT(message);
510 wStream* s = Stream_StaticConstInit(&sbuffer, buffer->pvBuffer, buffer->cbBuffer);
513 return SEC_E_INTERNAL_ERROR;
515 if (!ntlm_read_message_header(s, &message->header, MESSAGE_TYPE_NEGOTIATE))
516 return SEC_E_INVALID_TOKEN;
518 if (!ntlm_read_negotiate_flags(s, &message->NegotiateFlags,
519 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
520 NTLMSSP_NEGOTIATE_UNICODE,
521 "NTLM_NEGOTIATE_MESSAGE"))
522 return SEC_E_INVALID_TOKEN;
524 context->NegotiateFlags = message->NegotiateFlags;
529 if (!ntlm_read_message_fields(s, &(message->DomainName)))
530 return SEC_E_INVALID_TOKEN;
536 if (!ntlm_read_message_fields(s, &(message->Workstation)))
537 return SEC_E_INVALID_TOKEN;
540 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
542 if (!ntlm_read_version_info(s, &(message->Version)))
543 return SEC_E_INVALID_TOKEN;
546 if (!ntlm_read_message_fields_buffer(s, &message->DomainName))
547 return SEC_E_INVALID_TOKEN;
549 if (!ntlm_read_message_fields_buffer(s, &message->Workstation))
550 return SEC_E_INVALID_TOKEN;
552 length = Stream_GetPosition(s);
553 WINPR_ASSERT(length <= UINT32_MAX);
554 buffer->cbBuffer = (ULONG)length;
556 if (!sspi_SecBufferAlloc(&context->NegotiateMessage, (ULONG)length))
557 return SEC_E_INTERNAL_ERROR;
559 CopyMemory(context->NegotiateMessage.pvBuffer, buffer->pvBuffer, buffer->cbBuffer);
560 context->NegotiateMessage.BufferType = buffer->BufferType;
561#if defined(WITH_DEBUG_NTLM)
562 ntlm_print_negotiate_message(&context->NegotiateMessage, message);
564 ntlm_change_state(context, NTLM_STATE_CHALLENGE);
565 return SEC_I_CONTINUE_NEEDED;
570 wStream sbuffer = WINPR_C_ARRAY_INIT;
574 WINPR_ASSERT(context);
575 WINPR_ASSERT(buffer);
578 WINPR_ASSERT(message);
582 wStream* s = Stream_StaticInit(&sbuffer, buffer->pvBuffer, buffer->cbBuffer);
585 return SEC_E_INTERNAL_ERROR;
587 if (!ntlm_populate_message_header(&message->header, MESSAGE_TYPE_NEGOTIATE))
588 return SEC_E_INTERNAL_ERROR;
592 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
593 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
594 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY;
595 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM;
598 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
599 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
600 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
601 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
602 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
603 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
604 message->NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
605 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
607 if (context->confidentiality)
608 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
610 if (context->SendVersionInfo)
611 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
613 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
615 if (!ntlm_get_version_info(&(message->Version)))
616 return SEC_E_INTERNAL_ERROR;
619 context->NegotiateFlags = message->NegotiateFlags;
621 if (!ntlm_write_message_header(s, &message->header))
622 return SEC_E_INTERNAL_ERROR;
624 if (!ntlm_write_negotiate_flags(s, message->NegotiateFlags,
"NTLM_NEGOTIATE_MESSAGE"))
625 return SEC_E_INTERNAL_ERROR;
629 if (!ntlm_write_message_fields(s, &(message->DomainName)))
630 return SEC_E_INTERNAL_ERROR;
634 if (!ntlm_write_message_fields(s, &(message->Workstation)))
635 return SEC_E_INTERNAL_ERROR;
637 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
639 if (!ntlm_write_version_info(s, &(message->Version)))
640 return SEC_E_INTERNAL_ERROR;
643 length = Stream_GetPosition(s);
644 WINPR_ASSERT(length <= UINT32_MAX);
645 buffer->cbBuffer = (ULONG)length;
647 if (!sspi_SecBufferAlloc(&context->NegotiateMessage, (ULONG)length))
648 return SEC_E_INTERNAL_ERROR;
650 CopyMemory(context->NegotiateMessage.pvBuffer, buffer->pvBuffer, buffer->cbBuffer);
651 context->NegotiateMessage.BufferType = buffer->BufferType;
652#if defined(WITH_DEBUG_NTLM)
653 ntlm_print_negotiate_message(&context->NegotiateMessage, message);
655 ntlm_change_state(context, NTLM_STATE_CHALLENGE);
656 return SEC_I_CONTINUE_NEEDED;
661 SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
662 wStream sbuffer = WINPR_C_ARRAY_INIT;
664 size_t StartOffset = 0;
665 size_t PayloadOffset = 0;
668 if (!context || !buffer)
669 return SEC_E_INTERNAL_ERROR;
671 if (!ntlm_generate_client_challenge(context))
672 return SEC_E_INTERNAL_ERROR;
675 WINPR_ASSERT(message);
679 wStream* s = Stream_StaticConstInit(&sbuffer, buffer->pvBuffer, buffer->cbBuffer);
682 return SEC_E_INTERNAL_ERROR;
684 StartOffset = Stream_GetPosition(s);
686 if (!ntlm_read_message_header(s, &message->header, MESSAGE_TYPE_CHALLENGE))
689 if (!ntlm_read_message_fields(s, &(message->TargetName)))
692 if (!ntlm_read_negotiate_flags(s, &message->NegotiateFlags, 0,
"NTLM_CHALLENGE_MESSAGE"))
695 context->NegotiateFlags = message->NegotiateFlags;
697 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
700 Stream_Read(s, message->ServerChallenge, 8);
701 CopyMemory(context->ServerChallenge, message->ServerChallenge, 8);
702 Stream_Read(s, message->Reserved, 8);
704 if (!ntlm_read_message_fields(s, &(message->TargetInfo)))
707 if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
709 if (!ntlm_read_version_info(s, &(message->Version)))
714 PayloadOffset = Stream_GetPosition(s);
716 status = SEC_E_INTERNAL_ERROR;
717 if (message->TargetName.Len > 0)
719 if (!ntlm_read_message_fields_buffer(s, &(message->TargetName)))
723 if (message->TargetInfo.Len > 0)
725 size_t cbAvTimestamp = 0;
727 if (!ntlm_read_message_fields_buffer(s, &(message->TargetInfo)))
730 context->ChallengeTargetInfo.pvBuffer = message->TargetInfo.Buffer;
731 context->ChallengeTargetInfo.cbBuffer = message->TargetInfo.Len;
733 ntlm_av_pair_get((
NTLM_AV_PAIR*)message->TargetInfo.Buffer, message->TargetInfo.Len,
734 MsvAvTimestamp, &cbAvTimestamp);
738 PBYTE ptr = ntlm_av_pair_get_value_pointer(AvTimestamp, cbAvTimestamp);
740 if (!ptr || (AvTimestamp->AvLen < 8))
744 context->UseMIC = TRUE;
746 CopyMemory(context->ChallengeTimestamp, ptr, 8);
750 length = (PayloadOffset - StartOffset) + message->TargetName.Len + message->TargetInfo.Len;
751 if (length > buffer->cbBuffer)
754 if (!sspi_SecBufferAlloc(&context->ChallengeMessage, (ULONG)length))
757 if (context->ChallengeMessage.pvBuffer)
758 CopyMemory(context->ChallengeMessage.pvBuffer, Stream_Buffer(s) + StartOffset, length);
759#if defined(WITH_DEBUG_NTLM)
760 ntlm_print_challenge_message(&context->ChallengeMessage, message,
nullptr);
766 if (!ntlm_construct_authenticate_target_info(context))
769 sspi_SecBufferFree(&context->ChallengeTargetInfo);
770 context->ChallengeTargetInfo.pvBuffer = context->AuthenticateTargetInfo.pvBuffer;
771 context->ChallengeTargetInfo.cbBuffer = context->AuthenticateTargetInfo.cbBuffer;
774 ntlm_generate_timestamp(context);
777 const SECURITY_STATUS rc = ntlm_compute_lm_v2_response(context);
786 const SECURITY_STATUS rc2 =
787 ntlm_compute_ntlm_v2_response(context);
795 if (!ntlm_generate_key_exchange_key(context))
797 if (!ntlm_generate_random_session_key(context))
799 if (!ntlm_generate_exported_session_key(context))
801 if (!ntlm_encrypt_random_session_key(context))
805 status = SEC_E_ENCRYPT_FAILURE;
806 if (!ntlm_generate_client_signing_key(context))
808 if (!ntlm_generate_server_signing_key(context))
811 if (!ntlm_generate_client_sealing_key(context))
813 if (!ntlm_generate_server_sealing_key(context))
816 if (!ntlm_init_rc4_seal_states(context))
818#if defined(WITH_DEBUG_NTLM)
819 ntlm_print_authentication_complete(context);
821 ntlm_change_state(context, NTLM_STATE_AUTHENTICATE);
822 status = SEC_I_CONTINUE_NEEDED;
824 ntlm_free_message_fields_buffer(&(message->TargetName));
830 wStream sbuffer = WINPR_C_ARRAY_INIT;
832 UINT32 PayloadOffset = 0;
835 WINPR_ASSERT(context);
836 WINPR_ASSERT(buffer);
839 WINPR_ASSERT(message);
843 wStream* s = Stream_StaticInit(&sbuffer, buffer->pvBuffer, buffer->cbBuffer);
846 return SEC_E_INTERNAL_ERROR;
848 if (!ntlm_get_version_info(&(message->Version)))
849 return SEC_E_INTERNAL_ERROR;
850 if (!ntlm_generate_server_challenge(context))
851 return SEC_E_INTERNAL_ERROR;
852 ntlm_generate_timestamp(context);
854 if (!ntlm_construct_challenge_target_info(context))
855 return SEC_E_INTERNAL_ERROR;
857 CopyMemory(message->ServerChallenge, context->ServerChallenge, 8);
858 message->NegotiateFlags = context->NegotiateFlags;
859 if (!ntlm_populate_message_header(&message->header, MESSAGE_TYPE_CHALLENGE))
860 return SEC_E_INTERNAL_ERROR;
863 if (!ntlm_write_message_header(s, &message->header))
864 return SEC_E_INTERNAL_ERROR;
866 if (message->NegotiateFlags & NTLMSSP_REQUEST_TARGET)
868 message->TargetName.Len = (UINT16)context->TargetName.cbBuffer;
869 message->TargetName.Buffer = (PBYTE)context->TargetName.pvBuffer;
872 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
874 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
876 message->TargetInfo.Len = (UINT16)context->ChallengeTargetInfo.cbBuffer;
877 message->TargetInfo.Buffer = (PBYTE)context->ChallengeTargetInfo.pvBuffer;
882 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
885 message->TargetName.BufferOffset = PayloadOffset;
886 message->TargetInfo.BufferOffset = message->TargetName.BufferOffset + message->TargetName.Len;
888 if (!ntlm_write_message_fields(s, &(message->TargetName)))
889 return SEC_E_INTERNAL_ERROR;
891 if (!ntlm_write_negotiate_flags(s, message->NegotiateFlags,
"NTLM_CHALLENGE_MESSAGE"))
892 return SEC_E_INTERNAL_ERROR;
894 if (!NTLM_CheckAndLogRequiredCapacity(TAG, s, 16,
"NTLM_CHALLENGE_MESSAGE::ServerChallenge"))
895 return SEC_E_INTERNAL_ERROR;
897 Stream_Write(s, message->ServerChallenge, 8);
898 Stream_Write(s, message->Reserved, 8);
901 if (!ntlm_write_message_fields(s, &(message->TargetInfo)))
902 return SEC_E_INTERNAL_ERROR;
904 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
906 if (!ntlm_write_version_info(s, &(message->Version)))
907 return SEC_E_INTERNAL_ERROR;
911 if (message->NegotiateFlags & NTLMSSP_REQUEST_TARGET)
913 if (!ntlm_write_message_fields_buffer(s, &(message->TargetName)))
914 return SEC_E_INTERNAL_ERROR;
917 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
919 if (!ntlm_write_message_fields_buffer(s, &(message->TargetInfo)))
920 return SEC_E_INTERNAL_ERROR;
923 length = Stream_GetPosition(s);
924 WINPR_ASSERT(length <= UINT32_MAX);
925 buffer->cbBuffer = (ULONG)length;
927 if (!sspi_SecBufferAlloc(&context->ChallengeMessage, (ULONG)length))
928 return SEC_E_INTERNAL_ERROR;
930 CopyMemory(context->ChallengeMessage.pvBuffer, Stream_Buffer(s), length);
931#if defined(WITH_DEBUG_NTLM)
932 ntlm_print_challenge_message(&context->ChallengeMessage, message,
933 &context->ChallengeTargetInfo);
935 ntlm_change_state(context, NTLM_STATE_AUTHENTICATE);
936 return SEC_I_CONTINUE_NEEDED;
941 SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
942 wStream sbuffer = WINPR_C_ARRAY_INIT;
946 size_t PayloadBufferOffset = 0;
949 WINPR_ASSERT(context);
950 WINPR_ASSERT(buffer);
953 WINPR_ASSERT(credentials);
956 WINPR_ASSERT(message);
960 wStream* s = Stream_StaticConstInit(&sbuffer, buffer->pvBuffer, buffer->cbBuffer);
963 return SEC_E_INTERNAL_ERROR;
965 if (!ntlm_read_message_header(s, &message->header, MESSAGE_TYPE_AUTHENTICATE))
968 if (!ntlm_read_message_fields(
969 s, &(message->LmChallengeResponse)))
972 if (!ntlm_read_message_fields(
973 s, &(message->NtChallengeResponse)))
976 if (!ntlm_read_message_fields(s, &(message->DomainName)))
979 if (!ntlm_read_message_fields(s, &(message->UserName)))
982 if (!ntlm_read_message_fields(s, &(message->Workstation)))
985 if (!ntlm_read_message_fields(
987 &(message->EncryptedRandomSessionKey)))
990 if (!ntlm_read_negotiate_flags(s, &message->NegotiateFlags, 0,
"NTLM_AUTHENTICATE_MESSAGE"))
993 context->NegotiateKeyExchange = (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) != 0;
995 if ((context->NegotiateKeyExchange && !message->EncryptedRandomSessionKey.Len) ||
996 (!context->NegotiateKeyExchange && message->EncryptedRandomSessionKey.Len))
999 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
1001 if (!ntlm_read_version_info(s, &(message->Version)))
1005 PayloadBufferOffset = Stream_GetPosition(s);
1007 status = SEC_E_INTERNAL_ERROR;
1008 if (!ntlm_read_message_fields_buffer(s, &(message->DomainName)))
1011 if (!ntlm_read_message_fields_buffer(s, &(message->UserName)))
1014 if (!ntlm_read_message_fields_buffer(s, &(message->Workstation)))
1017 if (!ntlm_read_message_fields_buffer(s,
1018 &(message->LmChallengeResponse)))
1021 if (!ntlm_read_message_fields_buffer(s,
1022 &(message->NtChallengeResponse)))
1025 if (ntlm_SetContextWorkstationX(context, TRUE, message->Workstation.Buffer,
1026 message->Workstation.Len) != SEC_E_OK)
1029 if (message->NtChallengeResponse.Len > 0)
1031 size_t cbAvFlags = 0;
1033 wStream* snt = Stream_StaticConstInit(&ssbuffer, message->NtChallengeResponse.Buffer,
1034 message->NtChallengeResponse.Len);
1039 status = SEC_E_INVALID_TOKEN;
1040 if (!ntlm_read_ntlm_v2_response(snt, &(context->NTLMv2Response)))
1042 status = SEC_E_INTERNAL_ERROR;
1044 context->NtChallengeResponse.pvBuffer = message->NtChallengeResponse.Buffer;
1045 context->NtChallengeResponse.cbBuffer = message->NtChallengeResponse.Len;
1046 sspi_SecBufferFree(&(context->ChallengeTargetInfo));
1047 context->ChallengeTargetInfo.pvBuffer = (
void*)context->NTLMv2Response.Challenge.AvPairs;
1048 context->ChallengeTargetInfo.cbBuffer = message->NtChallengeResponse.Len - (28 + 16);
1049 CopyMemory(context->ClientChallenge, context->NTLMv2Response.Challenge.ClientChallenge, 8);
1051 ntlm_av_pair_get(context->NTLMv2Response.Challenge.AvPairs,
1052 context->NTLMv2Response.Challenge.cbAvPairs, MsvAvFlags, &cbAvFlags);
1056 const BYTE* ptr = ntlm_av_pair_get_value_pointer(AvFlags, cbAvFlags);
1057 if (!ptr || (AvFlags->AvLen < 4))
1059 flags = winpr_Data_Get_UINT32(ptr);
1063 if (!ntlm_read_message_fields_buffer(
1064 s, &(message->EncryptedRandomSessionKey)))
1067 if (message->EncryptedRandomSessionKey.Len > 0)
1069 if (message->EncryptedRandomSessionKey.Len != 16)
1072 CopyMemory(context->EncryptedRandomSessionKey, message->EncryptedRandomSessionKey.Buffer,
1076 length = Stream_GetPosition(s);
1077 WINPR_ASSERT(length <= UINT32_MAX);
1079 if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, (ULONG)length))
1082 CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length);
1083 buffer->cbBuffer = (ULONG)length;
1084 if (!Stream_SetPosition(s, PayloadBufferOffset))
1087 if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
1089 status = SEC_E_INVALID_TOKEN;
1090 if (!ntlm_read_message_integrity_check(
1091 s, &context->MessageIntegrityCheckOffset, message->MessageIntegrityCheck,
1092 sizeof(message->MessageIntegrityCheck),
"NTLM_AUTHENTICATE_MESSAGE"))
1096 status = SEC_E_INTERNAL_ERROR;
1098#if defined(WITH_DEBUG_NTLM)
1099 ntlm_print_authenticate_message(&context->AuthenticateMessage, message, flags,
nullptr);
1102 if (message->UserName.Len > 0)
1104 credentials->identity.User = (UINT16*)calloc(message->UserName.Len +
sizeof(WCHAR), 1);
1106 if (!credentials->identity.User)
1109 CopyMemory(credentials->identity.User, message->UserName.Buffer, message->UserName.Len);
1110 credentials->identity.UserLength = message->UserName.Len /
sizeof(WCHAR);
1113 if (message->DomainName.Len > 0)
1115 credentials->identity.Domain = (UINT16*)calloc(message->DomainName.Len +
sizeof(WCHAR), 1);
1117 if (!credentials->identity.Domain)
1120 CopyMemory(credentials->identity.Domain, message->DomainName.Buffer,
1121 message->DomainName.Len);
1122 credentials->identity.DomainLength = message->DomainName.Len /
sizeof(WCHAR);
1125 if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY)
1127 const SECURITY_STATUS rc = ntlm_compute_lm_v2_response(context);
1136 const SECURITY_STATUS rc = ntlm_compute_ntlm_v2_response(context);
1145 if (!ntlm_generate_key_exchange_key(context))
1148 if (!ntlm_decrypt_random_session_key(context))
1151 if (!ntlm_generate_exported_session_key(context))
1154 if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
1156 BYTE messageIntegrityCheck[16] = WINPR_C_ARRAY_INIT;
1158 if (!ntlm_compute_message_integrity_check(context, messageIntegrityCheck,
1159 sizeof(messageIntegrityCheck)))
1162 &((PBYTE)context->AuthenticateMessage.pvBuffer)[context->MessageIntegrityCheckOffset],
1163 message->MessageIntegrityCheck,
sizeof(message->MessageIntegrityCheck));
1165 if (memcmp(messageIntegrityCheck, message->MessageIntegrityCheck,
1166 sizeof(message->MessageIntegrityCheck)) != 0)
1168 WLog_ERR(TAG,
"Message Integrity Check (MIC) verification failed!");
1169#ifdef WITH_DEBUG_NTLM
1170 WLog_ERR(TAG,
"Expected MIC:");
1171 winpr_HexDump(TAG, WLOG_ERROR, messageIntegrityCheck,
sizeof(messageIntegrityCheck));
1172 WLog_ERR(TAG,
"Actual MIC:");
1173 winpr_HexDump(TAG, WLOG_ERROR, message->MessageIntegrityCheck,
1174 sizeof(message->MessageIntegrityCheck));
1176 status = SEC_E_MESSAGE_ALTERED;
1192#ifdef WITH_DEBUG_NTLM
1193 WLog_VRB(TAG,
"No MIC present, using NtProofString for verification.");
1196 if (memcmp(context->NTLMv2Response.Response, context->NtProofString, 16) != 0)
1198 WLog_ERR(TAG,
"NtProofString verification failed!");
1199#ifdef WITH_DEBUG_NTLM
1200 WLog_ERR(TAG,
"Expected NtProofString:");
1201 winpr_HexDump(TAG, WLOG_ERROR, context->NtProofString,
sizeof(context->NtProofString));
1202 WLog_ERR(TAG,
"Actual NtProofString:");
1203 winpr_HexDump(TAG, WLOG_ERROR, context->NTLMv2Response.Response,
1204 sizeof(context->NTLMv2Response));
1206 status = SEC_E_LOGON_DENIED;
1212 if (!ntlm_generate_client_signing_key(context))
1214 if (!ntlm_generate_server_signing_key(context))
1217 if (!ntlm_generate_client_sealing_key(context))
1219 if (!ntlm_generate_server_sealing_key(context))
1222 if (!ntlm_init_rc4_seal_states(context))
1224#if defined(WITH_DEBUG_NTLM)
1225 ntlm_print_authentication_complete(context);
1227 ntlm_change_state(context, NTLM_STATE_FINAL);
1231 ntlm_free_message_fields_buffer(&(message->DomainName));
1232 ntlm_free_message_fields_buffer(&(message->UserName));
1233 ntlm_free_message_fields_buffer(&(message->Workstation));
1234 ntlm_free_message_fields_buffer(&(message->LmChallengeResponse));
1239 if (context->NtChallengeResponse.pvBuffer != message->NtChallengeResponse.Buffer)
1240 ntlm_free_message_fields_buffer(&(message->NtChallengeResponse));
1241 ntlm_free_message_fields_buffer(&(message->EncryptedRandomSessionKey));
1254 wStream sbuffer = WINPR_C_ARRAY_INIT;
1256 UINT32 PayloadBufferOffset = 0;
1259 WINPR_ASSERT(context);
1260 WINPR_ASSERT(buffer);
1263 WINPR_ASSERT(credentials);
1266 WINPR_ASSERT(message);
1270 wStream* s = Stream_StaticInit(&sbuffer, buffer->pvBuffer, buffer->cbBuffer);
1273 return SEC_E_INTERNAL_ERROR;
1275 if (context->NTLMv2)
1277 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
1279 if (context->SendVersionInfo)
1280 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
1283 if (context->UseMIC)
1284 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
1286 if (context->SendWorkstationName)
1287 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
1289 if (context->confidentiality)
1290 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
1292 if (context->CHALLENGE_MESSAGE.NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
1293 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
1295 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
1296 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
1297 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
1298 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
1299 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
1300 message->NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
1301 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
1303 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
1305 if (!ntlm_get_version_info(&(message->Version)))
1306 return SEC_E_INTERNAL_ERROR;
1309 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED)
1311 message->Workstation.Len = context->Workstation.Length;
1312 message->Workstation.Buffer = (BYTE*)context->Workstation.Buffer;
1315 if (credentials->identity.DomainLength > 0)
1317 message->NegotiateFlags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
1318 message->DomainName.Len = (UINT16)credentials->identity.DomainLength *
sizeof(WCHAR);
1319 message->DomainName.Buffer = (BYTE*)credentials->identity.Domain;
1322 message->UserName.Len = (UINT16)credentials->identity.UserLength *
sizeof(WCHAR);
1323 message->UserName.Buffer = (BYTE*)credentials->identity.User;
1324 message->LmChallengeResponse.Len = (UINT16)context->LmChallengeResponse.cbBuffer;
1325 message->LmChallengeResponse.Buffer = (BYTE*)context->LmChallengeResponse.pvBuffer;
1326 message->NtChallengeResponse.Len = (UINT16)context->NtChallengeResponse.cbBuffer;
1327 message->NtChallengeResponse.Buffer = (BYTE*)context->NtChallengeResponse.pvBuffer;
1329 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
1331 message->EncryptedRandomSessionKey.Len = 16;
1332 message->EncryptedRandomSessionKey.Buffer = context->EncryptedRandomSessionKey;
1335 PayloadBufferOffset = 64;
1337 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
1338 PayloadBufferOffset += 8;
1340 if (context->UseMIC)
1341 PayloadBufferOffset += 16;
1343 message->DomainName.BufferOffset = PayloadBufferOffset;
1344 message->UserName.BufferOffset = message->DomainName.BufferOffset + message->DomainName.Len;
1345 message->Workstation.BufferOffset = message->UserName.BufferOffset + message->UserName.Len;
1346 message->LmChallengeResponse.BufferOffset =
1347 message->Workstation.BufferOffset + message->Workstation.Len;
1348 message->NtChallengeResponse.BufferOffset =
1349 message->LmChallengeResponse.BufferOffset + message->LmChallengeResponse.Len;
1350 message->EncryptedRandomSessionKey.BufferOffset =
1351 message->NtChallengeResponse.BufferOffset + message->NtChallengeResponse.Len;
1352 if (!ntlm_populate_message_header(&message->header, MESSAGE_TYPE_AUTHENTICATE))
1353 return SEC_E_INVALID_TOKEN;
1354 if (!ntlm_write_message_header(s, &message->header))
1355 return SEC_E_INTERNAL_ERROR;
1356 if (!ntlm_write_message_fields(
1357 s, &(message->LmChallengeResponse)))
1358 return SEC_E_INTERNAL_ERROR;
1359 if (!ntlm_write_message_fields(
1360 s, &(message->NtChallengeResponse)))
1361 return SEC_E_INTERNAL_ERROR;
1362 if (!ntlm_write_message_fields(s, &(message->DomainName)))
1363 return SEC_E_INTERNAL_ERROR;
1364 if (!ntlm_write_message_fields(s, &(message->UserName)))
1365 return SEC_E_INTERNAL_ERROR;
1366 if (!ntlm_write_message_fields(s, &(message->Workstation)))
1367 return SEC_E_INTERNAL_ERROR;
1368 if (!ntlm_write_message_fields(
1370 &(message->EncryptedRandomSessionKey)))
1371 return SEC_E_INTERNAL_ERROR;
1372 if (!ntlm_write_negotiate_flags(s, message->NegotiateFlags,
"NTLM_AUTHENTICATE_MESSAGE"))
1373 return SEC_E_INTERNAL_ERROR;
1375 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
1377 if (!ntlm_write_version_info(s, &(message->Version)))
1378 return SEC_E_INTERNAL_ERROR;
1381 if (context->UseMIC)
1383 const BYTE data[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1385 context->MessageIntegrityCheckOffset = Stream_GetPosition(s);
1386 if (!ntlm_write_message_integrity_check(s, Stream_GetPosition(s), data,
sizeof(data),
1387 "NTLM_AUTHENTICATE_MESSAGE"))
1388 return SEC_E_INTERNAL_ERROR;
1391 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED)
1393 if (!ntlm_write_message_fields_buffer(s, &(message->DomainName)))
1394 return SEC_E_INTERNAL_ERROR;
1397 if (!ntlm_write_message_fields_buffer(s, &(message->UserName)))
1398 return SEC_E_INTERNAL_ERROR;
1400 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED)
1402 if (!ntlm_write_message_fields_buffer(s, &(message->Workstation)))
1403 return SEC_E_INTERNAL_ERROR;
1406 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY)
1408 if (!ntlm_write_message_fields_buffer(
1409 s, &(message->LmChallengeResponse)))
1410 return SEC_E_INTERNAL_ERROR;
1412 if (!ntlm_write_message_fields_buffer(
1413 s, &(message->NtChallengeResponse)))
1414 return SEC_E_INTERNAL_ERROR;
1416 if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
1418 if (!ntlm_write_message_fields_buffer(
1419 s, &(message->EncryptedRandomSessionKey)))
1420 return SEC_E_INTERNAL_ERROR;
1423 length = Stream_GetPosition(s);
1424 WINPR_ASSERT(length <= UINT32_MAX);
1426 if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, (ULONG)length))
1427 return SEC_E_INTERNAL_ERROR;
1429 CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length);
1430 buffer->cbBuffer = (ULONG)length;
1432 if (context->UseMIC)
1435 if (!ntlm_compute_message_integrity_check(context, message->MessageIntegrityCheck,
1436 sizeof(message->MessageIntegrityCheck)))
1437 return SEC_E_INTERNAL_ERROR;
1438 if (!ntlm_write_message_integrity_check(
1439 s, context->MessageIntegrityCheckOffset, message->MessageIntegrityCheck,
1440 sizeof(message->MessageIntegrityCheck),
"NTLM_AUTHENTICATE_MESSAGE"))
1441 return SEC_E_INTERNAL_ERROR;
1444#if defined(WITH_DEBUG_NTLM)
1445 ntlm_print_authenticate_message(&context->AuthenticateMessage, message,
1446 context->UseMIC ? MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK : 0,
1447 &context->AuthenticateTargetInfo);
1449 ntlm_change_state(context, NTLM_STATE_FINAL);