From 6ba99a50f0b357cc24c1daa059e3b0e48ebafa14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 8 Jul 2011 00:37:25 -0400 Subject: [PATCH] libfreerdp-core: added unit tests for GCC and MCS --- cunit/test_ber.c | 4 +- cunit/test_gcc.c | 104 +++++++++++++++++++++++++++++++++++++ cunit/test_gcc.h | 4 ++ cunit/test_mcs.c | 41 ++++++++++----- include/freerdp/settings.h | 18 ++++++- libfreerdp-core/gcc.c | 61 ++++++++++++++++------ libfreerdp-core/mcs.c | 6 +-- libfreerdp-core/settings.c | 18 ++++++- libfreerdp-core/tpdu.c | 5 +- libfreerdp-core/tpdu.h | 2 +- 10 files changed, 224 insertions(+), 39 deletions(-) diff --git a/cunit/test_ber.c b/cunit/test_ber.c index 719f79f77..19ec7460c 100644 --- a/cunit/test_ber.c +++ b/cunit/test_ber.c @@ -65,14 +65,14 @@ void test_ber_write_length(void) } /* BOOLEAN, length 1, without value */ -uint8 ber_universal_tag_expected[2] = "\x01\x01"; +uint8 ber_universal_tag_expected[1] = "\x01"; void test_ber_write_universal_tag(void) { STREAM* s; s = stream_new(sizeof(ber_universal_tag_expected)); - ber_write_universal_tag(s, 1, 1); + ber_write_universal_tag(s, 1); ASSERT_STREAM(s, (uint8*) ber_universal_tag_expected, sizeof(ber_universal_tag_expected)); diff --git a/cunit/test_gcc.c b/cunit/test_gcc.c index 140c6ec04..9c53a43bd 100644 --- a/cunit/test_gcc.c +++ b/cunit/test_gcc.c @@ -40,6 +40,10 @@ int add_gcc_suite(void) add_test_suite(gcc); add_test_function(gcc_write_create_conference_request); + add_test_function(gcc_write_client_core_data); + add_test_function(gcc_write_client_security_data); + add_test_function(gcc_write_client_cluster_data); + add_test_function(gcc_write_client_network_data); return 0; } @@ -100,3 +104,103 @@ void test_gcc_write_create_conference_request(void) gcc_write_create_conference_request(s, &user_data); ASSERT_STREAM(s, (uint8*) gcc_create_conference_request_expected, sizeof(gcc_create_conference_request_expected)); } + +uint8 gcc_client_core_data_expected[216] = + "\x01\xc0\xd8\x00\x04\x00\x08\x00\x00\x05\x00\x04\x01\xCA\x03\xAA" + "\x09\x04\x00\x00\xCE\x0E\x00\x00\x45\x00\x4c\x00\x54\x00\x4f\x00" + "\x4e\x00\x53\x00\x2d\x00\x44\x00\x45\x00\x56\x00\x32\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00" + "\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x01\xCA\x01\x00\x00\x00\x00\x00\x18\x00\x07\x00" + "\x01\x00\x36\x00\x39\x00\x37\x00\x31\x00\x32\x00\x2d\x00\x37\x00" + "\x38\x00\x33\x00\x2d\x00\x30\x00\x33\x00\x35\x00\x37\x00\x39\x00" + "\x37\x00\x34\x00\x2d\x00\x34\x00\x32\x00\x37\x00\x31\x00\x34\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00"; + +void test_gcc_write_client_core_data(void) +{ + STREAM* s; + rdpSettings* settings; + + s = stream_new(512); + settings = settings_new(); + + settings->width = 1280; + settings->height = 1024; + settings->rdp_version = 5; + settings->color_depth = 24; + settings->kbd_layout = 0x409; + settings->client_build = 3790; + strcpy(settings->client_hostname, "ELTONS-DEV2"); + strcpy(settings->client_product_id, "69712-783-0357974-42714"); + + gcc_write_client_core_data(s, settings); + + ASSERT_STREAM(s, (uint8*) gcc_client_core_data_expected, sizeof(gcc_client_core_data_expected)); +} + +uint8 gcc_client_security_data_expected[12] = + "\x02\xC0\x0C\x00\x1B\x00\x00\x00\x00\x00\x00\x00"; + +void test_gcc_write_client_security_data(void) +{ + STREAM* s; + rdpSettings* settings; + + s = stream_new(12); + settings = settings_new(); + + gcc_write_client_security_data(s, settings); + + ASSERT_STREAM(s, (uint8*) gcc_client_security_data_expected, sizeof(gcc_client_security_data_expected)); +} + +uint8 gcc_client_cluster_data_expected[12] = + "\x04\xC0\x0C\x00\x0D\x00\x00\x00\x00\x00\x00\x00"; + +void test_gcc_write_client_cluster_data(void) +{ + STREAM* s; + rdpSettings* settings; + + s = stream_new(12); + settings = settings_new(); + + gcc_write_client_cluster_data(s, settings); + + ASSERT_STREAM(s, (uint8*) gcc_client_cluster_data_expected, sizeof(gcc_client_cluster_data_expected)); +} + +uint8 gcc_client_network_data_expected[44] = + "\x03\xC0\x2C\x00\x03\x00\x00\x00\x72\x64\x70\x64\x72\x00\x00\x00" + "\x00\x00\x80\x80\x63\x6c\x69\x70\x72\x64\x72\x00\x00\x00\xA0\xC0" + "\x72\x64\x70\x73\x6e\x64\x00\x00\x00\x00\x00\xc0"; + +void test_gcc_write_client_network_data(void) +{ + STREAM* s; + rdpSettings* settings; + + s = stream_new(44); + settings = settings_new(); + + settings->num_channels = 3; + memset(settings->channels, 0, sizeof(struct rdp_chan) * settings->num_channels); + + strcpy(settings->channels[0].name, "rdpdr"); + settings->channels[0].options = 0x80800000; + + strcpy(settings->channels[1].name, "cliprdr"); + settings->channels[1].options = 0xc0A00000; + + strcpy(settings->channels[2].name, "rdpsnd"); + settings->channels[2].options = 0xc0000000; + + gcc_write_client_network_data(s, settings); + + ASSERT_STREAM(s, (uint8*) gcc_client_network_data_expected, sizeof(gcc_client_network_data_expected)); +} diff --git a/cunit/test_gcc.h b/cunit/test_gcc.h index ab3e24090..a672f8610 100644 --- a/cunit/test_gcc.h +++ b/cunit/test_gcc.h @@ -24,3 +24,7 @@ int clean_gcc_suite(void); int add_gcc_suite(void); void test_gcc_write_create_conference_request(void); +void test_gcc_write_client_core_data(void); +void test_gcc_write_client_security_data(void); +void test_gcc_write_client_cluster_data(void); +void test_gcc_write_client_network_data(void); diff --git a/cunit/test_mcs.c b/cunit/test_mcs.c index eaf866781..7aad578ef 100644 --- a/cunit/test_mcs.c +++ b/cunit/test_mcs.c @@ -44,16 +44,6 @@ int add_mcs_suite(void) return 0; } -/* -7F 65 82 01 94 04 01 01 04 01 01 01 01 FF 30 19 -02 01 22 02 01 02 02 01 00 02 01 01 02 01 00 02 -01 01 02 02 FF FF 02 01 02 30 19 02 01 01 02 01 -01 02 01 01 02 01 01 02 01 00 02 01 01 02 02 04 -20 02 01 02 30 1C 02 02 FF FF 02 02 FC 17 02 02 -FF FF 02 01 01 02 01 00 02 01 01 02 02 FF FF 02 -01 02 04 82 01 33 -*/ - uint8 gcc_CCrq[307] = "\x00\x05\x00\x14\x7C\x00\x01\x81\x2A\x00\x08\x00\x10\x00\x01\xC0" "\x00\x44\x75\x63\x61\x81\x1c\x01\xc0\xd8\x00\x04\x00\x08\x00\x00" @@ -76,6 +66,34 @@ uint8 gcc_CCrq[307] = "\x64\x72\x00\x00\x00\xA0\xC0\x72\x64\x70\x73\x6e\x64\x00\x00\x00" "\x00\x00\xc0"; +uint8 mcs_connect_initial_expected[409] = + "\x7F\x65\x82\x01\x94\x04\x01\x01\x04\x01\x01\x01\x01\xFF\x30\x19" + "\x02\x01\x22\x02\x01\x02\x02\x01\x00\x02\x01\x01\x02\x01\x00\x02" + "\x01\x01\x02\x02\xFF\xFF\x02\x01\x02\x30\x19\x02\x01\x01\x02\x01" + "\x01\x02\x01\x01\x02\x01\x01\x02\x01\x00\x02\x01\x01\x02\x02\x04" + "\x20\x02\x01\x02\x30\x1C\x02\x02\xFF\xFF\x02\x02\xFC\x17\x02\x02" + "\xFF\xFF\x02\x01\x01\x02\x01\x00\x02\x01\x01\x02\x02\xFF\xFF\x02" + "\x01\x02\x04\x82\x01\x33\x00\x05\x00\x14\x7C\x00\x01\x81\x2A\x00" + "\x08\x00\x10\x00\x01\xC0\x00\x44\x75\x63\x61\x81\x1c\x01\xc0\xd8" + "\x00\x04\x00\x08\x00\x00\x05\x00\x04\x01\xCA\x03\xAA\x09\x04\x00" + "\x00\xCE\x0E\x00\x00\x45\x00\x4c\x00\x54\x00\x4f\x00\x4e\x00\x53" + "\x00\x2d\x00\x44\x00\x45\x00\x56\x00\x32\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x01\xCA\x01\x00\x00\x00\x00\x00\x18\x00\x07\x00\x01\x00\x36" + "\x00\x39\x00\x37\x00\x31\x00\x32\x00\x2d\x00\x37\x00\x38\x00\x33" + "\x00\x2d\x00\x30\x00\x33\x00\x35\x00\x37\x00\x39\x00\x37\x00\x34" + "\x00\x2d\x00\x34\x00\x32\x00\x37\x00\x31\x00\x34\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x04\xC0\x0C\x00\x0D\x00\x00\x00\x00\x00\x00" + "\x00\x02\xC0\x0C\x00\x1B\x00\x00\x00\x00\x00\x00\x00\x03\xC0\x2C" + "\x00\x03\x00\x00\x00\x72\x64\x70\x64\x72\x00\x00\x00\x00\x00\x80" + "\x80\x63\x6c\x69\x70\x72\x64\x72\x00\x00\x00\xA0\xC0\x72\x64\x70" + "\x73\x6e\x64\x00\x00\x00\x00\x00\xc0"; + void test_mcs_write_connect_initial(void) { STREAM* s; @@ -91,6 +109,5 @@ void test_mcs_write_connect_initial(void) s = stream_new(512); mcs_write_connect_initial(s, mcs, user_data); - /* get expected value to compare with */ - CU_ASSERT(1 == 1); + ASSERT_STREAM(s, (uint8*) mcs_connect_initial_expected, sizeof(mcs_connect_initial_expected)); } diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 48ee32cb6..948c751ec 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -21,6 +21,17 @@ #define __RDP_SETTINGS_H #include +#include + +#define PERF_FLAG_NONE 0x00000000 +#define PERF_DISABLE_WALLPAPER 0x00000001 +#define PERF_DISABLE_FULLWINDOWDRAG 0x00000002 +#define PERF_DISABLE_MENUANIMATIONS 0x00000004 +#define PERF_DISABLE_THEMING 0x00000008 +#define PERF_DISABLE_CURSOR_SHADOW 0x00000020 +#define PERF_DISABLE_CURSORSETTINGS 0x00000040 +#define PERF_ENABLE_FONT_SMOOTHING 0x00000080 +#define PERF_ENABLE_DESKTOP_COMPOSITION 0x00000100 struct rdp_chan { @@ -55,10 +66,11 @@ struct rdp_settings uint32 kbd_type; uint32 kbd_subtype; uint32 kbd_fn_keys; + uint32 client_build; uint32 selected_protocol; - uint32 session_id; int console_session; + uint32 redirected_session_id; int num_channels; struct rdp_chan channels[16]; @@ -66,6 +78,10 @@ struct rdp_settings int num_monitors; struct rdp_monitor monitors[16]; + UNICONV* uniconv; + char client_hostname[32]; + char client_product_id[32]; + char* hostname; char* username; char* password; diff --git a/libfreerdp-core/gcc.c b/libfreerdp-core/gcc.c index edd89cf0e..9d7f4fb14 100644 --- a/libfreerdp-core/gcc.c +++ b/libfreerdp-core/gcc.c @@ -157,14 +157,20 @@ void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length) void gcc_write_client_core_data(STREAM* s, rdpSettings *settings) { uint32 version; + uint8* clientName; + size_t clientNameLength; + uint8 connectionType; uint16 highColorDepth; uint16 supportedColorDepths; uint16 earlyCapabilityFlags; - uint8 connectionType; + uint8* clientDigProductId; + size_t clientDigProductIdLength; gcc_write_user_data_header(s, CS_CORE, 216); version = settings->rdp_version >= 5 ? RDP_VERSION_5_PLUS : RDP_VERSION_4; + clientName = freerdp_uniconv_out(settings->uniconv, settings->client_hostname, &clientNameLength); + clientDigProductId = freerdp_uniconv_out(settings->uniconv, settings->client_product_id, &clientDigProductIdLength); stream_write_uint32(s, version); /* version */ stream_write_uint16(s, settings->width); /* desktopWidth */ @@ -172,9 +178,18 @@ void gcc_write_client_core_data(STREAM* s, rdpSettings *settings) stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* colorDepth, ignored because of postBeta2ColorDepth */ stream_write_uint16(s, RNS_UD_SAS_DEL); /* SASSequence (Secure Access Sequence) */ stream_write_uint32(s, settings->kbd_layout); /* keyboardLayout */ - stream_write_uint32(s, 2600); /* clientBuild */ + stream_write_uint32(s, settings->client_build); /* clientBuild */ - stream_write_zero(s, 32); /* clientName */ + /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ + if (clientNameLength > 30) + { + clientNameLength = 30; + clientName[clientNameLength] = 0; + clientName[clientNameLength + 1] = 0; + } + stream_write(s, clientName, clientNameLength + 2); + stream_write_zero(s, 32 - clientNameLength - 2); + xfree(clientName); stream_write_uint32(s, settings->kbd_type); /* keyboardType */ stream_write_uint32(s, settings->kbd_subtype); /* keyboardSubType */ @@ -184,13 +199,10 @@ void gcc_write_client_core_data(STREAM* s, rdpSettings *settings) stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */ stream_write_uint16(s, 1); /* clientProductID */ - stream_write_uint16(s, 0); /* serialNumber (should be initialized to 0) */ + stream_write_uint32(s, 0); /* serialNumber (should be initialized to 0) */ highColorDepth = MIN(settings->color_depth, 24); - supportedColorDepths = RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT; - - stream_write_uint16(s, highColorDepth); /* highColorDepth */ - stream_write_uint16(s, supportedColorDepths); /* supportedColorDepths */ + supportedColorDepths = RNS_UD_24BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT; connectionType = 0; earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU; @@ -202,10 +214,26 @@ void gcc_write_client_core_data(STREAM* s, rdpSettings *settings) } if (settings->color_depth == 32) + { + supportedColorDepths |= RNS_UD_32BPP_SUPPORT; earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION; + } + + stream_write_uint16(s, highColorDepth); /* highColorDepth */ + stream_write_uint16(s, supportedColorDepths); /* supportedColorDepths */ stream_write_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */ - stream_write_zero(s, 64); /* clientDigProductId (64 bytes) */ + + /* clientDigProductId (64 bytes, null-terminated unicode, truncated to 30 characters) */ + if (clientDigProductIdLength > 62) + { + clientDigProductIdLength = 62; + clientDigProductId[clientDigProductIdLength] = 0; + clientDigProductId[clientDigProductIdLength + 1] = 0; + } + stream_write(s, clientDigProductId, clientDigProductIdLength + 2); + stream_write_zero(s, 64 - clientDigProductIdLength - 2); + xfree(clientDigProductId); stream_write_uint8(s, connectionType); /* connectionType */ stream_write_uint8(s, 0); /* pad1octet */ @@ -226,9 +254,13 @@ void gcc_write_client_security_data(STREAM* s, rdpSettings *settings) gcc_write_user_data_header(s, CS_SECURITY, 12); - encryptionMethods = ENCRYPTION_40BIT_FLAG | ENCRYPTION_128BIT_FLAG; + encryptionMethods = + ENCRYPTION_40BIT_FLAG | + ENCRYPTION_56BIT_FLAG | + ENCRYPTION_128BIT_FLAG | + ENCRYPTION_FIPS_FLAG; - if (settings->encryption) + if (settings->encryption > 0) { stream_write_uint32(s, encryptionMethods); /* encryptionMethods */ stream_write_uint32(s, 0); /* extEncryptionMethods */ @@ -280,17 +312,16 @@ void gcc_write_client_network_data(STREAM* s, rdpSettings *settings) void gcc_write_client_cluster_data(STREAM* s, rdpSettings *settings) { uint32 flags; - uint32 redirectedSessionID; gcc_write_user_data_header(s, CS_CLUSTER, 12); - flags = REDIRECTION_SUPPORTED | REDIRECTION_VERSION4; + flags = REDIRECTION_SUPPORTED | (REDIRECTION_VERSION4 << 2); - if (settings->console_session || settings->session_id) + if (settings->console_session || settings->redirected_session_id) flags |= REDIRECTED_SESSIONID_FIELD_VALID; stream_write_uint32(s, flags); /* flags */ - stream_write_uint32(s, settings->session_id); /* redirectedSessionID */ + stream_write_uint32(s, settings->redirected_session_id); /* redirectedSessionID */ } /** diff --git a/libfreerdp-core/mcs.c b/libfreerdp-core/mcs.c index 8e54cb537..347dfb4ac 100644 --- a/libfreerdp-core/mcs.c +++ b/libfreerdp-core/mcs.c @@ -160,9 +160,9 @@ void mcs_send_connect_initial(rdpMcs* mcs) client_data = stream_new(512); gcc_write_client_core_data(client_data, mcs->transport->settings); + gcc_write_client_cluster_data(client_data, mcs->transport->settings); gcc_write_client_security_data(client_data, mcs->transport->settings); gcc_write_client_network_data(client_data, mcs->transport->settings); - gcc_write_client_cluster_data(client_data, mcs->transport->settings); gcc_write_client_monitor_data(client_data, mcs->transport->settings); gcc_CCrq = stream_new(512); @@ -175,11 +175,11 @@ void mcs_send_connect_initial(rdpMcs* mcs) mcs_write_connect_initial(s, mcs, gcc_CCrq); stream_get_mark(s, em); - length = (em - bm) + 7; + length = (em - bm); stream_set_mark(s, bm); tpkt_write_header(s, length); - tpdu_write_connection_request(s, length - 5); + tpdu_write_data(s, length - 5); stream_set_mark(s, em); tls_write(mcs->transport->tls, s->data, stream_get_length(s)); diff --git a/libfreerdp-core/settings.c b/libfreerdp-core/settings.c index 1bcc8b97a..6d6ca4eb1 100644 --- a/libfreerdp-core/settings.c +++ b/libfreerdp-core/settings.c @@ -29,15 +29,28 @@ rdpSettings* settings_new() if (settings != NULL) { - /* assign default settings */ - settings->width = 1024; settings->height = 768; + settings->rdp_version = 7; settings->color_depth = 16; settings->nla_security = 1; settings->tls_security = 1; settings->rdp_security = 1; + settings->client_build = 2600; + settings->kbd_type = 4; + settings->kbd_subtype = 0; + settings->kbd_fn_keys = 12; + settings->kbd_layout = 0x409; settings->encryption = 1; + + settings->performance_flags = + PERF_DISABLE_FULLWINDOWDRAG | + PERF_DISABLE_MENUANIMATIONS | + PERF_DISABLE_WALLPAPER; + + settings->uniconv = freerdp_uniconv_new(); + strcpy(settings->client_product_id, "69712-783-0357974-42714"); + gethostname(settings->client_hostname, sizeof(settings->client_hostname) - 1); } return settings; @@ -47,6 +60,7 @@ void settings_free(rdpSettings* settings) { if (settings != NULL) { + freerdp_uniconv_free(settings->uniconv); xfree(settings); } } diff --git a/libfreerdp-core/tpdu.c b/libfreerdp-core/tpdu.c index bf65862b5..e11d0c627 100644 --- a/libfreerdp-core/tpdu.c +++ b/libfreerdp-core/tpdu.c @@ -159,11 +159,10 @@ tpdu_write_disconnect_request(STREAM* s, uint16 length) /** * Write Data TPDU. * @param s stream - * @param length TPDU length */ void -tpdu_write_data(STREAM* s, uint16 length) +tpdu_write_data(STREAM* s) { - tpdu_write_header(s, length, X224_TPDU_DATA); + tpdu_write_header(s, 2, X224_TPDU_DATA); } diff --git a/libfreerdp-core/tpdu.h b/libfreerdp-core/tpdu.h index 5b322334c..b756b4d98 100644 --- a/libfreerdp-core/tpdu.h +++ b/libfreerdp-core/tpdu.h @@ -46,6 +46,6 @@ tpdu_read_connection_confirm(STREAM* s); void tpdu_write_disconnect_request(STREAM* s, uint16 length); void -tpdu_write_data(STREAM* s, uint16 length); +tpdu_write_data(STREAM* s); #endif /* __TPDU_H */