diff options
Diffstat (limited to 'libxrdp/xrdp_rdp.c')
-rw-r--r-- | libxrdp/xrdp_rdp.c | 323 |
1 files changed, 299 insertions, 24 deletions
diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index bdbeed48..53e3ddc2 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -24,6 +24,7 @@ #if defined(XRDP_FREERDP1) #include <freerdp/codec/mppc_enc.h> +#include <freerdp/codec/rfx.h> #endif /* some compilers need unsigned char to avoid warnings */ @@ -113,13 +114,25 @@ xrdp_rdp_read_config(struct xrdp_client_info* client_info) { client_info->crypt_level = 3; } + else + { + g_writeln("Warning: Your configured crypt level is" + "undefined 'high' will be used"); + client_info->crypt_level = 3; + } } else if (g_strcasecmp(item, "channel_code") == 0) { - if (g_strcasecmp(value, "1") == 0) + if ((g_strcasecmp(value, "yes") == 0) || + (g_strcasecmp(value, "1") == 0) || + (g_strcasecmp(value, "true") == 0)) { client_info->channel_code = 1; } + else + { + g_writeln("Info: All channels are disabled"); + } } else if (g_strcasecmp(item, "max_bpp") == 0) { @@ -131,11 +144,66 @@ xrdp_rdp_read_config(struct xrdp_client_info* client_info) return 0; } +#if defined(XRDP_FREERDP1) +/*****************************************************************************/ +static void +cpuid(tui32 info, tui32* eax, tui32* ebx, tui32* ecx, tui32* edx) +{ +#ifdef __GNUC__ +#if defined(__i386__) || defined(__x86_64__) + __asm volatile + ( + /* The EBX (or RBX register on x86_64) is used for the PIC base address + and must not be corrupted by our inline assembly. */ +#if defined(__i386__) + "mov %%ebx, %%esi;" + "cpuid;" + "xchg %%ebx, %%esi;" +#else + "mov %%rbx, %%rsi;" + "cpuid;" + "xchg %%rbx, %%rsi;" +#endif + : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (info) + ); +#endif +#endif +} + +/*****************************************************************************/ +static tui32 +xrdp_rdp_detect_cpu(void) +{ + tui32 eax; + tui32 ebx; + tui32 ecx; + tui32 edx; + tui32 cpu_opt; + + eax = 0; + ebx = 0; + ecx = 0; + edx = 0; + cpu_opt = 0; + cpuid(1, &eax, &ebx, &ecx, &edx); + + if (edx & (1 << 26)) + { + DEBUG("SSE2 detected"); + cpu_opt |= CPU_SSE2; + } + + return cpu_opt; +} +#endif + /*****************************************************************************/ struct xrdp_rdp* APP_CC xrdp_rdp_create(struct xrdp_session* session, struct trans* trans) { struct xrdp_rdp* self = (struct xrdp_rdp *)NULL; + int bytes; DEBUG(("in xrdp_rdp_create")); self = (struct xrdp_rdp*)g_malloc(sizeof(struct xrdp_rdp), 1); @@ -153,9 +221,13 @@ xrdp_rdp_create(struct xrdp_session* session, struct trans* trans) self->client_info.cache2_size = 1024; self->client_info.cache3_entries = 262; self->client_info.cache3_size = 4096; - g_write_ip_address(trans->sck, self->client_info.client_ip); /* load client ip info */ + /* load client ip info */ + bytes = sizeof(self->client_info.client_ip) - 1; + g_write_ip_address(trans->sck, self->client_info.client_ip, bytes); #if defined(XRDP_FREERDP1) self->mppc_enc = mppc_enc_new(PROTO_RDP_50); + self->rfx_enc = rfx_context_new(); + rfx_context_set_cpu_opt(self->rfx_enc, xrdp_rdp_detect_cpu()); #endif self->client_info.size = sizeof(self->client_info); DEBUG(("out xrdp_rdp_create")); @@ -173,6 +245,7 @@ xrdp_rdp_delete(struct xrdp_rdp* self) xrdp_sec_delete(self->sec_layer); #if defined(XRDP_FREERDP1) mppc_enc_free((struct rdp_mppc_enc*)(self->mppc_enc)); + rfx_context_free((RFX_CONTEXT*)(self->rfx_enc)); #endif g_free(self); } @@ -220,7 +293,7 @@ xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code) { s->next_packet = 0; *code = -1; - DEBUG(("out xrdp_rdp_recv")); + DEBUG(("out (1) xrdp_rdp_recv")); return 0; } if (error != 0) @@ -232,35 +305,47 @@ xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code) { if (chan > MCS_GLOBAL_CHANNEL) { - xrdp_channel_process(self->sec_layer->chan_layer, s, chan); + if(xrdp_channel_process(self->sec_layer->chan_layer, s, chan)!=0) + { + g_writeln("xrdp_channel_process returned unhandled error") ; + } + } + else + { + g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d",chan); } s->next_packet = 0; *code = 0; - DEBUG(("out xrdp_rdp_recv")); + DEBUG(("out (2) xrdp_rdp_recv")); return 0; } s->next_packet = s->p; } else { + DEBUG(("xrdp_rdp_recv stream not touched")) s->p = s->next_packet; } if (!s_check_rem(s, 6)) { s->next_packet = 0; *code = 0; - DEBUG(("out xrdp_rdp_recv")); + DEBUG(("out (3) xrdp_rdp_recv")); len = (int)(s->end - s->p); g_writeln("xrdp_rdp_recv: bad RDP packet, length [%d]", len); return 0; } - in_uint16_le(s, len); - in_uint16_le(s, pdu_code); - *code = pdu_code & 0xf; - in_uint8s(s, 2); /* mcs user id */ - s->next_packet += len; - DEBUG(("out xrdp_rdp_recv")); - return 0; + else + { + in_uint16_le(s, len); + /*g_writeln("New len received : %d next packet: %d s_end: %d",len,s->next_packet,s->end); */ + in_uint16_le(s, pdu_code); + *code = pdu_code & 0xf; + in_uint8s(s, 2); /* mcs user id */ + s->next_packet += len; + DEBUG(("out (4) xrdp_rdp_recv")); + return 0; + } } /*****************************************************************************/ @@ -318,7 +403,7 @@ xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s, if (self->client_info.rdp_compression && self->session->up_and_running) { mppc_enc = (struct rdp_mppc_enc*)(self->mppc_enc); - if (compress_rdp(mppc_enc, s->p + 18, tocomplen)) + if (compress_rdp(mppc_enc, (tui8*)(s->p + 18), tocomplen)) { DEBUG(("mppc_encode ok flags 0x%x bytes_in_opb %d historyOffset %d " "tocomplen %d", mppc_enc->flags, mppc_enc->bytes_in_opb, @@ -474,9 +559,13 @@ 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; 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); @@ -589,12 +678,48 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) out_uint8(s, 0); /* unused */ out_uint8(s, 0); /* unused */ out_uint16_le(s, 0x6a1); - out_uint8s(s, 2); /* ? */ + /* 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); @@ -617,6 +742,27 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) out_uint8(s, 1); out_uint8s(s, 83); + /* 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); @@ -664,6 +810,7 @@ xrdp_process_capset_order(struct xrdp_rdp* self, struct stream* s, { int i; char order_caps[32]; + int ex_flags; DEBUG(("order capabilities")); in_uint8s(s, 20); /* Terminal desc, pad */ @@ -694,7 +841,15 @@ xrdp_process_capset_order(struct xrdp_rdp* self, struct stream* s, g_hexdump(order_caps, 32); #endif in_uint8s(s, 2); /* Text capability flags */ - in_uint8s(s, 6); /* Pad */ + /* read extended order support flags */ + in_uint16_le(s, ex_flags); /* Ex flags */ + if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT) + { + g_writeln("xrdp_process_capset_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)); @@ -709,6 +864,7 @@ static int APP_CC xrdp_process_capset_bmpcache(struct xrdp_rdp* self, struct stream* s, int len) { + self->client_info.bitmap_cache_version |= 1; in_uint8s(s, 24); in_uint16_le(s, self->client_info.cache1_entries); in_uint16_le(s, self->client_info.cache1_size); @@ -734,16 +890,9 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp* self, struct stream* s, int Bpp = 0; int i = 0; - self->client_info.bitmap_cache_version = 2; + self->client_info.bitmap_cache_version |= 2; Bpp = (self->client_info.bpp + 7) / 8; in_uint16_le(s, i); /* cache flags */ -#if defined(XRDP_JPEG) - if (i & 0x80) - { - g_writeln("xrdp_process_capset_bmpcache2: client supports jpeg"); - self->client_info.jpeg = 1; - } -#endif self->client_info.bitmap_cache_persist_enable = i; in_uint8s(s, 2); /* number of caches in set, 3 */ in_uint32_le(s, i); @@ -769,6 +918,20 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp* self, struct stream* s, } /*****************************************************************************/ +static int +xrdp_process_capset_cache_v3_codec_id(struct xrdp_rdp* self, struct stream* s, + int len) +{ + int codec_id; + + 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, @@ -823,6 +986,106 @@ xrdp_process_offscreen_bmpcache(struct xrdp_rdp* self, struct stream* s, } /*****************************************************************************/ +static int APP_CC +xrdp_process_capset_rail(struct xrdp_rdp* self, struct stream* s, int len) +{ + int i32; + + if (len - 4 < 4) + { + g_writeln("xrdp_process_capset_rail: bad len"); + 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 < 7) + { + g_writeln("xrdp_process_capset_window: bad len"); + 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_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; + + in_uint8(s, codec_count); + for (index = 0; index < codec_count; index++) + { + codec_guid = s->p; + in_uint8s(s, 16); + in_uint8(s, codec_id); + in_uint16_le(s, 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; + } + return 0; +} + +/*****************************************************************************/ int APP_CC xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s) { @@ -867,6 +1130,9 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s) 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; @@ -912,9 +1178,18 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s) 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; |