[core] implemented CS_CORE::EarlyCapabilityFlags filter

* Added missing definitions for RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN
  and RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED flags
* Updated stringification functions for these flags
* Implemented client and server EarlyCapabilityFlags filter for
  these flags as FreeRDP currently does not implement them.
This commit is contained in:
akallabeth 2023-01-19 15:49:05 +01:00 committed by Martin Fleisz
parent 22da7c532c
commit 2fc5eaeb80
2 changed files with 121 additions and 44 deletions

View File

@ -153,11 +153,13 @@ typedef enum
#define RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL 0x0100
#define RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE 0x0200
#define RNS_UD_CS_SUPPORT_HEARTBEAT_PDU 0x0400
#define RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN 0x0800
/* Early Capability Flags (Server to Client) */
#define RNS_UD_SC_EDGE_ACTIONS_SUPPORTED 0x00000001
#define RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 0x00000001
#define RNS_UD_SC_DYNAMIC_DST_SUPPORTED 0x00000002
#define RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2 0x00000004
#define RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED 0x00000008
/* Cluster Information Flags */
#define REDIRECTION_SUPPORTED 0x00000001

View File

@ -86,49 +86,73 @@ static const rdpSettings* mcs_get_const_settings(const rdpMcs* mcs)
return context->settings;
}
static void append(char* buffer, size_t size, const char* what)
static char* rdp_early_server_caps_string(UINT32 flags, char* buffer, size_t size)
{
winpr_str_append(what, buffer, size, "|");
char msg[32] = { 0 };
const UINT32 mask = RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 | RNS_UD_SC_DYNAMIC_DST_SUPPORTED |
RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2 | RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED;
const UINT32 unknown = flags & (~mask);
if (flags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1)
winpr_str_append("RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1", buffer, size, "|");
if (flags & RNS_UD_SC_DYNAMIC_DST_SUPPORTED)
winpr_str_append("RNS_UD_SC_DYNAMIC_DST_SUPPORTED", buffer, size, "|");
if (flags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2)
winpr_str_append("RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2", buffer, size, "|");
if (flags & RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED)
winpr_str_append("RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED", buffer, size, "|");
if (unknown != 0)
{
_snprintf(msg, sizeof(msg), "RNS_UD_SC_UNKNOWN[0x%08" PRIx32 "]", unknown);
winpr_str_append(msg, buffer, size, "|");
}
_snprintf(msg, sizeof(msg), "[0x%08" PRIx32 "]", flags);
winpr_str_append(msg, buffer, size, "|");
return buffer;
}
static const char* rdp_early_caps_string(UINT16 flags, char* buffer, size_t size)
static const char* rdp_early_client_caps_string(UINT32 flags, char* buffer, size_t size)
{
char number[32] = { 0 };
const UINT16 mask =
~(RNS_UD_CS_SUPPORT_ERRINFO_PDU | RNS_UD_CS_WANT_32BPP_SESSION |
RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS |
RNS_UD_CS_VALID_CONNECTION_TYPE | RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU |
RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT | RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL |
RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE | RNS_UD_CS_SUPPORT_HEARTBEAT_PDU);
char msg[32] = { 0 };
const UINT32 mask = RNS_UD_CS_SUPPORT_ERRINFO_PDU | RNS_UD_CS_WANT_32BPP_SESSION |
RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS |
RNS_UD_CS_VALID_CONNECTION_TYPE | RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU |
RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT |
RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL | RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE |
RNS_UD_CS_SUPPORT_HEARTBEAT_PDU | RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN;
const UINT32 unknown = flags & (~mask);
if (flags & RNS_UD_CS_SUPPORT_ERRINFO_PDU)
append(buffer, size, "RNS_UD_CS_SUPPORT_ERRINFO_PDU");
winpr_str_append("RNS_UD_CS_SUPPORT_ERRINFO_PDU", buffer, size, "|");
if (flags & RNS_UD_CS_WANT_32BPP_SESSION)
append(buffer, size, "RNS_UD_CS_WANT_32BPP_SESSION");
winpr_str_append("RNS_UD_CS_WANT_32BPP_SESSION", buffer, size, "|");
if (flags & RNS_UD_CS_SUPPORT_STATUSINFO_PDU)
append(buffer, size, "RNS_UD_CS_SUPPORT_STATUSINFO_PDU");
winpr_str_append("RNS_UD_CS_SUPPORT_STATUSINFO_PDU", buffer, size, "|");
if (flags & RNS_UD_CS_STRONG_ASYMMETRIC_KEYS)
append(buffer, size, "RNS_UD_CS_STRONG_ASYMMETRIC_KEYS");
winpr_str_append("RNS_UD_CS_STRONG_ASYMMETRIC_KEYS", buffer, size, "|");
if (flags & RNS_UD_CS_VALID_CONNECTION_TYPE)
append(buffer, size, "RNS_UD_CS_VALID_CONNECTION_TYPE");
winpr_str_append("RNS_UD_CS_VALID_CONNECTION_TYPE", buffer, size, "|");
if (flags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU)
append(buffer, size, "RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU");
winpr_str_append("RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU", buffer, size, "|");
if (flags & RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT)
append(buffer, size, "RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT");
winpr_str_append("RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT", buffer, size, "|");
if (flags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL)
append(buffer, size, "RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL");
winpr_str_append("RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL", buffer, size, "|");
if (flags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE)
append(buffer, size, "RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE");
winpr_str_append("RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE", buffer, size, "|");
if (flags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU)
append(buffer, size, "RNS_UD_CS_SUPPORT_HEARTBEAT_PDU");
if (flags & mask)
append(buffer, size, "RNS_UD_UNKNOWN_FLAG");
if (flags == 0)
append(buffer, size, "NO_FLAG_SET");
_snprintf(number, sizeof(number), " [0x%04" PRIx16 "]", flags);
append(buffer, size, number);
winpr_str_append("RNS_UD_CS_SUPPORT_HEARTBEAT_PDU", buffer, size, "|");
if (flags & RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN)
winpr_str_append("RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN", buffer, size, "|");
if (unknown != 0)
{
_snprintf(msg, sizeof(msg), "RNS_UD_CS_UNKNOWN[0x%08" PRIx32 "]", unknown);
winpr_str_append(msg, buffer, size, "|");
}
_snprintf(msg, sizeof(msg), "[0x%08" PRIx32 "]", flags);
winpr_str_append(msg, buffer, size, "|");
return buffer;
}
@ -829,9 +853,59 @@ BOOL gcc_write_user_data_header(wStream* s, UINT16 type, UINT16 length)
return TRUE;
}
static UINT16 earlyCapsFromSettings(const rdpSettings* settings)
static UINT32 filterAndLogEarlyServerCapabilityFlags(UINT32 flags)
{
UINT16 earlyCapabilityFlags = settings->EarlyCapabilityFlags;
const UINT32 mask =
(RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 | RNS_UD_SC_DYNAMIC_DST_SUPPORTED |
RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2); // TODO: Not implemented
// RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED
const UINT32 filtered = flags & mask;
const UINT32 unknown = flags & (~mask);
if (unknown != 0)
{
char buffer[256] = { 0 };
WLog_WARN(TAG,
"TS_UD_SC_CORE::EarlyCapabilityFlags [0x%08" PRIx32 " & 0x%08" PRIx32
" --> 0x%08" PRIx32 "] filtering %s, feature not implemented",
flags, ~mask, unknown,
rdp_early_server_caps_string(unknown, buffer, sizeof(buffer)));
}
return filtered;
}
static UINT32 earlyServerCapsFromSettings(const rdpSettings* settings)
{
UINT32 EarlyCapabilityFlags = settings->EarlyCapabilityFlags;
return filterAndLogEarlyServerCapabilityFlags(EarlyCapabilityFlags);
}
static UINT16 filterAndLogEarlyClientCapabilityFlags(UINT32 flags)
{
const UINT32 mask =
(RNS_UD_CS_SUPPORT_ERRINFO_PDU | RNS_UD_CS_WANT_32BPP_SESSION |
RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS |
RNS_UD_CS_VALID_CONNECTION_TYPE | RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU |
RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT | RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL |
RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE |
RNS_UD_CS_SUPPORT_HEARTBEAT_PDU); // unsupported RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN
const UINT32 filtered = flags & mask;
const UINT32 unknown = flags & ~mask;
if (unknown != 0)
{
char buffer[256] = { 0 };
WLog_WARN(TAG,
"(TS_UD_CS_CORE)::EarlyCapabilityFlags [0x%08" PRIx32 " & 0x%08" PRIx32
" --> 0x%08" PRIx32 "] filtering %s, feature not implemented",
flags, ~mask, unknown,
rdp_early_client_caps_string(unknown, buffer, sizeof(buffer)));
}
return filtered;
}
static UINT16 earlyClientCapsFromSettings(const rdpSettings* settings)
{
WINPR_ASSERT(settings);
UINT32 earlyCapabilityFlags = settings->EarlyCapabilityFlags;
WINPR_ASSERT(settings);
if (settings->SupportErrorInfoPdu)
@ -861,7 +935,7 @@ static UINT16 earlyCapsFromSettings(const rdpSettings* settings)
if (settings->SupportStatusInfoPdu)
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_STATUSINFO_PDU;
return earlyCapabilityFlags;
return filterAndLogEarlyClientCapabilityFlags(earlyCapabilityFlags);
}
static BOOL updateEarlyClientCaps(rdpSettings* settings, UINT32 earlyCapabilityFlags,
@ -896,7 +970,9 @@ static BOOL updateEarlyClientCaps(rdpSettings* settings, UINT32 earlyCapabilityF
if (!(earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE))
connectionType = 0;
settings->ConnectionType = connectionType;
settings->EarlyCapabilityFlags = earlyCapabilityFlags;
filterAndLogEarlyClientCapabilityFlags(earlyCapabilityFlags);
return TRUE;
}
@ -909,7 +985,8 @@ static BOOL updateEarlyServerCaps(rdpSettings* settings, UINT32 earlyCapabilityF
settings->SupportDynamicTimeZone && (earlyCapabilityFlags & RNS_UD_SC_DYNAMIC_DST_SUPPORTED)
? TRUE
: FALSE;
settings->EarlyCapabilityFlags = earlyCapabilityFlags;
filterAndLogEarlyServerCapabilityFlags(earlyCapabilityFlags);
return TRUE;
}
@ -1015,7 +1092,6 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
break;
Stream_Read_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
settings->EarlyCapabilityFlags = (UINT32)earlyCapabilityFlags;
blockLength -= 2;
/* clientDigProductId (64 bytes): Contains a value that uniquely identifies the client */
@ -1149,8 +1225,8 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, clientColorDepth);
WLog_DBG(TAG, "Received EarlyCapabilityFlags=%s",
rdp_early_caps_string(earlyCapabilityFlags, buffer, sizeof(buffer)));
settings->EarlyCapabilityFlags = earlyCapabilityFlags;
rdp_early_client_caps_string(earlyCapabilityFlags, buffer, sizeof(buffer)));
return updateEarlyClientCaps(settings, earlyCapabilityFlags, connectionType);
}
@ -1216,7 +1292,7 @@ BOOL gcc_write_client_core_data(wStream* s, const rdpMcs* mcs)
Stream_Write_UINT32(s, 0); /* serialNumber (should be initialized to 0) */
highColorDepth = MIN(freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth), 24);
supportedColorDepths = RNS_UD_24BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT;
earlyCapabilityFlags = earlyCapsFromSettings(settings);
earlyCapabilityFlags = earlyClientCapsFromSettings(settings);
connectionType = settings->ConnectionType;
@ -1230,7 +1306,7 @@ BOOL gcc_write_client_core_data(wStream* s, const rdpMcs* mcs)
"Sending highColorDepth=0x%04" PRIx16 ", supportedColorDepths=0x%04" PRIx16
", earlyCapabilityFlags=%s",
highColorDepth, supportedColorDepths,
rdp_early_caps_string(earlyCapabilityFlags, buffer, sizeof(buffer)));
rdp_early_client_caps_string(earlyCapabilityFlags, buffer, sizeof(buffer)));
Stream_Write_UINT16(s, highColorDepth); /* highColorDepth */
Stream_Write_UINT16(s, supportedColorDepths); /* supportedColorDepths */
Stream_Write_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
@ -1261,6 +1337,7 @@ BOOL gcc_write_client_core_data(wStream* s, const rdpMcs* mcs)
BOOL gcc_read_server_core_data(wStream* s, rdpMcs* mcs)
{
UINT32 serverVersion;
UINT32 EarlyCapabilityFlags = 0;
rdpSettings* settings = mcs_get_settings(mcs);
WINPR_ASSERT(s);
@ -1281,13 +1358,12 @@ BOOL gcc_read_server_core_data(wStream* s, rdpMcs* mcs)
{
char buffer[2048] = { 0 };
Stream_Read_UINT32(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags */
Stream_Read_UINT32(s, EarlyCapabilityFlags); /* earlyCapabilityFlags */
WLog_DBG(TAG, "Received EarlyCapabilityFlags=%s",
rdp_early_caps_string(settings->EarlyCapabilityFlags, buffer, sizeof(buffer)));
rdp_early_client_caps_string(EarlyCapabilityFlags, buffer, sizeof(buffer)));
}
return updateEarlyServerCaps(settings, settings->EarlyCapabilityFlags,
settings->ConnectionType);
return updateEarlyServerCaps(settings, EarlyCapabilityFlags, settings->ConnectionType);
}
/* TODO: This function modifies rdpMcs
@ -1295,7 +1371,6 @@ BOOL gcc_read_server_core_data(wStream* s, rdpMcs* mcs)
*/
BOOL gcc_write_server_core_data(wStream* s, rdpMcs* mcs)
{
UINT32 earlyCapabilityFlags;
rdpSettings* settings = mcs_get_settings(mcs);
WINPR_ASSERT(s);
@ -1305,11 +1380,11 @@ BOOL gcc_write_server_core_data(wStream* s, rdpMcs* mcs)
return FALSE;
updateEarlyServerCaps(settings, settings->EarlyCapabilityFlags, settings->ConnectionType);
earlyCapabilityFlags = settings->EarlyCapabilityFlags;
const UINT32 EarlyCapabilityFlags = earlyServerCapsFromSettings(settings);
Stream_Write_UINT32(s, settings->RdpVersion); /* version (4 bytes) */
Stream_Write_UINT32(s, settings->RequestedProtocols); /* clientRequestedProtocols (4 bytes) */
Stream_Write_UINT32(s, earlyCapabilityFlags); /* earlyCapabilityFlags (4 bytes) */
Stream_Write_UINT32(s, EarlyCapabilityFlags); /* earlyCapabilityFlags (4 bytes) */
return TRUE;
}