Blame winpr/libwinpr/sspi/NTLM/ntlm_message.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * NTLM Security Package (Message)
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include "ntlm.h"
Packit 1fb8d4
#include "../sspi.h"
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/print.h>
Packit 1fb8d4
#include <winpr/stream.h>
Packit 1fb8d4
#include <winpr/sysinfo.h>
Packit 1fb8d4
Packit 1fb8d4
#include "ntlm_compute.h"
Packit 1fb8d4
Packit 1fb8d4
#include "ntlm_message.h"
Packit 1fb8d4
Packit 1fb8d4
#include "../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("sspi.NTLM")
Packit 1fb8d4
Packit 1fb8d4
static const char NTLM_SIGNATURE[8] = { 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0' };
Packit 1fb8d4
Packit Service 5a9772
#ifdef WITH_DEBUG_NTLM
Packit Service 5a9772
static const char* const NTLM_NEGOTIATE_STRINGS[] = { "NTLMSSP_NEGOTIATE_56",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_KEY_EXCH",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_128",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED1",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED2",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED3",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_VERSION",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED4",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_TARGET_INFO",
Packit Service 5a9772
	                                                  "NTLMSSP_REQUEST_NON_NT_SESSION_KEY",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED5",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_IDENTIFY",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED6",
Packit Service 5a9772
	                                                  "NTLMSSP_TARGET_TYPE_SERVER",
Packit Service 5a9772
	                                                  "NTLMSSP_TARGET_TYPE_DOMAIN",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_ALWAYS_SIGN",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED7",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_ANONYMOUS",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED8",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_NTLM",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED9",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_LM_KEY",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_DATAGRAM",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_SEAL",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_SIGN",
Packit Service 5a9772
	                                                  "NTLMSSP_RESERVED10",
Packit Service 5a9772
	                                                  "NTLMSSP_REQUEST_TARGET",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_OEM",
Packit Service 5a9772
	                                                  "NTLMSSP_NEGOTIATE_UNICODE" };
Packit 1fb8d4
Packit 1fb8d4
static void ntlm_print_negotiate_flags(UINT32 flags)
Packit 1fb8d4
{
Packit 1fb8d4
	int i;
Packit 1fb8d4
	const char* str;
Packit Service 5a9772
	WLog_INFO(TAG, "negotiateFlags \"0x%08" PRIX32 "\"", flags);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 31; i >= 0; i--)
Packit 1fb8d4
	{
Packit 1fb8d4
		if ((flags >> i) & 1)
Packit 1fb8d4
		{
Packit 1fb8d4
			str = NTLM_NEGOTIATE_STRINGS[(31 - i)];
Packit 1fb8d4
			WLog_INFO(TAG, "\t%s (%d),", str, (31 - i));
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit Service 5a9772
#endif
Packit 1fb8d4
Packit 1fb8d4
static int ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
Packit 1fb8d4
{
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 12)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read(s, header->Signature, 8);
Packit 1fb8d4
	Stream_Read_UINT32(s, header->MessageType);
Packit 1fb8d4
Packit Service 5a9772
	if (strncmp((char*)header->Signature, NTLM_SIGNATURE, 8) != 0)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void ntlm_write_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
Packit 1fb8d4
{
Packit 1fb8d4
	Stream_Write(s, header->Signature, sizeof(NTLM_SIGNATURE));
Packit 1fb8d4
	Stream_Write_UINT32(s, header->MessageType);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void ntlm_populate_message_header(NTLM_MESSAGE_HEADER* header, UINT32 MessageType)
Packit 1fb8d4
{
Packit 1fb8d4
	CopyMemory(header->Signature, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE));
Packit 1fb8d4
	header->MessageType = MessageType;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
Packit 1fb8d4
{
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 8)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit Service 5a9772
	Stream_Read_UINT16(s, fields->Len);          /* Len (2 bytes) */
Packit Service 5a9772
	Stream_Read_UINT16(s, fields->MaxLen);       /* MaxLen (2 bytes) */
Packit 1fb8d4
	Stream_Read_UINT32(s, fields->BufferOffset); /* BufferOffset (4 bytes) */
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void ntlm_write_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
Packit 1fb8d4
{
Packit 1fb8d4
	if (fields->MaxLen < 1)
Packit 1fb8d4
		fields->MaxLen = fields->Len;
Packit 1fb8d4
Packit Service 5a9772
	Stream_Write_UINT16(s, fields->Len);          /* Len (2 bytes) */
Packit Service 5a9772
	Stream_Write_UINT16(s, fields->MaxLen);       /* MaxLen (2 bytes) */
Packit 1fb8d4
	Stream_Write_UINT32(s, fields->BufferOffset); /* BufferOffset (4 bytes) */
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
Packit 1fb8d4
{
Packit 1fb8d4
	if (fields->Len > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		const UINT32 offset = fields->BufferOffset + fields->Len;
Packit 1fb8d4
Packit 1fb8d4
		if (fields->BufferOffset > UINT32_MAX - fields->Len)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		if (offset > Stream_Length(s))
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit Service 5a9772
		fields->Buffer = (PBYTE)malloc(fields->Len);
Packit 1fb8d4
Packit 1fb8d4
		if (!fields->Buffer)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		Stream_SetPosition(s, fields->BufferOffset);
Packit 1fb8d4
		Stream_Read(s, fields->Buffer, fields->Len);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void ntlm_write_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
Packit 1fb8d4
{
Packit 1fb8d4
	if (fields->Len > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_SetPosition(s, fields->BufferOffset);
Packit 1fb8d4
		Stream_Write(s, fields->Buffer, fields->Len);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void ntlm_free_message_fields_buffer(NTLM_MESSAGE_FIELDS* fields)
Packit 1fb8d4
{
Packit 1fb8d4
	if (fields)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (fields->Buffer)
Packit 1fb8d4
		{
Packit 1fb8d4
			free(fields->Buffer);
Packit 1fb8d4
			fields->Len = 0;
Packit 1fb8d4
			fields->MaxLen = 0;
Packit 1fb8d4
			fields->Buffer = NULL;
Packit 1fb8d4
			fields->BufferOffset = 0;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
static void ntlm_print_message_fields(NTLM_MESSAGE_FIELDS* fields, const char* name)
Packit 1fb8d4
{
Packit Service 5a9772
	WLog_DBG(TAG, "%s (Len: %" PRIu16 " MaxLen: %" PRIu16 " BufferOffset: %" PRIu32 ")", name,
Packit Service 5a9772
	         fields->Len, fields->MaxLen, fields->BufferOffset);
Packit 1fb8d4
Packit 1fb8d4
	if (fields->Len > 0)
Packit 1fb8d4
		winpr_HexDump(TAG, WLOG_DEBUG, fields->Buffer, fields->Len);
Packit 1fb8d4
}
Packit Service 5a9772
#endif
Packit 1fb8d4
Packit 1fb8d4
SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
Packit 1fb8d4
{
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	size_t length;
Packit 1fb8d4
	NTLM_NEGOTIATE_MESSAGE* message;
Packit 1fb8d4
	message = &context->NEGOTIATE_MESSAGE;
Packit 1fb8d4
	ZeroMemory(message, sizeof(NTLM_NEGOTIATE_MESSAGE));
Packit Service 5a9772
	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit Service 5a9772
	if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*)message) < 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (message->MessageType != MESSAGE_TYPE_NEGOTIATE)
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	if (Stream_GetRemainingLength(s) < 4)
Packit Service 5a9772
	{
Packit Service 5a9772
		Stream_Free(s, FALSE);
Packit Service 5a9772
		return SEC_E_INVALID_TOKEN;
Packit Service 5a9772
	}
Packit 1fb8d4
	Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
Packit 1fb8d4
Packit 1fb8d4
	if (!((message->NegotiateFlags & NTLMSSP_REQUEST_TARGET) &&
Packit 1fb8d4
	      (message->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM) &&
Packit 1fb8d4
	      (message->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE)))
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	context->NegotiateFlags = message->NegotiateFlags;
Packit 1fb8d4
Packit 1fb8d4
	/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_read_message_fields(s, &(message->DomainName)) < 0) /* DomainNameFields (8 bytes) */
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_read_message_fields(s, &(message->Workstation)) < 0) /* WorkstationFields (8 bytes) */
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */
Packit 1fb8d4
		{
Packit 1fb8d4
			Stream_Free(s, FALSE);
Packit 1fb8d4
			return SEC_E_INVALID_TOKEN;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	length = Stream_GetPosition(s);
Packit 1fb8d4
	buffer->cbBuffer = length;
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&context->NegotiateMessage, length))
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(context->NegotiateMessage.pvBuffer, buffer->pvBuffer, buffer->cbBuffer);
Packit 1fb8d4
	context->NegotiateMessage.BufferType = buffer->BufferType;
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit Service 5a9772
	WLog_DBG(TAG, "NEGOTIATE_MESSAGE (length = %" PRIu32 ")", context->NegotiateMessage.cbBuffer);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->NegotiateMessage.pvBuffer,
Packit 1fb8d4
	              context->NegotiateMessage.cbBuffer);
Packit 1fb8d4
	ntlm_print_negotiate_flags(message->NegotiateFlags);
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_print_version_info(&(message->Version));
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	context->state = NTLM_STATE_CHALLENGE;
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit 1fb8d4
	return SEC_I_CONTINUE_NEEDED;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
Packit 1fb8d4
{
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	size_t length;
Packit 1fb8d4
	NTLM_NEGOTIATE_MESSAGE* message;
Packit 1fb8d4
	message = &context->NEGOTIATE_MESSAGE;
Packit 1fb8d4
	ZeroMemory(message, sizeof(NTLM_NEGOTIATE_MESSAGE));
Packit Service 5a9772
	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit Service 5a9772
	ntlm_populate_message_header((NTLM_MESSAGE_HEADER*)message, MESSAGE_TYPE_NEGOTIATE);
Packit 1fb8d4
Packit 1fb8d4
	if (context->NTLMv2)
Packit 1fb8d4
	{
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY;
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
Packit 1fb8d4
Packit 1fb8d4
	if (context->confidentiality)
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
Packit 1fb8d4
Packit 1fb8d4
	if (context->SendVersionInfo)
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_get_version_info(&(message->Version));
Packit 1fb8d4
Packit 1fb8d4
	context->NegotiateFlags = message->NegotiateFlags;
Packit 1fb8d4
	/* Message Header (12 bytes) */
Packit Service 5a9772
	ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*)message);
Packit 1fb8d4
	Stream_Write_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
Packit 1fb8d4
	/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
Packit 1fb8d4
	/* DomainNameFields (8 bytes) */
Packit 1fb8d4
	ntlm_write_message_fields(s, &(message->DomainName));
Packit 1fb8d4
	/* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */
Packit 1fb8d4
	/* WorkstationFields (8 bytes) */
Packit 1fb8d4
	ntlm_write_message_fields(s, &(message->Workstation));
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_write_version_info(s, &(message->Version));
Packit 1fb8d4
Packit 1fb8d4
	length = Stream_GetPosition(s);
Packit 1fb8d4
	buffer->cbBuffer = length;
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&context->NegotiateMessage, length))
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(context->NegotiateMessage.pvBuffer, buffer->pvBuffer, buffer->cbBuffer);
Packit 1fb8d4
	context->NegotiateMessage.BufferType = buffer->BufferType;
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
	WLog_DBG(TAG, "NEGOTIATE_MESSAGE (length = %d)", length);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), length);
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_print_version_info(&(message->Version));
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	context->state = NTLM_STATE_CHALLENGE;
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit 1fb8d4
	return SEC_I_CONTINUE_NEEDED;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
Packit 1fb8d4
{
Packit Service 5a9772
	SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
Packit 1fb8d4
	wStream* s;
Packit Service 5a9772
	size_t length;
Packit Service 5a9772
	size_t StartOffset;
Packit Service 5a9772
	size_t PayloadOffset;
Packit 1fb8d4
	NTLM_AV_PAIR* AvTimestamp;
Packit 1fb8d4
	NTLM_CHALLENGE_MESSAGE* message;
Packit Service 5a9772
	if (!context || !buffer)
Packit Service 5a9772
		return SEC_E_INTERNAL_ERROR;
Packit Service 5a9772
Packit 1fb8d4
	ntlm_generate_client_challenge(context);
Packit 1fb8d4
	message = &context->CHALLENGE_MESSAGE;
Packit 1fb8d4
	ZeroMemory(message, sizeof(NTLM_CHALLENGE_MESSAGE));
Packit Service 5a9772
	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit Service 5a9772
	StartOffset = Stream_GetPosition(s);
Packit 1fb8d4
Packit Service 5a9772
	if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*)message) < 0)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (message->MessageType != MESSAGE_TYPE_CHALLENGE)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_read_message_fields(s, &(message->TargetName)) < 0) /* TargetNameFields (8 bytes) */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 4)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
Packit 1fb8d4
	context->NegotiateFlags = message->NegotiateFlags;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 8)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read(s, message->ServerChallenge, 8); /* ServerChallenge (8 bytes) */
Packit 1fb8d4
	CopyMemory(context->ServerChallenge, message->ServerChallenge, 8);
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 8)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read(s, message->Reserved, 8); /* Reserved (8 bytes), should be ignored */
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_read_message_fields(s, &(message->TargetInfo)) < 0) /* TargetInfoFields (8 bytes) */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Payload (variable) */
Packit Service 5a9772
	PayloadOffset = Stream_GetPosition(s);
Packit 1fb8d4
Packit Service 5a9772
	status = SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
	if (message->TargetName.Len > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (ntlm_read_message_fields_buffer(s, &(message->TargetName)) < 0)
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (message->TargetInfo.Len > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		size_t cbAvTimestamp;
Packit 1fb8d4
Packit 1fb8d4
		if (ntlm_read_message_fields_buffer(s, &(message->TargetInfo)) < 0)
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		context->ChallengeTargetInfo.pvBuffer = message->TargetInfo.Buffer;
Packit 1fb8d4
		context->ChallengeTargetInfo.cbBuffer = message->TargetInfo.Len;
Packit Service 5a9772
		AvTimestamp = ntlm_av_pair_get((NTLM_AV_PAIR*)message->TargetInfo.Buffer,
Packit Service 5a9772
		                               message->TargetInfo.Len, MsvAvTimestamp, &cbAvTimestamp);
Packit 1fb8d4
Packit 1fb8d4
		if (AvTimestamp)
Packit 1fb8d4
		{
Packit Service 5a9772
			PBYTE ptr = ntlm_av_pair_get_value_pointer(AvTimestamp);
Packit 1fb8d4
Packit 1fb8d4
			if (!ptr)
Packit Service 5a9772
				goto fail;
Packit 1fb8d4
Packit 1fb8d4
			if (context->NTLMv2)
Packit 1fb8d4
				context->UseMIC = TRUE;
Packit 1fb8d4
Packit 1fb8d4
			CopyMemory(context->ChallengeTimestamp, ptr, 8);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	length = (PayloadOffset - StartOffset) + message->TargetName.Len + message->TargetInfo.Len;
Packit Service 5a9772
	if (length > buffer->cbBuffer)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&context->ChallengeMessage, length))
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	if (context->ChallengeMessage.pvBuffer)
Packit Service 5a9772
		CopyMemory(context->ChallengeMessage.pvBuffer, Stream_Buffer(s) + StartOffset, length);
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
	WLog_DBG(TAG, "CHALLENGE_MESSAGE (length = %d)", length);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ChallengeMessage.pvBuffer,
Packit 1fb8d4
	              context->ChallengeMessage.cbBuffer);
Packit 1fb8d4
	ntlm_print_negotiate_flags(context->NegotiateFlags);
Packit 1fb8d4
Packit 1fb8d4
	if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_print_version_info(&(message->Version));
Packit 1fb8d4
Packit 1fb8d4
	ntlm_print_message_fields(&(message->TargetName), "TargetName");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->TargetInfo), "TargetInfo");
Packit 1fb8d4
Packit 1fb8d4
	if (context->ChallengeTargetInfo.cbBuffer > 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_DBG(TAG, "ChallengeTargetInfo (%" PRIu32 "):", context->ChallengeTargetInfo.cbBuffer);
Packit Service 5a9772
		ntlm_print_av_pair_list(context->ChallengeTargetInfo.pvBuffer,
Packit Service 5a9772
		                        context->ChallengeTargetInfo.cbBuffer);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	/* AV_PAIRs */
Packit 1fb8d4
Packit 1fb8d4
	if (context->NTLMv2)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (ntlm_construct_authenticate_target_info(context) < 0)
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		sspi_SecBufferFree(&context->ChallengeTargetInfo);
Packit 1fb8d4
		context->ChallengeTargetInfo.pvBuffer = context->AuthenticateTargetInfo.pvBuffer;
Packit 1fb8d4
		context->ChallengeTargetInfo.cbBuffer = context->AuthenticateTargetInfo.cbBuffer;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ntlm_generate_timestamp(context); /* Timestamp */
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_compute_ntlm_v2_response(context) < 0) /* NtChallengeResponse */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	ntlm_generate_key_exchange_key(context);     /* KeyExchangeKey */
Packit Service 5a9772
	ntlm_generate_random_session_key(context);   /* RandomSessionKey */
Packit 1fb8d4
	ntlm_generate_exported_session_key(context); /* ExportedSessionKey */
Packit Service 5a9772
	ntlm_encrypt_random_session_key(context);    /* EncryptedRandomSessionKey */
Packit 1fb8d4
	/* Generate signing keys */
Packit 1fb8d4
	ntlm_generate_client_signing_key(context);
Packit 1fb8d4
	ntlm_generate_server_signing_key(context);
Packit 1fb8d4
	/* Generate sealing keys */
Packit 1fb8d4
	ntlm_generate_client_sealing_key(context);
Packit 1fb8d4
	ntlm_generate_server_sealing_key(context);
Packit 1fb8d4
	/* Initialize RC4 seal state using client sealing key */
Packit 1fb8d4
	ntlm_init_rc4_seal_states(context);
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
	WLog_DBG(TAG, "ClientChallenge");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ClientChallenge, 8);
Packit 1fb8d4
	WLog_DBG(TAG, "ServerChallenge");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ServerChallenge, 8);
Packit 1fb8d4
	WLog_DBG(TAG, "SessionBaseKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->SessionBaseKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "KeyExchangeKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->KeyExchangeKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ExportedSessionKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ExportedSessionKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "RandomSessionKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->RandomSessionKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ClientSigningKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ClientSigningKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ClientSealingKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ClientSealingKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ServerSigningKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ServerSigningKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ServerSealingKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ServerSealingKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "Timestamp");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->Timestamp, 8);
Packit 1fb8d4
#endif
Packit 1fb8d4
	context->state = NTLM_STATE_AUTHENTICATE;
Packit 1fb8d4
	ntlm_free_message_fields_buffer(&(message->TargetName));
Packit Service 5a9772
	status = SEC_I_CONTINUE_NEEDED;
Packit Service 5a9772
fail:
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit Service 5a9772
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
Packit 1fb8d4
{
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	size_t length;
Packit 1fb8d4
	UINT32 PayloadOffset;
Packit 1fb8d4
	NTLM_CHALLENGE_MESSAGE* message;
Packit 1fb8d4
	message = &context->CHALLENGE_MESSAGE;
Packit 1fb8d4
	ZeroMemory(message, sizeof(NTLM_CHALLENGE_MESSAGE));
Packit Service 5a9772
	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit 1fb8d4
	ntlm_get_version_info(&(message->Version)); /* Version */
Packit Service 5a9772
	ntlm_generate_server_challenge(context);    /* Server Challenge */
Packit Service 5a9772
	ntlm_generate_timestamp(context);           /* Timestamp */
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_construct_challenge_target_info(context) < 0) /* TargetInfo */
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(message->ServerChallenge, context->ServerChallenge, 8); /* ServerChallenge */
Packit 1fb8d4
	message->NegotiateFlags = context->NegotiateFlags;
Packit Service 5a9772
	ntlm_populate_message_header((NTLM_MESSAGE_HEADER*)message, MESSAGE_TYPE_CHALLENGE);
Packit 1fb8d4
	/* Message Header (12 bytes) */
Packit Service 5a9772
	ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*)message);
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_REQUEST_TARGET)
Packit 1fb8d4
	{
Packit Service 5a9772
		message->TargetName.Len = (UINT16)context->TargetName.cbBuffer;
Packit Service 5a9772
		message->TargetName.Buffer = (PBYTE)context->TargetName.pvBuffer;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
Packit 1fb8d4
	{
Packit Service 5a9772
		message->TargetInfo.Len = (UINT16)context->ChallengeTargetInfo.cbBuffer;
Packit Service 5a9772
		message->TargetInfo.Buffer = (PBYTE)context->ChallengeTargetInfo.pvBuffer;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	PayloadOffset = 48;
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		PayloadOffset += 8;
Packit 1fb8d4
Packit 1fb8d4
	message->TargetName.BufferOffset = PayloadOffset;
Packit 1fb8d4
	message->TargetInfo.BufferOffset = message->TargetName.BufferOffset + message->TargetName.Len;
Packit 1fb8d4
	/* TargetNameFields (8 bytes) */
Packit 1fb8d4
	ntlm_write_message_fields(s, &(message->TargetName));
Packit 1fb8d4
	Stream_Write_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
Packit Service 5a9772
	Stream_Write(s, message->ServerChallenge, 8);    /* ServerChallenge (8 bytes) */
Packit Service 5a9772
	Stream_Write(s, message->Reserved, 8);           /* Reserved (8 bytes), should be ignored */
Packit 1fb8d4
	/* TargetInfoFields (8 bytes) */
Packit 1fb8d4
	ntlm_write_message_fields(s, &(message->TargetInfo));
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_write_version_info(s, &(message->Version)); /* Version (8 bytes) */
Packit 1fb8d4
Packit 1fb8d4
	/* Payload (variable) */
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_REQUEST_TARGET)
Packit 1fb8d4
		ntlm_write_message_fields_buffer(s, &(message->TargetName));
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
Packit 1fb8d4
		ntlm_write_message_fields_buffer(s, &(message->TargetInfo));
Packit 1fb8d4
Packit 1fb8d4
	length = Stream_GetPosition(s);
Packit 1fb8d4
	buffer->cbBuffer = length;
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&context->ChallengeMessage, length))
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(context->ChallengeMessage.pvBuffer, Stream_Buffer(s), length);
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
	WLog_DBG(TAG, "CHALLENGE_MESSAGE (length = %d)", length);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ChallengeMessage.pvBuffer,
Packit 1fb8d4
	              context->ChallengeMessage.cbBuffer);
Packit 1fb8d4
	ntlm_print_negotiate_flags(message->NegotiateFlags);
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_print_version_info(&(message->Version));
Packit 1fb8d4
Packit 1fb8d4
	ntlm_print_message_fields(&(message->TargetName), "TargetName");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->TargetInfo), "TargetInfo");
Packit 1fb8d4
#endif
Packit 1fb8d4
	context->state = NTLM_STATE_AUTHENTICATE;
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit 1fb8d4
	return SEC_I_CONTINUE_NEEDED;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
Packit 1fb8d4
{
Packit Service 5a9772
	SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	size_t length;
Packit Service 5a9772
	UINT32 flags = 0;
Packit Service 5a9772
	NTLM_AV_PAIR* AvFlags = NULL;
Packit 1fb8d4
	UINT32 PayloadBufferOffset;
Packit 1fb8d4
	NTLM_AUTHENTICATE_MESSAGE* message;
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials = context->credentials;
Packit Service 5a9772
Packit 1fb8d4
	message = &context->AUTHENTICATE_MESSAGE;
Packit 1fb8d4
	ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE));
Packit Service 5a9772
	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit Service 5a9772
	if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*)message) < 0)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (message->MessageType != MESSAGE_TYPE_AUTHENTICATE)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	if (ntlm_read_message_fields(s, &(message->LmChallengeResponse)) <
Packit Service 5a9772
	    0) /* LmChallengeResponseFields (8 bytes) */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	if (ntlm_read_message_fields(s, &(message->NtChallengeResponse)) <
Packit Service 5a9772
	    0) /* NtChallengeResponseFields (8 bytes) */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_read_message_fields(s, &(message->DomainName)) < 0) /* DomainNameFields (8 bytes) */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_read_message_fields(s, &(message->UserName)) < 0) /* UserNameFields (8 bytes) */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_read_message_fields(s, &(message->Workstation)) < 0) /* WorkstationFields (8 bytes) */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	if (ntlm_read_message_fields(s, &(message->EncryptedRandomSessionKey)) <
Packit Service 5a9772
	    0) /* EncryptedRandomSessionKeyFields (8 bytes) */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	if (Stream_GetRemainingLength(s) < 4)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
	Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
Packit Service 5a9772
	context->NegotiateKeyExchange =
Packit Service 5a9772
	    (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) ? TRUE : FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if ((context->NegotiateKeyExchange && !message->EncryptedRandomSessionKey.Len) ||
Packit 1fb8d4
	    (!context->NegotiateKeyExchange && message->EncryptedRandomSessionKey.Len))
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	PayloadBufferOffset = Stream_GetPosition(s);
Packit 1fb8d4
Packit Service 5a9772
	status = SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
	if (ntlm_read_message_fields_buffer(s, &(message->DomainName)) < 0) /* DomainName */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_read_message_fields_buffer(s, &(message->UserName)) < 0) /* UserName */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_read_message_fields_buffer(s, &(message->Workstation)) < 0) /* Workstation */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	if (ntlm_read_message_fields_buffer(s, &(message->LmChallengeResponse)) <
Packit Service 5a9772
	    0) /* LmChallengeResponse */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	if (ntlm_read_message_fields_buffer(s, &(message->NtChallengeResponse)) <
Packit Service 5a9772
	    0) /* NtChallengeResponse */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (message->NtChallengeResponse.Len > 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		int rc;
Packit 1fb8d4
		size_t cbAvFlags;
Packit Service 5a9772
		wStream* snt =
Packit Service 5a9772
		    Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);
Packit 1fb8d4
Packit 1fb8d4
		if (!snt)
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
Packit Service 5a9772
		status = SEC_E_INVALID_TOKEN;
Packit Service 5a9772
		rc = ntlm_read_ntlm_v2_response(snt, &(context->NTLMv2Response));
Packit 1fb8d4
		Stream_Free(snt, FALSE);
Packit Service 5a9772
		if (rc < 0)
Packit Service 5a9772
			goto fail;
Packit Service 5a9772
		status = SEC_E_INTERNAL_ERROR;
Packit Service 5a9772
Packit 1fb8d4
		context->NtChallengeResponse.pvBuffer = message->NtChallengeResponse.Buffer;
Packit 1fb8d4
		context->NtChallengeResponse.cbBuffer = message->NtChallengeResponse.Len;
Packit 1fb8d4
		sspi_SecBufferFree(&(context->ChallengeTargetInfo));
Packit Service 5a9772
		context->ChallengeTargetInfo.pvBuffer = (void*)context->NTLMv2Response.Challenge.AvPairs;
Packit 1fb8d4
		context->ChallengeTargetInfo.cbBuffer = message->NtChallengeResponse.Len - (28 + 16);
Packit 1fb8d4
		CopyMemory(context->ClientChallenge, context->NTLMv2Response.Challenge.ClientChallenge, 8);
Packit Service 5a9772
		AvFlags =
Packit Service 5a9772
		    ntlm_av_pair_get(context->NTLMv2Response.Challenge.AvPairs,
Packit Service 5a9772
		                     context->NTLMv2Response.Challenge.cbAvPairs, MsvAvFlags, &cbAvFlags);
Packit 1fb8d4
Packit 1fb8d4
		if (AvFlags)
Packit Service 5a9772
			Data_Read_UINT32(ntlm_av_pair_get_value_pointer(AvFlags), flags);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	if (ntlm_read_message_fields_buffer(s, &(message->EncryptedRandomSessionKey)) <
Packit Service 5a9772
	    0) /* EncryptedRandomSessionKey */
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (message->EncryptedRandomSessionKey.Len > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (message->EncryptedRandomSessionKey.Len != 16)
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
Packit Service 5a9772
		CopyMemory(context->EncryptedRandomSessionKey, message->EncryptedRandomSessionKey.Buffer,
Packit Service 5a9772
		           16);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	length = Stream_GetPosition(s);
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, length))
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length);
Packit 1fb8d4
	buffer->cbBuffer = length;
Packit 1fb8d4
	Stream_SetPosition(s, PayloadBufferOffset);
Packit 1fb8d4
Packit 1fb8d4
	if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
Packit 1fb8d4
	{
Packit Service 5a9772
		context->MessageIntegrityCheckOffset = (UINT32)Stream_GetPosition(s);
Packit 1fb8d4
Packit Service 5a9772
		status = SEC_E_INVALID_TOKEN;
Packit 1fb8d4
		if (Stream_GetRemainingLength(s) < 16)
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		Stream_Read(s, message->MessageIntegrityCheck, 16);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	status = SEC_E_INTERNAL_ERROR;
Packit Service 5a9772
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit Service 5a9772
	WLog_DBG(TAG, "AUTHENTICATE_MESSAGE (length = %" PRIu32 ")",
Packit Service 5a9772
	         context->AuthenticateMessage.cbBuffer);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->AuthenticateMessage.pvBuffer,
Packit 1fb8d4
	              context->AuthenticateMessage.cbBuffer);
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_print_version_info(&(message->Version));
Packit 1fb8d4
Packit 1fb8d4
	ntlm_print_message_fields(&(message->DomainName), "DomainName");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->UserName), "UserName");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->Workstation), "Workstation");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->LmChallengeResponse), "LmChallengeResponse");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->NtChallengeResponse), "NtChallengeResponse");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->EncryptedRandomSessionKey), "EncryptedRandomSessionKey");
Packit Service 5a9772
	ntlm_print_av_pair_list(context->NTLMv2Response.Challenge.AvPairs,
Packit Service 5a9772
	                        context->NTLMv2Response.Challenge.cbAvPairs);
Packit 1fb8d4
Packit 1fb8d4
	if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_DBG(TAG, "MessageIntegrityCheck:");
Packit 1fb8d4
		winpr_HexDump(TAG, WLOG_DEBUG, message->MessageIntegrityCheck, 16);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (message->UserName.Len > 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		credentials->identity.User = (UINT16*)malloc(message->UserName.Len);
Packit 1fb8d4
Packit 1fb8d4
		if (!credentials->identity.User)
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(credentials->identity.User, message->UserName.Buffer, message->UserName.Len);
Packit 1fb8d4
		credentials->identity.UserLength = message->UserName.Len / 2;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (message->DomainName.Len > 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		credentials->identity.Domain = (UINT16*)malloc(message->DomainName.Len);
Packit 1fb8d4
Packit 1fb8d4
		if (!credentials->identity.Domain)
Packit Service 5a9772
			goto fail;
Packit 1fb8d4
Packit Service 5a9772
		CopyMemory(credentials->identity.Domain, message->DomainName.Buffer,
Packit Service 5a9772
		           message->DomainName.Len);
Packit 1fb8d4
		credentials->identity.DomainLength = message->DomainName.Len / 2;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit 1fb8d4
	/* Computations beyond this point require the NTLM hash of the password */
Packit 1fb8d4
	context->state = NTLM_STATE_COMPLETION;
Packit 1fb8d4
	return SEC_I_COMPLETE_NEEDED;
Packit Service 5a9772
Packit Service 5a9772
fail:
Packit Service 5a9772
	Stream_Free(s, FALSE);
Packit Service 5a9772
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Send NTLMSSP AUTHENTICATE_MESSAGE.\n
Packit 1fb8d4
 * AUTHENTICATE_MESSAGE @msdn{cc236643}
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 * @param buffer
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
Packit 1fb8d4
{
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	size_t length;
Packit 1fb8d4
	UINT32 PayloadBufferOffset;
Packit 1fb8d4
	NTLM_AUTHENTICATE_MESSAGE* message;
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials = context->credentials;
Packit 1fb8d4
	message = &context->AUTHENTICATE_MESSAGE;
Packit 1fb8d4
	ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE));
Packit Service 5a9772
	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit 1fb8d4
	if (context->NTLMv2)
Packit 1fb8d4
	{
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
Packit 1fb8d4
Packit 1fb8d4
		if (context->SendVersionInfo)
Packit 1fb8d4
			message->NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (context->UseMIC)
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
Packit 1fb8d4
Packit 1fb8d4
	if (context->SendWorkstationName)
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
Packit 1fb8d4
Packit 1fb8d4
	if (context->confidentiality)
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
Packit 1fb8d4
Packit 1fb8d4
	if (context->CHALLENGE_MESSAGE.NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
Packit 1fb8d4
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
Packit 1fb8d4
	message->NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_get_version_info(&(message->Version));
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED)
Packit 1fb8d4
	{
Packit 1fb8d4
		message->Workstation.Len = context->Workstation.Length;
Packit Service 5a9772
		message->Workstation.Buffer = (BYTE*)context->Workstation.Buffer;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (credentials->identity.DomainLength > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		message->NegotiateFlags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
Packit Service 5a9772
		message->DomainName.Len = (UINT16)credentials->identity.DomainLength * 2;
Packit Service 5a9772
		message->DomainName.Buffer = (BYTE*)credentials->identity.Domain;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	message->UserName.Len = (UINT16)credentials->identity.UserLength * 2;
Packit Service 5a9772
	message->UserName.Buffer = (BYTE*)credentials->identity.User;
Packit Service 5a9772
	message->LmChallengeResponse.Len = (UINT16)context->LmChallengeResponse.cbBuffer;
Packit Service 5a9772
	message->LmChallengeResponse.Buffer = (BYTE*)context->LmChallengeResponse.pvBuffer;
Packit Service 5a9772
	message->NtChallengeResponse.Len = (UINT16)context->NtChallengeResponse.cbBuffer;
Packit Service 5a9772
	message->NtChallengeResponse.Buffer = (BYTE*)context->NtChallengeResponse.pvBuffer;
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
Packit 1fb8d4
	{
Packit 1fb8d4
		message->EncryptedRandomSessionKey.Len = 16;
Packit 1fb8d4
		message->EncryptedRandomSessionKey.Buffer = context->EncryptedRandomSessionKey;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	PayloadBufferOffset = 64;
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		PayloadBufferOffset += 8; /* Version (8 bytes) */
Packit 1fb8d4
Packit 1fb8d4
	if (context->UseMIC)
Packit 1fb8d4
		PayloadBufferOffset += 16; /* Message Integrity Check (16 bytes) */
Packit 1fb8d4
Packit 1fb8d4
	message->DomainName.BufferOffset = PayloadBufferOffset;
Packit 1fb8d4
	message->UserName.BufferOffset = message->DomainName.BufferOffset + message->DomainName.Len;
Packit 1fb8d4
	message->Workstation.BufferOffset = message->UserName.BufferOffset + message->UserName.Len;
Packit Service 5a9772
	message->LmChallengeResponse.BufferOffset =
Packit Service 5a9772
	    message->Workstation.BufferOffset + message->Workstation.Len;
Packit Service 5a9772
	message->NtChallengeResponse.BufferOffset =
Packit Service 5a9772
	    message->LmChallengeResponse.BufferOffset + message->LmChallengeResponse.Len;
Packit Service 5a9772
	message->EncryptedRandomSessionKey.BufferOffset =
Packit Service 5a9772
	    message->NtChallengeResponse.BufferOffset + message->NtChallengeResponse.Len;
Packit Service 5a9772
	ntlm_populate_message_header((NTLM_MESSAGE_HEADER*)message, MESSAGE_TYPE_AUTHENTICATE);
Packit Service 5a9772
	ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*)message); /* Message Header (12 bytes) */
Packit Service 5a9772
	ntlm_write_message_fields(
Packit Service 5a9772
	    s, &(message->LmChallengeResponse)); /* LmChallengeResponseFields (8 bytes) */
Packit Service 5a9772
	ntlm_write_message_fields(
Packit Service 5a9772
	    s, &(message->NtChallengeResponse));               /* NtChallengeResponseFields (8 bytes) */
Packit Service 5a9772
	ntlm_write_message_fields(s, &(message->DomainName));  /* DomainNameFields (8 bytes) */
Packit Service 5a9772
	ntlm_write_message_fields(s, &(message->UserName));    /* UserNameFields (8 bytes) */
Packit 1fb8d4
	ntlm_write_message_fields(s, &(message->Workstation)); /* WorkstationFields (8 bytes) */
Packit Service 5a9772
	ntlm_write_message_fields(
Packit Service 5a9772
	    s, &(message->EncryptedRandomSessionKey));   /* EncryptedRandomSessionKeyFields (8 bytes) */
Packit 1fb8d4
	Stream_Write_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_write_version_info(s, &(message->Version)); /* Version (8 bytes) */
Packit 1fb8d4
Packit 1fb8d4
	if (context->UseMIC)
Packit 1fb8d4
	{
Packit Service 5a9772
		context->MessageIntegrityCheckOffset = (UINT32)Stream_GetPosition(s);
Packit 1fb8d4
		Stream_Zero(s, 16); /* Message Integrity Check (16 bytes) */
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED)
Packit 1fb8d4
		ntlm_write_message_fields_buffer(s, &(message->DomainName)); /* DomainName */
Packit 1fb8d4
Packit 1fb8d4
	ntlm_write_message_fields_buffer(s, &(message->UserName)); /* UserName */
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED)
Packit 1fb8d4
		ntlm_write_message_fields_buffer(s, &(message->Workstation)); /* Workstation */
Packit 1fb8d4
Packit 1fb8d4
	ntlm_write_message_fields_buffer(s, &(message->LmChallengeResponse)); /* LmChallengeResponse */
Packit 1fb8d4
	ntlm_write_message_fields_buffer(s, &(message->NtChallengeResponse)); /* NtChallengeResponse */
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
Packit Service 5a9772
		ntlm_write_message_fields_buffer(
Packit Service 5a9772
		    s, &(message->EncryptedRandomSessionKey)); /* EncryptedRandomSessionKey */
Packit 1fb8d4
Packit 1fb8d4
	length = Stream_GetPosition(s);
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, length))
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Free(s, FALSE);
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length);
Packit 1fb8d4
	buffer->cbBuffer = length;
Packit 1fb8d4
Packit 1fb8d4
	if (context->UseMIC)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* Message Integrity Check */
Packit 1fb8d4
		ntlm_compute_message_integrity_check(context, message->MessageIntegrityCheck, 16);
Packit 1fb8d4
		Stream_SetPosition(s, context->MessageIntegrityCheckOffset);
Packit 1fb8d4
		Stream_Write(s, message->MessageIntegrityCheck, 16);
Packit 1fb8d4
		Stream_SetPosition(s, length);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
	WLog_DBG(TAG, "AUTHENTICATE_MESSAGE (length = %d)", length);
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), length);
Packit 1fb8d4
	ntlm_print_negotiate_flags(message->NegotiateFlags);
Packit 1fb8d4
Packit 1fb8d4
	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
Packit 1fb8d4
		ntlm_print_version_info(&(message->Version));
Packit 1fb8d4
Packit 1fb8d4
	if (context->AuthenticateTargetInfo.cbBuffer > 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_DBG(TAG,
Packit Service 5a9772
		         "AuthenticateTargetInfo (%" PRIu32 "):", context->AuthenticateTargetInfo.cbBuffer);
Packit Service 5a9772
		ntlm_print_av_pair_list(context->AuthenticateTargetInfo.pvBuffer,
Packit Service 5a9772
		                        context->AuthenticateTargetInfo.cbBuffer);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ntlm_print_message_fields(&(message->DomainName), "DomainName");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->UserName), "UserName");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->Workstation), "Workstation");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->LmChallengeResponse), "LmChallengeResponse");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->NtChallengeResponse), "NtChallengeResponse");
Packit 1fb8d4
	ntlm_print_message_fields(&(message->EncryptedRandomSessionKey), "EncryptedRandomSessionKey");
Packit 1fb8d4
Packit 1fb8d4
	if (context->UseMIC)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_DBG(TAG, "MessageIntegrityCheck (length = 16)");
Packit 1fb8d4
		winpr_HexDump(TAG, WLOG_DEBUG, message->MessageIntegrityCheck, 16);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	context->state = NTLM_STATE_FINAL;
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit 1fb8d4
	return SEC_I_COMPLETE_NEEDED;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
SECURITY_STATUS ntlm_server_AuthenticateComplete(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 flags = 0;
Packit 1fb8d4
	size_t cbAvFlags;
Packit 1fb8d4
	NTLM_AV_PAIR* AvFlags = NULL;
Packit 1fb8d4
	NTLM_AUTHENTICATE_MESSAGE* message;
Packit 1fb8d4
	BYTE messageIntegrityCheck[16];
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return SEC_E_INVALID_PARAMETER;
Packit 1fb8d4
Packit 1fb8d4
	if (context->state != NTLM_STATE_COMPLETION)
Packit 1fb8d4
		return SEC_E_OUT_OF_SEQUENCE;
Packit 1fb8d4
Packit 1fb8d4
	message = &context->AUTHENTICATE_MESSAGE;
Packit 1fb8d4
	AvFlags = ntlm_av_pair_get(context->NTLMv2Response.Challenge.AvPairs,
Packit Service 5a9772
	                           context->NTLMv2Response.Challenge.cbAvPairs, MsvAvFlags, &cbAvFlags);
Packit 1fb8d4
Packit 1fb8d4
	if (AvFlags)
Packit Service 5a9772
		Data_Read_UINT32(ntlm_av_pair_get_value_pointer(AvFlags), flags);
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_compute_ntlm_v2_response(context) < 0) /* NtChallengeResponse */
Packit 1fb8d4
		return SEC_E_INTERNAL_ERROR;
Packit 1fb8d4
Packit 1fb8d4
	/* KeyExchangeKey */
Packit 1fb8d4
	ntlm_generate_key_exchange_key(context);
Packit 1fb8d4
	/* EncryptedRandomSessionKey */
Packit 1fb8d4
	ntlm_decrypt_random_session_key(context);
Packit 1fb8d4
	/* ExportedSessionKey */
Packit 1fb8d4
	ntlm_generate_exported_session_key(context);
Packit 1fb8d4
Packit 1fb8d4
	if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
Packit 1fb8d4
	{
Packit Service 5a9772
		ZeroMemory(
Packit Service 5a9772
		    &((PBYTE)context->AuthenticateMessage.pvBuffer)[context->MessageIntegrityCheckOffset],
Packit Service 5a9772
		    16);
Packit Service 5a9772
		ntlm_compute_message_integrity_check(context, messageIntegrityCheck,
Packit Service 5a9772
		                                     sizeof(messageIntegrityCheck));
Packit Service 5a9772
		CopyMemory(
Packit Service 5a9772
		    &((PBYTE)context->AuthenticateMessage.pvBuffer)[context->MessageIntegrityCheckOffset],
Packit Service 5a9772
		    message->MessageIntegrityCheck, 16);
Packit 1fb8d4
Packit 1fb8d4
		if (memcmp(messageIntegrityCheck, message->MessageIntegrityCheck, 16) != 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "Message Integrity Check (MIC) verification failed!");
Packit Service 5a9772
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
			WLog_ERR(TAG, "Expected MIC:");
Packit Service 5a9772
			winpr_HexDump(TAG, WLOG_ERROR, messageIntegrityCheck, sizeof(messageIntegrityCheck));
Packit 1fb8d4
			WLog_ERR(TAG, "Actual MIC:");
Packit Service 5a9772
			winpr_HexDump(TAG, WLOG_ERROR, message->MessageIntegrityCheck,
Packit Service 5a9772
			              sizeof(message->MessageIntegrityCheck));
Packit Service 5a9772
#endif
Packit 1fb8d4
			return SEC_E_MESSAGE_ALTERED;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit Service 5a9772
		/* no mic message was present
Packit Service 5a9772
Packit Service 5a9772
		   https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/f9e6fbc4-a953-4f24-b229-ccdcc213b9ec
Packit Service 5a9772
		   the mic is optional, as not supported in Windows NT, Windows 2000, Windows XP, and
Packit Service 5a9772
		   Windows Server 2003 and, as it seems, in the NTLMv2 implementation of Qt5.
Packit Service 5a9772
Packit Service 5a9772
		   now check the NtProofString, to detect if the entered client password matches the
Packit Service 5a9772
		   expected password.
Packit Service 5a9772
		   */
Packit Service 5a9772
Packit Service 5a9772
#ifdef WITH_DEBUG_NTLM
Packit Service 5a9772
		WLog_DBG(TAG, "No MIC present, using NtProofString for verification.");
Packit Service 5a9772
#endif
Packit Service 5a9772
Packit Service 5a9772
		if (memcmp(context->NTLMv2Response.Response, context->NtProofString, 16) != 0)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG, "NtProofString verification failed!");
Packit Service 5a9772
#ifdef WITH_DEBUG_NTLM
Packit Service 5a9772
			WLog_ERR(TAG, "Expected NtProofString:");
Packit Service 5a9772
			winpr_HexDump(TAG, WLOG_ERROR, context->NtProofString, sizeof(context->NtProofString));
Packit Service 5a9772
			WLog_ERR(TAG, "Actual NtProofString:");
Packit Service 5a9772
			winpr_HexDump(TAG, WLOG_ERROR, context->NTLMv2Response.Response,
Packit Service 5a9772
			              sizeof(context->NTLMv2Response));
Packit Service 5a9772
#endif
Packit Service 5a9772
			return SEC_E_LOGON_DENIED;
Packit Service 5a9772
		}
Packit Service 5a9772
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Generate signing keys */
Packit 1fb8d4
	ntlm_generate_client_signing_key(context);
Packit 1fb8d4
	ntlm_generate_server_signing_key(context);
Packit 1fb8d4
	/* Generate sealing keys */
Packit 1fb8d4
	ntlm_generate_client_sealing_key(context);
Packit 1fb8d4
	ntlm_generate_server_sealing_key(context);
Packit 1fb8d4
	/* Initialize RC4 seal state */
Packit 1fb8d4
	ntlm_init_rc4_seal_states(context);
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
	WLog_DBG(TAG, "ClientChallenge");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ClientChallenge, 8);
Packit 1fb8d4
	WLog_DBG(TAG, "ServerChallenge");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ServerChallenge, 8);
Packit 1fb8d4
	WLog_DBG(TAG, "SessionBaseKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->SessionBaseKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "KeyExchangeKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->KeyExchangeKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ExportedSessionKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ExportedSessionKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "RandomSessionKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->RandomSessionKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ClientSigningKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ClientSigningKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ClientSealingKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ClientSealingKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ServerSigningKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ServerSigningKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "ServerSealingKey");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->ServerSealingKey, 16);
Packit 1fb8d4
	WLog_DBG(TAG, "Timestamp");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->Timestamp, 8);
Packit 1fb8d4
#endif
Packit 1fb8d4
	context->state = NTLM_STATE_FINAL;
Packit 1fb8d4
	ntlm_free_message_fields_buffer(&(message->DomainName));
Packit 1fb8d4
	ntlm_free_message_fields_buffer(&(message->UserName));
Packit 1fb8d4
	ntlm_free_message_fields_buffer(&(message->Workstation));
Packit 1fb8d4
	ntlm_free_message_fields_buffer(&(message->LmChallengeResponse));
Packit 1fb8d4
	ntlm_free_message_fields_buffer(&(message->NtChallengeResponse));
Packit 1fb8d4
	ntlm_free_message_fields_buffer(&(message->EncryptedRandomSessionKey));
Packit 1fb8d4
	return SEC_E_OK;
Packit 1fb8d4
}