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_CLUSTER 0xC004
#define CS_MONITOR 0xC005 #define CS_MONITOR 0xC005
#define CS_MCS_MSGCHANNEL 0xC006 #define CS_MCS_MSGCHANNEL 0xC006
#define CS_MULTITRANSPORT 0xC008 #define CS_MONITOR_EX 0xC008
#define CS_MULTITRANSPORT 0xC00A
/* Server to Client (SC) data blocks */ /* Server to Client (SC) data blocks */
#define SC_CORE 0x0C01 #define SC_CORE 0x0C01
@ -408,6 +409,16 @@ struct _MONITOR_DEF
}; };
typedef struct _MONITOR_DEF 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 */ /* Device Redirection */
#define RDPDR_DTYP_SERIAL 0x00000001 #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 type;
UINT16 blockLength; UINT16 blockLength;
int pos; int begPos, endPos;
while (length > 0) while (length > 0)
{ {
pos = Stream_GetPosition(s); begPos = Stream_GetPosition(s);
if(!gcc_read_user_data_header(s, &type, &blockLength))
if (!gcc_read_user_data_header(s, &type, &blockLength))
return FALSE;
if (Stream_GetRemainingLength(s) < (blockLength - 4))
return FALSE; return FALSE;
switch (type) switch (type)
@ -354,12 +358,37 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length)
return FALSE; return FALSE;
break; 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: default:
fprintf(stderr, "Unknown GCC client data block: 0x%04X\n", type);
Stream_Seek(s, blockLength - 4);
break; 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; length -= blockLength;
Stream_SetPosition(s, pos + blockLength); Stream_SetPosition(s, begPos + blockLength);
} }
return TRUE; return TRUE;
@ -506,20 +535,25 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe
UINT16 highColorDepth = 0; UINT16 highColorDepth = 0;
UINT16 supportedColorDepths = 0; UINT16 supportedColorDepths = 0;
UINT32 serverSelectedProtocol = 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 */ /* Length of all required fields, until imeFileName */
if (blockLength < 128) if (blockLength < 128)
return FALSE; return FALSE;
Stream_Read_UINT32(s, version); /* version */ Stream_Read_UINT32(s, version); /* version (4 bytes) */
settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7); settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7);
Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth */ Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth (2 bytes) */
Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight */ Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight (2 bytes) */
Stream_Read_UINT16(s, colorDepth); /* ColorDepth */ Stream_Read_UINT16(s, colorDepth); /* ColorDepth (2 bytes) */
Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) */ Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) (2 bytes) */
Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */ Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout (4 bytes) */
Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild */ Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild (4 bytes) */
/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL); 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); free(str);
str = NULL; str = NULL;
Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType */ Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType (4 bytes) */
Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */ Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType (4 bytes) */
Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey */ Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey (4 bytes) */
Stream_Seek(s, 64); /* imeFileName */ Stream_Seek(s, 64); /* imeFileName (64 bytes) */
blockLength -= 128; blockLength -= 128;
@ -548,56 +582,81 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe
{ {
if (blockLength < 2) if (blockLength < 2)
break; break;
Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */ Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth (2 bytes) */
blockLength -= 2; blockLength -= 2;
if (blockLength < 2) if (blockLength < 2)
break; break;
Stream_Seek_UINT16(s); /* clientProductID */ Stream_Seek_UINT16(s); /* clientProductID (2 bytes) */
blockLength -= 2; blockLength -= 2;
if (blockLength < 4) if (blockLength < 4)
break; break;
Stream_Seek_UINT32(s); /* serialNumber */ Stream_Seek_UINT32(s); /* serialNumber (4 bytes) */
blockLength -= 4; blockLength -= 4;
if (blockLength < 2) if (blockLength < 2)
break; break;
Stream_Read_UINT16(s, highColorDepth); /* highColorDepth */ Stream_Read_UINT16(s, highColorDepth); /* highColorDepth (2 bytes) */
blockLength -= 2; blockLength -= 2;
if (blockLength < 2) if (blockLength < 2)
break; break;
Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths */ Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths (2 bytes) */
blockLength -= 2; blockLength -= 2;
if (blockLength < 2) if (blockLength < 2)
break; break;
Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags */ Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
blockLength -= 2; blockLength -= 2;
if (blockLength < 64) if (blockLength < 64)
break; break;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL); 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); sprintf_s(settings->ClientProductId, 32, "%s", str);
free(str); free(str);
blockLength -= 64; blockLength -= 64;
if (blockLength < 1) if (blockLength < 1)
break; break;
Stream_Read_UINT8(s, settings->PerformanceFlags); /* connectionType */ Stream_Read_UINT8(s, settings->PerformanceFlags); /* connectionType (1 byte) */
blockLength -= 1; blockLength -= 1;
if (blockLength < 1) if (blockLength < 1)
break; break;
Stream_Seek_UINT8(s); /* pad1octet */ Stream_Seek_UINT8(s); /* pad1octet (1 byte) */
blockLength -= 1; blockLength -= 1;
if (blockLength < 4) if (blockLength < 4)
break; 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; blockLength -= 4;
if (settings->SelectedProtocol != serverSelectedProtocol) if (settings->SelectedProtocol != serverSelectedProtocol)
@ -772,7 +831,7 @@ BOOL gcc_read_server_core_data(wStream* s, rdpSettings* settings)
UINT32 version; UINT32 version;
UINT32 clientRequestedProtocols; UINT32 clientRequestedProtocols;
if(Stream_GetRemainingLength(s) < 8) if (Stream_GetRemainingLength(s) < 8)
return FALSE; return FALSE;
Stream_Read_UINT32(s, version); /* version */ Stream_Read_UINT32(s, version); /* version */
Stream_Read_UINT32(s, clientRequestedProtocols); /* clientRequestedProtocols */ Stream_Read_UINT32(s, clientRequestedProtocols); /* clientRequestedProtocols */
@ -1138,23 +1197,25 @@ BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings)
UINT16 channelCount, channelsToTreat; UINT16 channelCount, channelsToTreat;
UINT16 channelId; UINT16 channelId;
if(Stream_GetRemainingLength(s) < 4) if (Stream_GetRemainingLength(s) < 4)
return FALSE; return FALSE;
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */ Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
Stream_Read_UINT16(s, channelCount); /* channelCount */ Stream_Read_UINT16(s, channelCount); /* channelCount */
channelsToTreat = channelCount; channelsToTreat = channelCount;
if (channelCount != settings->ChannelCount) if (channelCount != settings->ChannelCount)
{ {
fprintf(stderr, "requested %d channels, got %d instead\n", fprintf(stderr, "requested %d channels, got %d instead\n",
settings->ChannelCount, channelCount); 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) if (channelCount > settings->ChannelCount)
channelsToTreat = settings->ChannelCount; channelsToTreat = settings->ChannelCount;
} }
if(Stream_GetRemainingLength(s) < channelCount * 2) if (Stream_GetRemainingLength(s) < channelCount * 2)
return FALSE; return FALSE;
for (i = 0; i < channelsToTreat; i++) 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) BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
{ {
UINT32 flags; UINT32 flags;
UINT32 redirectedSessionId;
if (blockLength < 4) if (blockLength < 8)
return FALSE; return FALSE;
Stream_Read_UINT32(s, flags); /* flags */ Stream_Read_UINT32(s, flags); /* flags */
Stream_Read_UINT32(s, redirectedSessionId); /* redirectedSessionId */
if ((flags & REDIRECTED_SESSIONID_FIELD_VALID)) if (flags & REDIRECTED_SESSIONID_FIELD_VALID)
{ settings->RedirectedSessionId = redirectedSessionId;
if(blockLength < 8)
return FALSE;
Stream_Read_UINT32(s, settings->RedirectedSessionId); /* redirectedSessionID */
}
return TRUE; 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) 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; 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); void gcc_write_conference_create_request(wStream* s, wStream* user_data);
BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings); BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings);
void gcc_write_conference_create_response(wStream* s, wStream* user_data); void gcc_write_conference_create_response(wStream* s, wStream* user_data);
BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings *settings, int length); BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length);
void gcc_write_client_data_blocks(wStream* s, rdpSettings *settings); void gcc_write_client_data_blocks(wStream* s, rdpSettings* settings);
BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings *settings, int length); BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length);
void gcc_write_server_data_blocks(wStream* s, rdpSettings *settings); void gcc_write_server_data_blocks(wStream* s, rdpSettings* settings);
BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length); BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length);
void gcc_write_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); BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_core_data(wStream* s, rdpSettings *settings); void gcc_write_client_core_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_server_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); void gcc_write_server_core_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_security_data(wStream* s, rdpSettings *settings, UINT16 blockLength); BOOL gcc_read_client_security_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_security_data(wStream* s, rdpSettings *settings); void gcc_write_client_security_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_server_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); void gcc_write_server_security_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_network_data(wStream* s, rdpSettings *settings, UINT16 blockLength); BOOL gcc_read_client_network_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_network_data(wStream* s, rdpSettings *settings); void gcc_write_client_network_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_server_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); void gcc_write_server_network_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings *settings, UINT16 blockLength); BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_cluster_data(wStream* s, rdpSettings *settings); void gcc_write_client_cluster_data(wStream* s, rdpSettings* settings);
BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings *settings, UINT16 blockLength); BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
void gcc_write_client_monitor_data(wStream* s, rdpSettings *settings); 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 */ #endif /* FREERDP_CORE_GCC_H */