Blame libfreerdp/core/rdp.c

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