Merge pull request #168 from derfian/issue66-ts_fp_update_pdu

Clarify capability sets and Fast-Path code
This commit is contained in:
Henrik Andersson 2017-10-16 12:34:45 +02:00 committed by GitHub
commit 0e530e6095
5 changed files with 347 additions and 155 deletions

View File

@ -23,6 +23,40 @@
#define DEFAULT_CODEPAGE "UTF-8" #define DEFAULT_CODEPAGE "UTF-8"
#define WINDOWS_CODEPAGE "UTF-16LE" #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
#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 */ /* ISO PDU codes */
enum ISO_PDU_CODE enum ISO_PDU_CODE
{ {
@ -220,10 +254,11 @@ enum RDP_POINTER_PDU_TYPE
RDP_POINTER_NEW = 8 RDP_POINTER_NEW = 8
}; };
/* [MS-RDPBCGR] 2.2.9.1.1.4.3 */
enum RDP_SYSTEM_POINTER_TYPE enum RDP_SYSTEM_POINTER_TYPE
{ {
RDP_NULL_POINTER = 0, SYSPTR_NULL = 0x00000000,
RDP_DEFAULT_POINTER = 0x7F00 SYSPTR_DEFAULT = 0x00007F00
}; };
enum RDP_INPUT_DEVICE enum RDP_INPUT_DEVICE
@ -324,9 +359,21 @@ enum RDP_INPUT_DEVICE
#define RDP_CAPSET_COLCACHE 10 #define RDP_CAPSET_COLCACHE 10
#define RDP_CAPLEN_COLCACHE 0x08 #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_CAPSET_BRUSHCACHE 15
#define RDP_CAPLEN_BRUSHCACHE 0x08 #define RDP_CAPLEN_BRUSHCACHE 0x08
#define RDP_CAPSET_GLYPHCACHE 16
#define RDP_CAPLEN_GLYPHCACHE 52
#define RDP_CAPSET_BMPCACHE2 19 #define RDP_CAPSET_BMPCACHE2 19
#define RDP_CAPLEN_BMPCACHE2 0x28 #define RDP_CAPLEN_BMPCACHE2 0x28
#define BMPCACHE2_FLAG_PERSIST ((uint32)1<<31) #define BMPCACHE2_FLAG_PERSIST ((uint32)1<<31)
@ -626,3 +673,70 @@ enum RDP_PDU_REDIRECT_FLAGS
LB_REDIRECTION_GUID = 0x8000, LB_REDIRECTION_GUID = 0x8000,
LB_TARGET_CERTIFICATE = 0x10000 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
/* 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
/* [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

15
iso.c
View File

@ -110,16 +110,17 @@ iso_recv_msg(uint8 * code, uint8 * rdpver)
in_uint8(s, version); in_uint8(s, version);
if (rdpver != NULL) if (rdpver != NULL)
*rdpver = version; *rdpver = version;
if (version == 3) if (IS_SLOWPATH(version))
{ {
in_uint8s(s, 1); /* pad */ in_uint8s(s, 1); /* reserved */
in_uint16_be(s, length); in_uint16_be(s, length); /* length */
} }
else else
{ {
in_uint8(s, length); in_uint8(s, length); /* length1 */
if (length & 0x80) if (length & 0x80)
{ {
/* length2 is only present if the most significant bit of length1 is set */
length &= ~0x80; length &= ~0x80;
next_be(s, length); next_be(s, length);
} }
@ -132,7 +133,7 @@ iso_recv_msg(uint8 * code, uint8 * rdpver)
s = tcp_recv(s, length - 4); s = tcp_recv(s, length - 4);
if (s == NULL) if (s == NULL)
return NULL; return NULL;
if (version != 3) if (IS_FASTPATH(version))
return s; return s;
in_uint8s(s, 1); /* hdrlen */ in_uint8s(s, 1); /* hdrlen */
in_uint8(s, *code); in_uint8(s, *code);
@ -166,7 +167,7 @@ iso_send(STREAM s)
s_pop_layer(s, iso_hdr); s_pop_layer(s, iso_hdr);
length = s->end - s->p; length = s->end - s->p;
out_uint8(s, 3); /* version */ out_uint8(s, T123_HEADER_VERSION); /* version */
out_uint8(s, 0); /* reserved */ out_uint8(s, 0); /* reserved */
out_uint16_be(s, length); out_uint16_be(s, length);
@ -188,7 +189,7 @@ iso_recv(uint8 * rdpver)
if (s == NULL) if (s == NULL)
return NULL; return NULL;
if (rdpver != NULL) if (rdpver != NULL)
if (*rdpver != 3) if (IS_FASTPATH(*rdpver))
return s; return s;
if (code != ISO_PDU_DT) if (code != ISO_PDU_DT)
{ {

View File

@ -144,7 +144,7 @@ int rd_write_file(int fd, void *ptr, int len);
int rd_lseek_file(int fd, int offset); int rd_lseek_file(int fd, int offset);
RD_BOOL rd_lock_file(int fd, int start, int len); RD_BOOL rd_lock_file(int fd, int start, int len);
/* rdp5.c */ /* rdp5.c */
void rdp5_process(STREAM s); void process_ts_fp_updates(STREAM s);
/* rdp.c */ /* rdp.c */
void rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size); 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, void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1,
@ -154,6 +154,7 @@ void process_colour_pointer_pdu(STREAM s);
void process_new_pointer_pdu(STREAM s); void process_new_pointer_pdu(STREAM s);
void process_cached_pointer_pdu(STREAM s); void process_cached_pointer_pdu(STREAM s);
void process_system_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_bitmap_updates(STREAM s);
void process_palette(STREAM s); void process_palette(STREAM s);
void process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason); void process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason);

307
rdp.c
View File

@ -4,6 +4,7 @@
Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright 2003-2011 Peter Astrand <astrand@cendio.se> for Cendio AB Copyright 2003-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
Copyright 2011-2017 Henrik Andersson <hean01@cendio.se> for Cendio AB Copyright 2011-2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
Copyright 2017 Karl Mikaelsson <derfian@cendio.se> for Cendio AB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -103,8 +104,8 @@ rdp_recv(uint8 * type)
} }
else if (rdpver != 3) else if (rdpver != 3)
{ {
/* rdp5_process should move g_next_packet ok */ /* process_ts_fp_updates moves g_next_packet */
rdp5_process(rdp_s); process_ts_fp_updates(rdp_s);
*type = 0; *type = 0;
return rdp_s; return rdp_s;
} }
@ -624,93 +625,112 @@ rdp_send_fonts(uint16 seq)
rdp_send_data(s, RDP_DATA_PDU_FONT2); rdp_send_data(s, RDP_DATA_PDU_FONT2);
} }
/* Output general capability set */ /* Output general capability set (TS_GENERAL_CAPABILITYSET) */
static void 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_CAPSET_GENERAL);
out_uint16_le(s, RDP_CAPLEN_GENERAL); out_uint16_le(s, RDP_CAPLEN_GENERAL);
out_uint16_le(s, OSMAJORTYPE_WINDOWS); /* osMajorType */
out_uint16_le(s, 1); /* OS major type */ out_uint16_le(s, OSMINORTYPE_WINDOWSNT); /* osMinorType */
out_uint16_le(s, 3); /* OS minor type */ out_uint16_le(s, TS_CAPS_PROTOCOLVERSION); /* protocolVersion (must be TS_CAPS_PROTOCOLVERSION) */
out_uint16_le(s, 0x200); /* Protocol version */ out_uint16_le(s, 0); /* pad2OctetsA */
out_uint16(s, 0); /* Pad */ out_uint16_le(s, 0); /* generalCompressionTypes (must be 0) */
out_uint16(s, 0); /* Compression types */ out_uint16_le(s, extraFlags); /* extraFlags */
out_uint16_le(s, (g_rdp_version >= RDP_V5) ? 0x40d : 0); out_uint16_le(s, 0); /* updateCapabilityFlag (must be 0) */
/* Pad, according to T.128. 0x40d seems to out_uint16_le(s, 0); /* remoteUnshareFlag (must be 0) */
trigger out_uint16_le(s, 0); /* generalCompressionLevel (must be 0) */
the server to start sending RDP5 packets. out_uint8(s, 0); /* refreshRectSupport */
However, the value is 0x1d04 with W2KTSK and out_uint8(s, 0); /* suppressOutputSupport */
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 */
} }
/* Output bitmap capability set */ /* Output bitmap capability set */
static void 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_CAPSET_BITMAP);
out_uint16_le(s, RDP_CAPLEN_BITMAP); out_uint16_le(s, RDP_CAPLEN_BITMAP);
out_uint16_le(s, g_server_depth); /* preferredBitsPerPixel */
out_uint16_le(s, g_server_depth); /* Preferred colour depth */ out_uint16_le(s, 1); /* receive1BitPerPixel (ignored, should be 1) */
out_uint16_le(s, 1); /* Receive 1 BPP */ out_uint16_le(s, 1); /* receive4BitPerPixel (ignored, should be 1) */
out_uint16_le(s, 1); /* Receive 4 BPP */ out_uint16_le(s, 1); /* receive8BitPerPixel (ignored, should be 1) */
out_uint16_le(s, 1); /* Receive 8 BPP */ out_uint16_le(s, 800); /* desktopWidth */
out_uint16_le(s, 800); /* Desktop width */ out_uint16_le(s, 600); /* desktopHeight */
out_uint16_le(s, 600); /* Desktop height */ out_uint16_le(s, 0); /* pad2Octets */
out_uint16(s, 0); /* Pad */ out_uint16_le(s, 1); /* desktopResizeFlag */
out_uint16(s, 1); /* Allow resize */ out_uint16_le(s, 1); /* bitmapCompressionFlag (must be 1) */
out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */ out_uint8(s, 0); /* highColorFlags (ignored, should be 0) */
out_uint16(s, 0); /* Unknown */ out_uint8(s, 0); /* drawingFlags */
out_uint16_le(s, 1); /* Unknown */ out_uint16_le(s, 1); /* multipleRectangleSupport (must be 1) */
out_uint16(s, 0); /* Pad */ out_uint16_le(s, 0); /* pad2OctetsB */
} }
/* Output order capability set */ /* Output order capability set */
static void static void
rdp_out_order_caps(STREAM s) rdp_out_ts_order_capabilityset(STREAM s)
{ {
uint8 order_caps[32]; uint8 order_caps[32];
uint16 orderflags = 0;
uint32 cachesize = 0;
orderflags |= (NEGOTIATEORDERSUPPORT | ZEROBOUNDSDELTASSUPPORT); /* mandatory flags */
orderflags |= COLORINDEXSUPPORT;
memset(order_caps, 0, 32); memset(order_caps, 0, 32);
order_caps[0] = 1; /* dest blt */
order_caps[1] = 1; /* pat blt */ order_caps[TS_NEG_DSTBLT_INDEX] = 1;
order_caps[2] = 1; /* screen blt */ order_caps[TS_NEG_PATBLT_INDEX] = 1;
order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */ order_caps[TS_NEG_SCRBLT_INDEX] = 1;
order_caps[4] = 0; /* triblt */ order_caps[TS_NEG_LINETO_INDEX] = 1;
order_caps[8] = 1; /* line */ order_caps[TS_NEG_MULTI_DRAWNINEGRID_INDEX] = 1;
order_caps[9] = 1; /* line */ order_caps[TS_NEG_POLYLINE_INDEX] = 1;
order_caps[10] = 1; /* rect */ order_caps[TS_NEG_INDEX_INDEX] = 1;
order_caps[11] = (g_desktop_save ? 1 : 0); /* desksave */
order_caps[13] = 1; /* memblt */ if (g_bitmap_cache)
order_caps[14] = 1; /* triblt */ order_caps[TS_NEG_MEMBLT_INDEX] = 1;
order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon */
order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon2 */ if (g_desktop_save)
order_caps[22] = 1; /* polyline */ {
order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse */ cachesize = 230400;
order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse2 */ order_caps[TS_NEG_SAVEBITMAP_INDEX] = 1;
order_caps[27] = 1; /* text2 */ }
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_CAPSET_ORDER);
out_uint16_le(s, RDP_CAPLEN_ORDER); out_uint16_le(s, RDP_CAPLEN_ORDER);
out_uint8s(s, 16); /* terminalDescriptor (ignored, should be 0) */
out_uint8s(s, 20); /* Terminal desc, pad */ out_uint8s(s, 4); /* pad4OctetsA */
out_uint16_le(s, 1); /* Cache X granularity */ out_uint16_le(s, 1); /* desktopSaveXGranularity (ignored, assumed to be 1) */
out_uint16_le(s, 20); /* Cache Y granularity */ out_uint16_le(s, 20); /* desktopSaveYGranularity (ignored, assumed to be 20) */
out_uint16(s, 0); /* Pad */ out_uint16_le(s, 0); /* Pad */
out_uint16_le(s, 1); /* Max order level */ out_uint16_le(s, 1); /* maximumOrderLevel (ignored, should be 1) */
out_uint16_le(s, 0x147); /* Number of fonts */ out_uint16_le(s, 0); /* numberFonts (ignored, should be 0) */
out_uint16_le(s, 0x2a); /* Capability flags */ out_uint16_le(s, orderflags); /* orderFlags */
out_uint8p(s, order_caps, 32); /* Orders supported */ out_uint8p(s, order_caps, 32); /* orderSupport */
out_uint16_le(s, 0x6a1); /* Text capability flags */ out_uint16_le(s, 0); /* textFlags (ignored) */
out_uint8s(s, 6); /* Pad */ out_uint16_le(s, 0); /* orderSupportExFlags */
out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */ out_uint32_le(s, 0); /* pad4OctetsB */
out_uint32(s, 0); /* Unknown */ out_uint32_le(s, cachesize); /* desktopSaveSize */
out_uint32_le(s, 0x4e4); /* Unknown */ 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 */ /* Output bitmap cache capability set */
@ -836,41 +856,82 @@ rdp_out_brushcache_caps(STREAM s)
out_uint32_le(s, 1); /* cache type */ out_uint32_le(s, 1); /* cache type */
} }
static uint8 caps_0x0d[] = { /* Output Input Capability Set */
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 */
static void 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); uint16 inputflags = 0;
out_uint16_le(s, length); 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 #define RDP5_FLAG 0x0030
@ -881,11 +942,18 @@ rdp_send_confirm_active(void)
STREAM s; STREAM s;
uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG; uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
uint16 caplen = 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_COLCACHE +
RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL + RDP_CAPLEN_ACTIVATE +
RDP_CAPLEN_CONTROL +
RDP_CAPLEN_SHARE + 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 */ ; 4 /* w2k fix, sessionid */ ;
if (g_rdp_version >= RDP_V5) if (g_rdp_version >= RDP_V5)
@ -914,9 +982,9 @@ rdp_send_confirm_active(void)
out_uint16_le(s, 0xe); /* num_caps */ out_uint16_le(s, 0xe); /* num_caps */
out_uint8s(s, 2); /* pad */ out_uint8s(s, 2); /* pad */
rdp_out_general_caps(s); rdp_out_ts_general_capabilityset(s);
rdp_out_bitmap_caps(s); rdp_out_ts_bitmap_capabilityset(s);
rdp_out_order_caps(s); rdp_out_ts_order_capabilityset(s);
if (g_rdp_version >= RDP_V5) if (g_rdp_version >= RDP_V5)
{ {
rdp_out_bmpcache2_caps(s); rdp_out_bmpcache2_caps(s);
@ -933,10 +1001,10 @@ rdp_send_confirm_active(void)
rdp_out_share_caps(s); rdp_out_share_caps(s);
rdp_out_brushcache_caps(s); rdp_out_brushcache_caps(s);
rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* CAPSTYPE_INPUT */ rdp_out_ts_input_capabilityset(s);
rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c); /* CAPSTYPE_SOUND */ rdp_out_ts_sound_capabilityset(s);
rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e); /* CAPSTYPE_FONT */ rdp_out_ts_font_capabilityset(s);
rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* CAPSTYPE_GLYPHCACHE */ rdp_out_ts_glyphcache_capabilityset(s);
s_mark_end(s); s_mark_end(s);
sec_send(s, sec_flags); sec_send(s, sec_flags);
@ -1139,19 +1207,26 @@ process_cached_pointer_pdu(STREAM s)
void void
process_system_pointer_pdu(STREAM s) 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); set_system_pointer(system_pointer_type);
switch (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(); ui_set_null_cursor();
break; break;
default: default:
logger(Protocol, Warning, logger(Protocol, Warning,
"process_system_pointer_pdu(), unhandled pointer type 0x%x", "set_system_pointer(), unhandled pointer type 0x%x",
system_pointer_type); ptr);
} }
} }

59
rdp5.c
View File

@ -1,8 +1,9 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Protocol services - RDP5 short form PDU processing Protocol services - RDP Fast-Path PDU processing
Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright 2003-2008 Erik Forsberg <forsberg@cendio.se> for Cendio AB Copyright 2003-2008 Erik Forsberg <forsberg@cendio.se> for Cendio AB
Copyright 2017 Karl Mikaelsson <derfian@cendio.se> for Cendio AB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -25,10 +26,10 @@ extern uint8 *g_next_packet;
extern RDPCOMP g_mppc_dict; extern RDPCOMP g_mppc_dict;
void void
rdp5_process(STREAM s) process_ts_fp_updates(STREAM s)
{ {
uint16 length, count, x, y; uint16 length, count, x, y;
uint8 type, ctype; uint8 hdr, code, frag, comp, ctype = 0;
uint8 *next; uint8 *next;
uint32 roff, rlen; uint32 roff, rlen;
@ -38,25 +39,24 @@ rdp5_process(STREAM s)
ui_begin_update(); ui_begin_update();
while (s->p < s->end) while (s->p < s->end)
{ {
in_uint8(s, type); /* Reading a number of TS_FP_UPDATE structures from the stream here.. */
if (type & RDP5_COMPRESSED) in_uint8(s, hdr); /* updateHeader */
{ code = hdr & 0x0F; /* |- updateCode */
in_uint8(s, ctype); frag = hdr & 0x30; /* |- fragmentation */
in_uint16_le(s, length); comp = hdr & 0xC0; /* `- compression */
type ^= RDP5_COMPRESSED;
} if (comp & FASTPATH_OUTPUT_COMPRESSION_USED)
else in_uint8(s, ctype); /* compressionFlags */
{
ctype = 0; in_uint16_le(s, length); /* length */
in_uint16_le(s, length);
}
g_next_packet = next = s->p + length; g_next_packet = next = s->p + length;
if (ctype & RDP_MPPC_COMPRESSED) if (ctype & RDP_MPPC_COMPRESSED)
{ {
if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1) if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1)
logger(Protocol, Error, 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 */ /* allocate memory and copy the uncompressed data into the temporary stream */
ns->data = (uint8 *) xrealloc(ns->data, rlen); ns->data = (uint8 *) xrealloc(ns->data, rlen);
@ -73,45 +73,46 @@ rdp5_process(STREAM s)
else else
ts = s; ts = s;
switch (type) switch (code)
{ {
case 0: /* update orders */ case FASTPATH_UPDATETYPE_ORDERS:
in_uint16_le(ts, count); in_uint16_le(ts, count);
process_orders(ts, count); process_orders(ts, count);
break; break;
case 1: /* update bitmap */ case FASTPATH_UPDATETYPE_BITMAP:
in_uint8s(ts, 2); /* part length */ in_uint8s(ts, 2); /* part length */
process_bitmap_updates(ts); process_bitmap_updates(ts);
break; break;
case 2: /* update palette */ case FASTPATH_UPDATETYPE_PALETTE:
in_uint8s(ts, 2); /* uint16 = 2 */ in_uint8s(ts, 2); /* uint16 = 2 */
process_palette(ts); process_palette(ts);
break; break;
case 3: /* update synchronize */ case FASTPATH_UPDATETYPE_SYNCHRONIZE:
break; break;
case 5: /* null pointer */ case FASTPATH_UPDATETYPE_PTR_NULL:
ui_set_null_cursor(); ui_set_null_cursor();
break; break;
case 6: /* default pointer */ case FASTPATH_UPDATETYPE_PTR_DEFAULT:
set_system_pointer(SYSPTR_DEFAULT);
break; break;
case 8: /* pointer position */ case FASTPATH_UPDATETYPE_PTR_POSITION:
in_uint16_le(ts, x); in_uint16_le(ts, x);
in_uint16_le(ts, y); in_uint16_le(ts, y);
if (s_check(ts)) if (s_check(ts))
ui_move_pointer(x, y); ui_move_pointer(x, y);
break; break;
case 9: /* color pointer */ case FASTPATH_UPDATETYPE_COLOR:
process_colour_pointer_pdu(ts); process_colour_pointer_pdu(ts);
break; break;
case 10: /* cached pointer */ case FASTPATH_UPDATETYPE_CACHED:
process_cached_pointer_pdu(ts); process_cached_pointer_pdu(ts);
break; break;
case 11: case FASTPATH_UPDATETYPE_POINTER:
process_new_pointer_pdu(ts); process_new_pointer_pdu(ts);
break; break;
default: default:
logger(Protocol, Warning, "rdp5_process(), unhandled opcode %d", logger(Protocol, Warning, "process_ts_fp_updates(), unhandled opcode %d",
type); code);
} }
s->p = next; s->p = next;