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

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