summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libxrdp/libxrdp.h14
-rw-r--r--libxrdp/xrdp_fastpath.c20
-rw-r--r--libxrdp/xrdp_orders.c124
-rw-r--r--libxrdp/xrdp_rdp.c68
-rw-r--r--libxrdp/xrdp_sec.c88
5 files changed, 262 insertions, 52 deletions
diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h
index 7a4342db..da8ebc3f 100644
--- a/libxrdp/libxrdp.h
+++ b/libxrdp/libxrdp.h
@@ -346,6 +346,10 @@ 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_init_fastpath(struct xrdp_sec *self, struct stream *s);
+int APP_CC
+xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s);
+int APP_CC
xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s);
int APP_CC
xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan);
@@ -370,6 +374,8 @@ xrdp_rdp_init(struct xrdp_rdp* self, struct stream* s);
int APP_CC
xrdp_rdp_init_data(struct xrdp_rdp* self, struct stream* s);
int APP_CC
+xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s);
+int APP_CC
xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code);
int APP_CC
xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type);
@@ -377,6 +383,9 @@ int APP_CC
xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s,
int data_pdu_type);
int APP_CC
+xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s,
+ int data_pdu_type);
+int APP_CC
xrdp_rdp_send_data_update_sync(struct xrdp_rdp* self);
int APP_CC
xrdp_rdp_incoming(struct xrdp_rdp* self);
@@ -554,4 +563,9 @@ 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);
+
#endif
diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c
index 927f9407..681d5424 100644
--- a/libxrdp/xrdp_fastpath.c
+++ b/libxrdp/xrdp_fastpath.c
@@ -97,13 +97,28 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
}
/*****************************************************************************/
+/* no fragmenation */
int APP_CC
-xrdp_fastpath_init(struct xrdp_fastpath *self)
+xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s)
{
+ init_stream(s, 32 * 1024);
return 0;
}
/*****************************************************************************/
+/* no fragmenation */
+int APP_CC
+xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s)
+{
+ if (trans_force_write_s(self->trans, s) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+#if 0
+/*****************************************************************************/
int APP_CC
xrdp_fastpath_send_update_pdu(struct xrdp_fastpath *self, tui8 updateCode,
struct stream *s)
@@ -165,6 +180,7 @@ xrdp_fastpath_send_update_pdu(struct xrdp_fastpath *self, tui8 updateCode,
return 0;
}
+#endif
/*****************************************************************************/
int
@@ -194,6 +210,7 @@ xrdp_fastpath_process_update(struct xrdp_fastpath *self, tui8 updateCode,
return 0;
}
+#if 0
/*****************************************************************************/
int APP_CC
xrdp_fastpath_process_data(struct xrdp_fastpath *self, struct stream *s,
@@ -249,6 +266,7 @@ xrdp_fastpath_process_data(struct xrdp_fastpath *self, struct stream *s,
in_uint16_le(s, size);
return xrdp_fastpath_process_update(self, updateCode, size, s);
}
+#endif
/*****************************************************************************/
/* FASTPATH_INPUT_EVENT_SCANCODE */
diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c
index 317e1135..819c3d06 100644
--- a/libxrdp/xrdp_orders.c
+++ b/libxrdp/xrdp_orders.c
@@ -64,7 +64,6 @@ xrdp_orders_delete(struct xrdp_orders *self)
{
return;
}
-
xrdp_jpeg_deinit(self->jpeg_han);
free_stream(self->out_s);
g_free(self->orders_state.text_data);
@@ -81,7 +80,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 +96,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 +134,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 +144,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 +174,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, 0) != 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;
@@ -1632,7 +1654,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 +1675,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 +1721,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 +1749,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 +1790,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 +1825,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 +1853,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 +1867,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 +1881,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 +1895,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 +1909,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 +1923,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 +1937,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 +1958,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;
}
diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c
index 26e5c453..43daa874 100644
--- a/libxrdp/xrdp_rdp.c
+++ b/libxrdp/xrdp_rdp.c
@@ -26,6 +26,12 @@
#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)
+
/*****************************************************************************/
static int APP_CC
xrdp_rdp_read_config(struct xrdp_client_info *client_info)
@@ -289,6 +295,7 @@ xrdp_rdp_init_data(struct xrdp_rdp *self, struct stream *s)
s_push_layer(s, rdp_hdr, 18);
return 0;
}
+
/*****************************************************************************/
/* returns error */
int APP_CC
@@ -500,6 +507,65 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
/*****************************************************************************/
int APP_CC
+xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s)
+{
+ if (xrdp_sec_init_fastpath(self->sec_layer, s) != 0)
+ {
+ return 1;
+ }
+ if (self->client_info.rdp_compression)
+ {
+ s_push_layer(s, rdp_hdr, 4);
+ }
+ else
+ {
+ s_push_layer(s, rdp_hdr, 3);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* TODO: compression */
+int APP_CC
+xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s,
+ int data_pdu_type)
+{
+ int updateHeader;
+ int ctype;
+ int len;
+
+ LLOGLN(10, ("xrdp_rdp_send_fastpath:"));
+ s_pop_layer(s, rdp_hdr);
+ len = (int)(s->end - s->p);
+ if (self->client_info.rdp_compression)
+ {
+ /* TODO: finish compression */
+ LLOGLN(10, ("xrdp_rdp_send_fastpath: compress"));
+ updateHeader = data_pdu_type & 15;
+ updateHeader |= 2 << 6; /* FASTPATH_OUTPUT_COMPRESSION_USED */
+ out_uint8(s, updateHeader);
+ ctype = 0;
+ out_uint8(s, ctype);
+ len -= 4;
+ }
+ else
+ {
+ LLOGLN(10, ("xrdp_rdp_send_fastpath: no compress"));
+ updateHeader = data_pdu_type & 15;
+ out_uint8(s, updateHeader);
+ len -= 3;
+ }
+ out_uint16_le(s, len);
+ if (xrdp_sec_send_fastpath(self->sec_layer, s) != 0)
+ {
+ LLOGLN(0, ("xrdp_rdp_send_fastpath: xrdp_fastpath_send failed"));
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self)
{
struct stream *s = (struct stream *)NULL;
@@ -1581,6 +1647,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)
@@ -1620,6 +1687,7 @@ xrdp_rdp_send_monitorlayout(struct xrdp_rdp *self)
free_stream(s);
return 0;
}
+
/*****************************************************************************/
static int APP_CC
xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s)
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c
index 626fc91e..9db0594f 100644
--- a/libxrdp/xrdp_sec.c
+++ b/libxrdp/xrdp_sec.c
@@ -1245,6 +1245,94 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan)
DEBUG((" out xrdp_sec_send"));
return 0;
}
+
+/*****************************************************************************/
+/* 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 */
+int APP_CC
+xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s)
+{
+ int secFlags;
+ int fpOutputHeader;
+ int datalen;
+ int pdulen;
+ int pad;
+
+ LLOGLN(10, ("xrdp_sec_send_fastpath:"));
+ 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;
+ secFlags = 0x2;
+ fpOutputHeader = secFlags << 6;
+ out_uint8(s, fpOutputHeader);
+ pdulen |= 0x8000;
+ out_uint16_be(s, pdulen);
+ out_uint16_le(s, 16); /* crypto header size */
+ out_uint8(s, 1); /* fips version */
+ pad = (8 - (datalen % 8)) & 7;
+ g_memset(s->end, 0, pad);
+ s->end += pad;
+ out_uint8(s, pad); /* fips pad */
+ xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen);
+ xrdp_sec_fips_encrypt(self, s->p + 8, datalen + 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);
+ }
+ 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);
+ }
+ if (xrdp_fastpath_send(self->fastpath_layer, s) != 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) */