From 3b0a0c133413dafe8f782ce05d2a51007616dac7 Mon Sep 17 00:00:00 2001 From: Karl Mikaelsson Date: Thu, 12 Oct 2017 11:27:45 +0200 Subject: [PATCH 1/7] Improve rdp_out_general_caps Rename to rdp_out_ts_general_capabilityset to match the structure name, describe all fields and use constants instead of magic numbers. --- constants.h | 13 +++++++++++++ rdp.c | 44 +++++++++++++++++++++++--------------------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/constants.h b/constants.h index 1f4ab07..a85cbe3 100644 --- a/constants.h +++ b/constants.h @@ -626,3 +626,16 @@ enum RDP_PDU_REDIRECT_FLAGS LB_REDIRECTION_GUID = 0x8000, LB_TARGET_CERTIFICATE = 0x10000 }; + + +/* [MS-RDPBCGR] 2.2.7.1.1 */ +#define OSMAJORTYPE_WINDOWS 0x0001 +#define OSMINORTYPE_WINDOWSNT 0x0003 +#define TS_CAPS_PROTOCOLVERSION 0x0200 + +/* extraFlags, [MS-RDPBCGR] 2.2.7.1.1 */ +#define FASTPATH_OUTPUT_SUPPORTED 0x0001 +#define LONG_CREDENTIALS_SUPPORTED 0x0004 +#define AUTORECONNECT_SUPPORTED 0x0008 +#define ENC_SALTED_CHECKSUM 0x0010 +#define NO_BITMAP_COMPRESSION_HDR 0x0400 diff --git a/rdp.c b/rdp.c index 34895b7..b5831c7 100644 --- a/rdp.c +++ b/rdp.c @@ -624,30 +624,32 @@ rdp_send_fonts(uint16 seq) rdp_send_data(s, RDP_DATA_PDU_FONT2); } -/* Output general capability set */ +/* Output general capability set (TS_GENERAL_CAPABILITYSET) */ static void -rdp_out_general_caps(STREAM s) +rdp_out_ts_general_capabilityset(STREAM s) { + uint16 extraFlags = 0; + if (g_rdp_version >= RDP_V5) + { + extraFlags |= NO_BITMAP_COMPRESSION_HDR; + extraFlags |= AUTORECONNECT_SUPPORTED; + extraFlags |= LONG_CREDENTIALS_SUPPORTED; + extraFlags |= FASTPATH_OUTPUT_SUPPORTED; + } + out_uint16_le(s, RDP_CAPSET_GENERAL); out_uint16_le(s, RDP_CAPLEN_GENERAL); - - out_uint16_le(s, 1); /* OS major type */ - out_uint16_le(s, 3); /* OS minor type */ - out_uint16_le(s, 0x200); /* Protocol version */ - out_uint16(s, 0); /* Pad */ - out_uint16(s, 0); /* Compression types */ - out_uint16_le(s, (g_rdp_version >= RDP_V5) ? 0x40d : 0); - /* Pad, according to T.128. 0x40d seems to - trigger - the server to start sending RDP5 packets. - However, the value is 0x1d04 with W2KTSK and - NT4MS. Hmm.. Anyway, thankyou, Microsoft, - for sending such information in a padding - field.. */ - out_uint16(s, 0); /* Update capability */ - out_uint16(s, 0); /* Remote unshare capability */ - out_uint16(s, 0); /* Compression level */ - out_uint16(s, 0); /* Pad */ + out_uint16_le(s, OSMAJORTYPE_WINDOWS); /* osMajorType */ + out_uint16_le(s, OSMINORTYPE_WINDOWSNT); /* osMinorType */ + out_uint16_le(s, TS_CAPS_PROTOCOLVERSION); /* protocolVersion (must be TS_CAPS_PROTOCOLVERSION) */ + out_uint16_le(s, 0); /* pad2OctetsA */ + out_uint16_le(s, 0); /* generalCompressionTypes (must be 0) */ + out_uint16_le(s, extraFlags); /* extraFlags */ + out_uint16_le(s, 0); /* updateCapabilityFlag (must be 0) */ + out_uint16_le(s, 0); /* remoteUnshareFlag (must be 0) */ + out_uint16_le(s, 0); /* generalCompressionLevel (must be 0) */ + out_uint8(s, 0); /* refreshRectSupport */ + out_uint8(s, 0); /* suppressOutputSupport */ } /* Output bitmap capability set */ @@ -914,7 +916,7 @@ rdp_send_confirm_active(void) out_uint16_le(s, 0xe); /* num_caps */ out_uint8s(s, 2); /* pad */ - rdp_out_general_caps(s); + rdp_out_ts_general_capabilityset(s); rdp_out_bitmap_caps(s); rdp_out_order_caps(s); if (g_rdp_version >= RDP_V5) From 9ca206bc081e1c9e99584de0ff4a40b11727b564 Mon Sep 17 00:00:00 2001 From: Karl Mikaelsson Date: Thu, 12 Oct 2017 12:50:18 +0200 Subject: [PATCH 2/7] Clarify order and bitmap capability set functions --- constants.h | 31 ++++++++++++++ rdp.c | 113 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 96 insertions(+), 48 deletions(-) diff --git a/constants.h b/constants.h index a85cbe3..0049290 100644 --- a/constants.h +++ b/constants.h @@ -639,3 +639,34 @@ enum RDP_PDU_REDIRECT_FLAGS #define AUTORECONNECT_SUPPORTED 0x0008 #define ENC_SALTED_CHECKSUM 0x0010 #define NO_BITMAP_COMPRESSION_HDR 0x0400 + +/* orderFlags, [MS-RDPBCGR] 2.2.7.1.3 */ +#define NEGOTIATEORDERSUPPORT 0x0002 +#define ZEROBOUNDSDELTASSUPPORT 0x0008 +#define COLORINDEXSUPPORT 0x0020 +#define SOLIDPATTERNBRUSHONLY 0x0040 +#define ORDERFLAGS_EXTRA_FLAGS 0x0080 + +/* orderSupport index, [MS-RDPBCGR] 2.2.7.1.3 */ +#define TS_NEG_DSTBLT_INDEX 0x00 +#define TS_NEG_PATBLT_INDEX 0x01 +#define TS_NEG_SCRBLT_INDEX 0x02 +#define TS_NEG_MEMBLT_INDEX 0x03 +#define TS_NEG_MEM3BLT_INDEX 0x04 +#define TS_NEG_DRAWNINEGRID_INDEX 0x07 +#define TS_NEG_LINETO_INDEX 0x08 +#define TS_NEG_MULTI_DRAWNINEGRID_INDEX 0x09 +#define TS_NEG_SAVEBITMAP_INDEX 0x0B +#define TS_NEG_MULTIDSTBLT_INDEX 0x0F +#define TS_NEG_MULTIPATBLT_INDEX 0x10 +#define TS_NEG_MULTISCRBLT_INDEX 0x11 +#define TS_NEG_MULTIOPAQUERECT_INDEX 0x12 +#define TS_NEG_FAST_INDEX_INDEX 0x13 +#define TS_NEG_POLYGON_SC_INDEX 0x14 +#define TS_NEG_POLYGON_CB_INDEX 0x15 +#define TS_NEG_POLYLINE_INDEX 0x16 +#define TS_NEG_FAST_GLYPH_INDEX 0x18 +#define TS_NEG_ELLIPSE_SC_INDEX 0x19 +#define TS_NEG_ELLIPSE_CB_INDEX 0x1A +#define TS_NEG_INDEX_INDEX 0x1B + diff --git a/rdp.c b/rdp.c index b5831c7..37ee100 100644 --- a/rdp.c +++ b/rdp.c @@ -654,65 +654,82 @@ rdp_out_ts_general_capabilityset(STREAM s) /* Output bitmap capability set */ static void -rdp_out_bitmap_caps(STREAM s) +rdp_out_ts_bitmap_capabilityset(STREAM s) { out_uint16_le(s, RDP_CAPSET_BITMAP); out_uint16_le(s, RDP_CAPLEN_BITMAP); - - out_uint16_le(s, g_server_depth); /* Preferred colour depth */ - out_uint16_le(s, 1); /* Receive 1 BPP */ - out_uint16_le(s, 1); /* Receive 4 BPP */ - out_uint16_le(s, 1); /* Receive 8 BPP */ - out_uint16_le(s, 800); /* Desktop width */ - out_uint16_le(s, 600); /* Desktop height */ - out_uint16(s, 0); /* Pad */ - out_uint16(s, 1); /* Allow resize */ - out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */ - out_uint16(s, 0); /* Unknown */ - out_uint16_le(s, 1); /* Unknown */ - out_uint16(s, 0); /* Pad */ + out_uint16_le(s, g_server_depth); /* preferredBitsPerPixel */ + out_uint16_le(s, 1); /* receive1BitPerPixel (ignored, should be 1) */ + out_uint16_le(s, 1); /* receive4BitPerPixel (ignored, should be 1) */ + out_uint16_le(s, 1); /* receive8BitPerPixel (ignored, should be 1) */ + out_uint16_le(s, 800); /* desktopWidth */ + out_uint16_le(s, 600); /* desktopHeight */ + out_uint16_le(s, 0); /* pad2Octets */ + out_uint16_le(s, 1); /* desktopResizeFlag */ + out_uint16_le(s, 1); /* bitmapCompressionFlag (must be 1) */ + out_uint8(s, 0); /* highColorFlags (ignored, should be 0) */ + out_uint8(s, 0); /* drawingFlags */ + out_uint16_le(s, 1); /* multipleRectangleSupport (must be 1) */ + out_uint16_le(s, 0); /* pad2OctetsB */ } /* Output order capability set */ static void -rdp_out_order_caps(STREAM s) +rdp_out_ts_order_capabilityset(STREAM s) { uint8 order_caps[32]; + uint16 orderflags = 0; + uint32 cachesize = 0; + + orderflags |= (NEGOTIATEORDERSUPPORT | ZEROBOUNDSDELTASSUPPORT); /* mandatory flags */ + orderflags |= COLORINDEXSUPPORT; memset(order_caps, 0, 32); - order_caps[0] = 1; /* dest blt */ - order_caps[1] = 1; /* pat blt */ - order_caps[2] = 1; /* screen blt */ - order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */ - order_caps[4] = 0; /* triblt */ - order_caps[8] = 1; /* line */ - order_caps[9] = 1; /* line */ - order_caps[10] = 1; /* rect */ - order_caps[11] = (g_desktop_save ? 1 : 0); /* desksave */ - order_caps[13] = 1; /* memblt */ - order_caps[14] = 1; /* triblt */ - order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon */ - order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon2 */ - order_caps[22] = 1; /* polyline */ - order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse */ - order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse2 */ - order_caps[27] = 1; /* text2 */ + + order_caps[TS_NEG_DSTBLT_INDEX] = 1; + order_caps[TS_NEG_PATBLT_INDEX] = 1; + order_caps[TS_NEG_SCRBLT_INDEX] = 1; + order_caps[TS_NEG_LINETO_INDEX] = 1; + order_caps[TS_NEG_MULTI_DRAWNINEGRID_INDEX] = 1; + order_caps[TS_NEG_POLYLINE_INDEX] = 1; + order_caps[TS_NEG_INDEX_INDEX] = 1; + + if (g_bitmap_cache) + order_caps[TS_NEG_MEMBLT_INDEX] = 1; + + if (g_desktop_save) + { + cachesize = 230400; + order_caps[TS_NEG_SAVEBITMAP_INDEX] = 1; + } + + if (g_polygon_ellipse_orders) + { + order_caps[TS_NEG_POLYGON_SC_INDEX] = 1; + order_caps[TS_NEG_POLYGON_CB_INDEX] = 1; + order_caps[TS_NEG_ELLIPSE_SC_INDEX] = 1; + order_caps[TS_NEG_ELLIPSE_CB_INDEX] = 1; + } + out_uint16_le(s, RDP_CAPSET_ORDER); out_uint16_le(s, RDP_CAPLEN_ORDER); - - out_uint8s(s, 20); /* Terminal desc, pad */ - out_uint16_le(s, 1); /* Cache X granularity */ - out_uint16_le(s, 20); /* Cache Y granularity */ - out_uint16(s, 0); /* Pad */ - out_uint16_le(s, 1); /* Max order level */ - out_uint16_le(s, 0x147); /* Number of fonts */ - out_uint16_le(s, 0x2a); /* Capability flags */ - out_uint8p(s, order_caps, 32); /* Orders supported */ - out_uint16_le(s, 0x6a1); /* Text capability flags */ - out_uint8s(s, 6); /* Pad */ - out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */ - out_uint32(s, 0); /* Unknown */ - out_uint32_le(s, 0x4e4); /* Unknown */ + out_uint8s(s, 16); /* terminalDescriptor (ignored, should be 0) */ + out_uint8s(s, 4); /* pad4OctetsA */ + out_uint16_le(s, 1); /* desktopSaveXGranularity (ignored, assumed to be 1) */ + out_uint16_le(s, 20); /* desktopSaveYGranularity (ignored, assumed to be 20) */ + out_uint16_le(s, 0); /* Pad */ + out_uint16_le(s, 1); /* maximumOrderLevel (ignored, should be 1) */ + out_uint16_le(s, 0); /* numberFonts (ignored, should be 0) */ + out_uint16_le(s, orderflags); /* orderFlags */ + out_uint8p(s, order_caps, 32); /* orderSupport */ + out_uint16_le(s, 0); /* textFlags (ignored) */ + out_uint16_le(s, 0); /* orderSupportExFlags */ + out_uint32_le(s, 0); /* pad4OctetsB */ + out_uint32_le(s, cachesize); /* desktopSaveSize */ + out_uint16_le(s, 0); /* pad2OctetsC */ + out_uint16_le(s, 0); /* pad2OctetsD */ + out_uint16_le(s, 1252); /* textANSICodePage */ + out_uint16_le(s, 0); /* pad2OctetsE */ } /* Output bitmap cache capability set */ @@ -917,8 +934,8 @@ rdp_send_confirm_active(void) out_uint8s(s, 2); /* pad */ rdp_out_ts_general_capabilityset(s); - rdp_out_bitmap_caps(s); - rdp_out_order_caps(s); + rdp_out_ts_bitmap_capabilityset(s); + rdp_out_ts_order_capabilityset(s); if (g_rdp_version >= RDP_V5) { rdp_out_bmpcache2_caps(s); From 72f63d04ecab734ce8018f32a80d5cff3c4fda72 Mon Sep 17 00:00:00 2001 From: Karl Mikaelsson Date: Fri, 13 Oct 2017 13:34:02 +0200 Subject: [PATCH 3/7] Decipher remaining capabilitysets sent from rdesktop --- constants.h | 35 ++++++++++++++++ rdp.c | 114 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 113 insertions(+), 36 deletions(-) diff --git a/constants.h b/constants.h index 0049290..317d59c 100644 --- a/constants.h +++ b/constants.h @@ -324,9 +324,21 @@ enum RDP_INPUT_DEVICE #define RDP_CAPSET_COLCACHE 10 #define RDP_CAPLEN_COLCACHE 0x08 +#define RDP_CAPSET_SOUND 12 +#define RDP_CAPLEN_SOUND 8 + +#define RDP_CAPSET_INPUT 13 +#define RDP_CAPLEN_INPUT 88 + +#define RDP_CAPSET_FONT 14 +#define RDP_CAPLEN_FONT 8 + #define RDP_CAPSET_BRUSHCACHE 15 #define RDP_CAPLEN_BRUSHCACHE 0x08 +#define RDP_CAPSET_GLYPHCACHE 16 +#define RDP_CAPLEN_GLYPHCACHE 52 + #define RDP_CAPSET_BMPCACHE2 19 #define RDP_CAPLEN_BMPCACHE2 0x28 #define BMPCACHE2_FLAG_PERSIST ((uint32)1<<31) @@ -670,3 +682,26 @@ enum RDP_PDU_REDIRECT_FLAGS #define TS_NEG_ELLIPSE_CB_INDEX 0x1A #define TS_NEG_INDEX_INDEX 0x1B +/* [MS-RDPBCGR] 2.2.7.1.6 */ +#define INPUT_FLAG_SCANCODES 0x0001 +#define INPUT_FLAG_MOUSEX 0x0004 +#define INPUT_FLAG_FASTPATH_INPUT 0x0008 +#define INPUT_FLAG_UNICODE 0x0010 +#define INPUT_FLAG_FASTPATH_INPUT2 0x0020 +#define INPUT_FLAG_UNUSED1 0x0040 +#define INPUT_FLAG_UNUSED2 0x0080 +#define TS_INPUT_FLAG_MOUSE_HWHEEL 0x0100 +#define TS_INPUT_FLAG_QOE_TIMESTAMPS 0x0200 + +/* [MS-RDPBCGR] 2.2.7.1.8 */ +#define GLYPH_SUPPORT_NONE 0x0000 +#define GLYPH_SUPPORT_PARTIAL 0x0001 +#define GLYPH_SUPPORT_FULL 0x0002 +#define GLYPH_SUPPORT_ENCODE 0x0003 + +/* [MS-RDPBCGR] 2.2.7.1.11 */ +#define SOUND_BEEPS_FLAG 0x0001 + +/* [MS-RDPBCGR] 2.2.7.2.5 */ +#define FONTSUPPORT_FONTLIST 0x0001 + diff --git a/rdp.c b/rdp.c index 37ee100..8162892 100644 --- a/rdp.c +++ b/rdp.c @@ -4,6 +4,7 @@ Copyright (C) Matthew Chapman 1999-2008 Copyright 2003-2011 Peter Astrand for Cendio AB Copyright 2011-2017 Henrik Andersson for Cendio AB + Copyright 2017 Karl Mikaelsson for Cendio AB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -855,41 +856,82 @@ rdp_out_brushcache_caps(STREAM s) out_uint32_le(s, 1); /* cache type */ } -static uint8 caps_0x0d[] = { - 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 }; - -static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 }; - -static uint8 caps_0x10[] = { - 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, - 0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00, - 0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, - 0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00, - 0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, - 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00 -}; - -/* Output unknown capability sets */ +/* Output Input Capability Set */ static void -rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps) +rdp_out_ts_input_capabilityset(STREAM s) { - out_uint16_le(s, id); - out_uint16_le(s, length); + uint16 inputflags = 0; + inputflags |= INPUT_FLAG_SCANCODES; - out_uint8p(s, caps, length - 4); + out_uint16_le(s, RDP_CAPSET_INPUT); + out_uint16_le(s, RDP_CAPLEN_INPUT); + + out_uint16_le(s, inputflags); /* inputFlags */ + out_uint16_le(s, 0); /* pad2OctetsA */ + out_uint32_le(s, 0x409); /* keyboardLayout */ + out_uint32_le(s, 0x4); /* keyboardType */ + out_uint32_le(s, 0); /* keyboardSubtype */ + out_uint32_le(s, 0xC); /* keyboardFunctionKey */ + out_utf16s_padded(s, "", 64, 0); /* imeFileName */ +} + +/* Output Sound Capability Set */ +static void +rdp_out_ts_sound_capabilityset(STREAM s) +{ + uint16 soundflags = SOUND_BEEPS_FLAG; + + out_uint16_le(s, RDP_CAPSET_SOUND); + out_uint16_le(s, RDP_CAPLEN_SOUND); + + out_uint16_le(s, soundflags); /* soundFlags */ + out_uint16_le(s, 0); /* pad2OctetsA */ +} + +/* Output Font Capability Set */ +static void +rdp_out_ts_font_capabilityset(STREAM s) +{ + uint16 flags = FONTSUPPORT_FONTLIST; + + out_uint16_le(s, RDP_CAPSET_FONT); + out_uint16_le(s, RDP_CAPLEN_FONT); + + out_uint16_le(s, flags); /* fontSupportFlags */ + out_uint16_le(s, 0); /* pad2octets */ +} + +static void +rdp_out_ts_cache_definition(STREAM s, uint16 entries, uint16 maxcellsize) +{ + out_uint16_le(s, entries); + out_uint16_le(s, maxcellsize); +} + +/* Output Glyph Cache Capability Set */ +static void +rdp_out_ts_glyphcache_capabilityset(STREAM s) +{ + uint16 supportlvl = GLYPH_SUPPORT_FULL; + uint32 fragcache = 0x01000100; + out_uint16_le(s, RDP_CAPSET_GLYPHCACHE); + out_uint16_le(s, RDP_CAPLEN_GLYPHCACHE); + + /* GlyphCache - 10 TS_CACHE_DEFINITION structures */ + rdp_out_ts_cache_definition(s, 254, 4); + rdp_out_ts_cache_definition(s, 254, 4); + rdp_out_ts_cache_definition(s, 254, 8); + rdp_out_ts_cache_definition(s, 254, 8); + rdp_out_ts_cache_definition(s, 254, 16); + rdp_out_ts_cache_definition(s, 254, 32); + rdp_out_ts_cache_definition(s, 254, 64); + rdp_out_ts_cache_definition(s, 254, 128); + rdp_out_ts_cache_definition(s, 254, 256); + rdp_out_ts_cache_definition(s, 64, 2048); + + out_uint32_le(s, fragcache); /* FragCache */ + out_uint16_le(s, supportlvl); /* GlyphSupportLevel */ + out_uint16_le(s, 0); /* pad2octets */ } #define RDP5_FLAG 0x0030 @@ -952,10 +994,10 @@ rdp_send_confirm_active(void) rdp_out_share_caps(s); rdp_out_brushcache_caps(s); - rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* CAPSTYPE_INPUT */ - rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c); /* CAPSTYPE_SOUND */ - rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e); /* CAPSTYPE_FONT */ - rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* CAPSTYPE_GLYPHCACHE */ + rdp_out_ts_input_capabilityset(s); + rdp_out_ts_sound_capabilityset(s); + rdp_out_ts_font_capabilityset(s); + rdp_out_ts_glyphcache_capabilityset(s); s_mark_end(s); sec_send(s, sec_flags); From 3abeca252b774579914ff0ac63119e46cc08666f Mon Sep 17 00:00:00 2001 From: Karl Mikaelsson Date: Fri, 13 Oct 2017 13:37:37 +0200 Subject: [PATCH 4/7] Log system pointer changes via Fast-Path updates --- constants.h | 5 +++-- proto.h | 1 + rdp.c | 19 +++++++++++++------ rdp5.c | 2 ++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/constants.h b/constants.h index 317d59c..7bfa053 100644 --- a/constants.h +++ b/constants.h @@ -220,10 +220,11 @@ enum RDP_POINTER_PDU_TYPE RDP_POINTER_NEW = 8 }; +/* [MS-RDPBCGR] 2.2.9.1.1.4.3 */ enum RDP_SYSTEM_POINTER_TYPE { - RDP_NULL_POINTER = 0, - RDP_DEFAULT_POINTER = 0x7F00 + SYSPTR_NULL = 0x00000000, + SYSPTR_DEFAULT = 0x00007F00 }; enum RDP_INPUT_DEVICE diff --git a/proto.h b/proto.h index 1b35bba..382f50a 100644 --- a/proto.h +++ b/proto.h @@ -154,6 +154,7 @@ void process_colour_pointer_pdu(STREAM s); void process_new_pointer_pdu(STREAM s); void process_cached_pointer_pdu(STREAM s); void process_system_pointer_pdu(STREAM s); +void set_system_pointer(uint32 ptr); void process_bitmap_updates(STREAM s); void process_palette(STREAM s); void process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason); diff --git a/rdp.c b/rdp.c index 8162892..423d31e 100644 --- a/rdp.c +++ b/rdp.c @@ -1200,19 +1200,26 @@ process_cached_pointer_pdu(STREAM s) void process_system_pointer_pdu(STREAM s) { - uint16 system_pointer_type; + uint32 system_pointer_type; + in_uint32_le(s, system_pointer_type); - in_uint16_le(s, system_pointer_type); - switch (system_pointer_type) + set_system_pointer(system_pointer_type); +} + +/* Set a given system pointer */ +void +set_system_pointer(uint32 ptr) +{ + switch (ptr) { - case RDP_NULL_POINTER: + case SYSPTR_NULL: ui_set_null_cursor(); break; default: logger(Protocol, Warning, - "process_system_pointer_pdu(), unhandled pointer type 0x%x", - system_pointer_type); + "set_system_pointer(), unhandled pointer type 0x%x", + ptr); } } diff --git a/rdp5.c b/rdp5.c index f11f749..fcca5df 100644 --- a/rdp5.c +++ b/rdp5.c @@ -3,6 +3,7 @@ Protocol services - RDP5 short form PDU processing Copyright (C) Matthew Chapman 1999-2008 Copyright 2003-2008 Erik Forsberg for Cendio AB + Copyright 2017 Karl Mikaelsson for Cendio AB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -93,6 +94,7 @@ rdp5_process(STREAM s) ui_set_null_cursor(); break; case 6: /* default pointer */ + set_system_pointer(SYSPTR_DEFAULT); break; case 8: /* pointer position */ in_uint16_le(ts, x); From eec94365c45270f0d4e8ed05655583201f87ad69 Mon Sep 17 00:00:00 2001 From: Karl Mikaelsson Date: Fri, 13 Oct 2017 13:45:07 +0200 Subject: [PATCH 5/7] Improve Fast-Path code readability Using constants and field definitions from MS-RDPBCGR. --- constants.h | 21 ++++++++++++++++++++ proto.h | 2 +- rdp.c | 4 ++-- rdp5.c | 57 ++++++++++++++++++++++++++--------------------------- 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/constants.h b/constants.h index 7bfa053..370a65c 100644 --- a/constants.h +++ b/constants.h @@ -23,6 +23,27 @@ #define DEFAULT_CODEPAGE "UTF-8" #define WINDOWS_CODEPAGE "UTF-16LE" +/* [MS-RDPBCGR] 2.2.9.1.2.1 */ +/* adjusted for position in updateHeader */ +#define FASTPATH_UPDATETYPE_ORDERS 0x0 +#define FASTPATH_UPDATETYPE_BITMAP 0x1 +#define FASTPATH_UPDATETYPE_PALETTE 0x2 +#define FASTPATH_UPDATETYPE_SYNCHRONIZE 0x3 +#define FASTPATH_UPDATETYPE_SURFCMDS 0x4 +#define FASTPATH_UPDATETYPE_PTR_NULL 0x5 +#define FASTPATH_UPDATETYPE_PTR_DEFAULT 0x6 +#define FASTPATH_UPDATETYPE_PTR_POSITION 0x8 +#define FASTPATH_UPDATETYPE_COLOR 0x9 +#define FASTPATH_UPDATETYPE_CACHED 0xA +#define FASTPATH_UPDATETYPE_POINTER 0xB + +#define FASTPATH_FRAGMENT_SINGLE (0x0 << 4) +#define FASTPATH_FRAGMENT_LAST (0x1 << 4) +#define FASTPATH_FRAGMENT_FIRST (0x2 << 4) +#define FASTPATH_FRAGMENT_NEXT (0x3 << 4) + +#define FASTPATH_OUTPUT_COMPRESSION_USED (0x2 << 6) + /* ISO PDU codes */ enum ISO_PDU_CODE { diff --git a/proto.h b/proto.h index 382f50a..6bb5656 100644 --- a/proto.h +++ b/proto.h @@ -144,7 +144,7 @@ int rd_write_file(int fd, void *ptr, int len); int rd_lseek_file(int fd, int offset); RD_BOOL rd_lock_file(int fd, int start, int len); /* rdp5.c */ -void rdp5_process(STREAM s); +void process_ts_fp_updates(STREAM s); /* rdp.c */ void rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size); void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, diff --git a/rdp.c b/rdp.c index 423d31e..76db804 100644 --- a/rdp.c +++ b/rdp.c @@ -104,8 +104,8 @@ rdp_recv(uint8 * type) } else if (rdpver != 3) { - /* rdp5_process should move g_next_packet ok */ - rdp5_process(rdp_s); + /* process_ts_fp_updates moves g_next_packet */ + process_ts_fp_updates(rdp_s); *type = 0; return rdp_s; } diff --git a/rdp5.c b/rdp5.c index fcca5df..98eb916 100644 --- a/rdp5.c +++ b/rdp5.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. - Protocol services - RDP5 short form PDU processing + Protocol services - RDP Fast-Path PDU processing Copyright (C) Matthew Chapman 1999-2008 Copyright 2003-2008 Erik Forsberg for Cendio AB Copyright 2017 Karl Mikaelsson for Cendio AB @@ -26,10 +26,10 @@ extern uint8 *g_next_packet; extern RDPCOMP g_mppc_dict; void -rdp5_process(STREAM s) +process_ts_fp_updates(STREAM s) { uint16 length, count, x, y; - uint8 type, ctype; + uint8 hdr, code, frag, comp, ctype = 0; uint8 *next; uint32 roff, rlen; @@ -39,25 +39,24 @@ rdp5_process(STREAM s) ui_begin_update(); while (s->p < s->end) { - in_uint8(s, type); - if (type & RDP5_COMPRESSED) - { - in_uint8(s, ctype); - in_uint16_le(s, length); - type ^= RDP5_COMPRESSED; - } - else - { - ctype = 0; - in_uint16_le(s, length); - } + /* Reading a number of TS_FP_UPDATE structures from the stream here.. */ + in_uint8(s, hdr); /* updateHeader */ + code = hdr & 0x0F; /* |- updateCode */ + frag = hdr & 0x30; /* |- fragmentation */ + comp = hdr & 0xC0; /* `- compression */ + + if (comp & FASTPATH_OUTPUT_COMPRESSION_USED) + in_uint8(s, ctype); /* compressionFlags */ + + in_uint16_le(s, length); /* length */ + g_next_packet = next = s->p + length; if (ctype & RDP_MPPC_COMPRESSED) { if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1) logger(Protocol, Error, - "rdp5_process(), error while decompressing packet"); + "process_ts_fp_update_pdu(), error while decompressing packet"); /* allocate memory and copy the uncompressed data into the temporary stream */ ns->data = (uint8 *) xrealloc(ns->data, rlen); @@ -74,46 +73,46 @@ rdp5_process(STREAM s) else ts = s; - switch (type) + switch (code) { - case 0: /* update orders */ + case FASTPATH_UPDATETYPE_ORDERS: in_uint16_le(ts, count); process_orders(ts, count); break; - case 1: /* update bitmap */ + case FASTPATH_UPDATETYPE_BITMAP: in_uint8s(ts, 2); /* part length */ process_bitmap_updates(ts); break; - case 2: /* update palette */ + case FASTPATH_UPDATETYPE_PALETTE: in_uint8s(ts, 2); /* uint16 = 2 */ process_palette(ts); break; - case 3: /* update synchronize */ + case FASTPATH_UPDATETYPE_SYNCHRONIZE: break; - case 5: /* null pointer */ + case FASTPATH_UPDATETYPE_PTR_NULL: ui_set_null_cursor(); break; - case 6: /* default pointer */ + case FASTPATH_UPDATETYPE_PTR_DEFAULT: set_system_pointer(SYSPTR_DEFAULT); break; - case 8: /* pointer position */ + case FASTPATH_UPDATETYPE_PTR_POSITION: in_uint16_le(ts, x); in_uint16_le(ts, y); if (s_check(ts)) ui_move_pointer(x, y); break; - case 9: /* color pointer */ + case FASTPATH_UPDATETYPE_COLOR: process_colour_pointer_pdu(ts); break; - case 10: /* cached pointer */ + case FASTPATH_UPDATETYPE_CACHED: process_cached_pointer_pdu(ts); break; - case 11: + case FASTPATH_UPDATETYPE_POINTER: process_new_pointer_pdu(ts); break; default: - logger(Protocol, Warning, "rdp5_process(), unhandled opcode %d", - type); + logger(Protocol, Warning, "process_ts_fp_updates(), unhandled opcode %d", + code); } s->p = next; From 63ac9d3c423189cc5811674d8337ea57a25f54ab Mon Sep 17 00:00:00 2001 From: Karl Mikaelsson Date: Fri, 13 Oct 2017 13:53:09 +0200 Subject: [PATCH 6/7] Clarify the Fast-Path handling in the T.123/X.224 layer --- constants.h | 13 +++++++++++++ iso.c | 15 ++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/constants.h b/constants.h index 370a65c..3587050 100644 --- a/constants.h +++ b/constants.h @@ -23,6 +23,19 @@ #define DEFAULT_CODEPAGE "UTF-8" #define WINDOWS_CODEPAGE "UTF-16LE" +/* T-REC-T.123-200701, section 8 */ +#define T123_HEADER_VERSION 0x3 + +/* [MS-RDPBCGR] 2.2.9.1.2 */ +#define FASTPATH_OUTPUT_ACTION_FASTPATH 0x0 +#define FASTPATH_OUTPUT_ACTION_X224 T123_HEADER_VERSION + +#define FASTPATH_OUTPUT_SECURE_CHECKSUM 0x1 +#define FASTPATH_OUTPUT_ENCRYPTED 0x2 + +#define IS_FASTPATH(hdr) ((hdr & 0x03) == FASTPATH_OUTPUT_ACTION_FASTPATH) +#define IS_SLOWPATH(hdr) ((hdr) == FASTPATH_OUTPUT_ACTION_X224) + /* [MS-RDPBCGR] 2.2.9.1.2.1 */ /* adjusted for position in updateHeader */ #define FASTPATH_UPDATETYPE_ORDERS 0x0 diff --git a/iso.c b/iso.c index 9325274..7fccdd1 100644 --- a/iso.c +++ b/iso.c @@ -110,16 +110,17 @@ iso_recv_msg(uint8 * code, uint8 * rdpver) in_uint8(s, version); if (rdpver != NULL) *rdpver = version; - if (version == 3) + if (IS_SLOWPATH(version)) { - in_uint8s(s, 1); /* pad */ - in_uint16_be(s, length); + in_uint8s(s, 1); /* reserved */ + in_uint16_be(s, length); /* length */ } else { - in_uint8(s, length); + in_uint8(s, length); /* length1 */ if (length & 0x80) { + /* length2 is only present if the most significant bit of length1 is set */ length &= ~0x80; next_be(s, length); } @@ -132,7 +133,7 @@ iso_recv_msg(uint8 * code, uint8 * rdpver) s = tcp_recv(s, length - 4); if (s == NULL) return NULL; - if (version != 3) + if (IS_FASTPATH(version)) return s; in_uint8s(s, 1); /* hdrlen */ in_uint8(s, *code); @@ -166,7 +167,7 @@ iso_send(STREAM s) s_pop_layer(s, iso_hdr); length = s->end - s->p; - out_uint8(s, 3); /* version */ + out_uint8(s, T123_HEADER_VERSION); /* version */ out_uint8(s, 0); /* reserved */ out_uint16_be(s, length); @@ -188,7 +189,7 @@ iso_recv(uint8 * rdpver) if (s == NULL) return NULL; if (rdpver != NULL) - if (*rdpver != 3) + if (IS_FASTPATH(*rdpver)) return s; if (code != ISO_PDU_DT) { From 12ee9eb035e0a427705c106e6cf80f745ff0acc1 Mon Sep 17 00:00:00 2001 From: Karl Mikaelsson Date: Fri, 13 Oct 2017 14:34:01 +0200 Subject: [PATCH 7/7] Avoid magic constants in caplen too --- rdp.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/rdp.c b/rdp.c index 76db804..65bf1f8 100644 --- a/rdp.c +++ b/rdp.c @@ -942,11 +942,18 @@ rdp_send_confirm_active(void) STREAM s; uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG; uint16 caplen = - RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER + + RDP_CAPLEN_GENERAL + + RDP_CAPLEN_BITMAP + + RDP_CAPLEN_ORDER + RDP_CAPLEN_COLCACHE + - RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL + + RDP_CAPLEN_ACTIVATE + + RDP_CAPLEN_CONTROL + RDP_CAPLEN_SHARE + - RDP_CAPLEN_BRUSHCACHE + 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ + + RDP_CAPLEN_BRUSHCACHE + + RDP_CAPLEN_INPUT + + RDP_CAPLEN_FONT + + RDP_CAPLEN_SOUND + + RDP_CAPLEN_GLYPHCACHE + 4 /* w2k fix, sessionid */ ; if (g_rdp_version >= RDP_V5)