Blame libfreerdp/core/rdp.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * RDP Core
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 * Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.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 <winpr/crt.h>
Packit Service fa4841
Packit Service fa4841
#include "rdp.h"
Packit Service fa4841
Packit Service fa4841
#include "info.h"
Packit Service fa4841
#include "redirection.h"
Packit Service fa4841
Packit Service fa4841
#include <freerdp/crypto/per.h>
Packit Service fa4841
#include <freerdp/log.h>
Packit Service fa4841
Packit Service fa4841
#define TAG FREERDP_TAG("core.rdp")
Packit Service fa4841
Packit Service fa4841
const char* DATA_PDU_TYPE_STRINGS[80] = {
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",      /* 0x00 - 0x01 */
Packit Service fa4841
	"Update", /* 0x02 */
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?", /* 0x03 - 0x0A */
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",       /* 0x0B - 0x13 */
Packit Service fa4841
	"Control", /* 0x14 */
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",       /* 0x15 - 0x1A */
Packit Service fa4841
	"Pointer", /* 0x1B */
Packit Service fa4841
	"Input",   /* 0x1C */
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",                            /* 0x1D - 0x1E */
Packit Service fa4841
	"Synchronize",                  /* 0x1F */
Packit Service fa4841
	"?",                            /* 0x20 */
Packit Service fa4841
	"Refresh Rect",                 /* 0x21 */
Packit Service fa4841
	"Play Sound",                   /* 0x22 */
Packit Service fa4841
	"Suppress Output",              /* 0x23 */
Packit Service fa4841
	"Shutdown Request",             /* 0x24 */
Packit Service fa4841
	"Shutdown Denied",              /* 0x25 */
Packit Service fa4841
	"Save Session Info",            /* 0x26 */
Packit Service fa4841
	"Font List",                    /* 0x27 */
Packit Service fa4841
	"Font Map",                     /* 0x28 */
Packit Service fa4841
	"Set Keyboard Indicators",      /* 0x29 */
Packit Service fa4841
	"?",                            /* 0x2A */
Packit Service fa4841
	"Bitmap Cache Persistent List", /* 0x2B */
Packit Service fa4841
	"Bitmap Cache Error",           /* 0x2C */
Packit Service fa4841
	"Set Keyboard IME Status",      /* 0x2D */
Packit Service fa4841
	"Offscreen Cache Error",        /* 0x2E */
Packit Service fa4841
	"Set Error Info",               /* 0x2F */
Packit Service fa4841
	"Draw Nine Grid Error",         /* 0x30 */
Packit Service fa4841
	"Draw GDI+ Error",              /* 0x31 */
Packit Service fa4841
	"ARC Status",                   /* 0x32 */
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",              /* 0x33 - 0x35 */
Packit Service fa4841
	"Status Info",    /* 0x36 */
Packit Service fa4841
	"Monitor Layout", /* 0x37 */
Packit Service fa4841
	"FrameAcknowledge",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?", /* 0x38 - 0x40 */
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?",
Packit Service fa4841
	"?" /* 0x41 - 0x46 */
Packit Service fa4841
};
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_read_flow_control_pdu(wStream* s, UINT16* type, UINT16* channel_id);
Packit Service fa4841
static void rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type,
Packit Service fa4841
                                           UINT16 channel_id);
Packit Service fa4841
static void rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id);
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Read RDP Security Header.\n
Packit Service fa4841
 * @msdn{cc240579}
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param flags security flags
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL rdp_read_security_header(wStream* s, UINT16* flags, UINT16* length)
Packit Service fa4841
{
Packit Service fa4841
	/* Basic Security Header */
Packit Service fa4841
	if ((Stream_GetRemainingLength(s) < 4) || (length && (*length < 4)))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT16(s, *flags); /* flags */
Packit Service fa4841
	Stream_Seek(s, 2);             /* flagsHi (unused) */
Packit Service fa4841
Packit Service fa4841
	if (length)
Packit Service fa4841
		*length -= 4;
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Write RDP Security Header.\n
Packit Service fa4841
 * @msdn{cc240579}
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param flags security flags
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void rdp_write_security_header(wStream* s, UINT16 flags)
Packit Service fa4841
{
Packit Service fa4841
	/* Basic Security Header */
Packit Service fa4841
	Stream_Write_UINT16(s, flags); /* flags */
Packit Service fa4841
	Stream_Write_UINT16(s, 0);     /* flagsHi (unused) */
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL rdp_read_share_control_header(wStream* s, UINT16* tpktLength, UINT16* remainingLength,
Packit Service fa4841
                                   UINT16* type, UINT16* channel_id)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 len;
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 2)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/* Share Control Header */
Packit Service fa4841
	Stream_Read_UINT16(s, len); /* totalLength */
Packit Service fa4841
Packit Service fa4841
	/* If length is 0x8000 then we actually got a flow control PDU that we should ignore
Packit Service fa4841
	 http://msdn.microsoft.com/en-us/library/cc240576.aspx */
Packit Service fa4841
	if (len == 0x8000)
Packit Service fa4841
	{
Packit Service fa4841
		if (!rdp_read_flow_control_pdu(s, type, channel_id))
Packit Service fa4841
			return FALSE;
Packit Service fa4841
		*channel_id = 0;
Packit Service fa4841
		if (tpktLength)
Packit Service fa4841
			*tpktLength = 8; /* Flow control PDU is 8 bytes */
Packit Service fa4841
		if (remainingLength)
Packit Service fa4841
			*remainingLength = 0;
Packit Service fa4841
		return TRUE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if ((len < 4U) || ((len - 2U) > Stream_GetRemainingLength(s)))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (tpktLength)
Packit Service fa4841
		*tpktLength = len;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT16(s, *type); /* pduType */
Packit Service fa4841
	*type &= 0x0F;                /* type is in the 4 least significant bits */
Packit Service fa4841
Packit Service fa4841
	if (len > 5)
Packit Service fa4841
	{
Packit Service fa4841
		Stream_Read_UINT16(s, *channel_id); /* pduSource */
Packit Service fa4841
		if (remainingLength)
Packit Service fa4841
			*remainingLength = len - 6;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		*channel_id = 0; /* Windows XP can send such short DEACTIVATE_ALL PDUs. */
Packit Service fa4841
		if (remainingLength)
Packit Service fa4841
			*remainingLength = len - 4;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, UINT16 channel_id)
Packit Service fa4841
{
Packit Service fa4841
	length -= RDP_PACKET_HEADER_MAX_LENGTH;
Packit Service fa4841
	/* Share Control Header */
Packit Service fa4841
	Stream_Write_UINT16(s, length);      /* totalLength */
Packit Service fa4841
	Stream_Write_UINT16(s, type | 0x10); /* pduType */
Packit Service fa4841
	Stream_Write_UINT16(s, channel_id);  /* pduSource */
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* shareId,
Packit Service fa4841
                                BYTE* compressedType, UINT16* compressedLength)
Packit Service fa4841
{
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 12)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/* Share Data Header */
Packit Service fa4841
	Stream_Read_UINT32(s, *shareId);          /* shareId (4 bytes) */
Packit Service fa4841
	Stream_Seek_UINT8(s);                     /* pad1 (1 byte) */
Packit Service fa4841
	Stream_Seek_UINT8(s);                     /* streamId (1 byte) */
Packit Service fa4841
	Stream_Read_UINT16(s, *length);           /* uncompressedLength (2 bytes) */
Packit Service fa4841
	Stream_Read_UINT8(s, *type);              /* pduType2, Data PDU Type (1 byte) */
Packit Service fa4841
	Stream_Read_UINT8(s, *compressedType);    /* compressedType (1 byte) */
Packit Service fa4841
	Stream_Read_UINT16(s, *compressedLength); /* compressedLength (2 bytes) */
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id)
Packit Service fa4841
{
Packit Service fa4841
	length -= RDP_PACKET_HEADER_MAX_LENGTH;
Packit Service fa4841
	length -= RDP_SHARE_CONTROL_HEADER_LENGTH;
Packit Service fa4841
	length -= RDP_SHARE_DATA_HEADER_LENGTH;
Packit Service fa4841
	/* Share Data Header */
Packit Service fa4841
	Stream_Write_UINT32(s, share_id);  /* shareId (4 bytes) */
Packit Service fa4841
	Stream_Write_UINT8(s, 0);          /* pad1 (1 byte) */
Packit Service fa4841
	Stream_Write_UINT8(s, STREAM_LOW); /* streamId (1 byte) */
Packit Service fa4841
	Stream_Write_UINT16(s, length);    /* uncompressedLength (2 bytes) */
Packit Service fa4841
	Stream_Write_UINT8(s, type);       /* pduType2, Data PDU Type (1 byte) */
Packit Service fa4841
	Stream_Write_UINT8(s, 0);          /* compressedType (1 byte) */
Packit Service fa4841
	Stream_Write_UINT16(s, 0);         /* compressedLength (2 bytes) */
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header)
Packit Service fa4841
{
Packit Service fa4841
	if (!rdp || !s)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (rdp->do_crypt)
Packit Service fa4841
	{
Packit Service fa4841
		if (!Stream_SafeSeek(s, 12))
Packit Service fa4841
			return FALSE;
Packit Service fa4841
Packit Service fa4841
		if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
Packit Service fa4841
		{
Packit Service fa4841
			if (!Stream_SafeSeek(s, 4))
Packit Service fa4841
				return FALSE;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		rdp->sec_flags |= SEC_ENCRYPT;
Packit Service fa4841
Packit Service fa4841
		if (rdp->do_secure_checksum)
Packit Service fa4841
			rdp->sec_flags |= SEC_SECURE_CHECKSUM;
Packit Service fa4841
	}
Packit Service fa4841
	else if (rdp->sec_flags != 0 || sec_header)
Packit Service fa4841
	{
Packit Service fa4841
		if (!Stream_SafeSeek(s, 4))
Packit Service fa4841
			return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
wStream* rdp_send_stream_init(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s = transport_send_stream_init(rdp->transport, 4096);
Packit Service fa4841
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	if (!Stream_SafeSeek(s, RDP_PACKET_HEADER_MAX_LENGTH))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	if (!rdp_security_stream_init(rdp, s, FALSE))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	return s;
Packit Service fa4841
fail:
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return NULL;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
wStream* rdp_send_stream_pdu_init(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s = rdp_send_stream_init(rdp);
Packit Service fa4841
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	if (!Stream_SafeSeek(s, RDP_SHARE_CONTROL_HEADER_LENGTH))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	return s;
Packit Service fa4841
fail:
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return NULL;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
wStream* rdp_data_pdu_init(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s = rdp_send_stream_pdu_init(rdp);
Packit Service fa4841
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	if (!Stream_SafeSeek(s, RDP_SHARE_DATA_HEADER_LENGTH))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	return s;
Packit Service fa4841
fail:
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return NULL;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo)
Packit Service fa4841
{
Packit Service fa4841
	rdp->errorInfo = errorInfo;
Packit Service fa4841
Packit Service fa4841
	if (rdp->errorInfo != ERRINFO_SUCCESS)
Packit Service fa4841
	{
Packit Service fa4841
		rdpContext* context = rdp->context;
Packit Service fa4841
		rdp_print_errinfo(rdp->errorInfo);
Packit Service fa4841
Packit Service fa4841
		if (context)
Packit Service fa4841
		{
Packit Service fa4841
			freerdp_set_last_error_log(context, MAKE_FREERDP_ERROR(ERRINFO, errorInfo));
Packit Service fa4841
Packit Service fa4841
			if (context->pubSub)
Packit Service fa4841
			{
Packit Service fa4841
				ErrorInfoEventArgs e;
Packit Service fa4841
				EventArgsInit(&e, "freerdp");
Packit Service fa4841
				e.code = rdp->errorInfo;
Packit Service fa4841
				PubSub_OnErrorInfo(context->pubSub, context, &e);
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
			WLog_ERR(TAG, "%s missing context=%p", __FUNCTION__, context);
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		freerdp_set_last_error_log(rdp->context, FREERDP_ERROR_SUCCESS);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
wStream* rdp_message_channel_pdu_init(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s = transport_send_stream_init(rdp->transport, 4096);
Packit Service fa4841
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	if (!Stream_SafeSeek(s, RDP_PACKET_HEADER_MAX_LENGTH))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	if (!rdp_security_stream_init(rdp, s, TRUE))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	return s;
Packit Service fa4841
fail:
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return NULL;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Read an RDP packet header.\n
Packit Service fa4841
 * @param rdp rdp module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param length RDP packet length
Packit Service fa4841
 * @param channel_id channel id
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
Packit Service fa4841
{
Packit Service fa4841
	BYTE li;
Packit Service fa4841
	BYTE byte;
Packit Service fa4841
	BYTE code;
Packit Service fa4841
	BYTE choice;
Packit Service fa4841
	UINT16 initiator;
Packit Service fa4841
	enum DomainMCSPDU MCSPDU;
Packit Service fa4841
	enum DomainMCSPDU domainMCSPDU;
Packit Service fa4841
	MCSPDU = (rdp->settings->ServerMode) ? DomainMCSPDU_SendDataRequest
Packit Service fa4841
	                                     : DomainMCSPDU_SendDataIndication;
Packit Service fa4841
Packit Service fa4841
	*channelId = 0; /* Initialize in case of early abort */
Packit Service fa4841
	if (!tpkt_read_header(s, length))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!tpdu_read_header(s, &code, &li, *length))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (code != X224_TPDU_DATA)
Packit Service fa4841
	{
Packit Service fa4841
		if (code == X224_TPDU_DISCONNECT_REQUEST)
Packit Service fa4841
		{
Packit Service fa4841
			freerdp_abort_connect(rdp->instance);
Packit Service fa4841
			return TRUE;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!per_read_choice(s, &choice))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	domainMCSPDU = (enum DomainMCSPDU)(choice >> 2);
Packit Service fa4841
Packit Service fa4841
	if (domainMCSPDU != MCSPDU)
Packit Service fa4841
	{
Packit Service fa4841
		if (domainMCSPDU != DomainMCSPDU_DisconnectProviderUltimatum)
Packit Service fa4841
			return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	MCSPDU = domainMCSPDU;
Packit Service fa4841
Packit Service fa4841
	if (*length < 8U)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if ((*length - 8U) > Stream_GetRemainingLength(s))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum)
Packit Service fa4841
	{
Packit Service fa4841
		int reason = 0;
Packit Service fa4841
		TerminateEventArgs e;
Packit Service fa4841
		rdpContext* context;
Packit Service fa4841
Packit Service fa4841
		if (!mcs_recv_disconnect_provider_ultimatum(rdp->mcs, s, &reason))
Packit Service fa4841
			return FALSE;
Packit Service fa4841
Packit Service fa4841
		if (!rdp->instance)
Packit Service fa4841
			return FALSE;
Packit Service fa4841
Packit Service fa4841
		context = rdp->instance->context;
Packit Service fa4841
		context->disconnectUltimatum = reason;
Packit Service fa4841
Packit Service fa4841
		if (rdp->errorInfo == ERRINFO_SUCCESS)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * Some servers like Windows Server 2008 R2 do not send the error info pdu
Packit Service fa4841
			 * when the user logs off like they should. Map DisconnectProviderUltimatum
Packit Service fa4841
			 * to a ERRINFO_LOGOFF_BY_USER when the errinfo code is ERRINFO_SUCCESS.
Packit Service fa4841
			 */
Packit Service fa4841
			if (reason == Disconnect_Ultimatum_provider_initiated)
Packit Service fa4841
				rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
Packit Service fa4841
			else if (reason == Disconnect_Ultimatum_user_requested)
Packit Service fa4841
				rdp_set_error_info(rdp, ERRINFO_LOGOFF_BY_USER);
Packit Service fa4841
			else
Packit Service fa4841
				rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		WLog_DBG(TAG, "DisconnectProviderUltimatum: reason: %d", reason);
Packit Service fa4841
		freerdp_abort_connect(rdp->instance);
Packit Service fa4841
		EventArgsInit(&e, "freerdp");
Packit Service fa4841
		e.code = 0;
Packit Service fa4841
		PubSub_OnTerminate(context->pubSub, context, &e);
Packit Service fa4841
		return TRUE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 5)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!per_read_integer16(s, channelId, 0)) /* channelId */
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT8(s, byte); /* dataPriority + Segmentation (0x70) */
Packit Service fa4841
Packit Service fa4841
	if (!per_read_length(s, length)) /* userData (OCTET_STRING) */
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (*length > Stream_GetRemainingLength(s))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Write an RDP packet header.\n
Packit Service fa4841
 * @param rdp rdp module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param length RDP packet length
Packit Service fa4841
 * @param channel_id channel id
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void rdp_write_header(rdpRdp* rdp, wStream* s, UINT16 length, UINT16 channelId)
Packit Service fa4841
{
Packit Service fa4841
	int body_length;
Packit Service fa4841
	enum DomainMCSPDU MCSPDU;
Packit Service fa4841
	MCSPDU = (rdp->settings->ServerMode) ? DomainMCSPDU_SendDataIndication
Packit Service fa4841
	                                     : DomainMCSPDU_SendDataRequest;
Packit Service fa4841
Packit Service fa4841
	if ((rdp->sec_flags & SEC_ENCRYPT) &&
Packit Service fa4841
	    (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS))
Packit Service fa4841
	{
Packit Service fa4841
		int pad;
Packit Service fa4841
		body_length = length - RDP_PACKET_HEADER_MAX_LENGTH - 16;
Packit Service fa4841
		pad = 8 - (body_length % 8);
Packit Service fa4841
Packit Service fa4841
		if (pad != 8)
Packit Service fa4841
			length += pad;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	mcs_write_domain_mcspdu_header(s, MCSPDU, length, 0);
Packit Service fa4841
	per_write_integer16(s, rdp->mcs->userId, MCS_BASE_CHANNEL_ID); /* initiator */
Packit Service fa4841
	per_write_integer16(s, channelId, 0);                          /* channelId */
Packit Service fa4841
	Stream_Write_UINT8(s, 0x70);                                   /* dataPriority + segmentation */
Packit Service fa4841
	/*
Packit Service fa4841
	 * We always encode length in two bytes, even though we could use
Packit Service fa4841
	 * only one byte if length <= 0x7F. It is just easier that way,
Packit Service fa4841
	 * because we can leave room for fixed-length header, store all
Packit Service fa4841
	 * the data first and then store the header.
Packit Service fa4841
	 */
Packit Service fa4841
	length = (length - RDP_PACKET_HEADER_MAX_LENGTH) | 0x8000;
Packit Service fa4841
	Stream_Write_UINT16_BE(s, length); /* userData (OCTET_STRING) */
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_security_stream_out(rdpRdp* rdp, wStream* s, int length, UINT32 sec_flags,
Packit Service fa4841
                                    UINT32* pad)
Packit Service fa4841
{
Packit Service fa4841
	BYTE* data;
Packit Service fa4841
	BOOL status;
Packit Service fa4841
	sec_flags |= rdp->sec_flags;
Packit Service fa4841
	*pad = 0;
Packit Service fa4841
Packit Service fa4841
	if (sec_flags != 0)
Packit Service fa4841
	{
Packit Service fa4841
		rdp_write_security_header(s, sec_flags);
Packit Service fa4841
Packit Service fa4841
		if (sec_flags & SEC_ENCRYPT)
Packit Service fa4841
		{
Packit Service fa4841
			if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
Packit Service fa4841
			{
Packit Service fa4841
				data = Stream_Pointer(s) + 12;
Packit Service fa4841
				length = length - (data - Stream_Buffer(s));
Packit Service fa4841
				Stream_Write_UINT16(s, 0x10); /* length */
Packit Service fa4841
				Stream_Write_UINT8(s, 0x1);   /* TSFIPS_VERSION 1*/
Packit Service fa4841
				/* handle padding */
Packit Service fa4841
				*pad = 8 - (length % 8);
Packit Service fa4841
Packit Service fa4841
				if (*pad == 8)
Packit Service fa4841
					*pad = 0;
Packit Service fa4841
Packit Service fa4841
				if (*pad)
Packit Service fa4841
					memset(data + length, 0, *pad);
Packit Service fa4841
Packit Service fa4841
				Stream_Write_UINT8(s, *pad);
Packit Service fa4841
Packit Service fa4841
				if (!security_hmac_signature(data, length, Stream_Pointer(s), rdp))
Packit Service fa4841
					return FALSE;
Packit Service fa4841
Packit Service fa4841
				Stream_Seek(s, 8);
Packit Service fa4841
				security_fips_encrypt(data, length + *pad, rdp);
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				data = Stream_Pointer(s) + 8;
Packit Service fa4841
				length = length - (data - Stream_Buffer(s));
Packit Service fa4841
Packit Service fa4841
				if (sec_flags & SEC_SECURE_CHECKSUM)
Packit Service fa4841
					status =
Packit Service fa4841
					    security_salted_mac_signature(rdp, data, length, TRUE, Stream_Pointer(s));
Packit Service fa4841
				else
Packit Service fa4841
					status = security_mac_signature(rdp, data, length, Stream_Pointer(s));
Packit Service fa4841
Packit Service fa4841
				if (!status)
Packit Service fa4841
					return FALSE;
Packit Service fa4841
Packit Service fa4841
				Stream_Seek(s, 8);
Packit Service fa4841
Packit Service fa4841
				if (!security_encrypt(Stream_Pointer(s), length, rdp))
Packit Service fa4841
					return FALSE;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		rdp->sec_flags = 0;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static UINT32 rdp_get_sec_bytes(rdpRdp* rdp, UINT16 sec_flags)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 sec_bytes;
Packit Service fa4841
Packit Service fa4841
	if (rdp->sec_flags & SEC_ENCRYPT)
Packit Service fa4841
	{
Packit Service fa4841
		sec_bytes = 12;
Packit Service fa4841
Packit Service fa4841
		if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
Packit Service fa4841
			sec_bytes += 4;
Packit Service fa4841
	}
Packit Service fa4841
	else if (rdp->sec_flags != 0 || sec_flags != 0)
Packit Service fa4841
	{
Packit Service fa4841
		sec_bytes = 4;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		sec_bytes = 0;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return sec_bytes;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Send an RDP packet.
Packit Service fa4841
 * @param rdp RDP module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param channel_id channel id
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id)
Packit Service fa4841
{
Packit Service fa4841
	BOOL rc = FALSE;
Packit Service fa4841
	UINT32 pad;
Packit Service fa4841
	UINT16 length;
Packit Service fa4841
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!rdp)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	length = Stream_GetPosition(s);
Packit Service fa4841
	Stream_SetPosition(s, 0);
Packit Service fa4841
	rdp_write_header(rdp, s, length, channel_id);
Packit Service fa4841
Packit Service fa4841
	if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	length += pad;
Packit Service fa4841
	Stream_SetPosition(s, length);
Packit Service fa4841
	Stream_SealLength(s);
Packit Service fa4841
Packit Service fa4841
	if (transport_write(rdp->transport, s) < 0)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rc = TRUE;
Packit Service fa4841
fail:
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return rc;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 length;
Packit Service fa4841
	UINT32 sec_bytes;
Packit Service fa4841
	size_t sec_hold;
Packit Service fa4841
	UINT32 pad;
Packit Service fa4841
Packit Service fa4841
	if (!rdp || !s)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	length = Stream_GetPosition(s);
Packit Service fa4841
	Stream_SetPosition(s, 0);
Packit Service fa4841
	rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
Packit Service fa4841
	sec_bytes = rdp_get_sec_bytes(rdp, 0);
Packit Service fa4841
	sec_hold = Stream_GetPosition(s);
Packit Service fa4841
	Stream_Seek(s, sec_bytes);
Packit Service fa4841
	rdp_write_share_control_header(s, length - sec_bytes, type, channel_id);
Packit Service fa4841
	Stream_SetPosition(s, sec_hold);
Packit Service fa4841
Packit Service fa4841
	if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	length += pad;
Packit Service fa4841
	Stream_SetPosition(s, length);
Packit Service fa4841
	Stream_SealLength(s);
Packit Service fa4841
Packit Service fa4841
	if (transport_write(rdp->transport, s) < 0)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
Packit Service fa4841
{
Packit Service fa4841
	BOOL rc = FALSE;
Packit Service fa4841
	size_t length;
Packit Service fa4841
	UINT32 sec_bytes;
Packit Service fa4841
	size_t sec_hold;
Packit Service fa4841
	UINT32 pad;
Packit Service fa4841
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!rdp)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	length = Stream_GetPosition(s);
Packit Service fa4841
	Stream_SetPosition(s, 0);
Packit Service fa4841
	rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
Packit Service fa4841
	sec_bytes = rdp_get_sec_bytes(rdp, 0);
Packit Service fa4841
	sec_hold = Stream_GetPosition(s);
Packit Service fa4841
	Stream_Seek(s, sec_bytes);
Packit Service fa4841
	rdp_write_share_control_header(s, length - sec_bytes, PDU_TYPE_DATA, channel_id);
Packit Service fa4841
	rdp_write_share_data_header(s, length - sec_bytes, type, rdp->settings->ShareId);
Packit Service fa4841
	Stream_SetPosition(s, sec_hold);
Packit Service fa4841
Packit Service fa4841
	if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	length += pad;
Packit Service fa4841
	Stream_SetPosition(s, length);
Packit Service fa4841
	Stream_SealLength(s);
Packit Service fa4841
	WLog_DBG(TAG, "%s: sending data (type=0x%x size=%" PRIuz " channelId=%" PRIu16 ")",
Packit Service fa4841
	         __FUNCTION__, type, Stream_Length(s), channel_id);
Packit Service fa4841
Packit Service fa4841
	rdp->outPackets++;
Packit Service fa4841
	if (transport_write(rdp->transport, s) < 0)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rc = TRUE;
Packit Service fa4841
fail:
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return rc;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags)
Packit Service fa4841
{
Packit Service fa4841
	BOOL rc = FALSE;
Packit Service fa4841
	UINT16 length;
Packit Service fa4841
	UINT32 pad;
Packit Service fa4841
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!rdp)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	length = Stream_GetPosition(s);
Packit Service fa4841
	Stream_SetPosition(s, 0);
Packit Service fa4841
	rdp_write_header(rdp, s, length, rdp->mcs->messageChannelId);
Packit Service fa4841
Packit Service fa4841
	if (!rdp_security_stream_out(rdp, s, length, sec_flags, &pad))
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	length += pad;
Packit Service fa4841
	Stream_SetPosition(s, length);
Packit Service fa4841
	Stream_SealLength(s);
Packit Service fa4841
Packit Service fa4841
	if (transport_write(rdp->transport, s) < 0)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rc = TRUE;
Packit Service fa4841
fail:
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return rc;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_recv_server_shutdown_denied_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_recv_server_set_keyboard_indicators_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 unitId;
Packit Service fa4841
	UINT16 ledFlags;
Packit Service fa4841
	rdpContext* context = rdp->instance->context;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT16(s, unitId);   /* unitId (2 bytes) */
Packit Service fa4841
	Stream_Read_UINT16(s, ledFlags); /* ledFlags (2 bytes) */
Packit Service fa4841
	IFCALL(context->update->SetKeyboardIndicators, context, ledFlags);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_recv_server_set_keyboard_ime_status_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 unitId;
Packit Service fa4841
	UINT32 imeState;
Packit Service fa4841
	UINT32 imeConvMode;
Packit Service fa4841
Packit Service fa4841
	if (!rdp || !rdp->input)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 10)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT16(s, unitId);      /* unitId (2 bytes) */
Packit Service fa4841
	Stream_Read_UINT32(s, imeState);    /* imeState (4 bytes) */
Packit Service fa4841
	Stream_Read_UINT32(s, imeConvMode); /* imeConvMode (4 bytes) */
Packit Service fa4841
	IFCALL(rdp->update->SetKeyboardImeStatus, rdp->context, unitId, imeState, imeConvMode);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 errorInfo;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, errorInfo); /* errorInfo (4 bytes) */
Packit Service fa4841
	return rdp_set_error_info(rdp, errorInfo);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_recv_server_auto_reconnect_status_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 arcStatus;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, arcStatus); /* arcStatus (4 bytes) */
Packit Service fa4841
	WLog_WARN(TAG, "AutoReconnectStatus: 0x%08" PRIX32 "", arcStatus);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_recv_server_status_info_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 statusCode;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, statusCode); /* statusCode (4 bytes) */
Packit Service fa4841
Packit Service fa4841
	if (rdp->update->ServerStatusInfo)
Packit Service fa4841
		return rdp->update->ServerStatusInfo(rdp->context, statusCode);
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 index;
Packit Service fa4841
	UINT32 monitorCount;
Packit Service fa4841
	MONITOR_DEF* monitor;
Packit Service fa4841
	MONITOR_DEF* monitorDefArray;
Packit Service fa4841
	BOOL ret = TRUE;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, monitorCount); /* monitorCount (4 bytes) */
Packit Service fa4841
Packit Service fa4841
	if ((Stream_GetRemainingLength(s) / 20) < monitorCount)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	monitorDefArray = (MONITOR_DEF*)calloc(monitorCount, sizeof(MONITOR_DEF));
Packit Service fa4841
Packit Service fa4841
	if (!monitorDefArray)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	for (monitor = monitorDefArray, index = 0; index < monitorCount; index++, monitor++)
Packit Service fa4841
	{
Packit Service fa4841
		Stream_Read_UINT32(s, monitor->left);   /* left (4 bytes) */
Packit Service fa4841
		Stream_Read_UINT32(s, monitor->top);    /* top (4 bytes) */
Packit Service fa4841
		Stream_Read_UINT32(s, monitor->right);  /* right (4 bytes) */
Packit Service fa4841
		Stream_Read_UINT32(s, monitor->bottom); /* bottom (4 bytes) */
Packit Service fa4841
		Stream_Read_UINT32(s, monitor->flags);  /* flags (4 bytes) */
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	IFCALLRET(rdp->update->RemoteMonitors, ret, rdp->context, monitorCount, monitorDefArray);
Packit Service fa4841
	free(monitorDefArray);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	BYTE type;
Packit Service fa4841
	wStream* cs;
Packit Service fa4841
	UINT16 length;
Packit Service fa4841
	UINT32 shareId;
Packit Service fa4841
	BYTE compressedType;
Packit Service fa4841
	UINT16 compressedLength;
Packit Service fa4841
Packit Service fa4841
	if (!rdp_read_share_data_header(s, &length, &type, &shareId, &compressedType,
Packit Service fa4841
	                                &compressedLength))
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "rdp_read_share_data_header() failed");
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	cs = s;
Packit Service fa4841
Packit Service fa4841
	if (compressedType & PACKET_COMPRESSED)
Packit Service fa4841
	{
Packit Service fa4841
		UINT32 DstSize = 0;
Packit Service fa4841
		BYTE* pDstData = NULL;
Packit Service fa4841
		UINT16 SrcSize = compressedLength - 18;
Packit Service fa4841
Packit Service fa4841
		if ((compressedLength < 18) || (Stream_GetRemainingLength(s) < SrcSize))
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "bulk_decompress: not enough bytes for compressedLength %" PRIu16 "",
Packit Service fa4841
			         compressedLength);
Packit Service fa4841
			return -1;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (bulk_decompress(rdp->bulk, Stream_Pointer(s), SrcSize, &pDstData, &DstSize,
Packit Service fa4841
		                    compressedType))
Packit Service fa4841
		{
Packit Service fa4841
			if (!(cs = StreamPool_Take(rdp->transport->ReceivePool, DstSize)))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "Couldn't take stream from pool");
Packit Service fa4841
				return -1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			Stream_SetPosition(cs, 0);
Packit Service fa4841
			Stream_Write(cs, pDstData, DstSize);
Packit Service fa4841
			Stream_SealLength(cs);
Packit Service fa4841
			Stream_SetPosition(cs, 0);
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "bulk_decompress() failed");
Packit Service fa4841
			return -1;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		Stream_Seek(s, SrcSize);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	WLog_DBG(TAG, "recv %s Data PDU (0x%02" PRIX8 "), length: %" PRIu16 "",
Packit Service fa4841
	         type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type,
Packit Service fa4841
	         length);
Packit Service fa4841
Packit Service fa4841
	switch (type)
Packit Service fa4841
	{
Packit Service fa4841
		case DATA_PDU_TYPE_UPDATE:
Packit Service fa4841
			if (!update_recv(rdp->update, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "DATA_PDU_TYPE_UPDATE - update_recv() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_CONTROL:
Packit Service fa4841
			if (!rdp_recv_server_control_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "DATA_PDU_TYPE_CONTROL - rdp_recv_server_control_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_POINTER:
Packit Service fa4841
			if (!update_recv_pointer(rdp->update, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "DATA_PDU_TYPE_POINTER - update_recv_pointer() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_SYNCHRONIZE:
Packit Service fa4841
			if (!rdp_recv_synchronize_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "DATA_PDU_TYPE_SYNCHRONIZE - rdp_recv_synchronize_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_PLAY_SOUND:
Packit Service fa4841
			if (!update_recv_play_sound(rdp->update, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "DATA_PDU_TYPE_PLAY_SOUND - update_recv_play_sound() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_SHUTDOWN_DENIED:
Packit Service fa4841
			if (!rdp_recv_server_shutdown_denied_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(
Packit Service fa4841
				    TAG,
Packit Service fa4841
				    "DATA_PDU_TYPE_SHUTDOWN_DENIED - rdp_recv_server_shutdown_denied_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_SAVE_SESSION_INFO:
Packit Service fa4841
			if (!rdp_recv_save_session_info(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG,
Packit Service fa4841
				         "DATA_PDU_TYPE_SAVE_SESSION_INFO - rdp_recv_save_session_info() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_FONT_MAP:
Packit Service fa4841
			if (!rdp_recv_font_map_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "DATA_PDU_TYPE_FONT_MAP - rdp_recv_font_map_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS:
Packit Service fa4841
			if (!rdp_recv_server_set_keyboard_indicators_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS - "
Packit Service fa4841
				              "rdp_recv_server_set_keyboard_indicators_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS:
Packit Service fa4841
			if (!rdp_recv_server_set_keyboard_ime_status_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS - "
Packit Service fa4841
				              "rdp_recv_server_set_keyboard_ime_status_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_SET_ERROR_INFO:
Packit Service fa4841
			if (!rdp_recv_set_error_info_data_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(
Packit Service fa4841
				    TAG,
Packit Service fa4841
				    "DATA_PDU_TYPE_SET_ERROR_INFO - rdp_recv_set_error_info_data_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_ARC_STATUS:
Packit Service fa4841
			if (!rdp_recv_server_auto_reconnect_status_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "DATA_PDU_TYPE_ARC_STATUS - "
Packit Service fa4841
				              "rdp_recv_server_auto_reconnect_status_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_STATUS_INFO:
Packit Service fa4841
			if (!rdp_recv_server_status_info_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG,
Packit Service fa4841
				         "DATA_PDU_TYPE_STATUS_INFO - rdp_recv_server_status_info_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case DATA_PDU_TYPE_MONITOR_LAYOUT:
Packit Service fa4841
			if (!rdp_recv_monitor_layout_pdu(rdp, cs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG,
Packit Service fa4841
				         "DATA_PDU_TYPE_MONITOR_LAYOUT - rdp_recv_monitor_layout_pdu() failed");
Packit Service fa4841
				goto out_fail;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (cs != s)
Packit Service fa4841
		Stream_Release(cs);
Packit Service fa4841
Packit Service fa4841
	return 0;
Packit Service fa4841
out_fail:
Packit Service fa4841
Packit Service fa4841
	if (cs != s)
Packit Service fa4841
		Stream_Release(cs);
Packit Service fa4841
Packit Service fa4841
	return -1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 securityFlags)
Packit Service fa4841
{
Packit Service fa4841
	if (securityFlags & SEC_AUTODETECT_REQ)
Packit Service fa4841
	{
Packit Service fa4841
		/* Server Auto-Detect Request PDU */
Packit Service fa4841
		return rdp_recv_autodetect_request_packet(rdp, s);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (securityFlags & SEC_AUTODETECT_RSP)
Packit Service fa4841
	{
Packit Service fa4841
		/* Client Auto-Detect Response PDU */
Packit Service fa4841
		return rdp_recv_autodetect_response_packet(rdp, s);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (securityFlags & SEC_HEARTBEAT)
Packit Service fa4841
	{
Packit Service fa4841
		/* Heartbeat PDU */
Packit Service fa4841
		return rdp_recv_heartbeat_packet(rdp, s);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (securityFlags & SEC_TRANSPORT_REQ)
Packit Service fa4841
	{
Packit Service fa4841
		/* Initiate Multitransport Request PDU */
Packit Service fa4841
		return rdp_recv_multitransport_packet(rdp, s);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return -1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 type;
Packit Service fa4841
	UINT16 length;
Packit Service fa4841
	UINT16 channelId;
Packit Service fa4841
Packit Service fa4841
	if (!rdp_read_share_control_header(s, &length, NULL, &type, &channelId))
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service fa4841
	if (type == PDU_TYPE_DATA)
Packit Service fa4841
	{
Packit Service fa4841
		return rdp_recv_data_pdu(rdp, s);
Packit Service fa4841
	}
Packit Service fa4841
	else if (type == PDU_TYPE_SERVER_REDIRECTION)
Packit Service fa4841
	{
Packit Service fa4841
		return rdp_recv_enhanced_security_redirection_packet(rdp, s);
Packit Service fa4841
	}
Packit Service fa4841
	else if (type == PDU_TYPE_FLOW_RESPONSE || type == PDU_TYPE_FLOW_STOP ||
Packit Service fa4841
	         type == PDU_TYPE_FLOW_TEST)
Packit Service fa4841
	{
Packit Service fa4841
		return 0;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL rdp_read_flow_control_pdu(wStream* s, UINT16* type, UINT16* channel_id)
Packit Service fa4841
{
Packit Service fa4841
	/*
Packit Service fa4841
	 * Read flow control PDU - documented in FlowPDU section in T.128
Packit Service fa4841
	 * http://www.itu.int/rec/T-REC-T.128-199802-S/en
Packit Service fa4841
	 * The specification for the PDU has pad8bits listed BEFORE pduTypeFlow.
Packit Service fa4841
	 * However, so far pad8bits has always been observed to arrive AFTER pduTypeFlow.
Packit Service fa4841
	 * Switched the order of these two fields to match this observation.
Packit Service fa4841
	 */
Packit Service fa4841
	UINT8 pduType;
Packit Service fa4841
	if (!type)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 6)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	Stream_Read_UINT8(s, pduType); /* pduTypeFlow */
Packit Service fa4841
	*type = pduType;
Packit Service fa4841
	Stream_Seek_UINT8(s);               /* pad8bits */
Packit Service fa4841
	Stream_Seek_UINT8(s);               /* flowIdentifier */
Packit Service fa4841
	Stream_Seek_UINT8(s);               /* flowNumber */
Packit Service fa4841
	Stream_Read_UINT16(s, *channel_id); /* pduSource */
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Decrypt an RDP packet.\n
Packit Service fa4841
 * @param rdp RDP module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param length int
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags)
Packit Service fa4841
{
Packit Service fa4841
	BYTE cmac[8];
Packit Service fa4841
	BYTE wmac[8];
Packit Service fa4841
	BOOL status;
Packit Service fa4841
	INT32 length;
Packit Service fa4841
Packit Service fa4841
	if (!rdp || !s || !pLength)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	length = *pLength;
Packit Service fa4841
	if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
Packit Service fa4841
	{
Packit Service fa4841
		UINT16 len;
Packit Service fa4841
		BYTE version, pad;
Packit Service fa4841
		BYTE* sig;
Packit Service fa4841
		INT64 padLength;
Packit Service fa4841
Packit Service fa4841
		if (Stream_GetRemainingLength(s) < 12)
Packit Service fa4841
			return FALSE;
Packit Service fa4841
Packit Service fa4841
		Stream_Read_UINT16(s, len);    /* 0x10 */
Packit Service fa4841
		Stream_Read_UINT8(s, version); /* 0x1 */
Packit Service fa4841
		Stream_Read_UINT8(s, pad);
Packit Service fa4841
		sig = Stream_Pointer(s);
Packit Service fa4841
		Stream_Seek(s, 8); /* signature */
Packit Service fa4841
		length -= 12;
Packit Service fa4841
		padLength = length - pad;
Packit Service fa4841
Packit Service fa4841
		if ((length <= 0) || (padLength <= 0))
Packit Service fa4841
			return FALSE;
Packit Service fa4841
Packit Service fa4841
		if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "FATAL: cannot decrypt");
Packit Service fa4841
			return FALSE; /* TODO */
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp))
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "FATAL: invalid packet signature");
Packit Service fa4841
			return FALSE; /* TODO */
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		Stream_SetLength(s, Stream_Length(s) - pad);
Packit Service fa4841
		*pLength = padLength;
Packit Service fa4841
		return TRUE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < sizeof(wmac))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read(s, wmac, sizeof(wmac));
Packit Service fa4841
	length -= sizeof(wmac);
Packit Service fa4841
Packit Service fa4841
	if (length <= 0)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!security_decrypt(Stream_Pointer(s), length, rdp))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (securityFlags & SEC_SECURE_CHECKSUM)
Packit Service fa4841
		status = security_salted_mac_signature(rdp, Stream_Pointer(s), length, FALSE, cmac);
Packit Service fa4841
	else
Packit Service fa4841
		status = security_mac_signature(rdp, Stream_Pointer(s), length, cmac);
Packit Service fa4841
Packit Service fa4841
	if (!status)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (memcmp(wmac, cmac, sizeof(wmac)) != 0)
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "WARNING: invalid packet signature");
Packit Service fa4841
		/*
Packit Service fa4841
		 * Because Standard RDP Security is totally broken,
Packit Service fa4841
		 * and cannot protect against MITM, don't treat signature
Packit Service fa4841
		 * verification failure as critical. This at least enables
Packit Service fa4841
		 * us to work with broken RDP clients and servers that
Packit Service fa4841
		 * generate invalid signatures.
Packit Service fa4841
		 */
Packit Service fa4841
		// return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	*pLength = length;
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static const char* pdu_type_to_str(UINT16 pduType)
Packit Service fa4841
{
Packit Service fa4841
	static char buffer[1024] = { 0 };
Packit Service fa4841
	switch (pduType)
Packit Service fa4841
	{
Packit Service fa4841
		case PDU_TYPE_DEMAND_ACTIVE:
Packit Service fa4841
			return "PDU_TYPE_DEMAND_ACTIVE";
Packit Service fa4841
		case PDU_TYPE_CONFIRM_ACTIVE:
Packit Service fa4841
			return "PDU_TYPE_CONFIRM_ACTIVE";
Packit Service fa4841
		case PDU_TYPE_DEACTIVATE_ALL:
Packit Service fa4841
			return "PDU_TYPE_DEACTIVATE_ALL";
Packit Service fa4841
		case PDU_TYPE_DATA:
Packit Service fa4841
			return "PDU_TYPE_DATA";
Packit Service fa4841
		case PDU_TYPE_SERVER_REDIRECTION:
Packit Service fa4841
			return "PDU_TYPE_SERVER_REDIRECTION";
Packit Service fa4841
		case PDU_TYPE_FLOW_TEST:
Packit Service fa4841
			return "PDU_TYPE_FLOW_TEST";
Packit Service fa4841
		case PDU_TYPE_FLOW_RESPONSE:
Packit Service fa4841
			return "PDU_TYPE_FLOW_RESPONSE";
Packit Service fa4841
		case PDU_TYPE_FLOW_STOP:
Packit Service fa4841
			return "PDU_TYPE_FLOW_STOP";
Packit Service fa4841
		default:
Packit Service fa4841
			_snprintf(buffer, sizeof(buffer), "UNKNOWN %04" PRIx16, pduType);
Packit Service fa4841
			return buffer;
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Process an RDP packet.\n
Packit Service fa4841
 * @param rdp RDP module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	int rc = 0;
Packit Service fa4841
	UINT16 length;
Packit Service fa4841
	UINT16 pduType;
Packit Service fa4841
	UINT16 pduSource;
Packit Service fa4841
	UINT16 channelId = 0;
Packit Service fa4841
	UINT16 securityFlags = 0;
Packit Service fa4841
Packit Service fa4841
	if (!rdp_read_header(rdp, s, &length, &channelId))
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "Incorrect RDP header.");
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (freerdp_shall_disconnect(rdp->instance))
Packit Service fa4841
		return 0;
Packit Service fa4841
Packit Service fa4841
	if (rdp->autodetect->bandwidthMeasureStarted)
Packit Service fa4841
	{
Packit Service fa4841
		rdp->autodetect->bandwidthMeasureByteCount += length;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (rdp->settings->UseRdpSecurityLayer)
Packit Service fa4841
	{
Packit Service fa4841
		if (!rdp_read_security_header(s, &securityFlags, &length))
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_read_security_header() fail");
Packit Service fa4841
			return -1;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (securityFlags & (SEC_ENCRYPT | SEC_REDIRECTION_PKT))
Packit Service fa4841
		{
Packit Service fa4841
			if (!rdp_decrypt(rdp, s, &length, securityFlags))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "rdp_decrypt failed");
Packit Service fa4841
				return -1;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (securityFlags & SEC_REDIRECTION_PKT)
Packit Service fa4841
		{
Packit Service fa4841
			/*
Packit Service fa4841
			 * [MS-RDPBCGR] 2.2.13.2.1
Packit Service fa4841
			 *  - no share control header, nor the 2 byte pad
Packit Service fa4841
			 */
Packit Service fa4841
			Stream_Rewind(s, 2);
Packit Service fa4841
			rdp->inPackets++;
Packit Service fa4841
Packit Service fa4841
			rc = rdp_recv_enhanced_security_redirection_packet(rdp, s);
Packit Service fa4841
			goto out;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (channelId == MCS_GLOBAL_CHANNEL_ID)
Packit Service fa4841
	{
Packit Service fa4841
		while (Stream_GetRemainingLength(s) > 3)
Packit Service fa4841
		{
Packit Service fa4841
			wStream sub;
Packit Service fa4841
			size_t diff;
Packit Service fa4841
			UINT16 remain;
Packit Service fa4841
Packit Service fa4841
			if (!rdp_read_share_control_header(s, NULL, &remain, &pduType, &pduSource))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_read_share_control_header() fail");
Packit Service fa4841
				return -1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			Stream_StaticInit(&sub, Stream_Pointer(s), remain);
Packit Service fa4841
			if (!Stream_SafeSeek(s, remain))
Packit Service fa4841
				return -1;
Packit Service fa4841
Packit Service fa4841
			rdp->settings->PduSource = pduSource;
Packit Service fa4841
			rdp->inPackets++;
Packit Service fa4841
Packit Service fa4841
			switch (pduType)
Packit Service fa4841
			{
Packit Service fa4841
				case PDU_TYPE_DATA:
Packit Service fa4841
					rc = rdp_recv_data_pdu(rdp, &sub);
Packit Service fa4841
					if (rc < 0)
Packit Service fa4841
						return rc;
Packit Service fa4841
					break;
Packit Service fa4841
Packit Service fa4841
				case PDU_TYPE_DEACTIVATE_ALL:
Packit Service fa4841
					if (!rdp_recv_deactivate_all(rdp, &sub))
Packit Service fa4841
					{
Packit Service fa4841
						WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_recv_deactivate_all() fail");
Packit Service fa4841
						return -1;
Packit Service fa4841
					}
Packit Service fa4841
Packit Service fa4841
					break;
Packit Service fa4841
Packit Service fa4841
				case PDU_TYPE_SERVER_REDIRECTION:
Packit Service fa4841
					return rdp_recv_enhanced_security_redirection_packet(rdp, &sub);
Packit Service fa4841
Packit Service fa4841
				case PDU_TYPE_FLOW_RESPONSE:
Packit Service fa4841
				case PDU_TYPE_FLOW_STOP:
Packit Service fa4841
				case PDU_TYPE_FLOW_TEST:
Packit Service fa4841
					WLog_DBG(TAG, "flow message 0x%04" PRIX16 "", pduType);
Packit Service fa4841
					/* http://msdn.microsoft.com/en-us/library/cc240576.aspx */
Packit Service fa4841
					if (!Stream_SafeSeek(&sub, remain))
Packit Service fa4841
						return -1;
Packit Service fa4841
					break;
Packit Service fa4841
Packit Service fa4841
				default:
Packit Service fa4841
					WLog_ERR(TAG, "incorrect PDU type: 0x%04" PRIX16 "", pduType);
Packit Service fa4841
					break;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			diff = Stream_GetRemainingLength(&sub);
Packit Service fa4841
			if (diff > 0)
Packit Service fa4841
			{
Packit Service fa4841
				WLog_WARN(TAG,
Packit Service fa4841
				          "pduType %s not properly parsed, %" PRIdz
Packit Service fa4841
				          " bytes remaining unhandled. Skipping.",
Packit Service fa4841
				          pdu_type_to_str(pduType), diff);
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
	else if (rdp->mcs->messageChannelId && (channelId == rdp->mcs->messageChannelId))
Packit Service fa4841
	{
Packit Service fa4841
		if (!rdp->settings->UseRdpSecurityLayer)
Packit Service fa4841
			if (!rdp_read_security_header(s, &securityFlags, NULL))
Packit Service fa4841
				return -1;
Packit Service fa4841
		rdp->inPackets++;
Packit Service fa4841
		rc = rdp_recv_message_channel_pdu(rdp, s, securityFlags);
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		rdp->inPackets++;
Packit Service fa4841
Packit Service fa4841
		if (!freerdp_channel_process(rdp->instance, s, channelId, length))
Packit Service fa4841
			return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
out:
Packit Service fa4841
	if (!tpkt_ensure_stream_consumed(s, length))
Packit Service fa4841
		return -1;
Packit Service fa4841
	return rc;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static int rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 length;
Packit Service fa4841
	rdpFastPath* fastpath;
Packit Service fa4841
	fastpath = rdp->fastpath;
Packit Service fa4841
Packit Service fa4841
	if (!fastpath_read_header_rdp(fastpath, s, &length))
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "rdp_recv_fastpath_pdu: fastpath_read_header_rdp() fail");
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if ((length == 0) || (length > Stream_GetRemainingLength(s)))
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "incorrect FastPath PDU header length %" PRIu16 "", length);
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (rdp->autodetect->bandwidthMeasureStarted)
Packit Service fa4841
	{
Packit Service fa4841
		rdp->autodetect->bandwidthMeasureByteCount += length;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED)
Packit Service fa4841
	{
Packit Service fa4841
		UINT16 flags =
Packit Service fa4841
		    (fastpath->encryptionFlags & FASTPATH_OUTPUT_SECURE_CHECKSUM) ? SEC_SECURE_CHECKSUM : 0;
Packit Service fa4841
Packit Service fa4841
		if (!rdp_decrypt(rdp, s, &length, flags))
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "rdp_recv_fastpath_pdu: rdp_decrypt() fail");
Packit Service fa4841
			return -1;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return fastpath_recv_updates(rdp->fastpath, s);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static int rdp_recv_pdu(rdpRdp* rdp, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	if (tpkt_verify_header(s))
Packit Service fa4841
		return rdp_recv_tpkt_pdu(rdp, s);
Packit Service fa4841
	else
Packit Service fa4841
		return rdp_recv_fastpath_pdu(rdp, s);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
Packit Service fa4841
{
Packit Service fa4841
	int status = 0;
Packit Service fa4841
	rdpRdp* rdp = (rdpRdp*)extra;
Packit Service fa4841
Packit Service fa4841
	/*
Packit Service fa4841
	 * At any point in the connection sequence between when all
Packit Service fa4841
	 * MCS channels have been joined and when the RDP connection
Packit Service fa4841
	 * enters the active state, an auto-detect PDU can be received
Packit Service fa4841
	 * on the MCS message channel.
Packit Service fa4841
	 */
Packit Service fa4841
	if ((rdp->state > CONNECTION_STATE_MCS_CHANNEL_JOIN) && (rdp->state < CONNECTION_STATE_ACTIVE))
Packit Service fa4841
	{
Packit Service fa4841
		if (rdp_client_connect_auto_detect(rdp, s))
Packit Service fa4841
			return 0;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	switch (rdp->state)
Packit Service fa4841
	{
Packit Service fa4841
		case CONNECTION_STATE_NLA:
Packit Service fa4841
			if (nla_get_state(rdp->nla) < NLA_STATE_AUTH_INFO)
Packit Service fa4841
			{
Packit Service fa4841
				if (nla_recv_pdu(rdp->nla, s) < 1)
Packit Service fa4841
				{
Packit Service fa4841
					WLog_ERR(TAG, "%s: %s - nla_recv_pdu() fail", __FUNCTION__,
Packit Service fa4841
					         rdp_server_connection_state_string(rdp->state));
Packit Service fa4841
					return -1;
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
			else if (nla_get_state(rdp->nla) == NLA_STATE_POST_NEGO)
Packit Service fa4841
			{
Packit Service fa4841
				nego_recv(rdp->transport, s, (void*)rdp->nego);
Packit Service fa4841
Packit Service fa4841
				if (nego_get_state(rdp->nego) != NEGO_STATE_FINAL)
Packit Service fa4841
				{
Packit Service fa4841
					WLog_ERR(TAG, "%s: %s - nego_recv() fail", __FUNCTION__,
Packit Service fa4841
					         rdp_server_connection_state_string(rdp->state));
Packit Service fa4841
					return -1;
Packit Service fa4841
				}
Packit Service fa4841
Packit Service fa4841
				if (!nla_set_state(rdp->nla, NLA_STATE_FINAL))
Packit Service fa4841
					return -1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			if (nla_get_state(rdp->nla) == NLA_STATE_AUTH_INFO)
Packit Service fa4841
			{
Packit Service fa4841
				transport_set_nla_mode(rdp->transport, FALSE);
Packit Service fa4841
Packit Service fa4841
				if (rdp->settings->VmConnectMode)
Packit Service fa4841
				{
Packit Service fa4841
					if (!nego_set_state(rdp->nego, NEGO_STATE_NLA))
Packit Service fa4841
						return -1;
Packit Service fa4841
Packit Service fa4841
					if (!nego_set_requested_protocols(rdp->nego, PROTOCOL_HYBRID | PROTOCOL_SSL))
Packit Service fa4841
						return -1;
Packit Service fa4841
Packit Service fa4841
					nego_send_negotiation_request(rdp->nego);
Packit Service fa4841
Packit Service fa4841
					if (!nla_set_state(rdp->nla, NLA_STATE_POST_NEGO))
Packit Service fa4841
						return -1;
Packit Service fa4841
				}
Packit Service fa4841
				else
Packit Service fa4841
				{
Packit Service fa4841
					if (!nla_set_state(rdp->nla, NLA_STATE_FINAL))
Packit Service fa4841
						return -1;
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			if (nla_get_state(rdp->nla) == NLA_STATE_FINAL)
Packit Service fa4841
			{
Packit Service fa4841
				nla_free(rdp->nla);
Packit Service fa4841
				rdp->nla = NULL;
Packit Service fa4841
Packit Service fa4841
				if (!mcs_client_begin(rdp->mcs))
Packit Service fa4841
				{
Packit Service fa4841
					WLog_ERR(TAG, "%s: %s - mcs_client_begin() fail", __FUNCTION__,
Packit Service fa4841
					         rdp_server_connection_state_string(rdp->state));
Packit Service fa4841
					return -1;
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case CONNECTION_STATE_MCS_CONNECT:
Packit Service fa4841
			if (!mcs_recv_connect_response(rdp->mcs, s))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "mcs_recv_connect_response failure");
Packit Service fa4841
				return -1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			if (!mcs_send_erect_domain_request(rdp->mcs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "mcs_send_erect_domain_request failure");
Packit Service fa4841
				return -1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			if (!mcs_send_attach_user_request(rdp->mcs))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "mcs_send_attach_user_request failure");
Packit Service fa4841
				return -1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case CONNECTION_STATE_MCS_ATTACH_USER:
Packit Service fa4841
			if (!mcs_recv_attach_user_confirm(rdp->mcs, s))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "mcs_recv_attach_user_confirm failure");
Packit Service fa4841
				return -1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG, "mcs_send_channel_join_request failure");
Packit Service fa4841
				return -1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case CONNECTION_STATE_MCS_CHANNEL_JOIN:
Packit Service fa4841
			if (!rdp_client_connect_mcs_channel_join_confirm(rdp, s))
Packit Service fa4841
			{
Packit Service fa4841
				WLog_ERR(TAG,
Packit Service fa4841
				         "%s: %s - "
Packit Service fa4841
				         "rdp_client_connect_mcs_channel_join_confirm() fail",
Packit Service fa4841
				         __FUNCTION__, rdp_server_connection_state_string(rdp->state));
Packit Service fa4841
				status = -1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case CONNECTION_STATE_LICENSING:
Packit Service fa4841
			status = rdp_client_connect_license(rdp, s);
Packit Service fa4841
Packit Service fa4841
			if (status < 0)
Packit Service fa4841
				WLog_DBG(TAG, "%s: %s - rdp_client_connect_license() - %i", __FUNCTION__,
Packit Service fa4841
				         rdp_server_connection_state_string(rdp->state), status);
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case CONNECTION_STATE_CAPABILITIES_EXCHANGE:
Packit Service fa4841
			status = rdp_client_connect_demand_active(rdp, s);
Packit Service fa4841
Packit Service fa4841
			if (status < 0)
Packit Service fa4841
				WLog_DBG(TAG,
Packit Service fa4841
				         "%s: %s - "
Packit Service fa4841
				         "rdp_client_connect_demand_active() - %i",
Packit Service fa4841
				         __FUNCTION__, rdp_server_connection_state_string(rdp->state), status);
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case CONNECTION_STATE_FINALIZATION:
Packit Service fa4841
			status = rdp_recv_pdu(rdp, s);
Packit Service fa4841
Packit Service fa4841
			if ((status >= 0) && (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE))
Packit Service fa4841
			{
Packit Service fa4841
				ActivatedEventArgs activatedEvent;
Packit Service fa4841
				rdpContext* context = rdp->context;
Packit Service fa4841
				rdp_client_transition_to_state(rdp, CONNECTION_STATE_ACTIVE);
Packit Service fa4841
				EventArgsInit(&activatedEvent, "libfreerdp");
Packit Service fa4841
				activatedEvent.firstActivation = !rdp->deactivation_reactivation;
Packit Service fa4841
				PubSub_OnActivated(context->pubSub, context, &activatedEvent);
Packit Service fa4841
				return 2;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			if (status < 0)
Packit Service fa4841
				WLog_DBG(TAG, "%s: %s - rdp_recv_pdu() - %i", __FUNCTION__,
Packit Service fa4841
				         rdp_server_connection_state_string(rdp->state), status);
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case CONNECTION_STATE_ACTIVE:
Packit Service fa4841
			status = rdp_recv_pdu(rdp, s);
Packit Service fa4841
Packit Service fa4841
			if (status < 0)
Packit Service fa4841
				WLog_DBG(TAG, "%s: %s - rdp_recv_pdu() - %i", __FUNCTION__,
Packit Service fa4841
				         rdp_server_connection_state_string(rdp->state), status);
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service fa4841
			WLog_ERR(TAG, "%s: %s state %d", __FUNCTION__,
Packit Service fa4841
			         rdp_server_connection_state_string(rdp->state), rdp->state);
Packit Service fa4841
			status = -1;
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return status;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL rdp_send_channel_data(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_t size)
Packit Service fa4841
{
Packit Service fa4841
	return freerdp_channel_send(rdp, channelId, data, size);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL rdp_send_error_info(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s;
Packit Service fa4841
	BOOL status;
Packit Service fa4841
Packit Service fa4841
	if (rdp->errorInfo == ERRINFO_SUCCESS)
Packit Service fa4841
		return TRUE;
Packit Service fa4841
Packit Service fa4841
	s = rdp_data_pdu_init(rdp);
Packit Service fa4841
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Write_UINT32(s, rdp->errorInfo); /* error id (4 bytes) */
Packit Service fa4841
	status = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_ERROR_INFO, 0);
Packit Service fa4841
	return status;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int rdp_check_fds(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	int status;
Packit Service fa4841
	rdpTransport* transport = rdp->transport;
Packit Service fa4841
Packit Service fa4841
	if (transport->tsg)
Packit Service fa4841
	{
Packit Service fa4841
		rdpTsg* tsg = transport->tsg;
Packit Service fa4841
Packit Service fa4841
		if (!tsg_check_event_handles(tsg))
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "rdp_check_fds: tsg_check_event_handles()");
Packit Service fa4841
			return -1;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (tsg_get_state(tsg) != TSG_STATE_PIPE_CREATED)
Packit Service fa4841
			return 1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	status = transport_check_fds(transport);
Packit Service fa4841
Packit Service fa4841
	if (status == 1)
Packit Service fa4841
	{
Packit Service fa4841
		if (!rdp_client_redirect(rdp)) /* session redirection */
Packit Service fa4841
			return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (status < 0)
Packit Service fa4841
		WLog_DBG(TAG, "transport_check_fds() - %i", status);
Packit Service fa4841
Packit Service fa4841
	return status;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL freerdp_get_stats(rdpRdp* rdp, UINT64* inBytes, UINT64* outBytes, UINT64* inPackets,
Packit Service fa4841
                       UINT64* outPackets)
Packit Service fa4841
{
Packit Service fa4841
	if (!rdp)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (inBytes)
Packit Service fa4841
		*inBytes = rdp->inBytes;
Packit Service fa4841
	if (outBytes)
Packit Service fa4841
		*outBytes = rdp->outBytes;
Packit Service fa4841
	if (inPackets)
Packit Service fa4841
		*inPackets = rdp->inPackets;
Packit Service fa4841
	if (outPackets)
Packit Service fa4841
		*outPackets = rdp->outPackets;
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Instantiate new RDP module.
Packit Service fa4841
 * @return new RDP module
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
rdpRdp* rdp_new(rdpContext* context)
Packit Service fa4841
{
Packit Service fa4841
	rdpRdp* rdp;
Packit Service fa4841
	DWORD flags;
Packit Service fa4841
	BOOL newSettings = FALSE;
Packit Service fa4841
	rdp = (rdpRdp*)calloc(1, sizeof(rdpRdp));
Packit Service fa4841
Packit Service fa4841
	if (!rdp)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	InitializeCriticalSection(&rdp->critical);
Packit Service fa4841
	rdp->context = context;
Packit Service fa4841
	rdp->instance = context->instance;
Packit Service fa4841
	flags = 0;
Packit Service fa4841
Packit Service fa4841
	if (context->ServerMode)
Packit Service fa4841
		flags |= FREERDP_SETTINGS_SERVER_MODE;
Packit Service fa4841
Packit Service fa4841
	if (!context->settings)
Packit Service fa4841
	{
Packit Service fa4841
		context->settings = freerdp_settings_new(flags);
Packit Service fa4841
Packit Service fa4841
		if (!context->settings)
Packit Service fa4841
			goto fail;
Packit Service fa4841
Packit Service fa4841
		newSettings = TRUE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	rdp->settings = context->settings;
Packit Service fa4841
Packit Service fa4841
	if (context->instance)
Packit Service fa4841
	{
Packit Service fa4841
		rdp->settings->instance = context->instance;
Packit Service fa4841
		context->instance->settings = rdp->settings;
Packit Service fa4841
	}
Packit Service fa4841
	else if (context->peer)
Packit Service fa4841
	{
Packit Service fa4841
		rdp->settings->instance = context->peer;
Packit Service fa4841
		context->peer->settings = rdp->settings;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	rdp->transport = transport_new(context);
Packit Service fa4841
Packit Service fa4841
	if (!rdp->transport)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->license = license_new(rdp);
Packit Service fa4841
Packit Service fa4841
	if (!rdp->license)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->input = input_new(rdp);
Packit Service fa4841
Packit Service fa4841
	if (!rdp->input)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->update = update_new(rdp);
Packit Service fa4841
Packit Service fa4841
	if (!rdp->update)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->fastpath = fastpath_new(rdp);
Packit Service fa4841
Packit Service fa4841
	if (!rdp->fastpath)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->nego = nego_new(rdp->transport);
Packit Service fa4841
Packit Service fa4841
	if (!rdp->nego)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->mcs = mcs_new(rdp->transport);
Packit Service fa4841
Packit Service fa4841
	if (!rdp->mcs)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->redirection = redirection_new();
Packit Service fa4841
Packit Service fa4841
	if (!rdp->redirection)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->autodetect = autodetect_new();
Packit Service fa4841
Packit Service fa4841
	if (!rdp->autodetect)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->heartbeat = heartbeat_new();
Packit Service fa4841
Packit Service fa4841
	if (!rdp->heartbeat)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->multitransport = multitransport_new();
Packit Service fa4841
Packit Service fa4841
	if (!rdp->multitransport)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	rdp->bulk = bulk_new(context);
Packit Service fa4841
Packit Service fa4841
	if (!rdp->bulk)
Packit Service fa4841
		goto fail;
Packit Service fa4841
Packit Service fa4841
	return rdp;
Packit Service fa4841
Packit Service fa4841
fail:
Packit Service fa4841
	rdp_free(rdp);
Packit Service fa4841
	return NULL;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void rdp_reset(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	rdpContext* context;
Packit Service fa4841
	rdpSettings* settings;
Packit Service fa4841
	context = rdp->context;
Packit Service fa4841
	settings = rdp->settings;
Packit Service fa4841
	bulk_reset(rdp->bulk);
Packit Service fa4841
Packit Service fa4841
	if (rdp->rc4_decrypt_key)
Packit Service fa4841
	{
Packit Service fa4841
		winpr_RC4_Free(rdp->rc4_decrypt_key);
Packit Service fa4841
		rdp->rc4_decrypt_key = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (rdp->rc4_encrypt_key)
Packit Service fa4841
	{
Packit Service fa4841
		winpr_RC4_Free(rdp->rc4_encrypt_key);
Packit Service fa4841
		rdp->rc4_encrypt_key = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (rdp->fips_encrypt)
Packit Service fa4841
	{
Packit Service fa4841
		winpr_Cipher_Free(rdp->fips_encrypt);
Packit Service fa4841
		rdp->fips_encrypt = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (rdp->fips_decrypt)
Packit Service fa4841
	{
Packit Service fa4841
		winpr_Cipher_Free(rdp->fips_decrypt);
Packit Service fa4841
		rdp->fips_decrypt = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (settings->ServerRandom)
Packit Service fa4841
	{
Packit Service fa4841
		free(settings->ServerRandom);
Packit Service fa4841
		settings->ServerRandom = NULL;
Packit Service fa4841
		settings->ServerRandomLength = 0;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (settings->ServerCertificate)
Packit Service fa4841
	{
Packit Service fa4841
		free(settings->ServerCertificate);
Packit Service fa4841
		settings->ServerCertificate = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (settings->ClientAddress)
Packit Service fa4841
	{
Packit Service fa4841
		free(settings->ClientAddress);
Packit Service fa4841
		settings->ClientAddress = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	mcs_free(rdp->mcs);
Packit Service fa4841
	nego_free(rdp->nego);
Packit Service fa4841
	license_free(rdp->license);
Packit Service fa4841
	transport_free(rdp->transport);
Packit Service fa4841
	fastpath_free(rdp->fastpath);
Packit Service fa4841
	rdp->transport = transport_new(context);
Packit Service fa4841
	rdp->license = license_new(rdp);
Packit Service fa4841
	rdp->nego = nego_new(rdp->transport);
Packit Service fa4841
	rdp->mcs = mcs_new(rdp->transport);
Packit Service fa4841
	rdp->fastpath = fastpath_new(rdp);
Packit Service fa4841
	rdp->transport->layer = TRANSPORT_LAYER_TCP;
Packit Service fa4841
	rdp->errorInfo = 0;
Packit Service fa4841
	rdp->deactivation_reactivation = 0;
Packit Service fa4841
	rdp->finalize_sc_pdus = 0;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Free RDP module.
Packit Service fa4841
 * @param rdp RDP module to be freed
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void rdp_free(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	if (rdp)
Packit Service fa4841
	{
Packit Service fa4841
		DeleteCriticalSection(&rdp->critical);
Packit Service fa4841
		winpr_RC4_Free(rdp->rc4_decrypt_key);
Packit Service fa4841
		winpr_RC4_Free(rdp->rc4_encrypt_key);
Packit Service fa4841
		winpr_Cipher_Free(rdp->fips_encrypt);
Packit Service fa4841
		winpr_Cipher_Free(rdp->fips_decrypt);
Packit Service fa4841
		freerdp_settings_free(rdp->settings);
Packit Service fa4841
		transport_free(rdp->transport);
Packit Service fa4841
		license_free(rdp->license);
Packit Service fa4841
		input_free(rdp->input);
Packit Service fa4841
		update_free(rdp->update);
Packit Service fa4841
		fastpath_free(rdp->fastpath);
Packit Service fa4841
		nego_free(rdp->nego);
Packit Service fa4841
		mcs_free(rdp->mcs);
Packit Service fa4841
		nla_free(rdp->nla);
Packit Service fa4841
		redirection_free(rdp->redirection);
Packit Service fa4841
		autodetect_free(rdp->autodetect);
Packit Service fa4841
		heartbeat_free(rdp->heartbeat);
Packit Service fa4841
		multitransport_free(rdp->multitransport);
Packit Service fa4841
		bulk_free(rdp->bulk);
Packit Service fa4841
		free(rdp);
Packit Service fa4841
	}
Packit Service fa4841
}