diff options
Diffstat (limited to 'libxrdp')
-rw-r--r-- | libxrdp/Makefile.am | 8 | ||||
-rw-r--r-- | libxrdp/libxrdp.c | 418 | ||||
-rw-r--r-- | libxrdp/libxrdp.h | 615 | ||||
-rw-r--r-- | libxrdp/libxrdpinc.h | 218 | ||||
-rw-r--r-- | libxrdp/xrdp_bitmap32_compress.c | 508 | ||||
-rw-r--r-- | libxrdp/xrdp_caps.c | 916 | ||||
-rw-r--r-- | libxrdp/xrdp_channel.c | 19 | ||||
-rw-r--r-- | libxrdp/xrdp_fastpath.c | 391 | ||||
-rw-r--r-- | libxrdp/xrdp_iso.c | 304 | ||||
-rw-r--r-- | libxrdp/xrdp_jpeg_compress.c | 44 | ||||
-rw-r--r-- | libxrdp/xrdp_mcs.c | 288 | ||||
-rw-r--r-- | libxrdp/xrdp_mppc_enc.c | 62 | ||||
-rw-r--r-- | libxrdp/xrdp_orders.c | 183 | ||||
-rw-r--r-- | libxrdp/xrdp_orders_rail.h | 24 | ||||
-rw-r--r-- | libxrdp/xrdp_rdp.c | 1111 | ||||
-rw-r--r-- | libxrdp/xrdp_sec.c | 836 |
16 files changed, 3951 insertions, 1994 deletions
diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am index e83fce10..bd37cad4 100644 --- a/libxrdp/Makefile.am +++ b/libxrdp/Makefile.am @@ -18,8 +18,8 @@ endif if XRDP_TJPEG EXTRA_DEFINES += -DXRDP_JPEG -DXRDP_TJPEG -EXTRA_INCLUDES += -I/opt/libjpeg-turbo/include -EXTRA_FLAGS += -L/opt/libjpeg-turbo/lib -Wl,-rpath -Wl,/opt/libjpeg-turbo/lib +EXTRA_INCLUDES += @TurboJpegIncDir@ +EXTRA_FLAGS += @TurboJpegLibDir@ EXTRA_LIBS += -lturbojpeg else if XRDP_JPEG @@ -59,7 +59,9 @@ libxrdp_la_SOURCES = \ xrdp_bitmap32_compress.c \ xrdp_jpeg_compress.c \ xrdp_orders_rail.c \ - xrdp_mppc_enc.c + xrdp_mppc_enc.c \ + xrdp_fastpath.c \ + xrdp_caps.c libxrdp_la_LDFLAGS = \ $(EXTRA_FLAGS) diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index 7ab1f914..df755f2b 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -21,6 +21,12 @@ #include "libxrdp.h" #include "xrdp_orders_rail.h" +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) + /******************************************************************************/ struct xrdp_session *EXPORT_CC libxrdp_init(tbus id, struct trans *trans) @@ -29,6 +35,7 @@ libxrdp_init(tbus id, struct trans *trans) session = (struct xrdp_session *)g_malloc(sizeof(struct xrdp_session), 1); session->id = id; + session->trans = trans; session->rdp = xrdp_rdp_create(session, trans); session->orders = xrdp_orders_create(session, (struct xrdp_rdp *)session->rdp); session->client_info = &(((struct xrdp_rdp *)session->rdp)->client_info); @@ -61,7 +68,103 @@ libxrdp_disconnect(struct xrdp_session *session) int EXPORT_CC libxrdp_process_incomming(struct xrdp_session *session) { - return xrdp_rdp_incoming((struct xrdp_rdp *)session->rdp); + int rv; + + rv = xrdp_rdp_incoming((struct xrdp_rdp *)(session->rdp)); + return rv; +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_get_pdu_bytes(const char *aheader) +{ + int rv; + const tui8 *header; + + rv = -1; + header = (const tui8 *) aheader; + + if (header[0] == 0x03) + { + /* TPKT */ + rv = (header[2] << 8) | header[3]; + } + else if (header[0] == 0x30) + { + /* TSRequest (NLA) */ + if (header[1] & 0x80) + { + if ((header[1] & ~(0x80)) == 1) + { + rv = header[2]; + rv += 3; + } + else if ((header[1] & ~(0x80)) == 2) + { + rv = (header[2] << 8) | header[3]; + rv += 4; + } + else + { + g_writeln("libxrdp_get_pdu_bytes: error TSRequest!"); + return -1; + } + } + else + { + rv = header[1]; + rv += 2; + } + } + else + { + /* Fast-Path */ + if (header[1] & 0x80) + { + rv = ((header[1] & 0x7F) << 8) | header[2]; + } + else + { + rv = header[1]; + } + } + return rv; +} + +/******************************************************************************/ +/* only used durring connection */ +struct stream * APP_CC +libxrdp_force_read(struct trans* trans) +{ + int bytes; + struct stream *s; + + s = trans->in_s; + init_stream(s, 32 * 1024); + + if (trans_force_read(trans, 4) != 0) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + bytes = libxrdp_get_pdu_bytes(s->data); + if (bytes < 1) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + if (bytes > 32 * 1024) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + + if (trans_force_read(trans, bytes - 4) != 0) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + return s; } /******************************************************************************/ @@ -73,9 +176,15 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) int code; int term; int dead_lock_counter; + int do_read; struct xrdp_rdp *rdp; - struct stream *ls; + do_read = s == 0; + if (do_read && session->up_and_running) + { + g_writeln("libxrdp_process_data: error logic"); + return 1; + } if (session->in_process_data != 0) { g_writeln("libxrdp_process_data: error reentry"); @@ -83,14 +192,6 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) } session->in_process_data++; - ls = 0; - if (s == 0) - { - make_stream(ls); - init_stream(ls, 8192 * 4); - s = ls; - } - term = 0; cont = 1; rv = 0; @@ -105,13 +206,36 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) if (session->is_term()) { term = 1; + break; } } code = 0; + if (do_read) + { + if (s == 0) + { + s = libxrdp_force_read(session->trans); + } + else + { + if ((s->next_packet == 0) || (s->next_packet >= s->end)) + { + s = libxrdp_force_read(session->trans); + } + } + if (s == 0) + { + g_writeln("libxrdp_process_data: libxrdp_force_read failed"); + rv = 1; + break; + } + } + if (xrdp_rdp_recv(rdp, s, &code) != 0) { + g_writeln("libxrdp_process_data: xrdp_rdp_recv failed"); rv = 1; break; } @@ -121,39 +245,33 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) switch (code) { case -1: - xrdp_rdp_send_demand_active(rdp); - - /* send Monitor Layout PDU for multimon */ - if (session->client_info->monitorCount > 0 && - session->client_info->multimon == 1) - { - DEBUG(("sending monitor layout pdu")); - if (xrdp_rdp_send_monitorlayout(rdp) != 0) - { - g_writeln("xrdp_rdp_send_monitorlayout: error"); - } - } - + xrdp_caps_send_demand_active(rdp); session->up_and_running = 0; break; case 0: dead_lock_counter++; break; case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ - xrdp_rdp_process_confirm_active(rdp, s); + xrdp_caps_process_confirm_active(rdp, s); break; case RDP_PDU_DATA: /* 7 */ - if (xrdp_rdp_process_data(rdp, s) != 0) { DEBUG(("libxrdp_process_data returned non zero")); cont = 0; term = 1; } - + break; + case 2: /* FASTPATH_INPUT_EVENT */ + if (xrdp_fastpath_process_input_event(rdp->sec_layer->fastpath_layer, s) != 0) + { + DEBUG(("libxrdp_process_data returned non zero")); + cont = 0; + term = 1; + } break; default: - g_writeln("unknown in libxrdp_process_data"); + g_writeln("unknown in libxrdp_process_data: code= %d", code); dead_lock_counter++; break; } @@ -169,16 +287,10 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) if (cont) { - cont = (s->next_packet != 0) && - (s->next_packet < s->end); + cont = (s->next_packet != 0) && (s->next_packet < s->end); } } - if (s == ls) - { - free_stream(s); - } - session->in_process_data--; return rv; @@ -198,11 +310,27 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette) } DEBUG(("libxrdp_send_palette sending palette")); + /* clear orders */ libxrdp_orders_force_send(session); make_stream(s); init_stream(s, 8192); - xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + LLOGLN(10, ("libxrdp_send_palette: fastpath")); + if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) + { + free_stream(s); + return 1; + } + } + else { + LLOGLN(10, ("libxrdp_send_palette: slowpath")); + xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + } + + /* TS_UPDATE_PALETTE_DATA */ out_uint16_le(s, RDP_UPDATE_PALETTE); out_uint16_le(s, 0); out_uint16_le(s, 256); /* # of colors */ @@ -217,8 +345,22 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette) } s_mark_end(s); - xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_UPDATE); + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_PALETTE) != 0) + { + free_stream(s); + return 1; + } + } + else + { + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, + RDP_DATA_PDU_UPDATE); + } free_stream(s); + /* send the orders palette too */ libxrdp_orders_init(session); libxrdp_orders_send_palette(session, palette, 0); @@ -482,20 +624,46 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, } make_stream(s); init_stream(s, 8192); - xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); - if ((session->client_info->pointer_flags & 1) == 0) + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ { - out_uint16_le(s, RDP_POINTER_COLOR); - out_uint16_le(s, 0); /* pad */ - data_bytes = 3072; + LLOGLN(10, ("libxrdp_send_pointer: fastpath")); + if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) + { + free_stream(s); + return 1; + } + + if ((session->client_info->pointer_flags & 1) == 0) + { + data_bytes = 3072; + } + else + { + data_bytes = ((bpp + 7) / 8) * 32 * 32; + out_uint16_le(s, bpp); + } } - else + else /* slowpath */ { - out_uint16_le(s, RDP_POINTER_POINTER); - out_uint16_le(s, 0); /* pad */ - out_uint16_le(s, bpp); - data_bytes = ((bpp + 7) / 8) * 32 * 32; + LLOGLN(10, ("libxrdp_send_pointer: slowpath")); + xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + if ((session->client_info->pointer_flags & 1) == 0) + { + out_uint16_le(s, RDP_POINTER_COLOR); + out_uint16_le(s, 0); /* pad */ + data_bytes = 3072; + } + else + { + out_uint16_le(s, RDP_POINTER_POINTER); + out_uint16_le(s, 0); /* pad */ + out_uint16_le(s, bpp); + data_bytes = ((bpp + 7) / 8) * 32 * 32; + } } + + out_uint16_le(s, cache_idx); /* cache_idx */ out_uint16_le(s, x); out_uint16_le(s, y); @@ -506,7 +674,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, switch (bpp) { - case 15: + //case 15: /* coverity: this is logically dead code */ case 16: p16 = (tui16 *) data; for (i = 0; i < 32; i++) @@ -547,9 +715,34 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, } out_uint8a(s, mask, 128); /* mask */ + out_uint8(s, 0); /* pad */ s_mark_end(s); - xrdp_rdp_send_data((struct xrdp_rdp *)(session->rdp), s, - RDP_DATA_PDU_POINTER); + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + if ((session->client_info->pointer_flags & 1) == 0) + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_COLOR) != 0) + { + free_stream(s); + return 1; + } + } + else + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_POINTER) != 0) + { + free_stream(s); + return 1; + } + } + } + else + { + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, + RDP_DATA_PDU_POINTER); + } free_stream(s); return 0; } @@ -563,12 +756,41 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx) DEBUG(("libxrdp_set_pointer sending cursor index")); make_stream(s); init_stream(s, 8192); - xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); - out_uint16_le(s, RDP_POINTER_CACHED); - out_uint16_le(s, 0); /* pad */ + + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + LLOGLN(10, ("libxrdp_send_pointer: fastpath")); + if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) + { + return 1; + } + } + else + { + LLOGLN(10, ("libxrdp_send_pointer: slowpath")); + xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + out_uint16_le(s, RDP_POINTER_CACHED); + out_uint16_le(s, 0); /* pad */ + } + out_uint16_le(s, cache_idx); /* cache_idx */ s_mark_end(s); - xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_POINTER); + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_CACHED) != 0) + { + free_stream(s); + return 1; + } + } + else + { + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, + RDP_DATA_PDU_POINTER); + } free_stream(s); return 0; } @@ -782,7 +1004,7 @@ libxrdp_reset(struct xrdp_session *session, } /* this should do the resizing */ - if (xrdp_rdp_send_demand_active((struct xrdp_rdp *)session->rdp) != 0) + if (xrdp_caps_send_demand_active((struct xrdp_rdp *)session->rdp) != 0) { return 1; } @@ -1079,3 +1301,91 @@ libxrdp_monitored_desktop(struct xrdp_session *session, orders = (struct xrdp_orders *)(session->orders); return xrdp_orders_send_monitored_desktop(orders, mdo, flags); } + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_codec_jpeg_compress(struct xrdp_session *session, + int format, char *inp_data, + int width, int height, + int stride, int x, int y, + int cx, int cy, int quality, + char *out_data, int *io_len) +{ + struct xrdp_orders *orders; + void* jpeg_han; + + orders = (struct xrdp_orders *)(session->orders); + jpeg_han = orders->jpeg_han; + return xrdp_codec_jpeg_compress(jpeg_han, format, inp_data, + width, height, stride, x, y, + cx, cy, quality, out_data, io_len); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_fastpath_send_surface(struct xrdp_session *session, + char* data_pad, int pad_bytes, + int data_bytes, + int destLeft, int destTop, + int destRight, int destBottom, int bpp, + int codecID, int width, int height) +{ + struct stream ls; + struct stream *s; + struct xrdp_rdp *rdp; + int rv; + int sec_bytes; + int rdp_bytes; + int max_bytes; + int cmd_bytes; + + LLOGLN(10, ("libxrdp_fastpath_init:")); + if ((session->client_info->use_fast_path & 1) == 0) + { + return 1; + } + max_bytes = session->client_info->max_fastpath_frag_bytes; + if (max_bytes < 32 * 1024) + { + max_bytes = 32 * 1024; + } + rdp = (struct xrdp_rdp *) (session->rdp); + rdp_bytes = xrdp_rdp_get_fastpath_bytes(rdp); + sec_bytes = xrdp_sec_get_fastpath_bytes(rdp->sec_layer); + cmd_bytes = 10 + 12; + if (data_bytes + rdp_bytes + sec_bytes + cmd_bytes > max_bytes) + { + return 1; + } + if (sec_bytes + rdp_bytes + cmd_bytes > pad_bytes) + { + return 1; + } + g_memset(&ls, 0, sizeof(ls)); + s = &ls; + s->data = (data_pad + pad_bytes) - (rdp_bytes + sec_bytes + cmd_bytes); + s->sec_hdr = s->data; + s->rdp_hdr = s->sec_hdr + sec_bytes; + s->end = data_pad + pad_bytes + data_bytes; + s->p = s->data + (rdp_bytes + sec_bytes); + /* TS_SURFCMD_SET_SURF_BITS */ + out_uint16_le(s, 0x0001); /* CMDTYPE_SET_SURFACE_BITS */ + out_uint16_le(s, destLeft); + out_uint16_le(s, destTop); + out_uint16_le(s, destRight); + out_uint16_le(s, destBottom); + /* TS_ BITMAP_DATA_EX */ + out_uint8(s, bpp); + out_uint8(s, 0); + out_uint8(s, 0); + out_uint8(s, codecID); + out_uint16_le(s, width); + out_uint16_le(s, height); + out_uint32_le(s, data_bytes); + /* 4 = FASTPATH_UPDATETYPE_SURFCMDS */ + if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0) + { + return 1; + } + return 0; +} diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index d9e5e6d1..0bda9f45 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -37,33 +37,46 @@ #include "file_loc.h" #include "xrdp_client_info.h" + /* iso */ struct xrdp_iso { - struct xrdp_mcs* mcs_layer; /* owner */ - int requestedProtocol; - int selectedProtocol; - struct trans* trans; + struct xrdp_mcs *mcs_layer; /* owner */ + int rdpNegData; /* bool */ + int requestedProtocol; + int selectedProtocol; + int failureCode; + struct trans *trans; }; /* used in mcs */ struct mcs_channel_item { - char name[16]; - int flags; - int chanid; + char name[16]; + int flags; + int chanid; }; /* mcs */ struct xrdp_mcs { - struct xrdp_sec* sec_layer; /* owner */ - struct xrdp_iso* iso_layer; - int userid; - int chanid; - struct stream* client_mcs_data; - struct stream* server_mcs_data; - struct list* channel_list; + struct xrdp_sec *sec_layer; /* owner */ + struct xrdp_iso *iso_layer; + int userid; + int chanid; + struct stream *client_mcs_data; + struct stream *server_mcs_data; + struct list *channel_list; +}; + +/* fastpath */ +struct xrdp_fastpath +{ + struct xrdp_sec *sec_layer; /* owner */ + struct trans *trans; + struct xrdp_session *session; + int numEvents; + int secFlags; }; /* Encryption Methods */ @@ -80,177 +93,181 @@ struct xrdp_mcs #define CRYPT_LEVEL_HIGH 0x00000003 #define CRYPT_LEVEL_FIPS 0x00000004 + /* sec */ struct xrdp_sec { - struct xrdp_rdp* rdp_layer; /* owner */ - struct xrdp_mcs* mcs_layer; - struct xrdp_channel* chan_layer; - char server_random[32]; - char client_random[64]; - char client_crypt_random[72]; - struct stream client_mcs_data; - struct stream server_mcs_data; - int decrypt_use_count; - int encrypt_use_count; - char decrypt_key[16]; - char encrypt_key[16]; - char decrypt_update_key[16]; - char encrypt_update_key[16]; - int crypt_method; - int rc4_key_len; /* 8 = 40 bit, 16 = 128 bit */ - int crypt_level; - char sign_key[16]; - void* decrypt_rc4_info; - void* encrypt_rc4_info; - char pub_exp[4]; - char pub_mod[64]; - char pub_sig[64]; - char pri_exp[64]; - int channel_code; - int multimon; - char fips_encrypt_key[24]; - char fips_decrypt_key[24]; - char fips_sign_key[20]; - void* encrypt_fips_info; - void* decrypt_fips_info; - void* sign_fips_info; + struct xrdp_rdp *rdp_layer; /* owner */ + struct xrdp_mcs *mcs_layer; + struct xrdp_fastpath *fastpath_layer; + struct xrdp_channel *chan_layer; + char server_random[32]; + char client_random[256]; + char client_crypt_random[256 + 8]; /* 64 + 8, 256 + 8 */ + struct stream client_mcs_data; + struct stream server_mcs_data; + int decrypt_use_count; + int encrypt_use_count; + char decrypt_key[16]; + char encrypt_key[16]; + char decrypt_update_key[16]; + char encrypt_update_key[16]; + int crypt_method; + int rc4_key_len; /* 8 = 40 bit, 16 = 128 bit */ + int crypt_level; + char sign_key[16]; + void *decrypt_rc4_info; + void *encrypt_rc4_info; + char pub_exp[4]; + char pub_mod[256]; + char pub_sig[64]; + char pri_exp[256]; + int rsa_key_bytes; /* 64 or 256 , 0 = no rdp security */ + char fips_encrypt_key[24]; + char fips_decrypt_key[24]; + char fips_sign_key[20]; + void *encrypt_fips_info; + void *decrypt_fips_info; + void *sign_fips_info; }; /* channel */ struct xrdp_channel { - struct xrdp_sec* sec_layer; - struct xrdp_mcs* mcs_layer; + struct xrdp_sec *sec_layer; + struct xrdp_mcs *mcs_layer; }; /* rdp */ struct xrdp_rdp { - struct xrdp_session* session; - struct xrdp_sec* sec_layer; - int share_id; - int mcs_channel; - struct xrdp_client_info client_info; - struct xrdp_mppc_enc* mppc_enc; - void* rfx_enc; + struct xrdp_session *session; + struct xrdp_sec *sec_layer; + int share_id; + int mcs_channel; + struct xrdp_client_info client_info; + struct xrdp_mppc_enc *mppc_enc; + void *rfx_enc; }; /* state */ struct xrdp_orders_state { - int last_order; /* last order sent */ - - int clip_left; /* RDP_ORDER_BOUNDS, RDP_ORDER_LASTBOUNDS */ - int clip_top; - int clip_right; - int clip_bottom; - - int rect_x; /* RDP_ORDER_RECT */ - int rect_y; - int rect_cx; - int rect_cy; - int rect_color; - - int scr_blt_x; /* RDP_ORDER_SCREENBLT */ - int scr_blt_y; - int scr_blt_cx; - int scr_blt_cy; - int scr_blt_rop; - int scr_blt_srcx; - int scr_blt_srcy; - - int pat_blt_x; /* RDP_ORDER_PATBLT */ - int pat_blt_y; - int pat_blt_cx; - int pat_blt_cy; - int pat_blt_rop; - int pat_blt_bg_color; - int pat_blt_fg_color; - struct xrdp_brush pat_blt_brush; - - int dest_blt_x; /* RDP_ORDER_DESTBLT */ - int dest_blt_y; - int dest_blt_cx; - int dest_blt_cy; - int dest_blt_rop; - - int line_mix_mode; /* RDP_ORDER_LINE */ - int line_startx; - int line_starty; - int line_endx; - int line_endy; - int line_bg_color; - int line_rop; - struct xrdp_pen line_pen; - - int mem_blt_color_table; /* RDP_ORDER_MEMBLT */ - int mem_blt_cache_id; - int mem_blt_x; - int mem_blt_y; - int mem_blt_cx; - int mem_blt_cy; - int mem_blt_rop; - int mem_blt_srcx; - int mem_blt_srcy; - int mem_blt_cache_idx; - - int text_font; /* RDP_ORDER_TEXT2 */ - int text_flags; - int text_unknown; - int text_mixmode; - int text_fg_color; - int text_bg_color; - int text_clip_left; - int text_clip_top; - int text_clip_right; - int text_clip_bottom; - int text_box_left; - int text_box_top; - int text_box_right; - int text_box_bottom; - int text_x; - int text_y; - int text_len; - char* text_data; - - int com_blt_srcidx; /* RDP_ORDER_COMPOSITE */ /* 2 */ - int com_blt_srcformat; /* 2 */ - int com_blt_srcwidth; /* 2 */ - int com_blt_srcrepeat; /* 1 */ - int com_blt_srctransform[10]; /* 40 */ - int com_blt_mskflags; /* 1 */ - int com_blt_mskidx; /* 2 */ - int com_blt_mskformat; /* 2 */ - int com_blt_mskwidth; /* 2 */ - int com_blt_mskrepeat; /* 1 */ - int com_blt_op; /* 1 */ - int com_blt_srcx; /* 2 */ - int com_blt_srcy; /* 2 */ - int com_blt_mskx; /* 2 */ - int com_blt_msky; /* 2 */ - int com_blt_dstx; /* 2 */ - int com_blt_dsty; /* 2 */ - int com_blt_width; /* 2 */ - int com_blt_height; /* 2 */ - int com_blt_dstformat; /* 2 */ + int last_order; /* last order sent */ + + int clip_left; /* RDP_ORDER_BOUNDS, RDP_ORDER_LASTBOUNDS */ + int clip_top; + int clip_right; + int clip_bottom; + + int rect_x; /* RDP_ORDER_RECT */ + int rect_y; + int rect_cx; + int rect_cy; + int rect_color; + + int scr_blt_x; /* RDP_ORDER_SCREENBLT */ + int scr_blt_y; + int scr_blt_cx; + int scr_blt_cy; + int scr_blt_rop; + int scr_blt_srcx; + int scr_blt_srcy; + + int pat_blt_x; /* RDP_ORDER_PATBLT */ + int pat_blt_y; + int pat_blt_cx; + int pat_blt_cy; + int pat_blt_rop; + int pat_blt_bg_color; + int pat_blt_fg_color; + struct xrdp_brush pat_blt_brush; + + int dest_blt_x; /* RDP_ORDER_DESTBLT */ + int dest_blt_y; + int dest_blt_cx; + int dest_blt_cy; + int dest_blt_rop; + + int line_mix_mode; /* RDP_ORDER_LINE */ + int line_startx; + int line_starty; + int line_endx; + int line_endy; + int line_bg_color; + int line_rop; + struct xrdp_pen line_pen; + + int mem_blt_color_table; /* RDP_ORDER_MEMBLT */ + int mem_blt_cache_id; + int mem_blt_x; + int mem_blt_y; + int mem_blt_cx; + int mem_blt_cy; + int mem_blt_rop; + int mem_blt_srcx; + int mem_blt_srcy; + int mem_blt_cache_idx; + + int text_font; /* RDP_ORDER_TEXT2 */ + int text_flags; + int text_unknown; + int text_mixmode; + int text_fg_color; + int text_bg_color; + int text_clip_left; + int text_clip_top; + int text_clip_right; + int text_clip_bottom; + int text_box_left; + int text_box_top; + int text_box_right; + int text_box_bottom; + int text_x; + int text_y; + int text_len; + char *text_data; + + int com_blt_srcidx; /* RDP_ORDER_COMPOSITE */ /* 2 */ + int com_blt_srcformat; /* 2 */ + int com_blt_srcwidth; /* 2 */ + int com_blt_srcrepeat; /* 1 */ + int com_blt_srctransform[10]; /* 40 */ + int com_blt_mskflags; /* 1 */ + int com_blt_mskidx; /* 2 */ + int com_blt_mskformat; /* 2 */ + int com_blt_mskwidth; /* 2 */ + int com_blt_mskrepeat; /* 1 */ + int com_blt_op; /* 1 */ + int com_blt_srcx; /* 2 */ + int com_blt_srcy; /* 2 */ + int com_blt_mskx; /* 2 */ + int com_blt_msky; /* 2 */ + int com_blt_dstx; /* 2 */ + int com_blt_dsty; /* 2 */ + int com_blt_width; /* 2 */ + int com_blt_height; /* 2 */ + int com_blt_dstformat; /* 2 */ }; /* orders */ struct xrdp_orders { - struct stream* out_s; - struct xrdp_rdp* rdp_layer; - struct xrdp_session* session; - struct xrdp_wm* wm; - - char* order_count_ptr; /* pointer to count, set when sending */ - int order_count; - int order_level; /* inc for every call to xrdp_orders_init */ - struct xrdp_orders_state orders_state; - void* jpeg_han; - int rfx_min_pixel; + struct stream *out_s; + struct xrdp_rdp *rdp_layer; + struct xrdp_session *session; + struct xrdp_wm *wm; + + char *order_count_ptr; /* pointer to count, set when sending */ + int order_count; + int order_level; /* inc for every call to xrdp_orders_init */ + struct xrdp_orders_state orders_state; + void *jpeg_han; + int rfx_min_pixel; + /* shared */ + struct stream *s; + struct stream *temp_s; }; #define PROTO_RDP_40 1 @@ -258,19 +275,20 @@ struct xrdp_orders struct xrdp_mppc_enc { - int protocol_type; /* PROTO_RDP_40, PROTO_RDP_50 etc */ - char *historyBuffer; /* contains uncompressed data */ - char *outputBuffer; /* contains compressed data */ - char *outputBufferPlus; - int historyOffset; /* next free slot in historyBuffer */ - int buf_len; /* length of historyBuffer, protocol dependant */ - int bytes_in_opb; /* compressed bytes available in outputBuffer */ - int flags; /* PACKET_COMPRESSED, PACKET_AT_FRONT, PACKET_FLUSHED etc */ - int flagsHold; - int first_pkt; /* this is the first pkt passing through enc */ - tui16 *hash_table; + int protocol_type; /* PROTO_RDP_40, PROTO_RDP_50 etc */ + char *historyBuffer; /* contains uncompressed data */ + char *outputBuffer; /* contains compressed data */ + char *outputBufferPlus; + int historyOffset; /* next free slot in historyBuffer */ + int buf_len; /* length of historyBuffer, protocol dependant */ + int bytes_in_opb; /* compressed bytes available in outputBuffer */ + int flags; /* PACKET_COMPRESSED, PACKET_AT_FRONT, PACKET_FLUSHED etc */ + int flagsHold; + int first_pkt; /* this is the first pkt passing through enc */ + tui16 *hash_table; }; + int APP_CC compress_rdp(struct xrdp_mppc_enc *enc, tui8 *srcData, int len); struct xrdp_mppc_enc * APP_CC @@ -279,217 +297,225 @@ void APP_CC mppc_enc_free(struct xrdp_mppc_enc *enc); /* xrdp_tcp.c */ -struct xrdp_tcp* APP_CC -xrdp_tcp_create(struct xrdp_iso* owner, struct trans* trans); +struct xrdp_tcp * APP_CC +xrdp_tcp_create(struct xrdp_iso *owner, struct trans *trans); void APP_CC -xrdp_tcp_delete(struct xrdp_tcp* self); +xrdp_tcp_delete(struct xrdp_tcp *self); int APP_CC -xrdp_tcp_init(struct xrdp_tcp* self, struct stream* s); +xrdp_tcp_init(struct xrdp_tcp *self, struct stream *s); int APP_CC -xrdp_tcp_recv(struct xrdp_tcp* self, struct stream* s, int len); +xrdp_tcp_recv(struct xrdp_tcp *self, struct stream *s, int len); int APP_CC -xrdp_tcp_send(struct xrdp_tcp* self, struct stream* s); +xrdp_tcp_send(struct xrdp_tcp *self, struct stream *s); /* xrdp_iso.c */ -struct xrdp_iso* APP_CC -xrdp_iso_create(struct xrdp_mcs* owner, struct trans* trans); +struct xrdp_iso * APP_CC +xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans); void APP_CC -xrdp_iso_delete(struct xrdp_iso* self); +xrdp_iso_delete(struct xrdp_iso *self); +int APP_CC +xrdp_iso_init(struct xrdp_iso *self, struct stream *s); int APP_CC -xrdp_iso_init(struct xrdp_iso* self, struct stream* s); +xrdp_iso_recv(struct xrdp_iso *self, struct stream *s); int APP_CC -xrdp_iso_recv(struct xrdp_iso* self, struct stream* s); +xrdp_iso_send(struct xrdp_iso *self, struct stream *s); int APP_CC -xrdp_iso_send(struct xrdp_iso* self, struct stream* s); +xrdp_iso_incoming(struct xrdp_iso *self); int APP_CC -xrdp_iso_incoming(struct xrdp_iso* self); +xrdp_iso_detect_tpkt(struct xrdp_iso *self, struct stream *s); /* xrdp_mcs.c */ -struct xrdp_mcs* APP_CC -xrdp_mcs_create(struct xrdp_sec* owner, struct trans* trans, - struct stream* client_mcs_data, - struct stream* server_mcs_data); +struct xrdp_mcs * APP_CC +xrdp_mcs_create(struct xrdp_sec *owner, struct trans *trans, + struct stream *client_mcs_data, + struct stream *server_mcs_data); void APP_CC -xrdp_mcs_delete(struct xrdp_mcs* self); +xrdp_mcs_delete(struct xrdp_mcs *self); int APP_CC -xrdp_mcs_init(struct xrdp_mcs* self, struct stream* s); +xrdp_mcs_init(struct xrdp_mcs *self, struct stream *s); int APP_CC -xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan); +xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan); int APP_CC -xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s, int chan); +xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan); int APP_CC -xrdp_mcs_incoming(struct xrdp_mcs* self); +xrdp_mcs_incoming(struct xrdp_mcs *self); int APP_CC -xrdp_mcs_disconnect(struct xrdp_mcs* self); +xrdp_mcs_disconnect(struct xrdp_mcs *self); /* xrdp_sec.c */ -struct xrdp_sec* APP_CC -xrdp_sec_create(struct xrdp_rdp* owner, struct trans* trans, int crypt_level, - int channel_code, int multimon); +struct xrdp_sec *APP_CC +xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans); void APP_CC -xrdp_sec_delete(struct xrdp_sec* self); +xrdp_sec_delete(struct xrdp_sec *self); +int APP_CC +xrdp_sec_init(struct xrdp_sec *self, struct stream *s); +int APP_CC +xrdp_sec_get_fastpath_bytes(struct xrdp_sec *self); +int APP_CC +xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s); int APP_CC -xrdp_sec_init(struct xrdp_sec* self, struct stream* s); +xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s); int APP_CC -xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan); +xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s); int APP_CC -xrdp_sec_send(struct xrdp_sec* self, struct stream* s, int chan); +xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan); int APP_CC -xrdp_sec_process_mcs_data(struct xrdp_sec* self); +xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan); int APP_CC -xrdp_sec_out_mcs_data(struct xrdp_sec* self); +xrdp_sec_process_mcs_data(struct xrdp_sec *self); int APP_CC -xrdp_sec_incoming(struct xrdp_sec* self); +xrdp_sec_incoming(struct xrdp_sec *self); int APP_CC -xrdp_sec_disconnect(struct xrdp_sec* self); +xrdp_sec_disconnect(struct xrdp_sec *self); /* xrdp_rdp.c */ -struct xrdp_rdp* APP_CC -xrdp_rdp_create(struct xrdp_session* session, struct trans* trans); +struct xrdp_rdp * APP_CC +xrdp_rdp_create(struct xrdp_session *session, struct trans *trans); void APP_CC -xrdp_rdp_delete(struct xrdp_rdp* self); +xrdp_rdp_delete(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_init(struct xrdp_rdp* self, struct stream* s); +xrdp_rdp_init(struct xrdp_rdp *self, struct stream *s); int APP_CC -xrdp_rdp_init_data(struct xrdp_rdp* self, struct stream* s); +xrdp_rdp_init_data(struct xrdp_rdp *self, struct stream *s); int APP_CC -xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code); +xrdp_rdp_get_fastpath_bytes(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type); +xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s); int APP_CC -xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s, - int data_pdu_type); +xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code); int APP_CC -xrdp_rdp_send_data_update_sync(struct xrdp_rdp* self); +xrdp_rdp_send(struct xrdp_rdp *self, struct stream *s, int pdu_type); int APP_CC -xrdp_rdp_incoming(struct xrdp_rdp* self); +xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, + int data_pdu_type); int APP_CC -xrdp_rdp_send_demand_active(struct xrdp_rdp* self); +xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, + int data_pdu_type); int APP_CC -xrdp_rdp_send_monitorlayout(struct xrdp_rdp* self); +xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s); +xrdp_rdp_incoming(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s); +xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s); int APP_CC -xrdp_rdp_disconnect(struct xrdp_rdp* self); +xrdp_rdp_disconnect(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_send_deactive(struct xrdp_rdp* self); +xrdp_rdp_send_deactive(struct xrdp_rdp *self); /* xrdp_orders.c */ -struct xrdp_orders* APP_CC -xrdp_orders_create(struct xrdp_session* session, - struct xrdp_rdp* rdp_layer); +struct xrdp_orders * APP_CC +xrdp_orders_create(struct xrdp_session *session, + struct xrdp_rdp *rdp_layer); void APP_CC -xrdp_orders_delete(struct xrdp_orders* self); +xrdp_orders_delete(struct xrdp_orders *self); int APP_CC -xrdp_orders_reset(struct xrdp_orders* self); +xrdp_orders_reset(struct xrdp_orders *self); int APP_CC -xrdp_orders_init(struct xrdp_orders* self); +xrdp_orders_init(struct xrdp_orders *self); int APP_CC -xrdp_orders_send(struct xrdp_orders* self); +xrdp_orders_send(struct xrdp_orders *self); int APP_CC -xrdp_orders_force_send(struct xrdp_orders* self); +xrdp_orders_force_send(struct xrdp_orders *self); int APP_CC -xrdp_orders_check(struct xrdp_orders* self, int max_size); +xrdp_orders_check(struct xrdp_orders *self, int max_size); int APP_CC -xrdp_orders_rect(struct xrdp_orders* self, int x, int y, int cx, int cy, - int color, struct xrdp_rect* rect); +xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, + int color, struct xrdp_rect *rect); int APP_CC -xrdp_orders_screen_blt(struct xrdp_orders* self, int x, int y, +xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, int cx, int cy, int srcx, int srcy, - int rop, struct xrdp_rect* rect); + int rop, struct xrdp_rect *rect); int APP_CC -xrdp_orders_pat_blt(struct xrdp_orders* self, int x, int y, +xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, int cx, int cy, int rop, int bg_color, - int fg_color, struct xrdp_brush* brush, - struct xrdp_rect* rect); + int fg_color, struct xrdp_brush *brush, + struct xrdp_rect *rect); int APP_CC -xrdp_orders_dest_blt(struct xrdp_orders* self, int x, int y, +xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, int cx, int cy, int rop, - struct xrdp_rect* rect); + struct xrdp_rect *rect); int APP_CC -xrdp_orders_line(struct xrdp_orders* self, int mix_mode, +xrdp_orders_line(struct xrdp_orders *self, int mix_mode, int startx, int starty, int endx, int endy, int rop, int bg_color, - struct xrdp_pen* pen, - struct xrdp_rect* rect); + struct xrdp_pen *pen, + struct xrdp_rect *rect); int APP_CC -xrdp_orders_mem_blt(struct xrdp_orders* self, int cache_id, +xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, int color_table, int x, int y, int cx, int cy, int rop, int srcx, int srcy, - int cache_idx, struct xrdp_rect* rect); + int cache_idx, struct xrdp_rect *rect); int APP_CC -xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, +xrdp_orders_composite_blt(struct xrdp_orders *self, int srcidx, int srcformat, int srcwidth, - int srcrepeat, int* srctransform, int mskflags, + int srcrepeat, int *srctransform, int mskflags, int mskidx, int mskformat, int mskwidth, int mskrepeat, int op, int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat, - struct xrdp_rect* rect); + struct xrdp_rect *rect); int APP_CC -xrdp_orders_text(struct xrdp_orders* self, +xrdp_orders_text(struct xrdp_orders *self, int font, int flags, int mixmode, int fg_color, int bg_color, int clip_left, int clip_top, int clip_right, int clip_bottom, int box_left, int box_top, int box_right, int box_bottom, - int x, int y, char* data, int data_len, - struct xrdp_rect* rect); + int x, int y, char *data, int data_len, + struct xrdp_rect *rect); int APP_CC -xrdp_orders_send_palette(struct xrdp_orders* self, int* palette, +xrdp_orders_send_palette(struct xrdp_orders *self, int *palette, int cache_id); int APP_CC -xrdp_orders_send_raw_bitmap(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_raw_bitmap(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int APP_CC -xrdp_orders_send_bitmap(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_bitmap(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int APP_CC -xrdp_orders_send_font(struct xrdp_orders* self, - struct xrdp_font_char* font_char, +xrdp_orders_send_font(struct xrdp_orders *self, + struct xrdp_font_char *font_char, int font_index, int char_index); int APP_CC -xrdp_orders_send_raw_bitmap2(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int APP_CC -xrdp_orders_send_bitmap2(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_bitmap2(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx, int hints); int APP_CC -xrdp_orders_send_bitmap3(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_bitmap3(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx, int hints); int APP_CC -xrdp_orders_send_brush(struct xrdp_orders* self, int width, int height, - int bpp, int type, int size, char* data, int cache_id); +xrdp_orders_send_brush(struct xrdp_orders *self, int width, int height, + int bpp, int type, int size, char *data, int cache_id); int APP_CC -xrdp_orders_send_create_os_surface(struct xrdp_orders* self, int id, +xrdp_orders_send_create_os_surface(struct xrdp_orders *self, int id, int width, int height, - struct list* del_list); + struct list *del_list); int APP_CC -xrdp_orders_send_switch_os_surface(struct xrdp_orders* self, int id); +xrdp_orders_send_switch_os_surface(struct xrdp_orders *self, int id); /* xrdp_bitmap_compress.c */ int APP_CC -xrdp_bitmap_compress(char* in_data, int width, int height, - struct stream* s, int bpp, int byte_limit, - int start_line, struct stream* temp_s, +xrdp_bitmap_compress(char *in_data, int width, int height, + struct stream *s, int bpp, int byte_limit, + int start_line, struct stream *temp_s, int e); int APP_CC -xrdp_bitmap32_compress(char* in_data, int width, int height, - struct stream* s, int bpp, int byte_limit, - int start_line, struct stream* temp_s, - int e); +xrdp_bitmap32_compress(char *in_data, int width, int height, + struct stream *s, int bpp, int byte_limit, + int start_line, struct stream *temp_s, + int e, int flags); int APP_CC -xrdp_jpeg_compress(void *handle, char* in_data, int width, int height, - struct stream* s, int bpp, int byte_limit, - int start_line, struct stream* temp_s, +xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, + struct stream *s, int bpp, int byte_limit, + int start_line, struct stream *temp_s, int e, int quality); int APP_CC @@ -516,16 +542,35 @@ xrdp_jpeg_deinit(void *handle); /* xrdp_channel.c */ struct xrdp_channel* APP_CC -xrdp_channel_create(struct xrdp_sec* owner, struct xrdp_mcs* mcs_layer); +xrdp_channel_create(struct xrdp_sec *owner, struct xrdp_mcs *mcs_layer); void APP_CC -xrdp_channel_delete(struct xrdp_channel* self); +xrdp_channel_delete(struct xrdp_channel *self); int APP_CC -xrdp_channel_init(struct xrdp_channel* self, struct stream* s); +xrdp_channel_init(struct xrdp_channel *self, struct stream *s); int APP_CC -xrdp_channel_send(struct xrdp_channel* self, struct stream* s, int channel_id, +xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id, int total_data_len, int flags); int APP_CC -xrdp_channel_process(struct xrdp_channel* self, struct stream* s, +xrdp_channel_process(struct xrdp_channel *self, struct stream *s, int chanid); +/* xrdp_fastpath.c */ +struct xrdp_fastpath *APP_CC +xrdp_fastpath_create(struct xrdp_sec *owner, struct trans *trans); +void APP_CC +xrdp_fastpath_delete(struct xrdp_fastpath *self); +int APP_CC +xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s); + +/* xrdp_caps.c */ +int APP_CC +xrdp_caps_send_demand_active(struct xrdp_rdp *self); +int APP_CC +xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s); #endif diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index d322eafa..2262f66f 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,202 +27,220 @@ struct xrdp_brush { - int x_orgin; - int y_orgin; - int style; - char pattern[8]; + int x_orgin; + int y_orgin; + int style; + char pattern[8]; }; struct xrdp_pen { - int style; - int width; - int color; + int style; + int width; + int color; }; /* 2.2.2.2.1.2.5.1 Cache Glyph Data (TS_CACHE_GLYPH_DATA) */ struct xrdp_font_char { - int offset; /* x */ - int baseline; /* y */ - int width; /* cx */ - int height; /* cy */ - int incby; - int bpp; - char* data; + int offset; /* x */ + int baseline; /* y */ + int width; /* cx */ + int height; /* cy */ + int incby; + int bpp; + char *data; }; struct xrdp_rect { - int left; - int top; - int right; - int bottom; + int left; + int top; + int right; + int bottom; }; struct xrdp_session { - long id; - struct trans* trans; - int (*callback)(long id, int msg, long param1, long param2, long param3, - long param4); - void* rdp; - void* orders; - struct xrdp_client_info* client_info; - int up_and_running; - int (*is_term)(void); - int in_process_data; /* inc / dec libxrdp_process_data calls */ + tintptr id; + struct trans *trans; + int (*callback)(tintptr id, int msg, tintptr param1, tintptr param2, + tintptr param3, tintptr param4); + void *rdp; + void *orders; + struct xrdp_client_info *client_info; + int up_and_running; + int (*is_term)(void); + int in_process_data; /* inc / dec libxrdp_process_data calls */ }; -struct xrdp_session* DEFAULT_CC -libxrdp_init(tbus id, struct trans* trans); +struct xrdp_session * DEFAULT_CC +libxrdp_init(tbus id, struct trans *trans); int DEFAULT_CC -libxrdp_exit(struct xrdp_session* session); +libxrdp_exit(struct xrdp_session *session); int DEFAULT_CC -libxrdp_disconnect(struct xrdp_session* session); +libxrdp_disconnect(struct xrdp_session *session); int DEFAULT_CC -libxrdp_process_incomming(struct xrdp_session* session); +libxrdp_process_incomming(struct xrdp_session *session); +int EXPORT_CC +libxrdp_get_pdu_bytes(const char *aheader); +struct stream * APP_CC +libxrdp_force_read(struct trans *trans); int DEFAULT_CC -libxrdp_process_data(struct xrdp_session* session, struct stream *s); +libxrdp_process_data(struct xrdp_session *session, struct stream *s); int DEFAULT_CC -libxrdp_send_palette(struct xrdp_session* session, int* palette); +libxrdp_send_palette(struct xrdp_session *session, int *palette); int DEFAULT_CC -libxrdp_send_bell(struct xrdp_session* session); +libxrdp_send_bell(struct xrdp_session *session); int DEFAULT_CC -libxrdp_send_bitmap(struct xrdp_session* session, int width, int height, - int bpp, char* data, int x, int y, int cx, int cy); +libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, + int bpp, char *data, int x, int y, int cx, int cy); int DEFAULT_CC -libxrdp_send_pointer(struct xrdp_session* session, int cache_idx, - char* data, char* mask, int x, int y, int bpp); +libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, + char *data, char *mask, int x, int y, int bpp); int DEFAULT_CC -libxrdp_set_pointer(struct xrdp_session* session, int cache_idx); +libxrdp_set_pointer(struct xrdp_session *session, int cache_idx); int DEFAULT_CC -libxrdp_orders_init(struct xrdp_session* session); +libxrdp_orders_init(struct xrdp_session *session); int DEFAULT_CC -libxrdp_orders_send(struct xrdp_session* session); +libxrdp_orders_send(struct xrdp_session *session); int DEFAULT_CC -libxrdp_orders_force_send(struct xrdp_session* session); +libxrdp_orders_force_send(struct xrdp_session *session); int DEFAULT_CC -libxrdp_orders_rect(struct xrdp_session* session, int x, int y, - int cx, int cy, int color, struct xrdp_rect* rect); +libxrdp_orders_rect(struct xrdp_session *session, int x, int y, + int cx, int cy, int color, struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_screen_blt(struct xrdp_session* session, int x, int y, +libxrdp_orders_screen_blt(struct xrdp_session *session, int x, int y, int cx, int cy, int srcx, int srcy, - int rop, struct xrdp_rect* rect); + int rop, struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_pat_blt(struct xrdp_session* session, int x, int y, +libxrdp_orders_pat_blt(struct xrdp_session *session, int x, int y, int cx, int cy, int rop, int bg_color, - int fg_color, struct xrdp_brush* brush, - struct xrdp_rect* rect); + int fg_color, struct xrdp_brush *brush, + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_dest_blt(struct xrdp_session* session, int x, int y, +libxrdp_orders_dest_blt(struct xrdp_session *session, int x, int y, int cx, int cy, int rop, - struct xrdp_rect* rect); + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_line(struct xrdp_session* session, int mix_mode, +libxrdp_orders_line(struct xrdp_session *session, int mix_mode, int startx, int starty, int endx, int endy, int rop, int bg_color, - struct xrdp_pen* pen, - struct xrdp_rect* rect); + struct xrdp_pen *pen, + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_mem_blt(struct xrdp_session* session, int cache_id, +libxrdp_orders_mem_blt(struct xrdp_session *session, int cache_id, int color_table, int x, int y, int cx, int cy, int rop, int srcx, int srcy, - int cache_idx, struct xrdp_rect* rect); + int cache_idx, struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_composite_blt(struct xrdp_session* session, int srcidx, +libxrdp_orders_composite_blt(struct xrdp_session *session, int srcidx, int srcformat, int srcwidth, int srcrepeat, - int* srctransform, int mskflags, + int *srctransform, int mskflags, int mskidx, int mskformat, int mskwidth, int mskrepeat, int op, int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat, - struct xrdp_rect* rect); + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_text(struct xrdp_session* session, +libxrdp_orders_text(struct xrdp_session *session, int font, int flags, int mixmode, int fg_color, int bg_color, int clip_left, int clip_top, int clip_right, int clip_bottom, int box_left, int box_top, int box_right, int box_bottom, - int x, int y, char* data, int data_len, - struct xrdp_rect* rect); + int x, int y, char *data, int data_len, + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_send_palette(struct xrdp_session* session, int* palette, +libxrdp_orders_send_palette(struct xrdp_session *session, int *palette, int cache_id); int DEFAULT_CC -libxrdp_orders_send_raw_bitmap(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_raw_bitmap(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int DEFAULT_CC -libxrdp_orders_send_bitmap(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_bitmap(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int DEFAULT_CC -libxrdp_orders_send_font(struct xrdp_session* session, - struct xrdp_font_char* font_char, +libxrdp_orders_send_font(struct xrdp_session *session, + struct xrdp_font_char *font_char, int font_index, int char_index); int DEFAULT_CC -libxrdp_reset(struct xrdp_session* session, +libxrdp_reset(struct xrdp_session *session, int width, int height, int bpp); int DEFAULT_CC -libxrdp_orders_send_raw_bitmap2(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_raw_bitmap2(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int DEFAULT_CC -libxrdp_orders_send_bitmap2(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_bitmap2(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx, int hints); int DEFAULT_CC -libxrdp_orders_send_bitmap3(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_bitmap3(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx, int hints); int DEFAULT_CC -libxrdp_query_channel(struct xrdp_session* session, int index, - char* channel_name, int* channel_flags); +libxrdp_query_channel(struct xrdp_session *session, int index, + char *channel_name, int *channel_flags); int DEFAULT_CC -libxrdp_get_channel_id(struct xrdp_session* session, char* name); +libxrdp_get_channel_id(struct xrdp_session *session, char *name); int DEFAULT_CC -libxrdp_send_to_channel(struct xrdp_session* session, int channel_id, - char* data, int data_len, +libxrdp_send_to_channel(struct xrdp_session *session, int channel_id, + char *data, int data_len, int total_data_len, int flags); int DEFAULT_CC -libxrdp_orders_send_brush(struct xrdp_session* session, +libxrdp_orders_send_brush(struct xrdp_session *session, int width, int height, int bpp, int type, - int size, char* data, int cache_id); + int size, char *data, int cache_id); int DEFAULT_CC -libxrdp_orders_send_create_os_surface(struct xrdp_session* session, int id, +libxrdp_orders_send_create_os_surface(struct xrdp_session *session, int id, int width, int height, - struct list* del_list); + struct list *del_list); int DEFAULT_CC -libxrdp_orders_send_switch_os_surface(struct xrdp_session* session, int id); +libxrdp_orders_send_switch_os_surface(struct xrdp_session *session, int id); int DEFAULT_CC -libxrdp_window_new_update(struct xrdp_session* session, int window_id, - struct rail_window_state_order* window_state, +libxrdp_window_new_update(struct xrdp_session *session, int window_id, + struct rail_window_state_order *window_state, int flags); int DEFAULT_CC -libxrdp_window_delete(struct xrdp_session* session, int window_id); +libxrdp_window_delete(struct xrdp_session *session, int window_id); int DEFAULT_CC -libxrdp_window_icon(struct xrdp_session* session, int window_id, +libxrdp_window_icon(struct xrdp_session *session, int window_id, int cache_entry, int cache_id, - struct rail_icon_info* icon_info, int flags); + struct rail_icon_info *icon_info, int flags); int DEFAULT_CC -libxrdp_window_cached_icon(struct xrdp_session* session, int window_id, +libxrdp_window_cached_icon(struct xrdp_session *session, int window_id, int cache_entry, int cache_id, int flags); int DEFAULT_CC -libxrdp_notify_new_update(struct xrdp_session* session, +libxrdp_notify_new_update(struct xrdp_session *session, int window_id, int notify_id, - struct rail_notify_state_order* notify_state, + struct rail_notify_state_order *notify_state, int flags); int DEFAULT_CC -libxrdp_notify_delete(struct xrdp_session* session, +libxrdp_notify_delete(struct xrdp_session *session, int window_id, int notify_id); int DEFAULT_CC -libxrdp_monitored_desktop(struct xrdp_session* session, - struct rail_monitored_desktop_order* mdo, +libxrdp_monitored_desktop(struct xrdp_session *session, + struct rail_monitored_desktop_order *mdo, int flags); +int DEFAULT_CC +libxrdp_codec_jpeg_compress(struct xrdp_session *session, + int format, char *inp_data, + int width, int height, + int stride, int x, int y, + int cx, int cy, int quality, + char *out_data, int *io_len); +int DEFAULT_CC +libxrdp_fastpath_send_surface(struct xrdp_session *session, + char *data_pad, int pad_bytes, + int data_bytes, + int destLeft, int dst_Top, + int destRight, int destBottom, int bpp, + int codecID, int width, int height); #endif diff --git a/libxrdp/xrdp_bitmap32_compress.c b/libxrdp/xrdp_bitmap32_compress.c index b681d040..083c4409 100644 --- a/libxrdp/xrdp_bitmap32_compress.c +++ b/libxrdp/xrdp_bitmap32_compress.c @@ -19,14 +19,518 @@ * 32 bpp compression */ +/* +RDP 6.0 Bitmap Compression +http://msdn.microsoft.com/en-us/library/cc241877.aspx +*/ + #include "libxrdp.h" +#define FLAGS_RLE 0x10 +#define FLAGS_NOALPHA 0x20 + +#define LLOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LLOG_LEVEL) { g_writeln _args ; } } while (0) +#define LHEXDUMP(_level, _args) \ + do { if (_level < LLOG_LEVEL) { g_hexdump _args ; } } while (0) + +/*****************************************************************************/ +/* split RGB */ +static int APP_CC +fsplit3(char *in_data, int start_line, int width, int e, + char *r_data, char *g_data, char *b_data) +{ +#if defined(L_ENDIAN) + int rp; + int gp; + int bp; +#endif + int index; + int out_index; + int pixel; + int cy; + int *ptr32; + + cy = 0; + out_index = 0; + while (start_line >= 0) + { + ptr32 = (int *) (in_data + start_line * width * 4); + index = 0; +#if defined(L_ENDIAN) + while (index + 4 <= width) + { + pixel = *ptr32; + ptr32++; + rp = (pixel >> 16) & 0x000000ff; + gp = (pixel >> 8) & 0x000000ff; + bp = (pixel >> 0) & 0x000000ff; + pixel = *ptr32; + ptr32++; + rp |= (pixel >> 8) & 0x0000ff00; + gp |= (pixel << 0) & 0x0000ff00; + bp |= (pixel << 8) & 0x0000ff00; + pixel = *ptr32; + ptr32++; + rp |= (pixel >> 0) & 0x00ff0000; + gp |= (pixel << 8) & 0x00ff0000; + bp |= (pixel << 16) & 0x00ff0000; + pixel = *ptr32; + ptr32++; + rp |= (pixel << 8) & 0xff000000; + gp |= (pixel << 16) & 0xff000000; + bp |= (pixel << 24) & 0xff000000; + *((int*)(r_data + out_index)) = rp; + *((int*)(g_data + out_index)) = gp; + *((int*)(b_data + out_index)) = bp; + out_index += 4; + index += 4; + } +#endif + while (index < width) + { + pixel = *ptr32; + ptr32++; + r_data[out_index] = pixel >> 16; + g_data[out_index] = pixel >> 8; + b_data[out_index] = pixel >> 0; + out_index++; + index++; + } + for (index = 0; index < e; index++) + { + r_data[out_index] = r_data[out_index - 1]; + g_data[out_index] = g_data[out_index - 1]; + b_data[out_index] = b_data[out_index - 1]; + out_index++; + } + start_line--; + cy++; + if (out_index > 64 * 64) + { + break; + } + } + return cy; +} + /*****************************************************************************/ +/* split ARGB */ +static int APP_CC +fsplit4(char *in_data, int start_line, int width, int e, + char *a_data, char *r_data, char *g_data, char *b_data) +{ +#if defined(L_ENDIAN) + int ap; + int rp; + int gp; + int bp; +#endif + int index; + int out_index; + int pixel; + int cy; + int *ptr32; + + cy = 0; + out_index = 0; + while (start_line >= 0) + { + ptr32 = (int *) (in_data + start_line * width * 4); + index = 0; +#if defined(L_ENDIAN) + while (index + 4 <= width) + { + pixel = *ptr32; + ptr32++; + ap = (pixel >> 24) & 0x000000ff; + rp = (pixel >> 16) & 0x000000ff; + gp = (pixel >> 8) & 0x000000ff; + bp = (pixel >> 0) & 0x000000ff; + pixel = *ptr32; + ptr32++; + ap |= (pixel >> 16) & 0x0000ff00; + rp |= (pixel >> 8) & 0x0000ff00; + gp |= (pixel << 0) & 0x0000ff00; + bp |= (pixel << 8) & 0x0000ff00; + pixel = *ptr32; + ptr32++; + ap |= (pixel >> 8) & 0x00ff0000; + rp |= (pixel >> 0) & 0x00ff0000; + gp |= (pixel << 8) & 0x00ff0000; + bp |= (pixel << 16) & 0x00ff0000; + pixel = *ptr32; + ptr32++; + ap |= (pixel << 0) & 0xff000000; + rp |= (pixel << 8) & 0xff000000; + gp |= (pixel << 16) & 0xff000000; + bp |= (pixel << 24) & 0xff000000; + *((int*)(a_data + out_index)) = ap; + *((int*)(r_data + out_index)) = rp; + *((int*)(g_data + out_index)) = gp; + *((int*)(b_data + out_index)) = bp; + out_index += 4; + index += 4; + } +#endif + while (index < width) + { + pixel = *ptr32; + ptr32++; + a_data[out_index] = pixel >> 24; + r_data[out_index] = pixel >> 16; + g_data[out_index] = pixel >> 8; + b_data[out_index] = pixel >> 0; + out_index++; + index++; + } + for (index = 0; index < e; index++) + { + a_data[out_index] = a_data[out_index - 1]; + r_data[out_index] = r_data[out_index - 1]; + g_data[out_index] = g_data[out_index - 1]; + b_data[out_index] = b_data[out_index - 1]; + out_index++; + } + start_line--; + cy++; + if (out_index > 64 * 64) + { + break; + } + } + return cy; +} + +/*****************************************************************************/ +#define DELTA_ONE \ +do { \ + delta = src8[cx] - src8[0]; \ + is_neg = (delta >> 7) & 1; \ + dst8[cx] = (((delta ^ -is_neg) + is_neg) << 1) - is_neg; \ + src8++; \ + dst8++; \ +} while (0) + +/*****************************************************************************/ +static int APP_CC +fdelta(char *in_plane, char *out_plane, int cx, int cy) +{ + char delta; + char is_neg; + char *src8; + char *dst8; + char *src8_end; + + g_memcpy(out_plane, in_plane, cx); + src8 = in_plane; + dst8 = out_plane; + src8_end = src8 + (cx * cy - cx); + while (src8 + 8 <= src8_end) + { + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + } + while (src8 < src8_end) + { + DELTA_ONE; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +fout(int collen, int replen, char *colptr, struct stream *s) +{ + int code; + int lcollen; + int lreplen; + int cont; + + LLOGLN(10, ("fout: collen %d replen %d", collen, replen)); + cont = collen > 13; + while (cont) + { + lcollen = collen; + if (lcollen > 15) + { + lcollen = 15; + } + code = lcollen << 4; + out_uint8(s, code); + out_uint8a(s, colptr, lcollen); + colptr += lcollen; + collen -= lcollen; + cont = collen > 13; + } + cont = (collen > 0) || (replen > 0); + while (cont) + { + lreplen = replen; + if ((collen == 0) && (lreplen > 15)) + { + /* big run */ + if (lreplen > 47) + { + lreplen = 47; + } + LLOGLN(10, ("fout: big run lreplen %d", lreplen)); + replen -= lreplen; + code = ((lreplen & 0xF) << 4) | ((lreplen & 0xF0) >> 4); + out_uint8(s, code); + colptr += lreplen; + } + else + { + if (lreplen > 15) + { + lreplen = 15; + } + replen -= lreplen; + if (lreplen < 3) + { + collen += lreplen; + lreplen = 0; + } + code = (collen << 4) | lreplen; + out_uint8(s, code); + out_uint8a(s, colptr, collen); + colptr += collen + lreplen; + collen = 0; + } + cont = replen > 0; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +fpack(char *plane, int cx, int cy, struct stream *s) +{ + char *ptr8; + char *colptr; + char *lend; + char *holdp; + int jndex; + int collen; + int replen; + + LLOGLN(10, ("fpack:")); + holdp = s->p; + for (jndex = 0; jndex < cy; jndex++) + { + LLOGLN(10, ("line start line %d cx %d cy %d", jndex, cx, cy)); + ptr8 = plane + jndex * cx; + LHEXDUMP(10, (ptr8, cx)); + lend = ptr8 + (cx - 1); + colptr = ptr8; + if (colptr[0] == 0) + { + collen = 0; + replen = 1; + } + else + { + collen = 1; + replen = 0; + } + while (ptr8 < lend) + { + if (ptr8[0] == ptr8[1]) + { + replen++; + } + else + { + if (replen > 0) + { + if (replen < 3) + { + collen += replen + 1; + replen = 0; + } + else + { + fout(collen, replen, colptr, s); + colptr = ptr8 + 1; + replen = 0; + collen = 1; + } + } + else + { + collen++; + } + } + ptr8++; + } + /* end of line */ + fout(collen, replen, colptr, s); + } + return (int) (s->p - holdp); +} + +/*****************************************************************************/ +static int APP_CC +foutraw3(struct stream *s, int bytes, int header, + char *r_data, char *g_data, char *b_data) +{ + out_uint8(s, header); + out_uint8a(s, r_data, bytes); + out_uint8a(s, g_data, bytes); + out_uint8a(s, b_data, bytes); + /* pad if no RLE */ + out_uint8(s, 0x00); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +foutraw4(struct stream *s, int bytes, int header, + char *a_data, char *r_data, char *g_data, char *b_data) +{ + out_uint8(s, header); + out_uint8a(s, a_data, bytes); + out_uint8a(s, r_data, bytes); + out_uint8a(s, g_data, bytes); + out_uint8a(s, b_data, bytes); + /* pad if no RLE */ + out_uint8(s, 0x00); + return 0; +} + +/*****************************************************************************/ +/* returns the number of lines compressed */ int APP_CC xrdp_bitmap32_compress(char *in_data, int width, int height, struct stream *s, int bpp, int byte_limit, int start_line, struct stream *temp_s, - int e) + int e, int flags) { - return 0; + char *a_data; + char *r_data; + char *g_data; + char *b_data; + char *sa_data; + char *sr_data; + char *sg_data; + char *sb_data; + int a_bytes; + int r_bytes; + int g_bytes; + int b_bytes; + int cx; + int cy; + int max_bytes; + int total_bytes; + int header; + + LLOGLN(10, ("xrdp_bitmap32_compress:")); + max_bytes = 4 * 1024; + /* need max 8, 4K planes for work */ + if (max_bytes * 8 > temp_s->size) + { + return 0; + } + header = flags & 0xFF; + cx = width + e; + sa_data = temp_s->data; + sr_data = sa_data + max_bytes; + sg_data = sr_data + max_bytes; + sb_data = sg_data + max_bytes; + a_data = sb_data + max_bytes; + r_data = a_data + max_bytes; + g_data = r_data + max_bytes; + b_data = g_data + max_bytes; + + if (header & FLAGS_NOALPHA) + { + cy = fsplit3(in_data, start_line, width, e, + sr_data, sg_data, sb_data); + if (header & FLAGS_RLE) + { + fdelta(sr_data, r_data, cx, cy); + fdelta(sg_data, g_data, cx, cy); + fdelta(sb_data, b_data, cx, cy); + out_uint8(s, header); + r_bytes = fpack(r_data, cx, cy, s); + g_bytes = fpack(g_data, cx, cy, s); + b_bytes = fpack(b_data, cx, cy, s); + total_bytes = r_bytes + g_bytes + b_bytes; + if (1 + total_bytes > byte_limit) + { + /* failed */ + LLOGLN(0, ("xrdp_bitmap32_compress: too big, rgb " + "bytes %d %d %d total_bytes %d cx %d cy %d " + "byte_limit %d", r_bytes, g_bytes, b_bytes, + total_bytes, cx, cy, byte_limit)); + return 0; + } + max_bytes = cx * cy * 3; + if (total_bytes > max_bytes) + { + /* raw is better */ + LLOGLN(10, ("xrdp_bitmap32_compress: too big, rgb " + "bytes %d %d %d total_bytes %d cx %d cy %d " + "max_bytes %d", r_bytes, g_bytes, b_bytes, + total_bytes, cx, cy, max_bytes)); + init_stream(s, 0); + foutraw3(s, cx * cy, FLAGS_NOALPHA, sr_data, sg_data, sb_data); + } + } + else + { + foutraw3(s, cx * cy, FLAGS_NOALPHA, sr_data, sg_data, sb_data); + } + } + else + { + cy = fsplit4(in_data, start_line, width, e, + sa_data, sr_data, sg_data, sb_data); + if (header & FLAGS_RLE) + { + fdelta(sa_data, a_data, cx, cy); + fdelta(sr_data, r_data, cx, cy); + fdelta(sg_data, g_data, cx, cy); + fdelta(sb_data, b_data, cx, cy); + out_uint8(s, header); + a_bytes = fpack(a_data, cx, cy, s); + r_bytes = fpack(r_data, cx, cy, s); + g_bytes = fpack(g_data, cx, cy, s); + b_bytes = fpack(b_data, cx, cy, s); + max_bytes = cx * cy * 4; + total_bytes = a_bytes + r_bytes + g_bytes + b_bytes; + if (1 + total_bytes > byte_limit) + { + /* failed */ + LLOGLN(0, ("xrdp_bitmap32_compress: too big, argb " + "bytes %d %d %d %d total_bytes %d cx %d cy %d " + "byte_limit %d", a_bytes, r_bytes, g_bytes, b_bytes, + total_bytes, cx, cy, byte_limit)); + return 0; + } + if (total_bytes > max_bytes) + { + /* raw is better */ + LLOGLN(10, ("xrdp_bitmap32_compress: too big, argb " + "bytes %d %d %d %d total_bytes %d cx %d cy %d " + "max_bytes %d", a_bytes, r_bytes, g_bytes, b_bytes, + total_bytes, cx, cy, max_bytes)); + init_stream(s, 0); + foutraw4(s, cx * cy, 0, sa_data, sr_data, sg_data, sb_data); + } + } + else + { + foutraw4(s, cx * cy, 0, sa_data, sr_data, sg_data, sb_data); + } + } + return cy; } diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c new file mode 100644 index 00000000..a5883a01 --- /dev/null +++ b/libxrdp/xrdp_caps.c @@ -0,0 +1,916 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2014 + * Copyright (C) Idan Freiberg 2004-2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * RDP Capability Sets + */ + +#include "libxrdp.h" + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_send_monitorlayout(struct xrdp_rdp *self) +{ + struct stream *s; + int i; + + make_stream(s); + init_stream(s, 8192); + + if (xrdp_rdp_init_data(self, s) != 0) + { + free_stream(s); + return 1; + } + + out_uint32_le(s, self->client_info.monitorCount); /* monitorCount (4 bytes) */ + + /* TODO: validate for allowed monitors in terminal server (maybe by config?) */ + for (i = 0; i < self->client_info.monitorCount; i++) + { + out_uint32_le(s, self->client_info.minfo[i].left); + out_uint32_le(s, self->client_info.minfo[i].top); + out_uint32_le(s, self->client_info.minfo[i].right); + out_uint32_le(s, self->client_info.minfo[i].bottom); + out_uint32_le(s, self->client_info.minfo[i].is_primary); + } + + s_mark_end(s); + + if (xrdp_rdp_send_data(self, s, 0x37) != 0) + { + free_stream(s); + return 1; + } + + free_stream(s); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int extraFlags; + int client_does_fastpath_output; + + if (len < 10 + 2) + { + g_writeln("xrdp_caps_process_general: error"); + return 1; + } + in_uint8s(s, 10); + in_uint16_le(s, extraFlags); + /* use_compact_packets is pretty much 'use rdp5' */ + self->client_info.use_compact_packets = (extraFlags != 0); + /* op2 is a boolean to use compact bitmap headers in bitmap cache */ + /* set it to same as 'use rdp5' boolean */ + self->client_info.op2 = self->client_info.use_compact_packets; + /* FASTPATH_OUTPUT_SUPPORTED 0x0001 */ + client_does_fastpath_output = extraFlags & FASTPATH_OUTPUT_SUPPORTED; + if ((self->client_info.use_fast_path & 1) && !client_does_fastpath_output) + { + /* server supports fast path output and client does not, turn it off */ + self->client_info.use_fast_path &= ~1; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int i; + char order_caps[32]; + int ex_flags; + int cap_flags; + + DEBUG(("order capabilities")); + if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4) + { + g_writeln("xrdp_caps_process_order: error"); + return 1; + } + in_uint8s(s, 20); /* Terminal desc, pad */ + in_uint8s(s, 2); /* Cache X granularity */ + in_uint8s(s, 2); /* Cache Y granularity */ + in_uint8s(s, 2); /* Pad */ + in_uint8s(s, 2); /* Max order level */ + in_uint8s(s, 2); /* Number of fonts */ + in_uint16_le(s, cap_flags); /* Capability flags */ + in_uint8a(s, order_caps, 32); /* Orders supported */ + g_memcpy(self->client_info.orders, order_caps, 32); + DEBUG(("dest blt-0 %d", order_caps[0])); + DEBUG(("pat blt-1 %d", order_caps[1])); + DEBUG(("screen blt-2 %d", order_caps[2])); + DEBUG(("memblt-3-13 %d %d", order_caps[3], order_caps[13])); + DEBUG(("triblt-4-14 %d %d", order_caps[4], order_caps[14])); + DEBUG(("line-8 %d", order_caps[8])); + DEBUG(("line-9 %d", order_caps[9])); + DEBUG(("rect-10 %d", order_caps[10])); + DEBUG(("desksave-11 %d", order_caps[11])); + DEBUG(("polygon-20 %d", order_caps[20])); + DEBUG(("polygon2-21 %d", order_caps[21])); + DEBUG(("polyline-22 %d", order_caps[22])); + DEBUG(("ellipse-25 %d", order_caps[25])); + DEBUG(("ellipse2-26 %d", order_caps[26])); + DEBUG(("text2-27 %d", order_caps[27])); + DEBUG(("order_caps dump")); +#if defined(XRDP_DEBUG) + g_hexdump(order_caps, 32); +#endif + in_uint8s(s, 2); /* Text capability flags */ + /* read extended order support flags */ + in_uint16_le(s, ex_flags); /* Ex flags */ + + if (cap_flags & 0x80) /* ORDER_FLAGS_EXTRA_SUPPORT */ + { + self->client_info.order_flags_ex = ex_flags; + if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT) + { + g_writeln("xrdp_caps_process_order: bitmap cache v3 supported"); + self->client_info.bitmap_cache_version |= 4; + } + } + in_uint8s(s, 4); /* Pad */ + + in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */ + self->client_info.desktop_cache = i; + DEBUG(("desktop cache size %d", i)); + in_uint8s(s, 4); /* Unknown */ + in_uint8s(s, 4); /* Unknown */ + return 0; +} + +/*****************************************************************************/ +/* get the bitmap cache size */ +static int APP_CC +xrdp_caps_process_bmpcache(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int i; + + if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2) + { + g_writeln("xrdp_caps_process_bmpcache: error"); + return 1; + } + self->client_info.bitmap_cache_version |= 1; + in_uint8s(s, 24); + /* cache 1 */ + in_uint16_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache1_entries = i; + in_uint16_le(s, self->client_info.cache1_size); + /* cache 2 */ + in_uint16_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache2_entries = i; + in_uint16_le(s, self->client_info.cache2_size); + /* caceh 3 */ + in_uint16_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache3_entries = i; + in_uint16_le(s, self->client_info.cache3_size); + DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, + self->client_info.cache1_size)); + DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries, + self->client_info.cache2_size)); + DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries, + self->client_info.cache3_size)); + return 0; +} + +/*****************************************************************************/ +/* get the bitmap cache size */ +static int APP_CC +xrdp_caps_process_bmpcache2(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int Bpp = 0; + int i = 0; + + if (len < 2 + 2 + 4 + 4 + 4) + { + g_writeln("xrdp_caps_process_bmpcache2: error"); + return 1; + } + self->client_info.bitmap_cache_version |= 2; + Bpp = (self->client_info.bpp + 7) / 8; + in_uint16_le(s, i); /* cache flags */ + self->client_info.bitmap_cache_persist_enable = i; + in_uint8s(s, 2); /* number of caches in set, 3 */ + in_uint32_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache1_entries = i; + self->client_info.cache1_size = 256 * Bpp; + in_uint32_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache2_entries = i; + self->client_info.cache2_size = 1024 * Bpp; + in_uint32_le(s, i); + i = i & 0x7fffffff; + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache3_entries = i; + self->client_info.cache3_size = 4096 * Bpp; + DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, + self->client_info.cache1_size)); + DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries, + self->client_info.cache2_size)); + DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries, + self->client_info.cache3_size)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int codec_id; + + if (len < 1) + { + g_writeln("xrdp_caps_process_cache_v3_codec_id: error"); + return 1; + } + in_uint8(s, codec_id); + g_writeln("xrdp_caps_process_cache_v3_codec_id: cache_v3_codec_id %d", + codec_id); + self->client_info.v3_codec_id = codec_id; + return 0; +} + +/*****************************************************************************/ +/* get the number of client cursor cache */ +static int APP_CC +xrdp_caps_process_pointer(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int i; + int colorPointerFlag; + int no_new_cursor; + + if (len < 2 + 2 + 2) + { + g_writeln("xrdp_caps_process_pointer: error"); + return 1; + } + no_new_cursor = self->client_info.pointer_flags & 2; + in_uint16_le(s, colorPointerFlag); + self->client_info.pointer_flags = colorPointerFlag; + in_uint16_le(s, i); + i = MIN(i, 32); + self->client_info.pointer_cache_entries = i; + if (colorPointerFlag & 1) + { + g_writeln("xrdp_caps_process_pointer: client supports " + "new(color) cursor"); + in_uint16_le(s, i); + i = MIN(i, 32); + self->client_info.pointer_cache_entries = i; + } + else + { + g_writeln("xrdp_caps_process_pointer: client does not support " + "new(color) cursor"); + } + if (no_new_cursor) + { + g_writeln("xrdp_caps_process_pointer: new(color) cursor is " + "disabled by config"); + self->client_info.pointer_flags = 0; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_input(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int inputFlags; + int client_does_fastpath_input; + + in_uint16_le(s, inputFlags); + client_does_fastpath_input = (inputFlags & INPUT_FLAG_FASTPATH_INPUT) || + (inputFlags & INPUT_FLAG_FASTPATH_INPUT2); + if ((self->client_info.use_fast_path & 2) && !client_does_fastpath_input) + { + self->client_info.use_fast_path &= ~2; + } + return 0; +} + +/*****************************************************************************/ +/* get the type of client brush cache */ +int APP_CC +xrdp_caps_process_brushcache(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int code; + + if (len < 4) + { + g_writeln("xrdp_caps_process_brushcache: error"); + return 1; + } + in_uint32_le(s, code); + self->client_info.brush_cache_code = code; + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_caps_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int i32; + + if (len < 4 + 2 + 2) + { + g_writeln("xrdp_caps_process_offscreen_bmpcache: error"); + return 1; + } + in_uint32_le(s, i32); + self->client_info.offscreen_support_level = i32; + in_uint16_le(s, i32); + self->client_info.offscreen_cache_size = i32 * 1024; + in_uint16_le(s, i32); + self->client_info.offscreen_cache_entries = i32; + g_writeln("xrdp_process_offscreen_bmpcache: support level %d " + "cache size %d MB cache entries %d", + self->client_info.offscreen_support_level, + self->client_info.offscreen_cache_size, + self->client_info.offscreen_cache_entries); + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_caps_process_rail(struct xrdp_rdp *self, struct stream *s, int len) +{ + int i32; + + if (len < 4) + { + g_writeln("xrdp_caps_process_rail: error"); + return 1; + } + in_uint32_le(s, i32); + self->client_info.rail_support_level = i32; + g_writeln("xrdp_process_capset_rail: rail_support_level %d", + self->client_info.rail_support_level); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_window(struct xrdp_rdp *self, struct stream *s, int len) +{ + int i32; + + if (len < 4 + 1 + 2) + { + g_writeln("xrdp_caps_process_window: error"); + return 1; + } + in_uint32_le(s, i32); + self->client_info.wnd_support_level = i32; + in_uint8(s, i32); + self->client_info.wnd_num_icon_caches = i32; + in_uint16_le(s, i32); + self->client_info.wnd_num_icon_cache_entries = i32; + g_writeln("xrdp_process_capset_window wnd_support_level %d " + "wnd_num_icon_caches %d wnd_num_icon_cache_entries %d", + self->client_info.wnd_support_level, + self->client_info.wnd_num_icon_caches, + self->client_info.wnd_num_icon_cache_entries); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len) +{ + int codec_id; + int codec_count; + int index; + int codec_properties_length; + int i1; + char *codec_guid; + char *next_guid; + + if (len < 1) + { + g_writeln("xrdp_caps_process_codecs: error"); + return 1; + } + in_uint8(s, codec_count); + len--; + + for (index = 0; index < codec_count; index++) + { + codec_guid = s->p; + if (len < 16 + 1 + 2) + { + g_writeln("xrdp_caps_process_codecs: error"); + return 1; + } + in_uint8s(s, 16); + in_uint8(s, codec_id); + in_uint16_le(s, codec_properties_length); + len -= 16 + 1 + 2; + if (len < codec_properties_length) + { + g_writeln("xrdp_caps_process_codecs: error"); + return 1; + } + len -= codec_properties_length; + next_guid = s->p + codec_properties_length; + + if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) + { + g_writeln("xrdp_caps_process_codecs: nscodec codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.ns_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.ns_prop, s->p, i1); + self->client_info.ns_prop_len = i1; + } + else if (g_memcmp(codec_guid, XR_CODEC_GUID_REMOTEFX, 16) == 0) + { + g_writeln("xrdp_caps_process_codecs: rfx codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.rfx_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.rfx_prop, s->p, i1); + self->client_info.rfx_prop_len = i1; + } + else if (g_memcmp(codec_guid, XR_CODEC_GUID_JPEG, 16) == 0) + { + g_writeln("xrdp_caps_process_codecs: jpeg codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.jpeg_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.jpeg_prop, s->p, i1); + self->client_info.jpeg_prop_len = i1; + /* make sure that requested quality is between 0 to 100 */ + if (self->client_info.jpeg_prop[0] < 0 || self->client_info.jpeg_prop[0] > 100) + { + g_writeln(" Warning: the requested jpeg quality (%d) is invalid," + " falling back to default", self->client_info.jpeg_prop[0]); + self->client_info.jpeg_prop[0] = 75; /* use default */ + } + g_writeln(" jpeg quality set to %d", self->client_info.jpeg_prop[0]); + } + else + { + g_writeln("xrdp_caps_process_codecs: unknown codec id %d", codec_id); + } + + s->p = next_guid; + } + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_multifragmetupdate(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int MaxRequestSize; + + in_uint32_le(s, MaxRequestSize); + self->client_info.max_fastpath_frag_bytes = MaxRequestSize; + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) +{ + int cap_len; + int source_len; + int num_caps; + int index; + int type; + int len; + char *p; + + DEBUG(("in xrdp_caps_process_confirm_active")); + in_uint8s(s, 4); /* rdp_shareid */ + in_uint8s(s, 2); /* userid */ + in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */ + in_uint16_le(s, cap_len); + in_uint8s(s, source_len); + in_uint16_le(s, num_caps); + in_uint8s(s, 2); /* pad */ + + for (index = 0; index < num_caps; index++) + { + p = s->p; + if (!s_check_rem(s, 4)) + { + g_writeln("xrdp_caps_process_confirm_active: error 1"); + return 1; + } + in_uint16_le(s, type); + in_uint16_le(s, len); + if ((len < 4) || !s_check_rem(s, len - 4)) + { + g_writeln("xrdp_caps_process_confirm_active: error len %d", len, s->end - s->p); + return 1; + } + len -= 4; + switch (type) + { + case RDP_CAPSET_GENERAL: /* 1 */ + DEBUG(("RDP_CAPSET_GENERAL")); + xrdp_caps_process_general(self, s, len); + break; + case RDP_CAPSET_BITMAP: /* 2 */ + DEBUG(("RDP_CAPSET_BITMAP")); + break; + case RDP_CAPSET_ORDER: /* 3 */ + DEBUG(("RDP_CAPSET_ORDER")); + xrdp_caps_process_order(self, s, len); + break; + case RDP_CAPSET_BMPCACHE: /* 4 */ + DEBUG(("RDP_CAPSET_BMPCACHE")); + xrdp_caps_process_bmpcache(self, s, len); + break; + case RDP_CAPSET_CONTROL: /* 5 */ + DEBUG(("RDP_CAPSET_CONTROL")); + break; + case 6: + xrdp_caps_process_cache_v3_codec_id(self, s, len); + break; + case RDP_CAPSET_ACTIVATE: /* 7 */ + DEBUG(("RDP_CAPSET_ACTIVATE")); + break; + case RDP_CAPSET_POINTER: /* 8 */ + DEBUG(("RDP_CAPSET_POINTER")); + xrdp_caps_process_pointer(self, s, len); + break; + case RDP_CAPSET_SHARE: /* 9 */ + DEBUG(("RDP_CAPSET_SHARE")); + break; + case RDP_CAPSET_COLCACHE: /* 10 */ + DEBUG(("RDP_CAPSET_COLCACHE")); + break; + case 12: /* 12 */ + DEBUG(("--12")); + break; + case 13: /* 13 */ + xrdp_caps_process_input(self, s, len); + break; + case 14: /* 14 */ + DEBUG(("--14")); + break; + case RDP_CAPSET_BRUSHCACHE: /* 15 */ + xrdp_caps_process_brushcache(self, s, len); + break; + case 16: /* 16 */ + DEBUG(("--16")); + break; + case 17: /* 17 */ + DEBUG(("CAPSET_TYPE_OFFSCREEN_CACHE")); + xrdp_caps_process_offscreen_bmpcache(self, s, len); + break; + case RDP_CAPSET_BMPCACHE2: /* 19 */ + DEBUG(("RDP_CAPSET_BMPCACHE2")); + xrdp_caps_process_bmpcache2(self, s, len); + break; + case 20: /* 20 */ + DEBUG(("--20")); + break; + case 21: /* 21 */ + DEBUG(("--21")); + break; + case 22: /* 22 */ + DEBUG(("--22")); + break; + case 0x0017: /* 23 CAPSETTYPE_RAIL */ + xrdp_caps_process_rail(self, s, len); + break; + case 0x0018: /* 24 CAPSETTYPE_WINDOW */ + xrdp_caps_process_window(self, s, len); + break; + case 0x001A: /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */ + xrdp_caps_process_multifragmetupdate(self, s, len); + break; + case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */ + xrdp_caps_process_codecs(self, s, len); + break; + default: + g_writeln("unknown in xrdp_caps_process_confirm_active %d", type); + break; + } + + s->p = p + len + 4; + } + + DEBUG(("out xrdp_caps_process_confirm_active")); + return 0; +} +/*****************************************************************************/ +int APP_CC +xrdp_caps_send_demand_active(struct xrdp_rdp *self) +{ + struct stream *s; + int caps_count; + int caps_size; + int codec_caps_count; + int codec_caps_size; + int flags; + char *caps_count_ptr; + char *caps_size_ptr; + char *caps_ptr; + char *codec_caps_count_ptr; + char *codec_caps_size_ptr; + + make_stream(s); + init_stream(s, 8192); + + DEBUG(("in xrdp_caps_send_demand_active")); + + if (xrdp_rdp_init(self, s) != 0) + { + free_stream(s); + return 1; + } + + caps_count = 0; + out_uint32_le(s, self->share_id); + out_uint16_le(s, 4); /* 4 chars for RDP\0 */ + /* 2 bytes size after num caps, set later */ + caps_size_ptr = s->p; + out_uint8s(s, 2); + out_uint8a(s, "RDP", 4); + /* 4 byte num caps, set later */ + caps_count_ptr = s->p; + out_uint8s(s, 4); + caps_ptr = s->p; + + /* Output share capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_SHARE); + out_uint16_le(s, RDP_CAPLEN_SHARE); + out_uint16_le(s, self->mcs_channel); + out_uint16_be(s, 0xb5e2); /* 0x73e1 */ + + /* Output general capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */ + out_uint16_le(s, RDP_CAPLEN_GENERAL); /* 24(0x18) */ + 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_le(s, 0); /* pad */ + out_uint16_le(s, 0); /* Compression types */ + /* NO_BITMAP_COMPRESSION_HDR 0x0400 + FASTPATH_OUTPUT_SUPPORTED 0x0001 */ + if (self->client_info.use_fast_path & 1) + { + out_uint16_le(s, 0x401); + } + else + { + out_uint16_le(s, 0x400); + } + out_uint16_le(s, 0); /* Update capability */ + out_uint16_le(s, 0); /* Remote unshare capability */ + out_uint16_le(s, 0); /* Compression level */ + out_uint16_le(s, 0); /* Pad */ + + /* Output bitmap capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_BITMAP); /* 2 */ + out_uint16_le(s, RDP_CAPLEN_BITMAP); /* 28(0x1c) */ + out_uint16_le(s, self->client_info.bpp); /* Preferred BPP */ + 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, self->client_info.width); /* width */ + out_uint16_le(s, self->client_info.height); /* height */ + out_uint16_le(s, 0); /* Pad */ + out_uint16_le(s, 1); /* Allow resize */ + out_uint16_le(s, 1); /* bitmap compression */ + out_uint16_le(s, 0); /* unknown */ + out_uint16_le(s, 0); /* unknown */ + out_uint16_le(s, 0); /* pad */ + + /* Output font capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_FONT); /* 14 */ + out_uint16_le(s, RDP_CAPLEN_FONT); /* 4 */ + + /* Output order capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_ORDER); /* 3 */ + out_uint16_le(s, RDP_CAPLEN_ORDER); /* 88(0x58) */ + out_uint8s(s, 16); + out_uint32_be(s, 0x40420f00); + out_uint16_le(s, 1); /* Cache X granularity */ + out_uint16_le(s, 20); /* Cache Y granularity */ + out_uint16_le(s, 0); /* Pad */ + out_uint16_le(s, 1); /* Max order level */ + out_uint16_le(s, 0x2f); /* Number of fonts */ + out_uint16_le(s, 0x22); /* Capability flags */ + /* caps */ + out_uint8(s, 1); /* NEG_DSTBLT_INDEX 0x00 0 */ + out_uint8(s, 1); /* NEG_PATBLT_INDEX 0x01 1 */ + out_uint8(s, 1); /* NEG_SCRBLT_INDEX 0x02 2 */ + out_uint8(s, 1); /* NEG_MEMBLT_INDEX 0x03 3 */ + out_uint8(s, 0); /* NEG_MEM3BLT_INDEX 0x04 4 */ + out_uint8(s, 0); /* NEG_ATEXTOUT_INDEX 0x05 5 */ + out_uint8(s, 0); /* NEG_AEXTTEXTOUT_INDEX 0x06 6 */ + out_uint8(s, 0); /* NEG_DRAWNINEGRID_INDEX 0x07 7 */ + out_uint8(s, 1); /* NEG_LINETO_INDEX 0x08 8 */ + out_uint8(s, 0); /* NEG_MULTI_DRAWNINEGRID_INDEX 0x09 9 */ + out_uint8(s, 1); /* NEG_OPAQUE_RECT_INDEX 0x0A 10 */ + out_uint8(s, 0); /* NEG_SAVEBITMAP_INDEX 0x0B 11 */ + out_uint8(s, 0); /* NEG_WTEXTOUT_INDEX 0x0C 12 */ + out_uint8(s, 0); /* NEG_MEMBLT_V2_INDEX 0x0D 13 */ + out_uint8(s, 0); /* NEG_MEM3BLT_V2_INDEX 0x0E 14 */ + out_uint8(s, 0); /* NEG_MULTIDSTBLT_INDEX 0x0F 15 */ + out_uint8(s, 0); /* NEG_MULTIPATBLT_INDEX 0x10 16 */ + out_uint8(s, 0); /* NEG_MULTISCRBLT_INDEX 0x11 17 */ + out_uint8(s, 1); /* NEG_MULTIOPAQUERECT_INDEX 0x12 18 */ + out_uint8(s, 0); /* NEG_FAST_INDEX_INDEX 0x13 19 */ + out_uint8(s, 0); /* NEG_POLYGON_SC_INDEX 0x14 20 */ + out_uint8(s, 0); /* NEG_POLYGON_CB_INDEX 0x15 21 */ + out_uint8(s, 0); /* NEG_POLYLINE_INDEX 0x16 22 */ + out_uint8(s, 0); /* unused 0x17 23 */ + out_uint8(s, 0); /* NEG_FAST_GLYPH_INDEX 0x18 24 */ + out_uint8(s, 0); /* NEG_ELLIPSE_SC_INDEX 0x19 25 */ + out_uint8(s, 0); /* NEG_ELLIPSE_CB_INDEX 0x1A 26 */ + out_uint8(s, 1); /* NEG_GLYPH_INDEX_INDEX 0x1B 27 */ + out_uint8(s, 0); /* NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C 28 */ + out_uint8(s, 0); /* NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D 29 */ + out_uint8(s, 0); /* NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E 30 */ + out_uint8(s, 0); /* unused 0x1F 31 */ + out_uint16_le(s, 0x6a1); + /* declare support of bitmap cache rev3 */ + out_uint16_le(s, XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT); + out_uint32_le(s, 0x0f4240); /* desk save */ + out_uint32_le(s, 0x0f4240); /* desk save */ + out_uint32_le(s, 1); /* ? */ + out_uint32_le(s, 0); /* ? */ + + /* Output bmpcodecs capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_BMPCODECS); + codec_caps_size_ptr = s->p; + out_uint8s(s, 2); /* cap len set later */ + codec_caps_count = 0; + codec_caps_count_ptr = s->p; + out_uint8s(s, 1); /* bitmapCodecCount set later */ + /* nscodec */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_NSCODEC, 16); + out_uint8(s, 1); /* codec id, must be 1 */ + out_uint16_le(s, 3); + out_uint8(s, 0x01); /* fAllowDynamicFidelity */ + out_uint8(s, 0x01); /* fAllowSubsampling */ + out_uint8(s, 0x03); /* colorLossLevel */ + /* remotefx */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_REMOTEFX, 16); + out_uint8(s, 0); /* codec id, client sets */ + out_uint16_le(s, 256); + out_uint8s(s, 256); + /* jpeg */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_JPEG, 16); + out_uint8(s, 0); /* codec id, client sets */ + out_uint16_le(s, 1); /* ext length */ + out_uint8(s, 75); + /* calculate and set size and count */ + codec_caps_size = (int)(s->p - codec_caps_size_ptr); + codec_caps_size += 2; /* 2 bytes for RDP_CAPSET_BMPCODECS above */ + codec_caps_size_ptr[0] = codec_caps_size; + codec_caps_size_ptr[1] = codec_caps_size >> 8; + codec_caps_count_ptr[0] = codec_caps_count; + + /* Output color cache capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_COLCACHE); + out_uint16_le(s, RDP_CAPLEN_COLCACHE); + out_uint16_le(s, 6); /* cache size */ + out_uint16_le(s, 0); /* pad */ + + /* Output pointer capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_POINTER); + out_uint16_le(s, RDP_CAPLEN_POINTER); + out_uint16_le(s, 1); /* Colour pointer */ + out_uint16_le(s, 0x19); /* Cache size */ + out_uint16_le(s, 0x19); /* Cache size */ + + /* Output input capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_INPUT); /* 13(0xd) */ + out_uint16_le(s, RDP_CAPLEN_INPUT); /* 88(0x58) */ + + /* INPUT_FLAG_SCANCODES 0x0001 + INPUT_FLAG_MOUSEX 0x0004 + INPUT_FLAG_FASTPATH_INPUT 0x0008 + INPUT_FLAG_FASTPATH_INPUT2 0x0020 */ + flags = 0x0001 | 0x0004; + if (self->client_info.use_fast_path & 2) + { + /* 0x0008 INPUT_FLAG_FASTPATH_INPUT */ + /* 0x0020 INPUT_FLAG_FASTPATH_INPUT2 */ + flags |= 0x0008 | 0x0020; + } + out_uint16_le(s, flags); + out_uint8s(s, 82); + + /* Remote Programs Capability Set */ + caps_count++; + out_uint16_le(s, 0x0017); /* CAPSETTYPE_RAIL */ + out_uint16_le(s, 8); + out_uint32_le(s, 3); /* TS_RAIL_LEVEL_SUPPORTED + TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */ + + /* Window List Capability Set */ + caps_count++; + out_uint16_le(s, 0x0018); /* CAPSETTYPE_WINDOW */ + out_uint16_le(s, 11); + out_uint32_le(s, 2); /* TS_WINDOW_LEVEL_SUPPORTED_EX */ + out_uint8(s, 3); /* NumIconCaches */ + out_uint16_le(s, 12); /* NumIconCacheEntries */ + + /* 6 - bitmap cache v3 codecid */ + caps_count++; + out_uint16_le(s, 0x0006); + out_uint16_le(s, 5); + out_uint8(s, 0); /* client sets */ + + if (self->client_info.use_fast_path & 1) /* fastpath output on */ + { + caps_count++; + out_uint16_le(s, 0x001A); /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */ + out_uint16_le(s, 8); + out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */ + } + + out_uint8s(s, 4); /* pad */ + + s_mark_end(s); + + caps_size = (int)(s->end - caps_ptr); + caps_size_ptr[0] = caps_size; + caps_size_ptr[1] = caps_size >> 8; + + caps_count_ptr[0] = caps_count; + caps_count_ptr[1] = caps_count >> 8; + caps_count_ptr[2] = caps_count >> 16; + caps_count_ptr[3] = caps_count >> 24; + + if (xrdp_rdp_send(self, s, RDP_PDU_DEMAND_ACTIVE) != 0) + { + free_stream(s); + return 1; + } + DEBUG(("out (1) xrdp_caps_send_demand_active")); + + /* send Monitor Layout PDU for dual monitor */ + if (self->client_info.monitorCount > 0 && + self->client_info.multimon == 1) + { + DEBUG(("xrdp_caps_send_demand_active: sending monitor layout pdu")); + if (xrdp_caps_send_monitorlayout(self) != 0) + { + g_writeln("xrdp_caps_send_demand_active: error sending monitor layout pdu"); + } + } + + free_stream(s); + return 0; +} diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c index 198b876b..7d3909d5 100644 --- a/libxrdp/xrdp_channel.c +++ b/libxrdp/xrdp_channel.c @@ -105,10 +105,21 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id, s_pop_layer(s, channel_hdr); out_uint32_le(s, total_data_len); - if (channel->flags & XR_CHANNEL_OPTION_SHOW_PROTOCOL) - { - flags |= CHANNEL_FLAG_SHOW_PROTOCOL; - } + /* + * According to 2.2.1.3.4.1 Channel Definition Structure (CHANNEL_DEF): + * CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 + * The value of this flag MUST be ignored by the server. The + * visibility of the Channel PDU Header (section 2.2.6.1.1) is + * determined by the CHANNEL_FLAG_SHOW_PROTOCOL + * (0x00000010) flag as defined in the flags field (section + * 2.2.6.1.1). + * + * That's flag makes MSTSC crash when using RAIL channel. + */ +// if (channel->flags & XR_CHANNEL_OPTION_SHOW_PROTOCOL) +// { +// flags |= CHANNEL_FLAG_SHOW_PROTOCOL; +// } out_uint32_le(s, flags); diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index 10f844e5..f84f5ae1 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -1,8 +1,8 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2012-2013 - * Copyright (C) Kevin Zhou 2012 + * Copyright (C) Jay Sorg 2012-2014 + * Copyright (C) Idan Freiberg 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,16 +21,16 @@ /*****************************************************************************/ struct xrdp_fastpath *APP_CC -xrdp_fastpath_create(struct xrdp_session *session) +xrdp_fastpath_create(struct xrdp_sec *owner, struct trans *trans) { struct xrdp_fastpath *self; + DEBUG((" in xrdp_fastpath_create")); self = (struct xrdp_fastpath *)g_malloc(sizeof(struct xrdp_fastpath), 1); - self->tcp_layer = - ((struct xrdp_rdp *)session->rdp)->sec_layer-> - mcs_layer->iso_layer->tcp_layer; - make_stream(self->out_s); - init_stream(self->out_s, FASTPATH_MAX_PACKET_SIZE); + self->sec_layer = owner; + self->trans = trans; + self->session = owner->rdp_layer->session; + DEBUG((" out xrdp_fastpath_create")); return self; } @@ -42,8 +42,6 @@ xrdp_fastpath_delete(struct xrdp_fastpath *self) { return; } - - free_stream(self->out_s); g_free(self); } @@ -55,155 +53,306 @@ xrdp_fastpath_reset(struct xrdp_fastpath *self) return 0; } +/*****************************************************************************/ int APP_CC -xrdp_fastpath_init(struct xrdp_fastpath *self) +xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s) { + int fp_hdr; + int len = 0; /* unused */ + int byte; + char *holdp; + + DEBUG((" in xrdp_fastpath_recv")); + holdp = s->p; + if (!s_check_rem(s, 2)) + { + return 1; + } + in_uint8(s, fp_hdr); /* fpInputHeader (1 byte) */ + in_uint8(s, byte); /* length 1 (1 byte) */ + + self->numEvents = (fp_hdr & 0x3C) >> 2; + self->secFlags = (fp_hdr & 0xC0) >> 6; + + if (byte & 0x80) + { + byte &= ~(0x80); + len = (byte << 8); + + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, byte); /* length 2 (1 byte) */ + + len += byte; + } + else + { + len = byte; + } + s->next_packet = holdp + len; + DEBUG((" out xrdp_fastpath_recv")); return 0; } /*****************************************************************************/ +/* no fragmenation */ int APP_CC -xrdp_fastpath_send_update_pdu(struct xrdp_fastpath *self, tui8 updateCode, - struct stream *s) +xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s) { - tui16 len; - tui16 maxLen; - tui32 payloadLeft; - tui8 fragment; - struct stream *s_send; - int compression; - int i; - int i32; + int bytes; - compression = 0; - s_send = self->out_s; - maxLen = FASTPATH_MAX_PACKET_SIZE - 6; /* 6 bytes for header */ - payloadLeft = (s->end - s->data); + bytes = self->session->client_info->max_fastpath_frag_bytes; + if (bytes < 32 * 1024) + { + bytes = 32 * 1024; + } + init_stream(s, bytes); + return 0; +} - for (i = 0; payloadLeft > 0; i++) +/*****************************************************************************/ +/* no fragmenation */ +int APP_CC +xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s) +{ + if (trans_force_write_s(self->trans, s) != 0) { - if (payloadLeft > maxLen) - { - len = maxLen; - } - else - { - len = payloadLeft; - } + return 1; + } + return 0; +} - payloadLeft -= len; +/*****************************************************************************/ +/* FASTPATH_INPUT_EVENT_SCANCODE */ +int APP_CC +xrdp_fastpath_process_EVENT_SCANCODE(struct xrdp_fastpath *self, + int eventFlags, struct stream *s) +{ + int flags; + int code; + flags = 0; - if (payloadLeft == 0) - { - fragment = i ? FASTPATH_FRAGMENT_LAST : FASTPATH_FRAGMENT_SINGLE; - } - else - { - fragment = i ? FASTPATH_FRAGMENT_NEXT : FASTPATH_FRAGMENT_FIRST; - } + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, code); /* keyCode (1 byte) */ - init_stream(s_send, 0); - out_uint8(s_send, 0); /* fOutputHeader */ - i32 = ((len + 6) >> 8) | 0x80; - out_uint8(s_send, i32); /* use 2 bytes for length even length < 128 ??? */ - i32 = (len + 6) & 0xff; - out_uint8(s_send, i32); - i32 = (updateCode & 0x0f) | ((fragment & 0x03) << 4) | - ((compression & 0x03) << 6); - out_uint8(s_send, i32); - out_uint16_le(s_send, len); - s_copy(s_send, s, len); - s_mark_end(s_send); - - if (xrdp_tcp_send(self->tcp_layer, s_send) != 0) - { - return 1; - } + if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE)) + { + flags |= KBD_FLAG_UP; + } + else + { + flags |= KBD_FLAG_DOWN; } + if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_EXTENDED)) + flags |= KBD_FLAG_EXT; + + if (self->session->callback != 0) + { + /* msg_type can be + RDP_INPUT_SYNCHRONIZE - 0 + RDP_INPUT_SCANCODE - 4 + RDP_INPUT_MOUSE - 0x8001 + RDP_INPUT_MOUSEX - 0x8002 */ + /* call to xrdp_wm.c : callback */ + self->session->callback(self->session->id, RDP_INPUT_SCANCODE, code, 0, + flags, 0); + } return 0; } /*****************************************************************************/ -int -xrdp_fastpath_process_update(struct xrdp_fastpath *self, tui8 updateCode, - tui32 size, struct stream *s) +/* FASTPATH_INPUT_EVENT_MOUSE */ +int APP_CC +xrdp_fastpath_process_EVENT_MOUSE(struct xrdp_fastpath *self, int eventFlags, + struct stream *s) { - switch (updateCode) - { - case FASTPATH_UPDATETYPE_ORDERS: - case FASTPATH_UPDATETYPE_BITMAP: - case FASTPATH_UPDATETYPE_PALETTE: - case FASTPATH_UPDATETYPE_SYNCHRONIZE: - case FASTPATH_UPDATETYPE_SURFCMDS: - case FASTPATH_UPDATETYPE_PTR_NULL: - case FASTPATH_UPDATETYPE_PTR_DEFAULT: - case FASTPATH_UPDATETYPE_PTR_POSITION: - case FASTPATH_UPDATETYPE_COLOR: - case FASTPATH_UPDATETYPE_CACHED: - case FASTPATH_UPDATETYPE_POINTER: - break; - default: - g_writeln("xrdp_fastpath_process_update: unknown updateCode 0x%X", - updateCode); - break; + int pointerFlags; + int xPos; + int yPos; + + /* eventFlags MUST be zeroed out */ + if (eventFlags != 0) + { + return 1; + } + + if (!s_check_rem(s, 2 + 2 + 2)) + { + return 1; } + in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */ + in_uint16_le(s, xPos); /* xPos (2 bytes) */ + in_uint16_le(s, yPos); /* yPos (2 bytes) */ + if (self->session->callback != 0) + { + /* msg_type can be + RDP_INPUT_SYNCHRONIZE - 0 + RDP_INPUT_SCANCODE - 4 + RDP_INPUT_MOUSE - 0x8001 + RDP_INPUT_MOUSEX - 0x8002 */ + /* call to xrdp_wm.c : callback */ + self->session->callback(self->session->id, RDP_INPUT_MOUSE, + xPos, yPos, pointerFlags, 0); + } return 0; } /*****************************************************************************/ +/* FASTPATH_INPUT_EVENT_MOUSEX */ int APP_CC -xrdp_fastpath_process_data(struct xrdp_fastpath *self, struct stream *s, - tui8 header) +xrdp_fastpath_process_EVENT_MOUSEX(struct xrdp_fastpath *self, + int eventFlags, struct stream *s) { - tui8 encryptionFlags; - tui8 numberEvents; - tui8 length2; - tui8 updateHeader; - tui8 updateCode; - tui8 updateFrag; - tui8 updateComp; - tui16 length; - tui32 size; - - encryptionFlags = (header & 0xc0) >> 6; - numberEvents = (header & 0x3c) >> 2; - xrdp_tcp_recv(self->tcp_layer, s, 1); - in_uint8(s, length); - - if (length & 0x80) - { - xrdp_tcp_recv(self->tcp_layer, s, 1); - in_uint8(s, length2); - length = (length & 0x7f) << 8 + length2 - 3; + int pointerFlags; + int xPos; + int yPos; + + /* eventFlags MUST be zeroed out */ + if (eventFlags != 0) + { + return 1; } - else + + if (!s_check_rem(s, 2 + 2 + 2)) { - length -= 2; + return 1; } + in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */ + in_uint16_le(s, xPos); /* xPos (2 bytes) */ + in_uint16_le(s, yPos); /* yPos (2 bytes) */ - xrdp_tcp_recv(self->tcp_layer, s, length); + if (self->session->callback != 0) + { + /* msg_type can be + RDP_INPUT_SYNCHRONIZE - 0 + RDP_INPUT_SCANCODE - 4 + RDP_INPUT_MOUSE - 0x8001 + RDP_INPUT_MOUSEX - 0x8002 */ + /* call to xrdp_wm.c : callback */ + self->session->callback(self->session->id, RDP_INPUT_MOUSEX, + xPos, yPos, pointerFlags, 0); + } + return 0; +} - if (encryptionFlags != 0) +/*****************************************************************************/ +/* FASTPATH_INPUT_EVENT_SYNC */ +int APP_CC +xrdp_fastpath_process_EVENT_SYNC(struct xrdp_fastpath *self, int eventCode, + int eventFlags, struct stream *s) +{ + /* + * The eventCode bitfield (3 bits in size) MUST be set to + * FASTPATH_INPUT_EVENT_SYNC (3). + * The eventFlags bitfield (5 bits in size) contains flags + * indicating the "on" + * status of the keyboard toggle keys. + */ + if (self->session->callback != 0) { - /* TODO decryption ...*/ + /* msg_type can be + RDP_INPUT_SYNCHRONIZE - 0 + RDP_INPUT_SCANCODE - 4 + RDP_INPUT_MOUSE - 0x8001 + RDP_INPUT_MOUSEX - 0x8002 */ + /* call to xrdp_wm.c : callback */ + self->session->callback(self->session->id, RDP_INPUT_SYNCHRONIZE, + eventCode, 0, eventFlags, 0); } + return 0; +} + +/*****************************************************************************/ +/* FASTPATH_INPUT_EVENT_UNICODE */ +int APP_CC +xrdp_fastpath_process_EVENT_UNICODE(struct xrdp_fastpath *self, + int eventFlags, struct stream *s) +{ + if (!s_check_rem(s, 2)) + { + return 1; + } + in_uint8s(s, 2); + return 0; +} - /* parse updateHeader */ - in_uint8(s, updateHeader); - updateCode = (updateHeader & 0x0f); - updateFrag = (updateHeader & 0x30) >> 4; - updateComp = (updateHeader & 0xc0) >> 6; +/*****************************************************************************/ +/* FASTPATH_INPUT_EVENT */ +int APP_CC +xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, struct stream *s) +{ + int i; + int eventHeader; + int eventCode; + int eventFlags; - if (updateFrag && updateComp) + /* process fastpath input events */ + for (i = 0; i < self->numEvents; i++) { - /* TODO */ - g_writeln("xrdp_fastpath_process_data: updateFrag=%d, updateComp=%d", - updateFrag, updateComp); - return 1; - } + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, eventHeader); + + eventFlags = (eventHeader & 0x1F); + eventCode = (eventHeader >> 5); + + switch (eventCode) + { + case FASTPATH_INPUT_EVENT_SCANCODE: + if (xrdp_fastpath_process_EVENT_SCANCODE(self, + eventFlags, + s) != 0) + { + return 1; + } + break; - in_uint16_le(s, size); - return xrdp_fastpath_process_update(self, updateCode, size, s); + case FASTPATH_INPUT_EVENT_MOUSE: + if (xrdp_fastpath_process_EVENT_MOUSE(self, + eventFlags, + s) != 0) + { + return 1; + } + break; + case FASTPATH_INPUT_EVENT_MOUSEX: + if (xrdp_fastpath_process_EVENT_MOUSEX(self, + eventFlags, + s) != 0) + { + return 1; + } + break; + case FASTPATH_INPUT_EVENT_SYNC: + if (xrdp_fastpath_process_EVENT_SYNC(self, eventCode, + eventFlags, + s) != 0) + { + return 1; + } + break; + case FASTPATH_INPUT_EVENT_UNICODE: + if (xrdp_fastpath_process_EVENT_UNICODE(self, + eventFlags, + s) != 0) + { + return 1; + } + break; + default: + g_writeln("xrdp_fastpath_process_input_event: unknown " + "eventCode %d", eventCode); + break; + } + } + return 0; } diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c index 31c279b5..ee490839 100644 --- a/libxrdp/xrdp_iso.c +++ b/libxrdp/xrdp_iso.c @@ -1,8 +1,8 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 - * Copyright (C) Idan Freiberg 2013 + * Copyright (C) Jay Sorg 2004-2014 + * Copyright (C) Idan Freiberg 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,13 +22,14 @@ #include "libxrdp.h" /*****************************************************************************/ -struct xrdp_iso *APP_CC +struct xrdp_iso * +APP_CC xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans) { struct xrdp_iso *self; DEBUG((" in xrdp_iso_create")); - self = (struct xrdp_iso *)g_malloc(sizeof(struct xrdp_iso), 1); + self = (struct xrdp_iso *) g_malloc(sizeof(struct xrdp_iso), 1); self->mcs_layer = owner; self->trans = trans; DEBUG((" out xrdp_iso_create")); @@ -50,37 +51,33 @@ xrdp_iso_delete(struct xrdp_iso *self) /*****************************************************************************/ /* returns error */ static int APP_CC -xrdp_iso_recv_rdpnegreq(struct xrdp_iso *self, struct stream *s) +xrdp_iso_process_rdpNegReq(struct xrdp_iso *self, struct stream *s) { int flags; int len; - DEBUG((" in xrdp_iso_recv_rdpnegreq")); - in_uint8(s, flags); - if (flags != 0x0) + if (flags != 0x0 && flags != 0x8 && flags != 0x1) { - DEBUG((" xrdp_iso_recv_rdpnegreq: flags: %x",flags)); + DEBUG(("xrdp_iso_process_rdpNegReq: error, flags: %x",flags)); return 1; } in_uint16_le(s, len); - if (len != 8) // fixed length + if (len != 8) { - DEBUG((" xrdp_iso_recv_rdpnegreq: length: %x",len)); + DEBUG(("xrdp_iso_process_rdpNegReq: error, length: %x",len)); return 1; } in_uint32_le(s, self->requestedProtocol); + if (self->requestedProtocol > 0xb) + { + DEBUG(("xrdp_iso_process_rdpNegReq: error, requestedProtocol: %x", + self->requestedProtocol)); + return 1; + } - //TODO: think of protocol verification logic -// if (requestedProtocol != PROTOCOL_RDP || PROTOCOL_SSL || PROTOCOL_HYBRID || PROTOCOL_HYBRID_EX) -// { -// DEBUG((" xrdp_iso_recv_rdpnegreq: wrong requestedProtocol: %x",requestedProtocol)); -// return 1; -// } - - DEBUG((" out xrdp_iso_recv_rdpnegreq")); return 0; } /*****************************************************************************/ @@ -88,29 +85,23 @@ xrdp_iso_recv_rdpnegreq(struct xrdp_iso *self, struct stream *s) static int APP_CC xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len) { - int ver; // TPKT Version - int plen; // TPKT PacketLength - int do_read; - - *code = 0; // X.224 Packet Type - *len = 0; // X.224 Length Indicator + int ver; // tpkt ver + int plen; // tpkt len - /* early in connection sequence, iso needs to do a force read */ - do_read = s != self->trans->in_s; + *code = 0; // x.244 type + *len = 0; // X.224 len indicator - if (do_read) + if (s != self->trans->in_s) { - init_stream(s, 4); - if (trans_force_read_s(self->trans, s, 4) != 0) - { - return 1; - } + g_writeln("xrdp_iso_recv_msg error logic"); } in_uint8(s, ver); if (ver != 3) { + g_writeln("xrdp_iso_recv_msg: bad ver"); + g_hexdump(s->data, 4); return 1; } @@ -122,15 +113,6 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len) return 1; } - if (do_read) - { - init_stream(s, plen - 4); - if (trans_force_read_s(self->trans, s, plen - 4) != 0) - { - return 1; - } - } - if (!s_check_rem(s, 2)) { return 1; @@ -184,120 +166,70 @@ xrdp_iso_recv(struct xrdp_iso *self, struct stream *s) DEBUG((" out xrdp_iso_recv")); return 0; } - /*****************************************************************************/ static int APP_CC -xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s, int code) +xrdp_iso_send_cc(struct xrdp_iso *self) { - init_stream(s, 8192 * 4); /* 32 KB */ + struct stream *s; + char *holdp; + char *len_ptr; + char *len_indicator_ptr; + int len; + int len_indicator; - /* TPKT HEADER - 4 bytes */ - out_uint8(s, 3); /* version */ - out_uint8(s, 0); /* RESERVED */ - if (self->selectedProtocol != -1) - { - out_uint16_be(s, 19); /* length */ //rdp negotiation happens. - } - else - { - out_uint16_be(s, 11); /* length */ //rdp negotiation doesn't happen. - } - /* ISO LAYER - X.224 - 7 bytes*/ - if (self->selectedProtocol != -1) - { - out_uint8(s, 14); /* length */ - } - else - { - out_uint8(s, 6); /* length */ - } - out_uint8(s, code); /* SHOULD BE 0xD for CC */ + make_stream(s); + init_stream(s, 8192); + + holdp = s->p; + /* tpkt */ + out_uint8(s, 3); /* version */ + out_uint8(s, 0); /* pad */ + len_ptr = s->p; + out_uint16_be(s, 0); /* length, set later */ + /* iso */ + len_indicator_ptr = s->p; + out_uint8(s, 0); /* length indicator, set later */ + out_uint8(s, ISO_PDU_CC); /* Connection Confirm PDU */ out_uint16_be(s, 0); out_uint16_be(s, 0x1234); out_uint8(s, 0); - if (self->selectedProtocol != -1) + /* rdpNegData */ + if (self->rdpNegData) { - /* RDP_NEG_RSP - 8 bytes*/ - out_uint8(s, RDP_NEG_RSP); - out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ - out_uint16_le(s, 8); /* fixed length */ - out_uint32_le(s, self->selectedProtocol); /* selected protocol */ + if (self->failureCode) + { + out_uint8(s, RDP_NEG_FAILURE); + out_uint8(s, 0); /* no flags */ + out_uint16_le(s, 8); /* must be 8 */ + out_uint32_le(s, self->failureCode); /* failure code */ + } + else + { + out_uint8(s, RDP_NEG_RSP); + //TODO: hardcoded flags + out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ + out_uint16_le(s, 8); /* must be 8 */ + out_uint32_le(s, self->selectedProtocol); /* selected protocol */ + } } s_mark_end(s); - if (trans_force_write_s(self->trans, s) != 0) - { - return 1; - } - - return 0; -} -/*****************************************************************************/ -static int APP_CC -xrdp_iso_send_rdpnegfailure(struct xrdp_iso *self, struct stream *s, int code, int failureCode) -{ - init_stream(s, 8192 * 4); /* 32 KB */ - - /* TPKT HEADER - 4 bytes */ - out_uint8(s, 3); /* version */ - out_uint8(s, 0); /* RESERVED */ - out_uint16_be(s, 19); /* length */ - /* ISO LAYER - X.224 - 7 bytes*/ - out_uint8(s, 14); /* length */ - out_uint8(s, code); /* SHOULD BE 0xD for CC */ - out_uint16_be(s, 0); - out_uint16_be(s, 0x1234); - out_uint8(s, 0); - /* RDP_NEG_FAILURE - 8 bytes*/ - out_uint8(s, RDP_NEG_FAILURE); - out_uint8(s, 0); /* no flags available */ - out_uint16_le(s, 8); /* fixed length */ - out_uint32_le(s, failureCode); /* failure code */ - s_mark_end(s); + len = (int) (s->end - holdp); + len_indicator = (int) (s->end - len_indicator_ptr) - 1; + len_ptr[0] = len >> 8; + len_ptr[1] = len; + len_indicator_ptr[0] = len_indicator; if (trans_force_write_s(self->trans, s) != 0) { + free_stream(s); return 1; } - return 0; -} - -/*****************************************************************************/ -static int APP_CC -xrdp_iso_send_nego(struct xrdp_iso *self) -{ - struct stream *s; - - make_stream(s); - init_stream(s, 8192); - - //TODO: negotiation logic here. - if (self->requestedProtocol != PROTOCOL_RDP) - { - // Send RDP_NEG_FAILURE back to client - if (xrdp_iso_send_rdpnegfailure(self, s, ISO_PDU_CC, - SSL_NOT_ALLOWED_BY_SERVER) != 0) - { - free_stream(s); - return 1; - } - } - else - { - self->selectedProtocol = PROTOCOL_RDP; - // Send RDP_NEG_RSP back to client - if (xrdp_iso_send_rdpnegrsp(self, s, ISO_PDU_CC) != 0) - { - free_stream(s); - return 1; - } - } free_stream(s); return 0; } - /*****************************************************************************/ /* returns error */ int APP_CC @@ -311,26 +243,26 @@ xrdp_iso_incoming(struct xrdp_iso *self) char *pend; struct stream *s; - make_stream(s); - init_stream(s, 8192); DEBUG((" in xrdp_iso_incoming")); + s = libxrdp_force_read(self->trans); + if (s == 0) + { + return 1; + } + if (xrdp_iso_recv_msg(self, s, &code, &len) != 0) { - DEBUG((" in xrdp_iso_recv_msg error!!")); - free_stream(s); + g_writeln("xrdp_iso_incoming: xrdp_iso_recv_msg returned non zero"); return 1; } if ((code != ISO_PDU_CR) || (len < 6)) { - free_stream(s); return 1; } - self->selectedProtocol = -1; - self->requestedProtocol = PROTOCOL_RDP; - + /* process connection request */ pend = s->p + (len - 6); cookie_index = 0; while (s->p < pend) @@ -341,9 +273,10 @@ xrdp_iso_incoming(struct xrdp_iso *self) default: break; case RDP_NEG_REQ: /* rdpNegReq 1 */ - if (xrdp_iso_recv_rdpnegreq(self, s) != 0) + self->rdpNegData = 1; + if (xrdp_iso_process_rdpNegReq(self, s) != 0) { - free_stream(s); + g_writeln("xrdp_iso_incoming: xrdp_iso_process_rdpNegReq returned non zero"); return 1; } break; @@ -369,14 +302,87 @@ xrdp_iso_incoming(struct xrdp_iso *self) } } - if (xrdp_iso_send_nego(self) != 0) + int serverSecurityLayer = self->mcs_layer->sec_layer->rdp_layer->client_info.security_layer; + /* security layer negotiation */ + if (self->rdpNegData) { - free_stream(s); + self->selectedProtocol = PROTOCOL_RDP; /* set default security layer */ + + switch (serverSecurityLayer) + { + case (PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_HYBRID_EX): + /* server supports tls+hybrid+hybrid_ex */ + if (self->requestedProtocol == (PROTOCOL_SSL | PROTOCOL_HYBRID + | PROTOCOL_HYBRID_EX)) + { + /* client supports tls+hybrid+hybrid_ex */ + self->selectedProtocol = PROTOCOL_SSL; //TODO: change + } + else + { + self->failureCode = SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER; + } + break; + case (PROTOCOL_SSL | PROTOCOL_HYBRID): + /* server supports tls+hybrid */ + if (self->requestedProtocol == (PROTOCOL_SSL | PROTOCOL_HYBRID)) + { + /* client supports tls+hybrid */ + self->selectedProtocol = PROTOCOL_SSL; //TODO: change + } + else + { + self->failureCode = HYBRID_REQUIRED_BY_SERVER; + } + break; + case PROTOCOL_SSL: + /* server supports tls */ + if (self->requestedProtocol & PROTOCOL_SSL) //TODO + { + /* client supports tls */ + self->selectedProtocol = PROTOCOL_SSL; + } + else + { + self->failureCode = SSL_REQUIRED_BY_SERVER; + } + break; + case PROTOCOL_RDP: + /* server supports rdp */ + if (self->requestedProtocol == PROTOCOL_RDP) + { + /* client supports rdp */ + self->selectedProtocol = PROTOCOL_RDP; + } + else + { + self->failureCode = SSL_NOT_ALLOWED_BY_SERVER; + } + break; + default: + /* unsupported protocol */ + g_writeln("xrdp_iso_incoming: unsupported protocol %d", + self->requestedProtocol); + self->failureCode = INCONSISTENT_FLAGS; //TODO: ? + } + } + else if (self->requestedProtocol != serverSecurityLayer) + { + /* enforce server security */ + return 1; + } + + /* set things for tls connection */ + + + /* send connection confirm back to client */ + if (xrdp_iso_send_cc(self) != 0) + { + g_writeln("xrdp_iso_incoming: xrdp_iso_send_cc returned non zero"); return 1; } DEBUG((" out xrdp_iso_incoming")); - free_stream(s); return 0; } @@ -399,7 +405,7 @@ xrdp_iso_send(struct xrdp_iso *self, struct stream *s) DEBUG((" in xrdp_iso_send")); s_pop_layer(s, iso_hdr); - len = (int)(s->end - s->p); + len = (int) (s->end - s->p); out_uint8(s, 3); out_uint8(s, 0); out_uint16_be(s, len); diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c index 334cc2e3..e4ce64fe 100644 --- a/libxrdp/xrdp_jpeg_compress.c +++ b/libxrdp/xrdp_jpeg_compress.c @@ -120,10 +120,11 @@ xrdp_codec_jpeg_compress(void *handle, /* len of compressed data */ ) { - tjhandle tj_han; - int error; - int bpp; - char *src_ptr; + tjhandle tj_han; + int error; + int bpp; + char *src_ptr; + unsigned long lio_len; /* * note: for now we assume that format is always XBGR and ignore format @@ -143,7 +144,21 @@ xrdp_codec_jpeg_compress(void *handle, /* start of inner rect in inp_data */ src_ptr = inp_data + (y * stride + x * bpp); + lio_len = *io_len; /* compress inner rect */ + + /* notes + * TJPF_RGB no works, zero bytes + * TJPF_BGR no works, not zero but no open + * TJPF_RGBX no works, zero bytes + * TJPF_BGRX no works, off scaled image + * TJPF_XBGR works + * TJPF_XRGB no works, zero bytes + * TJPF_RGBA no works, zero bytes + * TJPF_BGRA no works, zero bytes + * TJPF_ABGR no works, zero bytes + * TJPF_ARGB no works, zero bytes */ + error = tjCompress(tj_han, /* opaque handle */ src_ptr, /* source buf */ cx, /* width of area to compress */ @@ -151,11 +166,12 @@ xrdp_codec_jpeg_compress(void *handle, cy, /* height of area to compress */ TJPF_XBGR, /* pixel size */ out_data, /* dest buf */ - io_len, /* inner_buf length & compressed_size */ + &lio_len, /* inner_buf length & compressed_size */ TJSAMP_420, /* jpeg sub sample */ quality, /* jpeg quality */ 0 /* flags */ ); + *io_len = lio_len; return height; } @@ -382,6 +398,15 @@ xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, } /*****************************************************************************/ +int APP_CC +xrdp_codec_jpeg_compress(void *handle, int format, char *inp_data, int width, + int height, int stride, int x, int y, int cx, int cy, + int quality, char *out_data, int *io_len) +{ + return 0; +} + +/*****************************************************************************/ void *APP_CC xrdp_jpeg_init(void) { @@ -408,6 +433,15 @@ xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, } /*****************************************************************************/ +int APP_CC +xrdp_codec_jpeg_compress(void *handle, int format, char *inp_data, int width, + int height, int stride, int x, int y, int cx, int cy, + int quality, char *out_data, int *io_len) +{ + return 0; +} + +/*****************************************************************************/ void *APP_CC xrdp_jpeg_init(void) { diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index 9dcb5b51..716ad13f 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -122,14 +122,14 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) int len; int userid; int chanid; - DEBUG((" in xrdp_mcs_recv")); while (1) { if (xrdp_iso_recv(self->iso_layer, s) != 0) { - DEBUG((" out xrdp_mcs_recv xrdp_iso_recv returned non zero")); + DEBUG((" out xrdp_mcs_recv, xrdp_iso_recv return non zero")); + g_writeln("xrdp_mcs_recv: xrdp_iso_recv failed"); return 1; } @@ -151,12 +151,7 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) /* this is channels getting added from the client */ if (appid == MCS_CJRQ) { - if (s == self->iso_layer->trans->in_s) - { - /* this should not happen */ - g_writeln("xrdp_mcs_recv: error, MCS_CJRQ at wrong time"); - return 1; - } + if (!s_check_rem(s, 4)) { return 1; @@ -171,6 +166,14 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) { log_message(LOG_LEVEL_ERROR,"Non handled error from xrdp_mcs_send_cjcf") ; } + + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + g_writeln("xrdp_mcs_recv: libxrdp_force_read failed"); + return 1; + } + continue; } @@ -322,30 +325,29 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) int len; struct stream *s; - make_stream(s); - init_stream(s, 16 * 1024); + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_ber_parse_header(self, s, MCS_CONNECT_INITIAL, &len) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { - free_stream(s); return 1; } if ((len < 0) || !s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -353,13 +355,11 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { - free_stream(s); return 1; } if ((len < 0) || !s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -367,13 +367,11 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0) { - free_stream(s); return 1; } if ((len < 0) || !s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -381,38 +379,32 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (xrdp_mcs_parse_domain_params(self, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_parse_domain_params(self, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_parse_domain_params(self, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { - free_stream(s); return 1; } /* mcs data can not be zero length */ if ((len <= 0) || (len > 16 * 1024)) { - free_stream(s); return 1; } if (!s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -424,12 +416,10 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (s_check_end(s)) { - free_stream(s); return 0; } else { - free_stream(s); return 1; } } @@ -443,18 +433,20 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) struct stream *s; DEBUG((" in xrdp_mcs_recv_edrq")); - make_stream(s); - init_stream(s, 8192); + + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } - + if (!s_check_rem(s, 1)) { - free_stream(s); return 1; } @@ -462,13 +454,11 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) if ((opcode >> 2) != MCS_EDRQ) { - free_stream(s); return 1; } if (!s_check_rem(s, 4)) { - free_stream(s); return 1; } @@ -479,7 +469,6 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) { if (!s_check_rem(s, 2)) { - free_stream(s); return 1; } in_uint16_be(s, self->userid); @@ -487,11 +476,9 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) if (!(s_check_end(s))) { - free_stream(s); return 1; } - free_stream(s); DEBUG((" out xrdp_mcs_recv_edrq")); return 0; } @@ -505,18 +492,20 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) struct stream *s; DEBUG((" in xrdp_mcs_recv_aurq")); - make_stream(s); - init_stream(s, 8192); + + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } if (!s_check_rem(s, 1)) { - free_stream(s); return 1; } @@ -524,7 +513,6 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) if ((opcode >> 2) != MCS_AURQ) { - free_stream(s); return 1; } @@ -532,7 +520,6 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) { if (!s_check_rem(s, 2)) { - free_stream(s); return 1; } in_uint16_be(s, self->userid); @@ -540,11 +527,9 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) if (!(s_check_end(s))) { - free_stream(s); return 1; } - free_stream(s); DEBUG((" out xrdp_mcs_recv_aurq")); return 0; } @@ -592,18 +577,19 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) int opcode; struct stream *s; - make_stream(s); - init_stream(s, 8192); + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } if (!s_check_rem(s, 1)) { - free_stream(s); return 1; } @@ -611,13 +597,11 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) if ((opcode >> 2) != MCS_CJRQ) { - free_stream(s); return 1; } if (!s_check_rem(s, 4)) { - free_stream(s); return 1; } @@ -627,7 +611,6 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) { if (!s_check_rem(s, 2)) { - free_stream(s); return 1; } in_uint8s(s, 2); @@ -635,11 +618,9 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) if (!(s_check_end(s))) { - free_stream(s); return 1; } - free_stream(s); return 0; } @@ -725,7 +706,163 @@ xrdp_mcs_out_domain_params(struct xrdp_mcs *self, struct stream *s, xrdp_mcs_ber_out_int8(self, s, 2); return 0; } +/*****************************************************************************/ +/* prepare server gcc data to send in mcs response msg */ +int APP_CC +xrdp_mcs_out_gcc_data(struct xrdp_sec *self) +{ + struct stream *s; + int num_channels_even; + int num_channels; + int index; + int channel; + int gcc_size; + char* gcc_size_ptr; + char* ud_ptr; + + num_channels = self->mcs_layer->channel_list->count; + num_channels_even = num_channels + (num_channels & 1); + s = &(self->server_mcs_data); + init_stream(s, 8192); + out_uint16_be(s, 5); /* AsnBerObjectIdentifier */ + out_uint16_be(s, 0x14); + out_uint8(s, 0x7c); + out_uint16_be(s, 1); /* -- */ + out_uint8(s, 0x2a); /* ConnectPDULen */ + out_uint8(s, 0x14); + out_uint8(s, 0x76); + out_uint8(s, 0x0a); + out_uint8(s, 1); + out_uint8(s, 1); + out_uint8(s, 0); + out_uint16_le(s, 0xc001); + out_uint8(s, 0); + out_uint8(s, 0x4d); /* M */ + out_uint8(s, 0x63); /* c */ + out_uint8(s, 0x44); /* D */ + out_uint8(s, 0x6e); /* n */ + /* GCC Response Total Length - 2 bytes , set later */ + gcc_size_ptr = s->p; /* RDPGCCUserDataResponseLength */ + out_uint8s(s, 2); + ud_ptr = s->p; /* User Data */ + out_uint16_le(s, SEC_TAG_SRV_INFO); + if (self->mcs_layer->iso_layer->rdpNegData) + { + out_uint16_le(s, 12); /* len */ + } + else + { + out_uint16_le(s, 8); /* len */ + } + out_uint8(s, 4); /* 4 = rdp5 1 = rdp4 */ + out_uint8(s, 0); + out_uint8(s, 8); + out_uint8(s, 0); + if (self->mcs_layer->iso_layer->rdpNegData) + { + /* ReqeustedProtocol */ + out_uint32_le(s, self->mcs_layer->iso_layer->requestedProtocol); + } + out_uint16_le(s, SEC_TAG_SRV_CHANNELS); + out_uint16_le(s, 8 + (num_channels_even * 2)); /* len */ + out_uint16_le(s, MCS_GLOBAL_CHANNEL); /* 1003, 0x03eb main channel */ + out_uint16_le(s, num_channels); /* number of other channels */ + + for (index = 0; index < num_channels_even; index++) + { + if (index < num_channels) + { + channel = MCS_GLOBAL_CHANNEL + (index + 1); + out_uint16_le(s, channel); + } + else + { + out_uint16_le(s, 0); + } + } + + if (self->rsa_key_bytes == 64) + { + g_writeln("xrdp_sec_out_mcs_data: using 512 bit RSA key"); + out_uint16_le(s, SEC_TAG_SRV_CRYPT); + out_uint16_le(s, 0x00ec); /* len is 236 */ + out_uint32_le(s, self->crypt_method); + out_uint32_le(s, self->crypt_level); + out_uint32_le(s, 32); /* 32 bytes random len */ + out_uint32_le(s, 0xb8); /* 184 bytes rsa info(certificate) len */ + out_uint8a(s, self->server_random, 32); + /* here to end is certificate */ + /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */ + /* TermService\Parameters\Certificate */ + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint16_le(s, SEC_TAG_PUBKEY); /* 0x0006 */ + out_uint16_le(s, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */ + out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */ + out_uint32_le(s, 0x0048); /* 72 bytes modulus len */ + out_uint32_be(s, 0x00020000); /* bit len */ + out_uint32_be(s, 0x3f000000); /* data len */ + out_uint8a(s, self->pub_exp, 4); /* pub exp */ + out_uint8a(s, self->pub_mod, 64); /* pub mod */ + out_uint8s(s, 8); /* pad */ + out_uint16_le(s, SEC_TAG_KEYSIG); /* 0x0008 */ + out_uint16_le(s, 72); /* len */ + out_uint8a(s, self->pub_sig, 64); /* pub sig */ + out_uint8s(s, 8); /* pad */ + } + else if (self->rsa_key_bytes == 256) + { + g_writeln("xrdp_sec_out_mcs_data: using 2048 bit RSA key"); + out_uint16_le(s, SEC_TAG_SRV_CRYPT); + out_uint16_le(s, 0x01ac); /* len is 428 */ + out_uint32_le(s, self->crypt_method); + out_uint32_le(s, self->crypt_level); + out_uint32_le(s, 32); /* 32 bytes random len */ + out_uint32_le(s, 0x178); /* 376 bytes rsa info(certificate) len */ + out_uint8a(s, self->server_random, 32); + /* here to end is certificate */ + /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */ + /* TermService\Parameters\Certificate */ + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint16_le(s, SEC_TAG_PUBKEY); /* 0x0006 */ + out_uint16_le(s, 0x011c); /* 284 bytes length of SEC_TAG_PUBKEY */ + out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */ + out_uint32_le(s, 0x0108); /* 264 bytes modulus len */ + out_uint32_be(s, 0x00080000); /* bit len */ + out_uint32_be(s, 0xff000000); /* data len */ + out_uint8a(s, self->pub_exp, 4); /* pub exp */ + out_uint8a(s, self->pub_mod, 256); /* pub mod */ + out_uint8s(s, 8); /* pad */ + out_uint16_le(s, SEC_TAG_KEYSIG); /* 0x0008 */ + out_uint16_le(s, 72); /* len */ + out_uint8a(s, self->pub_sig, 64); /* pub sig */ + out_uint8s(s, 8); /* pad */ + } + else if (self->rsa_key_bytes == 0) /* no security */ + { + g_writeln("xrdp_sec_out_mcs_data: using no security"); + out_uint16_le(s, SEC_TAG_SRV_CRYPT); + out_uint16_le(s, 12); /* len is 12 */ + out_uint32_le(s, self->crypt_method); + out_uint32_le(s, self->crypt_level); + } + else + { + g_writeln("xrdp_sec_out_mcs_data: error"); + } + /* end certificate */ + s_mark_end(s); + + gcc_size = (int)(s->end - ud_ptr) | 0x8000; + gcc_size_ptr[0] = gcc_size >> 8; + gcc_size_ptr[1] = gcc_size; + + return 0; +} /*****************************************************************************/ /* returns error */ static int APP_CC @@ -737,9 +874,11 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self) DEBUG((" in xrdp_mcs_send_connect_response")); make_stream(s); init_stream(s, 8192); - data_len = self->server_mcs_data->end - self->server_mcs_data->data; + data_len = (int) (self->server_mcs_data->end - self->server_mcs_data->data); xrdp_iso_init(self->iso_layer, s); - xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, data_len + 38); + //TODO: we should calculate the whole length include MCS_CONNECT_RESPONSE + xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, + data_len > 0x80 ? data_len + 38 : data_len + 36); xrdp_mcs_ber_out_header(self, s, BER_TAG_RESULT, 1); out_uint8(s, 0); xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1); @@ -767,13 +906,9 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self) int APP_CC xrdp_mcs_incoming(struct xrdp_mcs *self) { + int i; DEBUG((" in xrdp_mcs_incoming")); - if (xrdp_iso_incoming(self->iso_layer) != 0) - { - return 1; - } - if (xrdp_mcs_recv_connect_initial(self) != 0) { return 1; @@ -785,8 +920,7 @@ xrdp_mcs_incoming(struct xrdp_mcs *self) return 1; } - /* in xrdp_sec.c */ - if (xrdp_sec_out_mcs_data(self->sec_layer) != 0) + if (xrdp_mcs_out_gcc_data(self->sec_layer) != 0) { return 1; } @@ -811,25 +945,18 @@ xrdp_mcs_incoming(struct xrdp_mcs *self) return 1; } - if (xrdp_mcs_recv_cjrq(self) != 0) - { - return 1; - } - - if (xrdp_mcs_send_cjcf(self, self->userid, - self->userid + MCS_USERCHANNEL_BASE) != 0) - { - return 1; - } - - if (xrdp_mcs_recv_cjrq(self) != 0) + for (i = 0; i < self->channel_list->count + 2; i++) { - return 1; - } + if (xrdp_mcs_recv_cjrq(self) != 0) + { + return 1; + } - if (xrdp_mcs_send_cjcf(self, self->userid, MCS_GLOBAL_CHANNEL) != 0) - { - return 1; + if (xrdp_mcs_send_cjcf(self, self->userid, + self->userid + MCS_USERCHANNEL_BASE + i) != 0) + { + return 1; + } } DEBUG((" out xrdp_mcs_incoming")); @@ -895,7 +1022,7 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan) if (len > 8192 * 2) { - g_writeln("error in xrdp_mcs_send, size too bog, its %d", len); + g_writeln("error in xrdp_mcs_send, size too big, its %d", len); } //if (len > max_len) @@ -958,6 +1085,7 @@ close_rdp_socket(struct xrdp_mcs *self) { if (self->iso_layer->trans != 0) { + trans_shutdown_tls_mode(self->iso_layer->trans); g_tcp_close(self->iso_layer->trans->sck); self->iso_layer->trans->sck = 0 ; g_writeln("xrdp_mcs_disconnect - socket closed"); diff --git a/libxrdp/xrdp_mppc_enc.c b/libxrdp/xrdp_mppc_enc.c index 15125d54..ff6caf4d 100644 --- a/libxrdp/xrdp_mppc_enc.c +++ b/libxrdp/xrdp_mppc_enc.c @@ -456,7 +456,7 @@ mppc_enc_new(int protocol_type) return 0; } - enc->first_pkt = 1; + enc->flagsHold = PACKET_AT_FRONT; enc->historyBuffer = (char *) g_malloc(enc->buf_len, 1); if (enc->historyBuffer == 0) @@ -574,20 +574,13 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) g_memset(outputBuffer, 0, len); enc->flags = PACKET_COMPR_TYPE_64K; - if (enc->first_pkt) - { - enc->first_pkt = 0; - enc->flagsHold |= PACKET_AT_FRONT; - } - - if ((enc->historyOffset + len) >= enc->buf_len) + if ((enc->historyOffset + len) >= enc->buf_len - 3) { /* historyBuffer cannot hold srcData - rewind it */ enc->historyOffset = 0; g_memset(hash_table, 0, enc->buf_len * 2); g_memset(enc->historyBuffer, 0, enc->buf_len); // added - enc->first_pkt = 0; - enc->flagsHold |= PACKET_AT_FRONT; + enc->flagsHold |= PACKET_AT_FRONT | PACKET_FLUSHED; } /* point to next free byte in historyBuffer */ @@ -602,7 +595,7 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) ctr = copy_offset = lom = 0; /* if we are at start of history buffer, do not attempt to compress */ - /* first 2 bytes,because minimum LoM is 3 */ + /* first 2 bytes, because minimum LoM is 3 */ if (historyOffset == 0) { /* encode first two bytes as literals */ @@ -970,40 +963,6 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) ctr++; } - /* if bits_left == 8, opb_index has already been incremented */ - if ((bits_left == 8) && (opb_index > len)) - { - /* compressed data longer than uncompressed data */ - /* give up */ - enc->historyOffset = 0; - g_memset(hash_table, 0, enc->buf_len * 2); - g_memset(enc->historyBuffer, 0, enc->buf_len); - enc->flagsHold |= PACKET_FLUSHED; - enc->first_pkt = 1; - - g_memcpy(enc->outputBuffer, srcData, len); - enc->bytes_in_opb = len; - enc->flags = 0x81; - - return 1; - } - else if (opb_index + 1 > len) - { - /* compressed data longer than uncompressed data */ - /* give up */ - enc->historyOffset = 0; - g_memset(hash_table, 0, enc->buf_len * 2); - g_memset(enc->historyBuffer, 0, enc->buf_len); - enc->flagsHold |= PACKET_FLUSHED; - enc->first_pkt = 1; - - g_memcpy(enc->outputBuffer, srcData, len); - enc->bytes_in_opb = len; - enc->flags = 0x81; - - return 1; - } - /* if bits_left != 8, increment opb_index, which is zero indexed */ if (bits_left != 8) { @@ -1012,24 +971,21 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) if (opb_index > len) { + /* compressed data longer than uncompressed data */ /* give up */ enc->historyOffset = 0; g_memset(hash_table, 0, enc->buf_len * 2); g_memset(enc->historyBuffer, 0, enc->buf_len); - enc->flagsHold |= PACKET_FLUSHED; - enc->first_pkt = 1; - - g_memcpy(enc->outputBuffer, srcData, len); - enc->bytes_in_opb = len; - enc->flags = 0x81; - - return 1; + enc->flagsHold |= PACKET_AT_FRONT | PACKET_FLUSHED; + return 0; } + enc->flags |= PACKET_COMPRESSED; enc->bytes_in_opb = opb_index; enc->flags |= enc->flagsHold; enc->flagsHold = 0; + DLOG(("\n")); //g_writeln("compression ratio: %f", (float) len / (float) enc->bytes_in_opb); diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 317e1135..7d969514 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -34,6 +34,8 @@ } \ } +#define MAX_ORDERS_SIZE (16 * 1024 - 256) + /*****************************************************************************/ struct xrdp_orders *APP_CC xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer) @@ -44,7 +46,7 @@ xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer) self->session = session; self->rdp_layer = rdp_layer; make_stream(self->out_s); - init_stream(self->out_s, 16384); + init_stream(self->out_s, 32 * 1024); self->orders_state.clip_right = 1; /* silly rdp right clip */ self->orders_state.clip_bottom = 1; /* silly rdp bottom clip */ self->jpeg_han = xrdp_jpeg_init(); @@ -53,6 +55,8 @@ xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer) { self->rfx_min_pixel = 64 * 32; } + make_stream(self->s); + make_stream(self->temp_s); return self; } @@ -64,9 +68,10 @@ xrdp_orders_delete(struct xrdp_orders *self) { return; } - xrdp_jpeg_deinit(self->jpeg_han); free_stream(self->out_s); + free_stream(self->s); + free_stream(self->temp_s); g_free(self->orders_state.text_data); g_free(self); } @@ -81,7 +86,6 @@ xrdp_orders_reset(struct xrdp_orders *self) { return 1; } - g_free(self->orders_state.text_data); g_memset(&(self->orders_state), 0, sizeof(self->orders_state)); self->order_count_ptr = 0; @@ -98,24 +102,33 @@ int APP_CC xrdp_orders_init(struct xrdp_orders *self) { self->order_level++; - if (self->order_level == 1) { self->order_count = 0; - - /* is this big enough */ - if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0) + if (self->rdp_layer->client_info.use_fast_path & 1) { - return 1; + LLOGLN(10, ("xrdp_orders_init: fastpath")); + if (xrdp_rdp_init_fastpath(self->rdp_layer, self->out_s) != 0) + { + return 1; + } + self->order_count_ptr = self->out_s->p; + out_uint8s(self->out_s, 2); /* number of orders, set later */ + } + else + { + LLOGLN(10, ("xrdp_orders_init: slowpath")); + if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0) + { + return 1; + } + out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); + out_uint8s(self->out_s, 2); /* pad */ + self->order_count_ptr = self->out_s->p; + out_uint8s(self->out_s, 2); /* number of orders, set later */ + out_uint8s(self->out_s, 2); /* pad */ } - - out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); - out_uint8s(self->out_s, 2); /* pad */ - self->order_count_ptr = self->out_s->p; - out_uint8s(self->out_s, 2); /* number of orders, set later */ - out_uint8s(self->out_s, 2); /* pad */ } - return 0; } @@ -127,11 +140,9 @@ xrdp_orders_send(struct xrdp_orders *self) int rv; rv = 0; - if (self->order_level > 0) { self->order_level--; - if ((self->order_level == 0) && (self->order_count > 0)) { s_mark_end(self->out_s); @@ -139,15 +150,24 @@ xrdp_orders_send(struct xrdp_orders *self) self->order_count_ptr[0] = self->order_count; self->order_count_ptr[1] = self->order_count >> 8; self->order_count = 0; - - if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, - RDP_DATA_PDU_UPDATE) != 0) + if (self->rdp_layer->client_info.use_fast_path & 1) + { + if (xrdp_rdp_send_fastpath(self->rdp_layer, + self->out_s, 0) != 0) + { + rv = 1; + } + } + else { - rv = 1; + if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, + RDP_DATA_PDU_UPDATE) != 0) + { + rv = 1; + } } } } - return rv; } @@ -160,21 +180,29 @@ xrdp_orders_force_send(struct xrdp_orders *self) { return 1; } - if ((self->order_level > 0) && (self->order_count > 0)) { s_mark_end(self->out_s); DEBUG(("xrdp_orders_force_send sending %d orders", self->order_count)); self->order_count_ptr[0] = self->order_count; self->order_count_ptr[1] = self->order_count >> 8; - - if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, - RDP_DATA_PDU_UPDATE) != 0) + if (self->rdp_layer->client_info.use_fast_path & 1) { - return 1; + if (xrdp_rdp_send_fastpath(self->rdp_layer, + self->out_s, FASTPATH_UPDATETYPE_ORDERS) != 0) + { + return 1; + } + } + else + { + if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, + RDP_DATA_PDU_UPDATE) != 0) + { + return 1; + } } } - self->order_count = 0; self->order_level = 0; return 0; @@ -190,14 +218,7 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size) int size; int max_packet_size; - if (self->rdp_layer->client_info.bpp == 8) - { - max_packet_size = 8000; - } - else - { - max_packet_size = 16000; - } + max_packet_size = MAX_ORDERS_SIZE; if (self->order_level < 1) { @@ -1632,7 +1653,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, int present; char* present_ptr; char* order_flags_ptr; - + if (xrdp_orders_check(self, 80) != 0) { return 1; @@ -1653,9 +1674,9 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, order_flags |= RDP_ORDER_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - + order_flags |= RDP_ORDER_LASTBOUNDS; - + } } } @@ -1699,21 +1720,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, { xrdp_orders_out_bounds(self, rect); } - + if (srcidx != self->orders_state.com_blt_srcidx) { present |= 0x000001; out_uint16_le(self->out_s, srcidx); self->orders_state.com_blt_srcidx = srcidx; } - + if (srcformat != self->orders_state.com_blt_srcformat) { present |= 0x000002; out_uint32_le(self->out_s, srcformat); self->orders_state.com_blt_srcformat = srcformat; } - + if (srcwidth != self->orders_state.com_blt_srcwidth) { present |= 0x000004; @@ -1727,14 +1748,14 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_srcwidth = srcwidth; } - + if (srcrepeat != self->orders_state.com_blt_srcrepeat) { present |= 0x000008; out_uint8(self->out_s, srcrepeat); self->orders_state.com_blt_srcrepeat = srcrepeat; } - + if (srctransform != 0) { if (srctransform[0] != self->orders_state.com_blt_srctransform[0]) @@ -1768,21 +1789,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, self->orders_state.com_blt_srctransform[0] = 0; } } - + if (mskflags != self->orders_state.com_blt_mskflags) { present |= 0x000040; out_uint8(self->out_s, mskflags); self->orders_state.com_blt_mskflags = mskflags; } - + if (mskidx != self->orders_state.com_blt_mskidx) { present |= 0x000080; out_uint16_le(self->out_s, mskidx); self->orders_state.com_blt_mskidx = mskidx; } - + if (mskformat != self->orders_state.com_blt_mskformat) { present |= 0x000100; @@ -1803,21 +1824,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_mskwidth = mskwidth; } - + if (mskrepeat != self->orders_state.com_blt_mskrepeat) { present |= 0x000400; out_uint8(self->out_s, mskrepeat); self->orders_state.com_blt_mskrepeat = mskrepeat; } - + if (op != self->orders_state.com_blt_op) { present |= 0x000800; out_uint8(self->out_s, op); self->orders_state.com_blt_op = op; } - + if (srcx != self->orders_state.com_blt_srcx) { present |= 0x001000; @@ -1831,7 +1852,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_srcx = srcx; } - + if (srcy != self->orders_state.com_blt_srcy) { present |= 0x002000; @@ -1845,7 +1866,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_srcy = srcy; } - + if (mskx != self->orders_state.com_blt_mskx) { present |= 0x004000; @@ -1859,7 +1880,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_mskx = mskx; } - + if (msky != self->orders_state.com_blt_msky) { present |= 0x008000; @@ -1873,7 +1894,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_msky = msky; } - + if (dstx != self->orders_state.com_blt_dstx) { present |= 0x010000; @@ -1887,7 +1908,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_dstx = dstx; } - + if (dsty != self->orders_state.com_blt_dsty) { present |= 0x020000; @@ -1901,7 +1922,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_dsty = dsty; } - + if (width != self->orders_state.com_blt_width) { present |= 0x040000; @@ -1915,7 +1936,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_width = width; } - + if (height != self->orders_state.com_blt_height) { present |= 0x080000; @@ -1936,11 +1957,11 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, out_uint32_le(self->out_s, dstformat); self->orders_state.com_blt_dstformat = dstformat; } - + xrdp_order_pack_small_or_tiny(self, order_flags_ptr, order_flags, - + present_ptr, present, 3); - + return 0; } @@ -2304,19 +2325,26 @@ xrdp_orders_send_bitmap(struct xrdp_orders *self, e = 4 - e; } - make_stream(s); - init_stream(s, 16384); - make_stream(temp_s); - init_stream(temp_s, 16384); + s = self->s; + init_stream(s, 16384 * 2); + temp_s = self->temp_s; + init_stream(temp_s, 16384 * 2); p = s->p; i = height; - lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, - i - 1, temp_s, e); + if (bpp > 24) + { + lines_sending = xrdp_bitmap32_compress(data, width, height, s, + bpp, 16384, + i - 1, temp_s, e, 0x10); + } + else + { + lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, + i - 1, temp_s, e); + } if (lines_sending != height) { - free_stream(s); - free_stream(temp_s); g_writeln("error in xrdp_orders_send_bitmap, lines_sending(%d) != \ height(%d)", lines_sending, height); return 1; @@ -2364,8 +2392,6 @@ height(%d)", lines_sending, height); } out_uint8a(self->out_s, s->data, bufsize); - free_stream(s); - free_stream(temp_s); return 0; } @@ -2564,16 +2590,17 @@ xrdp_orders_send_bitmap2(struct xrdp_orders *self, e = 4 - e; } - make_stream(s); - init_stream(s, 16384); - make_stream(temp_s); - init_stream(temp_s, 16384); + s = self->s; + init_stream(s, 16384 * 2); + temp_s = self->temp_s; + init_stream(temp_s, 16384 * 2); p = s->p; i = height; if (bpp > 24) { - lines_sending = xrdp_bitmap32_compress(data, width, height, s, bpp, 16384, - i - 1, temp_s, e); + lines_sending = xrdp_bitmap32_compress(data, width, height, s, + bpp, 16384, + i - 1, temp_s, e, 0x10); } else { @@ -2583,8 +2610,6 @@ xrdp_orders_send_bitmap2(struct xrdp_orders *self, if (lines_sending != height) { - free_stream(s); - free_stream(temp_s); g_writeln("error in xrdp_orders_send_bitmap2, lines_sending(%d) != \ height(%d)", lines_sending, height); return 1; @@ -2613,8 +2638,6 @@ height(%d)", lines_sending, height); i = cache_idx & 0xff; out_uint8(self->out_s, i); out_uint8a(self->out_s, s->data, bufsize); - free_stream(s); - free_stream(temp_s); return 0; } diff --git a/libxrdp/xrdp_orders_rail.h b/libxrdp/xrdp_orders_rail.h index 8f5b402f..475b8f17 100644 --- a/libxrdp/xrdp_orders_rail.h +++ b/libxrdp/xrdp_orders_rail.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2012 + * Copyright (C) Jay Sorg 2012-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,31 +20,31 @@ #define _XRDP_ORDERS_RAIL_H int APP_CC -xrdp_orders_send_window_delete(struct xrdp_orders* self, int window_id); +xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id); int APP_CC -xrdp_orders_send_window_cached_icon(struct xrdp_orders* self, +xrdp_orders_send_window_cached_icon(struct xrdp_orders *self, int window_id, int cache_entry, int cache_id, int flags); int APP_CC -xrdp_orders_send_window_icon(struct xrdp_orders* self, +xrdp_orders_send_window_icon(struct xrdp_orders *self, int window_id, int cache_entry, int cache_id, - struct rail_icon_info* icon_info, + struct rail_icon_info *icon_info, int flags); int APP_CC -xrdp_orders_send_window_new_update(struct xrdp_orders* self, int window_id, - struct rail_window_state_order* window_state, +xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, + struct rail_window_state_order *window_state, int flags); int APP_CC -xrdp_orders_send_notify_delete(struct xrdp_orders* self, int window_id, +xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id, int notify_id); int APP_CC -xrdp_orders_send_notify_new_update(struct xrdp_orders* self, +xrdp_orders_send_notify_new_update(struct xrdp_orders *self, int window_id, int notify_id, - struct rail_notify_state_order* notify_state, + struct rail_notify_state_order *notify_state, int flags); int APP_CC -xrdp_orders_send_monitored_desktop(struct xrdp_orders* self, - struct rail_monitored_desktop_order* mdo, +xrdp_orders_send_monitored_desktop(struct xrdp_orders *self, + struct rail_monitored_desktop_order *mdo, int flags); #endif diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index ec882f4e..4fc83ae8 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -26,6 +26,14 @@ #include <freerdp/constants.h> #endif +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) + +#define FASTPATH_FRAG_SIZE (16 * 1024 - 128) + /*****************************************************************************/ static int APP_CC xrdp_rdp_read_config(struct xrdp_client_info *client_info) @@ -68,7 +76,11 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) } else if (g_strcasecmp(item, "crypt_level") == 0) { - if (g_strcasecmp(value, "low") == 0) + if (g_strcasecmp(value, "none") == 0) + { + client_info->crypt_level = 0; + } + else if (g_strcasecmp(value, "low") == 0) { client_info->crypt_level = 1; } @@ -123,6 +135,85 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) { client_info->require_credentials = g_text2bool(value); } + else if (g_strcasecmp(item, "use_fastpath") == 0) + { + if (g_strcasecmp(value, "output") == 0) + { + client_info->use_fast_path = 1; + } + else if (g_strcasecmp(value, "input") == 0) + { + client_info->use_fast_path = 2; + } + else if (g_strcasecmp(value, "both") == 0) + { + client_info->use_fast_path = 3; + } + else if (g_strcasecmp(value, "none") == 0) + { + client_info->use_fast_path = 0; + } + else + { + log_message(LOG_LEVEL_ALWAYS,"Warning: Your configured fastpath level is" + "undefined, fastpath will not be used"); + client_info->use_fast_path = 0; + } + } + else if (g_strcasecmp(item, "security_layer") == 0) + { + if (g_strcasecmp(value, "rdp") == 0) + { + client_info->security_layer = PROTOCOL_RDP; + } + else if (g_strcasecmp(value, "tls") == 0) + { + client_info->security_layer = PROTOCOL_SSL; + } + else if (g_strcasecmp(value, "hybrid") == 0) + { + client_info->security_layer = PROTOCOL_SSL | PROTOCOL_HYBRID; + } + else + { + log_message(LOG_LEVEL_ALWAYS,"Warning: Your configured security layer is" + "undefined, xrdp will negotiate client compatible"); + client_info->security_layer = PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_HYBRID_EX; + } + } + else if (g_strcasecmp(item, "certificate") == 0) + { + g_memset(client_info->certificate, 0, sizeof(char) * 1024); + if (value[0] != '/') + { + /* default certificate path */ + g_snprintf(client_info->certificate, 1023, "%s/cert.pem", XRDP_CFG_PATH); + log_message(LOG_LEVEL_ALWAYS,"WARNING: Invalid x.509 certificate path defined, " + "default path will be used: %s", client_info->certificate); + } + else + { + /* use user defined certificate */ + g_strncpy(client_info->certificate, value, 1023); + } + } + else if (g_strcasecmp(item, "key_file") == 0) + { + g_memset(client_info->key_file, 0, sizeof(char) * 1024); + if (value[0] != '/') + { + /* default key_file path */ + g_snprintf(client_info->key_file, 1023, "%s/key.pem", XRDP_CFG_PATH); + log_message(LOG_LEVEL_ALWAYS,"WARNING: Invalid x.509 certificate path defined, " + "default path will be used: %s", client_info->key_file); + } + else + { + /* use user defined key_file */ + g_strncpy(client_info->key_file, value, 1023); + } + } + } list_delete(items); @@ -198,10 +289,7 @@ xrdp_rdp_create(struct xrdp_session *session, struct trans *trans) /* read ini settings */ xrdp_rdp_read_config(&self->client_info); /* create sec layer */ - self->sec_layer = xrdp_sec_create(self, trans, - self->client_info.crypt_level, - self->client_info.channel_code, - self->client_info.multimon); + self->sec_layer = xrdp_sec_create(self, trans); /* default 8 bit v1 color bitmap cache entries and size */ self->client_info.cache1_entries = 600; self->client_info.cache1_size = 256; @@ -266,7 +354,7 @@ xrdp_rdp_init_data(struct xrdp_rdp *self, struct stream *s) } /*****************************************************************************/ -/* returns erros */ +/* returns error */ int APP_CC xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) { @@ -274,11 +362,26 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) int len = 0; int pdu_code = 0; int chan = 0; + const tui8 *header; DEBUG(("in xrdp_rdp_recv")); - if (s->next_packet == 0 || s->next_packet >= s->end) { + /* check for fastpath first */ + header = (const tui8 *) (s->p); + if ((header[0] != 0x3) && (header[0] != 0x3c)) + { + if (xrdp_sec_recv_fastpath(self->sec_layer, s) != 0) + { + return 1; + } + /* next_packet gets set in xrdp_sec_recv_fastpath */ + *code = 2; // special code for fastpath input + DEBUG(("out (fastpath) xrdp_rdp_recv")); + return 0; + } + + /* not fastpath, do tpkt */ chan = 0; error = xrdp_sec_recv(self->sec_layer, s, &chan); @@ -293,6 +396,7 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) if (error != 0) { DEBUG(("out xrdp_rdp_recv error")); + g_writeln("xrdp_rdp_recv: xrdp_sec_recv failed"); return 1; } @@ -433,7 +537,9 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, } else { - g_writeln("mppc_encode not ok: type %d flags %d", mppc_enc->protocol_type, mppc_enc->flags); + LLOGLN(10, ("xrdp_rdp_send_data: mppc_encode not ok " + "type %d flags %d", mppc_enc->protocol_type, + mppc_enc->flags)); } } @@ -459,841 +565,241 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, } /*****************************************************************************/ +/* returns the fastpath rdp byte count */ int APP_CC -xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) +xrdp_rdp_get_fastpath_bytes(struct xrdp_rdp *self) { - struct stream *s = (struct stream *)NULL; - - make_stream(s); - init_stream(s, 8192); - DEBUG(("in xrdp_rdp_send_data_update_sync")); - - if (xrdp_rdp_init_data(self, s) != 0) + if (self->client_info.rdp_compression) { - DEBUG(("out xrdp_rdp_send_data_update_sync error")); - free_stream(s); - return 1; + return 4; } - - out_uint16_le(s, RDP_UPDATE_SYNCHRONIZE); - out_uint8s(s, 2); - s_mark_end(s); - - if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_UPDATE) != 0) - { - DEBUG(("out xrdp_rdp_send_data_update_sync error")); - free_stream(s); - return 1; - } - - DEBUG(("out xrdp_rdp_send_data_update_sync")); - free_stream(s); - return 0; + return 3; } /*****************************************************************************/ int APP_CC -xrdp_rdp_incoming(struct xrdp_rdp *self) +xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s) { - DEBUG(("in xrdp_rdp_incoming")); - - if (xrdp_sec_incoming(self->sec_layer) != 0) + if (xrdp_sec_init_fastpath(self->sec_layer, s) != 0) { return 1; } - self->mcs_channel = self->sec_layer->mcs_layer->userid + - MCS_USERCHANNEL_BASE; - DEBUG(("out xrdp_rdp_incoming mcs channel %d", self->mcs_channel)); - g_strncpy(self->client_info.client_addr, - self->sec_layer->mcs_layer->iso_layer->trans->addr, - sizeof(self->client_info.client_addr) - 1); - g_strncpy(self->client_info.client_port, - self->sec_layer->mcs_layer->iso_layer->trans->port, - sizeof(self->client_info.client_port) - 1); - return 0; -} - -/*****************************************************************************/ -int APP_CC -xrdp_rdp_send_demand_active(struct xrdp_rdp *self) -{ - struct stream *s; - int caps_count; - int caps_size; - int codec_caps_count; - int codec_caps_size; - int flags; - char *caps_count_ptr; - char *caps_size_ptr; - char *caps_ptr; - char *codec_caps_count_ptr; - char *codec_caps_size_ptr; - - make_stream(s); - init_stream(s, 8192); - - if (xrdp_rdp_init(self, s) != 0) - { - free_stream(s); - return 1; - } - - caps_count = 0; - out_uint32_le(s, self->share_id); - out_uint16_le(s, 4); /* 4 chars for RDP\0 */ - /* 2 bytes size after num caps, set later */ - caps_size_ptr = s->p; - out_uint8s(s, 2); - out_uint8a(s, "RDP", 4); - /* 4 byte num caps, set later */ - caps_count_ptr = s->p; - out_uint8s(s, 4); - caps_ptr = s->p; - - /* Output share capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_SHARE); - out_uint16_le(s, RDP_CAPLEN_SHARE); - out_uint16_le(s, self->mcs_channel); - out_uint16_be(s, 0xb5e2); /* 0x73e1 */ - - /* Output general capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */ - out_uint16_le(s, RDP_CAPLEN_GENERAL); /* 24(0x18) */ - 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_le(s, 0); /* pad */ - out_uint16_le(s, 0); /* Compression types */ - /* NO_BITMAP_COMPRESSION_HDR 0x0400 - FASTPATH_OUTPUT_SUPPORTED 0x0001 */ - if (self->client_info.use_fast_path & 1) + if (self->client_info.rdp_compression) { - out_uint16_le(s, 0x401); + s_push_layer(s, rdp_hdr, 4); } else { - out_uint16_le(s, 0x400); + s_push_layer(s, rdp_hdr, 3); } - out_uint16_le(s, 0); /* Update capability */ - out_uint16_le(s, 0); /* Remote unshare capability */ - out_uint16_le(s, 0); /* Compression level */ - out_uint16_le(s, 0); /* Pad */ - - /* Output bitmap capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_BITMAP); /* 2 */ - out_uint16_le(s, RDP_CAPLEN_BITMAP); /* 28(0x1c) */ - out_uint16_le(s, self->client_info.bpp); /* Preferred BPP */ - 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, self->client_info.width); /* width */ - out_uint16_le(s, self->client_info.height); /* height */ - out_uint16_le(s, 0); /* Pad */ - out_uint16_le(s, 1); /* Allow resize */ - out_uint16_le(s, 1); /* bitmap compression */ - out_uint16_le(s, 0); /* unknown */ - out_uint16_le(s, 0); /* unknown */ - out_uint16_le(s, 0); /* pad */ - - /* Output font capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_FONT); /* 14 */ - out_uint16_le(s, RDP_CAPLEN_FONT); /* 4 */ - - /* Output order capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_ORDER); /* 3 */ - out_uint16_le(s, RDP_CAPLEN_ORDER); /* 88(0x58) */ - out_uint8s(s, 16); - out_uint32_be(s, 0x40420f00); - out_uint16_le(s, 1); /* Cache X granularity */ - out_uint16_le(s, 20); /* Cache Y granularity */ - out_uint16_le(s, 0); /* Pad */ - out_uint16_le(s, 1); /* Max order level */ - out_uint16_le(s, 0x2f); /* Number of fonts */ - out_uint16_le(s, 0x22); /* Capability flags */ - /* caps */ - out_uint8(s, 1); /* NEG_DSTBLT_INDEX 0x00 0 */ - out_uint8(s, 1); /* NEG_PATBLT_INDEX 0x01 1 */ - out_uint8(s, 1); /* NEG_SCRBLT_INDEX 0x02 2 */ - out_uint8(s, 1); /* NEG_MEMBLT_INDEX 0x03 3 */ - out_uint8(s, 0); /* NEG_MEM3BLT_INDEX 0x04 4 */ - out_uint8(s, 0); /* NEG_ATEXTOUT_INDEX 0x05 5 */ - out_uint8(s, 0); /* NEG_AEXTTEXTOUT_INDEX 0x06 6 */ - out_uint8(s, 0); /* NEG_DRAWNINEGRID_INDEX 0x07 7 */ - out_uint8(s, 1); /* NEG_LINETO_INDEX 0x08 8 */ - out_uint8(s, 0); /* NEG_MULTI_DRAWNINEGRID_INDEX 0x09 9 */ - out_uint8(s, 1); /* NEG_OPAQUE_RECT_INDEX 0x0A 10 */ - out_uint8(s, 0); /* NEG_SAVEBITMAP_INDEX 0x0B 11 */ - out_uint8(s, 0); /* NEG_WTEXTOUT_INDEX 0x0C 12 */ - out_uint8(s, 0); /* NEG_MEMBLT_V2_INDEX 0x0D 13 */ - out_uint8(s, 0); /* NEG_MEM3BLT_V2_INDEX 0x0E 14 */ - out_uint8(s, 0); /* NEG_MULTIDSTBLT_INDEX 0x0F 15 */ - out_uint8(s, 0); /* NEG_MULTIPATBLT_INDEX 0x10 16 */ - out_uint8(s, 0); /* NEG_MULTISCRBLT_INDEX 0x11 17 */ - out_uint8(s, 1); /* NEG_MULTIOPAQUERECT_INDEX 0x12 18 */ - out_uint8(s, 0); /* NEG_FAST_INDEX_INDEX 0x13 19 */ - out_uint8(s, 0); /* NEG_POLYGON_SC_INDEX 0x14 20 */ - out_uint8(s, 0); /* NEG_POLYGON_CB_INDEX 0x15 21 */ - out_uint8(s, 0); /* NEG_POLYLINE_INDEX 0x16 22 */ - out_uint8(s, 0); /* unused 0x17 23 */ - out_uint8(s, 0); /* NEG_FAST_GLYPH_INDEX 0x18 24 */ - out_uint8(s, 0); /* NEG_ELLIPSE_SC_INDEX 0x19 25 */ - out_uint8(s, 0); /* NEG_ELLIPSE_CB_INDEX 0x1A 26 */ - out_uint8(s, 1); /* NEG_GLYPH_INDEX_INDEX 0x1B 27 */ - out_uint8(s, 0); /* NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C 28 */ - out_uint8(s, 0); /* NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D 29 */ - out_uint8(s, 0); /* NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E 30 */ - out_uint8(s, 0); /* unused 0x1F 31 */ - out_uint16_le(s, 0x6a1); - /* declare support of bitmap cache rev3 */ - out_uint16_le(s, XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT); - out_uint32_le(s, 0x0f4240); /* desk save */ - out_uint32_le(s, 0x0f4240); /* desk save */ - out_uint32_le(s, 1); /* ? */ - out_uint32_le(s, 0); /* ? */ - - /* Output bmpcodecs capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_BMPCODECS); - codec_caps_size_ptr = s->p; - out_uint8s(s, 2); /* cap len set later */ - codec_caps_count = 0; - codec_caps_count_ptr = s->p; - out_uint8s(s, 1); /* bitmapCodecCount set later */ - /* nscodec */ - codec_caps_count++; - out_uint8a(s, XR_CODEC_GUID_NSCODEC, 16); - out_uint8(s, 1); /* codec id, must be 1 */ - out_uint16_le(s, 3); - out_uint8(s, 0x01); /* fAllowDynamicFidelity */ - out_uint8(s, 0x01); /* fAllowSubsampling */ - out_uint8(s, 0x03); /* colorLossLevel */ - /* remotefx */ - codec_caps_count++; - out_uint8a(s, XR_CODEC_GUID_REMOTEFX, 16); - out_uint8(s, 0); /* codec id, client sets */ - out_uint16_le(s, 256); - out_uint8s(s, 256); - /* jpeg */ - codec_caps_count++; - out_uint8a(s, XR_CODEC_GUID_JPEG, 16); - out_uint8(s, 0); /* codec id, client sets */ - out_uint16_le(s, 1); /* ext length */ - out_uint8(s, 75); - /* calculate and set size and count */ - codec_caps_size = (int)(s->p - codec_caps_size_ptr); - codec_caps_size += 2; /* 2 bytes for RDP_CAPSET_BMPCODECS above */ - codec_caps_size_ptr[0] = codec_caps_size; - codec_caps_size_ptr[1] = codec_caps_size >> 8; - codec_caps_count_ptr[0] = codec_caps_count; - - /* Output color cache capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_COLCACHE); - out_uint16_le(s, RDP_CAPLEN_COLCACHE); - out_uint16_le(s, 6); /* cache size */ - out_uint16_le(s, 0); /* pad */ - - /* Output pointer capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_POINTER); - out_uint16_le(s, RDP_CAPLEN_POINTER); - out_uint16_le(s, 1); /* Colour pointer */ - out_uint16_le(s, 0x19); /* Cache size */ - out_uint16_le(s, 0x19); /* Cache size */ - - /* Output input capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_INPUT); /* 13(0xd) */ - out_uint16_le(s, RDP_CAPLEN_INPUT); /* 88(0x58) */ - - /* INPUT_FLAG_SCANCODES 0x0001 - INPUT_FLAG_MOUSEX 0x0004 - INPUT_FLAG_FASTPATH_INPUT 0x0008 - INPUT_FLAG_FASTPATH_INPUT2 0x0020 */ - flags = 0x0001 | 0x0004; - if (self->client_info.use_fast_path & 2) - flags |= 0x0008 | 0x0020; - out_uint16_le(s, flags); - out_uint8s(s, 82); - - /* Remote Programs Capability Set */ - caps_count++; - out_uint16_le(s, 0x0017); /* CAPSETTYPE_RAIL */ - out_uint16_le(s, 8); - out_uint32_le(s, 3); /* TS_RAIL_LEVEL_SUPPORTED - TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */ - - /* Window List Capability Set */ - caps_count++; - out_uint16_le(s, 0x0018); /* CAPSETTYPE_WINDOW */ - out_uint16_le(s, 11); - out_uint32_le(s, 2); /* TS_WINDOW_LEVEL_SUPPORTED_EX */ - out_uint8(s, 3); /* NumIconCaches */ - out_uint16_le(s, 12); /* NumIconCacheEntries */ - - /* 6 - bitmap cache v3 codecid */ - caps_count++; - out_uint16_le(s, 0x0006); - out_uint16_le(s, 5); - out_uint8(s, 0); /* client sets */ - - out_uint8s(s, 4); /* pad */ - - s_mark_end(s); - - caps_size = (int)(s->end - caps_ptr); - caps_size_ptr[0] = caps_size; - caps_size_ptr[1] = caps_size >> 8; - - caps_count_ptr[0] = caps_count; - caps_count_ptr[1] = caps_count >> 8; - caps_count_ptr[2] = caps_count >> 16; - caps_count_ptr[3] = caps_count >> 24; - - if (xrdp_rdp_send(self, s, RDP_PDU_DEMAND_ACTIVE) != 0) - { - free_stream(s); - return 1; - } - - free_stream(s); return 0; } /*****************************************************************************/ -static int APP_CC -xrdp_process_capset_general(struct xrdp_rdp *self, struct stream *s, - int len) +/* returns error */ +/* 2.2.9.1.2.1 Fast-Path Update (TS_FP_UPDATE) + * http://msdn.microsoft.com/en-us/library/cc240622.aspx */ +int APP_CC +xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, + int data_pdu_type) { - int i; + int updateHeader; + int updateCode; + int fragmentation; + int compression; + int comp_type; + int comp_len; + int no_comp_len; + int send_len; + int cont; + int header_bytes; + int sec_bytes; + int to_comp_len; + int sec_offset; + int rdp_offset; + struct stream frag_s; + struct stream comp_s; + struct stream send_s; + struct xrdp_mppc_enc *mppc_enc; - if (len < 10 + 2) + LLOGLN(10, ("xrdp_rdp_send_fastpath:")); + s_pop_layer(s, rdp_hdr); + updateCode = data_pdu_type; + if (self->client_info.rdp_compression) { - g_writeln("xrdp_process_capset_general: error"); - return 1; + compression = 2; + header_bytes = 4; } - in_uint8s(s, 10); - in_uint16_le(s, i); - /* use_compact_packets is pretty much 'use rdp5' */ - self->client_info.use_compact_packets = (i != 0); - /* op2 is a boolean to use compact bitmap headers in bitmap cache */ - /* set it to same as 'use rdp5' boolean */ - self->client_info.op2 = self->client_info.use_compact_packets; - return 0; -} - -/*****************************************************************************/ -static int APP_CC -xrdp_process_capset_order(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int i; - char order_caps[32]; - int ex_flags; - int cap_flags; - - DEBUG(("order capabilities")); - if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4) + else { - g_writeln("xrdp_process_capset_order: error"); - return 1; + compression = 0; + header_bytes = 3; } - in_uint8s(s, 20); /* Terminal desc, pad */ - in_uint8s(s, 2); /* Cache X granularity */ - in_uint8s(s, 2); /* Cache Y granularity */ - in_uint8s(s, 2); /* Pad */ - in_uint8s(s, 2); /* Max order level */ - in_uint8s(s, 2); /* Number of fonts */ - in_uint16_le(s, cap_flags); /* Capability flags */ - in_uint8a(s, order_caps, 32); /* Orders supported */ - g_memcpy(self->client_info.orders, order_caps, 32); - DEBUG(("dest blt-0 %d", order_caps[0])); - DEBUG(("pat blt-1 %d", order_caps[1])); - DEBUG(("screen blt-2 %d", order_caps[2])); - DEBUG(("memblt-3-13 %d %d", order_caps[3], order_caps[13])); - DEBUG(("triblt-4-14 %d %d", order_caps[4], order_caps[14])); - DEBUG(("line-8 %d", order_caps[8])); - DEBUG(("line-9 %d", order_caps[9])); - DEBUG(("rect-10 %d", order_caps[10])); - DEBUG(("desksave-11 %d", order_caps[11])); - DEBUG(("polygon-20 %d", order_caps[20])); - DEBUG(("polygon2-21 %d", order_caps[21])); - DEBUG(("polyline-22 %d", order_caps[22])); - DEBUG(("ellipse-25 %d", order_caps[25])); - DEBUG(("ellipse2-26 %d", order_caps[26])); - DEBUG(("text2-27 %d", order_caps[27])); - DEBUG(("order_caps dump")); -#if defined(XRDP_DEBUG) - g_hexdump(order_caps, 32); -#endif - in_uint8s(s, 2); /* Text capability flags */ - /* read extended order support flags */ - in_uint16_le(s, ex_flags); /* Ex flags */ - - if (cap_flags & 0x80) /* ORDER_FLAGS_EXTRA_SUPPORT */ + sec_bytes = xrdp_sec_get_fastpath_bytes(self->sec_layer); + fragmentation = 0; + frag_s = *s; + sec_offset = (int)(frag_s.sec_hdr - frag_s.data); + rdp_offset = (int)(frag_s.rdp_hdr - frag_s.data); + cont = 1; + while (cont) { - self->client_info.order_flags_ex = ex_flags; - if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT) + comp_type = 0; + send_s = frag_s; + no_comp_len = (int)(frag_s.end - frag_s.p); + if (no_comp_len > FASTPATH_FRAG_SIZE) { - g_writeln("xrdp_process_capset_order: bitmap cache v3 supported"); - self->client_info.bitmap_cache_version |= 4; + no_comp_len = FASTPATH_FRAG_SIZE; + if (fragmentation == 0) + { + fragmentation = 2; /* FASTPATH_FRAGMENT_FIRST */ + } + else if (fragmentation == 2) + { + fragmentation = 3; /* FASTPATH_FRAGMENT_NEXT */ + } } + else + { + if (fragmentation != 0) + { + fragmentation = 1; /* FASTPATH_FRAGMENT_LAST */ + } + } + send_len = no_comp_len; + LLOGLN(10, ("xrdp_rdp_send_fastpath: no_comp_len %d fragmentation %d", + no_comp_len, fragmentation)); + if ((compression != 0) && (no_comp_len > header_bytes + 16)) + { + to_comp_len = no_comp_len - header_bytes; + mppc_enc = self->mppc_enc; + if (compress_rdp(mppc_enc, (tui8 *)(frag_s.p + header_bytes), + to_comp_len)) + { + comp_len = mppc_enc->bytes_in_opb + header_bytes; + LLOGLN(10, ("xrdp_rdp_send_fastpath: no_comp_len %d " + "comp_len %d", no_comp_len, comp_len)); + send_len = comp_len; + comp_type = mppc_enc->flags; + /* outputBuffer has 64 bytes preceding it */ + g_memset(&comp_s, 0, sizeof(comp_s)); + comp_s.data = mppc_enc->outputBuffer - + (rdp_offset + header_bytes); + comp_s.p = comp_s.data + rdp_offset; + comp_s.end = comp_s.p + send_len; + comp_s.size = send_len; + comp_s.sec_hdr = comp_s.data + sec_offset; + comp_s.rdp_hdr = comp_s.data + rdp_offset; + send_s = comp_s; + } + else + { + LLOGLN(10, ("xrdp_rdp_send_fastpath: mppc_encode not ok " + "type %d flags %d", mppc_enc->protocol_type, + mppc_enc->flags)); + } + } + updateHeader = (updateCode & 15) | + ((fragmentation & 3) << 4) | + ((compression & 3) << 6); + out_uint8(&send_s, updateHeader); + if (compression != 0) + { + out_uint8(&send_s, comp_type); + } + send_len -= header_bytes; + out_uint16_le(&send_s, send_len); + send_s.end = send_s.p + send_len; + if (xrdp_sec_send_fastpath(self->sec_layer, &send_s) != 0) + { + LLOGLN(0, ("xrdp_rdp_send_fastpath: xrdp_fastpath_send failed")); + return 1; + } + frag_s.p += no_comp_len; + cont = frag_s.p < frag_s.end; + frag_s.p -= header_bytes; + frag_s.sec_hdr = frag_s.p - sec_bytes; + frag_s.data = frag_s.sec_hdr; } - in_uint8s(s, 4); /* Pad */ - - in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */ - self->client_info.desktop_cache = i; - DEBUG(("desktop cache size %d", i)); - in_uint8s(s, 4); /* Unknown */ - in_uint8s(s, 4); /* Unknown */ - return 0; -} - -/*****************************************************************************/ -/* get the bitmap cache size */ -static int APP_CC -xrdp_process_capset_bmpcache(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int i; - - if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2) - { - g_writeln("xrdp_process_capset_bmpcache: error"); - return 1; - } - self->client_info.bitmap_cache_version |= 1; - in_uint8s(s, 24); - /* cache 1 */ - in_uint16_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache1_entries = i; - in_uint16_le(s, self->client_info.cache1_size); - /* cache 2 */ - in_uint16_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache2_entries = i; - in_uint16_le(s, self->client_info.cache2_size); - /* caceh 3 */ - in_uint16_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache3_entries = i; - in_uint16_le(s, self->client_info.cache3_size); - DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, - self->client_info.cache1_size)); - DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries, - self->client_info.cache2_size)); - DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries, - self->client_info.cache3_size)); - return 0; -} - -/*****************************************************************************/ -/* get the bitmap cache size */ -static int APP_CC -xrdp_process_capset_bmpcache2(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int Bpp = 0; - int i = 0; - - if (len < 2 + 2 + 4 + 4 + 4) - { - g_writeln("xrdp_process_capset_bmpcache2: error"); - return 1; - } - self->client_info.bitmap_cache_version |= 2; - Bpp = (self->client_info.bpp + 7) / 8; - in_uint16_le(s, i); /* cache flags */ - self->client_info.bitmap_cache_persist_enable = i; - in_uint8s(s, 2); /* number of caches in set, 3 */ - in_uint32_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache1_entries = i; - self->client_info.cache1_size = 256 * Bpp; - in_uint32_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache2_entries = i; - self->client_info.cache2_size = 1024 * Bpp; - in_uint32_le(s, i); - i = i & 0x7fffffff; - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache3_entries = i; - self->client_info.cache3_size = 4096 * Bpp; - DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, - self->client_info.cache1_size)); - DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries, - self->client_info.cache2_size)); - DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries, - self->client_info.cache3_size)); - return 0; -} - -/*****************************************************************************/ -static int -xrdp_process_capset_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int codec_id; - - if (len < 1) - { - g_writeln("xrdp_process_capset_cache_v3_codec_id: error"); - return 1; - } - in_uint8(s, codec_id); - g_writeln("xrdp_process_capset_cache_v3_codec_id: cache_v3_codec_id %d", - codec_id); - self->client_info.v3_codec_id = codec_id; - return 0; -} - -/*****************************************************************************/ -/* get the number of client cursor cache */ -static int APP_CC -xrdp_process_capset_pointercache(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int i; - int colorPointerFlag; - int no_new_cursor; - - if (len < 2 + 2 + 2) - { - g_writeln("xrdp_process_capset_pointercache: error"); - return 1; - } - no_new_cursor = self->client_info.pointer_flags & 2; - in_uint16_le(s, colorPointerFlag); - self->client_info.pointer_flags = colorPointerFlag; - in_uint16_le(s, i); - i = MIN(i, 32); - self->client_info.pointer_cache_entries = i; - if (colorPointerFlag & 1) - { - g_writeln("xrdp_process_capset_pointercache: client supports " - "new(color) cursor"); - in_uint16_le(s, i); - i = MIN(i, 32); - self->client_info.pointer_cache_entries = i; - } - else - { - g_writeln("xrdp_process_capset_pointercache: client does not support " - "new(color) cursor"); - } - if (no_new_cursor) - { - g_writeln("xrdp_process_capset_pointercache: new(color) cursor is " - "disabled by config"); - self->client_info.pointer_flags = 0; - } - return 0; -} - -/*****************************************************************************/ -/* get the type of client brush cache */ -static int APP_CC -xrdp_process_capset_brushcache(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int code; - - if (len < 4) - { - g_writeln("xrdp_process_capset_brushcache: error"); - return 1; - } - in_uint32_le(s, code); - self->client_info.brush_cache_code = code; return 0; } /*****************************************************************************/ -static int APP_CC -xrdp_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s, - int len) +int APP_CC +xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) { - int i32; - - if (len < 4 + 2 + 2) - { - g_writeln("xrdp_process_offscreen_bmpcache: error"); - return 1; - } - in_uint32_le(s, i32); - self->client_info.offscreen_support_level = i32; - in_uint16_le(s, i32); - self->client_info.offscreen_cache_size = i32 * 1024; - in_uint16_le(s, i32); - self->client_info.offscreen_cache_entries = i32; - g_writeln("xrdp_process_offscreen_bmpcache: support level %d " - "cache size %d MB cache entries %d", - self->client_info.offscreen_support_level, - self->client_info.offscreen_cache_size, - self->client_info.offscreen_cache_entries); - return 0; -} + struct stream *s = (struct stream *)NULL; -/*****************************************************************************/ -static int APP_CC -xrdp_process_capset_rail(struct xrdp_rdp *self, struct stream *s, int len) -{ - int i32; + make_stream(s); + init_stream(s, 8192); + DEBUG(("in xrdp_rdp_send_data_update_sync")); - if (len < 4) + if (self->client_info.use_fast_path & 1) /* fastpath output supported */ { - g_writeln("xrdp_process_capset_rail: error"); - return 1; + LLOGLN(10, ("xrdp_rdp_send_data_update_sync: fastpath")); + if (xrdp_rdp_init_fastpath(self, s) != 0) + { + free_stream(s); + return 1; + } } - in_uint32_le(s, i32); - self->client_info.rail_support_level = i32; - g_writeln("xrdp_process_capset_rail: rail_support_level %d", - self->client_info.rail_support_level); - return 0; -} - -/*****************************************************************************/ -static int APP_CC -xrdp_process_capset_window(struct xrdp_rdp *self, struct stream *s, int len) -{ - int i32; - - if (len < 4 + 1 + 2) + else /* slowpath */ { - g_writeln("xrdp_process_capset_window: error"); - return 1; + if (xrdp_rdp_init_data(self, s) != 0) + { + DEBUG(("out xrdp_rdp_send_data_update_sync error")); + free_stream(s); + return 1; + } + out_uint16_le(s, RDP_UPDATE_SYNCHRONIZE); } - in_uint32_le(s, i32); - self->client_info.wnd_support_level = i32; - in_uint8(s, i32); - self->client_info.wnd_num_icon_caches = i32; - in_uint16_le(s, i32); - self->client_info.wnd_num_icon_cache_entries = i32; - g_writeln("xrdp_process_capset_window wnd_support_level %d " - "wnd_num_icon_caches %d wnd_num_icon_cache_entries %d", - self->client_info.wnd_support_level, - self->client_info.wnd_num_icon_caches, - self->client_info.wnd_num_icon_cache_entries); - return 0; -} - -/*****************************************************************************/ -static int APP_CC -xrdp_process_capset_codecs(struct xrdp_rdp *self, struct stream *s, int len) -{ - int codec_id; - int codec_count; - int index; - int codec_properties_length; - int i1; - char *codec_guid; - char *next_guid; - if (len < 1) - { - g_writeln("xrdp_process_capset_codecs: error"); - return 1; - } - in_uint8(s, codec_count); - len--; + out_uint16_le(s, 0); /* pad */ + s_mark_end(s); - for (index = 0; index < codec_count; index++) + if (self->client_info.use_fast_path & 1) /* fastpath output supported */ { - codec_guid = s->p; - if (len < 16 + 1 + 2) + if (xrdp_rdp_send_fastpath(self, s, + FASTPATH_UPDATETYPE_SYNCHRONIZE) != 0) { - g_writeln("xrdp_process_capset_codecs: error"); + free_stream(s); return 1; } - in_uint8s(s, 16); - in_uint8(s, codec_id); - in_uint16_le(s, codec_properties_length); - len -= 16 + 1 + 2; - if (len < codec_properties_length) + } + else /* slowpath */ + { + if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_UPDATE) != 0) { - g_writeln("xrdp_process_capset_codecs: error"); + DEBUG(("out xrdp_rdp_send_data_update_sync error")); + free_stream(s); return 1; } - len -= codec_properties_length; - next_guid = s->p + codec_properties_length; - - if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) - { - g_writeln("xrdp_process_capset_codecs: nscodec codec id %d prop len %d", - codec_id, codec_properties_length); - self->client_info.ns_codec_id = codec_id; - i1 = MIN(64, codec_properties_length); - g_memcpy(self->client_info.ns_prop, s->p, i1); - self->client_info.ns_prop_len = i1; - } - else if (g_memcmp(codec_guid, XR_CODEC_GUID_REMOTEFX, 16) == 0) - { - g_writeln("xrdp_process_capset_codecs: rfx codec id %d prop len %d", - codec_id, codec_properties_length); - self->client_info.rfx_codec_id = codec_id; - i1 = MIN(64, codec_properties_length); - g_memcpy(self->client_info.rfx_prop, s->p, i1); - self->client_info.rfx_prop_len = i1; - } - else if (g_memcmp(codec_guid, XR_CODEC_GUID_JPEG, 16) == 0) - { - g_writeln("xrdp_process_capset_codecs: jpeg codec id %d prop len %d", - codec_id, codec_properties_length); - self->client_info.jpeg_codec_id = codec_id; - i1 = MIN(64, codec_properties_length); - g_memcpy(self->client_info.jpeg_prop, s->p, i1); - self->client_info.jpeg_prop_len = i1; - g_writeln(" jpeg quality %d", self->client_info.jpeg_prop[0]); - } - else - { - g_writeln("xrdp_process_capset_codecs: unknown codec id %d", codec_id); - } - - s->p = next_guid; } + + DEBUG(("out xrdp_rdp_send_data_update_sync")); + free_stream(s); return 0; } /*****************************************************************************/ int APP_CC -xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s) +xrdp_rdp_incoming(struct xrdp_rdp *self) { - int cap_len; - int source_len; - int num_caps; - int index; - int type; - int len; - char *p; - - DEBUG(("in xrdp_rdp_process_confirm_active")); - in_uint8s(s, 4); /* rdp_shareid */ - in_uint8s(s, 2); /* userid */ - in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */ - in_uint16_le(s, cap_len); - in_uint8s(s, source_len); - in_uint16_le(s, num_caps); - in_uint8s(s, 2); /* pad */ + DEBUG(("in xrdp_rdp_incoming")); - for (index = 0; index < num_caps; index++) + if (xrdp_sec_incoming(self->sec_layer) != 0) { - p = s->p; - if (!s_check_rem(s, 4)) - { - g_writeln("xrdp_rdp_process_confirm_active: error 1"); - return 1; - } - in_uint16_le(s, type); - in_uint16_le(s, len); - if ((len < 4) || !s_check_rem(s, len - 4)) - { - g_writeln("xrdp_rdp_process_confirm_active: error len %d", len, s->end - s->p); - return 1; - } - len -= 4; - switch (type) - { - case RDP_CAPSET_GENERAL: /* 1 */ - DEBUG(("RDP_CAPSET_GENERAL")); - xrdp_process_capset_general(self, s, len); - break; - case RDP_CAPSET_BITMAP: /* 2 */ - DEBUG(("RDP_CAPSET_BITMAP")); - break; - case RDP_CAPSET_ORDER: /* 3 */ - DEBUG(("RDP_CAPSET_ORDER")); - xrdp_process_capset_order(self, s, len); - break; - case RDP_CAPSET_BMPCACHE: /* 4 */ - DEBUG(("RDP_CAPSET_BMPCACHE")); - xrdp_process_capset_bmpcache(self, s, len); - break; - case RDP_CAPSET_CONTROL: /* 5 */ - DEBUG(("RDP_CAPSET_CONTROL")); - break; - case 6: - xrdp_process_capset_cache_v3_codec_id(self, s, len); - break; - case RDP_CAPSET_ACTIVATE: /* 7 */ - DEBUG(("RDP_CAPSET_ACTIVATE")); - break; - case RDP_CAPSET_POINTER: /* 8 */ - DEBUG(("RDP_CAPSET_POINTER")); - xrdp_process_capset_pointercache(self, s, len); - break; - case RDP_CAPSET_SHARE: /* 9 */ - DEBUG(("RDP_CAPSET_SHARE")); - break; - case RDP_CAPSET_COLCACHE: /* 10 */ - DEBUG(("RDP_CAPSET_COLCACHE")); - break; - case 12: /* 12 */ - DEBUG(("--12")); - break; - case 13: /* 13 */ - DEBUG(("--13")); - break; - case 14: /* 14 */ - DEBUG(("--14")); - break; - case RDP_CAPSET_BRUSHCACHE: /* 15 */ - xrdp_process_capset_brushcache(self, s, len); - break; - case 16: /* 16 */ - DEBUG(("--16")); - break; - case 17: /* 17 */ - DEBUG(("CAPSET_TYPE_OFFSCREEN_CACHE")); - xrdp_process_offscreen_bmpcache(self, s, len); - break; - case RDP_CAPSET_BMPCACHE2: /* 19 */ - DEBUG(("RDP_CAPSET_BMPCACHE2")); - xrdp_process_capset_bmpcache2(self, s, len); - break; - case 20: /* 20 */ - DEBUG(("--20")); - break; - case 21: /* 21 */ - DEBUG(("--21")); - break; - case 22: /* 22 */ - DEBUG(("--22")); - break; - case 0x0017: /* 23 CAPSETTYPE_RAIL */ - xrdp_process_capset_rail(self, s, len); - break; - case 0x0018: /* 24 CAPSETTYPE_WINDOW */ - xrdp_process_capset_window(self, s, len); - break; - case 26: /* 26 */ - DEBUG(("--26")); - break; - case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */ - xrdp_process_capset_codecs(self, s, len); - break; - default: - g_writeln("unknown in xrdp_rdp_process_confirm_active %d", type); - break; - } - - s->p = p + len + 4; + return 1; } - - DEBUG(("out xrdp_rdp_process_confirm_active")); + self->mcs_channel = self->sec_layer->mcs_layer->userid + + MCS_USERCHANNEL_BASE; + DEBUG(("out xrdp_rdp_incoming mcs channel %d", self->mcs_channel)); + g_strncpy(self->client_info.client_addr, + self->sec_layer->mcs_layer->iso_layer->trans->addr, + sizeof(self->client_info.client_addr) - 1); + g_strncpy(self->client_info.client_port, + self->sec_layer->mcs_layer->iso_layer->trans->port, + sizeof(self->client_info.client_port) - 1); return 0; } @@ -1371,8 +877,8 @@ xrdp_rdp_send_synchronise(struct xrdp_rdp *self) return 1; } - out_uint16_le(s, 1); - out_uint16_le(s, 1002); + out_uint16_le(s, 1); /* messageType (2 bytes) */ + out_uint16_le(s, 1002); /* targetUser (2 bytes) */ s_mark_end(s); if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_SYNCHRONISE) != 0) @@ -1511,45 +1017,7 @@ xrdp_rdp_send_fontmap(struct xrdp_rdp *self) free_stream(s); return 0; } -/*****************************************************************************/ -int APP_CC -xrdp_rdp_send_monitorlayout(struct xrdp_rdp *self) -{ - struct stream *s; - int i; - make_stream(s); - init_stream(s, 8192); - - if (xrdp_rdp_init_data(self, s) != 0) - { - free_stream(s); - return 1; - } - - out_uint32_le(s, self->client_info.monitorCount); /* MonitorCount */ - - /* TODO: validate for allowed monitors in terminal server (maybe by config?) */ - for (i = 0; i < self->client_info.monitorCount; i++) - { - out_uint32_le(s, self->client_info.minfo[i].left); - out_uint32_le(s, self->client_info.minfo[i].top); - out_uint32_le(s, self->client_info.minfo[i].right); - out_uint32_le(s, self->client_info.minfo[i].bottom); - out_uint32_le(s, self->client_info.minfo[i].is_primary); - } - - s_mark_end(s); - - if (xrdp_rdp_send_data(self, s, 0x37) != 0) - { - free_stream(s); - return 1; - } - - free_stream(s); - return 0; -} /*****************************************************************************/ static int APP_CC xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) @@ -1694,7 +1162,6 @@ xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s) return 0; } - /*****************************************************************************/ int APP_CC xrdp_rdp_disconnect(struct xrdp_rdp *self) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index a4fe8c5a..63957a45 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -26,6 +26,8 @@ do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) +#define LHEXDUMP(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_hexdump _args ; } } while (0) /* some compilers need unsigned char to avoid warnings */ static tui8 g_pad_54[40] = @@ -183,6 +185,8 @@ static const tui8 g_fips_ivec[8] = 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; +static int is_security_header_present = 1; /* next packet should contain security header? */ + /*****************************************************************************/ static void APP_CC hex_str_to_bin(char *in, char *out, int out_len) @@ -219,85 +223,251 @@ hex_str_to_bin(char *in, char *out, int out_len) } /*****************************************************************************/ -struct xrdp_sec *APP_CC -xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans, int crypt_level, - int channel_code, int multimon) +static void APP_CC +xrdp_load_keyboard_layout(struct xrdp_client_info *client_info) { - struct xrdp_sec *self; + int fd; + int index = 0; + int bytes; + struct list *names = (struct list *)NULL; + struct list *items = (struct list *)NULL; + struct list *values = (struct list *)NULL; + char *item = (char *)NULL; + char *value = (char *)NULL; + char *q = (char *)NULL; + char keyboard_cfg_file[256] = { 0 }; + char rdp_layout[256] = { 0 }; + + LLOGLN(0, ("xrdp_load_keyboard_layout:")); + /* infer model/variant */ + /* TODO specify different X11 keyboard models/variants */ + g_memset(client_info->model, 0, sizeof(client_info->model)); + g_memset(client_info->variant, 0, sizeof(client_info->variant)); + g_strncpy(client_info->layout, "us", sizeof(client_info->layout) - 1); + if (client_info->keyboard_subtype == 3) + { + /* macintosh keyboard */ + bytes = sizeof(client_info->variant); + g_strncpy(client_info->variant, "mac", bytes - 1); + } + else if (client_info->keyboard_subtype == 0) + { + /* default - standard subtype */ + client_info->keyboard_subtype = 1; + } + + g_snprintf(keyboard_cfg_file, 255, "%s/xrdp_keyboard.ini", XRDP_CFG_PATH); + LLOGLN(10, ("keyboard_cfg_file %s", keyboard_cfg_file)); + + fd = g_file_open(keyboard_cfg_file); + + if (fd > 0) + { + int section_found = -1; + char section_rdp_layouts[256] = { 0 }; + char section_layouts_map[256] = { 0 }; + + names = list_create(); + names->auto_free = 1; + items = list_create(); + items->auto_free = 1; + values = list_create(); + values->auto_free = 1; + + file_read_sections(fd, names); + for (index = 0; index < names->count; index++) + { + q = (char *)list_get_item(names, index); + if (g_strncasecmp("default", q, 8) != 0) + { + int i; - DEBUG((" in xrdp_sec_create")); - self = (struct xrdp_sec *)g_malloc(sizeof(struct xrdp_sec), 1); - self->rdp_layer = owner; - self->crypt_method = CRYPT_METHOD_NONE; - self->crypt_level = CRYPT_LEVEL_NONE; - switch (crypt_level) - { - case 1: /* low */ - self->crypt_method = CRYPT_METHOD_40BIT; - self->crypt_level = CRYPT_LEVEL_LOW; - break; - case 2: /* medium */ - self->crypt_method = CRYPT_METHOD_40BIT; - self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE; - break; - case 3: /* high */ - self->crypt_method = CRYPT_METHOD_128BIT; - self->crypt_level = CRYPT_LEVEL_HIGH; - break; - case 4: /* fips */ - self->crypt_method = CRYPT_METHOD_FIPS; - self->crypt_level = CRYPT_LEVEL_FIPS; - break; - default: - g_writeln("Fatal : Illegal crypt_level"); - break ; - } + file_read_section(fd, q, items, values); - self->channel_code = channel_code; - self->multimon = multimon; + for (i = 0; i < items->count; i++) + { + item = (char *)list_get_item(items, i); + value = (char *)list_get_item(values, i); + LLOGLN(10, ("xrdp_load_keyboard_layout: item %s value %s", + item, value)); + if (g_strcasecmp(item, "keyboard_type") == 0) + { + int v = g_atoi(value); + if (v == client_info->keyboard_type) + { + section_found = index; + } + } + else if (g_strcasecmp(item, "keyboard_subtype") == 0) + { + int v = g_atoi(value); + if (v != client_info->keyboard_subtype && + section_found == index) + { + section_found = -1; + break; + } + } + else if (g_strcasecmp(item, "rdp_layouts") == 0) + { + if (section_found != -1 && section_found == index) + { + g_strncpy(section_rdp_layouts, value, 255); + } + } + else if (g_strcasecmp(item, "layouts_map") == 0) + { + if (section_found != -1 && section_found == index) + { + g_strncpy(section_layouts_map, value, 255); + } + } + else if (g_strcasecmp(item, "model") == 0) + { + if (section_found != -1 && section_found == index) + { + bytes = sizeof(client_info->model); + g_memset(client_info->model, 0, bytes); + g_strncpy(client_info->model, value, bytes - 1); + } + } + else if (g_strcasecmp(item, "variant") == 0) + { + if (section_found != -1 && section_found == index) + { + bytes = sizeof(client_info->variant); + g_memset(client_info->variant, 0, bytes); + g_strncpy(client_info->variant, value, bytes - 1); + } + } + else + { + /* + * mixing items from different sections will result in + * skipping over current section. + */ + LLOGLN(10, ("xrdp_load_keyboard_layout: skipping " + "configuration item - %s, continuing to next " + "section", item)); + break; + } + } - if (self->decrypt_rc4_info != NULL) - { - g_writeln("xrdp_sec_create - decrypt_rc4_info already created !!!"); - } + list_clear(items); + list_clear(values); + } + } + + if (section_found == -1) + { + g_memset(section_rdp_layouts, 0, sizeof(char) * 256); + g_memset(section_layouts_map, 0, sizeof(char) * 256); + // read default section + file_read_section(fd, "default", items, values); + for (index = 0; index < items->count; index++) + { + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + if (g_strcasecmp(item, "rdp_layouts") == 0) + { + g_strncpy(section_rdp_layouts, value, 255); + } + else if (g_strcasecmp(item, "layouts_map") == 0) + { + g_strncpy(section_layouts_map, value, 255); + } + } + list_clear(items); + list_clear(values); + } - self->decrypt_rc4_info = ssl_rc4_info_create(); + /* load the map */ + file_read_section(fd, section_rdp_layouts, items, values); + for (index = 0; index < items->count; index++) + { + int rdp_layout_id; + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + rdp_layout_id = g_htoi(value); + if (rdp_layout_id == client_info->keylayout) + { + g_strncpy(rdp_layout, item, 255); + break; + } + } + list_clear(items); + list_clear(values); + file_read_section(fd, section_layouts_map, items, values); + for (index = 0; index < items->count; index++) + { + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + if (g_strcasecmp(item, rdp_layout) == 0) + { + bytes = sizeof(client_info->layout); + g_strncpy(client_info->layout, value, bytes - 1); + break; + } + } - if (self->encrypt_rc4_info != NULL) + list_delete(names); + list_delete(items); + list_delete(values); + + LLOGLN(0, ("xrdp_load_keyboard_layout: model [%s] variant [%s] " + "layout [%s]", client_info->model, client_info->variant, + client_info->layout)); + g_file_close(fd); + } + else { - g_writeln("xrdp_sec_create - encrypt_rc4_info already created !!!"); + LLOGLN(0, ("xrdp_load_keyboard_layout: error opening %d", + keyboard_cfg_file)); } +} + +/*****************************************************************************/ +struct xrdp_sec *APP_CC +xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans) +{ + struct xrdp_sec *self; - self->encrypt_rc4_info = ssl_rc4_info_create(); - self->mcs_layer = xrdp_mcs_create(self, trans, &self->client_mcs_data, - &self->server_mcs_data); - self->chan_layer = xrdp_channel_create(self, self->mcs_layer); - DEBUG((" out xrdp_sec_create")); - return self; + DEBUG((" in xrdp_sec_create")); + self = (struct xrdp_sec *) g_malloc(sizeof(struct xrdp_sec), 1); + self->rdp_layer = owner; + self->crypt_method = CRYPT_METHOD_NONE; /* set later */ + self->crypt_level = CRYPT_LEVEL_NONE; + self->mcs_layer = xrdp_mcs_create(self, trans, &(self->client_mcs_data), + &(self->server_mcs_data)); + self->fastpath_layer = xrdp_fastpath_create(self, trans); + self->chan_layer = xrdp_channel_create(self, self->mcs_layer); + DEBUG((" out xrdp_sec_create")); + + return self; } /*****************************************************************************/ void APP_CC -xrdp_sec_delete(struct xrdp_sec *self) -{ - if (self == 0) - { - g_writeln("xrdp_sec_delete: indata is null"); - return; - } - - xrdp_channel_delete(self->chan_layer); - xrdp_mcs_delete(self->mcs_layer); - ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */ - ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */ - ssl_des3_info_delete(self->decrypt_fips_info); - ssl_des3_info_delete(self->encrypt_fips_info); - ssl_hmac_info_delete(self->sign_fips_info); - g_free(self->client_mcs_data.data); - g_free(self->server_mcs_data.data); - /* Crypto information must always be cleared */ - g_memset(self, 0, sizeof(struct xrdp_sec)); - g_free(self); +xrdp_sec_delete(struct xrdp_sec *self) { + + if (self == 0) { + g_writeln("xrdp_sec_delete: indata is null"); + return; + } + + xrdp_channel_delete(self->chan_layer); + xrdp_mcs_delete(self->mcs_layer); + xrdp_fastpath_delete(self->fastpath_layer); + ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */ + ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */ + ssl_des3_info_delete(self->decrypt_fips_info); + ssl_des3_info_delete(self->encrypt_fips_info); + ssl_hmac_info_delete(self->sign_fips_info); + g_free(self->client_mcs_data.data); + g_free(self->server_mcs_data.data); + /* Crypto information must always be cleared */ + g_memset(self, 0, sizeof(struct xrdp_sec)); + g_free(self); } /*****************************************************************************/ @@ -320,7 +490,7 @@ xrdp_sec_init(struct xrdp_sec *self, struct stream *s) } else { - s_push_layer(s, sec_hdr, 4); +// s_push_layer(s, sec_hdr, 4); } return 0; @@ -766,9 +936,12 @@ xrdp_sec_send_media_lic_response(struct xrdp_sec *self) /*****************************************************************************/ static void APP_CC -xrdp_sec_rsa_op(char *out, char *in, char *mod, char *exp) +xrdp_sec_rsa_op(struct xrdp_sec *self, char *out, char *in, int in_bytes, + char *mod, char *exp) { - ssl_mod_exp(out, 64, in, 64, mod, 64, exp, 64); + ssl_mod_exp(out, self->rsa_key_bytes, in, in_bytes, + mod, self->rsa_key_bytes, + exp, self->rsa_key_bytes); } /*****************************************************************************/ @@ -952,6 +1125,68 @@ xrdp_sec_establish_keys(struct xrdp_sec *self) /*****************************************************************************/ /* returns error */ int APP_CC +xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s) +{ + int ver; + int len; + int pad; + + LLOGLN(10, ("xrdp_sec_recv_fastpath:")); + if (xrdp_fastpath_recv(self->fastpath_layer, s) != 0) + { + return 1; + } + + if (self->fastpath_layer->secFlags & FASTPATH_INPUT_ENCRYPTED) + { + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + if (!s_check_rem(s, 12)) + { + return 1; + } + in_uint16_le(s, len); + in_uint8(s, ver); /* length (2 bytes) */ + if (len != 0x10) /* length MUST set to 0x10 */ + { + return 1; + } + in_uint8(s, pad); + LLOGLN(10, ("xrdp_sec_recv_fastpath: len %d ver %d pad %d", len, ver, pad)); + in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ + LLOGLN(10, ("xrdp_sec_recv_fastpath: data len %d", (int)(s->end - s->p))); + xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); + s->end -= pad; + } + else + { + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ + xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); + } + } + + if (self->fastpath_layer->numEvents == 0) + { + /** + * If numberEvents is not provided in fpInputHeader, it will be provided + * as one additional byte here. + */ + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint8(s, self->fastpath_layer->numEvents); /* numEvents (1 byte) (optional) */ + } + + return 0; +} +/*****************************************************************************/ +/* returns error */ +int APP_CC xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) { int flags; @@ -963,7 +1198,8 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) if (xrdp_mcs_recv(self->mcs_layer, s, chan) != 0) { - DEBUG((" out xrdp_sec_recv error")); + DEBUG((" out xrdp_sec_recv : error")); + g_writeln("xrdp_sec_recv: xrdp_mcs_recv failed"); return 1; } @@ -971,6 +1207,13 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) { return 1; } + + + if (!is_security_header_present) + { + return 0; + } + in_uint32_le(s, flags); DEBUG((" in xrdp_sec_recv flags $%x", flags)); @@ -995,7 +1238,7 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); s->end -= pad; } - else + else if (self->crypt_level > CRYPT_LEVEL_NONE) { if (!s_check_rem(s, 8)) { @@ -1008,19 +1251,31 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) if (flags & SEC_CLIENT_RANDOM) /* 0x01 */ { - if (!s_check_rem(s, 4 + 64)) + if (!s_check_rem(s, 4)) { return 1; } in_uint32_le(s, len); - in_uint8a(s, self->client_crypt_random, 64); - xrdp_sec_rsa_op(self->client_random, self->client_crypt_random, - self->pub_mod, self->pri_exp); + /* 512, 2048 bit */ + if ((len != 64 + 8) && (len != 256 + 8)) + { + return 1; + } + if (!s_check_rem(s, len - 8)) + { + return 1; + } + in_uint8a(s, self->client_crypt_random, len - 8); + xrdp_sec_rsa_op(self, self->client_random, self->client_crypt_random, + len - 8, self->pub_mod, self->pri_exp); + LLOGLN(10, ("xrdp_sec_recv: client random - len %d", len)); + LHEXDUMP(10, (self->client_random, 256)); + LHEXDUMP(10, (self->client_crypt_random, len - 8)); if (self->crypt_level == CRYPT_LEVEL_FIPS) { xrdp_sec_fips_establish_keys(self); } - else + else if (self->crypt_method != CRYPT_METHOD_NONE) { xrdp_sec_establish_keys(self); } @@ -1068,6 +1323,12 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) return 1; } + if (self->crypt_level == CRYPT_LEVEL_NONE + && self->crypt_method == CRYPT_METHOD_NONE) + { + is_security_header_present = 0; /* in tls mode, no more security header from now on */ + } + DEBUG((" out xrdp_sec_recv")); return -1; /* special error that means send demand active */ } @@ -1170,7 +1431,7 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) } else { - out_uint32_le(s, 0); +// out_uint32_le(s, 0); } if (xrdp_mcs_send(self->mcs_layer, s, chan) != 0) @@ -1183,6 +1444,120 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) } /*****************************************************************************/ +/* returns the fastpath sec byte count */ +int APP_CC +xrdp_sec_get_fastpath_bytes(struct xrdp_sec *self) +{ + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + return 3 + 4 + 8; + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) + { + return 3 + 8; + } + return 3; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s) +{ + if (xrdp_fastpath_init(self->fastpath_layer, s) != 0) + { + return 1; + } + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + s_push_layer(s, sec_hdr, 3 + 4 + 8); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) + { + s_push_layer(s, sec_hdr, 3 + 8); + } + else + { + s_push_layer(s, sec_hdr, 3); + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +/* 2.2.9.1.2 Server Fast-Path Update PDU (TS_FP_UPDATE_PDU) + * http://msdn.microsoft.com/en-us/library/cc240621.aspx */ +int APP_CC +xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s) +{ + int secFlags; + int fpOutputHeader; + int datalen; + int pdulen; + int pad; + int error; + char save[8]; + + LLOGLN(10, ("xrdp_sec_send_fastpath:")); + error = 0; + s_pop_layer(s, sec_hdr); + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + LLOGLN(10, ("xrdp_sec_send_fastpath: fips")); + pdulen = (int)(s->end - s->p); + datalen = pdulen - 15; + pad = (8 - (datalen % 8)) & 7; + secFlags = 0x2; + fpOutputHeader = secFlags << 6; + out_uint8(s, fpOutputHeader); + pdulen += pad; + pdulen |= 0x8000; + out_uint16_be(s, pdulen); + out_uint16_le(s, 16); /* crypto header size */ + out_uint8(s, 1); /* fips version */ + s->end += pad; + out_uint8(s, pad); /* fips pad */ + xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen); + g_memcpy(save, s->p + 8 + datalen, pad); + g_memset(s->p + 8 + datalen, 0, pad); + xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad); + error = xrdp_fastpath_send(self->fastpath_layer, s); + g_memcpy(s->p + 8 + datalen, save, pad); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) + { + LLOGLN(10, ("xrdp_sec_send_fastpath: crypt")); + pdulen = (int)(s->end - s->p); + datalen = pdulen - 11; + secFlags = 0x2; + fpOutputHeader = secFlags << 6; + out_uint8(s, fpOutputHeader); + pdulen |= 0x8000; + out_uint16_be(s, pdulen); + xrdp_sec_sign(self, s->p, 8, s->p + 8, datalen); + xrdp_sec_encrypt(self, s->p + 8, datalen); + error = xrdp_fastpath_send(self->fastpath_layer, s); + } + else + { + LLOGLN(10, ("xrdp_sec_send_fastpath: no crypt")); + pdulen = (int)(s->end - s->p); + LLOGLN(10, ("xrdp_sec_send_fastpath: pdulen %d", pdulen)); + secFlags = 0x0; + fpOutputHeader = secFlags << 6; + out_uint8(s, fpOutputHeader); + pdulen |= 0x8000; + out_uint16_be(s, pdulen); + error = xrdp_fastpath_send(self->fastpath_layer, s); + } + if (error != 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ /* http://msdn.microsoft.com/en-us/library/cc240510.aspx 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE) */ static int APP_CC @@ -1404,10 +1779,23 @@ xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream* s) found = 1; } } - if (found == 0) + if ((found == 0) && + (self->crypt_level == CRYPT_LEVEL_NONE)) { - g_writeln(" no security"); + if (crypt_method == CRYPT_METHOD_NONE) + { + g_writeln(" client and server support none crypt, using " + "none crypt"); + self->crypt_method = CRYPT_METHOD_NONE; + self->crypt_level = CRYPT_LEVEL_NONE; + found = 1; + } } +// if (found == 0) +// { +// g_writeln(" can not find client / server agreed encryption method"); +// return 1; +// } return 0; } @@ -1420,11 +1808,15 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) int num_channels; int index; struct mcs_channel_item *channel_item; + struct xrdp_client_info *client_info = (struct xrdp_client_info *)NULL; + + client_info = &(self->rdp_layer->client_info); + - DEBUG(("processing channels, channel_code is %d", self->channel_code)); + DEBUG(("processing channels, channel_code is %d", client_info->channel_code)); /* this is an option set in xrdp.ini */ - if (self->channel_code != 1) /* are channels on? */ + if (client_info->channel_code != 1) /* are channels on? */ { g_writeln("Processing channel data from client - The channel is off"); return 0; @@ -1444,16 +1836,19 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) for (index = 0; index < num_channels; index++) { + struct mcs_channel_item *channel_item; + channel_item = (struct mcs_channel_item *) g_malloc(sizeof(struct mcs_channel_item), 1); if (!s_check_rem(s, 12)) { + g_free(channel_item); return 1; } in_uint8a(s, channel_item->name, 8); in_uint32_le(s, channel_item->flags); channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1); - list_add_item(self->mcs_layer->channel_list, (tintptr)channel_item); + list_add_item(self->mcs_layer->channel_list, (tintptr) channel_item); DEBUG(("got channel flags %8.8x name %s", channel_item->flags, channel_item->name)); } @@ -1473,9 +1868,9 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) client_info = &(self->rdp_layer->client_info); - DEBUG(("processing monitors data, allow_multimon is %d", self->multimon)); + DEBUG(("processing monitors data, allow_multimon is %d", client_info->multimon)); /* this is an option set in xrdp.ini */ - if (self->multimon != 1) /* are multi-monitors allowed ? */ + if (client_info->multimon != 1) /* are multi-monitors allowed ? */ { DEBUG(("[INFO] xrdp_sec_process_mcs_data_monitors: multimon is not " "allowed, skipping")); @@ -1617,113 +2012,6 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) } /*****************************************************************************/ -/* prepare server mcs data to send in mcs layer */ -int APP_CC -xrdp_sec_out_mcs_data(struct xrdp_sec *self) -{ - struct stream *s; - int num_channels_even; - int num_channels; - int index; - int channel; - - num_channels = self->mcs_layer->channel_list->count; - num_channels_even = num_channels + (num_channels & 1); - s = &self->server_mcs_data; - init_stream(s, 512); - out_uint16_be(s, 5); - out_uint16_be(s, 0x14); - out_uint8(s, 0x7c); - out_uint16_be(s, 1); - out_uint8(s, 0x2a); - out_uint8(s, 0x14); - out_uint8(s, 0x76); - out_uint8(s, 0x0a); - out_uint8(s, 1); - out_uint8(s, 1); - out_uint8(s, 0); - out_uint16_le(s, 0xc001); - out_uint8(s, 0); - out_uint8(s, 0x4d); /* M */ - out_uint8(s, 0x63); /* c */ - out_uint8(s, 0x44); /* D */ - out_uint8(s, 0x6e); /* n */ - if (self->mcs_layer->iso_layer->selectedProtocol != -1) - { // Check for RDPNEGDATA availability - out_uint16_be(s, 0x80fc + (num_channels_even * 2) + 4); - } - else - { - out_uint16_be(s, 0x80fc + (num_channels_even * 2)); - } - out_uint16_le(s, SEC_TAG_SRV_INFO); - if (self->mcs_layer->iso_layer->selectedProtocol != -1) - { - out_uint16_le(s, 12); /* len */ - } - else - { - out_uint16_le(s, 8); /* len */ - } - out_uint8(s, 4); /* 4 = rdp5 1 = rdp4 */ - out_uint8(s, 0); - out_uint8(s, 8); - out_uint8(s, 0); - if (self->mcs_layer->iso_layer->selectedProtocol != -1) - { - /* clientReqeustedProtocol */ - out_uint32_le(s, self->mcs_layer->iso_layer->selectedProtocol); - } - out_uint16_le(s, SEC_TAG_SRV_CHANNELS); - out_uint16_le(s, 8 + (num_channels_even * 2)); /* len */ - out_uint16_le(s, MCS_GLOBAL_CHANNEL); /* 1003, 0x03eb main channel */ - out_uint16_le(s, num_channels); /* number of other channels */ - - for (index = 0; index < num_channels_even; index++) - { - if (index < num_channels) - { - channel = MCS_GLOBAL_CHANNEL + (index + 1); - out_uint16_le(s, channel); - } - else - { - out_uint16_le(s, 0); - } - } - - out_uint16_le(s, SEC_TAG_SRV_CRYPT); - out_uint16_le(s, 0x00ec); /* len is 236 */ - out_uint32_le(s, self->crypt_method); - out_uint32_le(s, self->crypt_level); - out_uint32_le(s, 32); /* 32 bytes random len */ - out_uint32_le(s, 0xb8); /* 184 bytes rsa info(certificate) len */ - out_uint8a(s, self->server_random, 32); - /* here to end is certificate */ - /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */ - /* TermService\Parameters\Certificate */ - out_uint32_le(s, 1); - out_uint32_le(s, 1); - out_uint32_le(s, 1); - out_uint16_le(s, SEC_TAG_PUBKEY); - out_uint16_le(s, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */ - out_uint32_le(s, SEC_RSA_MAGIC); - out_uint32_le(s, 0x48); /* 72 bytes modulus len */ - out_uint32_be(s, 0x00020000); - out_uint32_be(s, 0x3f000000); - out_uint8a(s, self->pub_exp, 4); /* pub exp */ - out_uint8a(s, self->pub_mod, 64); /* pub mod */ - out_uint8s(s, 8); /* pad */ - out_uint16_le(s, SEC_TAG_KEYSIG); - out_uint16_le(s, 72); /* len */ - out_uint8a(s, self->pub_sig, 64); /* pub sig */ - out_uint8s(s, 8); /* pad */ - /* end certificate */ - s_mark_end(s); - return 0; -} - -/*****************************************************************************/ /* process the mcs client data we received from the mcs layer */ static int APP_CC xrdp_sec_in_mcs_data(struct xrdp_sec *self) @@ -1782,67 +2070,166 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) in_uint8s(s, 79); in_uint32_le(s, client_info->keyboard_type); in_uint32_le(s, client_info->keyboard_subtype); + xrdp_load_keyboard_layout(client_info); s->p = s->data; return 0; } /*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_sec_init_rdp_security(struct xrdp_sec *self) +{ + switch (self->rdp_layer->client_info.crypt_level) + { + case 0: /* none */ + self->crypt_method = CRYPT_METHOD_NONE; + self->crypt_level = CRYPT_LEVEL_NONE; + break; + case 1: /* low */ + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_LOW; + break; + case 2: /* medium */ + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE; + break; + case 3: /* high */ + self->crypt_method = CRYPT_METHOD_128BIT; + self->crypt_level = CRYPT_LEVEL_HIGH; + break; + case 4: /* fips */ + self->crypt_method = CRYPT_METHOD_FIPS; + self->crypt_level = CRYPT_LEVEL_FIPS; + break; + default: + g_writeln("Fatal : Illegal crypt_level"); + break ; + } + + if (self->decrypt_rc4_info != NULL) + { + g_writeln("xrdp_sec_init_rdp_security: decrypt_rc4_info already created !!!"); + } + else + { + self->decrypt_rc4_info = ssl_rc4_info_create(); + } + + if (self->encrypt_rc4_info != NULL) + { + g_writeln("xrdp_sec_init_rdp_security: encrypt_rc4_info already created !!!"); + } + else + { + self->encrypt_rc4_info = ssl_rc4_info_create(); + } + + return 0; +} + +/*****************************************************************************/ int APP_CC xrdp_sec_incoming(struct xrdp_sec *self) { struct list *items = NULL; struct list *values = NULL; + struct xrdp_iso *iso; int index = 0; char *item = NULL; char *value = NULL; char key_file[256]; - LLOGLN(10, ("xrdp_sec_incoming:")); - g_memset(key_file, 0, sizeof(char) * 256); - DEBUG((" in xrdp_sec_incoming")); - g_random(self->server_random, 32); - items = list_create(); - items->auto_free = 1; - values = list_create(); - values->auto_free = 1; - g_snprintf(key_file, 255, "%s/rsakeys.ini", XRDP_CFG_PATH); - - if (file_by_name_read_section(key_file, "keys", items, values) != 0) - { - /* this is a show stopper */ - log_message(LOG_LEVEL_ALWAYS, "XRDP cannot read file: %s " - "(check permissions)", key_file); - list_delete(items); - list_delete(values); + DEBUG((" in xrdp_sec_incoming:")); + iso = self->mcs_layer->iso_layer; + + /* negotiate security layer */ + if (xrdp_iso_incoming(iso) != 0) + { + DEBUG(("xrdp_sec_incoming: xrdp_iso_incoming failed")); return 1; } - for (index = 0; index < items->count; index++) + /* initialize selected security layer */ + if (iso->requestedProtocol > PROTOCOL_RDP) { - item = (char *)list_get_item(items, index); - value = (char *)list_get_item(values, index); + /* init tls security */ + DEBUG((" in xrdp_sec_incoming: init tls security")); - if (g_strcasecmp(item, "pub_exp") == 0) + if (trans_set_tls_mode(self->mcs_layer->iso_layer->trans, + self->rdp_layer->client_info.key_file, + self->rdp_layer->client_info.certificate) != 0) { - hex_str_to_bin(value, self->pub_exp, 4); - } - else if (g_strcasecmp(item, "pub_mod") == 0) - { - hex_str_to_bin(value, self->pub_mod, 64); + g_writeln("xrdp_sec_incoming: trans_set_tls_mode failed"); + return 1; } - else if (g_strcasecmp(item, "pub_sig") == 0) + + self->crypt_level = CRYPT_LEVEL_NONE; + self->crypt_method = CRYPT_METHOD_NONE; + self->rsa_key_bytes = 0; + + } + else + { + /* init rdp security */ + DEBUG((" in xrdp_sec_incoming: init rdp security")); + if (xrdp_sec_init_rdp_security(self) != 0) { - hex_str_to_bin(value, self->pub_sig, 64); + DEBUG(("xrdp_sec_incoming: xrdp_sec_init_rdp_security failed")); + return 1; } - else if (g_strcasecmp(item, "pri_exp") == 0) + if (self->crypt_method != CRYPT_METHOD_NONE) { - hex_str_to_bin(value, self->pri_exp, 64); + g_memset(key_file, 0, sizeof(char) * 256); + g_random(self->server_random, 32); + items = list_create(); + items->auto_free = 1; + values = list_create(); + values->auto_free = 1; + g_snprintf(key_file, 255, "%s/rsakeys.ini", XRDP_CFG_PATH); + + if (file_by_name_read_section(key_file, "keys", items, values) != 0) + { + /* this is a show stopper */ + log_message(LOG_LEVEL_ALWAYS, "XRDP cannot read file: %s " + "(check permissions)", key_file); + list_delete(items); + list_delete(values); + return 1; + } + + for (index = 0; index < items->count; index++) + { + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + + if (g_strcasecmp(item, "pub_exp") == 0) + { + hex_str_to_bin(value, self->pub_exp, 4); + } + else if (g_strcasecmp(item, "pub_mod") == 0) + { + self->rsa_key_bytes = (g_strlen(value) + 1) / 5; + g_writeln("pub_mod bytes %d", self->rsa_key_bytes); + hex_str_to_bin(value, self->pub_mod, self->rsa_key_bytes); + } + else if (g_strcasecmp(item, "pub_sig") == 0) + { + hex_str_to_bin(value, self->pub_sig, 64); + } + else if (g_strcasecmp(item, "pri_exp") == 0) + { + self->rsa_key_bytes = (g_strlen(value) + 1) / 5; + g_writeln("pri_exp %d", self->rsa_key_bytes); + hex_str_to_bin(value, self->pri_exp, self->rsa_key_bytes); + } + } + list_delete(items); + list_delete(values); } } - list_delete(items); - list_delete(values); - + /* negotiate mcs layer */ if (xrdp_mcs_incoming(self->mcs_layer) != 0) { return 1; @@ -1861,6 +2248,7 @@ xrdp_sec_incoming(struct xrdp_sec *self) { return 1; } + LLOGLN(10, ("xrdp_sec_incoming: out")); return 0; } |