Refactored capability parsing

* Add new settings for previously ignored capability options
* Store raw capability data in settings for later use
* Add function to extract settings from raw capability data
* Split capability read/write from client/server logic (e.g. enforce
  limits, ...)
This commit is contained in:
Armin Novak 2022-10-05 09:30:37 +02:00 committed by akallabeth
parent b5e8b419b8
commit 7cef0cb8d6
8 changed files with 1138 additions and 488 deletions

View File

@ -790,6 +790,8 @@ typedef struct
#define FreeRDP_RemoteApplicationWorkingDir (2128)
#define FreeRDP_ReceivedCapabilities (2240)
#define FreeRDP_ReceivedCapabilitiesSize (2241)
#define FreeRDP_ReceivedCapabilityData (2242)
#define FreeRDP_ReceivedCapabilityDataSizes (2243)
#define FreeRDP_OsMajorType (2304)
#define FreeRDP_OsMinorType (2305)
#define FreeRDP_RefreshRect (2306)
@ -799,6 +801,11 @@ typedef struct
#define FreeRDP_LongCredentialsSupported (2310)
#define FreeRDP_NoBitmapCompressionHeader (2311)
#define FreeRDP_BitmapCompressionDisabled (2312)
#define FreeRDP_CapsProtocolVersion (2313)
#define FreeRDP_CapsGeneralCompressionTypes (2314)
#define FreeRDP_CapsUpdateCapabilityFlag (2315)
#define FreeRDP_CapsRemoteUnshareFlag (2316)
#define FreeRDP_CapsGeneralCompressionLevel (2317)
#define FreeRDP_DesktopResize (2368)
#define FreeRDP_DrawAllowDynamicColorFidelity (2369)
#define FreeRDP_DrawAllowColorSubsampling (2370)
@ -1209,13 +1216,13 @@ struct rdp_settings
ALIGN64 char* CertificateName; /* 1409 */
ALIGN64 char* CertificateFile; /* 1410 */
ALIGN64 char* PrivateKeyFile; /* 1411 */
UINT64 padding1412[1]; /* 1412 */
UINT64 padding1412[1413 - 1412]; /* 1412 */
ALIGN64 rdpRsaKey* RdpServerRsaKey; /* 1413 */
ALIGN64 rdpCertificate* RdpServerCertificate; /* 1414 */
ALIGN64 BOOL ExternalCertificateManagement; /* 1415 */
ALIGN64 char* CertificateContent; /* 1416 */
ALIGN64 char* PrivateKeyContent; /* 1417 */
UINT64 padding1418[1]; /* 1418 */
UINT64 padding1418[1419 - 1418]; /* 1418 */
ALIGN64 BOOL AutoAcceptCertificate; /* 1419 */
ALIGN64 BOOL AutoDenyCertificate; /* 1420 */
ALIGN64 char* CertificateAcceptedFingerprints; /* 1421 */
@ -1356,19 +1363,26 @@ struct rdp_settings
/* Capabilities */
ALIGN64 BYTE* ReceivedCapabilities; /* 2240 */
ALIGN64 UINT32 ReceivedCapabilitiesSize; /* 2241 */
UINT64 padding2304[2304 - 2242]; /* 2242 */
ALIGN64 BYTE** ReceivedCapabilityData; /* 2242 */
ALIGN64 UINT32* ReceivedCapabilityDataSizes; /* 2243 */
UINT64 padding2304[2304 - 2244]; /* 2244 */
/* General Capabilities */
ALIGN64 UINT32 OsMajorType; /* 2304 */
ALIGN64 UINT32 OsMinorType; /* 2305 */
ALIGN64 BOOL RefreshRect; /* 2306 */
ALIGN64 BOOL SuppressOutput; /* 2307 */
ALIGN64 BOOL FastPathOutput; /* 2308 */
ALIGN64 BOOL SaltedChecksum; /* 2309 */
ALIGN64 BOOL LongCredentialsSupported; /* 2310 */
ALIGN64 BOOL NoBitmapCompressionHeader; /* 2311 */
ALIGN64 BOOL BitmapCompressionDisabled; /* 2312 */
UINT64 padding2368[2368 - 2313]; /* 2313 */
ALIGN64 UINT32 OsMajorType; /* 2304 */
ALIGN64 UINT32 OsMinorType; /* 2305 */
ALIGN64 BOOL RefreshRect; /* 2306 */
ALIGN64 BOOL SuppressOutput; /* 2307 */
ALIGN64 BOOL FastPathOutput; /* 2308 */
ALIGN64 BOOL SaltedChecksum; /* 2309 */
ALIGN64 BOOL LongCredentialsSupported; /* 2310 */
ALIGN64 BOOL NoBitmapCompressionHeader; /* 2311 */
ALIGN64 BOOL BitmapCompressionDisabled; /* 2312 */
ALIGN64 UINT16 CapsProtocolVersion; /* 2313 */
ALIGN64 UINT16 CapsGeneralCompressionTypes; /* 2314 */
ALIGN64 UINT16 CapsUpdateCapabilityFlag; /* 2315 */
ALIGN64 UINT16 CapsRemoteUnshareFlag; /* 2316 */
ALIGN64 UINT16 CapsGeneralCompressionLevel; /* 2317 */
UINT64 padding2368[2368 - 2318]; /* 2318 */
/* Bitmap Capabilities */
ALIGN64 BOOL DesktopResize; /* 2368 */
@ -1834,6 +1848,10 @@ extern "C"
FREERDP_API const char* freerdp_settings_get_name_for_key(size_t key);
FREERDP_API UINT32 freerdp_settings_get_codecs_flags(const rdpSettings* settings);
FREERDP_API BOOL freerdp_settings_update_from_caps(rdpSettings* settings, BYTE* capsFlags,
BYTE** capsData, UINT32* capsSizes,
UINT32 capsCount, BOOL serverReceivedCaps);
FREERDP_API const char* freerdp_settings_get_server_name(const rdpSettings* settings);
FREERDP_API char* freerdp_rail_support_flags_to_string(UINT32 flags, char* buffer,

View File

@ -30,6 +30,7 @@
#include "../core/settings.h"
#include "../core/certificate.h"
#include "../core/capabilities.h"
#include <freerdp/settings.h>
#include <freerdp/freerdp.h>
#include <freerdp/log.h>
@ -823,10 +824,25 @@ void freerdp_dynamic_channel_collection_free(rdpSettings* settings)
void freerdp_capability_buffer_free(rdpSettings* settings)
{
UINT32 x;
WINPR_ASSERT(settings);
if (settings->ReceivedCapabilityData)
{
for (x = 0; x < settings->ReceivedCapabilitiesSize; x++)
{
free(settings->ReceivedCapabilityData[x]);
settings->ReceivedCapabilityData[x] = NULL;
}
}
settings->ReceivedCapabilitiesSize = 0;
free(settings->ReceivedCapabilityDataSizes);
settings->ReceivedCapabilityDataSizes = NULL;
free(settings->ReceivedCapabilityData);
settings->ReceivedCapabilityData = NULL;
free(settings->ReceivedCapabilities);
settings->ReceivedCapabilities = NULL;
}
@ -841,8 +857,29 @@ BOOL freerdp_capability_buffer_copy(rdpSettings* settings, const rdpSettings* sr
for (UINT32 x = 0; x < src->ReceivedCapabilitiesSize; x++)
{
void* tmp;
WINPR_ASSERT(settings->ReceivedCapabilities);
settings->ReceivedCapabilities[x] = src->ReceivedCapabilities[x];
WINPR_ASSERT(settings->ReceivedCapabilityDataSizes);
settings->ReceivedCapabilityDataSizes[x] = src->ReceivedCapabilityDataSizes[x];
WINPR_ASSERT(settings->ReceivedCapabilityData);
if (src->ReceivedCapabilityDataSizes[x] > 0)
{
tmp = realloc(settings->ReceivedCapabilityData[x],
settings->ReceivedCapabilityDataSizes[x]);
if (!tmp)
return FALSE;
memcpy(tmp, src->ReceivedCapabilityData[x], src->ReceivedCapabilityDataSizes[x]);
settings->ReceivedCapabilityData[x] = tmp;
}
else
{
free(settings->ReceivedCapabilityData[x]);
settings->ReceivedCapabilityData[x] = NULL;
}
}
return TRUE;
}
@ -1338,6 +1375,11 @@ BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, size_t id, const vo
freerdp_dynamic_channel_collection_free(settings);
return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_DynamicChannelArraySize,
data, len, sizeof(ADDIN_ARGV*));
case FreeRDP_ReceivedCapabilityData:
if (data == NULL)
freerdp_capability_buffer_free(settings);
return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ReceivedCapabilitiesSize,
data, len, sizeof(BYTE*));
case FreeRDP_ReceivedCapabilities:
if (data == NULL)
freerdp_capability_buffer_free(settings);
@ -1476,7 +1518,7 @@ void* freerdp_settings_get_pointer_array_writable(const rdpSettings* settings, s
max = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
if (offset >= max)
goto fail;
return &settings->TargetNetPorts[offset];
return settings->TargetNetPorts[offset];
case FreeRDP_ClientTimeZone:
max = 1;
if (offset >= max)
@ -1850,6 +1892,31 @@ char* freerdp_rail_support_flags_to_string(UINT32 flags, char* buffer, size_t le
return buffer;
}
BOOL freerdp_settings_update_from_caps(rdpSettings* settings, BYTE* capsFlags, BYTE** capsData,
UINT32* capsSizes, UINT32 capsCount, BOOL serverReceivedCaps)
{
UINT32 x;
WINPR_ASSERT(settings);
WINPR_ASSERT(capsFlags || (capsCount == 0));
WINPR_ASSERT(capsData || (capsCount == 0));
WINPR_ASSERT(capsSizes || (capsCount == 0));
WINPR_ASSERT(capsCount <= UINT16_MAX);
for (x = 0; x < capsCount; x++)
{
if (capsFlags[x])
{
wStream buffer;
wStream* sub = Stream_StaticConstInit(&buffer, capsData[x], capsSizes[x]);
if (!rdp_read_capability_set(sub, (UINT16)x, settings, serverReceivedCaps))
return FALSE;
}
}
return TRUE;
}
const char* freerdp_rdp_version_string(UINT32 version)
{
switch (version)

View File

@ -1282,6 +1282,21 @@ UINT16 freerdp_settings_get_uint16(const rdpSettings* settings, size_t id)
switch (id)
{
case FreeRDP_CapsGeneralCompressionLevel:
return settings->CapsGeneralCompressionLevel;
case FreeRDP_CapsGeneralCompressionTypes:
return settings->CapsGeneralCompressionTypes;
case FreeRDP_CapsProtocolVersion:
return settings->CapsProtocolVersion;
case FreeRDP_CapsRemoteUnshareFlag:
return settings->CapsRemoteUnshareFlag;
case FreeRDP_CapsUpdateCapabilityFlag:
return settings->CapsUpdateCapabilityFlag;
case FreeRDP_DesktopOrientation:
return settings->DesktopOrientation;
@ -1317,6 +1332,26 @@ BOOL freerdp_settings_set_uint16(rdpSettings* settings, size_t id, UINT16 val)
switch (id)
{
case FreeRDP_CapsGeneralCompressionLevel:
settings->CapsGeneralCompressionLevel = cnv.c;
break;
case FreeRDP_CapsGeneralCompressionTypes:
settings->CapsGeneralCompressionTypes = cnv.c;
break;
case FreeRDP_CapsProtocolVersion:
settings->CapsProtocolVersion = cnv.c;
break;
case FreeRDP_CapsRemoteUnshareFlag:
settings->CapsRemoteUnshareFlag = cnv.c;
break;
case FreeRDP_CapsUpdateCapabilityFlag:
settings->CapsUpdateCapabilityFlag = cnv.c;
break;
case FreeRDP_DesktopOrientation:
settings->DesktopOrientation = cnv.c;
break;
@ -3276,6 +3311,12 @@ void* freerdp_settings_get_pointer_writable(rdpSettings* settings, size_t id)
case FreeRDP_ReceivedCapabilities:
return settings->ReceivedCapabilities;
case FreeRDP_ReceivedCapabilityData:
return settings->ReceivedCapabilityData;
case FreeRDP_ReceivedCapabilityDataSizes:
return settings->ReceivedCapabilityDataSizes;
case FreeRDP_RedirectionPassword:
return settings->RedirectionPassword;
@ -3392,6 +3433,14 @@ BOOL freerdp_settings_set_pointer(rdpSettings* settings, size_t id, const void*
settings->ReceivedCapabilities = cnv.v;
break;
case FreeRDP_ReceivedCapabilityData:
settings->ReceivedCapabilityData = cnv.v;
break;
case FreeRDP_ReceivedCapabilityDataSizes:
settings->ReceivedCapabilityDataSizes = cnv.v;
break;
case FreeRDP_RedirectionPassword:
settings->RedirectionPassword = cnv.v;
break;

View File

@ -239,6 +239,15 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_WaitForOutputBufferFlush, FREERDP_SETTINGS_TYPE_BOOL,
"FreeRDP_WaitForOutputBufferFlush" },
{ FreeRDP_Workarea, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_Workarea" },
{ FreeRDP_CapsGeneralCompressionLevel, FREERDP_SETTINGS_TYPE_UINT16,
"FreeRDP_CapsGeneralCompressionLevel" },
{ FreeRDP_CapsGeneralCompressionTypes, FREERDP_SETTINGS_TYPE_UINT16,
"FreeRDP_CapsGeneralCompressionTypes" },
{ FreeRDP_CapsProtocolVersion, FREERDP_SETTINGS_TYPE_UINT16, "FreeRDP_CapsProtocolVersion" },
{ FreeRDP_CapsRemoteUnshareFlag, FREERDP_SETTINGS_TYPE_UINT16,
"FreeRDP_CapsRemoteUnshareFlag" },
{ FreeRDP_CapsUpdateCapabilityFlag, FREERDP_SETTINGS_TYPE_UINT16,
"FreeRDP_CapsUpdateCapabilityFlag" },
{ FreeRDP_DesktopOrientation, FREERDP_SETTINGS_TYPE_UINT16, "FreeRDP_DesktopOrientation" },
{ FreeRDP_ProxyPort, FREERDP_SETTINGS_TYPE_UINT16, "FreeRDP_ProxyPort" },
{ FreeRDP_TLSMaxVersion, FREERDP_SETTINGS_TYPE_UINT16, "FreeRDP_TLSMaxVersion" },
@ -523,6 +532,10 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_RdpServerCertificate, FREERDP_SETTINGS_TYPE_POINTER, "FreeRDP_RdpServerCertificate" },
{ FreeRDP_RdpServerRsaKey, FREERDP_SETTINGS_TYPE_POINTER, "FreeRDP_RdpServerRsaKey" },
{ FreeRDP_ReceivedCapabilities, FREERDP_SETTINGS_TYPE_POINTER, "FreeRDP_ReceivedCapabilities" },
{ FreeRDP_ReceivedCapabilityData, FREERDP_SETTINGS_TYPE_POINTER,
"FreeRDP_ReceivedCapabilityData" },
{ FreeRDP_ReceivedCapabilityDataSizes, FREERDP_SETTINGS_TYPE_POINTER,
"FreeRDP_ReceivedCapabilityDataSizes" },
{ FreeRDP_RedirectionPassword, FREERDP_SETTINGS_TYPE_POINTER, "FreeRDP_RedirectionPassword" },
{ FreeRDP_RedirectionTsvUrl, FREERDP_SETTINGS_TYPE_POINTER, "FreeRDP_RedirectionTsvUrl" },
{ FreeRDP_ServerAutoReconnectCookie, FREERDP_SETTINGS_TYPE_POINTER,

File diff suppressed because it is too large Load Diff

View File

@ -172,4 +172,6 @@ FREERDP_LOCAL BOOL rdp_send_demand_active(rdpRdp* rdp);
FREERDP_LOCAL BOOL rdp_recv_confirm_active(rdpRdp* rdp, wStream* s, UINT16 pduLength);
FREERDP_LOCAL BOOL rdp_send_confirm_active(rdpRdp* rdp);
BOOL rdp_read_capability_set(wStream* sub, UINT16 type, rdpSettings* settings, BOOL isServer);
#endif /* FREERDP_LIB_CORE_CAPABILITIES_H */

View File

@ -321,7 +321,20 @@ BOOL freerdp_capability_buffer_allocate(rdpSettings* settings, UINT32 count)
memset(tmp, 0, count * sizeof(BYTE));
settings->ReceivedCapabilities = tmp;
return settings->ReceivedCapabilities != NULL;
tmp = realloc(settings->ReceivedCapabilityData, count * sizeof(BYTE*));
if (!tmp)
return FALSE;
memset(tmp, 0, count * sizeof(BYTE*));
settings->ReceivedCapabilityData = tmp;
tmp = realloc(settings->ReceivedCapabilityDataSizes, count * sizeof(UINT32));
if (!tmp)
return FALSE;
memset(tmp, 0, count * sizeof(UINT32));
settings->ReceivedCapabilityDataSizes = tmp;
return (settings->ReceivedCapabilities && settings->ReceivedCapabilityData &&
settings->ReceivedCapabilityDataSizes);
}
rdpSettings* freerdp_settings_new(DWORD flags)
@ -1027,7 +1040,6 @@ BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
_settings->ChannelDefArray = NULL;
_settings->MonitorDefArray = NULL;
_settings->MonitorIds = NULL;
_settings->ReceivedCapabilities = NULL;
_settings->OrderSupport = NULL;
_settings->BitmapCacheV2CellInfo = NULL;
_settings->GlyphCache = NULL;
@ -1041,6 +1053,9 @@ BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
_settings->DeviceArray = NULL;
_settings->StaticChannelArray = NULL;
_settings->DynamicChannelArray = NULL;
_settings->ReceivedCapabilities = NULL;
_settings->ReceivedCapabilityData = NULL;
_settings->ReceivedCapabilityDataSizes = NULL;
_settings->XSelectionAtom = NULL;
if (!rc)

View File

@ -180,6 +180,11 @@ static const size_t bool_list_indices[] = {
#define have_uint16_list_indices
static const size_t uint16_list_indices[] = {
FreeRDP_CapsGeneralCompressionLevel,
FreeRDP_CapsGeneralCompressionTypes,
FreeRDP_CapsProtocolVersion,
FreeRDP_CapsRemoteUnshareFlag,
FreeRDP_CapsUpdateCapabilityFlag,
FreeRDP_DesktopOrientation,
FreeRDP_ProxyPort,
FreeRDP_TLSMaxVersion,
@ -428,6 +433,8 @@ static const size_t pointer_list_indices[] = {
FreeRDP_RdpServerCertificate,
FreeRDP_RdpServerRsaKey,
FreeRDP_ReceivedCapabilities,
FreeRDP_ReceivedCapabilityData,
FreeRDP_ReceivedCapabilityDataSizes,
FreeRDP_RedirectionPassword,
FreeRDP_RedirectionTsvUrl,
FreeRDP_ServerAutoReconnectCookie,