libfreerdp-core: fix and update parsing of server-side GCC client data blocks

This commit is contained in:
Marc-André Moreau 2014-01-23 16:00:02 -05:00
parent 83b9431dd0
commit 38b125f336
3 changed files with 238 additions and 58 deletions

View File

@ -51,7 +51,8 @@
#define CS_CLUSTER 0xC004
#define CS_MONITOR 0xC005
#define CS_MCS_MSGCHANNEL 0xC006
#define CS_MULTITRANSPORT 0xC008
#define CS_MONITOR_EX 0xC008
#define CS_MULTITRANSPORT 0xC00A
/* Server to Client (SC) data blocks */
#define SC_CORE 0x0C01
@ -408,6 +409,16 @@ struct _MONITOR_DEF
};
typedef struct _MONITOR_DEF MONITOR_DEF;
struct _MONITOR_ATTRIBUTES
{
UINT32 physicalWidth;
UINT32 physicalHeight;
UINT32 orientation;
UINT32 desktopScaleFactor;
UINT32 deviceScaleFactor;
};
typedef struct _MONITOR_ATTRIBUTES MONITOR_ATTRIBUTES;
/* Device Redirection */
#define RDPDR_DTYP_SERIAL 0x00000001

View File

@ -319,12 +319,16 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length)
{
UINT16 type;
UINT16 blockLength;
int pos;
int begPos, endPos;
while (length > 0)
{
pos = Stream_GetPosition(s);
if(!gcc_read_user_data_header(s, &type, &blockLength))
begPos = Stream_GetPosition(s);
if (!gcc_read_user_data_header(s, &type, &blockLength))
return FALSE;
if (Stream_GetRemainingLength(s) < (blockLength - 4))
return FALSE;
switch (type)
@ -354,12 +358,37 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length)
return FALSE;
break;
case CS_MCS_MSGCHANNEL:
if (!gcc_read_client_message_channel_data(s, settings, blockLength - 4))
return FALSE;
break;
case CS_MONITOR_EX:
if (!gcc_read_client_monitor_extended_data(s, settings, blockLength - 4))
return FALSE;
break;
case CS_MULTITRANSPORT:
if (!gcc_read_client_multitransport_channel_data(s, settings, blockLength - 4))
return FALSE;
break;
default:
fprintf(stderr, "Unknown GCC client data block: 0x%04X\n", type);
Stream_Seek(s, blockLength - 4);
break;
}
endPos = Stream_GetPosition(s);
if (endPos != (begPos + blockLength))
{
fprintf(stderr, "Error parsing GCC client data block 0x%04X: Actual Offset: %d Expected Offset: %d\n",
type, endPos, begPos + blockLength);
}
length -= blockLength;
Stream_SetPosition(s, pos + blockLength);
Stream_SetPosition(s, begPos + blockLength);
}
return TRUE;
@ -506,20 +535,25 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe
UINT16 highColorDepth = 0;
UINT16 supportedColorDepths = 0;
UINT32 serverSelectedProtocol = 0;
UINT32 desktopPhysicalWidth = 0;
UINT32 desktopPhysicalHeight = 0;
UINT16 desktopOrientation = 0;
UINT32 desktopScaleFactor = 0;
UINT32 deviceScaleFactor = 0;
/* Length of all required fields, until imeFileName */
if (blockLength < 128)
return FALSE;
Stream_Read_UINT32(s, version); /* version */
Stream_Read_UINT32(s, version); /* version (4 bytes) */
settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7);
Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth */
Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight */
Stream_Read_UINT16(s, colorDepth); /* ColorDepth */
Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) */
Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */
Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild */
Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth (2 bytes) */
Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight (2 bytes) */
Stream_Read_UINT16(s, colorDepth); /* ColorDepth (2 bytes) */
Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) (2 bytes) */
Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout (4 bytes) */
Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild (4 bytes) */
/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL);
@ -529,11 +563,11 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe
free(str);
str = NULL;
Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType */
Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */
Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey */
Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType (4 bytes) */
Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType (4 bytes) */
Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey (4 bytes) */
Stream_Seek(s, 64); /* imeFileName */
Stream_Seek(s, 64); /* imeFileName (64 bytes) */
blockLength -= 128;
@ -548,56 +582,81 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe
{
if (blockLength < 2)
break;
Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */
Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth (2 bytes) */
blockLength -= 2;
if (blockLength < 2)
break;
Stream_Seek_UINT16(s); /* clientProductID */
Stream_Seek_UINT16(s); /* clientProductID (2 bytes) */
blockLength -= 2;
if (blockLength < 4)
break;
Stream_Seek_UINT32(s); /* serialNumber */
Stream_Seek_UINT32(s); /* serialNumber (4 bytes) */
blockLength -= 4;
if (blockLength < 2)
break;
Stream_Read_UINT16(s, highColorDepth); /* highColorDepth */
Stream_Read_UINT16(s, highColorDepth); /* highColorDepth (2 bytes) */
blockLength -= 2;
if (blockLength < 2)
break;
Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths */
Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths (2 bytes) */
blockLength -= 2;
if (blockLength < 2)
break;
Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags */
Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
blockLength -= 2;
if (blockLength < 64)
break;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL);
Stream_Seek(s, 64);
Stream_Seek(s, 64); /* clientDigProductId (64 bytes) */
sprintf_s(settings->ClientProductId, 32, "%s", str);
free(str);
blockLength -= 64;
if (blockLength < 1)
break;
Stream_Read_UINT8(s, settings->PerformanceFlags); /* connectionType */
Stream_Read_UINT8(s, settings->PerformanceFlags); /* connectionType (1 byte) */
blockLength -= 1;
if (blockLength < 1)
break;
Stream_Seek_UINT8(s); /* pad1octet */
Stream_Seek_UINT8(s); /* pad1octet (1 byte) */
blockLength -= 1;
if (blockLength < 4)
break;
Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol */
Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol (4 bytes) */
blockLength -= 4;
if (blockLength < 4)
break;
Stream_Read_UINT32(s, desktopPhysicalWidth); /* desktopPhysicalWidth (4 bytes) */
blockLength -= 4;
if (blockLength < 4)
break;
Stream_Read_UINT32(s, desktopPhysicalHeight); /* desktopPhysicalHeight (4 bytes) */
blockLength -= 4;
if (blockLength < 2)
break;
Stream_Read_UINT16(s, desktopOrientation); /* desktopOrientation (2 bytes) */
blockLength -= 2;
if (blockLength < 4)
break;
Stream_Read_UINT32(s, desktopScaleFactor); /* desktopScaleFactor (4 bytes) */
blockLength -= 4;
if (blockLength < 4)
break;
Stream_Read_UINT32(s, deviceScaleFactor); /* deviceScaleFactor (4 bytes) */
blockLength -= 4;
if (settings->SelectedProtocol != serverSelectedProtocol)
@ -772,7 +831,7 @@ BOOL gcc_read_server_core_data(wStream* s, rdpSettings* settings)
UINT32 version;
UINT32 clientRequestedProtocols;
if(Stream_GetRemainingLength(s) < 8)
if (Stream_GetRemainingLength(s) < 8)
return FALSE;
Stream_Read_UINT32(s, version); /* version */
Stream_Read_UINT32(s, clientRequestedProtocols); /* clientRequestedProtocols */
@ -1138,23 +1197,25 @@ BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings)
UINT16 channelCount, channelsToTreat;
UINT16 channelId;
if(Stream_GetRemainingLength(s) < 4)
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
Stream_Read_UINT16(s, channelCount); /* channelCount */
channelsToTreat = channelCount;
if (channelCount != settings->ChannelCount)
{
fprintf(stderr, "requested %d channels, got %d instead\n",
settings->ChannelCount, channelCount);
// we ensure that the response is not bigger than the request
/* we ensure that the response is not bigger than the request */
if (channelCount > settings->ChannelCount)
channelsToTreat = settings->ChannelCount;
}
if(Stream_GetRemainingLength(s) < channelCount * 2)
if (Stream_GetRemainingLength(s) < channelCount * 2)
return FALSE;
for (i = 0; i < channelsToTreat; i++)
@ -1197,18 +1258,16 @@ void gcc_write_server_network_data(wStream* s, rdpSettings* settings)
BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
{
UINT32 flags;
UINT32 redirectedSessionId;
if (blockLength < 4)
if (blockLength < 8)
return FALSE;
Stream_Read_UINT32(s, flags); /* flags */
Stream_Read_UINT32(s, redirectedSessionId); /* redirectedSessionId */
if ((flags & REDIRECTED_SESSIONID_FIELD_VALID))
{
if(blockLength < 8)
return FALSE;
Stream_Read_UINT32(s, settings->RedirectedSessionId); /* redirectedSessionID */
}
if (flags & REDIRECTED_SESSIONID_FIELD_VALID)
settings->RedirectedSessionId = redirectedSessionId;
return TRUE;
}
@ -1244,7 +1303,34 @@ void gcc_write_client_cluster_data(wStream* s, rdpSettings* settings)
BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
{
fprintf(stderr, "CS_MONITOR\n");
UINT32 index;
UINT32 flags;
UINT32 monitorCount;
MONITOR_DEF* monitorDefArray;
if (blockLength < 8)
return FALSE;
Stream_Read_UINT32(s, flags); /* flags */
Stream_Read_UINT32(s, monitorCount); /* monitorCount */
if (blockLength < (8 + (monitorCount * 20)))
return FALSE;
monitorDefArray = (MONITOR_DEF*) malloc(sizeof(MONITOR_DEF) * monitorCount);
ZeroMemory(monitorDefArray, sizeof(MONITOR_DEF) * monitorCount);
for (index = 0; index < monitorCount; index++)
{
Stream_Read_UINT32(s, monitorDefArray[index].left); /* left */
Stream_Read_UINT32(s, monitorDefArray[index].top); /* top */
Stream_Read_UINT32(s, monitorDefArray[index].right); /* right */
Stream_Read_UINT32(s, monitorDefArray[index].bottom); /* bottom */
Stream_Read_UINT32(s, monitorDefArray[index].flags); /* flags */
}
free(monitorDefArray);
return TRUE;
}
@ -1285,3 +1371,80 @@ void gcc_write_client_monitor_data(wStream* s, rdpSettings* settings)
}
}
}
BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
{
UINT32 index;
UINT32 flags;
UINT32 monitorCount;
UINT32 monitorAttributeSize;
MONITOR_ATTRIBUTES* monitorAttributesArray;
if (blockLength < 8)
return FALSE;
Stream_Read_UINT32(s, flags); /* flags */
Stream_Read_UINT32(s, monitorAttributeSize); /* monitorAttributeSize */
Stream_Read_UINT32(s, monitorCount); /* monitorCount */
if (monitorAttributeSize != 20)
return FALSE;
if (blockLength < (12 + (monitorCount * monitorAttributeSize)))
return FALSE;
monitorAttributesArray = (MONITOR_ATTRIBUTES*) malloc(sizeof(MONITOR_ATTRIBUTES) * monitorCount);
ZeroMemory(monitorAttributesArray, sizeof(MONITOR_ATTRIBUTES) * monitorCount);
for (index = 0; index < monitorCount; index++)
{
Stream_Read_UINT32(s, monitorAttributesArray[index].physicalWidth); /* physicalWidth */
Stream_Read_UINT32(s, monitorAttributesArray[index].physicalHeight); /* physicalHeight */
Stream_Read_UINT32(s, monitorAttributesArray[index].orientation); /* orientation */
Stream_Read_UINT32(s, monitorAttributesArray[index].desktopScaleFactor); /* desktopScaleFactor */
Stream_Read_UINT32(s, monitorAttributesArray[index].deviceScaleFactor); /* deviceScaleFactor */
}
free(monitorAttributesArray);
return TRUE;
}
void gcc_write_client_monitor_extended_data(wStream* s, rdpSettings* settings)
{
}
BOOL gcc_read_client_message_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
{
UINT32 flags;
if (blockLength < 4)
return FALSE;
Stream_Read_UINT32(s, flags);
return TRUE;
}
void gcc_write_client_message_channel_data(wStream* s, rdpSettings* settings)
{
}
BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
{
UINT32 flags;
if (blockLength < 4)
return FALSE;
Stream_Read_UINT32(s, flags);
return TRUE;
}
void gcc_write_client_multitransport_channel_data(wStream* s, rdpSettings* settings)
{
}

View File

@ -33,27 +33,33 @@ BOOL gcc_read_conference_create_request(wStream* s, rdpSettings* settings);
void gcc_write_conference_create_request(wStream* s, wStream* user_data);
BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings);
void gcc_write_conference_create_response(wStream* s, wStream* user_data);
BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings *settings, int length);
void gcc_write_client_data_blocks(wStream* s, rdpSettings *settings);
BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings *settings, int length);
void gcc_write_server_data_blocks(wStream* s, rdpSettings *settings);
BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length);
void gcc_write_client_data_blocks(wStream* s, rdpSettings* settings);
BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length);
void gcc_write_server_data_blocks(wStream* s, rdpSettings* settings);
BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length);
void gcc_write_user_data_header(wStream* s, UINT16 type, UINT16 length);
BOOL gcc_read_client_core_data(wStream* s, rdpSettings *settings, UINT16 blockLength);
void gcc_write_client_core_data(wStream* s, rdpSettings *settings);
BOOL gcc_read_server_core_data(wStream* s, rdpSettings *settings);
void gcc_write_server_core_data(wStream* s, rdpSettings *settings);
BOOL gcc_read_client_security_data(wStream* s, rdpSettings *settings, UINT16 blockLength);
void gcc_write_client_security_data(wStream* s, rdpSettings *settings);
BOOL gcc_read_server_security_data(wStream* s, rdpSettings *settings);
void gcc_write_server_security_data(wStream* s, rdpSettings *settings);
BOOL gcc_read_client_network_data(wStream* s, rdpSettings *settings, UINT16 blockLength);
void gcc_write_client_network_data(wStream* s, rdpSettings *settings);
BOOL gcc_read_server_network_data(wStream* s, rdpSettings *settings);
void gcc_write_server_network_data(wStream* s, rdpSettings *settings);
BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings *settings, UINT16 blockLength);
void gcc_write_client_cluster_data(wStream* s, rdpSettings *settings);
BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings *settings, UINT16 blockLength);
void gcc_write_client_monitor_data(wStream* s, rdpSettings *settings);
BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_core_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_server_core_data(wStream* s, rdpSettings* settings);
void gcc_write_server_core_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_security_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_security_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_server_security_data(wStream* s, rdpSettings* settings);
void gcc_write_server_security_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_network_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_network_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings);
void gcc_write_server_network_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_cluster_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_monitor_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_monitor_extended_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_message_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_message_channel_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_multitransport_channel_data(wStream* s, rdpSettings* settings);
#endif /* FREERDP_CORE_GCC_H */