diff --git a/Makefile b/Makefile index 8d7f7e4..ba6c514 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ datadir = $(prefix)/share/rdesktop VERSION = 1.3.1 KEYMAP_PATH = $(datadir)/keymaps/ -RDPOBJ = tcp.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o +RDPOBJ = tcp.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o mppc.o X11OBJ = rdesktop.o xwin.o xkeymap.o ewmhints.o xclip.o cliprdr.o VNCOBJ = vnc/rdp2vnc.o vnc/vnc.o vnc/xkeymap.o vnc/x11stubs.o CRYPTOBJ = crypto/rc4_enc.o crypto/rc4_skey.o crypto/md5_dgst.o crypto/sha1dgst.o crypto/bn_exp.o crypto/bn_mul.o crypto/bn_div.o crypto/bn_sqr.o crypto/bn_add.o crypto/bn_shift.o crypto/bn_asm.o crypto/bn_ctx.o crypto/bn_lib.o diff --git a/constants.h b/constants.h index 709fb6d..57ae013 100644 --- a/constants.h +++ b/constants.h @@ -251,6 +251,12 @@ enum RDP_INPUT_DEVICE #define RDP5_NO_CURSOR_SHADOW 0x20 #define RDP5_NO_CURSORSETTINGS 0x40 /* disables cursor blinking */ +/* compression types */ +#define RDP_MPPC_COMPRESSED 0x20 +#define RDP_MPPC_RESET 0x40 +#define RDP_MPPC_FLUSH 0x80 +#define RDP_MPPC_DICT_SIZE 8192 + /* Keymap flags */ #define MapRightShiftMask (1<<0) #define MapLeftShiftMask (1<<1) diff --git a/orders.c b/orders.c index ebf0c44..d24eb4b 100644 --- a/orders.c +++ b/orders.c @@ -948,9 +948,12 @@ process_orders(STREAM s, uint16 num_orders) processed++; } - +#if 0 + /* not true when RDP_COMPRESSION is set */ if (s->p != g_next_packet) error("%d bytes remaining\n", (int) (g_next_packet - s->p)); +#endif + } /* Reset order state */ diff --git a/proto.h b/proto.h index 879b75e..5fa9836 100644 --- a/proto.h +++ b/proto.h @@ -31,6 +31,8 @@ NTSTATUS disk_query_information(HANDLE handle, uint32 info_class, STREAM out); NTSTATUS disk_set_information(HANDLE handle, uint32 info_class, STREAM in, STREAM out); NTSTATUS disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out); NTSTATUS disk_query_directory(HANDLE handle, uint32 info_class, char *pattern, STREAM out); +/* mppc.c */ +int mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen); /* ewmhints.c */ int get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height); /* iso.c */ diff --git a/rdp.c b/rdp.c index b09c887..0805995 100644 --- a/rdp.c +++ b/rdp.c @@ -38,6 +38,8 @@ extern BOOL g_bitmap_cache; uint8 *g_next_packet; uint32 g_rdp_shareid; +extern RDPCOMP mppc_dict; + #if WITH_DEBUG static uint32 g_packetno; #endif @@ -174,15 +176,16 @@ rdp_send_logon_info(uint32 flags, char *domain, char *user, time_t t = time(NULL); time_t tzone; -#if 0 - // enable rdp compression - flags |= RDP_COMPRESSION; -#endif - if (!g_use_rdp5 || 1 == g_server_rdp_version) { DEBUG_RDP5(("Sending RDP4-style Logon packet\n")); +#if 0 + /* enable rdp compression */ + /* decompression also works with rdp5 */ + /* but there are some unknown opcodes */ + flags |= RDP_COMPRESSION; +#endif s = sec_init(sec_flags, 18 + len_domain + len_user + len_password + len_program + len_directory + 10); @@ -201,6 +204,7 @@ rdp_send_logon_info(uint32 flags, char *domain, char *user, } else { + flags |= RDP_LOGON_BLOB; DEBUG_RDP5(("Sending RDP5-style Logon packet\n")); packetlen = 4 + /* Unknown uint32 */ @@ -437,7 +441,7 @@ rdp_out_order_caps(STREAM s) 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[3] = (g_bitmap_cache ? 1 : 0); /* memblt */ order_caps[8] = 1; /* line */ order_caps[9] = 1; /* line */ order_caps[10] = 1; /* rect */ @@ -954,12 +958,12 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason) uint8 data_pdu_type; uint8 ctype; uint16 clen; - int len; -#if 0 - int roff, rlen, ret; - static struct stream ns; - static signed char *dict = 0; -#endif + uint32 len; + + uint32 roff, rlen; + + struct stream *ns = &(mppc_dict.ns); + uint8 *dict = (mppc_dict.hist); in_uint8s(s, 6); /* shareid, pad, streamid */ in_uint16(s, len); @@ -968,31 +972,30 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason) in_uint16(s, clen); clen -= 18; -#if 0 - if (ctype & 0x20) + if (ctype & RDP_MPPC_COMPRESSED) { - if (!dict) - { - dict = (signed char *) malloc(8200 * sizeof(signed char)); - dict = (signed char *) memset(dict, 0, 8200 * sizeof(signed char)); - } - ret = decompress(s->p, clen, ctype, (signed char *) dict, &roff, &rlen); + if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1) + error("error while decompressing packet\n"); len -= 18; - ns.data = xrealloc(ns.data, len); + /* this should never happen */ + if (len != rlen) + error("decompression error len != rlen\n"); - ns.data = (unsigned char *) memcpy(ns.data, (unsigned char *) (dict + roff), len); + /* allocate memory and copy the uncompressed data into the temporary stream */ + ns->data = xrealloc(ns->data, len); - ns.size = len; - ns.end = ns.data + ns.size; - ns.p = ns.data; - ns.rdp_hdr = ns.p; + memcpy((ns->data), (unsigned char *) (mppc_dict.hist + roff), len); - s = &ns; + ns->size = len; + ns->end = (ns->data + ns->size); + ns->p = ns->data; + ns->rdp_hdr = ns->p; + + s = ns; } -#endif switch (data_pdu_type) { diff --git a/types.h b/types.h index 33b4509..abc79db 100644 --- a/types.h +++ b/types.h @@ -134,6 +134,14 @@ typedef struct uint8 cb[MAX_CBSIZE]; } WAVEFORMATEX; +typedef struct _RDPCOMP +{ + uint32 roff; + uint8 hist[RDP_MPPC_DICT_SIZE]; + struct stream ns; +} +RDPCOMP; + /* RDPDR */ typedef uint32 NTSTATUS; typedef uint32 HANDLE;