diff options
Diffstat (limited to 'libxrdp')
-rw-r--r-- | libxrdp/Makefile.am | 9 | ||||
-rw-r--r-- | libxrdp/libxrdp.c | 166 | ||||
-rw-r--r-- | libxrdp/xrdp_bitmap32_compress.c | 122 | ||||
-rw-r--r-- | libxrdp/xrdp_bitmap_compress.c | 8 | ||||
-rw-r--r-- | libxrdp/xrdp_caps.c | 114 | ||||
-rw-r--r-- | libxrdp/xrdp_fastpath.c | 30 | ||||
-rw-r--r-- | libxrdp/xrdp_iso.c | 9 | ||||
-rw-r--r-- | libxrdp/xrdp_jpeg_compress.c | 53 | ||||
-rw-r--r-- | libxrdp/xrdp_orders.c | 115 | ||||
-rw-r--r-- | libxrdp/xrdp_rdp.c | 15 | ||||
-rw-r--r-- | libxrdp/xrdp_sec.c | 12 |
11 files changed, 465 insertions, 188 deletions
diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am index b7d1dc26..3812de9c 100644 --- a/libxrdp/Makefile.am +++ b/libxrdp/Makefile.am @@ -1,3 +1,6 @@ +EXTRA_DIST = \ + xrdp_surface.c + AM_CPPFLAGS = \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ @@ -11,8 +14,6 @@ LIBXRDP_EXTRA_LIBS = if XRDP_DEBUG AM_CPPFLAGS += -DXRDP_DEBUG -else -AM_CPPFLAGS += -DXRDP_NODEBUG endif if XRDP_NEUTRINORDP @@ -20,6 +21,10 @@ AM_CPPFLAGS += -DXRDP_NEUTRINORDP LIBXRDP_EXTRA_LIBS += $(FREERDP_LIBS) endif +if XRDP_RFXCODEC +AM_CPPFLAGS += -DXRDP_RFXCODEC +endif + if XRDP_TJPEG AM_CPPFLAGS += -DXRDP_JPEG -DXRDP_TJPEG @TurboJpegIncDir@ AM_LDFLAGS += @TurboJpegLibDir@ diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index c3763bf5..827b1247 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -27,6 +27,8 @@ #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) +#define MAX_BITMAP_BUF_SIZE (16 * 1024) /* 16K */ + /******************************************************************************/ struct xrdp_session *EXPORT_CC libxrdp_init(tbus id, struct trans *trans) @@ -373,15 +375,15 @@ libxrdp_send_bell(struct xrdp_session *session) return 0; } - /*****************************************************************************/ int EXPORT_CC libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, int bpp, char *data, int x, int y, int cx, int cy) { - int line_size = 0; + int line_bytes = 0; int i = 0; int j = 0; + int k; int total_lines = 0; int lines_sending = 0; int Bpp = 0; @@ -389,27 +391,43 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, int bufsize = 0; int total_bufsize = 0; int num_updates = 0; + int line_pad_bytes; + int server_line_bytes; char *p_num_updates = (char *)NULL; char *p = (char *)NULL; char *q = (char *)NULL; struct stream *s = (struct stream *)NULL; struct stream *temp_s = (struct stream *)NULL; + tui32 pixel; - DEBUG(("libxrdp_send_bitmap sending bitmap")); + LLOGLN(10, ("libxrdp_send_bitmap: sending bitmap")); Bpp = (bpp + 7) / 8; - e = width % 4; - - if (e != 0) + e = (4 - width) & 3; + switch (bpp) { - e = 4 - e; + case 15: + case 16: + server_line_bytes = width * 2; + break; + case 24: + case 32: + server_line_bytes = width * 4; + break; + default: /* 8 bpp */ + server_line_bytes = width; + break; } + line_bytes = width * Bpp; + line_pad_bytes = line_bytes + e * Bpp; - line_size = width * Bpp; + LLOGLN(10, ("libxrdp_send_bitmap: bpp %d Bpp %d line_bytes %d " + "server_line_bytes %d", bpp, Bpp, line_bytes, server_line_bytes)); make_stream(s); - init_stream(s, 8192); + init_stream(s, MAX_BITMAP_BUF_SIZE); if (session->client_info->use_bitmap_comp) { + LLOGLN(10, ("libxrdp_send_bitmap: compression")); make_stream(temp_s); init_stream(temp_s, 65536); i = 0; @@ -421,6 +439,8 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, while (i > 0) { + LLOGLN(10, ("libxrdp_send_bitmap: i %d", i)); + total_bufsize = 0; num_updates = 0; xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); @@ -440,10 +460,26 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, } p = s->p; - lines_sending = xrdp_bitmap_compress(data, width, height, - s, bpp, - 4096 - total_bufsize, - i - 1, temp_s, e); + + if (bpp > 24) + { + LLOGLN(10, ("libxrdp_send_bitmap: 32 bpp")); + lines_sending = xrdp_bitmap32_compress(data, width, height, + s, 32, + (MAX_BITMAP_BUF_SIZE - 100) - total_bufsize, + i - 1, temp_s, e, 0x10); + LLOGLN(10, ("libxrdp_send_bitmap: i %d lines_sending %d", + i, lines_sending)); + } + else + { + lines_sending = xrdp_bitmap_compress(data, width, height, + s, bpp, + (MAX_BITMAP_BUF_SIZE - 100) - total_bufsize, + i - 1, temp_s, e); + LLOGLN(10, ("libxrdp_send_bitmap: i %d lines_sending %d", + i, lines_sending)); + } if (lines_sending == 0) { @@ -470,6 +506,7 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, out_uint16_le(s, bufsize); /* compressed size */ j = (width + e) * Bpp; j = j * lines_sending; + total_bufsize += 18; /* bytes since pop layer */ } else { @@ -481,31 +518,42 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, out_uint16_le(s, j); /* line size */ j = j * lines_sending; out_uint16_le(s, j); /* final size */ + total_bufsize += 26; /* bytes since pop layer */ } - if (j > 32768) + LLOGLN(10, ("libxrdp_send_bitmap: decompressed pixels %d " + "decompressed bytes %d compressed bytes %d", + lines_sending * (width + e), + line_pad_bytes * lines_sending, bufsize)); + + if (j > MAX_BITMAP_BUF_SIZE) { - g_writeln("error, decompressed size too big: %d bytes", j); + LLOGLN(0, ("libxrdp_send_bitmap: error, decompressed " + "size too big: %d bytes", j)); } - if (bufsize > 8192) + if (bufsize > MAX_BITMAP_BUF_SIZE) { - g_writeln("error, compressed size too big: %d bytes", bufsize); + LLOGLN(0, ("libxrdp_send_bitmap: error, compressed size " + "too big: %d bytes", bufsize)); } s->p = s->end; } - while (total_bufsize < 4096 && i > 0); + while (total_bufsize < MAX_BITMAP_BUF_SIZE && i > 0); + + LLOGLN(10, ("libxrdp_send_bitmap: num_updates %d total_bufsize %d", + num_updates, total_bufsize)); p_num_updates[0] = num_updates; p_num_updates[1] = num_updates >> 8; xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_UPDATE); - if (total_bufsize > 8192) + if (total_bufsize > MAX_BITMAP_BUF_SIZE) { - g_writeln("error, total compressed size too big: %d bytes", - total_bufsize); + LLOGLN(0, ("libxrdp_send_bitmap: error, total compressed " + "size too big: %d bytes", total_bufsize)); } } @@ -513,22 +561,30 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, } else { + LLOGLN(10, ("libxrdp_send_bitmap: no compression")); total_lines = height; i = 0; p = data; - if (line_size > 0 && total_lines > 0) + if (line_bytes > 0 && total_lines > 0) { while (i < total_lines) { - lines_sending = 4096 / (line_size + e * Bpp); + + lines_sending = (MAX_BITMAP_BUF_SIZE - 100) / line_pad_bytes; if (i + lines_sending > total_lines) { lines_sending = total_lines - i; } - p = p + line_size * lines_sending; + if (lines_sending == 0) + { + LLOGLN(0, ("libxrdp_send_bitmap: error, lines_sending == zero")); + break; + } + + p += server_line_bytes * lines_sending; xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); out_uint16_le(s, RDP_UPDATE_BITMAP); out_uint16_le(s, 1); /* num updates */ @@ -540,14 +596,58 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, out_uint16_le(s, lines_sending); out_uint16_le(s, bpp); /* bpp */ out_uint16_le(s, 0); /* compress */ - out_uint16_le(s, (line_size + e * Bpp) * lines_sending); /* bufsize */ + out_uint16_le(s, line_pad_bytes * lines_sending); /* bufsize */ q = p; - for (j = 0; j < lines_sending; j++) + switch (bpp) { - q = q - line_size; - out_uint8a(s, q, line_size); /* B_ENDIAN doesn't work here, todo */ - out_uint8s(s, e * Bpp); + case 8: + for (j = 0; j < lines_sending; j++) + { + q = q - line_bytes; + out_uint8a(s, q, line_bytes); + out_uint8s(s, e); + } + break; + case 15: + case 16: + for (j = 0; j < lines_sending; j++) + { + q = q - server_line_bytes; + for (k = 0; k < width; k++) + { + pixel = *((tui16*)(q + k * 2)); + out_uint16_le(s, pixel); + } + out_uint8s(s, e * 2); + } + break; + case 24: + for (j = 0; j < lines_sending; j++) + { + q = q - server_line_bytes; + for (k = 0; k < width; k++) + { + pixel = *((tui32*)(q + k * 4)); + out_uint8(s, pixel); + out_uint8(s, pixel >> 8); + out_uint8(s, pixel >> 16); + } + out_uint8s(s, e * 3); + } + break; + case 32: + for (j = 0; j < lines_sending; j++) + { + q = q - server_line_bytes; + for (k = 0; k < width; k++) + { + pixel = *((int*)(q + k * 4)); + out_uint32_le(s, pixel); + } + out_uint8s(s, e * 4); + } + break; } s_mark_end(s); @@ -1142,7 +1242,7 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id, if (xrdp_channel_send(chan, s, channel_id, total_data_len, flags) != 0) { - g_writeln("Debug - data NOT sent to channel"); + g_writeln("libxrdp_send_to_channel: error, server channel data NOT sent to client channel"); free_stream(s); return 1; } @@ -1332,13 +1432,13 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session, 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 */ + /* TS_SURFCMD_STREAM_SURF_BITS */ + out_uint16_le(s, CMDTYPE_STREAM_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 */ + /* TS_BITMAP_DATA_EX */ out_uint8(s, bpp); out_uint8(s, 0); out_uint8(s, 0); diff --git a/libxrdp/xrdp_bitmap32_compress.c b/libxrdp/xrdp_bitmap32_compress.c index 083c4409..daec9f28 100644 --- a/libxrdp/xrdp_bitmap32_compress.c +++ b/libxrdp/xrdp_bitmap32_compress.c @@ -107,7 +107,7 @@ fsplit3(char *in_data, int start_line, int width, int e, } start_line--; cy++; - if (out_index > 64 * 64) + if (out_index + width + e > 64 * 64) { break; } @@ -195,7 +195,7 @@ fsplit4(char *in_data, int start_line, int width, int e, } start_line--; cy++; - if (out_index > 64 * 64) + if (out_index + width + e > 64 * 64) { break; } @@ -422,6 +422,7 @@ xrdp_bitmap32_compress(char *in_data, int width, int height, char *sr_data; char *sg_data; char *sb_data; + char *hold_p; int a_bytes; int r_bytes; int g_bytes; @@ -449,6 +450,7 @@ xrdp_bitmap32_compress(char *in_data, int width, int height, r_data = a_data + max_bytes; g_data = r_data + max_bytes; b_data = g_data + max_bytes; + hold_p = s->p; if (header & FLAGS_NOALPHA) { @@ -459,35 +461,44 @@ xrdp_bitmap32_compress(char *in_data, int width, int height, 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) + while (cy > 0) { - /* 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); + s->p = hold_p; + 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); + max_bytes = cx * cy * 3; + total_bytes = r_bytes + g_bytes + b_bytes; + if (total_bytes > max_bytes) + { + if (2 + max_bytes <= byte_limit) + { + s->p = hold_p; + foutraw3(s, cx * cy, FLAGS_NOALPHA, sr_data, sg_data, sb_data); + break; + } + } + if (1 + total_bytes <= byte_limit) + { + break; + } + cy--; } } else { - foutraw3(s, cx * cy, FLAGS_NOALPHA, sr_data, sg_data, sb_data); + while (cy > 0) + { + max_bytes = cx * cy * 3; + if (2 + max_bytes <= byte_limit) + { + s->p = hold_p; + foutraw3(s, cx * cy, FLAGS_NOALPHA, sr_data, sg_data, sb_data); + break; + } + cy--; + } } } else @@ -500,36 +511,45 @@ xrdp_bitmap32_compress(char *in_data, int width, int height, 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) + while (cy > 0) { - /* 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); + s->p = hold_p; + 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 (total_bytes > max_bytes) + { + if (2 + max_bytes <= byte_limit) + { + s->p = hold_p; + foutraw4(s, cx * cy, 0, sa_data, sr_data, sg_data, sb_data); + break; + } + } + if (1 + total_bytes <= byte_limit) + { + break; + } + cy--; } } else { - foutraw4(s, cx * cy, 0, sa_data, sr_data, sg_data, sb_data); + while (cy > 0) + { + max_bytes = cx * cy * 4; + if (2 + max_bytes <= byte_limit) + { + s->p = hold_p; + foutraw4(s, cx * cy, 0, sa_data, sr_data, sg_data, sb_data); + break; + } + cy--; + } } } return cy; diff --git a/libxrdp/xrdp_bitmap_compress.c b/libxrdp/xrdp_bitmap_compress.c index 03c56f10..56898776 100644 --- a/libxrdp/xrdp_bitmap_compress.c +++ b/libxrdp/xrdp_bitmap_compress.c @@ -22,6 +22,8 @@ #include "libxrdp.h" +#define BC_MAX_BYTES (16 * 1024) + /*****************************************************************************/ #define IN_PIXEL8(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \ do { \ @@ -695,7 +697,7 @@ xrdp_bitmap_compress(char *in_data, int width, int height, out_count = end; line = in_data + width * start_line; - while (start_line >= 0 && out_count < 32768) + while (start_line >= 0 && out_count <= BC_MAX_BYTES) { i = (s->p - s->data) + count; @@ -987,7 +989,7 @@ xrdp_bitmap_compress(char *in_data, int width, int height, out_count = end * 2; line = in_data + width * start_line * 2; - while (start_line >= 0 && out_count < 32768) + while (start_line >= 0 && out_count <= BC_MAX_BYTES) { i = (s->p - s->data) + count * 2; @@ -1279,7 +1281,7 @@ xrdp_bitmap_compress(char *in_data, int width, int height, out_count = end * 3; line = in_data + width * start_line * 4; - while (start_line >= 0 && out_count < 32768) + while (start_line >= 0 && out_count <= BC_MAX_BYTES) { i = (s->p - s->data) + count * 3; diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index 9dfe6fef..c4ec7b02 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -74,8 +74,13 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s, g_writeln("xrdp_caps_process_general: error"); return 1; } - in_uint8s(s, 10); - in_uint16_le(s, extraFlags); + + in_uint16_le(s, self->client_info.client_os_major); /* osMajorType (2 bytes) */ + in_uint16_le(s, self->client_info.client_os_minor); /* osMinorType (2 bytes) */ + in_uint8s(s, 6); + in_uint16_le(s, extraFlags); /* extraFlags (2 bytes) */ + + self->client_info.op1 = extraFlags & NO_BITMAP_COMPRESSION_HDR; /* 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 */ @@ -155,6 +160,15 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, DEBUG(("desktop cache size %d", i)); in_uint8s(s, 4); /* Unknown */ in_uint8s(s, 4); /* Unknown */ + + /* check if libpainter should be used for drawing, instead of orders */ + if (!(order_caps[TS_NEG_DSTBLT_INDEX] && order_caps[TS_NEG_PATBLT_INDEX] && + order_caps[TS_NEG_SCRBLT_INDEX] && order_caps[TS_NEG_MEMBLT_INDEX])) + { + g_writeln("xrdp_caps_process_order: not enough orders supported by client, using painter."); + self->client_info.no_orders_supported = 1; + } + return 0; } @@ -453,7 +467,7 @@ xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len) if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) { - g_writeln("xrdp_caps_process_codecs: nscodec codec id %d prop len %d", + g_writeln("xrdp_caps_process_codecs: nscodec, codec id %d, properties len %d", codec_id, codec_properties_length); self->client_info.ns_codec_id = codec_id; i1 = MIN(64, codec_properties_length); @@ -462,7 +476,7 @@ xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len) } 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", + g_writeln("xrdp_caps_process_codecs: RemoteFX, codec id %d, properties len %d", codec_id, codec_properties_length); self->client_info.rfx_codec_id = codec_id; i1 = MIN(64, codec_properties_length); @@ -471,7 +485,7 @@ xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len) } 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", + g_writeln("xrdp_caps_process_codecs: jpeg, codec id %d, properties len %d", codec_id, codec_properties_length); self->client_info.jpeg_codec_id = codec_id; i1 = MIN(64, codec_properties_length); @@ -488,7 +502,7 @@ xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len) } else if (g_memcmp(codec_guid, XR_CODEC_GUID_H264, 16) == 0) { - g_writeln("xrdp_caps_process_codecs: h264 codec id %d prop len %d", + g_writeln("xrdp_caps_process_codecs: h264, codec id %d, properties len %d", codec_id, codec_properties_length); self->client_info.h264_codec_id = codec_id; i1 = MIN(64, codec_properties_length); @@ -525,11 +539,29 @@ xrdp_caps_process_frame_ack(struct xrdp_rdp *self, struct stream *s, int len) g_writeln("xrdp_caps_process_frame_ack:"); self->client_info.use_frame_acks = 1; in_uint32_le(s, self->client_info.max_unacknowledged_frame_count); + if (self->client_info.max_unacknowledged_frame_count < 0) + { + g_writeln(" invalid max_unacknowledged_frame_count value (%d), setting to 0", + self->client_info.max_unacknowledged_frame_count); + self->client_info.max_unacknowledged_frame_count = 0; + } g_writeln(" max_unacknowledged_frame_count %d", self->client_info.max_unacknowledged_frame_count); return 0; } /*****************************************************************************/ +static int APP_CC +xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len) +{ + int cmdFlags; + g_writeln("xrdp_caps_process_surface_cmds:"); + in_uint32_le(s, cmdFlags); + in_uint8s(s, 4); /* reserved */ + g_writeln(" cmdFlags 0x%08x", cmdFlags); + return 0; +} + +/*****************************************************************************/ int APP_CC xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) { @@ -655,6 +687,9 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) case 0x001E: /* CAPSSETTYPE_FRAME_ACKNOWLEDGE */ xrdp_caps_process_frame_ack(self, s, len); break; + case RDP_CAPSET_SURFCMDS: /* CAPSETTYPE_SURFACE_COMMANDS */ + xrdp_caps_process_surface_cmds(self, s, len); + break; default: g_writeln("unknown in xrdp_caps_process_confirm_active %d", type); break; @@ -663,6 +698,17 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) s->p = p + len + 4; } + if (self->client_info.no_orders_supported && + (self->client_info.offscreen_support_level != 0)) + { + g_writeln("xrdp_caps_process_confirm_active: not enough orders " + "supported by client, client wants off screen bitmap but " + "offscreen bitmaps disabled"); + self->client_info.offscreen_support_level = 0; + self->client_info.offscreen_cache_size = 0; + self->client_info.offscreen_cache_entries = 0; + } + DEBUG(("out xrdp_caps_process_confirm_active")); return 0; } @@ -823,22 +869,30 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) 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_uint16_le(s, 3); /* codecPropertiesLength */ out_uint8(s, 0x01); /* fAllowDynamicFidelity */ out_uint8(s, 0x01); /* fAllowSubsampling */ out_uint8(s, 0x03); /* colorLossLevel */ +#if defined(XRDP_RFXCODEC) || defined(XRDP_NEUTRINORDP) /* 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); + out_uint16_le(s, 4); /* codecPropertiesLength */ + out_uint32_le(s, 0); /* reserved */ + /* image remotefx */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_IMAGE_REMOTEFX, 16); + out_uint8(s, 0); /* codec id, client sets */ + out_uint16_le(s, 4); /* codecPropertiesLength */ + out_uint32_le(s, 0); /* reserved */ +#endif /* 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); + out_uint16_le(s, 1); /* codecPropertiesLength */ + out_uint8(s, 75); /* jpeg compression ratio */ /* 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 */ @@ -866,16 +920,10 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) 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; + flags = INPUT_FLAG_SCANCODES | INPUT_FLAG_MOUSEX | INPUT_FLAG_UNICODE; if (self->client_info.use_fast_path & 2) { - /* 0x0008 INPUT_FLAG_FASTPATH_INPUT */ - /* 0x0020 INPUT_FLAG_FASTPATH_INPUT2 */ - flags |= 0x0008 | 0x0020; + flags |= INPUT_FLAG_FASTPATH_INPUT | INPUT_FLAG_FASTPATH_INPUT2; } out_uint16_le(s, flags); out_uint8s(s, 82); @@ -901,19 +949,29 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint16_le(s, 5); out_uint8(s, 0); /* client sets */ - if (self->client_info.use_fast_path & 1) /* fastpath output on */ + if (self->client_info.use_fast_path & FASTPATH_OUTPUT_SUPPORTED) /* fastpath output on */ { + /* multifragment update */ caps_count++; - out_uint16_le(s, 0x001A); /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */ - out_uint16_le(s, 8); + out_uint16_le(s, RDP_CAPSET_MULTIFRAGMENT); /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */ + out_uint16_le(s, RDP_CAPLEN_MULTIFRAGMENT); out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */ - } - /* frame acks */ - caps_count++; - out_uint16_le(s, 0x001E); /* CAPSETTYPE_FRAME_ACKNOWLEDGE */ - out_uint16_le(s, 8); - out_uint32_le(s, 2); /* 2 frames in flight */ + /* frame acks */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_FRAME_ACKNOWLEDGE); /* CAPSETTYPE_FRAME_ACKNOWLEDGE */ + out_uint16_le(s, RDP_CAPLEN_FRAME_ACKNOWLEDGE); + out_uint32_le(s, 2); /* 2 frames in flight */ + + /* surface commands */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_SURFCMDS); /* CAPSETTYPE_SURFACE_COMMANDS */ + out_uint16_le(s, RDP_CAPLEN_SURFCMDS); /* lengthCapability */ + out_uint32_le(s, (SURFCMDS_SETSURFACEBITS | + SURFCMDS_FRAMEMARKER | + SURFCMDS_STREAMSUFRACEBITS)); /* cmdFlags */ + out_uint32_le(s, 0); /* reserved */ + } out_uint8s(s, 4); /* pad */ diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index 008c8289..33e9c9d0 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -265,12 +265,30 @@ static 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; + int flags; + int code; + + flags = 0; + if (!s_check_rem(s, 2)) + { + return 1; + } + in_uint16_le(s, code); /* unicode (2 byte) */ + 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; + } + xrdp_fastpath_session_callback(self, RDP_INPUT_UNICODE, + code, 0, flags, 0); + return 0; } /*****************************************************************************/ diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c index fa7a3f1a..b89e1616 100644 --- a/libxrdp/xrdp_iso.c +++ b/libxrdp/xrdp_iso.c @@ -20,6 +20,7 @@ */ #include "libxrdp.h" +#include "log.h" #define LOG_LEVEL 1 #define LLOG(_level, _args) \ @@ -97,7 +98,9 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self) case PROTOCOL_HYBRID: case PROTOCOL_HYBRID_EX: default: - if (self->requestedProtocol & PROTOCOL_SSL) + if ((self->requestedProtocol & PROTOCOL_SSL) && + g_file_exist(client_info->certificate) && + g_file_exist(client_info->key_file)) { /* that's a patch since we don't support CredSSP for now */ self->selectedProtocol = PROTOCOL_SSL; @@ -109,8 +112,8 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self) break; } - LLOGLN(10, ("xrdp_iso_negotiate_security: server security layer %d , client security layer %d", - self->selectedProtocol, self->requestedProtocol)); + log_message(LOG_LEVEL_DEBUG, "Security layer: requested %d, selected %d", + self->requestedProtocol, self->selectedProtocol); return rv; } diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c index 27c31639..d337af1b 100644 --- a/libxrdp/xrdp_jpeg_compress.c +++ b/libxrdp/xrdp_jpeg_compress.c @@ -28,6 +28,7 @@ #include <stdlib.h> #include <string.h> #include <turbojpeg.h> +#include "log.h" /*****************************************************************************/ int APP_CC @@ -81,10 +82,13 @@ xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, *dst32 = pixel; dst32++; } - for (i = 0; i < e; i++) + if (width > 0) { - *dst32 = pixel; - dst32++; + for (i = 0; i < e; i++) + { + *dst32 = pixel; + dst32++; + } } } src_buf = (unsigned char *) temp_buf; @@ -93,6 +97,13 @@ xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, error = tjCompress(tj_han, src_buf, width + e, (width + e) * 4, height, TJPF_XBGR, dst_buf, &cdata_bytes, TJSAMP_420, quality, 0); + if (error != 0) + { + log_message(LOG_LEVEL_ERROR, + "xrdp_jpeg_compress: tjCompress error: %s", + tjGetErrorStr()); + } + s->p += cdata_bytes; g_free(temp_buf); return height; @@ -160,17 +171,24 @@ xrdp_codec_jpeg_compress(void *handle, * TJPF_ARGB no works, zero bytes */ error = tjCompress(tj_han, /* opaque handle */ - src_ptr, /* source buf */ + (unsigned char *) src_ptr, /* source buf */ cx, /* width of area to compress */ stride, /* pitch */ cy, /* height of area to compress */ TJPF_XBGR, /* pixel size */ - out_data, /* dest buf */ + (unsigned char *) out_data, /* dest buf */ &lio_len, /* inner_buf length & compressed_size */ TJSAMP_420, /* jpeg sub sample */ quality, /* jpeg quality */ 0 /* flags */ ); + if (error != 0) + { + log_message(LOG_LEVEL_ERROR, + "xrdp_codec_jpeg_compress: tjCompress error: %s", + tjGetErrorStr()); + } + *io_len = lio_len; return height; } @@ -213,7 +231,7 @@ xrdp_jpeg_deinit(void *handle) struct mydata_comp { - char *cb; + JOCTET *cb; int cb_bytes; int total_done; int overwrite; @@ -265,8 +283,8 @@ my_term_destination(j_compress_ptr cinfo) /*****************************************************************************/ static int APP_CC -jp_do_compress(char *data, int width, int height, int bpp, int quality, - char *comp_data, int *comp_data_bytes) +jp_do_compress(JOCTET *data, int width, int height, int bpp, int quality, + JOCTET *comp_data, int *comp_data_bytes) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; @@ -336,9 +354,8 @@ jpeg_compress(char *in_data, int width, int height, struct stream *s, struct stream *temp_s, int bpp, int byte_limit, int e, int quality) { - char *data; + JOCTET *data; tui32 *src32; - tui16 *src16; tui8 *dst8; tui32 pixel; int red; @@ -348,7 +365,7 @@ jpeg_compress(char *in_data, int width, int height, int i; int cdata_bytes; - data = temp_s->data; + data = (JOCTET *) temp_s->data; dst8 = data; if (bpp == 24) @@ -366,11 +383,14 @@ jpeg_compress(char *in_data, int width, int height, *(dst8++) = red; } - for (i = 0; i < e; i++) + if (width > 0) { - *(dst8++) = blue; - *(dst8++) = green; - *(dst8++) = red; + for (i = 0; i < e; i++) + { + *(dst8++) = blue; + *(dst8++) = green; + *(dst8++) = red; + } } } } @@ -380,7 +400,8 @@ jpeg_compress(char *in_data, int width, int height, } cdata_bytes = byte_limit; - jp_do_compress(data, width + e, height, 24, quality, s->p, &cdata_bytes); + jp_do_compress(data, width + e, height, 24, quality, (JOCTET *) s->p, + &cdata_bytes); s->p += cdata_bytes; return cdata_bytes; } diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 18a5ad38..b0c28ed8 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -2235,6 +2235,11 @@ xrdp_orders_send_raw_bitmap(struct xrdp_orders *self, Bpp = (bpp + 7) / 8; bufsize = (width + e) * height * Bpp; + while (bufsize + 16 > MAX_ORDERS_SIZE) + { + height--; + bufsize = (width + e) * height * Bpp; + } if (xrdp_orders_check(self, bufsize + 16) != 0) { return 1; @@ -2254,33 +2259,58 @@ xrdp_orders_send_raw_bitmap(struct xrdp_orders *self, out_uint16_le(self->out_s, bufsize); out_uint16_le(self->out_s, cache_idx); - for (i = height - 1; i >= 0; i--) + if (Bpp == 4) { - for (j = 0; j < width; j++) + for (i = height - 1; i >= 0; i--) { - if (Bpp == 3) + for (j = 0; j < width; j++) { pixel = GETPIXEL32(data, j, i, width); out_uint8(self->out_s, pixel); out_uint8(self->out_s, pixel >> 8); out_uint8(self->out_s, pixel >> 16); + out_uint8(self->out_s, pixel >> 24); } - else if (Bpp == 2) + out_uint8s(self->out_s, Bpp * e); + } + } + else if (Bpp == 3) + { + for (i = height - 1; i >= 0; i--) + { + for (j = 0; j < width; j++) { - pixel = GETPIXEL16(data, j, i, width); + pixel = GETPIXEL32(data, j, i, width); out_uint8(self->out_s, pixel); out_uint8(self->out_s, pixel >> 8); + out_uint8(self->out_s, pixel >> 16); } - else if (Bpp == 1) + out_uint8s(self->out_s, Bpp * e); + } + } + else if (Bpp == 2) + { + for (i = height - 1; i >= 0; i--) + { + for (j = 0; j < width; j++) { - pixel = GETPIXEL8(data, j, i, width); + pixel = GETPIXEL16(data, j, i, width); out_uint8(self->out_s, pixel); + out_uint8(self->out_s, pixel >> 8); } + out_uint8s(self->out_s, Bpp * e); } - - for (j = 0; j < e; j++) + } + else if (Bpp == 1) + { + for (i = height - 1; i >= 0; i--) { - out_uint8s(self->out_s, Bpp); + for (j = 0; j < width; j++) + { + pixel = GETPIXEL8(data, j, i, width); + out_uint8(self->out_s, pixel); + } + out_uint8s(self->out_s, Bpp * e); } } @@ -2334,20 +2364,19 @@ xrdp_orders_send_bitmap(struct xrdp_orders *self, if (bpp > 24) { lines_sending = xrdp_bitmap32_compress(data, width, height, s, - bpp, 16384, + bpp, MAX_ORDERS_SIZE, i - 1, temp_s, e, 0x10); } else { - lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, + lines_sending = xrdp_bitmap_compress(data, width, height, s, + bpp, MAX_ORDERS_SIZE, i - 1, temp_s, e); } if (lines_sending != height) { - g_writeln("error in xrdp_orders_send_bitmap, lines_sending(%d) != \ -height(%d)", lines_sending, height); - return 1; + height = lines_sending; } bufsize = (int)(s->p - p); @@ -2458,6 +2487,7 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self, int pixel = 0; int e = 0; + g_writeln("xrdp_orders_send_raw_bitmap2:"); if (width > 64) { g_writeln("error, width > 64"); @@ -2479,6 +2509,11 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self, Bpp = (bpp + 7) / 8; bufsize = (width + e) * height * Bpp; + while (bufsize + 14 > MAX_ORDERS_SIZE) + { + height--; + bufsize = (width + e) * height * Bpp; + } if (xrdp_orders_check(self, bufsize + 14) != 0) { return 1; @@ -2499,7 +2534,7 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self, i = cache_idx & 0xff; out_uint8(self->out_s, i); - if (1 && Bpp == 3) + if (Bpp == 4) { for (i = height - 1; i >= 0; i--) { @@ -2509,44 +2544,49 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self, out_uint8(self->out_s, pixel); out_uint8(self->out_s, pixel >> 8); out_uint8(self->out_s, pixel >> 16); + out_uint8(self->out_s, pixel >> 24); } - for (j = 0; j < e; j++) - { - out_uint8s(self->out_s, Bpp); - } + out_uint8s(self->out_s, Bpp * e); } } - else - { - for (i = height - 1; i >= 0; i--) + else if (Bpp == 3) { - for (j = 0; j < width; j++) + for (i = height - 1; i >= 0; i--) { - if (Bpp == 3) + for (j = 0; j < width; j++) { pixel = GETPIXEL32(data, j, i, width); out_uint8(self->out_s, pixel); out_uint8(self->out_s, pixel >> 8); out_uint8(self->out_s, pixel >> 16); } - else if (Bpp == 2) + out_uint8s(self->out_s, Bpp * e); + } + } + else if (Bpp == 2) + { + for (i = height - 1; i >= 0; i--) + { + for (j = 0; j < width; j++) { pixel = GETPIXEL16(data, j, i, width); out_uint8(self->out_s, pixel); out_uint8(self->out_s, pixel >> 8); } - else if (Bpp == 1) + out_uint8s(self->out_s, Bpp * e); + } + } + else if (Bpp == 1) + { + for (i = height - 1; i >= 0; i--) + { + for (j = 0; j < width; j++) { pixel = GETPIXEL8(data, j, i, width); out_uint8(self->out_s, pixel); } + out_uint8s(self->out_s, Bpp * e); } - - for (j = 0; j < e; j++) - { - out_uint8s(self->out_s, Bpp); - } - } } return 0; @@ -2599,20 +2639,19 @@ xrdp_orders_send_bitmap2(struct xrdp_orders *self, if (bpp > 24) { lines_sending = xrdp_bitmap32_compress(data, width, height, s, - bpp, 16384, + bpp, MAX_ORDERS_SIZE, i - 1, temp_s, e, 0x10); } else { - lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, + lines_sending = xrdp_bitmap_compress(data, width, height, s, + bpp, MAX_ORDERS_SIZE, i - 1, temp_s, e); } if (lines_sending != height) { - g_writeln("error in xrdp_orders_send_bitmap2, lines_sending(%d) != \ -height(%d)", lines_sending, height); - return 1; + height = lines_sending; } bufsize = (int)(s->p - p); diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 1520cb37..ca82df70 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -105,8 +105,8 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) } else if (g_strcasecmp(item, "allow_channels") == 0) { - client_info->channel_code = g_text2bool(value); - if (client_info->channel_code == 0) + client_info->channels_allowed = g_text2bool(value); + if (client_info->channels_allowed == 0) { log_message(LOG_LEVEL_DEBUG,"Info - All channels are disabled"); } @@ -182,10 +182,15 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) { client_info->security_layer = PROTOCOL_SSL | PROTOCOL_HYBRID; } + else if (g_strcasecmp(value, "negotiate") == 0) + { + client_info->security_layer = PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_HYBRID_EX; + } else { - log_message(LOG_LEVEL_ALWAYS,"Warning: Your configured security layer is " - "undefined, xrdp will negotiate client compatible"); + log_message(LOG_LEVEL_ERROR, "security_layer=%s is not " + "recognized, will use security_layer=negotiate", + value); client_info->security_layer = PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_HYBRID_EX; } } @@ -777,9 +782,9 @@ xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) return 1; } out_uint16_le(s, RDP_UPDATE_SYNCHRONIZE); + out_uint16_le(s, 0); /* pad */ } - out_uint16_le(s, 0); /* pad */ s_mark_end(s); if (self->client_info.use_fast_path & 1) /* fastpath output supported */ diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 06813d25..422acfe2 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -1829,12 +1829,12 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) client_info = &(self->rdp_layer->client_info); - DEBUG(("processing channels, channel_code is %d", client_info->channel_code)); + DEBUG(("processing channels, channels_allowed is %d", client_info->channels_allowed)); /* this is an option set in xrdp.ini */ - if (client_info->channel_code != 1) /* are channels on? */ + if (client_info->channels_allowed != 1) /* are channels on? */ { - g_writeln("Processing channel data from client - The channel is off"); + g_writeln("xrdp_sec_process_mcs_data_channels: all channels are disabled by configuration"); return 0; } @@ -1862,6 +1862,12 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) return 1; } in_uint8a(s, channel_item->name, 8); + if (g_strlen(channel_item->name) == 0) + { + log_message(LOG_LEVEL_WARNING, "xrdp_sec_process_mcs_data_channels: got an empty channel name, ignoring it"); + g_free(channel_item); + continue; + } 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); |