diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index dad62d585..6203516fd 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -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 */