[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:
parent
4ab9fb4425
commit
0da0f5ca54
@ -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) */
|
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).
|
* Read Extended Info Packet (TS_EXTENDED_INFO_PACKET).
|
||||||
* msdn{cc240476}
|
* 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.
|
* 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 "",
|
WLog_ERR(TAG, "protocol error: invalid cbClientAddress value: %" PRIu16 "",
|
||||||
cbClientAddress);
|
cbClientAddress);
|
||||||
@ -435,6 +456,7 @@ static BOOL rdp_write_extended_info_packet(rdpRdp* rdp, wStream* s)
|
|||||||
UINT16 clientAddressFamily;
|
UINT16 clientAddressFamily;
|
||||||
WCHAR* clientAddress = NULL;
|
WCHAR* clientAddress = NULL;
|
||||||
size_t cbClientAddress;
|
size_t cbClientAddress;
|
||||||
|
const size_t cbClientAddressMax = rdp_get_client_address_max_size(rdp);
|
||||||
WCHAR* clientDir = NULL;
|
WCHAR* clientDir = NULL;
|
||||||
size_t cbClientDir;
|
size_t cbClientDir;
|
||||||
UINT16 cbAutoReconnectCookie;
|
UINT16 cbAutoReconnectCookie;
|
||||||
@ -447,7 +469,18 @@ static BOOL rdp_write_extended_info_packet(rdpRdp* rdp, wStream* s)
|
|||||||
|
|
||||||
if (cbClientAddress > (UINT16_MAX / sizeof(WCHAR)))
|
if (cbClientAddress > (UINT16_MAX / sizeof(WCHAR)))
|
||||||
goto fail;
|
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);
|
clientDir = ConvertUtf8ToWCharAlloc(settings->ClientDir, &cbClientDir);
|
||||||
if (cbClientDir > (UINT16_MAX / sizeof(WCHAR)))
|
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;
|
cbAutoReconnectCookie = (UINT16)settings->ServerAutoReconnectCookie->cbLen;
|
||||||
|
|
||||||
Stream_Write_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */
|
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(s, clientAddress, cbClientAddress); /* clientAddress */
|
||||||
|
|
||||||
Stream_Write_UINT16(s, 0);
|
|
||||||
Stream_Write_UINT16(s, cbClientDir + 2); /* cbClientDir (2 bytes) */
|
Stream_Write_UINT16(s, cbClientDir + 2); /* cbClientDir (2 bytes) */
|
||||||
|
|
||||||
Stream_Write(s, clientDir, cbClientDir); /* clientDir */
|
Stream_Write(s, clientDir, cbClientDir); /* clientDir */
|
||||||
|
Loading…
Reference in New Issue
Block a user