summaryrefslogtreecommitdiffstats
path: root/libxrdp
diff options
context:
space:
mode:
Diffstat (limited to 'libxrdp')
-rw-r--r--libxrdp/Makefile.am8
-rw-r--r--libxrdp/libxrdp.c418
-rw-r--r--libxrdp/libxrdp.h615
-rw-r--r--libxrdp/libxrdpinc.h218
-rw-r--r--libxrdp/xrdp_bitmap32_compress.c508
-rw-r--r--libxrdp/xrdp_caps.c916
-rw-r--r--libxrdp/xrdp_channel.c19
-rw-r--r--libxrdp/xrdp_fastpath.c391
-rw-r--r--libxrdp/xrdp_iso.c304
-rw-r--r--libxrdp/xrdp_jpeg_compress.c44
-rw-r--r--libxrdp/xrdp_mcs.c288
-rw-r--r--libxrdp/xrdp_mppc_enc.c62
-rw-r--r--libxrdp/xrdp_orders.c183
-rw-r--r--libxrdp/xrdp_orders_rail.h24
-rw-r--r--libxrdp/xrdp_rdp.c1111
-rw-r--r--libxrdp/xrdp_sec.c836
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;
}