First cut at network characteristics auto-detect and multitransport protocol

This commit is contained in:
Mike McDonald 2014-01-23 18:01:31 -05:00
parent 3d75db05e9
commit 07083acc97
7 changed files with 237 additions and 19 deletions

View File

@ -51,13 +51,14 @@
#define CS_CLUSTER 0xC004
#define CS_MONITOR 0xC005
#define CS_MCS_MSGCHANNEL 0xC006
#define CS_MULTITRANSPORT 0xC008
#define CS_MULTITRANSPORT 0xC00A
/* Server to Client (SC) data blocks */
#define SC_CORE 0x0C01
#define SC_SECURITY 0x0C02
#define SC_NET 0x0C03
#define SC_MULTITRANSPORT 0x0C06
#define SC_MCS_MSGCHANNEL 0x0C04
#define SC_MULTITRANSPORT 0x0C08
/* RDP version */
#define RDP_VERSION_4 0x00080001
@ -493,6 +494,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_SupportMonitorLayoutPdu 141
#define FreeRDP_SupportGraphicsPipeline 142
#define FreeRDP_SupportDynamicTimeZone 143
#define FreeRDP_SupportHeartbeatPdu 144
#define FreeRDP_DisableEncryption 192
#define FreeRDP_EncryptionMethods 193
#define FreeRDP_ExtEncryptionMethods 194
@ -516,6 +518,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_DesktopPosX 390
#define FreeRDP_DesktopPosY 391
#define FreeRDP_MultitransportFlags 512
#define FreeRDP_SupportMultitransport 513
#define FreeRDP_AlternateShell 640
#define FreeRDP_ShellWorkingDirectory 641
#define FreeRDP_AutoLogonEnabled 704
@ -786,7 +789,8 @@ struct rdp_settings
ALIGN64 BOOL SupportMonitorLayoutPdu; /* 141 */
ALIGN64 BOOL SupportGraphicsPipeline; /* 142 */
ALIGN64 BOOL SupportDynamicTimeZone; /* 143 */
UINT64 padding0192[192 - 143]; /* 143 */
ALIGN64 BOOL SupportHeartbeatPdu; /* 144 */
UINT64 padding0192[192 - 145]; /* 145 */
/* Client/Server Security Data */
ALIGN64 BOOL DisableEncryption; /* 192 */
@ -831,7 +835,8 @@ struct rdp_settings
/* Client Multitransport Channel Data */
ALIGN64 UINT32 MultitransportFlags; /* 512 */
UINT64 padding0576[576 - 513]; /* 513 */
ALIGN64 BOOL SupportMultitransport; /* 513 */
UINT64 padding0576[576 - 514]; /* 514 */
UINT64 padding0640[640 - 576]; /* 576 */
/*
@ -1291,7 +1296,7 @@ struct rdp_settings
/* Extensions */
ALIGN64 int num_extensions; /* */
ALIGN64 struct rdp_ext_set extensions[16]; /* */
ALIGN64 BYTE* SettingsModified; /* byte array marking fields that have been modified from their default value */
};
typedef struct rdp_settings rdpSettings;

View File

@ -83,6 +83,10 @@ set(${MODULE_PREFIX}_SRCS
connection.h
redirection.c
redirection.h
autodetect.c
autodetect.h
multitransport.c
multitransport.h
timezone.c
timezone.h
rdp.c

View File

@ -366,10 +366,12 @@ void gcc_write_client_data_blocks(wStream* s, rdpSettings* settings)
if (settings->NegotiationFlags & EXTENDED_CLIENT_DATA_SUPPORTED)
{
if (!settings->SpanMonitors)
if (settings->SpanMonitors)
{
gcc_write_client_monitor_data(s, settings);
}
gcc_write_client_message_channel_data(s, settings);
gcc_write_client_multitransport_channel_data(s, settings);
}
else
{
@ -433,6 +435,22 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length)
}
break;
case SC_MCS_MSGCHANNEL:
if (!gcc_read_server_message_channel_data(s, settings))
{
fprintf(stderr, "gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed\n");
return FALSE;
}
break;
case SC_MULTITRANSPORT:
if (!gcc_read_server_multitransport_channel_data(s, settings))
{
fprintf(stderr, "gcc_read_server_data_blocks: gcc_read_server_multitransport_channel_data failed\n");
return FALSE;
}
break;
default:
fprintf(stderr, "gcc_read_server_data_blocks: ignoring type=%hu\n", type);
break;
@ -730,6 +748,9 @@ void gcc_write_client_core_data(wStream* s, rdpSettings* settings)
if (settings->NetworkAutoDetect)
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT;
if (settings->SupportHeartbeatPdu)
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_HEARTBEAT_PDU;
if (settings->SupportGraphicsPipeline)
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL;
@ -1270,3 +1291,103 @@ void gcc_write_client_monitor_data(wStream* s, rdpSettings* settings)
}
}
}
/**
* Read a client message channel data block (TS_UD_CS_MCS_MSGCHANNEL).\n
* @msdn{jj217627}
* @param s stream
* @param settings rdp settings
*/
BOOL gcc_read_client_message_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
{
fprintf(stderr, "CS_MCS_MSGCHANNEL\n");
return TRUE;
}
/**
* Write a client message channel data block (TS_UD_CS_MCS_MSGCHANNEL).\n
* @msdn{jj217627}
* @param s stream
* @param settings rdp settings
*/
void gcc_write_client_message_channel_data(wStream* s, rdpSettings* settings)
{
if (settings->NetworkAutoDetect ||
settings->SupportHeartbeatPdu ||
settings->SupportMultitransport)
{
gcc_write_user_data_header(s, CS_MCS_MSGCHANNEL, 8);
Stream_Write_UINT32(s, 0); /* flags */
}
}
BOOL gcc_read_server_message_channel_data(wStream* s, rdpSettings* settings)
{
freerdp* instance;
UINT16 MCSChannelId;
if (Stream_GetRemainingLength(s) < 2)
return FALSE;
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
/* Save the MCS message channel id */
instance = (freerdp*)settings->instance;
instance->context->rdp->mcs->message_channel_id = MCSChannelId;
return TRUE;
}
void gcc_write_server_message_channel_data(wStream* s, rdpSettings* settings)
{
fprintf(stderr, "SC_MCS_MSGCHANNEL\n");
}
/**
* Read a client multitransport channel data block (TS_UD_CS_MULTITRANSPORT).\n
* @msdn{jj217498}
* @param s stream
* @param settings rdp settings
*/
BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
{
fprintf(stderr, "CS_MULTITRANSPORT\n");
return TRUE;
}
/**
* Write a client multitransport channel data block (TS_UD_CS_MULTITRANSPORT).\n
* @msdn{jj217498}
* @param s stream
* @param settings rdp settings
*/
void gcc_write_client_multitransport_channel_data(wStream* s, rdpSettings* settings)
{
if (settings->MultitransportFlags != 0)
{
gcc_write_user_data_header(s, CS_MULTITRANSPORT, 8);
Stream_Write_UINT32(s, settings->MultitransportFlags); /* flags */
}
}
BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpSettings* settings)
{
UINT32 flags;
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
Stream_Read_UINT32(s, flags); /* flags */
return TRUE;
}
void gcc_write_server_multitransport_channel_data(wStream* s, rdpSettings* settings)
{
fprintf(stderr, "SC_MULTITRANSPORT\n");
}

View File

@ -55,5 +55,13 @@ BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings *settings, UINT16 bloc
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_message_channel_data(wStream* s, rdpSettings *settings, UINT16 blockLength);
void gcc_write_client_message_channel_data(wStream* s, rdpSettings *settings);
BOOL gcc_read_server_message_channel_data(wStream* s, rdpSettings *settings);
void gcc_write_server_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);
BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpSettings *settings);
void gcc_write_server_multitransport_channel_data(wStream* s, rdpSettings *settings);
#endif /* FREERDP_CORE_GCC_H */

View File

@ -115,6 +115,7 @@ typedef struct
struct rdp_mcs
{
UINT16 user_id;
UINT16 message_channel_id;
struct rdp_transport* transport;
DomainParameters domainParameters;
DomainParameters targetParameters;
@ -123,6 +124,7 @@ struct rdp_mcs
BOOL user_channel_joined;
BOOL global_channel_joined;
BOOL message_channel_joined;
};
typedef struct rdp_mcs rdpMcs;

View File

@ -229,6 +229,15 @@ wStream* rdp_data_pdu_init(rdpRdp* rdp)
return s;
}
wStream* rdp_message_channel_pdu_init(rdpRdp* rdp)
{
wStream* s;
s = transport_send_stream_init(rdp->transport, 2048);
Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
rdp_security_stream_init(rdp, s);
return s;
}
/**
* Read an RDP packet header.\n
* @param rdp rdp module
@ -328,13 +337,12 @@ void rdp_write_header(rdpRdp* rdp, wStream* s, UINT16 length, UINT16 channelId)
Stream_Write_UINT16_BE(s, length); /* userData (OCTET_STRING) */
}
static UINT32 rdp_security_stream_out(rdpRdp* rdp, wStream* s, int length)
static UINT32 rdp_security_stream_out(rdpRdp* rdp, wStream* s, int length, UINT32 sec_flags)
{
BYTE* data;
UINT32 sec_flags;
UINT32 pad = 0;
sec_flags = rdp->sec_flags;
sec_flags |= rdp->sec_flags;
if (sec_flags != 0)
{
@ -431,7 +439,7 @@ BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id)
Stream_Seek(s, sec_bytes);
Stream_SetPosition(s, secm);
length += rdp_security_stream_out(rdp, s, length);
length += rdp_security_stream_out(rdp, s, length, 0);
Stream_SetPosition(s, length);
Stream_SealLength(s);
@ -460,7 +468,7 @@ BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id)
rdp_write_share_control_header(s, length - sec_bytes, type, channel_id);
Stream_SetPosition(s, sec_hold);
length += rdp_security_stream_out(rdp, s, length);
length += rdp_security_stream_out(rdp, s, length, 0);
Stream_SetPosition(s, length);
Stream_SealLength(s);
@ -490,7 +498,34 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
rdp_write_share_data_header(s, length - sec_bytes, type, rdp->settings->ShareId);
Stream_SetPosition(s, sec_hold);
length += rdp_security_stream_out(rdp, s, length);
length += rdp_security_stream_out(rdp, s, length, 0);
Stream_SetPosition(s, length);
Stream_SealLength(s);
if (transport_write(rdp->transport, s) < 0)
return FALSE;
return TRUE;
}
BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags)
{
UINT16 length;
UINT32 sec_bytes;
int sec_hold;
length = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
rdp_write_header(rdp, s, length, rdp->mcs->message_channel_id);
sec_bytes = rdp_get_sec_bytes(rdp);
sec_hold = Stream_GetPosition(s);
Stream_Seek(s, sec_bytes);
Stream_SetPosition(s, sec_hold);
length += rdp_security_stream_out(rdp, s, length, sec_flags);
Stream_SetPosition(s, length);
Stream_SealLength(s);
@ -569,7 +604,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
#ifdef WITH_DEBUG_RDP
printf("recv %s Data PDU (0x%02X), length: %d\n",
type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
#endif
switch (type)
@ -672,6 +707,28 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
return 0;
}
int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s)
{
UINT16 securityFlags;
if (!rdp_read_security_header(s, &securityFlags))
return -1;
if (securityFlags & SEC_AUTODETECT_REQ)
{
/* Server Auto-Detect Request PDU */
return rdp_recv_autodetect_packet(rdp, s);
}
if (securityFlags & SEC_TRANSPORT_REQ)
{
/* Initiate Multitransport Request PDU */
return rdp_recv_multitransport_packet(rdp, s);
}
return -1;
}
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
{
UINT16 type;
@ -820,12 +877,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
}
}
if (channelId != MCS_GLOBAL_CHANNEL_ID)
{
if (!freerdp_channel_process(rdp->instance, s, channelId))
return -1;
}
else
if (channelId == MCS_GLOBAL_CHANNEL_ID)
{
while (Stream_GetRemainingLength(s) > 3)
{
@ -865,6 +917,15 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
Stream_SetPosition(s, nextPosition);
}
}
else if (channelId == rdp->mcs->message_channel_id)
{
return rdp_recv_message_channel_pdu(rdp, s);
}
else
{
if (!freerdp_channel_process(rdp->instance, s, channelId))
return -1;
}
return 0;
}
@ -1020,6 +1081,8 @@ rdpRdp* rdp_new(rdpContext* context)
rdp->nego = nego_new(rdp->transport);
rdp->mcs = mcs_new(rdp->transport);
rdp->redirection = redirection_new();
rdp->autodetect = autodetect_new();
rdp->multitransport = multitransport_new();
rdp->mppc_dec = mppc_dec_new();
rdp->mppc_enc = mppc_enc_new(PROTO_RDP_50);
}
@ -1092,6 +1155,8 @@ void rdp_free(rdpRdp* rdp)
nego_free(rdp->nego);
mcs_free(rdp->mcs);
redirection_free(rdp->redirection);
autodetect_free(rdp->autodetect);
multitransport_free(rdp->multitransport);
mppc_dec_free(rdp->mppc_dec);
mppc_enc_free(rdp->mppc_enc);
free(rdp);

View File

@ -34,6 +34,8 @@
#include "license.h"
#include "errinfo.h"
#include "extension.h"
#include "autodetect.h"
#include "multitransport.h"
#include "security.h"
#include "transport.h"
#include "connection.h"
@ -51,6 +53,8 @@
/* Security Header Flags */
#define SEC_EXCHANGE_PKT 0x0001
#define SEC_TRANSPORT_REQ 0x0002
#define SEC_TRANSPORT_RSP 0x0004
#define SEC_ENCRYPT 0x0008
#define SEC_RESET_SEQNO 0x0010
#define SEC_IGNORE_SEQNO 0x0020
@ -60,6 +64,9 @@
#define SEC_LICENSE_ENCRYPT_SC 0x0200
#define SEC_REDIRECTION_PKT 0x0400
#define SEC_SECURE_CHECKSUM 0x0800
#define SEC_AUTODETECT_REQ 0x1000
#define SEC_AUTODETECT_RSP 0x2000
#define SEC_HEARTBEAT 0x4000
#define SEC_FLAGSHI_VALID 0x8000
#define SEC_PKT_CS_MASK (SEC_EXCHANGE_PKT | SEC_INFO_PKT)
@ -131,6 +138,8 @@ struct rdp_rdp
rdpSettings* settings;
rdpTransport* transport;
rdpExtension* extension;
rdpAutoDetect* autodetect;
rdpMultitransport* multitransport;
struct rdp_mppc_dec* mppc_dec;
struct rdp_mppc_enc* mppc_enc;
struct crypto_rc4_struct* rc4_decrypt_key;
@ -191,6 +200,10 @@ BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id);
int rdp_send_channel_data(rdpRdp* rdp, int channel_id, BYTE* data, int size);
wStream* rdp_message_channel_pdu_init(rdpRdp* rdp);
BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags);
int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s);
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking);