core/capabilities: Fix handling of Virtual Channel Capability Set

The VirtualChannelChunkSize can only be larger than 1600 Bytes, when
both client and server write that value in their capability set
regardless of the value itself.
Also, Microsoft clients and servers only advertise the capabilities that
are relevant for the other peer, e.g. mstsc only tells the server that
it supports decompressing compressed data from the server, but it does
not advertise, that it is able to compress data for the server.

Additionally, correctly apply the read capabilities after reading them.
This commit is contained in:
Pascal Nowack 2023-04-28 06:52:40 +02:00 committed by akallabeth
parent 264d19765c
commit 50c3559a43

View File

@ -29,6 +29,8 @@
#define TAG FREERDP_TAG("core.capabilities")
#define CHANNEL_CHUNK_LENGTH 1600
static const char* const CAPSET_TYPE_STRINGS[] = { "Unknown",
"General",
"Bitmap",
@ -2137,11 +2139,30 @@ static BOOL rdp_apply_virtual_channel_capability_set(rdpSettings* settings, cons
WINPR_ASSERT(settings);
WINPR_ASSERT(src);
if (!settings->ServerMode)
{
settings->VirtualChannelCompressionFlags = src->VirtualChannelCompressionFlags;
/* MS servers and clients disregard in advertising what is relevant for their own side */
if (settings->ServerMode && (settings->VirtualChannelCompressionFlags & VCCAPS_COMPR_SC) &&
(src->VirtualChannelCompressionFlags & VCCAPS_COMPR_SC))
settings->VirtualChannelCompressionFlags |= VCCAPS_COMPR_SC;
else
settings->VirtualChannelCompressionFlags &= ~VCCAPS_COMPR_SC;
if (!settings->ServerMode && (settings->VirtualChannelCompressionFlags & VCCAPS_COMPR_CS_8K) &&
(src->VirtualChannelCompressionFlags & VCCAPS_COMPR_CS_8K))
settings->VirtualChannelCompressionFlags |= VCCAPS_COMPR_CS_8K;
else
settings->VirtualChannelCompressionFlags &= ~VCCAPS_COMPR_CS_8K;
/*
* When one peer does not write the VCChunkSize, the VCChunkSize must not be
* larger than CHANNEL_CHUNK_LENGTH (1600) bytes.
* Also prevent an invalid 0 size.
*/
if (!settings->ServerMode &&
((src->VirtualChannelChunkSize > 16256) || (src->VirtualChannelChunkSize == 0)))
settings->VirtualChannelChunkSize = CHANNEL_CHUNK_LENGTH;
else if (!settings->ServerMode)
settings->VirtualChannelChunkSize = src->VirtualChannelChunkSize;
}
return TRUE;
}
@ -2164,7 +2185,7 @@ static BOOL rdp_read_virtual_channel_capability_set(wStream* s, rdpSettings* set
if (Stream_GetRemainingLength(s) >= 4)
Stream_Read_UINT32(s, VCChunkSize); /* VCChunkSize (4 bytes) */
else
VCChunkSize = 1600;
VCChunkSize = UINT32_MAX; /* Use an invalid value to determine that value is not present */
settings->VirtualChannelCompressionFlags = flags;
settings->VirtualChannelChunkSize = VCChunkSize;
@ -3920,7 +3941,7 @@ static BOOL rdp_apply_from_received(UINT16 type, rdpSettings* dst, const rdpSett
case CAPSET_TYPE_INPUT:
return rdp_apply_input_capability_set(dst, src);
case CAPSET_TYPE_VIRTUAL_CHANNEL:
return rdp_apply_input_capability_set(dst, src);
return rdp_apply_virtual_channel_capability_set(dst, src);
case CAPSET_TYPE_SHARE:
return rdp_apply_share_capability_set(dst, src);
case CAPSET_TYPE_COLOR_CACHE: