[core,info] enforce extended info limits

the cbClientAddress field limits defined in [MS-RDPBCGR]
2.2.1.11.1.1.1 Extended Info Packet (TS_EXTENDED_INFO_PACKET) are now
properly enforced.
This commit is contained in:
Armin Novak 2022-12-14 09:44:57 +01:00 committed by Pascal Nowack
parent 4ab9fb4425
commit 0da0f5ca54

View File

@ -274,6 +274,27 @@ static void rdp_write_client_auto_reconnect_cookie(rdpRdp* rdp, wStream* s)
Stream_Write(s, autoReconnectCookie->securityVerifier, 16); /* SecurityVerifier (16 bytes) */
}
/*
* Get the cbClientAddress size limit
* see [MS-RDPBCGR] 2.2.1.11.1.1.1 Extended Info Packet (TS_EXTENDED_INFO_PACKET)
*/
static size_t rdp_get_client_address_max_size(const rdpRdp* rdp)
{
UINT32 version;
rdpSettings* settings;
WINPR_ASSERT(rdp);
settings = rdp->settings;
WINPR_ASSERT(settings);
version = freerdp_settings_get_uint32(settings, FreeRDP_RdpVersion);
if (version < RDP_VERSION_10_0)
return 64;
return 80;
}
/**
* Read Extended Info Packet (TS_EXTENDED_INFO_PACKET).
* msdn{cc240476}
@ -300,7 +321,7 @@ static BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
* is mandatory, connections via Microsoft's TS Gateway set cbClientAddress to 0.
*/
if ((cbClientAddress % 2) || cbClientAddress > 80)
if ((cbClientAddress % 2) || (cbClientAddress > rdp_get_client_address_max_size(rdp)))
{
WLog_ERR(TAG, "protocol error: invalid cbClientAddress value: %" PRIu16 "",
cbClientAddress);
@ -435,6 +456,7 @@ static BOOL rdp_write_extended_info_packet(rdpRdp* rdp, wStream* s)
UINT16 clientAddressFamily;
WCHAR* clientAddress = NULL;
size_t cbClientAddress;
const size_t cbClientAddressMax = rdp_get_client_address_max_size(rdp);
WCHAR* clientDir = NULL;
size_t cbClientDir;
UINT16 cbAutoReconnectCookie;
@ -447,7 +469,18 @@ static BOOL rdp_write_extended_info_packet(rdpRdp* rdp, wStream* s)
if (cbClientAddress > (UINT16_MAX / sizeof(WCHAR)))
goto fail;
cbClientAddress = (UINT16)cbClientAddress * sizeof(WCHAR);
cbClientAddress = (UINT16)(cbClientAddress + 1) * sizeof(WCHAR);
if (cbClientAddress > cbClientAddressMax)
{
WLog_WARN(TAG,
"[%s] the client address %s [%" PRIuz "] exceeds the limit of %" PRIuz
", truncating.",
__FUNCTION__, settings->ClientAddress, cbClientAddress, cbClientAddressMax);
clientAddress[(cbClientAddressMax / sizeof(WCHAR)) - 1] = '\0';
cbClientAddress = cbClientAddressMax;
}
clientDir = ConvertUtf8ToWCharAlloc(settings->ClientDir, &cbClientDir);
if (cbClientDir > (UINT16_MAX / sizeof(WCHAR)))
@ -459,11 +492,10 @@ static BOOL rdp_write_extended_info_packet(rdpRdp* rdp, wStream* s)
cbAutoReconnectCookie = (UINT16)settings->ServerAutoReconnectCookie->cbLen;
Stream_Write_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */
Stream_Write_UINT16(s, cbClientAddress + 2); /* cbClientAddress (2 bytes) */
Stream_Write_UINT16(s, cbClientAddress); /* cbClientAddress (2 bytes) */
Stream_Write(s, clientAddress, cbClientAddress); /* clientAddress */
Stream_Write_UINT16(s, 0);
Stream_Write_UINT16(s, cbClientDir + 2); /* cbClientDir (2 bytes) */
Stream_Write(s, clientDir, cbClientDir); /* clientDir */