diff --git a/NEWS.md b/NEWS.md index e496291f..7c761a5c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,29 @@ +# Release notes for xrdp v0.9.9 (2018/12/25) + +# Release cycle +From the next release, release cycle will be changed from quarterly to every +4 months. xrdp will be released in April, August, December. + +# New features +* Disconnection by idle timeout (requires xorgxrdp v0.2.9 or later) #1227 +* Glyph cache v2 (fixes no font issue on iOS/macOS/Android client) #367 #1235 + +# Bug fixes +* Fix xrdp-chansrv crashes caused in drive redirection #1202 #1225 +* Fix build with FDK AAC v2 #1257 +* Do not enable RemoteApp if the INFO_RAIL flag is not set (RDP-RDP proxy) #1253 + +# Other changes +* Add Spanish Latin Amarican keyboard #1237 #1240 #1244 +* Dynamic channel improvements #1222 #1224 +* Remove some deprecated sesman session types #1232 +* Refactoring and cleanups + +# Known issues +* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to + xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266 +* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965 + # Release notes for xrdp v0.9.8 (2018/09/25) ## Deprecation notice diff --git a/README.md b/README.md index 3f1d4a9b..fec7ee66 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/neutrinolabs/xrdp) ![Apache-License](https://img.shields.io/badge/License-Apache%202.0-blue.svg) -*Current Version:* 0.9.8 +*Current Version:* 0.9.9 # xrdp - an open source RDP server diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index e8e91da4..ca349f0a 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -154,6 +154,8 @@ struct xrdp_client_info int client_os_minor; int no_orders_supported; + int use_cache_glyph_v2; + int rail_enable; }; #endif diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index 4a6d2c27..e3ae5517 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -201,6 +201,11 @@ #define OSMINORTYPE_PSEUDO_XSERVER 0x0008 #define OSMINORTYPE_WINDOWS_RT 0x0009 +/* Window List Capability Set: WndSupportLevel (MS-RDPERP 2.2.1.1.2) */ +#define TS_WINDOW_LEVEL_NOT_SUPPORTED 0x00000000 +#define TS_WINDOW_LEVEL_SUPPORTED 0x00000001 +#define TS_WINDOW_LEVEL_SUPPORTED_EX 0x00000002 + /* Extended Info Packet: performanceFlags (MS-RDPBCGR 2.2.1.11.1.1.1) */ /* TODO: to be renamed */ #define RDP5_DISABLE_NOTHING 0x00 @@ -370,6 +375,7 @@ #define RDP_COMPRESSION 0x0080 #define RDP_LOGON_BLOB 0x0100 #define RDP_LOGON_LEAVE_AUDIO 0x2000 +#define RDP_LOGON_RAIL 0x8000 /* Compression Flags (MS-RDPBCGR 3.1.8.2.1) */ /* TODO: to be renamed, not used anywhere */ @@ -379,15 +385,14 @@ #define RDP_MPPC_DICT_SIZE 8192 /* RDP 4.0 | MS-RDPBCGR 3.1.8 */ /* Drawing Order: controlFlags (MS-RDPEGDI 2.2.2.2.1, ) */ -/* TODO: to be renamed */ -#define RDP_ORDER_STANDARD 0x01 -#define RDP_ORDER_SECONDARY 0x02 -#define RDP_ORDER_BOUNDS 0x04 -#define RDP_ORDER_CHANGE 0x08 -#define RDP_ORDER_DELTA 0x10 -#define RDP_ORDER_LASTBOUNDS 0x20 -#define RDP_ORDER_SMALL 0x40 -#define RDP_ORDER_TINY 0x80 +#define TS_STANDARD 0x01 +#define TS_SECONDARY 0x02 +#define TS_BOUNDS 0x04 +#define TS_TYPE_CHANGE 0x08 +#define TS_DELTA_COORDINATES 0x10 +#define TS_ZERO_BOUNDS_DELTAS 0x20 +#define TS_ZERO_FIELD_BYTE_BIT0 0x40 +#define TS_ZERO_FIELD_BYTE_BIT1 0x80 /* Drawing Order: orderType (MS-RDPEGDI 2.2.2.2.1.1.2) ? */ #define RDP_ORDER_DESTBLT 0 @@ -403,98 +408,94 @@ #define RDP_ORDER_COMPOSITE 37 /* 0x25 */ /* Secondary Drawing Order Header: orderType (MS-RDPEGDI 2.2.2.2.1.2.1.1) */ -/* TODO: to be renamed */ -#define RDP_ORDER_RAW_BMPCACHE 0 -#define RDP_ORDER_COLCACHE 1 -#define RDP_ORDER_BMPCACHE 2 -#define RDP_ORDER_FONTCACHE 3 -#define RDP_ORDER_RAW_BMPCACHE2 4 -#define RDP_ORDER_BMPCACHE2 5 -#define RDP_ORDER_BRUSHCACHE 7 -#define RDP_ORDER_BMPCACHE3 8 +#define TS_CACHE_BITMAP_UNCOMPRESSED 0x00 +#define TS_CACHE_COLOR_TABLE 0x01 +#define TS_CACHE_BITMAP_COMPRESSED 0x02 +#define TS_CACHE_GLYPH 0x03 +#define TS_CACHE_BITMAP_UNCOMPRESSED_REV2 0x04 +#define TS_CACHE_BITMAP_COMPRESSED_REV2 0x05 +#define TS_CACHE_BRUSH 0x07 +#define TS_CACHE_BITMAP_COMPRESSED_REV3 0x08 /* Maps to generalCapabilitySet in T.128 page 138 */ /* Capability Set: capabilitySetType (MS-RDPBCGR 2.2.1.13.1.1.1) */ -/* TODO: to be renamed */ -#define RDP_CAPSET_GENERAL 0x0001 -#define RDP_CAPLEN_GENERAL 0x18 +#define CAPSTYPE_GENERAL 0x0001 +#define CAPSTYPE_GENERAL_LEN 0x18 -#define RDP_CAPSET_BITMAP 0x0002 -#define RDP_CAPLEN_BITMAP 0x1C +#define CAPSTYPE_BITMAP 0x0002 +#define CAPSTYPE_BITMAP_LEN 0x1C -#define RDP_CAPSET_ORDER 0x0003 -#define RDP_CAPLEN_ORDER 0x58 -#define ORDER_CAP_NEGOTIATE 2 -#define ORDER_CAP_NOSUPPORT 4 +#define CAPSTYPE_ORDER 0x0003 +#define CAPSTYPE_ORDER_LEN 0x58 +#define ORDER_CAP_NEGOTIATE 2 /* NEGOTIATEORDERSUPPORT? not used */ +#define ORDER_CAP_NOSUPPORT 4 /* not used */ -#define RDP_CAPSET_BMPCACHE 0x0004 -#define RDP_CAPLEN_BMPCACHE 0x28 +#define CAPSTYPE_BITMAPCACHE 0x0004 +#define CAPSTYPE_BITMAPCACHE_LEN 0x28 -#define RDP_CAPSET_CONTROL 0x0005 -#define RDP_CAPLEN_CONTROL 0x0C +#define CAPSTYPE_CONTROL 0x0005 +#define CAPSTYPE_CONTROL_LEN 0x0C -#define RDP_CAPSET_ACTIVATE 0x0007 -#define RDP_CAPLEN_ACTIVATE 0x0C +#define CAPSTYPE_ACTIVATION 0x0007 +#define CAPSTYPE_ACTIVATION_LEN 0x0C -#define RDP_CAPSET_POINTER 0x0008 -#define RDP_CAPLEN_POINTER 0x0a -#define RDP_CAPLEN_POINTER_MONO 0x08 +#define CAPSTYPE_POINTER 0x0008 +#define CAPSTYPE_POINTER_LEN 0x0a +#define CAPSTYPE_POINTER_MONO_LEN 0x08 -#define RDP_CAPSET_SHARE 0x0009 -#define RDP_CAPLEN_SHARE 0x08 +#define CAPSTYPE_SHARE 0x0009 +#define CAPSTYPE_SHARE_LEN 0x08 -#define RDP_CAPSET_COLCACHE 0x000A -#define RDP_CAPLEN_COLCACHE 0x08 +#define CAPSTYPE_COLORCACHE 0x000A +#define CAPSTYPE_COLORCACHE_LEN 0x08 -#define RDP_CAPSET_SOUND 0x000C +#define CAPSTYPE_SOUND 0x000C -#define RDP_CAPSET_INPUT 0x000D -#define RDP_CAPLEN_INPUT 0x58 +#define CAPSTYPE_INPUT 0x000D +#define CAPSTYPE_INPUT_LEN 0x58 -#define RDP_CAPSET_FONT 0x000E -#define RDP_CAPLEN_FONT 0x04 +#define CAPSTYPE_FONT 0x000E +#define CAPSTYPE_FONT_LEN 0x04 -#define RDP_CAPSET_BRUSHCACHE 0x000F -#define RDP_CAPLEN_BRUSHCACHE 0x08 +#define CAPSTYPE_BRUSH 0x000F +#define CAPSTYPE_BRUSH_LEN 0x08 -#define RDP_CAPSET_GLYPHCACHE 0x0010 -#define RDP_CAPSET_OFFSCREENCACHE 0x0011 +#define CAPSTYPE_GLYPHCACHE 0x0010 +#define CAPSTYPE_OFFSCREENCACHE 0x0011 -#define RDP_CAPSET_BITMAP_OFFSCREEN 0x0012 -#define RDP_CAPLEN_BITMAP_OFFSCREEN 0x08 +#define CAPSTYPE_BITMAPCACHE_HOSTSUPPORT 0x0012 +#define CAPSTYPE_BITMAPCACHE_HOSTSUPPORT_LEN 0x08 -#define RDP_CAPSET_BMPCACHE2 0x0013 -#define RDP_CAPLEN_BMPCACHE2 0x28 -#define BMPCACHE2_FLAG_PERSIST ((long)1<<31) +#define CAPSTYPE_BITMAPCACHE_REV2 0x0013 +#define CAPSTYPE_BITMAPCACHE_REV2_LEN 0x28 +#define BMPCACHE2_FLAG_PERSIST ((long)1<<31) -#define RDP_CAPSET_VIRCHAN 0x0014 -#define RDP_CAPLEN_VIRCHAN 0x08 +#define CAPSTYPE_VIRTUALCHANNEL 0x0014 +#define CAPSTYPE_VIRTUALCHANNEL_LEN 0x08 -#define RDP_CAPSET_DRAWNINEGRIDCACHE 0x0015 -#define RDP_CAPSET_DRAWGDIPLUS 0x0016 -#define RDP_CAPSET_RAIL 0x0017 -#define RDP_CAPSET_WINDOW 0x0018 +#define CAPSTYPE_DRAWNINGRIDCACHE 0x0015 +#define CAPSTYPE_DRAWGDIPLUS 0x0016 +#define CAPSTYPE_RAIL 0x0017 +#define CAPSTYPE_WINDOW 0x0018 -#define RDP_CAPSET_COMPDESK 0x0019 -#define RDP_CAPLEN_COMPDESK 0x06 +#define CAPSSETTYPE_COMPDESK 0x0019 +#define CAPSSETTYPE_COMPDESK_LEN 0x06 -#define RDP_CAPSET_MULTIFRAGMENT 0x001A -#define RDP_CAPLEN_MULTIFRAGMENT 0x08 +#define CAPSSETTYPE_MULTIFRAGMENTUPDATE 0x001A +#define CAPSSETTYPE_MULTIFRAGMENTUPDATE_LEN 0x08 -#define RDP_CAPSET_LPOINTER 0x001B -#define RDP_CAPLEN_LPOINTER 0x06 +#define CAPSETTYPE_LARGE_POINTER 0x001B +#define CAPSETTYPE_LARGE_POINTER_LEN 0x06 -#define RDP_CAPSET_FRAME_ACKNOWLEDGE 0x001E -#define RDP_CAPLEN_FRAME_ACKNOWLEDGE 0x08 - -#define RDP_CAPSET_SURFCMDS 0x001C -#define RDP_CAPLEN_SURFCMDS 0x0C - -#define RDP_CAPSET_BMPCODECS 0x001D -#define RDP_CAPLEN_BMPCODECS 0x1C +#define CAPSETTYPE_SURFACE_COMMANDS 0x001C +#define CAPSETTYPE_SURFACE_COMMANDS_LEN 0x0C +#define CAPSSETTYPE_BITMAP_CODECS 0x001D +#define CAPSSETTYPE_BITMAP_CODECS_LEN 0x1C +#define CAPSTYPE_FRAME_ACKNOWLEDGE 0x001E +#define CAPSTYPE_FRAME_ACKNOWLEDGE_LEN 0x08 /* TS_SECURITY_HEADER: flags (MS-RDPBCGR 2.2.8.1.1.2.1) */ /* TODO: to be renamed */ @@ -588,6 +589,12 @@ #define KBD_FLAG_CAPITAL 0x0004 #define TS_SYNC_KANA_LOCK 0x0008 +/* Glyph Cache Capability Set: GlyphSupportLevel (MS-RDPBCGR 2.2.7.1.8) */ +#define GLYPH_SUPPORT_NONE 0x0000 +#define GLYPH_SUPPORT_PARTIAL 0x0001 +#define GLYPH_SUPPORT_FULL 0x0002 +#define GLYPH_SUPPORT_ENCODE 0x0003 + /****************************************************************************** * * Constants come from other Microsoft products @@ -664,12 +671,12 @@ #define LICENCE_SIGNATURE_SIZE 16 -/* RDP PDU codes */ -#define RDP_PDU_DEMAND_ACTIVE 1 -#define RDP_PDU_CONFIRM_ACTIVE 3 -#define RDP_PDU_REDIRECT 4 -#define RDP_PDU_DEACTIVATE 6 -#define RDP_PDU_DATA 7 +/* PDU Types (MS-RDPBCGR 2.2.8.1.1.1.1) */ +#define PDUTYPE_DEMANDACTIVEPDU 0x1 +#define PDUTYPE_CONFIRMACTIVEPDU 0x3 +#define PDUTYPE_DEACTIVATEALLPDU 0x6 +#define PDUTYPE_DATAPDU 0x7 +#define PDUTYPE_SERVER_REDIR_PKT 0xA /* See T.128 */ /* not used anywhere */ diff --git a/configure.ac b/configure.ac index 3aa14db6..4dbcf230 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # Process this file with autoconf to produce a configure script AC_PREREQ(2.65) -AC_INIT([xrdp], [0.9.8], [xrdp-devel@googlegroups.com]) +AC_INIT([xrdp], [0.9.9], [xrdp-devel@googlegroups.com]) AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in) AM_INIT_AUTOMAKE([1.7.2 foreign]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/docs/man/sesman.ini.5.in b/docs/man/sesman.ini.5.in index 4fad8eb4..2074985c 100644 --- a/docs/man/sesman.ini.5.in +++ b/docs/man/sesman.ini.5.in @@ -139,6 +139,13 @@ within 60 seconds after the user disconnects. Sets the time limit (in seconds) before a disconnected session is killed. If set to \fI0\fR, automatic killing is disabled. +.TP +\fBIdleTimeLimit\fR=\fInumber\fR +Sets the time limit (in seconds) before an idle session is disconnected. +Idle means no keyboard inputs and no mouse moves/clicks here. +If set to \fI0\fR, idle sessions will never be disconnected by timeout. +This works only with xorgxrdp session. Moreover, xorgxrdp must be v0.2.9 or later. + .TP \fBPolicy\fR=\fI[Default|UBD|UBI|UBC|UBDI|UBDC]\fR Session allocation policy. By default, a new session is created diff --git a/instfiles/Makefile.am b/instfiles/Makefile.am index cc7e1446..e393bb5f 100644 --- a/instfiles/Makefile.am +++ b/instfiles/Makefile.am @@ -45,6 +45,7 @@ dist_startscript_DATA = \ km-0000041d.ini \ km-00000807.ini \ km-00000809.ini \ + km-0000080a.ini \ km-0000080c.ini \ km-00000813.ini \ km-00000816.ini \ diff --git a/instfiles/km-0000080a.ini b/instfiles/km-0000080a.ini new file mode 100644 index 00000000..314fc8ae --- /dev/null +++ b/instfiles/km-0000080a.ini @@ -0,0 +1,1055 @@ +[noshift] +Key8=65406:0 +Key9=65307:27 +Key10=49:49 +Key11=50:50 +Key12=51:51 +Key13=52:52 +Key14=53:53 +Key15=54:54 +Key16=55:55 +Key17=56:56 +Key18=57:57 +Key19=48:48 +Key20=39:39 +Key21=191:191 +Key22=65288:8 +Key23=65289:9 +Key24=113:113 +Key25=119:119 +Key26=101:101 +Key27=114:114 +Key28=116:116 +Key29=121:121 +Key30=117:117 +Key31=105:105 +Key32=111:111 +Key33=112:112 +Key34=65105:180 +Key35=43:43 +Key36=65293:13 +Key37=65507:0 +Key38=97:97 +Key39=115:115 +Key40=100:100 +Key41=102:102 +Key42=103:103 +Key43=104:104 +Key44=106:106 +Key45=107:107 +Key46=108:108 +Key47=241:241 +Key48=123:123 +Key49=124:124 +Key50=65505:0 +Key51=125:125 +Key52=122:122 +Key53=120:120 +Key54=99:99 +Key55=118:118 +Key56=98:98 +Key57=110:110 +Key58=109:109 +Key59=44:44 +Key60=46:46 +Key61=45:45 +Key62=65506:0 +Key63=65450:42 +Key64=65513:0 +Key65=32:32 +Key66=65509:0 +Key67=65470:0 +Key68=65471:0 +Key69=65472:0 +Key70=65473:0 +Key71=65474:0 +Key72=65475:0 +Key73=65476:0 +Key74=65477:0 +Key75=65478:0 +Key76=65479:0 +Key77=65407:0 +Key78=65300:0 +Key79=65429:0 +Key80=65431:0 +Key81=65434:0 +Key82=65453:45 +Key83=65430:0 +Key84=65437:0 +Key85=65432:0 +Key86=65451:43 +Key87=65436:0 +Key88=65433:0 +Key89=65435:0 +Key90=65438:0 +Key91=65439:0 +Key92=65377:0 +Key93=0:0 +Key94=60:60 +Key95=65480:0 +Key96=65481:0 +Key97=65360:0 +Key98=65362:0 +Key99=65365:0 +Key100=65361:0 +Key101=0:0 +Key102=65363:0 +Key103=65367:0 +Key104=65364:0 +Key105=65366:0 +Key106=65379:0 +Key107=65535:127 +Key108=65421:13 +Key109=65508:0 +Key110=65299:0 +Key111=65377:0 +Key112=65455:47 +Key113=65027:0 +Key114=269025049:0 +Key115=65515:0 +Key116=65516:0 +Key117=0:0 +Key118=269025153:0 +Key119=269025093:0 +Key120=269025094:0 +Key121=269025095:0 +Key122=269025096:0 +Key123=0:0 +Key124=65027:0 +Key125=0:0 +Key126=65469:61 +Key127=0:0 +Key128=0:0 +Key129=0:0 +Key130=0:0 +Key131=0:0 +Key132=0:0 +Key133=0:0 +Key134=0:0 +Key135=0:0 +Key136=0:0 +Key137=0:0 + +[shift] +Key8=65406:0 +Key9=65307:27 +Key10=33:33 +Key11=34:34 +Key12=35:35 +Key13=36:36 +Key14=37:37 +Key15=38:38 +Key16=47:47 +Key17=40:40 +Key18=41:41 +Key19=61:61 +Key20=63:63 +Key21=161:161 +Key22=65288:8 +Key23=65056:0 +Key24=81:81 +Key25=87:87 +Key26=69:69 +Key27=82:82 +Key28=84:84 +Key29=89:89 +Key30=85:85 +Key31=73:73 +Key32=79:79 +Key33=80:80 +Key34=65111:168 +Key35=42:42 +Key36=65293:13 +Key37=65507:0 +Key38=65:65 +Key39=83:83 +Key40=68:68 +Key41=70:70 +Key42=71:71 +Key43=72:72 +Key44=74:74 +Key45=75:75 +Key46=76:76 +Key47=209:209 +Key48=91:91 +Key49=176:176 +Key50=65505:0 +Key51=93:93 +Key52=90:90 +Key53=88:88 +Key54=67:67 +Key55=86:86 +Key56=66:66 +Key57=78:78 +Key58=77:77 +Key59=59:59 +Key60=58:58 +Key61=95:95 +Key62=65506:0 +Key63=65450:42 +Key64=65511:0 +Key65=32:32 +Key66=65509:0 +Key67=65470:0 +Key68=65471:0 +Key69=65472:0 +Key70=65473:0 +Key71=65474:0 +Key72=65475:0 +Key73=65476:0 +Key74=65477:0 +Key75=65478:0 +Key76=65479:0 +Key77=65407:0 +Key78=65300:0 +Key79=65463:55 +Key80=65464:56 +Key81=65465:57 +Key82=65453:45 +Key83=65460:52 +Key84=65461:53 +Key85=65462:54 +Key86=65451:43 +Key87=65457:49 +Key88=65458:50 +Key89=65459:51 +Key90=65456:48 +Key91=65454:46 +Key92=65377:0 +Key93=0:0 +Key94=62:62 +Key95=65480:0 +Key96=65481:0 +Key97=65360:0 +Key98=65362:0 +Key99=65365:0 +Key100=65361:0 +Key101=0:0 +Key102=65363:0 +Key103=65367:0 +Key104=65364:0 +Key105=65366:0 +Key106=65379:0 +Key107=65535:127 +Key108=65421:13 +Key109=65508:0 +Key110=65299:0 +Key111=65377:0 +Key112=65455:47 +Key113=65027:0 +Key114=269025049:0 +Key115=65515:0 +Key116=65516:0 +Key117=0:0 +Key118=269025153:0 +Key119=269025093:0 +Key120=269025094:0 +Key121=269025095:0 +Key122=269025096:0 +Key123=0:0 +Key124=65027:0 +Key125=65513:0 +Key126=65469:61 +Key127=65515:0 +Key128=65517:0 +Key129=0:0 +Key130=0:0 +Key131=0:0 +Key132=0:0 +Key133=0:0 +Key134=0:0 +Key135=0:0 +Key136=0:0 +Key137=0:0 + +[altgr] +Key8=65406:0 +Key9=65307:27 +Key10=124:124 +Key11=64:64 +Key12=183:183 +Key13=126:126 +Key14=189:189 +Key15=172:172 +Key16=123:123 +Key17=91:91 +Key18=93:93 +Key19=125:125 +Key20=92:92 +Key21=65115:184 +Key22=0:0 +Key23=65289:9 +Key24=64:64 +Key25=435:322 +Key26=8364:8364 +Key27=182:182 +Key28=956:359 +Key29=2299:8592 +Key30=2302:8595 +Key31=2301:8594 +Key32=248:248 +Key33=254:254 +Key34=65111:168 +Key35=65107:126 +Key36=65293:13 +Key37=65507:0 +Key38=230:230 +Key39=223:223 +Key40=240:240 +Key41=496:273 +Key42=959:331 +Key43=689:295 +Key44=65121:0 +Key45=930:312 +Key46=435:322 +Key47=126:126 +Key48=65106:94 +Key49=172:172 +Key50=65505:0 +Key51=65104:96 +Key52=171:171 +Key53=187:187 +Key54=162:162 +Key55=2770:8220 +Key56=2771:8221 +Key57=110:110 +Key58=181:181 +Key59=2211:0 +Key60=183:183 +Key61=65120:0 +Key62=65506:0 +Key63=65450:42 +Key64=65513:0 +Key65=32:32 +Key66=65509:0 +Key67=65470:0 +Key68=65471:0 +Key69=65472:0 +Key70=65473:0 +Key71=65474:0 +Key72=65475:0 +Key73=65476:0 +Key74=65477:0 +Key75=65478:0 +Key76=65479:0 +Key77=65407:0 +Key78=65300:0 +Key79=65429:0 +Key80=65431:0 +Key81=65434:0 +Key82=65453:45 +Key83=65430:0 +Key84=65437:0 +Key85=65432:0 +Key86=65451:43 +Key87=65436:0 +Key88=65433:0 +Key89=65435:0 +Key90=65438:0 +Key91=65439:0 +Key92=65377:0 +Key93=0:0 +Key94=124:124 +Key95=65480:0 +Key96=65481:0 +Key97=65360:0 +Key98=65362:0 +Key99=65365:0 +Key100=65361:0 +Key101=0:0 +Key102=65363:0 +Key103=65367:0 +Key104=65364:0 +Key105=65366:0 +Key106=65379:0 +Key107=65535:127 +Key108=65421:13 +Key109=65508:0 +Key110=65299:0 +Key111=65377:0 +Key112=65455:47 +Key113=65027:0 +Key114=269025049:0 +Key115=65515:0 +Key116=65516:0 +Key117=0:0 +Key118=269025153:0 +Key119=269025093:0 +Key120=269025094:0 +Key121=269025095:0 +Key122=269025096:0 +Key123=0:0 +Key124=65027:0 +Key125=0:0 +Key126=65469:61 +Key127=0:0 +Key128=0:0 +Key129=0:0 +Key130=0:0 +Key131=0:0 +Key132=0:0 +Key133=0:0 +Key134=0:0 +Key135=0:0 +Key136=0:0 +Key137=0:0 + +[shiftaltgr] +Key8=65406:0 +Key9=65307:27 +Key10=161:161 +Key11=2755:8539 +Key12=163:163 +Key13=36:36 +Key14=2756:8540 +Key15=2757:8541 +Key16=2758:8542 +Key17=2761:8482 +Key18=177:177 +Key19=176:176 +Key20=191:191 +Key21=65116:731 +Key22=0:0 +Key23=65056:0 +Key24=2009:937 +Key25=419:321 +Key26=162:162 +Key27=174:174 +Key28=940:358 +Key29=165:165 +Key30=2300:8593 +Key31=697:305 +Key32=216:216 +Key33=222:222 +Key34=65112:176 +Key35=65108:175 +Key36=65293:13 +Key37=65507:0 +Key38=198:198 +Key39=167:167 +Key40=208:208 +Key41=170:170 +Key42=957:330 +Key43=673:294 +Key44=65122:0 +Key45=38:38 +Key46=419:321 +Key47=65113:733 +Key48=123:123 +Key49=172:172 +Key50=65505:0 +Key51=125:125 +Key52=60:60 +Key53=62:62 +Key54=169:169 +Key55=2768:8216 +Key56=2769:8217 +Key57=78:78 +Key58=186:186 +Key59=215:215 +Key60=247:247 +Key61=65110:729 +Key62=65506:0 +Key63=65450:42 +Key64=65511:0 +Key65=32:32 +Key66=65509:0 +Key67=65470:0 +Key68=65471:0 +Key69=65472:0 +Key70=65473:0 +Key71=65474:0 +Key72=65475:0 +Key73=65476:0 +Key74=65477:0 +Key75=65478:0 +Key76=65479:0 +Key77=65407:0 +Key78=65300:0 +Key79=65463:55 +Key80=65464:56 +Key81=65465:57 +Key82=65453:45 +Key83=65460:52 +Key84=65461:53 +Key85=65462:54 +Key86=65451:43 +Key87=65457:49 +Key88=65458:50 +Key89=65459:51 +Key90=65456:48 +Key91=65454:46 +Key92=65377:0 +Key93=0:0 +Key94=166:166 +Key95=65480:0 +Key96=65481:0 +Key97=65360:0 +Key98=65362:0 +Key99=65365:0 +Key100=65361:0 +Key101=0:0 +Key102=65363:0 +Key103=65367:0 +Key104=65364:0 +Key105=65366:0 +Key106=65379:0 +Key107=65535:127 +Key108=65421:13 +Key109=65508:0 +Key110=65299:0 +Key111=65377:0 +Key112=65455:47 +Key113=65027:0 +Key114=269025049:0 +Key115=65515:0 +Key116=65516:0 +Key117=0:0 +Key118=269025153:0 +Key119=269025093:0 +Key120=269025094:0 +Key121=269025095:0 +Key122=269025096:0 +Key123=0:0 +Key124=65027:0 +Key125=65513:0 +Key126=65469:61 +Key127=65515:0 +Key128=65517:0 +Key129=0:0 +Key130=0:0 +Key131=0:0 +Key132=0:0 +Key133=0:0 +Key134=0:0 +Key135=0:0 +Key136=0:0 +Key137=0:0 + +[capslock] +Key8=65406:0 +Key9=65307:27 +Key10=49:49 +Key11=50:50 +Key12=51:51 +Key13=52:52 +Key14=53:53 +Key15=54:54 +Key16=55:55 +Key17=56:56 +Key18=57:57 +Key19=48:48 +Key20=39:39 +Key21=191:191 +Key22=65288:8 +Key23=65289:9 +Key24=81:81 +Key25=87:87 +Key26=69:69 +Key27=82:82 +Key28=84:84 +Key29=89:89 +Key30=85:85 +Key31=73:73 +Key32=79:79 +Key33=80:80 +Key34=65105:180 +Key35=43:43 +Key36=65293:13 +Key37=65507:0 +Key38=65:65 +Key39=83:83 +Key40=68:68 +Key41=70:70 +Key42=71:71 +Key43=72:72 +Key44=74:74 +Key45=75:75 +Key46=76:76 +Key47=209:209 +Key48=123:123 +Key49=124:124 +Key50=65505:0 +Key51=125:125 +Key52=90:90 +Key53=88:88 +Key54=67:67 +Key55=86:86 +Key56=66:66 +Key57=78:78 +Key58=77:77 +Key59=44:44 +Key60=46:46 +Key61=45:45 +Key62=65506:0 +Key63=65450:42 +Key64=65513:0 +Key65=32:32 +Key66=65509:0 +Key67=65470:0 +Key68=65471:0 +Key69=65472:0 +Key70=65473:0 +Key71=65474:0 +Key72=65475:0 +Key73=65476:0 +Key74=65477:0 +Key75=65478:0 +Key76=65479:0 +Key77=65407:0 +Key78=65300:0 +Key79=65429:0 +Key80=65431:0 +Key81=65434:0 +Key82=65453:45 +Key83=65430:0 +Key84=65437:0 +Key85=65432:0 +Key86=65451:43 +Key87=65436:0 +Key88=65433:0 +Key89=65435:0 +Key90=65438:0 +Key91=65439:0 +Key92=65377:0 +Key93=0:0 +Key94=60:60 +Key95=65480:0 +Key96=65481:0 +Key97=65360:0 +Key98=65362:0 +Key99=65365:0 +Key100=65361:0 +Key101=0:0 +Key102=65363:0 +Key103=65367:0 +Key104=65364:0 +Key105=65366:0 +Key106=65379:0 +Key107=65535:127 +Key108=65421:13 +Key109=65508:0 +Key110=65299:0 +Key111=65377:0 +Key112=65455:47 +Key113=65027:0 +Key114=269025049:0 +Key115=65515:0 +Key116=65516:0 +Key117=0:0 +Key118=269025153:0 +Key119=269025093:0 +Key120=269025094:0 +Key121=269025095:0 +Key122=269025096:0 +Key123=0:0 +Key124=65027:0 +Key125=0:0 +Key126=65469:61 +Key127=0:0 +Key128=0:0 +Key129=0:0 +Key130=0:0 +Key131=0:0 +Key132=0:0 +Key133=0:0 +Key134=0:0 +Key135=0:0 +Key136=0:0 +Key137=0:0 + +[capslockaltgr] +Key8=65406:0 +Key9=65307:27 +Key10=124:124 +Key11=64:64 +Key12=183:183 +Key13=126:126 +Key14=189:189 +Key15=172:172 +Key16=123:123 +Key17=91:91 +Key18=93:93 +Key19=125:125 +Key20=92:92 +Key21=65115:184 +Key22=0:0 +Key23=65289:9 +Key24=64:64 +Key25=419:321 +Key26=8364:8364 +Key27=182:182 +Key28=940:358 +Key29=2299:8592 +Key30=2302:8595 +Key31=2301:8594 +Key32=216:216 +Key33=222:222 +Key34=65111:168 +Key35=65107:126 +Key36=65293:13 +Key37=65507:0 +Key38=198:198 +Key39=223:223 +Key40=208:208 +Key41=464:272 +Key42=957:330 +Key43=673:294 +Key44=65121:0 +Key45=930:312 +Key46=419:321 +Key47=126:126 +Key48=65106:94 +Key49=172:172 +Key50=65505:0 +Key51=65104:96 +Key52=171:171 +Key53=187:187 +Key54=162:162 +Key55=2770:8220 +Key56=2771:8221 +Key57=78:78 +Key58=924:0 +Key59=2211:0 +Key60=183:183 +Key61=65120:0 +Key62=65506:0 +Key63=65450:42 +Key64=65513:0 +Key65=32:32 +Key66=65509:0 +Key67=65470:0 +Key68=65471:0 +Key69=65472:0 +Key70=65473:0 +Key71=65474:0 +Key72=65475:0 +Key73=65476:0 +Key74=65477:0 +Key75=65478:0 +Key76=65479:0 +Key77=65407:0 +Key78=65300:0 +Key79=65429:0 +Key80=65431:0 +Key81=65434:0 +Key82=65453:45 +Key83=65430:0 +Key84=65437:0 +Key85=65432:0 +Key86=65451:43 +Key87=65436:0 +Key88=65433:0 +Key89=65435:0 +Key90=65438:0 +Key91=65439:0 +Key92=65377:0 +Key93=0:0 +Key94=124:124 +Key95=65480:0 +Key96=65481:0 +Key97=65360:0 +Key98=65362:0 +Key99=65365:0 +Key100=65361:0 +Key101=0:0 +Key102=65363:0 +Key103=65367:0 +Key104=65364:0 +Key105=65366:0 +Key106=65379:0 +Key107=65535:127 +Key108=65421:13 +Key109=65508:0 +Key110=65299:0 +Key111=65377:0 +Key112=65455:47 +Key113=65027:0 +Key114=269025049:0 +Key115=65515:0 +Key116=65516:0 +Key117=0:0 +Key118=269025153:0 +Key119=269025093:0 +Key120=269025094:0 +Key121=269025095:0 +Key122=269025096:0 +Key123=0:0 +Key124=65027:0 +Key125=0:0 +Key126=65469:61 +Key127=0:0 +Key128=0:0 +Key129=0:0 +Key130=0:0 +Key131=0:0 +Key132=0:0 +Key133=0:0 +Key134=0:0 +Key135=0:0 +Key136=0:0 +Key137=0:0 + +[shiftcapslock] +Key8=65406:0 +Key9=65307:27 +Key10=33:33 +Key11=34:34 +Key12=35:35 +Key13=36:36 +Key14=37:37 +Key15=38:38 +Key16=47:47 +Key17=40:40 +Key18=41:41 +Key19=61:61 +Key20=63:63 +Key21=161:161 +Key22=65288:8 +Key23=65056:0 +Key24=113:113 +Key25=119:119 +Key26=101:101 +Key27=114:114 +Key28=116:116 +Key29=121:121 +Key30=117:117 +Key31=105:105 +Key32=111:111 +Key33=112:112 +Key34=65111:168 +Key35=42:42 +Key36=65293:13 +Key37=65507:0 +Key38=97:97 +Key39=115:115 +Key40=100:100 +Key41=102:102 +Key42=103:103 +Key43=104:104 +Key44=106:106 +Key45=107:107 +Key46=108:108 +Key47=241:241 +Key48=91:91 +Key49=176:176 +Key50=65505:0 +Key51=93:93 +Key52=122:122 +Key53=120:120 +Key54=99:99 +Key55=118:118 +Key56=98:98 +Key57=110:110 +Key58=109:109 +Key59=59:59 +Key60=58:58 +Key61=95:95 +Key62=65506:0 +Key63=65450:42 +Key64=65511:0 +Key65=32:32 +Key66=65509:0 +Key67=65470:0 +Key68=65471:0 +Key69=65472:0 +Key70=65473:0 +Key71=65474:0 +Key72=65475:0 +Key73=65476:0 +Key74=65477:0 +Key75=65478:0 +Key76=65479:0 +Key77=65407:0 +Key78=65300:0 +Key79=65463:55 +Key80=65464:56 +Key81=65465:57 +Key82=65453:45 +Key83=65460:52 +Key84=65461:53 +Key85=65462:54 +Key86=65451:43 +Key87=65457:49 +Key88=65458:50 +Key89=65459:51 +Key90=65456:48 +Key91=65454:46 +Key92=65377:0 +Key93=0:0 +Key94=62:62 +Key95=65480:0 +Key96=65481:0 +Key97=65360:0 +Key98=65362:0 +Key99=65365:0 +Key100=65361:0 +Key101=0:0 +Key102=65363:0 +Key103=65367:0 +Key104=65364:0 +Key105=65366:0 +Key106=65379:0 +Key107=65535:127 +Key108=65421:13 +Key109=65508:0 +Key110=65299:0 +Key111=65377:0 +Key112=65455:47 +Key113=65027:0 +Key114=269025049:0 +Key115=65515:0 +Key116=65516:0 +Key117=0:0 +Key118=269025153:0 +Key119=269025093:0 +Key120=269025094:0 +Key121=269025095:0 +Key122=269025096:0 +Key123=0:0 +Key124=65027:0 +Key125=65513:0 +Key126=65469:61 +Key127=65515:0 +Key128=65517:0 +Key129=0:0 +Key130=0:0 +Key131=0:0 +Key132=0:0 +Key133=0:0 +Key134=0:0 +Key135=0:0 +Key136=0:0 +Key137=0:0 + +[shiftcapslockaltgr] +Key8=65406:0 +Key9=65307:27 +Key10=161:161 +Key11=2755:8539 +Key12=163:163 +Key13=36:36 +Key14=2756:8540 +Key15=2757:8541 +Key16=2758:8542 +Key17=2761:8482 +Key18=177:177 +Key19=176:176 +Key20=191:191 +Key21=65116:731 +Key22=0:0 +Key23=65056:0 +Key24=2009:937 +Key25=435:322 +Key26=162:162 +Key27=174:174 +Key28=956:359 +Key29=165:165 +Key30=2300:8593 +Key31=697:305 +Key32=248:248 +Key33=254:254 +Key34=65112:176 +Key35=65108:175 +Key36=65293:13 +Key37=65507:0 +Key38=230:230 +Key39=167:167 +Key40=240:240 +Key41=170:170 +Key42=959:331 +Key43=689:295 +Key44=65122:0 +Key45=38:38 +Key46=435:322 +Key47=65113:733 +Key48=123:123 +Key49=172:172 +Key50=65505:0 +Key51=125:125 +Key52=60:60 +Key53=62:62 +Key54=169:169 +Key55=2768:8216 +Key56=2769:8217 +Key57=110:110 +Key58=186:186 +Key59=215:215 +Key60=247:247 +Key61=65110:729 +Key62=65506:0 +Key63=65450:42 +Key64=65511:0 +Key65=32:32 +Key66=65509:0 +Key67=65470:0 +Key68=65471:0 +Key69=65472:0 +Key70=65473:0 +Key71=65474:0 +Key72=65475:0 +Key73=65476:0 +Key74=65477:0 +Key75=65478:0 +Key76=65479:0 +Key77=65407:0 +Key78=65300:0 +Key79=65463:55 +Key80=65464:56 +Key81=65465:57 +Key82=65453:45 +Key83=65460:52 +Key84=65461:53 +Key85=65462:54 +Key86=65451:43 +Key87=65457:49 +Key88=65458:50 +Key89=65459:51 +Key90=65456:48 +Key91=65454:46 +Key92=65377:0 +Key93=0:0 +Key94=166:166 +Key95=65480:0 +Key96=65481:0 +Key97=65360:0 +Key98=65362:0 +Key99=65365:0 +Key100=65361:0 +Key101=0:0 +Key102=65363:0 +Key103=65367:0 +Key104=65364:0 +Key105=65366:0 +Key106=65379:0 +Key107=65535:127 +Key108=65421:13 +Key109=65508:0 +Key110=65299:0 +Key111=65377:0 +Key112=65455:47 +Key113=65027:0 +Key114=269025049:0 +Key115=65515:0 +Key116=65516:0 +Key117=0:0 +Key118=269025153:0 +Key119=269025093:0 +Key120=269025094:0 +Key121=269025095:0 +Key122=269025096:0 +Key123=0:0 +Key124=65027:0 +Key125=65513:0 +Key126=65469:61 +Key127=65515:0 +Key128=65517:0 +Key129=0:0 +Key130=0:0 +Key131=0:0 +Key132=0:0 +Key133=0:0 +Key134=0:0 +Key135=0:0 +Key136=0:0 +Key137=0:0 diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index 99da37f8..f82ae953 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -230,10 +230,10 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) case 0: dead_lock_counter++; break; - case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ + case PDUTYPE_CONFIRMACTIVEPDU: xrdp_caps_process_confirm_active(rdp, s); break; - case RDP_PDU_DATA: /* 7 */ + case PDUTYPE_DATAPDU: if (xrdp_rdp_process_data(rdp, s) != 0) { DEBUG(("libxrdp_process_data returned non zero")); @@ -1263,6 +1263,93 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id, return 0; } +/*****************************************************************************/ +int +libxrdp_disable_channel(struct xrdp_session *session, int channel_id, + int is_disabled) +{ + struct xrdp_rdp *rdp; + struct xrdp_mcs *mcs; + struct mcs_channel_item *channel_item; + + rdp = (struct xrdp_rdp *) (session->rdp); + mcs = rdp->sec_layer->mcs_layer; + if (mcs->channel_list == NULL) + { + return 1; + } + channel_item = (struct mcs_channel_item *) + list_get_item(mcs->channel_list, channel_id); + if (channel_item == NULL) + { + return 1; + } + channel_item->disabled = is_disabled; + return 1; +} + +/*****************************************************************************/ +int +libxrdp_drdynvc_open(struct xrdp_session *session, const char *name, + int flags, struct xrdp_drdynvc_procs *procs, + int *chan_id) +{ + struct xrdp_rdp *rdp; + struct xrdp_sec *sec; + struct xrdp_channel *chan; + + rdp = (struct xrdp_rdp *) (session->rdp); + sec = rdp->sec_layer; + chan = sec->chan_layer; + return xrdp_channel_drdynvc_open(chan, name, flags, procs, chan_id); +} + +/*****************************************************************************/ +int +libxrdp_drdynvc_close(struct xrdp_session *session, int chan_id) +{ + struct xrdp_rdp *rdp; + struct xrdp_sec *sec; + struct xrdp_channel *chan; + + rdp = (struct xrdp_rdp *) (session->rdp); + sec = rdp->sec_layer; + chan = sec->chan_layer; + return xrdp_channel_drdynvc_close(chan, chan_id); +} + +/*****************************************************************************/ +int +libxrdp_drdynvc_data_first(struct xrdp_session *session, int chan_id, + const char *data, int data_bytes, + int total_data_bytes) +{ + struct xrdp_rdp *rdp; + struct xrdp_sec *sec; + struct xrdp_channel *chan; + + rdp = (struct xrdp_rdp *) (session->rdp); + sec = rdp->sec_layer; + chan = sec->chan_layer; + return xrdp_channel_drdynvc_data_first(chan, chan_id, data, data_bytes, + total_data_bytes); +} + +/*****************************************************************************/ +int +libxrdp_drdynvc_data(struct xrdp_session *session, int chan_id, + const char *data, int data_bytes) +{ + struct xrdp_rdp *rdp; + struct xrdp_sec *sec; + struct xrdp_channel *chan; + + rdp = (struct xrdp_rdp *) (session->rdp); + sec = rdp->sec_layer; + chan = sec->chan_layer; + return xrdp_channel_drdynvc_data(chan, chan_id, data, data_bytes); +} + /*****************************************************************************/ int EXPORT_CC libxrdp_orders_send_brush(struct xrdp_session *session, diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index 0ac5f635..98c8f030 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -51,6 +51,8 @@ struct mcs_channel_item char name[16]; int flags; int chanid; + int disabled; + int pad0; }; /* mcs */ @@ -128,11 +130,27 @@ struct xrdp_sec int is_security_header_present; /* boolean */ }; +struct xrdp_drdynvc +{ + int chan_id; + int status; /* see XRDP_DRDYNVC_STATUS_* */ + int flags; + int pad0; + int (*open_response)(intptr_t id, int chan_id, int creation_status); + int (*close_response)(intptr_t id, int chan_id); + int (*data_first)(intptr_t id, int chan_id, char *data, int bytes, int total_bytes); + int (*data)(intptr_t id, int chan_id, char *data, int bytes); +}; + /* channel */ struct xrdp_channel { struct xrdp_sec *sec_layer; struct xrdp_mcs *mcs_layer; + int drdynvc_channel_id; + int drdynvc_state; + struct stream *s; + struct xrdp_drdynvc drdynvcs[256]; }; /* rdp */ @@ -285,7 +303,6 @@ struct xrdp_mppc_enc tui16 *hash_table; }; - int compress_rdp(struct xrdp_mppc_enc *enc, tui8 *srcData, int len); struct xrdp_mppc_enc * @@ -553,6 +570,21 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id, int xrdp_channel_process(struct xrdp_channel *self, struct stream *s, int chanid); +int +xrdp_channel_drdynvc_start(struct xrdp_channel *self); +int +xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name, + int flags, struct xrdp_drdynvc_procs *procs, + int *chan_id); +int +xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id); +int +xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id, + const char *data, int data_bytes, + int total_data_bytes); +int +xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id, + const char *data, int data_bytes); /* xrdp_fastpath.c */ struct xrdp_fastpath * diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index 38bd4b34..c236bec9 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -76,6 +76,14 @@ struct xrdp_session struct source_info si; }; +struct xrdp_drdynvc_procs +{ + int (*open_response)(intptr_t id, int chan_id, int creation_status); + int (*close_response)(intptr_t id, int chan_id); + int (*data_first)(intptr_t id, int chan_id, char *data, int bytes, int total_bytes); + int (*data)(intptr_t id, int chan_id, char *data, int bytes); +}; + struct xrdp_session * libxrdp_init(tbus id, struct trans *trans); int @@ -195,6 +203,22 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id, char *data, int data_len, int total_data_len, int flags); int +libxrdp_disable_channel(struct xrdp_session *session, int channel_id, + int is_disabled); +int +libxrdp_drdynvc_open(struct xrdp_session *session, const char *name, + int flags, struct xrdp_drdynvc_procs *procs, + int *chan_id); +int +libxrdp_drdynvc_close(struct xrdp_session *session, int chan_id); +int +libxrdp_drdynvc_data_first(struct xrdp_session *session, int chan_id, + const char *data, int data_bytes, + int total_data_bytes); +int +libxrdp_drdynvc_data(struct xrdp_session *session, int chan_id, + const char *data, int data_bytes); +int libxrdp_orders_send_brush(struct xrdp_session *session, int width, int height, int bpp, int type, int size, char *data, int cache_id); diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index dddf6d23..4d1ab45f 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -360,6 +360,33 @@ xrdp_caps_process_brushcache(struct xrdp_rdp *self, struct stream *s, return 0; } +/*****************************************************************************/ +static int +xrdp_caps_process_glyphcache(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int glyph_support_level; + + if (len < 40 + 4 + 2 + 2) /* MS-RDPBCGR 2.2.7.1.8 */ + { + g_writeln("xrdp_caps_process_glyphcache: error"); + return 1; + } + + in_uint8s(s, 40); /* glyph cache */ + in_uint8s(s, 4); /* frag cache */ + in_uint16_le(s, glyph_support_level); + in_uint8s(s, 2); /* pad */ + + if (glyph_support_level == GLYPH_SUPPORT_ENCODE) + { + self->client_info.use_cache_glyph_v2 = 1; + } + g_writeln("xrdp_caps_process_glyphcache: support level %d ", + glyph_support_level); + return 0; +} + /*****************************************************************************/ int xrdp_caps_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s, @@ -610,88 +637,89 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) len -= 4; switch (type) { - case RDP_CAPSET_GENERAL: - DEBUG(("RDP_CAPSET_GENERAL")); + case CAPSTYPE_GENERAL: + DEBUG(("CAPSTYPE_GENERAL")); xrdp_caps_process_general(self, s, len); break; - case RDP_CAPSET_BITMAP: - DEBUG(("RDP_CAPSET_BITMAP")); + case CAPSTYPE_BITMAP: + DEBUG(("CAPSTYPE_BITMAP")); break; - case RDP_CAPSET_ORDER: - DEBUG(("RDP_CAPSET_ORDER")); + case CAPSTYPE_ORDER: + DEBUG(("CAPSTYPE_ORDER")); xrdp_caps_process_order(self, s, len); break; - case RDP_CAPSET_BMPCACHE: - DEBUG(("RDP_CAPSET_BMPCACHE")); + case CAPSTYPE_BITMAPCACHE: + DEBUG(("CAPSTYPE_BMPCACHE")); xrdp_caps_process_bmpcache(self, s, len); break; - case RDP_CAPSET_CONTROL: - DEBUG(("RDP_CAPSET_CONTROL")); + case CAPSTYPE_CONTROL: + DEBUG(("CAPSTYPE_CONTROL")); break; case 6: xrdp_caps_process_cache_v3_codec_id(self, s, len); break; - case RDP_CAPSET_ACTIVATE: - DEBUG(("RDP_CAPSET_ACTIVATE")); + case CAPSTYPE_ACTIVATION: + DEBUG(("CAPSTYPE_ACTIVAION")); break; - case RDP_CAPSET_POINTER: - DEBUG(("RDP_CAPSET_POINTER")); + case CAPSTYPE_POINTER: + DEBUG(("CAPSTYPE_POINTER")); xrdp_caps_process_pointer(self, s, len); break; - case RDP_CAPSET_SHARE: - DEBUG(("RDP_CAPSET_SHARE")); + case CAPSTYPE_SHARE: + DEBUG(("CAPSTYPE_SHARE")); break; - case RDP_CAPSET_COLCACHE: - DEBUG(("RDP_CAPSET_COLCACHE")); + case CAPSTYPE_COLORCACHE: + DEBUG(("CAPSTYPE_COLORCACHE")); break; - case RDP_CAPSET_SOUND: - DEBUG(("--0x0C")); + case CAPSTYPE_SOUND: + DEBUG(("CAPSTYPE_SOUND")); break; - case RDP_CAPSET_INPUT: + case CAPSTYPE_INPUT: xrdp_caps_process_input(self, s, len); break; - case RDP_CAPSET_FONT: - DEBUG(("--0x0D")); + case CAPSTYPE_FONT: + DEBUG(("CAPSTYPE_FONT")); break; - case RDP_CAPSET_BRUSHCACHE: + case CAPSTYPE_BRUSH: xrdp_caps_process_brushcache(self, s, len); break; - case RDP_CAPSET_GLYPHCACHE: - DEBUG(("--0x11")); + case CAPSTYPE_GLYPHCACHE: + DEBUG(("CAPSTYPE_GLYPHCACHE")); + xrdp_caps_process_glyphcache(self, s, len); break; - case RDP_CAPSET_OFFSCREENCACHE: - DEBUG(("CAPSET_TYPE_OFFSCREEN_CACHE")); + case CAPSTYPE_OFFSCREENCACHE: + DEBUG(("CAPSTYPE_OFFSCREENCACHE")); xrdp_caps_process_offscreen_bmpcache(self, s, len); break; - case RDP_CAPSET_BMPCACHE2: - DEBUG(("RDP_CAPSET_BMPCACHE2")); + case CAPSTYPE_BITMAPCACHE_REV2: + DEBUG(("CAPSTYPE_BITMAPCACHE_REV2")); xrdp_caps_process_bmpcache2(self, s, len); break; - case RDP_CAPSET_VIRCHAN: - DEBUG(("--0x14")); + case CAPSTYPE_VIRTUALCHANNEL: + DEBUG(("CAPSTYPE_VIRTUALCHANNEL")); break; - case RDP_CAPSET_DRAWNINEGRIDCACHE: - DEBUG(("--0x15")); + case CAPSTYPE_DRAWNINGRIDCACHE: + DEBUG(("CAPSTYPE_DRAWNINGRIDCACHE")); break; - case RDP_CAPSET_DRAWGDIPLUS: - DEBUG(("--0x16")); + case CAPSTYPE_DRAWGDIPLUS: + DEBUG(("CAPSTYPE_DRAWGDIPLUS")); break; - case RDP_CAPSET_RAIL: + case CAPSTYPE_RAIL: xrdp_caps_process_rail(self, s, len); break; - case RDP_CAPSET_WINDOW: + case CAPSTYPE_WINDOW: xrdp_caps_process_window(self, s, len); break; - case RDP_CAPSET_MULTIFRAGMENT: + case CAPSSETTYPE_MULTIFRAGMENTUPDATE: xrdp_caps_process_multifragmentupdate(self, s, len); break; - case RDP_CAPSET_SURFCMDS: + case CAPSETTYPE_SURFACE_COMMANDS: xrdp_caps_process_surface_cmds(self, s, len); break; - case RDP_CAPSET_BMPCODECS: + case CAPSSETTYPE_BITMAP_CODECS: xrdp_caps_process_codecs(self, s, len); break; - case RDP_CAPSET_FRAME_ACKNOWLEDGE: + case CAPSTYPE_FRAME_ACKNOWLEDGE: xrdp_caps_process_frame_ack(self, s, len); break; default: @@ -757,29 +785,27 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) /* Output share capability set */ caps_count++; - out_uint16_le(s, RDP_CAPSET_SHARE); - out_uint16_le(s, RDP_CAPLEN_SHARE); + out_uint16_le(s, CAPSTYPE_SHARE); + out_uint16_le(s, CAPSTYPE_SHARE_LEN); 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, CAPSTYPE_GENERAL); + out_uint16_le(s, CAPSTYPE_GENERAL_LEN); + out_uint16_le(s, OSMAJORTYPE_WINDOWS); + out_uint16_le(s, OSMINORTYPE_WINDOWS_NT); 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); + out_uint16_le(s, NO_BITMAP_COMPRESSION_HDR | FASTPATH_OUTPUT_SUPPORTED); } else { - out_uint16_le(s, 0x400); + out_uint16_le(s, NO_BITMAP_COMPRESSION_HDR); } out_uint16_le(s, 0); /* Update capability */ out_uint16_le(s, 0); /* Remote unshare capability */ @@ -788,8 +814,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) /* 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, CAPSTYPE_BITMAP); + out_uint16_le(s, CAPSTYPE_BITMAP_LEN); 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 */ @@ -805,13 +831,13 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) /* Output font capability set */ caps_count++; - out_uint16_le(s, RDP_CAPSET_FONT); /* 14 */ - out_uint16_le(s, RDP_CAPLEN_FONT); /* 4 */ + out_uint16_le(s, CAPSTYPE_FONT); + out_uint16_le(s, CAPSTYPE_FONT_LEN); /* Output order capability set */ caps_count++; - out_uint16_le(s, RDP_CAPSET_ORDER); /* 3 */ - out_uint16_le(s, RDP_CAPLEN_ORDER); /* 88(0x58) */ + out_uint16_le(s, CAPSTYPE_ORDER); + out_uint16_le(s, CAPSTYPE_ORDER_LEN); out_uint8s(s, 16); out_uint32_be(s, 0x40420f00); out_uint16_le(s, 1); /* Cache X granularity */ @@ -863,7 +889,7 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) /* Output bmpcodecs capability set */ caps_count++; - out_uint16_le(s, RDP_CAPSET_BMPCODECS); + out_uint16_le(s, CAPSSETTYPE_BITMAP_CODECS); codec_caps_size_ptr = s->p; out_uint8s(s, 2); /* cap len set later */ codec_caps_count = 0; @@ -899,30 +925,30 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) 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 */ + codec_caps_size += 2; /* 2 bytes for CAPSTYPE_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, CAPSTYPE_COLORCACHE); + out_uint16_le(s, CAPSTYPE_COLORCACHE_LEN); 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, CAPSTYPE_POINTER); + out_uint16_le(s, CAPSTYPE_POINTER_LEN); 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) */ + out_uint16_le(s, CAPSTYPE_INPUT); + out_uint16_le(s, CAPSTYPE_INPUT_LEN); flags = INPUT_FLAG_SCANCODES | INPUT_FLAG_MOUSEX | @@ -936,20 +962,24 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) 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 */ + if (self->client_info.rail_enable) /* MS-RDPERP 3.3.5.1.4 */ + { + /* Remote Programs Capability Set */ + caps_count++; + out_uint16_le(s, CAPSTYPE_RAIL); + out_uint16_le(s, 8); /* LengthCapability: MS-RDPERP 2.2.1.1.1 */ + out_uint32_le(s, 3); /* See: https://msdn.microsoft.com/en-us/library/cc242518.aspx + 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 */ + /* Window List Capability Set */ + caps_count++; + out_uint16_le(s, CAPSTYPE_WINDOW); + out_uint16_le(s, 11); /* LengthCapability: MS-RDPERP 2.2.1.1.2 */ + out_uint32_le(s, TS_WINDOW_LEVEL_SUPPORTED_EX); + out_uint8(s, 3); /* NumIconCaches */ + out_uint16_le(s, 12); /* NumIconCacheEntries */ + } /* 6 - bitmap cache v3 codecid */ caps_count++; @@ -961,20 +991,20 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) { /* multifragment update */ caps_count++; - out_uint16_le(s, RDP_CAPSET_MULTIFRAGMENT); /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */ - out_uint16_le(s, RDP_CAPLEN_MULTIFRAGMENT); + out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE); + out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE_LEN); out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */ /* frame acks */ caps_count++; - out_uint16_le(s, RDP_CAPSET_FRAME_ACKNOWLEDGE); /* CAPSETTYPE_FRAME_ACKNOWLEDGE */ - out_uint16_le(s, RDP_CAPLEN_FRAME_ACKNOWLEDGE); + out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE); + out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE_LEN); 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_uint16_le(s, CAPSETTYPE_SURFACE_COMMANDS); + out_uint16_le(s, CAPSETTYPE_SURFACE_COMMANDS_LEN); out_uint32_le(s, (SURFCMDS_SETSURFACEBITS | SURFCMDS_FRAMEMARKER | SURFCMDS_STREAMSUFRACEBITS)); /* cmdFlags */ @@ -994,7 +1024,7 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) 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) + if (xrdp_rdp_send(self, s, PDUTYPE_DEMANDACTIVEPDU) != 0) { free_stream(s); return 1; diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c index 4f4f3ef3..9662582e 100644 --- a/libxrdp/xrdp_channel.c +++ b/libxrdp/xrdp_channel.c @@ -31,6 +31,17 @@ #define CHANNEL_FLAG_LAST 0x02 #define CHANNEL_FLAG_SHOW_PROTOCOL 0x10 +#define CMD_DVC_OPEN_CHANNEL 0x10 +#define CMD_DVC_DATA_FIRST 0x20 +#define CMD_DVC_DATA 0x30 +#define CMD_DVC_CLOSE_CHANNEL 0x40 +#define CMD_DVC_CAPABILITY 0x50 + +#define XRDP_DRDYNVC_STATUS_CLOSED 0 +#define XRDP_DRDYNVC_STATUS_OPEN_SENT 1 +#define XRDP_DRDYNVC_STATUS_OPEN 2 +#define XRDP_DRDYNVC_STATUS_CLOSE_SENT 3 + /*****************************************************************************/ /* returns pointer or nil on error */ static struct mcs_channel_item * @@ -58,6 +69,7 @@ xrdp_channel_create(struct xrdp_sec *owner, struct xrdp_mcs *mcs_layer) self = (struct xrdp_channel *)g_malloc(sizeof(struct xrdp_channel), 1); self->sec_layer = owner; self->mcs_layer = mcs_layer; + self->drdynvc_channel_id = -1; return self; } @@ -70,7 +82,7 @@ xrdp_channel_delete(struct xrdp_channel *self) { return; } - + free_stream(self->s); g_memset(self, 0, sizeof(struct xrdp_channel)); g_free(self); } @@ -106,6 +118,12 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id, return 1; } + if (channel->disabled) + { + g_writeln("xrdp_channel_send, channel disabled"); + return 0; /* not an error */ + } + s_pop_layer(s, channel_hdr); out_uint32_le(s, total_data_len); @@ -175,6 +193,333 @@ xrdp_channel_call_callback(struct xrdp_channel *self, struct stream *s, return rv; } +/*****************************************************************************/ +static int +drdynvc_insert_uint_124(struct stream *s, uint32_t val) +{ + int ret_val; + + if (val <= 0xff) + { + out_uint8(s, val); + ret_val = 0; + } + else if (val <= 0xffff) + { + out_uint16_le(s, val); + ret_val = 1; + } + else + { + out_uint32_le(s, val); + ret_val = 2; + } + + return ret_val; +} + +/*****************************************************************************/ +static int +drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p) +{ + int cbChId; + int chan_id; + + cbChId = cmd & 0x03; + if (cbChId == 0) + { + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, chan_id); + } + else if (cbChId == 1) + { + if (!s_check_rem(s, 2)) + { + return 1; + } + in_uint16_le(s, chan_id); + } + else + { + if (!s_check_rem(s, 4)) + { + return 1; + } + in_uint32_le(s, chan_id); + } + *chan_id_p = chan_id; + return 0; +} + +/*****************************************************************************/ +static int +drdynvc_process_capability_response(struct xrdp_channel *self, + int cmd, struct stream *s) +{ + struct xrdp_session *session; + int cap_version; + int rv; + + /* skip padding */ + in_uint8s(s, 1); + /* read client's version */ + in_uint16_le(s, cap_version); + if ((cap_version != 2) && (cap_version != 3)) + { + g_writeln("drdynvc_process_capability_response: incompatible DVC " + "version %d detected", cap_version); + return 1; + } + g_writeln("drdynvc_process_capability_response: DVC version %d selected", + cap_version); + self->drdynvc_state = 1; + session = self->sec_layer->rdp_layer->session; + rv = session->callback(session->id, 0x5558, 0, 0, 0, 0); + return rv; +} + +/*****************************************************************************/ +static int +drdynvc_process_open_channel_response(struct xrdp_channel *self, + int cmd, struct stream *s) +{ + struct xrdp_session *session; + int creation_status; + uint32_t chan_id; + struct xrdp_drdynvc *drdynvc; + + if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) + { + return 1; + } + if (!s_check_rem(s, 4)) + { + return 1; + } + in_uint32_le(s, creation_status); + //g_writeln("drdynvc_process_open_channel_response: chan_id 0x%x " + // "creation_status %d", chan_id, creation_status); + session = self->sec_layer->rdp_layer->session; + if (chan_id > 255) + { + return 1; + } + drdynvc = self->drdynvcs + chan_id; + if (creation_status == 0) + { + drdynvc->status = XRDP_DRDYNVC_STATUS_OPEN; + } + else + { + drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED; + } + if (drdynvc->open_response != NULL) + { + return drdynvc->open_response(session->id, chan_id, creation_status); + } + return 0; +} + +/*****************************************************************************/ +static int +drdynvc_process_close_channel_response(struct xrdp_channel *self, + int cmd, struct stream *s) +{ + struct xrdp_session *session; + uint32_t chan_id; + struct xrdp_drdynvc *drdynvc; + + if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) + { + return 1; + } + //g_writeln("drdynvc_process_close_channel_response: chan_id 0x%x", chan_id); + session = self->sec_layer->rdp_layer->session; + if (chan_id > 255) + { + return 1; + } + drdynvc = self->drdynvcs + chan_id; + drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED; + if (drdynvc->close_response != NULL) + { + return drdynvc->close_response(session->id, chan_id); + } + return 0; +} + +/*****************************************************************************/ +static int +drdynvc_process_data_first(struct xrdp_channel *self, + int cmd, struct stream *s) +{ + struct xrdp_session *session; + uint32_t chan_id; + int len; + int bytes; + int total_bytes; + struct xrdp_drdynvc *drdynvc; + + if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) + { + return 1; + } + len = (cmd >> 2) & 0x03; + if (len == 0) + { + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, total_bytes); + } + else if (len == 1) + { + if (!s_check_rem(s, 2)) + { + return 1; + } + in_uint16_le(s, total_bytes); + } + else + { + if (!s_check_rem(s, 4)) + { + return 1; + } + in_uint32_le(s, total_bytes); + } + bytes = (int) (s->end - s->p); + //g_writeln("drdynvc_process_data_first: bytes %d total_bytes %d", bytes, total_bytes); + session = self->sec_layer->rdp_layer->session; + if (chan_id > 255) + { + return 1; + } + drdynvc = self->drdynvcs + chan_id; + if (drdynvc->data_first != NULL) + { + return drdynvc->data_first(session->id, chan_id, s->p, + bytes, total_bytes); + } + return 0; +} + +/*****************************************************************************/ +static int +drdynvc_process_data(struct xrdp_channel *self, + int cmd, struct stream *s) +{ + struct xrdp_session *session; + uint32_t chan_id; + int bytes; + struct xrdp_drdynvc *drdynvc; + + if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) + { + return 1; + } + bytes = (int) (s->end - s->p); + //g_writeln("drdynvc_process_data: bytes %d", bytes); + session = self->sec_layer->rdp_layer->session; + if (chan_id > 255) + { + return 1; + } + drdynvc = self->drdynvcs + chan_id; + if (drdynvc->data != NULL) + { + return drdynvc->data(session->id, chan_id, s->p, bytes); + } + return 0; +} + +/*****************************************************************************/ +static int +xrdp_channel_process_drdynvc(struct xrdp_channel *self, + struct mcs_channel_item *channel, + struct stream *s) +{ + int total_length; + int length; + int flags; + int cmd; + int rv; + struct stream *ls; + + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint32_le(s, total_length); + in_uint32_le(s, flags); + //g_writeln("xrdp_channel_process_drdynvc: total_length %d flags 0x%8.8x", + // total_length, flags); + ls = NULL; + switch (flags & 3) + { + case 0: + length = (int) (s->end - s->p); + out_uint8a(self->s, s->p, length); + in_uint8s(s, length); + return 0; + case 1: + free_stream(self->s); + make_stream(self->s); + init_stream(self->s, total_length); + length = (int) (s->end - s->p); + out_uint8a(self->s, s->p, length); + in_uint8s(s, length); + return 0; + case 2: + length = (int) (s->end - s->p); + out_uint8a(self->s, s->p, length); + in_uint8s(s, length); + ls = self->s; + break; + case 3: + ls = s; + break; + default: + g_writeln("xrdp_channel_process_drdynvc: error"); + return 1; + } + if (ls == NULL) + { + return 1; + } + in_uint8(ls, cmd); /* read command */ + //g_writeln("xrdp_channel_process_drdynvc: cmd 0x%x", cmd); + rv = 1; + switch (cmd & 0xf0) + { + case CMD_DVC_CAPABILITY: + rv = drdynvc_process_capability_response(self, cmd, s); + break; + case CMD_DVC_OPEN_CHANNEL: + rv = drdynvc_process_open_channel_response(self, cmd, s); + break; + case CMD_DVC_CLOSE_CHANNEL: + rv = drdynvc_process_close_channel_response(self, cmd, s); + break; + case CMD_DVC_DATA_FIRST: + rv = drdynvc_process_data_first(self, cmd, s); + break; + case CMD_DVC_DATA: + rv = drdynvc_process_data(self, cmd, s); + break; + default: + g_writeln("xrdp_channel_process_drdynvc: got unknown " + "command 0x%x", cmd); + break; + } + //g_writeln("xrdp_channel_process_drdynvc: rv %d", rv); + return rv; +} + /*****************************************************************************/ /* returns error */ /* This is called from the secure layer to process an incoming non global @@ -191,23 +536,319 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s, int channel_id; struct mcs_channel_item *channel; - /* this assumes that the channels are in order of chanid(mcs channel id) but they should be, see xrdp_sec_process_mcs_data_channels the first channel should be MCS_GLOBAL_CHANNEL + 1, second one should be MCS_GLOBAL_CHANNEL + 2, and so on */ channel_id = (chanid - MCS_GLOBAL_CHANNEL) - 1; channel = xrdp_channel_get_item(self, channel_id); - if (channel == NULL) { g_writeln("xrdp_channel_process, channel not found"); return 1; } - + if (channel->disabled) + { + g_writeln("xrdp_channel_process, channel disabled"); + return 0; /* not an error */ + } + if (channel_id == self->drdynvc_channel_id) + { + return xrdp_channel_process_drdynvc(self, channel, s); + } rv = 0; in_uint32_le(s, length); in_uint32_le(s, flags); rv = xrdp_channel_call_callback(self, s, channel_id, length, flags); return rv; } + +/*****************************************************************************/ +/* drdynvc */ +static int +xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self) +{ + struct stream *s; + int flags; + int total_data_len; + int channel_id; + char *phold; + + /* setup stream */ + make_stream(s); + init_stream(s, 8192); + if (xrdp_channel_init(self, s) != 0) + { + free_stream(s); + return 1; + } + phold = s->p; + out_uint8(s, 0x50); /* insert cmd */ + out_uint8(s, 0x00); /* insert padding */ + out_uint16_le(s, 2); /* insert version */ + /* channel priority unused for now */ + out_uint16_le(s, 0x0000); /* priority charge 0 */ + out_uint16_le(s, 0x0000); /* priority charge 1 */ + out_uint16_le(s, 0x0000); /* priority charge 2 */ + out_uint16_le(s, 0x0000); /* priority charge 3 */ + s_mark_end(s); + /* send command to client */ + total_data_len = (int) (s->end - phold); + flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; + channel_id = self->drdynvc_channel_id; + if (xrdp_channel_send(self, s, channel_id, total_data_len, flags) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + return 0; +} + +/*****************************************************************************/ +int +xrdp_channel_drdynvc_start(struct xrdp_channel *self) +{ + int index; + int count; + struct mcs_channel_item *ci; + struct mcs_channel_item *dci; + + g_writeln("xrdp_channel_drdynvc_start:"); + dci = NULL; + count = self->mcs_layer->channel_list->count; + for (index = 0; index < count; index++) + { + ci = (struct mcs_channel_item *) + list_get_item(self->mcs_layer->channel_list, index); + if (ci != NULL) + { + if (g_strcasecmp(ci->name, "drdynvc") == 0) + { + dci = ci; + } + } + } + if (dci != NULL) + { + self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1; + xrdp_channel_drdynvc_send_capability_request(self); + } + return 0; +} + +/*****************************************************************************/ +int +xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name, + int flags, struct xrdp_drdynvc_procs *procs, + int *chan_id) +{ + struct stream *s; + int ChId; + int cbChId; + int chan_pri; + int static_channel_id; + int name_length; + int total_data_len; + int static_flags; + char *cmd_ptr; + + make_stream(s); + init_stream(s, 8192); + if (xrdp_channel_init(self, s) != 0) + { + free_stream(s); + return 1; + } + cmd_ptr = s->p; + out_uint8(s, 0); + ChId = 1; + while (self->drdynvcs[ChId].status != XRDP_DRDYNVC_STATUS_CLOSED) + { + ChId++; + if (ChId > 255) + { + free_stream(s); + return 1; + } + } + cbChId = drdynvc_insert_uint_124(s, ChId); + name_length = g_strlen(name); + out_uint8a(s, name, name_length + 1); + chan_pri = 0; + cmd_ptr[0] = CMD_DVC_OPEN_CHANNEL | ((chan_pri << 2) & 0x0c) | cbChId; + static_channel_id = self->drdynvc_channel_id; + static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; + s_mark_end(s); + total_data_len = (int) (s->end - cmd_ptr); + if (xrdp_channel_send(self, s, static_channel_id, total_data_len, + static_flags) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + *chan_id = ChId; + self->drdynvcs[ChId].open_response = procs->open_response; + self->drdynvcs[ChId].close_response = procs->close_response; + self->drdynvcs[ChId].data_first = procs->data_first; + self->drdynvcs[ChId].data = procs->data; + self->drdynvcs[ChId].status = XRDP_DRDYNVC_STATUS_OPEN_SENT; + return 0; +} + +/*****************************************************************************/ +int +xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id) +{ + struct stream *s; + int ChId; + int cbChId; + int static_channel_id; + int total_data_len; + int static_flags; + char *cmd_ptr; + + if ((chan_id < 0) || (chan_id > 255)) + { + return 1; + } + if ((self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) && + (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN_SENT)) + { + /* not open */ + return 1; + } + make_stream(s); + init_stream(s, 8192); + if (xrdp_channel_init(self, s) != 0) + { + free_stream(s); + return 1; + } + cmd_ptr = s->p; + out_uint8(s, 0); + ChId = chan_id; + cbChId = drdynvc_insert_uint_124(s, ChId); + cmd_ptr[0] = CMD_DVC_CLOSE_CHANNEL | cbChId; + static_channel_id = self->drdynvc_channel_id; + static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; + s_mark_end(s); + total_data_len = (int) (s->end - cmd_ptr); + if (xrdp_channel_send(self, s, static_channel_id, total_data_len, + static_flags) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + self->drdynvcs[ChId].status = XRDP_DRDYNVC_STATUS_CLOSE_SENT; + return 0; +} + +/*****************************************************************************/ +int +xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id, + const char *data, int data_bytes, + int total_data_bytes) +{ + struct stream *s; + int ChId; + int cbChId; + int cbTotalDataSize; + int static_channel_id; + int total_data_len; + int static_flags; + char *cmd_ptr; + + if ((chan_id < 0) || (chan_id > 255)) + { + return 1; + } + if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) + { + return 1; + } + if (data_bytes > 1590) + { + return 1; + } + make_stream(s); + init_stream(s, 8192); + if (xrdp_channel_init(self, s) != 0) + { + free_stream(s); + return 1; + } + cmd_ptr = s->p; + out_uint8(s, 0); + ChId = chan_id; + cbChId = drdynvc_insert_uint_124(s, ChId); + cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes); + out_uint8p(s, data, data_bytes); + cmd_ptr[0] = CMD_DVC_DATA_FIRST | (cbTotalDataSize << 2) | cbChId; + static_channel_id = self->drdynvc_channel_id; + static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; + s_mark_end(s); + total_data_len = (int) (s->end - cmd_ptr); + if (xrdp_channel_send(self, s, static_channel_id, total_data_len, + static_flags) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + return 0; +} + +/*****************************************************************************/ +int +xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id, + const char *data, int data_bytes) +{ + struct stream *s; + int ChId; + int cbChId; + int static_channel_id; + int total_data_len; + int static_flags; + char *cmd_ptr; + + if ((chan_id < 0) || (chan_id > 255)) + { + return 1; + } + if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) + { + return 1; + } + if (data_bytes > 1590) + { + return 1; + } + make_stream(s); + init_stream(s, 8192); + if (xrdp_channel_init(self, s) != 0) + { + free_stream(s); + return 1; + } + cmd_ptr = s->p; + out_uint8(s, 0); + ChId = chan_id; + cbChId = drdynvc_insert_uint_124(s, ChId); + out_uint8p(s, data, data_bytes); + cmd_ptr[0] = CMD_DVC_DATA | cbChId; + static_channel_id = self->drdynvc_channel_id; + static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; + s_mark_end(s); + total_data_len = (int) (s->end - cmd_ptr); + if (xrdp_channel_send(self, s, static_channel_id, total_data_len, + static_flags) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + return 0; +} diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 52d043c9..3d9c833f 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -503,11 +503,11 @@ xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD; + order_flags = TS_STANDARD; if (self->orders_state.last_order != RDP_ORDER_RECT) { - order_flags |= RDP_ORDER_CHANGE; + order_flags |= TS_TYPE_CHANGE; } self->orders_state.last_order = RDP_ORDER_RECT; @@ -518,11 +518,11 @@ xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, if (x < rect->left || y < rect->top || x + cx > rect->right || y + cy > rect->bottom) { - order_flags |= RDP_ORDER_BOUNDS; + order_flags |= TS_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - order_flags |= RDP_ORDER_LASTBOUNDS; + order_flags |= TS_ZERO_BOUNDS_DELTAS; } } } @@ -538,14 +538,14 @@ xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, if (xrdp_orders_send_delta(self, vals, 8)) { - order_flags |= RDP_ORDER_DELTA; + order_flags |= TS_DELTA_COORDINATES; } /* order_flags, set later, 1 byte */ order_flags_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if (order_flags & RDP_ORDER_CHANGE) + if (order_flags & TS_TYPE_CHANGE) { out_uint8(self->out_s, self->orders_state.last_order); } @@ -555,8 +555,8 @@ xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, present_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if ((order_flags & RDP_ORDER_BOUNDS) && - !(order_flags & RDP_ORDER_LASTBOUNDS)) + if ((order_flags & TS_BOUNDS) && + !(order_flags & TS_ZERO_BOUNDS_DELTAS)) { xrdp_orders_out_bounds(self, rect); } @@ -565,7 +565,7 @@ xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, { present |= 0x01; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, x - self->orders_state.rect_x); } @@ -581,7 +581,7 @@ xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, { present |= 0x02; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, y - self->orders_state.rect_y); } @@ -597,7 +597,7 @@ xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, { present |= 0x04; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cx - self->orders_state.rect_cx); } @@ -613,7 +613,7 @@ xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, { present |= 0x08; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cy - self->orders_state.rect_cy); } @@ -674,11 +674,11 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD; + order_flags = TS_STANDARD; if (self->orders_state.last_order != RDP_ORDER_SCREENBLT) { - order_flags |= RDP_ORDER_CHANGE; + order_flags |= TS_TYPE_CHANGE; } self->orders_state.last_order = RDP_ORDER_SCREENBLT; @@ -689,11 +689,11 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, if (x < rect->left || y < rect->top || x + cx > rect->right || y + cy > rect->bottom) { - order_flags |= RDP_ORDER_BOUNDS; + order_flags |= TS_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - order_flags |= RDP_ORDER_LASTBOUNDS; + order_flags |= TS_ZERO_BOUNDS_DELTAS; } } } @@ -713,14 +713,14 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, if (xrdp_orders_send_delta(self, vals, 12)) { - order_flags |= RDP_ORDER_DELTA; + order_flags |= TS_DELTA_COORDINATES; } /* order_flags, set later, 1 byte */ order_flags_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if (order_flags & RDP_ORDER_CHANGE) + if (order_flags & TS_TYPE_CHANGE) { out_uint8(self->out_s, self->orders_state.last_order); } @@ -730,8 +730,8 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, present_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if ((order_flags & RDP_ORDER_BOUNDS) && - !(order_flags & RDP_ORDER_LASTBOUNDS)) + if ((order_flags & TS_BOUNDS) && + !(order_flags & TS_ZERO_BOUNDS_DELTAS)) { xrdp_orders_out_bounds(self, rect); } @@ -740,7 +740,7 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, { present |= 0x01; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, x - self->orders_state.scr_blt_x); } @@ -756,7 +756,7 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, { present |= 0x02; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, y - self->orders_state.scr_blt_y); } @@ -772,7 +772,7 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, { present |= 0x04; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cx - self->orders_state.scr_blt_cx); } @@ -788,7 +788,7 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, { present |= 0x08; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cy - self->orders_state.scr_blt_cy); } @@ -811,7 +811,7 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, { present |= 0x20; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, srcx - self->orders_state.scr_blt_srcx); } @@ -827,7 +827,7 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, { present |= 0x40; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, srcy - self->orders_state.scr_blt_srcy); } @@ -866,11 +866,11 @@ xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD; + order_flags = TS_STANDARD; if (self->orders_state.last_order != RDP_ORDER_PATBLT) { - order_flags |= RDP_ORDER_CHANGE; + order_flags |= TS_TYPE_CHANGE; } self->orders_state.last_order = RDP_ORDER_PATBLT; @@ -881,11 +881,11 @@ xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, if (x < rect->left || y < rect->top || x + cx > rect->right || y + cy > rect->bottom) { - order_flags |= RDP_ORDER_BOUNDS; + order_flags |= TS_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - order_flags |= RDP_ORDER_LASTBOUNDS; + order_flags |= TS_ZERO_BOUNDS_DELTAS; } } } @@ -901,14 +901,14 @@ xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, if (xrdp_orders_send_delta(self, vals, 8)) { - order_flags |= RDP_ORDER_DELTA; + order_flags |= TS_DELTA_COORDINATES; } /* order_flags, set later, 1 byte */ order_flags_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if (order_flags & RDP_ORDER_CHANGE) + if (order_flags & TS_TYPE_CHANGE) { out_uint8(self->out_s, self->orders_state.last_order); } @@ -918,8 +918,8 @@ xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, present_ptr = self->out_s->p; out_uint8s(self->out_s, 2); - if ((order_flags & RDP_ORDER_BOUNDS) && - !(order_flags & RDP_ORDER_LASTBOUNDS)) + if ((order_flags & TS_BOUNDS) && + !(order_flags & TS_ZERO_BOUNDS_DELTAS)) { xrdp_orders_out_bounds(self, rect); } @@ -928,7 +928,7 @@ xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, { present |= 0x0001; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, x - self->orders_state.pat_blt_x); } @@ -944,7 +944,7 @@ xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, { present |= 0x0002; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, y - self->orders_state.pat_blt_y); } @@ -960,7 +960,7 @@ xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, { present |= 0x0004; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cx - self->orders_state.pat_blt_cx); } @@ -976,7 +976,7 @@ xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, { present |= 0x0008; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cy - self->orders_state.pat_blt_cy); } @@ -1083,11 +1083,11 @@ xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD; + order_flags = TS_STANDARD; if (self->orders_state.last_order != RDP_ORDER_DESTBLT) { - order_flags |= RDP_ORDER_CHANGE; + order_flags |= TS_TYPE_CHANGE; } self->orders_state.last_order = RDP_ORDER_DESTBLT; @@ -1098,11 +1098,11 @@ xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, if (x < rect->left || y < rect->top || x + cx > rect->right || y + cy > rect->bottom) { - order_flags |= RDP_ORDER_BOUNDS; + order_flags |= TS_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - order_flags |= RDP_ORDER_LASTBOUNDS; + order_flags |= TS_ZERO_BOUNDS_DELTAS; } } } @@ -1118,14 +1118,14 @@ xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, if (xrdp_orders_send_delta(self, vals, 8)) { - order_flags |= RDP_ORDER_DELTA; + order_flags |= TS_DELTA_COORDINATES; } /* order_flags, set later, 1 byte */ order_flags_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if (order_flags & RDP_ORDER_CHANGE) + if (order_flags & TS_TYPE_CHANGE) { out_uint8(self->out_s, self->orders_state.last_order); } @@ -1135,8 +1135,8 @@ xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, present_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if ((order_flags & RDP_ORDER_BOUNDS) && - !(order_flags & RDP_ORDER_LASTBOUNDS)) + if ((order_flags & TS_BOUNDS) && + !(order_flags & TS_ZERO_BOUNDS_DELTAS)) { xrdp_orders_out_bounds(self, rect); } @@ -1145,7 +1145,7 @@ xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, { present |= 0x01; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, x - self->orders_state.dest_blt_x); } @@ -1161,7 +1161,7 @@ xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, { present |= 0x02; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, y - self->orders_state.dest_blt_y); } @@ -1177,7 +1177,7 @@ xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, { present |= 0x04; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cx - self->orders_state.dest_blt_cx); } @@ -1193,7 +1193,7 @@ xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, { present |= 0x08; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cy - self->orders_state.dest_blt_cy); } @@ -1254,11 +1254,11 @@ xrdp_orders_line(struct xrdp_orders *self, int mix_mode, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD; + order_flags = TS_STANDARD; if (self->orders_state.last_order != RDP_ORDER_LINE) { - order_flags |= RDP_ORDER_CHANGE; + order_flags |= TS_TYPE_CHANGE; } self->orders_state.last_order = RDP_ORDER_LINE; @@ -1271,11 +1271,11 @@ xrdp_orders_line(struct xrdp_orders *self, int mix_mode, MAX(endx, startx) >= rect->right || MAX(endy, starty) >= rect->bottom) { - order_flags |= RDP_ORDER_BOUNDS; + order_flags |= TS_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - order_flags |= RDP_ORDER_LASTBOUNDS; + order_flags |= TS_ZERO_BOUNDS_DELTAS; } } } @@ -1291,14 +1291,14 @@ xrdp_orders_line(struct xrdp_orders *self, int mix_mode, if (xrdp_orders_send_delta(self, vals, 8)) { - order_flags |= RDP_ORDER_DELTA; + order_flags |= TS_DELTA_COORDINATES; } /* order_flags, set later, 1 byte */ order_flags_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if (order_flags & RDP_ORDER_CHANGE) + if (order_flags & TS_TYPE_CHANGE) { out_uint8(self->out_s, self->orders_state.last_order); } @@ -1308,8 +1308,8 @@ xrdp_orders_line(struct xrdp_orders *self, int mix_mode, present_ptr = self->out_s->p; out_uint8s(self->out_s, 2); - if ((order_flags & RDP_ORDER_BOUNDS) && - !(order_flags & RDP_ORDER_LASTBOUNDS)) + if ((order_flags & TS_BOUNDS) && + !(order_flags & TS_ZERO_BOUNDS_DELTAS)) { xrdp_orders_out_bounds(self, rect); } @@ -1325,7 +1325,7 @@ xrdp_orders_line(struct xrdp_orders *self, int mix_mode, { present |= 0x0002; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, startx - self->orders_state.line_startx); } @@ -1341,7 +1341,7 @@ xrdp_orders_line(struct xrdp_orders *self, int mix_mode, { present |= 0x0004; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, starty - self->orders_state.line_starty); } @@ -1357,7 +1357,7 @@ xrdp_orders_line(struct xrdp_orders *self, int mix_mode, { present |= 0x0008; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, endx - self->orders_state.line_endx); } @@ -1373,7 +1373,7 @@ xrdp_orders_line(struct xrdp_orders *self, int mix_mode, { present |= 0x0010; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, endy - self->orders_state.line_endy); } @@ -1456,11 +1456,11 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD; + order_flags = TS_STANDARD; if (self->orders_state.last_order != RDP_ORDER_MEMBLT) { - order_flags |= RDP_ORDER_CHANGE; + order_flags |= TS_TYPE_CHANGE; } self->orders_state.last_order = RDP_ORDER_MEMBLT; @@ -1471,11 +1471,11 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, if (x < rect->left || y < rect->top || x + cx > rect->right || y + cy > rect->bottom) { - order_flags |= RDP_ORDER_BOUNDS; + order_flags |= TS_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - order_flags |= RDP_ORDER_LASTBOUNDS; + order_flags |= TS_ZERO_BOUNDS_DELTAS; } } } @@ -1495,14 +1495,14 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, if (xrdp_orders_send_delta(self, vals, 12)) { - order_flags |= RDP_ORDER_DELTA; + order_flags |= TS_DELTA_COORDINATES; } /* order_flags, set later, 1 byte */ order_flags_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if (order_flags & RDP_ORDER_CHANGE) + if (order_flags & TS_TYPE_CHANGE) { out_uint8(self->out_s, self->orders_state.last_order); } @@ -1512,8 +1512,8 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, present_ptr = self->out_s->p; out_uint8s(self->out_s, 2); - if ((order_flags & RDP_ORDER_BOUNDS) && - !(order_flags & RDP_ORDER_LASTBOUNDS)) + if ((order_flags & TS_BOUNDS) && + !(order_flags & TS_ZERO_BOUNDS_DELTAS)) { xrdp_orders_out_bounds(self, rect); } @@ -1532,7 +1532,7 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, { present |= 0x0002; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, x - self->orders_state.mem_blt_x); } @@ -1548,7 +1548,7 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, { present |= 0x0004; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, y - self->orders_state.mem_blt_y); } @@ -1564,7 +1564,7 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, { present |= 0x0008; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cx - self->orders_state.mem_blt_cx); } @@ -1580,7 +1580,7 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, { present |= 0x0010; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, cy - self->orders_state.mem_blt_cy); } @@ -1603,7 +1603,7 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, { present |= 0x0040; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, srcx - self->orders_state.mem_blt_srcx); } @@ -1619,7 +1619,7 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, { present |= 0x0080; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, srcy - self->orders_state.mem_blt_srcy); } @@ -1666,10 +1666,10 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD; + order_flags = TS_STANDARD; if (self->orders_state.last_order != RDP_ORDER_COMPOSITE) { - order_flags |= RDP_ORDER_CHANGE; + order_flags |= TS_TYPE_CHANGE; } self->orders_state.last_order = RDP_ORDER_COMPOSITE; if (rect != 0) @@ -1678,11 +1678,11 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (dstx < rect->left || dsty < rect->top || dstx + width > rect->right || dsty + height > rect->bottom) { - order_flags |= RDP_ORDER_BOUNDS; + order_flags |= TS_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - order_flags |= RDP_ORDER_LASTBOUNDS; + order_flags |= TS_ZERO_BOUNDS_DELTAS; } } @@ -1709,12 +1709,12 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, vals[19] = self->orders_state.com_blt_mskwidth; if (xrdp_orders_send_delta(self, vals, 20)) { - order_flags |= RDP_ORDER_DELTA; + order_flags |= TS_DELTA_COORDINATES; } /* order_flags, set later, 1 byte */ order_flags_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if (order_flags & RDP_ORDER_CHANGE) + if (order_flags & TS_TYPE_CHANGE) { out_uint8(self->out_s, self->orders_state.last_order); } @@ -1722,8 +1722,8 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, /* present, set later, 3 bytes */ present_ptr = self->out_s->p; out_uint8s(self->out_s, 3); - if ((order_flags & RDP_ORDER_BOUNDS) && - !(order_flags & RDP_ORDER_LASTBOUNDS)) + if ((order_flags & TS_BOUNDS) && + !(order_flags & TS_ZERO_BOUNDS_DELTAS)) { xrdp_orders_out_bounds(self, rect); } @@ -1745,7 +1745,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (srcwidth != self->orders_state.com_blt_srcwidth) { present |= 0x000004; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, srcwidth - self->orders_state.com_blt_srcwidth); } @@ -1821,7 +1821,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (mskwidth != self->orders_state.com_blt_mskwidth) { present |= 0x000200; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, mskwidth - self->orders_state.com_blt_mskwidth); } @@ -1849,7 +1849,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (srcx != self->orders_state.com_blt_srcx) { present |= 0x001000; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, srcx - self->orders_state.com_blt_srcx); } @@ -1863,7 +1863,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (srcy != self->orders_state.com_blt_srcy) { present |= 0x002000; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, srcy - self->orders_state.com_blt_srcy); } @@ -1877,7 +1877,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (mskx != self->orders_state.com_blt_mskx) { present |= 0x004000; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, mskx - self->orders_state.com_blt_mskx); } @@ -1891,7 +1891,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (msky != self->orders_state.com_blt_msky) { present |= 0x008000; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, msky - self->orders_state.com_blt_msky); } @@ -1905,7 +1905,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (dstx != self->orders_state.com_blt_dstx) { present |= 0x010000; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, dstx - self->orders_state.com_blt_dstx); } @@ -1919,7 +1919,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (dsty != self->orders_state.com_blt_dsty) { present |= 0x020000; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, dsty - self->orders_state.com_blt_dsty); } @@ -1933,7 +1933,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (width != self->orders_state.com_blt_width) { present |= 0x040000; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, width - self->orders_state.com_blt_width); } @@ -1947,7 +1947,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, if (height != self->orders_state.com_blt_height) { present |= 0x080000; - if (order_flags & RDP_ORDER_DELTA) + if (order_flags & TS_DELTA_COORDINATES) { out_uint8(self->out_s, height - self->orders_state.com_blt_height); } @@ -1995,11 +1995,11 @@ xrdp_orders_text(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD; + order_flags = TS_STANDARD; if (self->orders_state.last_order != RDP_ORDER_TEXT2) { - order_flags |= RDP_ORDER_CHANGE; + order_flags |= TS_TYPE_CHANGE; } self->orders_state.last_order = RDP_ORDER_TEXT2; @@ -2017,11 +2017,11 @@ xrdp_orders_text(struct xrdp_orders *self, clip_right > rect->right || clip_bottom > rect->bottom)) { - order_flags |= RDP_ORDER_BOUNDS; + order_flags |= TS_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - order_flags |= RDP_ORDER_LASTBOUNDS; + order_flags |= TS_ZERO_BOUNDS_DELTAS; } } } @@ -2030,7 +2030,7 @@ xrdp_orders_text(struct xrdp_orders *self, order_flags_ptr = self->out_s->p; out_uint8s(self->out_s, 1); - if (order_flags & RDP_ORDER_CHANGE) + if (order_flags & TS_TYPE_CHANGE) { out_uint8(self->out_s, self->orders_state.last_order); } @@ -2040,8 +2040,8 @@ xrdp_orders_text(struct xrdp_orders *self, present_ptr = self->out_s->p; out_uint8s(self->out_s, 3); - if ((order_flags & RDP_ORDER_BOUNDS) && - !(order_flags & RDP_ORDER_LASTBOUNDS)) + if ((order_flags & TS_BOUNDS) && + !(order_flags & TS_ZERO_BOUNDS_DELTAS)) { xrdp_orders_out_bounds(self, rect); } @@ -2184,12 +2184,12 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + order_flags = TS_STANDARD | TS_SECONDARY; out_uint8(self->out_s, order_flags); len = 1027 - 7; /* length after type minus 7 */ out_uint16_le(self->out_s, len); out_uint16_le(self->out_s, 0); /* flags */ - out_uint8(self->out_s, RDP_ORDER_COLCACHE); /* type */ + out_uint8(self->out_s, TS_CACHE_COLOR_TABLE); /* type */ out_uint8(self->out_s, cache_id); out_uint16_le(self->out_s, 256); /* num colors */ @@ -2256,12 +2256,12 @@ xrdp_orders_send_raw_bitmap(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + order_flags = TS_STANDARD | TS_SECONDARY; out_uint8(self->out_s, order_flags); len = (bufsize + 9) - 7; /* length after type minus 7 */ out_uint16_le(self->out_s, len); out_uint16_le(self->out_s, 8); /* flags */ - out_uint8(self->out_s, RDP_ORDER_RAW_BMPCACHE); /* type */ + out_uint8(self->out_s, TS_CACHE_BITMAP_UNCOMPRESSED); /* type */ out_uint8(self->out_s, cache_id); out_uint8s(self->out_s, 1); /* pad */ out_uint8(self->out_s, width + e); @@ -2402,7 +2402,7 @@ xrdp_orders_send_bitmap(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + order_flags = TS_STANDARD | TS_SECONDARY; out_uint8(self->out_s, order_flags); if (self->rdp_layer->client_info.op2) @@ -2418,7 +2418,7 @@ xrdp_orders_send_bitmap(struct xrdp_orders *self, out_uint16_le(self->out_s, 8); /* flags */ } - out_uint8(self->out_s, RDP_ORDER_BMPCACHE); /* type */ + out_uint8(self->out_s, TS_CACHE_BITMAP_COMPRESSED); /* type */ out_uint8(self->out_s, cache_id); out_uint8s(self->out_s, 1); /* pad */ out_uint8(self->out_s, width + e); @@ -2444,10 +2444,10 @@ xrdp_orders_send_bitmap(struct xrdp_orders *self, /* returns error */ /* max size datasize + 18*/ /* todo, only sends one for now */ -int -xrdp_orders_send_font(struct xrdp_orders *self, - struct xrdp_font_char *font_char, - int font_index, int char_index) +static int +xrdp_orders_cache_glyph(struct xrdp_orders *self, + struct xrdp_font_char *font_char, + int font_index, int char_index) { int order_flags = 0; int datasize = 0; @@ -2469,12 +2469,12 @@ xrdp_orders_send_font(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + order_flags = TS_STANDARD | TS_SECONDARY; out_uint8(self->out_s, order_flags); len = (datasize + 12) - 7; /* length after type minus 7 */ out_uint16_le(self->out_s, len); out_uint16_le(self->out_s, flags); - out_uint8(self->out_s, RDP_ORDER_FONTCACHE); /* type */ + out_uint8(self->out_s, TS_CACHE_GLYPH); /* type */ out_uint8(self->out_s, font_index); out_uint8(self->out_s, 1); /* num of chars */ out_uint16_le(self->out_s, char_index); @@ -2486,6 +2486,150 @@ xrdp_orders_send_font(struct xrdp_orders *self, return 0; } +/*****************************************************************************/ +/* returns error */ +static int write_2byte_signed(struct stream * s, int value) +{ + unsigned char byte; + int negative = 0; + + if (value < 0) + { + negative = 1; + value *= -1; + } + + if (value > 0x3FFF) + { + return 1; + } + + if (value >= 0x3F) + { + byte = ((value & 0x3F00) >> 8); + + if (negative) + { + byte |= 0x40; + } + + out_uint8(s, byte | 0x80); + byte = (value & 0xFF); + out_uint8(s, byte); + } + else + { + byte = (value & 0x3F); + + if (negative) + { + byte |= 0x40; + } + + out_uint8(s, byte); + } + + return 0; +} + +/*****************************************************************************/ +/* returns error */ +static int write_2byte_unsigned(struct stream * s, unsigned int value) +{ + unsigned char byte; + + if (value > 0x7FFF) + { + return 1; + } + + if (value >= 0x7F) + { + byte = ((value & 0x7F00) >> 8); + out_uint8(s, byte | 0x80); + byte = (value & 0xFF); + out_uint8(s, byte); + } + else + { + byte = (value & 0x7F); + out_uint8(s, byte); + } + + return 0; +} + +/*****************************************************************************/ +/* returns error */ +/* max size datasize + 15*/ +/* todo, only sends one for now */ +static int +xrdp_orders_cache_glyph_v2(struct xrdp_orders *self, + struct xrdp_font_char *font_char, + int font_index, int char_index) +{ + int order_flags = 0; + int datasize = 0; + int len = 0; + int extra_flags; + char *len_ptr; + + if (font_char->bpp == 8) /* alpha font */ + { + datasize = ((font_char->width + 3) & ~3) * font_char->height; + } + else + { + datasize = FONT_DATASIZE(font_char); + } + + /* cacheId, flags(GLYPH_ORDER_REV2), cGlyphs */ + extra_flags = (font_index & 0x000F) | (0x2 << 4) | (1 << 8); + + if (xrdp_orders_check(self, datasize + 15) != 0) + { + return 1; + } + self->order_count++; + order_flags = TS_STANDARD | TS_SECONDARY; + out_uint8(self->out_s, order_flags); + len_ptr = self->out_s->p; + out_uint16_le(self->out_s, 0); /* set later */ + out_uint16_le(self->out_s, extra_flags); + out_uint8(self->out_s, TS_CACHE_GLYPH); /* type */ + + out_uint8(self->out_s, char_index); + if (write_2byte_signed(self->out_s, font_char->offset) || + write_2byte_signed(self->out_s, font_char->baseline) || + write_2byte_unsigned(self->out_s, font_char->width) || + write_2byte_unsigned(self->out_s, font_char->height)) + { + return 1; + } + + out_uint8a(self->out_s, font_char->data, datasize); + len = (self->out_s->p - len_ptr) + 1 - 13; + len_ptr[0] = len & 0xFF; + len_ptr[1] = (len >> 8) & 0xFF; + + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int +xrdp_orders_send_font(struct xrdp_orders *self, + struct xrdp_font_char *font_char, + int font_index, int char_index) +{ + if (self->rdp_layer->client_info.use_cache_glyph_v2) + { + return xrdp_orders_cache_glyph_v2(self, font_char, font_index, char_index); + } + + return xrdp_orders_cache_glyph(self, font_char, font_index, char_index); +} + /*****************************************************************************/ /* returns error */ /* max size width * height * Bpp + 14 */ @@ -2539,13 +2683,13 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + order_flags = TS_STANDARD | TS_SECONDARY; out_uint8(self->out_s, order_flags); len = (bufsize + 6) - 7; /* length after type minus 7 */ out_uint16_le(self->out_s, len); i = (((Bpp + 2) << 3) & 0x38) | (cache_id & 7); out_uint16_le(self->out_s, i); /* flags */ - out_uint8(self->out_s, RDP_ORDER_RAW_BMPCACHE2); /* type */ + out_uint8(self->out_s, TS_CACHE_BITMAP_UNCOMPRESSED_REV2); /* type */ out_uint8(self->out_s, width + e); out_uint8(self->out_s, height); out_uint16_be(self->out_s, bufsize | 0x4000); @@ -2686,14 +2830,14 @@ xrdp_orders_send_bitmap2(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + order_flags = TS_STANDARD | TS_SECONDARY; out_uint8(self->out_s, order_flags); len = (bufsize + 6) - 7; /* length after type minus 7 */ out_uint16_le(self->out_s, len); i = (((Bpp + 2) << 3) & 0x38) | (cache_id & 7); i = i | (0x08 << 7); /* CBR2_NO_BITMAP_COMPRESSION_HDR */ out_uint16_le(self->out_s, i); /* flags */ - out_uint8(self->out_s, RDP_ORDER_BMPCACHE2); /* type */ + out_uint8(self->out_s, TS_CACHE_BITMAP_COMPRESSED_REV2); /* type */ out_uint8(self->out_s, width + e); out_uint8(self->out_s, height); out_uint16_be(self->out_s, bufsize | 0x4000); @@ -2777,13 +2921,13 @@ xrdp_orders_out_v3(struct xrdp_orders *self, int cache_id, int cache_idx, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + order_flags = TS_STANDARD | TS_SECONDARY; out_uint8(self->out_s, order_flags); len = (bufsize + 22) - 7; /* length after type minus 7 */ out_uint16_le(self->out_s, len); i = (((Bpp + 2) << 3) & 0x38) | (cache_id & 7); out_uint16_le(self->out_s, i); /* flags */ - out_uint8(self->out_s, RDP_ORDER_BMPCACHE3); /* type */ + out_uint8(self->out_s, TS_CACHE_BITMAP_COMPRESSED_REV3); /* type */ /* cache index */ out_uint16_le(self->out_s, cache_idx); /* persistent cache key 1/2 */ @@ -2924,12 +3068,12 @@ xrdp_orders_send_brush(struct xrdp_orders *self, int width, int height, return 1; } self->order_count++; - order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + order_flags = TS_STANDARD | TS_SECONDARY; out_uint8(self->out_s, order_flags); len = (size + 6) - 7; /* length after type minus 7 */ out_uint16_le(self->out_s, len); out_uint16_le(self->out_s, 0); /* flags */ - out_uint8(self->out_s, RDP_ORDER_BRUSHCACHE); /* type */ + out_uint8(self->out_s, TS_CACHE_BRUSH); /* type */ out_uint8(self->out_s, cache_id); out_uint8(self->out_s, bpp); out_uint8(self->out_s, width); @@ -2969,7 +3113,7 @@ xrdp_orders_send_create_os_surface(struct xrdp_orders *self, int id, return 1; } self->order_count++; - order_flags = RDP_ORDER_SECONDARY; + order_flags = TS_SECONDARY; order_flags |= 1 << 2; /* type RDP_ORDER_ALTSEC_CREATE_OFFSCR_BITMAP */ out_uint8(self->out_s, order_flags); cache_id = id & 0x7fff; @@ -3013,7 +3157,7 @@ xrdp_orders_send_switch_os_surface(struct xrdp_orders *self, int id) return 1; } self->order_count++; - order_flags = RDP_ORDER_SECONDARY; + order_flags = TS_SECONDARY; order_flags |= 0 << 2; /* type RDP_ORDER_ALTSEC_SWITCH_SURFACE */ out_uint8(self->out_s, order_flags); cache_id = id & 0xffff; diff --git a/libxrdp/xrdp_orders_rail.c b/libxrdp/xrdp_orders_rail.c index 7bc7eed9..b6170818 100644 --- a/libxrdp/xrdp_orders_rail.c +++ b/libxrdp/xrdp_orders_rail.c @@ -43,7 +43,7 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id) return 1; } self->order_count++; - order_flags = RDP_ORDER_SECONDARY; + order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); /* orderSize (2 bytes) */ @@ -76,7 +76,7 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_SECONDARY; + order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); /* orderSize (2 bytes) */ @@ -170,7 +170,7 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_SECONDARY; + order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); /* orderSize (2 bytes) */ @@ -373,7 +373,7 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, return 1; } self->order_count++; - order_flags = RDP_ORDER_SECONDARY; + order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); /* orderSize (2 bytes) */ @@ -517,7 +517,7 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id, return 1; } self->order_count++; - order_flags = RDP_ORDER_SECONDARY; + order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); /* orderSize (2 bytes) */ @@ -611,7 +611,7 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_SECONDARY; + order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); /* orderSize (2 bytes) */ @@ -705,7 +705,7 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self, return 1; } self->order_count++; - order_flags = RDP_ORDER_SECONDARY; + order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); /* orderSize (2 bytes) */ diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 099cec47..e4ee660f 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -269,7 +269,7 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) g_strncpy(client_info->key_file, value, 1023); } - if (!g_file_readable(client_info->key_file)) + if (!g_file_readable(client_info->key_file)) { log_message(LOG_LEVEL_ERROR, "Cannot read private key file %s: %s", client_info->key_file, g_get_strerror()); @@ -561,7 +561,7 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, DEBUG(("in xrdp_rdp_send_data")); s_pop_layer(s, rdp_hdr); len = (int)(s->end - s->p); - pdutype = 0x10 | RDP_PDU_DATA; + pdutype = 0x10 | PDUTYPE_DATAPDU; pdulen = len; dlen = len; ctype = 0; @@ -1125,6 +1125,7 @@ xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) g_writeln("yeah, up_and_running"); DEBUG(("up_and_running set")); xrdp_rdp_send_data_update_sync(self); + xrdp_channel_drdynvc_start(self->sec_layer->chan_layer); } DEBUG(("out xrdp_rdp_process_data_font")); @@ -1295,7 +1296,7 @@ xrdp_rdp_send_deactivate(struct xrdp_rdp *self) s_mark_end(s); - if (xrdp_rdp_send(self, s, RDP_PDU_DEACTIVATE) != 0) + if (xrdp_rdp_send(self, s, PDUTYPE_DEACTIVATEALLPDU) != 0) { free_stream(s); DEBUG(("out xrdp_rdp_send_deactivate error")); diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 0436edf2..31197ab6 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -701,6 +701,12 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) DEBUG(("flag RDP_LOGON_LEAVE_AUDIO found")); } + if (flags & RDP_LOGON_RAIL) + { + self->rdp_layer->client_info.rail_enable = 1; + DEBUG(("flag RDP_LOGON_RAIL found")); + } + if ((flags & RDP_LOGON_AUTO) && (!self->rdp_layer->client_info.is_mce)) /* todo, for now not allowing autologon and mce both */ { @@ -1840,57 +1846,54 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) { int num_channels; int index; - struct xrdp_client_info *client_info = (struct xrdp_client_info *)NULL; + struct xrdp_client_info *client_info; + struct mcs_channel_item *channel_item; client_info = &(self->rdp_layer->client_info); - - - DEBUG(("processing channels, channels_allowed is %d", client_info->channels_allowed)); - + DEBUG(("processing channels, channels_allowed is %d", + client_info->channels_allowed)); /* this is an option set in xrdp.ini */ - if (client_info->channels_allowed != 1) /* are channels on? */ + if (client_info->channels_allowed == 0) /* are channels on? */ { - g_writeln("xrdp_sec_process_mcs_data_channels: all channels are disabled by configuration"); + log_message(LOG_LEVEL_INFO, "all channels are disabled by " + "configuration"); return 0; } - if (!s_check_rem(s, 4)) { return 1; } - in_uint32_le(s, num_channels); - if (num_channels > 31) { return 1; } - 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); + channel_item = g_new0(struct mcs_channel_item, 1); if (!s_check_rem(s, 12)) { g_free(channel_item); 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); - DEBUG(("got channel flags %8.8x name %s", channel_item->flags, - channel_item->name)); + if (g_strlen(channel_item->name) > 0) + { + channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1); + log_message(LOG_LEVEL_INFO, "adding channel item name %s chan_id " + "%d flags 0x%8.8x", channel_item->name, + channel_item->chanid, channel_item->flags); + list_add_item(self->mcs_layer->channel_list, + (intptr_t) channel_item); + DEBUG(("got channel flags %8.8x name %s", channel_item->flags, + channel_item->name)); + } + else + { + g_free(channel_item); + } } - return 0; } diff --git a/neutrinordp/xrdp-neutrinordp.c b/neutrinordp/xrdp-neutrinordp.c index d7f90e18..89e8f2ea 100644 --- a/neutrinordp/xrdp-neutrinordp.c +++ b/neutrinordp/xrdp-neutrinordp.c @@ -1527,7 +1527,7 @@ lfreerdp_pre_connect(freerdp *instance) instance->settings->password = g_strdup(mod->password); instance->settings->domain = g_strdup(mod->domain); - if (mod->client_info.rail_support_level > 0) + if (mod->client_info.rail_enable && (mod->client_info.rail_support_level > 0)) { LLOGLN(0, ("Railsupport !!!!!!!!!!!!!!!!!!")); instance->settings->remote_app = 1; diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 35273283..05007757 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -56,8 +56,6 @@ xrdp_chansrv_SOURCES = \ clipboard_file.h \ devredir.c \ devredir.h \ - drdynvc.c \ - drdynvc.h \ fifo.c \ fifo.h \ irp.c \ diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 6ec05e53..7a0de556 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -36,7 +36,6 @@ #include "rail.h" #include "xcommon.h" #include "chansrv_fuse.h" -#include "drdynvc.h" #include "xrdp_sockets.h" static struct trans *g_lis_trans = 0; @@ -49,25 +48,17 @@ static int g_cliprdr_index = -1; static int g_rdpsnd_index = -1; static int g_rdpdr_index = -1; static int g_rail_index = -1; -static int g_drdynvc_index = -1; - -/* state info for dynamic virtual channels */ -static struct xrdp_api_data *g_dvc_channels[MAX_DVC_CHANNELS]; static tbus g_term_event = 0; static tbus g_thread_done_event = 0; static int g_use_unix_socket = 0; -static const unsigned char g_xrdpapi_magic[12] = -{ 0x78, 0x32, 0x10, 0x67, 0x00, 0x92, 0x30, 0x56, 0xff, 0xd8, 0xa9, 0x1f }; - int g_display_num = 0; int g_cliprdr_chan_id = -1; /* cliprdr */ int g_rdpsnd_chan_id = -1; /* rdpsnd */ int g_rdpdr_chan_id = -1; /* rdpdr */ int g_rail_chan_id = -1; /* rail */ -int g_drdynvc_chan_id = -1; /* drdynvc */ char *g_exec_name; tbus g_exec_event; @@ -76,10 +67,36 @@ tbus g_exec_sem; int g_exec_pid = 0; #define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x))) +/* max total channel bytes size */ +#define MAX_CHANNEL_BYTES (1 * 1024 * 1024 * 1024) /* 1 GB */ +#define MAX_CHANNEL_FRAG_BYTES 1600 -/* each time we create a DVC we need a unique DVC channel id */ -/* this variable gets bumped up once per DVC we create */ -tui32 g_dvc_chan_id = 100; +#define CHANSRV_DRDYNVC_STATUS_CLOSED 0 +#define CHANSRV_DRDYNVC_STATUS_OPEN_SENT 1 +#define CHANSRV_DRDYNVC_STATUS_OPEN 2 +#define CHANSRV_DRDYNVC_STATUS_CLOSE_SENT 3 + +struct chansrv_drdynvc +{ + int chan_id; + int status; /* see CHANSRV_DRDYNVC_STATUS_* */ + int flags; + int pad0; + int (*open_response)(int chan_id, int creation_status); + int (*close_response)(int chan_id); + int (*data_first)(int chan_id, char *data, int bytes, int total_bytes); + int (*data)(int chan_id, char *data, int bytes); + struct trans *xrdp_api_trans; +}; + +static struct chansrv_drdynvc g_drdynvcs[256]; + +/* data in struct trans::callback_data */ +struct xrdp_api_data +{ + int chan_flags; + int chan_id; +}; struct timeout_obj { @@ -226,151 +243,60 @@ g_is_term(void) } /*****************************************************************************/ -/* add data to chan_item, on its way to the client */ -/* returns error */ -static int -add_data_to_chan_item(struct chan_item *chan_item, char *data, int size) -{ - struct stream *s; - struct chan_out_data *cod; - - make_stream(s); - init_stream(s, size); - g_memcpy(s->data, data, size); - s->end = s->data + size; - cod = (struct chan_out_data *)g_malloc(sizeof(struct chan_out_data), 1); - cod->s = s; - - if (chan_item->tail == 0) - { - chan_item->tail = cod; - chan_item->head = cod; - } - else - { - chan_item->tail->next = cod; - chan_item->tail = cod; - } - - return 0; -} - -/*****************************************************************************/ -/* returns error */ -static int -send_data_from_chan_item(struct chan_item *chan_item) -{ - struct stream *s; - struct chan_out_data *cod; - int bytes_left; - int size; - int chan_flags; - int error; - - if (chan_item->head == 0) - { - return 0; - } - - cod = chan_item->head; - bytes_left = (int)(cod->s->end - cod->s->p); - size = MIN(1600, bytes_left); - chan_flags = 0; - - if (cod->s->p == cod->s->data) - { - chan_flags |= 1; /* first */ - } - - if (cod->s->p + size >= cod->s->end) - { - chan_flags |= 2; /* last */ - } - - s = trans_get_out_s(g_con_trans, 8192); - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ - out_uint32_le(s, 8); /* msg id */ - out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */ - out_uint16_le(s, chan_item->id); - out_uint16_le(s, chan_flags); - out_uint16_le(s, size); - out_uint32_le(s, cod->s->size); - out_uint8a(s, cod->s->p, size); - s_mark_end(s); - LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- " - "size %d chan_flags 0x%8.8x", size, chan_flags)); - - error = trans_write_copy(g_con_trans); - if (error != 0) - { - return 1; - } - - cod->s->p += size; - - if (cod->s->p >= cod->s->end) - { - free_stream(cod->s); - chan_item->head = chan_item->head->next; - - if (chan_item->head == 0) - { - chan_item->tail = 0; - } - - g_free(cod); - } - - return 0; -} - -/*****************************************************************************/ -/* returns error */ -static int -check_chan_items(void) -{ - int index; - - for (index = 0; index < g_num_chan_items; index++) - { - if (g_chan_items[index].head != 0) - { - send_data_from_chan_item(g_chan_items + index); - } - } - - return 0; -} - -/*****************************************************************************/ +/* send data to a static virtual channel + size can be > MAX_CHANNEL_FRAG_BYTES, in which case, > 1 message + will be sent*/ /* returns error */ int -send_channel_data(int chan_id, char *data, int size) +send_channel_data(int chan_id, const char *data, int size) { - int index; + int sending_bytes; + int chan_flags; + int error; + int total_size; + struct stream *s; - //g_writeln("send_channel_data chan_id %d size %d", chan_id, size); - - LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: size %d", size)); - - if (chan_id == -1) + if ((chan_id < 0) || (chan_id > 31) || + (data == NULL) || + (size < 1) || (size > MAX_CHANNEL_BYTES)) { - g_writeln("send_channel_data: error, chan_id is -1"); + /* bad param */ return 1; } - - for (index = 0; index < g_num_chan_items; index++) + total_size = size; + chan_flags = 1; /* first */ + while (size > 0) { - if (g_chan_items[index].id == chan_id) + sending_bytes = MIN(MAX_CHANNEL_FRAG_BYTES, size); + if (sending_bytes >= size) { - add_data_to_chan_item(g_chan_items + index, data, size); - check_chan_items(); - return 0; + chan_flags |= 2; /* last */ } + s = trans_get_out_s(g_con_trans, 26 + sending_bytes); + if (s == NULL) + { + return 2; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 26 + sending_bytes); + out_uint32_le(s, 8); /* msg id */ + out_uint32_le(s, 18 + sending_bytes); + out_uint16_le(s, chan_id); + out_uint16_le(s, chan_flags); + out_uint16_le(s, sending_bytes); + out_uint32_le(s, total_size); + out_uint8a(s, data, sending_bytes); + s_mark_end(s); + size -= sending_bytes; + data += sending_bytes; + error = trans_write_copy(g_con_trans); + if (error != 0) + { + return 3; + } + chan_flags = 0; } - - return 1; + return 0; } /*****************************************************************************/ @@ -398,84 +324,6 @@ send_rail_drawing_orders(char* data, int size) return 0; } -/*****************************************************************************/ -/* returns error */ -static int -send_init_response_message(void) -{ - struct stream *s = (struct stream *)NULL; - - LOGM((LOG_LEVEL_INFO, "send_init_response_message:")); - s = trans_get_out_s(g_con_trans, 8192); - - if (s == 0) - { - return 1; - } - - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 2); /* msg id */ - out_uint32_le(s, 8); /* size */ - s_mark_end(s); - return trans_write_copy(g_con_trans); -} - -/*****************************************************************************/ -/* returns error */ -static int -send_channel_setup_response_message(void) -{ - struct stream *s = (struct stream *)NULL; - - LOGM((LOG_LEVEL_DEBUG, "send_channel_setup_response_message:")); - s = trans_get_out_s(g_con_trans, 8192); - - if (s == 0) - { - return 1; - } - - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 4); /* msg id */ - out_uint32_le(s, 8); /* size */ - s_mark_end(s); - return trans_write_copy(g_con_trans); -} - -/*****************************************************************************/ -/* returns error */ -static int -send_channel_data_response_message(void) -{ - struct stream *s = (struct stream *)NULL; - - LOGM((LOG_LEVEL_DEBUG, "send_channel_data_response_message:")); - s = trans_get_out_s(g_con_trans, 8192); - - if (s == 0) - { - return 1; - } - - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 6); /* msg id */ - out_uint32_le(s, 8); /* size */ - s_mark_end(s); - return trans_write_copy(g_con_trans); -} - -/*****************************************************************************/ -/* returns error */ -static int -process_message_init(struct stream *s) -{ - LOGM((LOG_LEVEL_DEBUG, "process_message_init:")); - return send_init_response_message(); -} - /*****************************************************************************/ /* returns error */ static int @@ -485,8 +333,6 @@ process_message_channel_setup(struct stream *s) int index; int rv; struct chan_item *ci; - struct chan_out_data *cod; - struct chan_out_data *old_cod; g_num_chan_items = 0; g_cliprdr_index = -1; @@ -497,7 +343,6 @@ process_message_channel_setup(struct stream *s) g_rdpsnd_chan_id = -1; g_rdpdr_chan_id = -1; g_rail_chan_id = -1; - g_drdynvc_chan_id = -1; LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup:")); in_uint16_le(s, num_chans); LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: num_chans %d", @@ -509,25 +354,6 @@ process_message_channel_setup(struct stream *s) g_memset(ci->name, 0, sizeof(ci->name)); in_uint8a(s, ci->name, 8); in_uint16_le(s, ci->id); - /* there might be leftover data from last session after reconnecting - so free it */ - if (ci->head != 0) - { - cod = ci->head; - while (1) - { - free_stream(cod->s); - old_cod = cod; - cod = cod->next; - g_free(old_cod); - if (ci->tail == old_cod) - { - break; - } - } - } - ci->head = 0; - ci->tail = 0; in_uint16_le(s, ci->flags); LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: chan name '%s' " "id %d flags %8.8x", ci->name, ci->id, ci->flags)); @@ -556,11 +382,6 @@ process_message_channel_setup(struct stream *s) g_rail_index = g_num_chan_items; g_rail_chan_id = ci->id; } - else if (g_strcasecmp(ci->name, "drdynvc") == 0) - { - g_drdynvc_index = g_num_chan_items; // LK_TODO use this - g_drdynvc_chan_id = ci->id; // LK_TODO use this - } else { LOG(10, ("other %s", ci->name)); @@ -569,7 +390,7 @@ process_message_channel_setup(struct stream *s) g_num_chan_items++; } - rv = send_channel_setup_response_message(); + rv = 0; if (g_cliprdr_index >= 0) { @@ -593,12 +414,6 @@ process_message_channel_setup(struct stream *s) rail_init(); } - if (g_drdynvc_index >= 0) - { - g_memset(&g_dvc_channels[0], 0, sizeof(g_dvc_channels)); - drdynvc_init(); - } - return rv; } @@ -607,12 +422,13 @@ process_message_channel_setup(struct stream *s) static int process_message_channel_data(struct stream *s) { - int chan_id = 0; - int chan_flags = 0; - int rv = 0; - int length = 0; - int total_length = 0; + int chan_id; + int chan_flags; + int rv; + int length; + int total_length; int index; + int found; struct stream *ls; struct trans *ltran; struct xrdp_api_data *api_data; @@ -624,7 +440,7 @@ process_message_channel_data(struct stream *s) LOGM((LOG_LEVEL_DEBUG, "process_message_channel_data: chan_id %d " "chan_flags %d", chan_id, chan_flags)); LOG(10, ("process_message_channel_data")); - rv = send_channel_data_response_message(); + rv = 0; if (rv == 0) { @@ -644,22 +460,20 @@ process_message_channel_data(struct stream *s) { rv = rail_data_in(s, chan_id, chan_flags, length, total_length); } - else if (chan_id == g_drdynvc_chan_id) - { - rv = drdynvc_data_in(s, chan_id, chan_flags, length, total_length); - } - else if (g_api_con_trans_list != 0) + else { + found = 0; for (index = 0; index < g_api_con_trans_list->count; index++) { ltran = (struct trans *) list_get_item(g_api_con_trans_list, index); - if (ltran != 0) + if (ltran != NULL) { api_data = (struct xrdp_api_data *) (ltran->callback_data); - if (api_data != 0) + if (api_data != NULL) { if (api_data->chan_id == chan_id) { + found = 1; ls = ltran->out_s; if (chan_flags & 1) /* first */ { @@ -669,25 +483,333 @@ process_message_channel_data(struct stream *s) if (chan_flags & 2) /* last */ { s_mark_end(ls); - rv = trans_force_write(ltran); + rv = trans_write_copy(ltran); } break; } } } } + if (found == 0) + { + LOG(0, ("process_message_channel_data: not found channel %d", chan_id)); + } } + } return rv; } /*****************************************************************************/ /* returns error */ +/* open response from client */ static int -process_message_channel_data_response(struct stream *s) +process_message_drdynvc_open_response(struct stream *s) { - LOG(10, ("process_message_channel_data_response:")); - check_chan_items(); + struct chansrv_drdynvc *drdynvc; + int chan_id; + int creation_status; + + LOG(10, ("process_message_drdynvc_open_response:")); + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint32_le(s, chan_id); + in_uint32_le(s, creation_status); + if ((chan_id < 0) || (chan_id > 255)) + { + return 1; + } + drdynvc = g_drdynvcs + chan_id; + if (drdynvc->status != CHANSRV_DRDYNVC_STATUS_OPEN_SENT) + { + g_writeln("process_message_drdynvc_open_response: status not right"); + return 1; + } + if (creation_status == 0) + { + drdynvc->status = CHANSRV_DRDYNVC_STATUS_OPEN; + } + else + { + drdynvc->status = CHANSRV_DRDYNVC_STATUS_CLOSED; + } + if (drdynvc->open_response != NULL) + { + if (drdynvc->open_response(chan_id, creation_status) != 0) + { + return 1; + } + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +/* close response from client */ +static int +process_message_drdynvc_close_response(struct stream *s) +{ + struct chansrv_drdynvc *drdynvc; + int chan_id; + + LOG(10, ("process_message_drdynvc_close_response:")); + if (!s_check_rem(s, 4)) + { + return 1; + } + in_uint32_le(s, chan_id); + if ((chan_id < 0) || (chan_id > 255)) + { + return 1; + } + drdynvc = g_drdynvcs + chan_id; + if (drdynvc->status != CHANSRV_DRDYNVC_STATUS_CLOSE_SENT) + { + g_writeln("process_message_drdynvc_close_response: status not right"); + return 0; + } + drdynvc->status = CHANSRV_DRDYNVC_STATUS_CLOSED; + if (drdynvc->close_response != NULL) + { + if (drdynvc->close_response(chan_id) != 0) + { + return 1; + } + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +/* data from client */ +static int +process_message_drdynvc_data_first(struct stream *s) +{ + struct chansrv_drdynvc *drdynvc; + int chan_id; + int bytes; + int total_bytes; + char *data; + + LOG(10, ("process_message_drdynvc_data_first:")); + if (!s_check_rem(s, 12)) + { + return 1; + } + in_uint32_le(s, chan_id); + in_uint32_le(s, bytes); + in_uint32_le(s, total_bytes); + if (!s_check_rem(s, bytes)) + { + return 1; + } + in_uint8p(s, data, bytes); + if ((chan_id < 0) || (chan_id > 255)) + { + return 1; + } + drdynvc = g_drdynvcs + chan_id; + if (drdynvc->data_first != NULL) + { + if (drdynvc->data_first(chan_id, data, bytes, total_bytes) != 0) + { + return 1; + } + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +/* data from client */ +static int +process_message_drdynvc_data(struct stream *s) +{ + struct chansrv_drdynvc *drdynvc; + int chan_id; + int bytes; + char *data; + + LOG(10, ("process_message_drdynvc_data:")); + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint32_le(s, chan_id); + in_uint32_le(s, bytes); + if (!s_check_rem(s, bytes)) + { + return 1; + } + in_uint8p(s, data, bytes); + drdynvc = g_drdynvcs + chan_id; + if (drdynvc->data != NULL) + { + if (drdynvc->data(chan_id, data, bytes) != 0) + { + return 1; + } + } + return 0; +} + +/*****************************************************************************/ +/* open call from chansrv */ +int +chansrv_drdynvc_open(const char *name, int flags, + struct chansrv_drdynvc_procs *procs, int *chan_id) +{ + struct stream *s; + int name_bytes; + int lchan_id; + int error; + + lchan_id = 1; + while (g_drdynvcs[lchan_id].status != CHANSRV_DRDYNVC_STATUS_CLOSED) + { + lchan_id++; + if (lchan_id > 255) + { + return 1; + } + } + s = trans_get_out_s(g_con_trans, 8192); + if (s == NULL) + { + return 1; + } + name_bytes = g_strlen(name); + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8 + 4 + name_bytes + 4 + 4); + out_uint32_le(s, 12); /* msg id */ + out_uint32_le(s, 8 + 4 + name_bytes + 4 + 4); + out_uint32_le(s, name_bytes); + out_uint8a(s, name, name_bytes); + out_uint32_le(s, flags); + out_uint32_le(s, lchan_id); + s_mark_end(s); + error = trans_write_copy(g_con_trans); + if (error == 0) + { + if (chan_id != NULL) + { + *chan_id = lchan_id; + g_drdynvcs[lchan_id].open_response = procs->open_response; + g_drdynvcs[lchan_id].close_response = procs->close_response; + g_drdynvcs[lchan_id].data_first = procs->data_first; + g_drdynvcs[lchan_id].data = procs->data; + g_drdynvcs[lchan_id].status = CHANSRV_DRDYNVC_STATUS_OPEN_SENT; + + } + } + return error; +} + +/*****************************************************************************/ +/* close call from chansrv */ +int +chansrv_drdynvc_close(int chan_id) +{ + struct stream *s; + int error; + + s = trans_get_out_s(g_con_trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 20); + out_uint32_le(s, 14); /* msg id */ + out_uint32_le(s, 12); + out_uint32_le(s, chan_id); + s_mark_end(s); + error = trans_write_copy(g_con_trans); + g_drdynvcs[chan_id].status = CHANSRV_DRDYNVC_STATUS_CLOSE_SENT; + return error; +} + +/*****************************************************************************/ +int +chansrv_drdynvc_data_first(int chan_id, const char *data, int data_bytes, + int total_data_bytes) +{ + struct stream *s; + int error; + + //g_writeln("chansrv_drdynvc_data_first: data_bytes %d total_data_bytes %d", + // data_bytes, total_data_bytes); + s = trans_get_out_s(g_con_trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 28 + data_bytes); + out_uint32_le(s, 16); /* msg id */ + out_uint32_le(s, 20 + data_bytes); + out_uint32_le(s, chan_id); + out_uint32_le(s, data_bytes); + out_uint32_le(s, total_data_bytes); + out_uint8a(s, data, data_bytes); + s_mark_end(s); + error = trans_write_copy(g_con_trans); + return error; +} + +/*****************************************************************************/ +int +chansrv_drdynvc_data(int chan_id, const char *data, int data_bytes) +{ + struct stream *s; + int error; + + //g_writeln("chansrv_drdynvc_data: data_bytes %d", data_bytes); + s = trans_get_out_s(g_con_trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 24 + data_bytes); + out_uint32_le(s, 18); /* msg id */ + out_uint32_le(s, 16 + data_bytes); + out_uint32_le(s, chan_id); + out_uint32_le(s, data_bytes); + out_uint8a(s, data, data_bytes); + s_mark_end(s); + error = trans_write_copy(g_con_trans); + return error; +} + +/*****************************************************************************/ +int +chansrv_drdynvc_send_data(int chan_id, const char *data, int data_bytes) +{ + int this_send_bytes; + + //g_writeln("chansrv_drdynvc_send_data: data_bytes %d", data_bytes); + if (data_bytes > 1590) + { + if (chansrv_drdynvc_data_first(chan_id, data, 1590, data_bytes) != 0) + { + return 1; + } + data_bytes -= 1590; + data += 1590; + } + while (data_bytes > 0) + { + this_send_bytes = MIN(1590, data_bytes); + if (chansrv_drdynvc_data(chan_id, data, this_send_bytes) != 0) + { + return 1; + } + data_bytes -= this_send_bytes; + data += this_send_bytes; + } return 0; } @@ -725,17 +847,23 @@ process_message(void) switch (id) { - case 1: /* init */ - rv = process_message_init(s); - break; case 3: /* channel setup */ rv = process_message_channel_setup(s); break; case 5: /* channel data */ rv = process_message_channel_data(s); break; - case 7: /* channel data response */ - rv = process_message_channel_data_response(s); + case 13: /* drdynvc open response */ + rv = process_message_drdynvc_open_response(s); + break; + case 15: /* drdynvc close response */ + rv = process_message_drdynvc_close_response(s); + break; + case 17: /* drdynvc data first */ + rv = process_message_drdynvc_data_first(s); + break; + case 19: /* drdynvc data */ + rv = process_message_drdynvc_data(s); break; default: LOGM((LOG_LEVEL_ERROR, "process_message: unknown msg %d", id)); @@ -744,7 +872,8 @@ process_message(void) if (rv != 0) { - break; + g_writeln("process_message: error rv %d id %d", rv, id); + rv = 0; } s->p = next_msg; @@ -782,11 +911,119 @@ my_trans_data_in(struct trans *trans) { /* here, the entire message block is read in, process it */ error = process_message(); + if (error == 0) + { + } + else + { + g_writeln("my_trans_data_in: process_message failed"); + } + } + else + { + g_writeln("my_trans_data_in: trans_force_read failed"); } return error; } +/*****************************************************************************/ +struct trans * +get_api_trans_from_chan_id(int chan_id) +{ + return g_drdynvcs[chan_id].xrdp_api_trans; +} + +/*****************************************************************************/ +static int +my_api_open_response(int chan_id, int creation_status) +{ + struct trans *trans; + struct stream *s; + + //g_writeln("my_api_open_response: chan_id %d creation_status %d", + // chan_id, creation_status); + trans = get_api_trans_from_chan_id(chan_id); + if (trans == NULL) + { + return 1; + } + s = trans_get_out_s(trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, creation_status); + s_mark_end(s); + if (trans_write_copy(trans) != 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +static int +my_api_close_response(int chan_id) +{ + //g_writeln("my_api_close_response:"); + return 0; +} + +/*****************************************************************************/ +static int +my_api_data_first(int chan_id, char *data, int bytes, int total_bytes) +{ + struct trans *trans; + struct stream *s; + + //g_writeln("my_api_data_first: bytes %d total_bytes %d", bytes, total_bytes); + trans = get_api_trans_from_chan_id(chan_id); + if (trans == NULL) + { + return 1; + } + s = trans_get_out_s(trans, bytes); + if (s == NULL) + { + return 1; + } + out_uint8a(s, data, bytes); + s_mark_end(s); + if (trans_write_copy(trans) != 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +static int +my_api_data(int chan_id, char *data, int bytes) +{ + struct trans *trans; + struct stream *s; + + //g_writeln("my_api_data: bytes %d", bytes); + trans = get_api_trans_from_chan_id(chan_id); + if (trans == NULL) + { + return 1; + } + s = trans_get_out_s(trans, bytes); + if (s == NULL) + { + return 1; + } + out_uint8a(s, data, bytes); + s_mark_end(s); + if (trans_write_copy(trans) != 0) + { + return 1; + } + return 0; +} + /* * called when WTSVirtualChannelWrite() is invoked in xrdpapi.c * @@ -794,94 +1031,130 @@ my_trans_data_in(struct trans *trans) int my_api_trans_data_in(struct trans *trans) { - struct stream *s; - int bytes_read; - int i32; + struct stream *s; + struct stream *out_s; struct xrdp_api_data *ad; + int index; + int rv; + int bytes; + int ver; + int channel_name_bytes; + struct chansrv_drdynvc_procs procs; + char *chan_name; - //g_writeln("my_api_trans_data_in:"); - - LOG(10, ("my_api_trans_data_in:")); - - if (trans == 0) + //g_writeln("my_api_trans_data_in: extra_flags %d", trans->extra_flags); + rv = 0; + ad = (struct xrdp_api_data *) (trans->callback_data); + s = trans_get_in_s(trans); + if (trans->extra_flags == 0) { - return 0; - } - - if (g_api_con_trans_list != 0) - { - if (list_index_of(g_api_con_trans_list, (tintptr) trans) == -1) + in_uint32_le(s, bytes); + in_uint32_le(s, ver); + //g_writeln("my_api_trans_data_in: bytes %d ver %d", bytes, ver); + if (ver != 0) { return 1; } + trans->header_size = bytes; + trans->extra_flags = 1; } - - LOGM((LOG_LEVEL_DEBUG, "my_api_trans_data_in:")); - - s = trans_get_in_s(trans); - bytes_read = g_tcp_recv(trans->sck, s->data, 16, 0); - if (bytes_read == 16) + else if (trans->extra_flags == 1) { - if (g_memcmp(s->data, g_xrdpapi_magic, 12) == 0) + rv = 1; + in_uint32_le(s, channel_name_bytes); + //g_writeln("my_api_trans_data_in: channel_name_bytes %d", channel_name_bytes); + chan_name = g_new0(char, channel_name_bytes + 1); + if (chan_name == NULL) { - in_uint8s(s, 12); - in_uint32_le(s, bytes_read); - init_stream(s, bytes_read); - if (trans_force_read(trans, bytes_read)) - log_message(LOG_LEVEL_ERROR, "chansrv.c: error reading from transport"); + return 1; } - else if (g_tcp_select(trans->sck, 0) & 1) + in_uint8a(s, chan_name, channel_name_bytes); + in_uint32_le(s, ad->chan_flags); + //g_writeln("my_api_trans_data_in: chan_name %s chan_flags 0x%8.8x", chan_name, ad->chan_flags); + if (ad->chan_flags == 0) { - i32 = bytes_read; - bytes_read = g_tcp_recv(trans->sck, s->data + bytes_read, - 8192 * 4 - bytes_read, 0); - if (bytes_read > 0) + /* SVC */ + for (index = 0; index < g_num_chan_items; index++) { - bytes_read += i32; + if (g_strcasecmp(g_chan_items[index].name, chan_name) == 0) + { + ad->chan_id = g_chan_items[index].id; + rv = 0; + break; + } } - } - } - - //g_writeln("bytes_read %d", bytes_read); - - if (bytes_read > 0) - { - LOG(10, ("my_api_trans_data_in: got data %d", bytes_read)); - ad = (struct xrdp_api_data *) trans->callback_data; - - if (ad->dvc_chan_id < 0) - { - /* writing data to a static virtual channel */ - if (send_channel_data(ad->chan_id, s->data, bytes_read) != 0) + if (rv == 0) { - LOG(0, ("my_api_trans_data_in: send_channel_data failed")); + /* open ok */ + out_s = trans_get_out_s(trans, 8192); + if (out_s == NULL) + { + return 1; + } + out_uint32_le(out_s, 0); + s_mark_end(out_s); + if (trans_write_copy(trans) != 0) + { + return 1; + } + } + else + { + /* open failed */ + out_s = trans_get_out_s(trans, 8192); + if (out_s == NULL) + { + return 1; + } + out_uint32_le(out_s, 1); + s_mark_end(out_s); + if (trans_write_copy(trans) != 0) + { + return 1; + } } } else { - /* writing data to a dynamic virtual channel */ - drdynvc_write_data(ad->dvc_chan_id, s->data, bytes_read); + /* DVS */ + g_memset(&procs, 0, sizeof(procs)); + procs.open_response = my_api_open_response; + procs.close_response = my_api_close_response; + procs.data_first = my_api_data_first; + procs.data = my_api_data; + rv = chansrv_drdynvc_open(chan_name, ad->chan_flags, + &procs, &(ad->chan_id)); + //g_writeln("my_api_trans_data_in: chansrv_drdynvc_open rv %d " + // "chan_id %d", rv, ad->chan_id); + g_drdynvcs[ad->chan_id].xrdp_api_trans = trans; } + g_free(chan_name); + init_stream(s, 0); + trans->extra_flags = 2; + trans->header_size = 0; } else { - ad = (struct xrdp_api_data *) (trans->callback_data); - if ((ad != NULL) && (ad->dvc_chan_id > 0)) + bytes = g_sck_recv(trans->sck, s->data, s->size, 0); + if (bytes < 1) { - /* WTSVirtualChannelClose() was invoked, or connection dropped */ - LOG(10, ("my_api_trans_data_in: g_tcp_recv failed or disconnected for DVC")); - ad->transp = NULL; - ad->is_connected = 0; - remove_struct_with_chan_id(ad->dvc_chan_id); + //g_writeln("my_api_trans_data_in: disconnect"); + return 1; + } + if (ad->chan_flags == 0) + { + /* SVC */ + rv = send_channel_data(ad->chan_id, s->data, bytes); } else { - LOG(10, ("my_api_trans_data_in: g_tcp_recv failed or disconnected for SVC")); + /* DVS */ + //g_writeln("my_api_trans_data_in: s->size %d bytes %d", s->size, bytes); + rv = chansrv_drdynvc_send_data(ad->chan_id, s->data, bytes); } - return 1; + init_stream(s, 0); } - - return 0; + return rv; } /*****************************************************************************/ @@ -926,92 +1199,24 @@ int my_api_trans_conn_in(struct trans *trans, struct trans *new_trans) { struct xrdp_api_data *ad; - struct stream *s; - int error; - int index; - char chan_pri; - if ((trans == 0) || (trans != g_api_lis_trans) || (new_trans == 0)) + //g_writeln("my_api_trans_conn_in:"); + if ((trans == NULL) || (trans != g_api_lis_trans) || (new_trans == NULL)) { + g_writeln("my_api_trans_conn_in: error"); return 1; } - - LOGM((LOG_LEVEL_DEBUG, "my_api_trans_conn_in:")); - LOG(10, ("my_api_trans_conn_in: got incoming")); - - s = trans_get_in_s(new_trans); - s->end = s->data; - - error = trans_force_read(new_trans, 64); - - if (error != 0) - { - LOG(0, ("my_api_trans_conn_in: trans_force_read failed")); - trans_delete(new_trans); - return 1; - } - - s->end = s->data; - - ad = (struct xrdp_api_data *) g_malloc(sizeof(struct xrdp_api_data), 1); - g_memcpy(ad->header, s->data, 64); - - ad->flags = GGET_UINT32(ad->header, 16); - ad->chan_id = -1; - ad->dvc_chan_id = -1; - - if (ad->flags > 0) - { - /* opening a dynamic virtual channel */ - - if ((index = find_empty_slot_in_dvc_channels()) < 0) - { - /* exceeded MAX_DVC_CHANNELS */ - LOG(0, ("my_api_trans_conn_in: MAX_DVC_CHANNELS reached; giving up!")) - g_free(ad); - trans_delete(new_trans); - return 1; - } - - g_dvc_channels[index] = ad; - chan_pri = 4 - ad->flags; - ad->dvc_chan_id = g_dvc_chan_id++; - ad->is_connected = 0; - ad->transp = new_trans; - drdynvc_send_open_channel_request(chan_pri, ad->dvc_chan_id, ad->header); - } - else - { - /* opening a static virtual channel */ - - for (index = 0; index < g_num_chan_items; index++) - { - LOG(10, ("my_api_trans_conn_in: %s %s", ad->header, - g_chan_items[index].name)); - - if (g_strcasecmp(ad->header, g_chan_items[index].name) == 0) - { - LOG(10, ("my_api_trans_conn_in: found it at %d", index)); - ad->chan_id = g_chan_items[index].id; - break; - } - } - if (index == g_num_chan_items) - { - g_writeln("did not find SVC named %s", ad->header); - } - } - - new_trans->callback_data = ad; - - if (g_api_con_trans_list == 0) - { - g_api_con_trans_list = list_create(); - } new_trans->trans_data_in = my_api_trans_data_in; - new_trans->header_size = 0; - list_add_item(g_api_con_trans_list, (tintptr) new_trans); - + new_trans->header_size = 8; + new_trans->no_stream_init_on_data_in = 1; + ad = g_new0(struct xrdp_api_data, 1); + if (ad == NULL) + { + g_writeln("my_api_trans_conn_in: error"); + return 1; + } + new_trans->callback_data = ad; + list_add_item(g_api_con_trans_list, (intptr_t) new_trans); return 0; } @@ -1076,6 +1281,96 @@ setup_api_listen(void) return 0; } +/*****************************************************************************/ +static int +api_con_trans_list_get_wait_objs_rw(intptr_t *robjs, int *rcount, + intptr_t *wobjs, int *wcount, + int *timeout) +{ + int api_con_index; + struct trans *ltran; + + for (api_con_index = g_api_con_trans_list->count - 1; + api_con_index >= 0; + api_con_index--) + { + ltran = (struct trans *) + list_get_item(g_api_con_trans_list, api_con_index); + if (ltran != NULL) + { + trans_get_wait_objs_rw(ltran, robjs, rcount, wobjs, wcount, + timeout); + } + } + return 0; +} + +/*****************************************************************************/ +static int +api_con_trans_list_check_wait_objs(void) +{ + int api_con_index; + int drdynvc_index; + struct trans *ltran; + struct xrdp_api_data *ad; + + for (api_con_index = g_api_con_trans_list->count - 1; + api_con_index >= 0; + api_con_index--) + { + ltran = (struct trans *) + list_get_item(g_api_con_trans_list, api_con_index); + if (ltran != NULL) + { + if (trans_check_wait_objs(ltran) != 0) + { + /* disconnect */ + list_remove_item(g_api_con_trans_list, api_con_index); + ad = (struct xrdp_api_data *) (ltran->callback_data); + if (ad->chan_flags != 0) + { + chansrv_drdynvc_close(ad->chan_id); + } + for (drdynvc_index = 0; + drdynvc_index < (int) ARRAYSIZE(g_drdynvcs); + drdynvc_index++) + { + if (g_drdynvcs[drdynvc_index].xrdp_api_trans == ltran) + { + g_drdynvcs[drdynvc_index].xrdp_api_trans = NULL; + } + } + g_free(ad); + trans_delete(ltran); + } + } + } + return 0; +} + +/*****************************************************************************/ +static int +api_con_trans_list_remove_all(void) +{ + int api_con_index; + struct trans *ltran; + + for (api_con_index = g_api_con_trans_list->count - 1; + api_con_index >= 0; + api_con_index--) + { + ltran = (struct trans *) + list_get_item(g_api_con_trans_list, api_con_index); + if (ltran != NULL) + { + list_remove_item(g_api_con_trans_list, api_con_index); + g_free(ltran->callback_data); + trans_delete(ltran); + } + } + return 0; +} + /*****************************************************************************/ THREAD_RV THREAD_CC channel_thread_loop(void *in_val) @@ -1086,12 +1381,11 @@ channel_thread_loop(void *in_val) int num_wobjs; int timeout; int error; - int index; THREAD_RV rv; - struct trans *ltran; LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread start")); rv = 0; + g_api_con_trans_list = list_create(); setup_api_listen(); error = setup_listen(); @@ -1105,6 +1399,7 @@ channel_thread_loop(void *in_val) trans_get_wait_objs(g_lis_trans, objs, &num_objs); trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); + //g_writeln("timeout %d", timeout); while (g_obj_wait(objs, num_objs, wobjs, num_wobjs, timeout) == 0) { check_timeout(); @@ -1157,24 +1452,8 @@ channel_thread_loop(void *in_val) LOG(0, ("channel_thread_loop: trans_check_wait_objs failed")); } } - - if (g_api_con_trans_list != 0) - { - for (index = g_api_con_trans_list->count - 1; index >= 0; index--) - { - ltran = (struct trans *) list_get_item(g_api_con_trans_list, index); - if (ltran != 0) - { - if (trans_check_wait_objs(ltran) != 0) - { - list_remove_item(g_api_con_trans_list, index); - g_free(ltran->callback_data); - trans_delete(ltran); - } - } - } - } - + /* check the wait_objs in g_api_con_trans_list */ + api_con_trans_list_check_wait_objs(); xcommon_check_wait_objs(); sound_check_wait_objs(); dev_redir_check_wait_objs(); @@ -1184,23 +1463,16 @@ channel_thread_loop(void *in_val) num_wobjs = 0; objs[num_objs] = g_term_event; num_objs++; - trans_get_wait_objs(g_lis_trans, objs, &num_objs); + trans_get_wait_objs_rw(g_lis_trans, objs, &num_objs, + wobjs, &num_wobjs, &timeout); trans_get_wait_objs_rw(g_con_trans, objs, &num_objs, wobjs, &num_wobjs, &timeout); - trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); - - if (g_api_con_trans_list != 0) - { - for (index = g_api_con_trans_list->count - 1; index >= 0; index--) - { - ltran = (struct trans *) list_get_item(g_api_con_trans_list, index); - if (ltran != 0) - { - trans_get_wait_objs(ltran, objs, &num_objs); - } - } - } - + trans_get_wait_objs_rw(g_api_lis_trans, objs, &num_objs, + wobjs, &num_wobjs, &timeout); + /* get the wait_objs from in g_api_con_trans_list */ + api_con_trans_list_get_wait_objs_rw(objs, &num_objs, + wobjs, &num_wobjs, + &timeout); xcommon_get_wait_objs(objs, &num_objs, &timeout); sound_get_wait_objs(objs, &num_objs, &timeout); dev_redir_get_wait_objs(objs, &num_objs, &timeout); @@ -1215,20 +1487,8 @@ channel_thread_loop(void *in_val) g_con_trans = 0; trans_delete(g_api_lis_trans); g_api_lis_trans = 0; - if (g_api_con_trans_list != 0) - { - for (index = g_api_con_trans_list->count - 1; index >= 0; index--) - { - ltran = (struct trans *) list_get_item(g_api_con_trans_list, index); - if (ltran != 0) - { - list_remove_item(g_api_con_trans_list, index); - g_free(ltran->callback_data); - trans_delete(ltran); - } - } - list_delete(g_api_con_trans_list); - } + api_con_trans_list_remove_all(); + list_delete(g_api_con_trans_list); LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread stop")); g_set_wait_obj(g_thread_done_event); return rv; @@ -1551,6 +1811,8 @@ main(int argc, char **argv) g_file_delete(log_file); } + g_memset(g_drdynvcs, 0, sizeof(g_drdynvcs)); + logconfig.log_file = log_file; logconfig.fd = -1; logconfig.log_level = log_level; @@ -1649,66 +1911,3 @@ main(int argc, char **argv) return 0; } -/* - * return unused slot in dvc_channels[] - * - * @return unused slot index on success, -1 on failure - ******************************************************************************/ -int -find_empty_slot_in_dvc_channels(void) -{ - int i; - - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (g_dvc_channels[i] == NULL) - { - return i; - } - } - - return -1; -} - -/* - * return struct xrdp_api_data that contains specified dvc_chan_id - * - * @param dvc_chan_id channel id to look for - * - * @return xrdp_api_data struct containing dvc_chan_id or NULL on failure - ******************************************************************************/ -struct xrdp_api_data * -struct_from_dvc_chan_id(tui32 dvc_chan_id) -{ - int i; - - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (g_dvc_channels[i] != NULL && - g_dvc_channels[i]->dvc_chan_id >= 0 && - (tui32) g_dvc_channels[i]->dvc_chan_id == dvc_chan_id) - { - return g_dvc_channels[i]; - } - } - - return NULL; -} - -int -remove_struct_with_chan_id(tui32 dvc_chan_id) -{ - int i; - - for (i = 0; i < MAX_DVC_CHANNELS; i++) - { - if (g_dvc_channels[i] != NULL && - g_dvc_channels[i]->dvc_chan_id >= 0 && - (tui32) g_dvc_channels[i]->dvc_chan_id == dvc_chan_id) - { - g_dvc_channels[i] = NULL; - return 0; - } - } - return -1; -} diff --git a/sesman/chansrv/chansrv.h b/sesman/chansrv/chansrv.h index e75810c8..e1a0e34f 100644 --- a/sesman/chansrv/chansrv.h +++ b/sesman/chansrv/chansrv.h @@ -24,46 +24,20 @@ #include "parse.h" #include "log.h" -#define MAX_DVC_CHANNELS 32 - -struct chan_out_data -{ - struct stream *s; - struct chan_out_data *next; -}; - struct chan_item { int id; int flags; char name[16]; - struct chan_out_data *head; - struct chan_out_data *tail; -}; - -/* data in struct trans::callback_data */ -struct xrdp_api_data -{ - int chan_id; - char header[64]; - int flags; - - /* for dynamic virtual channels */ - struct trans *transp; - int dvc_chan_id; - int is_connected; }; int g_is_term(void); -int send_channel_data(int chan_id, char *data, int size); +int send_channel_data(int chan_id, const char *data, int size); int send_rail_drawing_orders(char* data, int size); int main_cleanup(void); int add_timeout(int msoffset, void (*callback)(void* data), void* data); -int find_empty_slot_in_dvc_channels(void); -struct xrdp_api_data * struct_from_dvc_chan_id(tui32 dvc_chan_id); -int remove_struct_with_chan_id(tui32 dvc_chan_id); #define LOG_LEVEL 5 @@ -97,4 +71,25 @@ int remove_struct_with_chan_id(tui32 dvc_chan_id); ((GGET_UINT16(_ptr, (_offset) + 2)) << 16) #endif +struct chansrv_drdynvc_procs +{ + int (*open_response)(int chan_id, int creation_status); + int (*close_response)(int chan_id); + int (*data_first)(int chan_id, char *data, int bytes, int total_bytes); + int (*data)(int chan_id, char *data, int bytes); +}; + +int +chansrv_drdynvc_open(const char *name, int flags, + struct chansrv_drdynvc_procs *procs, int *chan_id); +int +chansrv_drdynvc_close(int chan_id); +int +chansrv_drdynvc_data_first(int chan_id, const char *data, int data_bytes, + int total_data_bytes); +int +chansrv_drdynvc_data(int chan_id, const char *data, int data_bytes); +int +chansrv_drdynvc_send_data(int chan_id, const char *data, int data_bytes); + #endif diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index ff50f136..1095b63e 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -1228,10 +1228,17 @@ xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name, { XRDP_INODE *xinode; XRDP_INODE *xinodep; + time_t cur_time; if ((name == NULL) || (strlen(name) == 0)) return NULL; + /* Do we have an inode table yet? */ + if (xfuse_init_xrdp_fs()) + { + return NULL; + } + xinode = g_new0(XRDP_INODE, 1); if (xinode == NULL) { @@ -1239,14 +1246,16 @@ xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name, return NULL; } + cur_time = time(0); + xinode->parent_inode = pinode; xinode->inode = g_xrdp_fs.next_node++; xinode->nlink = 1; xinode->uid = getuid(); xinode->gid = getgid(); - xinode->atime = time(0); - xinode->mtime = time(0); - xinode->ctime = time(0); + xinode->atime = cur_time; + xinode->mtime = cur_time; + xinode->ctime = cur_time; xinode->device_id = device_id; xinode->is_synced = 1; strcpy(xinode->name, name); diff --git a/sesman/chansrv/drdynvc.c b/sesman/chansrv/drdynvc.c deleted file mode 100644 index c02bdadb..00000000 --- a/sesman/chansrv/drdynvc.c +++ /dev/null @@ -1,531 +0,0 @@ -/** - * xrdp: A Remote Desktop Protocol server. - * - * Copyright (C) Laxmikant Rashinkar 2012 LK.Rashinkar@gmail.com - * - * 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. - */ - -#if defined(HAVE_CONFIG_H) -#include -#endif - -#include "drdynvc.h" - -extern int g_drdynvc_chan_id; /* in chansrv.c */ -int g_drdynvc_inited = 0; - -static int drdynvc_send_capability_request(uint16_t version); -static int drdynvc_process_capability_response(struct stream* s, unsigned char cmd); -static int drdynvc_process_open_channel_response(struct stream *s, unsigned char cmd); -static int drdynvc_process_close_channel_response(struct stream *s, unsigned char cmd); -static int drdynvc_process_data_first(struct stream* s, unsigned char cmd); -static int drdynvc_process_data(struct stream* s, unsigned char cmd); -static int drdynvc_insert_uint_124(struct stream *s, uint32_t val); -static int drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p); - -/** - * bring up dynamic virtual channel - * - * @return 0 on success, -1 on response - ******************************************************************************/ -int -drdynvc_init(void) -{ - /* bring up X11 */ - xcommon_init(); - - /* let client know what version of DVC we support */ - drdynvc_send_capability_request(2); - - return 0; -} - -/** - * let DVC Manager on client end know what version of protocol we support - * client will respond with version that it supports - * - * @return 0 on success, -1 on response - ******************************************************************************/ -static int -drdynvc_send_capability_request(uint16_t version) -{ - struct stream *s; - int bytes_in_stream; - - /* setup stream */ - make_stream(s); - init_stream(s, MAX_PDU_SIZE); - - out_uint8(s, 0x50); /* insert cmd */ - out_uint8(s, 0x00); /* insert padding */ - out_uint16_le(s, version); /* insert version */ - - /* channel priority unused for now */ - out_uint16_le(s, 0x0000); /* priority charge 0 */ - out_uint16_le(s, 0x0000); /* priority charge 1 */ - out_uint16_le(s, 0x0000); /* priority charge 2 */ - out_uint16_le(s, 0x0000); /* priority charge 3 */ - - /* send command to client */ - bytes_in_stream = stream_length_before_p(s); - send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream); - free_stream(s); - - return 0; -} - -/** - * process capability response received from DVC manager at client end - * - * @param s stream containing client response - * - * @return 0 on success, -1 on failure - ******************************************************************************/ -static int -drdynvc_process_capability_response(struct stream *s, unsigned char cmd) -{ - int cap_version; - - /* skip padding */ - in_uint8s(s, 1); - - /* read client's version */ - in_uint16_le(s, cap_version); - - if ((cap_version != 2) && (cap_version != 3)) - { - LOG(0, ("drdynvc_process_capability_response: incompatible DVC " - "version %d detected", cap_version)); - return -1; - } - - LOG(0, ("drdynvc_process_capability_response: DVC version %d selected", - cap_version)); - g_drdynvc_inited = 1; - - return 0; -} - -/** - * create a new dynamic virtual channel - * - * @pram channel_id channel id number - * @pram channel_name name of channel - * - * @return 0 on success, -1 on failure - ******************************************************************************/ -int -drdynvc_send_open_channel_request(int chan_pri, unsigned int chan_id, - char *chan_name) -{ - struct stream *s; - int bytes_in_stream; - int cbChId; - int name_length; - - if ((chan_name == NULL) || (strlen(chan_name) == 0)) - { - LOG(0, ("drdynvc_send_open_channel_request: bad channel name specified")); - return -1; - } - - make_stream(s); - init_stream(s, MAX_PDU_SIZE); - - name_length = strlen(chan_name); - - /* dummy command for now */ - out_uint8(s, 0); - - /* insert channel id */ - cbChId = drdynvc_insert_uint_124(s, chan_id); - - /* insert channel name */ - out_uint8a(s, chan_name, name_length + 1); - - /* insert command */ - s->data[0] = CMD_DVC_OPEN_CHANNEL | ((chan_pri << 2) & 0x0c) | cbChId; - - /* send command */ - bytes_in_stream = stream_length_before_p(s); - send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream); - free_stream(s); - - return 0; -} - -static int -drdynvc_process_open_channel_response(struct stream *s, unsigned char cmd) -{ - struct xrdp_api_data *adp; - - uint32_t chan_id; - int creation_status; - - drdynvc_get_chan_id(s, cmd, &chan_id); - in_uint32_le(s, creation_status); - - /* LK_TODO now do something using useful! */ - - if (creation_status < 0) - { - // TODO - } - else - { - /* get struct xrdp_api_data containing this channel id */ - if ((adp = struct_from_dvc_chan_id(chan_id)) == NULL) - { - LOG(0, ("drdynvc_process_open_channel_response: error : " - "could not find xrdp_api_data containing chan_id %d", chan_id)); - - return -1; - } - - adp->is_connected = 1; - } - - return 0; -} - -int -drdynvc_send_close_channel_request(unsigned int chan_id) -{ - struct stream *s; - int bytes_in_stream; - int cbChId; - - make_stream(s); - init_stream(s, MAX_PDU_SIZE); - - /* insert dummy cmd for now */ - out_uint8(s, 0); - - /* insert channel id */ - cbChId = drdynvc_insert_uint_124(s, chan_id); - - /* insert command */ - s->data[0] = CMD_DVC_CLOSE_CHANNEL | cbChId; - - /* send command */ - bytes_in_stream = stream_length_before_p(s); - send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream); - - free_stream(s); - return 0; -} - -static int -drdynvc_process_close_channel_response(struct stream *s, unsigned char cmd) -{ - uint32_t chan_id; - - drdynvc_get_chan_id(s, cmd, &chan_id); - - /* LK_TODO now do something using useful! */ - - return 0; -} - -/* - * send data to client - * - * @param chan_id the virtual channel to write to - * @param data data to write - * @param data_size number of bytes to write - * - * @return 0 on success, -1 on failure - ******************************************************************************/ -int drdynvc_write_data(uint32_t chan_id, char *data, int data_size) -{ - struct stream *s; - char *saved_ptr; - int cbChId; - int Len; - int bytes_in_stream; - int frag_size; - - if (data == NULL) - { - LOG(0, ("drdynvc_write_data: data is NULL\n")); - return -1; - } - - if (data_size <= 0) - { - return 0; - } - - make_stream(s); - init_stream(s, MAX_PDU_SIZE); - - /* this is a dummy write */ - out_uint8(s, 0); - - /* insert channel id */ - cbChId = drdynvc_insert_uint_124(s, chan_id); - - /* will data fit into one pkt? */ - bytes_in_stream = stream_length_before_p(s); - - if ((bytes_in_stream + data_size) <= MAX_PDU_SIZE) - { - /* yes it will - insert data */ - out_uint8p(s, data, data_size); - - /* insert command */ - s->data[0] = CMD_DVC_DATA | cbChId; - - /* write data to client */ - bytes_in_stream = stream_length_before_p(s); - send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream); - free_stream(s); - return 0; - } - - /* no it won't - fragment it */ - - saved_ptr = s->p; - - /* let client know how much data to expect */ - Len = drdynvc_insert_uint_124(s, data_size); - - /* insert data into first fragment */ - frag_size = MAX_PDU_SIZE - stream_length_before_p(s); - out_uint8p(s, data, frag_size); - - /* insert command */ - s->data[0] = CMD_DVC_DATA_FIRST | Len << 2 | cbChId; - - /* write first fragment to client */ - bytes_in_stream = stream_length_before_p(s); - send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream); - data_size -= frag_size; - data += frag_size; - s->data[0] = CMD_DVC_DATA | cbChId; - s->p = saved_ptr; - - /* now send rest of the data using CMD_DVC_DATA */ - while (data_size > 0) - { - frag_size = MAX_PDU_SIZE - stream_length_before_p(s); - - if (frag_size > data_size) - { - frag_size = data_size; - } - - out_uint8p(s, data, frag_size); - bytes_in_stream = stream_length_before_p(s); - send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream); - data_size -= frag_size; - data += frag_size; - s->p = saved_ptr; - } - - free_stream(s); - return 0; -} - -static int -drdynvc_process_data_first(struct stream *s, unsigned char cmd) -{ - struct xrdp_api_data *adp; - struct stream *ls; - - uint32_t chan_id; - int bytes_in_stream; - int Len; - - drdynvc_get_chan_id(s, cmd, &chan_id); - - Len = (cmd >> 2) & 0x03; - - /* skip data_len */ - if (Len == 0) - { - in_uint8s(s, 1); - } - else if (Len == 1) - { - in_uint8s(s, 2); - } - else - { - in_uint8s(s, 4); - } - - bytes_in_stream = stream_length_after_p(s); - - /* get struct xrdp_api_data containing this channel id */ - if ((adp = struct_from_dvc_chan_id(chan_id)) == NULL) - { - LOG(0, ("drdynvc_process_data_first: error : " - "could not find xrdp_api_data containing chan_id %d", chan_id)); - - return -1; - } - - ls = trans_get_out_s(adp->transp, MAX_PDU_SIZE); - out_uint8p(ls, s->p, bytes_in_stream); - s_mark_end(ls); - trans_force_write(adp->transp); - - return 0; -} - -static int -drdynvc_process_data(struct stream *s, unsigned char cmd) -{ - struct xrdp_api_data *adp; - struct stream *ls; - - uint32_t chan_id; - int bytes_in_stream; - - drdynvc_get_chan_id(s, cmd, &chan_id); - bytes_in_stream = stream_length_after_p(s); - - /* get struct xrdp_api_data containing this channel id */ - if ((adp = struct_from_dvc_chan_id(chan_id)) == NULL) - { - LOG(0, ("drdynvc_process_data: error : " - "could not find xrdp_api_data containing chan_id %d", chan_id)); - - return -1; - } - - ls = trans_get_out_s(adp->transp, MAX_PDU_SIZE); - out_uint8p(ls, s->p, bytes_in_stream); - s_mark_end(ls); - trans_force_write(adp->transp); - - return 0; -} - -/** - * process incoming data on a dynamic virtual channel - * - * @pram s stream containing the incoming data - * @pram chan_id LK_TODO - * @pram chan_flags LK_TODO - * @pram length LK_TODO - * @pram total_length LK_TODO - * - * @return 0 on success, -1 on failure - ******************************************************************************/ -int -drdynvc_data_in(struct stream *s, int chan_id, int chan_flags, int length, - int total_length) -{ - unsigned char cmd; - - in_uint8(s, cmd); /* read command */ - - switch (cmd & 0xf0) - { - case CMD_DVC_CAPABILITY: - drdynvc_process_capability_response(s, cmd); - break; - - case CMD_DVC_OPEN_CHANNEL: - drdynvc_process_open_channel_response(s, cmd); - break; - - case CMD_DVC_CLOSE_CHANNEL: - drdynvc_process_close_channel_response(s, cmd); - break; - - case CMD_DVC_DATA_FIRST: - drdynvc_process_data_first(s, cmd); - break; - - case CMD_DVC_DATA: - drdynvc_process_data(s, cmd); - break; - - default: - LOG(0, ("drdynvc_data_in: got unknown command 0x%x", cmd)); - break; - } - - return 0; -} - -/* - * insert a byte, short or 32bit value into specified stream - * - * @param s stream used for insertion - * @param val value to insert - * - * @return 0 for byte insertions - * @return 1 for short insertion - * @return 2 for uint32_t insertions - ******************************************************************************/ -static int -drdynvc_insert_uint_124(struct stream *s, uint32_t val) -{ - int ret_val; - - if (val <= 0xff) - { - out_uint8(s, val); - ret_val = 0; - } - else if (val <= 0xffff) - { - out_uint16_le(s, val); - ret_val = 1; - } - else - { - out_uint32_le(s, val); - ret_val = 2; - } - - return ret_val; -} - -/* - * extract channel id from stream - * - * @param s stream containing channel id - * @param cmd first byte in stream - * @param chan_id return channel id here - ******************************************************************************/ -static int -drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p) -{ - int cbChId; - int chan_id; - - cbChId = cmd & 0x03; - - if (cbChId == 0) - { - in_uint8(s, chan_id); - } - else if (cbChId == 1) - { - in_uint16_le(s, chan_id); - } - else - { - in_uint32_le(s, chan_id); - } - - *chan_id_p = chan_id; - - return 0; -} diff --git a/sesman/chansrv/drdynvc.h b/sesman/chansrv/drdynvc.h deleted file mode 100644 index cd6a5fca..00000000 --- a/sesman/chansrv/drdynvc.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * xrdp: A Remote Desktop Protocol server. - * - * Copyright (C) Laxmikant Rashinkar 2012 LK.Rashinkar@gmail.com - * - * 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. - */ - -#ifndef _DRDYNVC_H_ -#define _DRDYNVC_H_ - -#include -#include -#include -#include - -#include "arch.h" -#include "chansrv.h" -#include "xcommon.h" -#include "log.h" -#include "os_calls.h" -#include "trans.h" - -/* move this to tsmf.c */ -#define TSMF_CHAN_ID 0x1000 - -/* get number of bytes in stream before s->p */ -#define stream_length_before_p(s) (int) ((s)->p - (s)->data) - -/* get number of bytes in stream after s->p */ -#define stream_length_after_p(s) (int) ((s)->end - (s)->p) - -#define rewind_stream(s) do \ -{ \ - (s)->p = (s)->data; \ - (s)->end = (s)->data; \ -} while (0) - -/* max number of bytes we can send in one pkt */ -#define MAX_PDU_SIZE 1600 - -/* commands used to manage dynamic virtual channels */ -#define CMD_DVC_OPEN_CHANNEL 0x10 -#define CMD_DVC_DATA_FIRST 0x20 -#define CMD_DVC_DATA 0x30 -#define CMD_DVC_CLOSE_CHANNEL 0x40 -#define CMD_DVC_CAPABILITY 0x50 - -int drdynvc_init(void); -int drdynvc_send_open_channel_request(int chan_pri, unsigned int chan_id, - char *chan_name); -int drdynvc_send_close_channel_request(unsigned int chan_id); -int drdynvc_write_data(uint32_t chan_id, char *data, int data_size); -int drdynvc_data_in(struct stream* s, int chan_id, int chan_flags, - int length, int total_length); - -#endif diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index cc9f2ceb..452acc12 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -38,6 +38,12 @@ #if defined(XRDP_FDK_AAC) #include static HANDLE_AACENCODER g_fdk_aac_encoder = 0; + +#define AACENCODER_LIB_VER_GTEQ(vl0, vl1, vl2) \ + (defined(AACENCODER_LIB_VL0) && \ + ((AACENCODER_LIB_VL0 > vl0) || \ + (AACENCODER_LIB_VL0 == vl0 && AACENCODER_LIB_VL1 >= vl1) || \ + (AACENCODER_LIB_VL0 == vl0 && AACENCODER_LIB_VL1 == vl1 && AACENCODER_LIB_VL2 > vl2))) #endif #if defined(XRDP_OPUS) @@ -598,7 +604,12 @@ sound_wave_compress_fdk_aac(char *data, int data_bytes, int *format_index) LOG(0, (" inBufFillLevel %d", info.inBufFillLevel)); LOG(0, (" inputChannels %d", info.inputChannels)); LOG(0, (" frameLength %d", info.frameLength)); +#if AACENCODER_LIB_VER_GTEQ(4, 0, 0) + LOG(0, (" nDelay %d", info.nDelay)); + LOG(0, (" nDelayCore %d", info.nDelayCore)); +#else LOG(0, (" encoderDelay %d", info.encoderDelay)); +#endif LOG(0, (" confBuf")); LOG(0, (" confSize %d", info.confSize)); } diff --git a/sesman/sesman.ini.in b/sesman/sesman.ini.in index 68ef7795..9af7a100 100644 --- a/sesman/sesman.ini.in +++ b/sesman/sesman.ini.in @@ -44,6 +44,12 @@ KillDisconnected=false ; min 60 seconds DisconnectedTimeLimit=0 +;; IdleTimeLimit (specify in second) - wait before disconnect idle sessions +; Type: integer +; Default: 0 +; Set to 0 to disable idle disconnection. +IdleTimeLimit=0 + ;; Policy - session allocation policy ; Type: enum [ "Default" | "UBD" | "UBI" | "UBC" | "UBDI" | "UBDC" ] ; Default: Xrdp: and Xvnc: @@ -84,13 +90,6 @@ param=tcp param=-logfile param=.xorgxrdp.%s.log -[X11rdp] -param=X11rdp -param=-bs -param=-nolisten -param=tcp -param=-uds - [Xvnc] param=Xvnc param=-bs diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 65e5c4f6..5ed46a3a 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -138,6 +138,8 @@ int callback(intptr_t id, int msg, intptr_t param1, intptr_t param2, intptr_t param3, intptr_t param4); int +xrdp_wm_drdynvc_up(intptr_t id); +int xrdp_wm_delete_all_children(struct xrdp_wm* self); int xrdp_wm_show_log(struct xrdp_wm *self); @@ -367,6 +369,8 @@ xrdp_bitmap_compress(char* in_data, int width, int height, int e); /* xrdp_mm.c */ +int +xrdp_mm_drdynvc_up(struct xrdp_mm* self); struct xrdp_mm* xrdp_mm_create(struct xrdp_wm* owner); void diff --git a/xrdp/xrdp.ini.in b/xrdp/xrdp.ini.in index c73e271c..bba2624e 100644 --- a/xrdp/xrdp.ini.in +++ b/xrdp/xrdp.ini.in @@ -162,16 +162,6 @@ ip=127.0.0.1 port=-1 code=20 -[X11rdp] -name=X11rdp -lib=libxup.@lib_extension@ -username=ask -password=ask -ip=127.0.0.1 -port=-1 -xserverbpp=24 -code=10 - [Xvnc] name=Xvnc lib=libvnc.@lib_extension@ @@ -182,15 +172,6 @@ port=-1 #xserverbpp=24 #delay_ms=2000 -[console] -name=console -lib=libvnc.@lib_extension@ -ip=127.0.0.1 -port=5900 -username=na -password=ask -#delay_ms=2000 - [vnc-any] name=vnc-any lib=libvnc.@lib_extension@ @@ -203,15 +184,6 @@ password=ask #pamsessionmng=127.0.0.1 #delay_ms=2000 -[sesman-any] -name=sesman-any -lib=libvnc.@lib_extension@ -ip=ask -port=-1 -username=ask -password=ask -#delay_ms=2000 - [neutrinordp-any] name=neutrinordp-any lib=libxrdpneutrinordp.@lib_extension@ diff --git a/xrdp/xrdp_keyboard.ini b/xrdp/xrdp_keyboard.ini index dcc57b7a..df267991 100644 --- a/xrdp/xrdp_keyboard.ini +++ b/xrdp/xrdp_keyboard.ini @@ -74,8 +74,9 @@ rdp_layout_br=0x00000416 rdp_layout_ru=0x00000419 rdp_layout_se=0x0000041D rdp_layout_ch=0x00000807 -rdp_layout_ch_fr=0x0000100c +rdp_layout_ch_fr=0x0000100C rdp_layout_gb=0x00000809 +rdp_layout_latam=0x0000080A rdp_layout_be=0x00000813 rdp_layout_pt=0x00000816 @@ -97,6 +98,7 @@ rdp_layout_se=se rdp_layout_ch=ch rdp_layout_ch_fr=ch(fr) rdp_layout_gb=gb +rdp_layout_latam=latam rdp_layout_be=be rdp_layout_pt=pt @@ -132,5 +134,6 @@ rdp_layout_se=se rdp_layout_ch=ch rdp_layout_ch_fr=ch(fr) rdp_layout_gb=gb +rdp_layout_latam=latam rdp_layout_be=be rdp_layout_pt=pt diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 4c716d46..7d204b5b 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -679,71 +679,28 @@ xrdp_mm_trans_send_channel_setup(struct xrdp_mm *self, struct trans *trans) return trans_force_write(trans); } -/*****************************************************************************/ -/* returns error */ -static int -xrdp_mm_trans_send_channel_data_response(struct xrdp_mm *self, - struct trans *trans) -{ - struct stream *s; - - s = trans_get_out_s(trans, 8192); - - if (s == 0) - { - return 1; - } - - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 7); /* msg id */ - out_uint32_le(s, 8); /* size */ - s_mark_end(s); - return trans_force_write(trans); -} - -/*****************************************************************************/ -/* returns error - init is done, sent channel setup */ -static int -xrdp_mm_trans_process_init_response(struct xrdp_mm *self, struct trans *trans) -{ - return xrdp_mm_trans_send_channel_setup(self, trans); -} - /*****************************************************************************/ /* returns error data coming in from the channel handler, send it to the client */ static int -xrdp_mm_trans_process_channel_data(struct xrdp_mm *self, struct trans *trans) +xrdp_mm_trans_process_channel_data(struct xrdp_mm *self, struct stream *s) { - struct stream *s; int size; int total_size; int chan_id; int chan_flags; int rv; - s = trans_get_in_s(trans); - - if (s == 0) - { - return 1; - } - in_uint16_le(s, chan_id); in_uint16_le(s, chan_flags); in_uint16_le(s, size); in_uint32_le(s, total_size); - rv = xrdp_mm_trans_send_channel_data_response(self, trans); + rv = 0; if (rv == 0) { - if (is_channel_allowed(self->wm, chan_id)) - { - rv = libxrdp_send_to_channel(self->wm->session, chan_id, s->p, size, total_size, - chan_flags); - } + rv = libxrdp_send_to_channel(self->wm->session, chan_id, s->p, size, total_size, + chan_flags); } return rv; @@ -970,12 +927,11 @@ xrdp_mm_process_rail_update_window_text(struct xrdp_mm* self, struct stream* s) { int size; int flags; - int rv = 0; + int rv; int window_id; struct rail_window_state_order rwso; g_writeln("xrdp_mm_process_rail_update_window_text:"); - in_uint32_le(s, window_id); in_uint32_le(s, flags); g_writeln(" update window title info: 0x%8.8x", window_id); @@ -1006,17 +962,12 @@ xrdp_mm_process_rail_update_window_text(struct xrdp_mm* self, struct stream* s) /* returns error process alternate secondary drawing orders for rail channel */ static int -xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct trans* trans) +xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct stream *s) { - struct stream* s; int order_type; - int rv = 0; + int rv; - s = trans_get_in_s(trans); - if (s == 0) - { - return 1; - } + rv = 0; in_uint32_le(s, order_type); switch(order_type) @@ -1040,6 +991,302 @@ xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct trans* trans) return rv; } +/******************************************************************************/ +int +xrdp_mm_drdynvc_up(struct xrdp_mm* self) +{ + LLOGLN(0, ("xrdp_mm_drdynvc_up:")); + return 0; +} + +/*****************************************************************************/ +/* open response from client going to channel server */ +static int +xrdp_mm_drdynvc_open_response(intptr_t id, int chan_id, int creation_status) +{ + struct trans *trans; + struct stream *s; + struct xrdp_wm* wm; + struct xrdp_process *pro; + int chansrv_chan_id; + + LLOGLN(10, ("xrdp_mm_drdynvc_open_response: chan_id %d creation_status %d", + chan_id, creation_status)); + pro = (struct xrdp_process *) id; + wm = pro->wm; + trans = wm->mm->chan_trans; + s = trans_get_out_s(trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 24); /* size */ + out_uint32_le(s, 13); /* msg id */ + out_uint32_le(s, 16); /* size */ + chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; + out_uint32_le(s, chansrv_chan_id); + out_uint32_le(s, creation_status); /* status */ + s_mark_end(s); + return trans_write_copy(trans); +} + +/*****************************************************************************/ +/* close response from client going to channel server */ +static int +xrdp_mm_drdynvc_close_response(intptr_t id, int chan_id) +{ + struct trans *trans; + struct stream *s; + struct xrdp_wm* wm; + struct xrdp_process *pro; + int chansrv_chan_id; + + pro = (struct xrdp_process *) id; + wm = pro->wm; + trans = wm->mm->chan_trans; + s = trans_get_out_s(trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 20); /* size */ + out_uint32_le(s, 15); /* msg id */ + out_uint32_le(s, 12); /* size */ + chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; + out_uint32_le(s, chansrv_chan_id); + s_mark_end(s); + return trans_write_copy(trans); +} + +/*****************************************************************************/ +/* part data from client going to channel server */ +static int +xrdp_mm_drdynvc_data_first(intptr_t id, int chan_id, char *data, + int bytes, int total_bytes) +{ + struct trans *trans; + struct stream *s; + struct xrdp_wm* wm; + struct xrdp_process *pro; + int chansrv_chan_id; + + pro = (struct xrdp_process *) id; + wm = pro->wm; + trans = wm->mm->chan_trans; + s = trans_get_out_s(trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8 + 4 + 4 + 4 + bytes); + out_uint32_le(s, 17); /* msg id */ + out_uint32_le(s, 8 + 4 + 4 + 4 + bytes); + chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; + out_uint32_le(s, chansrv_chan_id); + out_uint32_le(s, bytes); + out_uint32_le(s, total_bytes); + out_uint8a(s, data, bytes); + s_mark_end(s); + return trans_write_copy(trans); +} + +/*****************************************************************************/ +/* data from client going to channel server */ +static int +xrdp_mm_drdynvc_data(intptr_t id, int chan_id, char *data, int bytes) +{ + struct trans *trans; + struct stream *s; + struct xrdp_wm* wm; + struct xrdp_process *pro; + int chansrv_chan_id; + + pro = (struct xrdp_process *) id; + wm = pro->wm; + trans = wm->mm->chan_trans; + s = trans_get_out_s(trans, 8192); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8 + 4 + 4 + bytes); + out_uint32_le(s, 19); /* msg id */ + out_uint32_le(s, 8 + 4 + 4 + bytes); + chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; + out_uint32_le(s, chansrv_chan_id); + out_uint32_le(s, bytes); + out_uint8a(s, data, bytes); + s_mark_end(s); + return trans_write_copy(trans); +} + +/*****************************************************************************/ +/* open message from channel server going to client */ +static int +xrdp_mm_trans_process_drdynvc_channel_open(struct xrdp_mm* self, + struct stream *s) +{ + int name_bytes; + int flags; + int error; + int chan_id; + int chansrv_chan_id; + char *name; + struct xrdp_drdynvc_procs procs; + + if (!s_check_rem(s, 2)) + { + return 1; + } + in_uint32_le(s, name_bytes); + if ((name_bytes < 1) || (name_bytes > 1024)) + { + return 1; + } + name = g_new(char, name_bytes + 1); + if (name == NULL) + { + return 1; + } + if (!s_check_rem(s, name_bytes)) + { + g_free(name); + return 1; + } + in_uint8a(s, name, name_bytes); + name[name_bytes] = 0; + if (!s_check_rem(s, 8)) + { + g_free(name); + return 1; + } + in_uint32_le(s, flags); + in_uint32_le(s, chansrv_chan_id); + if (flags == 0) + { + /* open static channel, not supported */ + g_free(name); + return 1; + } + else + { + /* dynamic channel */ + g_memset(&procs, 0, sizeof(procs)); + procs.open_response = xrdp_mm_drdynvc_open_response; + procs.close_response = xrdp_mm_drdynvc_close_response; + procs.data_first = xrdp_mm_drdynvc_data_first; + procs.data = xrdp_mm_drdynvc_data; + chan_id = 0; + error = libxrdp_drdynvc_open(self->wm->session, name, flags, &procs, + &chan_id); + if (error != 0) + { + g_free(name); + return 1; + } + self->xr2cr_cid_map[chan_id] = chansrv_chan_id; + self->cs2xr_cid_map[chansrv_chan_id] = chan_id; + } + g_free(name); + return 0; +} + +/*****************************************************************************/ +/* close message from channel server going to client */ +static int +xrdp_mm_trans_process_drdynvc_channel_close(struct xrdp_mm* self, + struct stream *s) +{ + int chansrv_chan_id; + int chan_id; + int error; + + if (!s_check_rem(s, 4)) + { + return 1; + } + in_uint32_le(s, chansrv_chan_id); + chan_id = self->cs2xr_cid_map[chansrv_chan_id]; + /* close dynamic channel */ + error = libxrdp_drdynvc_close(self->wm->session, chan_id); + if (error != 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +/* data from channel server going to client */ +static int +xrdp_mm_trans_process_drdynvc_data_first(struct xrdp_mm* self, + struct stream *s) +{ + int chansrv_chan_id; + int chan_id; + int error; + int data_bytes; + int total_bytes; + char *data; + + if (!s_check_rem(s, 12)) + { + return 1; + } + in_uint32_le(s, chansrv_chan_id); + in_uint32_le(s, data_bytes); + in_uint32_le(s, total_bytes); + if ((!s_check_rem(s, data_bytes))) + { + return 1; + } + in_uint8p(s, data, data_bytes); + chan_id = self->cs2xr_cid_map[chansrv_chan_id]; + error = libxrdp_drdynvc_data_first(self->wm->session, chan_id, data, + data_bytes, total_bytes); + if (error != 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +/* data from channel server going to client */ +static int +xrdp_mm_trans_process_drdynvc_data(struct xrdp_mm* self, + struct stream *s) +{ + int chansrv_chan_id; + int chan_id; + int error; + int data_bytes; + char *data; + + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint32_le(s, chansrv_chan_id); + in_uint32_le(s, data_bytes); + if ((!s_check_rem(s, data_bytes))) + { + return 1; + } + in_uint8p(s, data, data_bytes); + chan_id = self->cs2xr_cid_map[chansrv_chan_id]; + error = libxrdp_drdynvc_data(self->wm->session, chan_id, data, data_bytes); + if (error != 0) + { + return 1; + } + return 0; +} + /*****************************************************************************/ /* returns error process a message for the channel handler */ @@ -1051,6 +1298,7 @@ xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans, int id; int size; char *next_msg; + char *s_end; rv = 0; @@ -1059,31 +1307,47 @@ xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans, next_msg = s->p; in_uint32_le(s, id); in_uint32_le(s, size); + if (size < 8) + { + return 1; + } + if (!s_check_rem(s, size - 8)) + { + return 1; + } next_msg += size; - + s_end = s->end; + s->end = next_msg; + LLOGLN(10, ("xrdp_mm_chan_process_msg: got msg id %d", id)); switch (id) { - case 2: /* channel init response */ - rv = xrdp_mm_trans_process_init_response(self, trans); - break; - case 4: /* channel setup response */ - break; - case 6: /* channel data response */ - break; case 8: /* channel data */ - rv = xrdp_mm_trans_process_channel_data(self, trans); + rv = xrdp_mm_trans_process_channel_data(self, s); break; case 10: /* rail alternate secondary drawing orders */ - rv = xrdp_mm_process_rail_drawing_orders(self, trans); + rv = xrdp_mm_process_rail_drawing_orders(self, s); + break; + case 12: + rv = xrdp_mm_trans_process_drdynvc_channel_open(self, s); + break; + case 14: + rv = xrdp_mm_trans_process_drdynvc_channel_close(self, s); + break; + case 16: + rv = xrdp_mm_trans_process_drdynvc_data_first(self, s); + break; + case 18: + rv = xrdp_mm_trans_process_drdynvc_data(self, s); break; default: log_message(LOG_LEVEL_ERROR,"xrdp_mm_chan_process_msg: unknown id %d", id); break; } - + s->end = s_end; if (rv != 0) { - break; + LLOGLN(0, ("xrdp_mm_chan_process_msg: error rv %d id %d", rv, id)); + rv = 0; } s->p = next_msg; @@ -1116,40 +1380,28 @@ xrdp_mm_chan_data_in(struct trans *trans) return 1; } - in_uint8s(s, 4); /* id */ - in_uint32_le(s, size); - error = trans_force_read(trans, size - 8); - - if (error == 0) + if (trans->extra_flags == 0) { - /* here, the entire message block is read in, process it */ - error = xrdp_mm_chan_process_msg(self, trans, s); + in_uint8s(s, 4); /* id */ + in_uint32_le(s, size); + LLOGLN(10, ("xrdp_mm_chan_data_in: got header, size %d", size)); + if (size > 8) + { + self->chan_trans->header_size = size; + trans->extra_flags = 1; + return 0; + } } - + /* here, the entire message block is read in, process it */ + error = xrdp_mm_chan_process_msg(self, trans, s); + self->chan_trans->header_size = 8; + trans->extra_flags = 0; + init_stream(s, 0); + LLOGLN(10, ("xrdp_mm_chan_data_in: got whole message, reset for " + "next header")); return error; } -/*****************************************************************************/ -static int -xrdp_mm_chan_send_init(struct xrdp_mm *self) -{ - struct stream *s; - - s = trans_get_out_s(self->chan_trans, 8192); - - if (s == 0) - { - return 1; - } - - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 1); /* msg id */ - out_uint32_le(s, 8); /* size */ - s_mark_end(s); - return trans_force_write(self->chan_trans); -} - /*****************************************************************************/ /* connect to chansrv */ static int @@ -1177,6 +1429,8 @@ xrdp_mm_connect_chansrv(struct xrdp_mm *self, const char *ip, const char *port) self->chan_trans->trans_data_in = xrdp_mm_chan_data_in; self->chan_trans->header_size = 8; self->chan_trans->callback_data = self; + self->chan_trans->no_stream_init_on_data_in = 1; + self->chan_trans->extra_flags = 0; /* try to connect up to 4 times */ for (index = 0; index < 4; index++) @@ -1200,10 +1454,10 @@ xrdp_mm_connect_chansrv(struct xrdp_mm *self, const char *ip, const char *port) if (self->chan_trans_up) { - if (xrdp_mm_chan_send_init(self) != 0) + if (xrdp_mm_trans_send_channel_setup(self, self->chan_trans) != 0) { log_message(LOG_LEVEL_ERROR,"xrdp_mm_connect_chansrv: error in " - "xrdp_mm_chan_send_init"); + "xrdp_mm_trans_send_channel_setup"); } else { @@ -1227,6 +1481,47 @@ static void cleanup_sesman_connection(struct xrdp_mm *self) } } +/*****************************************************************************/ +/* does the section in xrdp.ini has any channel.*=true | false */ +static int +xrdp_mm_update_allowed_channels(struct xrdp_mm *self) +{ + int index; + int count; + int chan_id; + int disabled; + const char *name; + const char *value; + const char *chan_name; + struct xrdp_session *session; + + session = self->wm->session; + count = self->login_names->count; + for (index = 0; index < count; index++) + { + name = (const char *) list_get_item(self->login_names, index); + if (g_strncasecmp(name, "channel.", 8) == 0) + { + value = (const char *) list_get_item(self->login_values, index); + chan_name = name + 8; + chan_id = libxrdp_get_channel_id(session, chan_name); + disabled = !g_text2bool(value); + libxrdp_disable_channel(session, chan_id, disabled); + if (disabled) + { + g_writeln("xrdp_mm_update_allowed_channels: channel %s " + "channel id %d is disabled", chan_name, chan_id); + } + else + { + g_writeln("xrdp_mm_update_allowed_channels: channel %s " + "channel id %d is allowed", chan_name, chan_id); + } + } + } + return 0; +} + /*****************************************************************************/ static int xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s) @@ -1271,7 +1566,7 @@ xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s) { g_snprintf(port, 255, "%d", 7200 + display); } - + xrdp_mm_update_allowed_channels(self); xrdp_mm_connect_chansrv(self, ip, port); } } @@ -2068,7 +2363,8 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self, if ((self->chan_trans != 0) && self->chan_trans_up) { - trans_get_wait_objs(self->chan_trans, read_objs, rcount); + trans_get_wait_objs_rw(self->chan_trans, read_objs, rcount, + write_objs, wcount, timeout); } if (self->mod != 0) @@ -2975,220 +3271,6 @@ server_reset(struct xrdp_mod *mod, int width, int height, int bpp) return 0; } -/* read the channel section of the ini file into lists - * return 1 on success 0 on failure */ -int read_allowed_channel_names(struct list *names, struct list *values) -{ - int fd; - int ret = 0; - char cfg_file[256]; - - g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); - fd = g_file_open(cfg_file); - - if (fd != -1) - { - names->auto_free = 1; - values->auto_free = 1; - - /* all values in this section can be valid channel names */ - if (file_read_section(fd, "channels", names, values) == 0) - { - ret = 1; - } - else - { - log_message(LOG_LEVEL_ERROR,"Failure reading channel section of configuration"); - } - - g_file_close(fd); - } - return ret; -} - -/* internal function return -1 if name is not in list - * otherwise return the index 0->count-1*/ -int -find_name_in_lists(char *inName, struct list *names) -{ - int reply = -1; /*means not in the list*/ - int index; - char *name; - - for (index = 0; index < names->count; index++) - { - name = (char *)list_get_item(names, index); - if ( (name != 0) && (g_strncasecmp(name, inName, MAX_CHANNEL_NAME) == 0) ) - { - reply = index; - break; /* stop loop - item found*/ - } - } - - return reply; -} - -#define CHANNEL_NAME_PREFIX "channel." -/* update the channel lists from connection specific overrides - * return 1 on success 0 on failure */ -int update_allowed_channel_names(struct xrdp_wm *wm, struct list *names, struct list *values) -{ - int ret = 1; - int index; - int oldindex; - char *val; - char *name; - //wm->mm->login_names,wm->mm->login_values - for (index = 0; index < wm->mm->login_names->count; index++) - { - name = (char *)list_get_item(wm->mm->login_names, index); - if ( (name != 0) && (g_strncmp( name, CHANNEL_NAME_PREFIX, g_strlen(CHANNEL_NAME_PREFIX)) == 0 ) ) - { - name += g_strlen(CHANNEL_NAME_PREFIX); - // locate and remove from list - oldindex = find_name_in_lists(name, names); - if (oldindex >= 0) - { - list_remove_item(names, oldindex); - list_remove_item(values, oldindex); - } - val = (char *)list_get_item(wm->mm->login_values, index); - // (re)add to lists - list_add_item(names, (tbus)g_strdup(name)); - list_add_item(values, (tbus)g_strdup(val)); - } - } - return ret; -} - -/* internal function return 1 if name is in list of channels - * and if the value is allowed */ -int -is_channel_enabled(char *inName, struct list *names, struct list *values) -{ - int reply = 0; /*means not in the list*/ - int index; - char *val; - - index = find_name_in_lists(inName, names); - if ( index >= 0 ) - { - val = (char *)list_get_item(values, index); - reply = g_text2bool(val); - if (reply == 0) - { - log_message(LOG_LEVEL_INFO,"This channel is disabled: %s", inName); - } - } - else - { - log_message(LOG_LEVEL_INFO,"This channel is disabled (not in List): %s", inName); - } - - return reply; -} -/* internal function only used once per session - * creates the list of allowed channels and store the information - * in wm struct */ -void init_channel_allowed(struct xrdp_wm *wm) -{ - int error; - int i; - char channelname[MAX_CHANNEL_NAME]; - int index = 0; - int allowindex = 0; - struct list *names; - struct list *values; - - /* first reset allowedchannels */ - for (i = 0; i < MAX_NR_CHANNELS; i++) - { - /* 0 is a valid channel so we use -1 to mark the index as unused */ - wm->allowedchannels[i] = -1; - } - - names = list_create(); - values = list_create(); - /* You can override the list of allowed channels individually for each - * session type. */ - if ( read_allowed_channel_names(names, values) - && update_allowed_channel_names(wm, names, values) ) - { - do - { - /* libxrdp_query_channel return 1 on error*/ - error = libxrdp_query_channel(wm->session, index, channelname, NULL); - - if (error == 0) - { - /* examples of channel names: rdpdr ; rdpsnd ; drdynvc ; cliprdr */ - if (is_channel_enabled(channelname, names, values)) - { - log_message(LOG_LEVEL_INFO,"The following channel is allowed: %s (%d)", channelname, index); - wm->allowedchannels[allowindex] = index; - allowindex++; - - if (allowindex >= MAX_NR_CHANNELS) - { - log_message(LOG_LEVEL_ALWAYS,"Programming error in is_channel_allowed"); - error = 1; /* end loop */ - } - } - else - { - log_message(LOG_LEVEL_INFO,"The following channel is not allowed: %s (%d)", channelname, index); - } - - index++; - } - } - while ((error == 0) && (index < MAX_NR_CHANNELS)); - } - else - { - log_message(LOG_LEVEL_ERROR,"Error reading channel section in inifile"); - } - - list_delete(names); - list_delete(values); -} - -/*****************************************************************************/ -/* This function returns 1 if the channelID is allowed by rule set - * returns 0 if not allowed */ -int is_channel_allowed(struct xrdp_wm *wm, int channel_id) -{ - int i; - int reply = 0; /* not allowed */ - - /* The first time each client is using this function we have to - * define the list of allowed channels */ - if (wm->allowedinitialized == 0) - { - init_channel_allowed(wm); - log_message(LOG_LEVEL_DEBUG,"The allow channel list now initialized for this session"); - wm->allowedinitialized = 1; - } - - for (i = 0; i < MAX_NR_CHANNELS; i++) - { - if (channel_id == wm->allowedchannels[i]) - { - /*g_writeln("Channel allowed: %d",channel_id);*/ - reply = 1; /*channel allowed*/ - break; - } - else if (wm->allowedchannels[i] == -1) - { - /* We are in the unused space of the allowedchannels list - * We can end the loop */ - break; - } - } - - return reply; -} - /*****************************************************************************/ /*return 0 if the index is not found*/ int @@ -3235,25 +3317,18 @@ server_send_to_channel(struct xrdp_mod *mod, int channel_id, wm = (struct xrdp_wm *)(mod->wm); - if (is_channel_allowed(wm, channel_id)) + if (wm->mm->usechansrv) { - if (wm->mm->usechansrv) - { - /* - * Xvnc backend reaches here - * should not return 1 as this case is not an error - */ - return 0; - } + /* + * Xvnc backend reaches here + * should not return 1 as this case is not an error + */ + return 0; + } - /* vnc proxy mode reaches here */ - return libxrdp_send_to_channel(wm->session, channel_id, data, data_len, - total_data_len, flags); - } - else - { - return 1; - } + /* vnc proxy mode reaches here */ + return libxrdp_send_to_channel(wm->session, channel_id, data, data_len, + total_data_len, flags); } /*****************************************************************************/ diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index e317f584..7e416125 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -295,6 +295,8 @@ struct xrdp_mm int delete_chan_trans; /* boolean set when done with channel connection */ int usechansrv; /* true if chansrvport is set in xrdp.ini or using sesman */ struct xrdp_encoder *encoder; + int cs2xr_cid_map[256]; + int xr2cr_cid_map[256]; }; struct xrdp_key_info @@ -376,8 +378,6 @@ struct xrdp_wm struct xrdp_bitmap* target_surface; /* either screen or os surface */ int current_surface_index; int hints; - int allowedchannels[MAX_NR_CHANNELS]; - int allowedinitialized ; char pamerrortxt[256]; /* configuration derived from xrdp.ini */ diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 8b26718d..fd7b13b8 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -27,6 +27,18 @@ #include "xrdp.h" #include "log.h" +#define LLOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do \ + { \ + if (_level < LLOG_LEVEL) \ + { \ + g_write("xrdp:xrdp_wm [%10.10u]: ", g_time3()); \ + g_writeln _args ; \ + } \ + } \ + while (0) + /*****************************************************************************/ struct xrdp_wm * xrdp_wm_create(struct xrdp_process *owner, @@ -563,6 +575,69 @@ xrdp_wm_init(struct xrdp_wm *self) load_xrdp_config(self->xrdp_config, self->screen->bpp); + /* global channels allow */ + names = list_create(); + names->auto_free = 1; + values = list_create(); + values->auto_free = 1; + g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); + if (file_by_name_read_section(cfg_file, "Channels", names, values) == 0) + { + int error; + int ii; + int chan_id; + int chan_flags; + int disabled; + char chan_name[16]; + + ii = 0; + error = libxrdp_query_channel(self->session, ii, chan_name, + &chan_flags); + while (error == 0) + { + r = NULL; + for (index = 0; index < names->count; index++) + { + q = (char *) list_get_item(names, index); + if (g_strcasecmp(q, chan_name) == 0) + { + r = (char *) list_get_item(values, index); + break; + } + } + if (r == NULL) + { + /* not found, disable the channel */ + chan_id = libxrdp_get_channel_id(self->session, chan_name); + libxrdp_disable_channel(self->session, chan_id, 1); + g_writeln("xrdp_wm_init: channel %s channel id %d is " + "disabled", chan_name, chan_id); + } + else + { + /* found */ + chan_id = libxrdp_get_channel_id(self->session, q); + disabled = !g_text2bool(r); + libxrdp_disable_channel(self->session, chan_id, disabled); + if (disabled) + { + g_writeln("xrdp_wm_init: channel %s channel id %d is " + "disabled", chan_name, chan_id); + } + else + { + g_writeln("xrdp_wm_init: channel %s channel id %d is " + "allowed", chan_name, chan_id); + } + } + ii++; + error = libxrdp_query_channel(self->session, ii, chan_name, + &chan_flags); + } + } + list_delete(names); + list_delete(values); + xrdp_wm_load_static_colors_plus(self, autorun_name); xrdp_wm_load_static_pointers(self); self->screen->bg_color = self->xrdp_config->cfg_globals.ls_top_window_bg_color; @@ -1758,27 +1833,21 @@ xrdp_wm_process_channel_data(struct xrdp_wm *self, tbus param3, tbus param4) { int rv; - int chanid ; rv = 1; if (self->mm->mod != 0) { - chanid = LOWORD(param1); - - if (is_channel_allowed(self, chanid)) + if (self->mm->usechansrv) { - if (self->mm->usechansrv) + rv = xrdp_mm_process_channel_data(self->mm, param1, param2, + param3, param4); + } + else + { + if (self->mm->mod->mod_event != 0) { - rv = xrdp_mm_process_channel_data(self->mm, param1, param2, - param3, param4); - } - else - { - if (self->mm->mod->mod_event != 0) - { - rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2, - param3, param4); - } + rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2, + param3, param4); } } } @@ -1844,6 +1913,9 @@ callback(intptr_t id, int msg, intptr_t param1, intptr_t param2, //g_writeln("callback: frame ack %d", param1); xrdp_mm_frame_ack(wm->mm, param1); break; + case 0x5558: + xrdp_mm_drdynvc_up(wm->mm); + break; } return rv; } diff --git a/xrdpapi/xrdpapi.c b/xrdpapi/xrdpapi.c index 320052ab..a9017aff 100644 --- a/xrdpapi/xrdpapi.c +++ b/xrdpapi/xrdpapi.c @@ -44,24 +44,21 @@ struct wts_obj { - int fd; - int status; - char name[9]; - char dname[128]; - int display_num; - uint32_t flags; + int fd; + int display_num; }; /* helper functions used by WTSxxx API - do not invoke directly */ -static int get_display_num_from_display(char *display_text); -static int send_init(struct wts_obj *wts); -static int can_send(int sck, int millis); -static int can_recv(int sck, int millis); - -static const unsigned char g_xrdpapi_magic[12] = -{ - 0x78, 0x32, 0x10, 0x67, 0x00, 0x92, 0x30, 0x56, 0xff, 0xd8, 0xa9, 0x1f -}; +static int +get_display_num_from_display(char *display_text); +static int +can_send(int sck, int millis); +static int +can_recv(int sck, int millis); +static int +mysend(int sck, const void* adata, int bytes); +static int +myrecv(int sck, void* adata, int bytes); /* * Opens a handle to the server end of a specified virtual channel - this @@ -100,22 +97,27 @@ void * WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName, unsigned int flags) { - struct wts_obj *wts; - char *display_text; - int bytes; - unsigned long llong; - struct sockaddr_un s; + struct wts_obj *wts; + char *display_text; + int bytes; + unsigned long long1; + struct sockaddr_un s; + char *connect_data; + int chan_name_bytes; + int lerrno; if (SessionId != WTS_CURRENT_SESSION) { LLOGLN(0, ("WTSVirtualChannelOpenEx: bad SessionId")); return 0; } - wts = (struct wts_obj *) calloc(1, sizeof(struct wts_obj)); - + if (wts == NULL) + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: calloc failed")); + return 0; + } wts->fd = -1; - wts->flags = flags; display_text = getenv("DISPLAY"); if (display_text != 0) @@ -133,16 +135,17 @@ WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName, /* we use unix domain socket to communicate with chansrv */ if ((wts->fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + LLOGLN(0, ("WTSVirtualChannelOpenEx: socket failed")); free(wts); return NULL; } /* set non blocking */ - llong = fcntl(wts->fd, F_GETFL); - llong = llong | O_NONBLOCK; - if (fcntl(wts->fd, F_SETFL, llong) < 0) + long1 = fcntl(wts->fd, F_GETFL); + long1 = long1 | O_NONBLOCK; + if (fcntl(wts->fd, F_SETFL, long1) < 0) { - LLOGLN(10, ("WTSVirtualChannelOpenEx: set non-block mode failed")); + LLOGLN(0, ("WTSVirtualChannelOpenEx: set non-block mode failed")); } /* connect to chansrv session */ @@ -153,17 +156,93 @@ WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName, s.sun_path[bytes - 1] = 0; bytes = sizeof(struct sockaddr_un); - if (connect(wts->fd, (struct sockaddr *) &s, bytes) == 0) + if (connect(wts->fd, (struct sockaddr *) &s, bytes) < 0) { - LLOGLN(10, ("WTSVirtualChannelOpenEx: connected ok, name %s", pVirtualName)); - strncpy(wts->name, pVirtualName, 8); - - /* wait for connection to complete and send init */ - if (send_init(wts) == 0) + lerrno = errno; + if ((lerrno == EWOULDBLOCK) || (lerrno == EAGAIN) || + (lerrno == EINPROGRESS)) { - /* all ok */ - wts->status = 1; + /* ok */ } + else + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: connect failed")); + free(wts); + return NULL; + } + } + + /* wait for connection to complete */ + if (!can_send(wts->fd, 500)) + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: can_send failed")); + free(wts); + return NULL; + } + + chan_name_bytes = strlen(pVirtualName); + bytes = 4 + 4 + 4 + chan_name_bytes + 4; + + LLOGLN(10, ("WTSVirtualChannelOpenEx: chan_name_bytes %d bytes %d pVirtualName %s", chan_name_bytes, bytes, pVirtualName)); + + connect_data = (char *) calloc(bytes, 1); + if (connect_data == NULL) + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: calloc failed")); + free(wts); + return NULL; + } + + connect_data[0] = (bytes >> 0) & 0xFF; + connect_data[1] = (bytes >> 8) & 0xFF; + connect_data[2] = (bytes >> 16) & 0xFF; + connect_data[3] = (bytes >> 24) & 0xFF; + + /* version here(4-7), just leave 0 */ + + connect_data[8] = (chan_name_bytes >> 0) & 0xFF; + connect_data[9] = (chan_name_bytes >> 8) & 0xFF; + connect_data[10] = (chan_name_bytes >> 16) & 0xFF; + connect_data[11] = (chan_name_bytes >> 24) & 0xFF; + + memcpy(connect_data + 12, pVirtualName, chan_name_bytes); + + connect_data[4 + 4 + 4 + chan_name_bytes + 0] = (flags >> 0) & 0xFF; + connect_data[4 + 4 + 4 + chan_name_bytes + 1] = (flags >> 8) & 0xFF; + connect_data[4 + 4 + 4 + chan_name_bytes + 2] = (flags >> 16) & 0xFF; + connect_data[4 + 4 + 4 + chan_name_bytes + 3] = (flags >> 24) & 0xFF; + + LLOGLN(10, ("WTSVirtualChannelOpenEx: calling mysend with %d bytes", bytes)); + + if (mysend(wts->fd, connect_data, bytes) != bytes) + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: mysend failed")); + free(wts); + return NULL; + } + LLOGLN(10, ("WTSVirtualChannelOpenEx: sent ok")); + + if (!can_recv(wts->fd, 500)) + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: can_recv failed")); + free(wts); + return NULL; + } + + /* get response */ + if (myrecv(wts->fd, connect_data, 4) != 4) + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: myrecv failed")); + free(wts); + return NULL; + } + + if ((connect_data[0] != 0) || (connect_data[1] != 0) || + (connect_data[2] != 0) || (connect_data[3] != 0)) + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: connect_data not ok")); + free(wts); + return NULL; } return wts; @@ -179,18 +258,18 @@ WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName, /*****************************************************************************/ static int -mysend(int sck, const void* adata, int bytes) +mysend(int sck, const void *adata, int bytes) { int sent; int error; - const char* data; + const char *data; #if defined(SO_NOSIGPIPE) const int on = 1; setsockopt(sck, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); #endif - data = (const char*)adata; + data = (const char *) adata; sent = 0; while (sent < bytes) { @@ -207,6 +286,36 @@ mysend(int sck, const void* adata, int bytes) return sent; } +/*****************************************************************************/ +static int +myrecv(int sck, void *adata, int bytes) +{ + int recd; + int error; + char *data; + +#if defined(SO_NOSIGPIPE) + const int on = 1; + setsockopt(sck, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); +#endif + + data = (char *) adata; + recd = 0; + while (recd < bytes) + { + if (can_recv(sck, 100)) + { + error = recv(sck, data + recd, bytes - recd, MSG_NOSIGNAL); + if (error < 1) + { + return -1; + } + recd += error; + } + } + return recd; +} + /* * write data to client connection * @@ -217,8 +326,7 @@ WTSVirtualChannelWrite(void *hChannelHandle, const char *Buffer, unsigned int Length, unsigned int *pBytesWritten) { struct wts_obj *wts; - int rv; - int header[4]; + int rv; wts = (struct wts_obj *) hChannelHandle; @@ -230,29 +338,12 @@ WTSVirtualChannelWrite(void *hChannelHandle, const char *Buffer, return 0; } - if (wts->status != 1) - { - LLOGLN(10, ("WTSVirtualChannelWrite: wts->status != 1")); - return 0; - } - if (!can_send(wts->fd, 0)) { return 1; /* can't write now, ok to try again */ } - rv = 0; - memcpy(header, g_xrdpapi_magic, 12); - header[3] = Length; - if (mysend(wts->fd, header, 16) == 16) - { - rv = mysend(wts->fd, Buffer, Length); - } - else - { - LLOGLN(0, ("WTSVirtualChannelWrite: header write failed")); - return 0; - } + rv = mysend(wts->fd, Buffer, Length); LLOGLN(10, ("WTSVirtualChannelWrite: mysend() returned %d", rv)); @@ -263,14 +354,6 @@ WTSVirtualChannelWrite(void *hChannelHandle, const char *Buffer, return 1; } -#if 0 /* coverity: this is dead code */ - /* error, but is it ok to try again? */ - if ((rv == EWOULDBLOCK) || (rv == EAGAIN) || (rv == EINPROGRESS)) - { - return 0; /* failed to send, but should try again */ - } -#endif - /* fatal error */ return 0; } @@ -296,11 +379,6 @@ WTSVirtualChannelRead(void *hChannelHandle, unsigned int TimeOut, return 0; } - if (wts->status != 1) - { - return 0; - } - if (can_recv(wts->fd, TimeOut)) { rv = recv(wts->fd, Buffer, BufferSize, 0); @@ -341,7 +419,7 @@ WTSVirtualChannelClose(void *hChannelHandle) wts = (struct wts_obj *)hChannelHandle; - if (wts == 0) + if (wts == NULL) { return 0; } @@ -364,12 +442,7 @@ WTSVirtualChannelQuery(void *hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, wts = (struct wts_obj *)hChannelHandle; - if (wts == 0) - { - return 0; - } - - if (wts->status != 1) + if (wts == NULL) { return 0; } @@ -378,6 +451,10 @@ WTSVirtualChannelQuery(void *hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, { *pBytesReturned = 4; *ppBuffer = malloc(4); + if (*ppBuffer == NULL) + { + return 0; + } memcpy(*ppBuffer, &(wts->fd), 4); } @@ -388,7 +465,7 @@ WTSVirtualChannelQuery(void *hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, void WTSFreeMemory(void *pMemory) { - if (pMemory != 0) + if (pMemory != NULL) { free(pMemory); } @@ -452,39 +529,6 @@ can_recv(int sck, int millis) return 0; } -/*****************************************************************************/ -static int -send_init(struct wts_obj *wts) -{ - char initmsg[64]; - - memset(initmsg, 0, 64); - - /* insert channel name */ - strncpy(initmsg, wts->name, 8); - - /* insert open mode flags */ - initmsg[16] = (wts->flags >> 0) & 0xff; - initmsg[17] = (wts->flags >> 8) & 0xff; - initmsg[18] = (wts->flags >> 16) & 0xff; - initmsg[19] = (wts->flags >> 24) & 0xff; - - if (!can_send(wts->fd, 500)) - { - LLOGLN(10, ("send_init: send() will block!")); - return 1; - } - - if (send(wts->fd, initmsg, 64, 0) != 64) - { - LLOGLN(10, ("send_init: send() failed!")); - return 1; - } - - LLOGLN(10, ("send_init: sent ok!")); - return 0; -} - /*****************************************************************************/ static int get_display_num_from_display(char *display_text) @@ -513,7 +557,6 @@ get_display_num_from_display(char *display_text) disp[disp_index] = display_text[index]; disp_index++; } - index++; }