Merge branch 'devel' into v0.9

This commit is contained in:
Koichiro IWAO 2019-04-18 11:26:55 +09:00
commit 9e8fbf2d5a
No known key found for this signature in database
GPG Key ID: 9F72CDBC01BF10EB
24 changed files with 1820 additions and 535 deletions

42
NEWS.md
View File

@ -1,29 +1,59 @@
# Release notes for xrdp v0.9.9 (2018/12/25) # Release notes for xrdp v0.9.10 (2019/04/18)
# Release cycle ## Special thanks
Thank you for matt335672 contributing to lots of improvements in drive redirection!
## New features
* Restrict outbound (server->client) clipboard transfer, configured in `sesman.ini` #1298
## Bug fixes
* Fix the issue libscp v1 not setting width but height twice #1293
* Fix the issue reconnecting to session causes duplicate drive entries in fuse fs #1299
* Fix default_wm and reconnect_sh refer wrong path after sesman caught SIGUP #1315 #1331
* Shutdown xrdp more responsively #1325
* Improve remote file lookup in drive redirection #996 #1327
* Overwriting & appending to existing files is are now supported #1327
## Other changes
* Add Danish Keyboard #1290
* Put xrdp- prefix to some executables appear in man page #1313
* Replace some URLs from SF.net to xrdp.org #1313
## 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.9 (2018/12/25)
## Release cycle
From the next release, release cycle will be changed from quarterly to every From the next release, release cycle will be changed from quarterly to every
4 months. xrdp will be released in April, August, December. 4 months. xrdp will be released in April, August, December.
# New features ## New features
* Disconnection by idle timeout (requires xorgxrdp v0.2.9 or later) #1227 * 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 * Glyph cache v2 (fixes no font issue on iOS/macOS/Android client) #367 #1235
# Bug fixes ## Bug fixes
* Fix xrdp-chansrv crashes caused in drive redirection #1202 #1225 * Fix xrdp-chansrv crashes caused in drive redirection #1202 #1225
* Fix build with FDK AAC v2 #1257 * Fix build with FDK AAC v2 #1257
* Do not enable RemoteApp if the INFO_RAIL flag is not set (RDP-RDP proxy) #1253 * Do not enable RemoteApp if the INFO_RAIL flag is not set (RDP-RDP proxy) #1253
# Other changes ## Other changes
* Add Spanish Latin Amarican keyboard #1237 #1240 #1244 * Add Spanish Latin Amarican keyboard #1237 #1240 #1244
* Dynamic channel improvements #1222 #1224 * Dynamic channel improvements #1222 #1224
* Remove some deprecated sesman session types #1232 * Remove some deprecated sesman session types #1232
* Refactoring and cleanups * Refactoring and cleanups
# Known issues ## Known issues
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to * 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 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 * 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) # Release notes for xrdp v0.9.8 (2018/09/25)
## Deprecation notice ## Deprecation notice

View File

@ -2,7 +2,7 @@
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/neutrinolabs/xrdp) [![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) ![Apache-License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)
*Current Version:* 0.9.9 *Current Version:* 0.9.10
# xrdp - an open source RDP server # xrdp - an open source RDP server

View File

@ -712,13 +712,21 @@ trans_connect(struct trans *self, const char *server, const char *port,
now = g_time3(); now = g_time3();
if (now - start_time < timeout) if (now - start_time < timeout)
{ {
g_sleep(timeout / 5); g_sleep(100);
} }
else else
{ {
self->status = TRANS_STATUS_DOWN; self->status = TRANS_STATUS_DOWN;
return 1; return 1;
} }
if (self->is_term != NULL)
{
if (self->is_term())
{
self->status = TRANS_STATUS_DOWN;
return 1;
}
}
} }
} }
} }
@ -748,13 +756,21 @@ trans_connect(struct trans *self, const char *server, const char *port,
now = g_time3(); now = g_time3();
if (now - start_time < timeout) if (now - start_time < timeout)
{ {
g_sleep(timeout / 5); g_sleep(100);
} }
else else
{ {
self->status = TRANS_STATUS_DOWN; self->status = TRANS_STATUS_DOWN;
return 1; return 1;
} }
if (self->is_term != NULL)
{
if (self->is_term())
{
self->status = TRANS_STATUS_DOWN;
return 1;
}
}
} }
} }
} }

View File

@ -1,7 +1,7 @@
# Process this file with autoconf to produce a configure script # Process this file with autoconf to produce a configure script
AC_PREREQ(2.65) AC_PREREQ(2.65)
AC_INIT([xrdp], [0.9.9], [xrdp-devel@googlegroups.com]) AC_INIT([xrdp], [0.9.10], [xrdp-devel@googlegroups.com])
AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in) AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
AM_INIT_AUTOMAKE([1.7.2 foreign]) AM_INIT_AUTOMAKE([1.7.2 foreign])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])

View File

@ -196,6 +196,12 @@ login for all users is enabled.
\fIThis option is currently ignored!\fR Only members of this group can \fIThis option is currently ignored!\fR Only members of this group can
have session management rights. have session management rights.
.TP
\fBRestrictOutboundClipboard\fR=\fI[true|false]\fR
If set to \fB1\fR, \fBtrue\fR or \fByes\fR, will restrict the clipboard
outbound from the server, to prevent data copied inside the xrdp session
to be be pasted in the client host. Default value is \fBfalse\fR.
.TP .TP
\fBAlwaysGroupCheck\fR=\fI[true|false]\fR \fBAlwaysGroupCheck\fR=\fI[true|false]\fR
If set to \fB1\fR, \fBtrue\fR or \fByes\fR, require group membership even If set to \fB1\fR, \fBtrue\fR or \fByes\fR, require group membership even

View File

@ -23,15 +23,15 @@ Kills running \fBxrdp\-sesman\fR daemon.
Output help information and exit. Output help information and exit.
.SH "FILES" .SH "FILES"
@bindir@/sesman @bindir@/xrdp\-sesman
.br .br
@bindir@/sesrun @bindir@/xrdp\-sesrun
.br .br
@sysconfdir@/xrdp/sesman.ini @sysconfdir@/xrdp/sesman.ini
.br .br
@localstatedir@/log/sesman.log @localstatedir@/log/xrdp\-sesman.log
.br .br
@localstatedir@/run/sesman.pid @localstatedir@/run/xrdp\-sesman.pid
.SH "AUTHORS" .SH "AUTHORS"
Jay Sorg <jsorg71@users.sourceforge.net> Jay Sorg <jsorg71@users.sourceforge.net>

View File

@ -32,9 +32,9 @@ Screen height
Session color depth Session color depth
.SH "FILES" .SH "FILES"
@bindir@/sesman @bindir@/xrdp\-sesman
.br .br
@bindir@/sesrun @bindir@/xrdp\-sesrun
.SH "AUTHORS" .SH "AUTHORS"
Jay Sorg <jsorg71@users.sourceforge.net> Jay Sorg <jsorg71@users.sourceforge.net>

View File

@ -30,6 +30,7 @@ SUFFIXES = .in
startscriptdir=$(sysconfdir)/xrdp startscriptdir=$(sysconfdir)/xrdp
dist_startscript_DATA = \ dist_startscript_DATA = \
km-00000406.ini \
km-00000407.ini \ km-00000407.ini \
km-00000409.ini \ km-00000409.ini \
km-0000040a.ini \ km-0000040a.ini \

659
instfiles/km-00000406.ini Normal file
View File

@ -0,0 +1,659 @@
[noshift]
Key8=0: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=43:43
Key21=65105:180
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=229:229
Key35=168:168
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=230:230
Key48=248:248
Key49=189:189
Key50=65505:0
Key51=39:39
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=0:0
Key93=65406: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=0:0
Key115=65515:0
Key116=65516:0
Key117=65383:0
Key118=0:0
Key119=0:0
Key120=0:0
Key121=0:0
Key122=0: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=0:0
Key9=65307:27
Key10=33:33
Key11=34:34
Key12=35:35
Key13=164:164
Key14=37:37
Key15=38:38
Key16=47:47
Key17=40:40
Key18=41:41
Key19=61:61
Key20=63:63
Key21=65104:96
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=197:197
Key35=94:94
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=198:198
Key48=216:216
Key49=167:167
Key50=65505:0
Key51=42:42
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=65273: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=65452:44
Key92=0:0
Key93=65406: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=0:0
Key115=65515:0
Key116=65516:0
Key117=65383:0
Key118=0:0
Key119=0:0
Key120=0:0
Key121=0:0
Key122=0: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=0:0
Key9=65307:27
Key10=161:161
Key11=64:64
Key12=163:163
Key13=36:36
Key14=8364:8364
Key15=165:165
Key16=123:123
Key17=91:91
Key18=93:93
Key19=125:125
Key20=92:92
Key21=124:124
Key22=65288:8
Key23=65289:9
Key24=64:64
Key25=435:322
Key26=8364:8364
Key27=174:174
Key28=254:254
Key29=2299:8592
Key30=2302:8595
Key31=2301:8594
Key32=5053:339
Key33=254:254
Key34=65111:168
Key35=126:126
Key36=65293:13
Key37=65507:0
Key38=170:170
Key39=223:223
Key40=240:240
Key41=496:273
Key42=959:331
Key43=689:295
Key44=106:106
Key45=930:312
Key46=435:322
Key47=248:248
Key48=230:230
Key49=182:182
Key50=65505:0
Key51=180:180
Key52=171:171
Key53=187:187
Key54=169:169
Key55=2770:8220
Key56=2771:8221
Key57=110:110
Key58=181:181
Key59=65115:184
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=0:0
Key93=65406:0
Key94=92:92
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=0:0
Key112=65455:47
Key113=65027:0
Key114=0:0
Key115=65515:0
Key116=65516:0
Key117=65383:0
Key118=0:0
Key119=0:0
Key120=0:0
Key121=0:0
Key122=0: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
[capslock]
Key8=0: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=43:43
Key21=65105:180
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=197:197
Key35=65111:168
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=214:214
Key48=196:196
Key49=167:167
Key50=65505:0
Key51=39:39
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=0:0
Key93=65406: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=0:0
Key115=65515:0
Key116=65516:0
Key117=65383:0
Key118=0:0
Key119=0:0
Key120=0:0
Key121=0:0
Key122=0: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=0:0
Key9=65307:27
Key10=33:33
Key11=34:34
Key12=35:35
Key13=164:164
Key14=37:37
Key15=38:38
Key16=47:47
Key17=40:40
Key18=41:41
Key19=61:61
Key20=63:63
Key21=65104:96
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=229:229
Key35=65106:94
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=246:246
Key48=228:228
Key49=189:189
Key50=65505:0
Key51=42:42
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=65273: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=65452:44
Key92=0:0
Key93=65406: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=0:0
Key115=65515:0
Key116=65516:0
Key117=65383:0
Key118=0:0
Key119=0:0
Key120=0:0
Key121=0:0
Key122=0: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

View File

@ -59,6 +59,7 @@ int g_cliprdr_chan_id = -1; /* cliprdr */
int g_rdpsnd_chan_id = -1; /* rdpsnd */ int g_rdpsnd_chan_id = -1; /* rdpsnd */
int g_rdpdr_chan_id = -1; /* rdpdr */ int g_rdpdr_chan_id = -1; /* rdpdr */
int g_rail_chan_id = -1; /* rail */ int g_rail_chan_id = -1; /* rail */
int g_restrict_outbound_clipboard = 0;
char *g_exec_name; char *g_exec_name;
tbus g_exec_event; tbus g_exec_event;
@ -1780,7 +1781,7 @@ main(int argc, char **argv)
enum logReturns error; enum logReturns error;
struct log_config logconfig; struct log_config logconfig;
enum logLevels log_level; enum logLevels log_level;
char *restrict_outbound_clipboard_env;
g_init("xrdp-chansrv"); /* os_calls */ g_init("xrdp-chansrv"); /* os_calls */
log_path[255] = 0; log_path[255] = 0;
@ -1791,6 +1792,15 @@ main(int argc, char **argv)
return 1; return 1;
} }
restrict_outbound_clipboard_env = g_getenv("CHANSRV_RESTRICT_OUTBOUND_CLIPBOARD");
if (restrict_outbound_clipboard_env != 0)
{
if (g_strcmp(restrict_outbound_clipboard_env, "1") == 0)
{
g_restrict_outbound_clipboard = 1;
}
}
read_ini(); read_ini();
pid = g_getpid(); pid = g_getpid();
display_text = g_getenv("DISPLAY"); display_text = g_getenv("DISPLAY");

File diff suppressed because it is too large Load Diff

View File

@ -19,31 +19,27 @@
#ifndef _CHANSRV_FUSE_H #ifndef _CHANSRV_FUSE_H
#define _CHANSRV_FUSE_H #define _CHANSRV_FUSE_H
/* a file or dir entry in the xrdp file system */ #include "arch.h"
struct xrdp_inode
/*
* a file or dir entry in the xrdp file system (opaque type externally) */
struct xrdp_inode;
/* Used to pass file info in to xfuse_devredir_add_file_or_dir()
*
* The string storage the name field points to is only valid
* for the duration of the xfuse_devredir_add_file_or_dir()
* call
*/
struct file_attr
{ {
tui32 parent_inode; /* Parent serial number. */ const char *name; /* Name of file or directory */
tui32 inode; /* File serial number. */
tui32 mode; /* File mode. */ tui32 mode; /* File mode. */
tui32 nlink; /* symbolic link count. */
tui32 nentries; /* number of entries in a dir */
tui32 nopen; /* number of simultaneous opens */
tui32 uid; /* User ID of the file's owner. */
tui32 gid; /* Group ID of the file's group. */
size_t size; /* Size of file, in bytes. */ size_t size; /* Size of file, in bytes. */
time_t atime; /* Time of last access. */ time_t atime; /* Time of last access. */
time_t mtime; /* Time of last modification. */ time_t mtime; /* Time of last modification. */
time_t ctime; /* Time of last status change. */ time_t ctime; /* Time of last status change. */
char name[1024]; /* Dir or filename */
tui32 device_id; /* for file system redirection */
char is_synced; /* dir struct has been read from */
/* remote device, done just once */
int lindex; /* used in clipboard operations */
int is_loc_resource; /* this is not a redirected resource */
int close_in_progress; /* close cmd sent to client */
int stale; /* mark file as stale, ok to remove */
}; };
typedef struct xrdp_inode XRDP_INODE; // LK_TODO use this instead of using struct xrdp_inode
int xfuse_init(void); int xfuse_init(void);
int xfuse_deinit(void); int xfuse_deinit(void);
@ -57,9 +53,18 @@ int xfuse_file_contents_size(int stream_id, int file_size);
int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex); int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex);
/* functions that are invoked from devredir */ /* functions that are invoked from devredir */
int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode); struct xrdp_inode *xfuse_devredir_add_file_or_dir(
void *vp,
const struct file_attr *file_info);
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus); void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus);
void xfuse_devredir_cb_lookup_entry(void *vp, tui32 IoStatus,
struct xrdp_inode *xinode);
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId); void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId);
void xfuse_devredir_cb_write_file(
void *vp,
tui32 IoStatus,
const char *buf,
size_t length);
void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length); void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length);
void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus); void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus);
void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus); void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus);

View File

@ -185,38 +185,38 @@ x-special/gnome-copied-files
#define LOG_LEVEL LOG_ERROR #define LOG_LEVEL LOG_ERROR
#define log_error(_params...) \ #define log_error(_params...) \
{ \ { \
g_write("[%10.10u]: CLIPBOARD %s: %d : ERROR: ", \ g_write("[%10.10u]: CLIPBOARD %s: %d : ERROR: ", \
g_time3(), __func__, __LINE__); \ g_time3(), __func__, __LINE__); \
g_writeln (_params); \ g_writeln (_params); \
} }
#define log_always(_params...) \ #define log_always(_params...) \
{ \ { \
g_write("[%10.10u]: CLIPBOARD %s: %d : ALWAYS: ", \ g_write("[%10.10u]: CLIPBOARD %s: %d : ALWAYS: ", \
g_time3(), __func__, __LINE__); \ g_time3(), __func__, __LINE__); \
g_writeln (_params); \ g_writeln (_params); \
} }
#define log_info(_params...) \ #define log_info(_params...) \
{ \ { \
if (LOG_INFO <= LOG_LEVEL) \ if (LOG_INFO <= LOG_LEVEL) \
{ \ { \
g_write("[%10.10u]: CLIPBOARD %s: %d : ", \ g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
g_time3(), __func__, __LINE__); \ g_time3(), __func__, __LINE__); \
g_writeln (_params); \ g_writeln (_params); \
} \ } \
} }
#define log_debug(_params...) \ #define log_debug(_params...) \
{ \ { \
if (LOG_DEBUG <= LOG_LEVEL) \ if (LOG_DEBUG <= LOG_LEVEL) \
{ \ { \
g_write("[%10.10u]: CLIPBOARD %s: %d : ", \ g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
g_time3(), __func__, __LINE__); \ g_time3(), __func__, __LINE__); \
g_writeln (_params); \ g_writeln (_params); \
} \ } \
} }
static char g_bmp_image_header[] = static char g_bmp_image_header[] =
{ {
@ -235,6 +235,8 @@ extern tbus g_x_wait_obj; /* in xcommon.c */
extern Screen *g_screen; /* in xcommon.c */ extern Screen *g_screen; /* in xcommon.c */
extern int g_screen_num; /* in xcommon.c */ extern int g_screen_num; /* in xcommon.c */
extern int g_restrict_outbound_clipboard; /* in chansrv.c */
int g_clip_up = 0; int g_clip_up = 0;
static Atom g_clipboard_atom = 0; /* CLIPBOARD */ static Atom g_clipboard_atom = 0; /* CLIPBOARD */
@ -286,10 +288,10 @@ static int g_file_format_id = -1;
static char g_last_atom_name[256] = ""; static char g_last_atom_name[256] = "";
/*****************************************************************************/ /*****************************************************************************/
static char* static char *
get_atom_text(Atom atom) get_atom_text(Atom atom)
{ {
char* name; char *name;
int failed; int failed;
failed = 0; failed = 0;
@ -405,10 +407,10 @@ clipboard_init(void)
if (rv == 0) if (rv == 0)
{ {
log_debug("clipboard_init: g_xfixes_event_base %d", log_debug("clipboard_init: g_xfixes_event_base %d",
g_xfixes_event_base); g_xfixes_event_base);
st = XFixesQueryVersion(g_display, &ver_maj, &ver_min); st = XFixesQueryVersion(g_display, &ver_maj, &ver_min);
log_debug("clipboard_init st %d, maj %d min %d", st, log_debug("clipboard_init st %d, maj %d min %d", st,
ver_maj, ver_min); ver_maj, ver_min);
g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM", g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM",
False); False);
g_get_time_atom = XInternAtom(g_display, "XRDP_GET_TIME_ATOM", g_get_time_atom = XInternAtom(g_display, "XRDP_GET_TIME_ATOM",
@ -428,7 +430,7 @@ clipboard_init(void)
if (g_image_bmp_atom == None) if (g_image_bmp_atom == None)
{ {
log_error("clipboard_init: g_image_bmp_atom was " log_error("clipboard_init: g_image_bmp_atom was "
"not allocated"); "not allocated");
} }
g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen),
@ -463,12 +465,12 @@ clipboard_init(void)
s_mark_end(s); s_mark_end(s);
size = (int)(s->end - s->data); size = (int)(s->end - s->data);
log_debug("clipboard_init: data out, sending " log_debug("clipboard_init: data out, sending "
"CB_CLIP_CAPS (clip_msg_id = 1)"); "CB_CLIP_CAPS (clip_msg_id = 1)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size); rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
if (rv != 0) if (rv != 0)
{ {
log_error("clipboard_init: send_channel_data failed " log_error("clipboard_init: send_channel_data failed "
"rv = %d", rv); "rv = %d", rv);
rv = 4; rv = 4;
} }
} }
@ -484,12 +486,12 @@ clipboard_init(void)
s_mark_end(s); s_mark_end(s);
size = (int)(s->end - s->data); size = (int)(s->end - s->data);
log_debug("clipboard_init: data out, sending " log_debug("clipboard_init: data out, sending "
"CB_MONITOR_READY (clip_msg_id = 1)"); "CB_MONITOR_READY (clip_msg_id = 1)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size); rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
if (rv != 0) if (rv != 0)
{ {
log_error("clipboard_init: send_channel_data failed " log_error("clipboard_init: send_channel_data failed "
"rv = %d", rv); "rv = %d", rv);
rv = 4; rv = 4;
} }
} }
@ -554,7 +556,7 @@ clipboard_send_data_request(int format_id)
s_mark_end(s); s_mark_end(s);
size = (int)(s->end - s->data); size = (int)(s->end - s->data);
log_debug("clipboard_send_data_request: data out, sending " log_debug("clipboard_send_data_request: data out, sending "
"CLIPRDR_DATA_REQUEST (clip_msg_id = 4)"); "CLIPRDR_DATA_REQUEST (clip_msg_id = 4)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size); rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s); free_stream(s);
return rv; return rv;
@ -577,7 +579,7 @@ clipboard_send_format_ack(void)
s_mark_end(s); s_mark_end(s);
size = (int)(s->end - s->data); size = (int)(s->end - s->data);
log_debug("clipboard_send_format_ack: data out, sending " log_debug("clipboard_send_format_ack: data out, sending "
"CLIPRDR_FORMAT_ACK (clip_msg_id = 3)"); "CLIPRDR_FORMAT_ACK (clip_msg_id = 3)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size); rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s); free_stream(s);
return rv; return rv;
@ -715,7 +717,7 @@ clipboard_send_format_announce(int xrdp_clip_type)
break; break;
default: default:
log_debug("clipboard_send_format_announce: unknown " log_debug("clipboard_send_format_announce: unknown "
"xrdp_clip_type %d", xrdp_clip_type); "xrdp_clip_type %d", xrdp_clip_type);
break; break;
} }
} }
@ -759,7 +761,7 @@ clipboard_send_format_announce(int xrdp_clip_type)
break; break;
default: default:
log_debug("clipboard_send_format_announce: unknown " log_debug("clipboard_send_format_announce: unknown "
"xrdp_clip_type %d", xrdp_clip_type); "xrdp_clip_type %d", xrdp_clip_type);
break; break;
} }
} }
@ -774,7 +776,7 @@ clipboard_send_format_announce(int xrdp_clip_type)
size = (int)(s->end - s->data); size = (int)(s->end - s->data);
//g_hexdump(s->data, size); //g_hexdump(s->data, size);
log_debug("clipboard_send_format_announce: data out, sending " log_debug("clipboard_send_format_announce: data out, sending "
"CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)"); "CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size); rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s); free_stream(s);
return rv; return rv;
@ -789,7 +791,7 @@ clipboard_send_data_response_for_image(const char *data, int data_size)
int rv; int rv;
log_debug("clipboard_send_data_response_for_image: data_size %d", log_debug("clipboard_send_data_response_for_image: data_size %d",
data_size); data_size);
make_stream(s); make_stream(s);
init_stream(s, 64 + data_size); init_stream(s, 64 + data_size);
out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */ out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */
@ -814,17 +816,17 @@ clipboard_send_data_response_for_text(const char *data, int data_size)
int num_chars; int num_chars;
log_debug("clipboard_send_data_response_for_text: data_size %d", log_debug("clipboard_send_data_response_for_text: data_size %d",
data_size); data_size);
//g_hexdump(data, data_size); //g_hexdump(data, data_size);
num_chars = g_mbstowcs(0, data, 0); num_chars = g_mbstowcs(0, data, 0);
if (num_chars < 0) if (num_chars < 0)
{ {
log_error("clipboard_send_data_response_for_text: " log_error("clipboard_send_data_response_for_text: "
"bad string"); "bad string");
num_chars = 0; num_chars = 0;
} }
log_debug("clipboard_send_data_response_for_text: data_size %d " log_debug("clipboard_send_data_response_for_text: data_size %d "
"num_chars %d", data_size, num_chars); "num_chars %d", data_size, num_chars);
make_stream(s); make_stream(s);
init_stream(s, 64 + num_chars * 2); init_stream(s, 64 + num_chars * 2);
out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */ out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */
@ -833,15 +835,15 @@ clipboard_send_data_response_for_text(const char *data, int data_size)
if (clipboard_out_unicode(s, data, num_chars) != num_chars * 2) if (clipboard_out_unicode(s, data, num_chars) != num_chars * 2)
{ {
log_error("clipboard_send_data_response_for_text: error " log_error("clipboard_send_data_response_for_text: error "
"clipboard_out_unicode didn't write right number of bytes"); "clipboard_out_unicode didn't write right number of bytes");
} }
out_uint16_le(s, 0); /* nil for string */ out_uint16_le(s, 0); /* nil for string */
out_uint32_le(s, 0); out_uint32_le(s, 0);
s_mark_end(s); s_mark_end(s);
size = (int)(s->end - s->data); size = (int)(s->end - s->data);
log_debug("clipboard_send_data_response_for_text: data out, " log_debug("clipboard_send_data_response_for_text: data out, "
"sending CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d " "sending CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d "
"num_chars %d", size, num_chars); "num_chars %d", size, num_chars);
rv = send_channel_data(g_cliprdr_chan_id, s->data, size); rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s); free_stream(s);
return rv; return rv;
@ -869,7 +871,7 @@ clipboard_send_data_response(int xrdp_clip_type, const char *data, int data_size
else else
{ {
log_debug("clipboard_send_data_response: unknown " log_debug("clipboard_send_data_response: unknown "
"xrdp_clip_type %d", xrdp_clip_type); "xrdp_clip_type %d", xrdp_clip_type);
} }
} }
else else
@ -908,7 +910,7 @@ clipboard_provide_selection_c2s(XSelectionRequestEvent *req, Atom type)
long val1[2]; long val1[2];
log_debug("clipboard_provide_selection_c2s: bytes %d", log_debug("clipboard_provide_selection_c2s: bytes %d",
g_clip_c2s.total_bytes); g_clip_c2s.total_bytes);
if (g_clip_c2s.total_bytes < g_incr_max_req_size) if (g_clip_c2s.total_bytes < g_incr_max_req_size)
{ {
XChangeProperty(g_display, req->requestor, req->property, XChangeProperty(g_display, req->requestor, req->property,
@ -934,8 +936,8 @@ clipboard_provide_selection_c2s(XSelectionRequestEvent *req, Atom type)
g_clip_c2s.property = req->property; g_clip_c2s.property = req->property;
g_clip_c2s.window = req->requestor; g_clip_c2s.window = req->requestor;
log_debug("clipboard_provide_selection_c2s: start INCR property %s " log_debug("clipboard_provide_selection_c2s: start INCR property %s "
"type %s", get_atom_text(req->property), "type %s", get_atom_text(req->property),
get_atom_text(type)); get_atom_text(type));
val1[0] = g_clip_c2s.total_bytes; val1[0] = g_clip_c2s.total_bytes;
val1[1] = 0; val1[1] = 0;
XChangeProperty(g_display, req->requestor, req->property, XChangeProperty(g_display, req->requestor, req->property,
@ -1020,7 +1022,7 @@ clipboard_process_format_announce(struct stream *s, int clip_msg_status,
char *holdp; char *holdp;
log_debug("clipboard_process_format_announce: " log_debug("clipboard_process_format_announce: "
"CLIPRDR_FORMAT_ANNOUNCE"); "CLIPRDR_FORMAT_ANNOUNCE");
log_debug("clipboard_process_format_announce %d", clip_msg_len); log_debug("clipboard_process_format_announce %d", clip_msg_len);
clipboard_send_format_ack(); clipboard_send_format_ack();
@ -1052,8 +1054,8 @@ clipboard_process_format_announce(struct stream *s, int clip_msg_status,
clip_msg_len -= 32; clip_msg_len -= 32;
} }
log_debug("clipboard_process_format_announce: formatId 0x%8.8x " log_debug("clipboard_process_format_announce: formatId 0x%8.8x "
"wszFormatName [%s] clip_msg_len %d", formatId, desc, "wszFormatName [%s] clip_msg_len %d", formatId, desc,
clip_msg_len); clip_msg_len);
if (g_num_formatIds <= 15) if (g_num_formatIds <= 15)
{ {
g_formatIds[g_num_formatIds] = formatId; g_formatIds[g_num_formatIds] = formatId;
@ -1073,13 +1075,13 @@ clipboard_process_format_announce(struct stream *s, int clip_msg_status,
} }
if ((g_num_formatIds > 0) && if ((g_num_formatIds > 0) &&
(g_clip_c2s.incr_in_progress == 0) && /* don't interrupt incr */ (g_clip_c2s.incr_in_progress == 0) && /* don't interrupt incr */
(g_clip_s2c.incr_in_progress == 0)) (g_clip_s2c.incr_in_progress == 0))
{ {
if (clipboard_set_selection_owner() != 0) if (clipboard_set_selection_owner() != 0)
{ {
log_error("clipboard_process_format_announce: " log_error("clipboard_process_format_announce: "
"XSetSelectionOwner failed"); "XSetSelectionOwner failed");
} }
} }
@ -1130,7 +1132,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
int requestedFormatId; int requestedFormatId;
log_debug("clipboard_process_data_request: " log_debug("clipboard_process_data_request: "
"CLIPRDR_DATA_REQUEST"); "CLIPRDR_DATA_REQUEST");
log_debug("clipboard_process_data_request:"); log_debug("clipboard_process_data_request:");
log_debug(" %d", g_clip_s2c.xrdp_clip_type); log_debug(" %d", g_clip_s2c.xrdp_clip_type);
in_uint32_le(s, requestedFormatId); in_uint32_le(s, requestedFormatId);
@ -1146,7 +1148,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
else else
{ {
log_debug("clipboard_process_data_request: CB_FORMAT_FILE, " log_debug("clipboard_process_data_request: CB_FORMAT_FILE, "
"calling XConvertSelection to g_utf8_atom"); "calling XConvertSelection to g_utf8_atom");
g_clip_s2c.xrdp_clip_type = XRDP_CB_FILE; g_clip_s2c.xrdp_clip_type = XRDP_CB_FILE;
XConvertSelection(g_display, g_clipboard_atom, g_clip_s2c.type, XConvertSelection(g_display, g_clipboard_atom, g_clip_s2c.type,
g_clip_property_atom, g_wnd, CurrentTime); g_clip_property_atom, g_wnd, CurrentTime);
@ -1162,7 +1164,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
else else
{ {
log_debug("clipboard_process_data_request: CB_FORMAT_DIB, " log_debug("clipboard_process_data_request: CB_FORMAT_DIB, "
"calling XConvertSelection to g_image_bmp_atom"); "calling XConvertSelection to g_image_bmp_atom");
g_clip_s2c.xrdp_clip_type = XRDP_CB_BITMAP; g_clip_s2c.xrdp_clip_type = XRDP_CB_BITMAP;
XConvertSelection(g_display, g_clipboard_atom, g_image_bmp_atom, XConvertSelection(g_display, g_clipboard_atom, g_image_bmp_atom,
g_clip_property_atom, g_wnd, CurrentTime); g_clip_property_atom, g_wnd, CurrentTime);
@ -1178,7 +1180,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
else else
{ {
log_debug("clipboard_process_data_request: CB_FORMAT_UNICODETEXT, " log_debug("clipboard_process_data_request: CB_FORMAT_UNICODETEXT, "
"calling XConvertSelection to g_utf8_atom"); "calling XConvertSelection to g_utf8_atom");
g_clip_s2c.xrdp_clip_type = XRDP_CB_TEXT; g_clip_s2c.xrdp_clip_type = XRDP_CB_TEXT;
XConvertSelection(g_display, g_clipboard_atom, g_utf8_atom, XConvertSelection(g_display, g_clipboard_atom, g_utf8_atom,
g_clip_property_atom, g_wnd, CurrentTime); g_clip_property_atom, g_wnd, CurrentTime);
@ -1186,7 +1188,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
break; break;
default: default:
log_debug("clipboard_process_data_request: unknown type %d", log_debug("clipboard_process_data_request: unknown type %d",
requestedFormatId); requestedFormatId);
clipboard_send_data_response_failed(); clipboard_send_data_response_failed();
break; break;
} }
@ -1201,14 +1203,14 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
clipboard data. */ clipboard data. */
static int static int
clipboard_process_data_response_for_image(struct stream *s, clipboard_process_data_response_for_image(struct stream *s,
int clip_msg_status, int clip_msg_status,
int clip_msg_len) int clip_msg_len)
{ {
XSelectionRequestEvent *lxev; XSelectionRequestEvent *lxev;
int len; int len;
log_debug("clipboard_process_data_response_for_image: " log_debug("clipboard_process_data_response_for_image: "
"CLIPRDR_DATA_RESPONSE_FOR_IMAGE"); "CLIPRDR_DATA_RESPONSE_FOR_IMAGE");
lxev = &g_saved_selection_req_event; lxev = &g_saved_selection_req_event;
len = (int)(s->end - s->p); len = (int)(s->end - s->p);
if (len < 1) if (len < 1)
@ -1231,7 +1233,7 @@ clipboard_process_data_response_for_image(struct stream *s,
g_memcpy(g_clip_c2s.data, g_bmp_image_header, 14); g_memcpy(g_clip_c2s.data, g_bmp_image_header, 14);
in_uint8a(s, g_clip_c2s.data + 14, len); in_uint8a(s, g_clip_c2s.data + 14, len);
log_debug("clipboard_process_data_response_for_image: calling " log_debug("clipboard_process_data_response_for_image: calling "
"clipboard_provide_selection_c2s"); "clipboard_provide_selection_c2s");
clipboard_provide_selection_c2s(lxev, lxev->target); clipboard_provide_selection_c2s(lxev, lxev->target);
return 0; return 0;
} }
@ -1259,7 +1261,7 @@ clipboard_process_data_response(struct stream *s, int clip_msg_status,
if (g_clip_c2s.xrdp_clip_type == XRDP_CB_BITMAP) if (g_clip_c2s.xrdp_clip_type == XRDP_CB_BITMAP)
{ {
clipboard_process_data_response_for_image(s, clip_msg_status, clipboard_process_data_response_for_image(s, clip_msg_status,
clip_msg_len); clip_msg_len);
return 0; return 0;
} }
if (g_clip_c2s.xrdp_clip_type == XRDP_CB_FILE) if (g_clip_c2s.xrdp_clip_type == XRDP_CB_FILE)
@ -1287,7 +1289,7 @@ clipboard_process_data_response(struct stream *s, int clip_msg_status,
return 0; return 0;
} }
log_debug("clipboard_process_data_response: " log_debug("clipboard_process_data_response: "
"CLIPRDR_DATA_RESPONSE"); "CLIPRDR_DATA_RESPONSE");
len = (int)(s->end - s->p); len = (int)(s->end - s->p);
if (len < 1) if (len < 1)
{ {
@ -1362,10 +1364,10 @@ clipboard_process_clip_caps(struct stream *s, int clip_msg_status,
in_uint32_le(s, version); /* version */ in_uint32_le(s, version); /* version */
in_uint32_le(s, flags); /* generalFlags */ in_uint32_le(s, flags); /* generalFlags */
log_debug("clipboard_process_clip_caps: " log_debug("clipboard_process_clip_caps: "
"g_cliprdr_version %d version %d " "g_cliprdr_version %d version %d "
"g_cliprdr_flags 0x%x flags 0x%x", "g_cliprdr_flags 0x%x flags 0x%x",
g_cliprdr_version, version, g_cliprdr_version, version,
g_cliprdr_flags, flags); g_cliprdr_flags, flags);
if (version < g_cliprdr_version) if (version < g_cliprdr_version)
{ {
g_cliprdr_version = version; g_cliprdr_version = version;
@ -1374,7 +1376,7 @@ clipboard_process_clip_caps(struct stream *s, int clip_msg_status,
break; break;
default: default:
log_debug("clipboard_process_clip_caps: unknown " log_debug("clipboard_process_clip_caps: unknown "
"capabilitySetType %d", capabilitySetType); "capabilitySetType %d", capabilitySetType);
break; break;
} }
s->p = holdp + lengthCapability; s->p = holdp + lengthCapability;
@ -1552,16 +1554,16 @@ clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
if (!g_clip_up) if (!g_clip_up)
{ {
log_error("aborting clipboard_data_in - clipboard has not " log_error("aborting clipboard_data_in - clipboard has not "
"been initialized"); "been initialized");
/* we return 0 here to indicate no protocol problem occurred */ /* we return 0 here to indicate no protocol problem occurred */
return 0; return 0;
} }
log_debug("clipboard_data_in: chan_id %d " log_debug("clipboard_data_in: chan_id %d "
"chan_flags 0x%x length %d total_length %d " "chan_flags 0x%x length %d total_length %d "
"in_request %d g_ins->size %d", "in_request %d g_ins->size %d",
chan_id, chan_flags, length, total_length, chan_id, chan_flags, length, total_length,
g_clip_c2s.in_request, g_ins->size); g_clip_c2s.in_request, g_ins->size);
if (g_clip_c2s.doing_response_ss) if (g_clip_c2s.doing_response_ss)
{ {
@ -1621,37 +1623,37 @@ clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
in_uint32_le(ls, clip_msg_len); in_uint32_le(ls, clip_msg_len);
log_debug("clipboard_data_in: clip_msg_id %d " log_debug("clipboard_data_in: clip_msg_id %d "
"clip_msg_status %d clip_msg_len %d", "clip_msg_status %d clip_msg_len %d",
clip_msg_id, clip_msg_status, clip_msg_len); clip_msg_id, clip_msg_status, clip_msg_len);
rv = 0; rv = 0;
log_debug("clipboard_data_in: %d", clip_msg_id); log_debug("clipboard_data_in: %d", clip_msg_id);
switch (clip_msg_id) switch (clip_msg_id)
{ {
/* sent by client or server when its local system clipboard is */ /* sent by client or server when its local system clipboard is */
/* updated with new clipboard data; contains Clipboard Format ID */ /* updated with new clipboard data; contains Clipboard Format ID */
/* and name pairs of new Clipboard Formats on the clipboard. */ /* and name pairs of new Clipboard Formats on the clipboard. */
case CB_FORMAT_LIST: /* 2 CLIPRDR_FORMAT_ANNOUNCE */ case CB_FORMAT_LIST: /* 2 CLIPRDR_FORMAT_ANNOUNCE */
rv = clipboard_process_format_announce(ls, clip_msg_status, rv = clipboard_process_format_announce(ls, clip_msg_status,
clip_msg_len); clip_msg_len);
break; break;
/* response to CB_FORMAT_LIST; used to indicate whether */ /* response to CB_FORMAT_LIST; used to indicate whether */
/* processing of the Format List PDU was successful */ /* processing of the Format List PDU was successful */
case CB_FORMAT_LIST_RESPONSE: /* 3 CLIPRDR_FORMAT_ACK */ case CB_FORMAT_LIST_RESPONSE: /* 3 CLIPRDR_FORMAT_ACK */
rv = clipboard_process_format_ack(ls, clip_msg_status, rv = clipboard_process_format_ack(ls, clip_msg_status,
clip_msg_len); clip_msg_len);
break; break;
/* sent by recipient of CB_FORMAT_LIST; used to request data for one */ /* sent by recipient of CB_FORMAT_LIST; used to request data for one */
/* of the formats that was listed in CB_FORMAT_LIST */ /* of the formats that was listed in CB_FORMAT_LIST */
case CB_FORMAT_DATA_REQUEST: /* 4 CLIPRDR_DATA_REQUEST */ case CB_FORMAT_DATA_REQUEST: /* 4 CLIPRDR_DATA_REQUEST */
rv = clipboard_process_data_request(ls, clip_msg_status, rv = clipboard_process_data_request(ls, clip_msg_status,
clip_msg_len); clip_msg_len);
break; break;
/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate */ /* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate */
/* whether processing of the CB_FORMAT_DATA_REQUEST was */ /* whether processing of the CB_FORMAT_DATA_REQUEST was */
/* successful; if processing was successful, */ /* successful; if processing was successful, */
/* CB_FORMAT_DATA_RESPONSE includes contents of requested */ /* CB_FORMAT_DATA_RESPONSE includes contents of requested */
/* clipboard data. */ /* clipboard data. */
case CB_FORMAT_DATA_RESPONSE: /* 5 CLIPRDR_DATA_RESPONSE */ case CB_FORMAT_DATA_RESPONSE: /* 5 CLIPRDR_DATA_RESPONSE */
rv = clipboard_process_data_response(ls, clip_msg_status, rv = clipboard_process_data_response(ls, clip_msg_status,
clip_msg_len); clip_msg_len);
@ -1671,7 +1673,7 @@ clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
default: default:
log_debug("clipboard_data_in: unknown clip_msg_id %d", clip_msg_id); log_debug("clipboard_data_in: unknown clip_msg_id %d", clip_msg_id);
log_error("clipboard_data_in: unknown clip_msg_id %d", log_error("clipboard_data_in: unknown clip_msg_id %d",
clip_msg_id); clip_msg_id);
break; break;
} }
@ -1703,21 +1705,22 @@ clipboard_event_selection_owner_notify(XEvent *xevent)
lxevent = (XFixesSelectionNotifyEvent *)xevent; lxevent = (XFixesSelectionNotifyEvent *)xevent;
log_debug("clipboard_event_selection_owner_notify: 0x%lx", lxevent->owner); log_debug("clipboard_event_selection_owner_notify: 0x%lx", lxevent->owner);
log_debug("clipboard_event_selection_owner_notify: " log_debug("clipboard_event_selection_owner_notify: "
"window %ld subtype %d owner %ld g_wnd %ld", "window %ld subtype %d owner %ld g_wnd %ld",
lxevent->window, lxevent->subtype, lxevent->owner, g_wnd); lxevent->window, lxevent->subtype, lxevent->owner, g_wnd);
if (lxevent->owner == g_wnd) if (lxevent->owner == g_wnd)
{ {
log_debug("clipboard_event_selection_owner_notify: matches g_wnd"); log_debug("clipboard_event_selection_owner_notify: matches g_wnd");
log_debug("clipboard_event_selection_owner_notify: skipping, " log_debug("clipboard_event_selection_owner_notify: skipping, "
"owner == g_wnd"); "owner == g_wnd");
g_got_selection = 1; g_got_selection = 1;
return 0; return 0;
} }
g_got_selection = 0; g_got_selection = 0;
if (lxevent->owner != 0) /* nil owner comes when selection */ if (lxevent->owner != 0) /* nil owner comes when selection */
{ /* window is closed */ {
/* window is closed */
XConvertSelection(g_display, g_clipboard_atom, g_targets_atom, XConvertSelection(g_display, g_clipboard_atom, g_targets_atom,
g_clip_property_atom, g_wnd, lxevent->timestamp); g_clip_property_atom, g_wnd, lxevent->timestamp);
} }
@ -1871,22 +1874,22 @@ clipboard_event_selection_notify(XEvent *xevent)
if (lxevent->property == None) if (lxevent->property == None)
{ {
log_error("clipboard_event_selection_notify: clip could " log_error("clipboard_event_selection_notify: clip could "
"not be converted"); "not be converted");
rv = 1; rv = 1;
} }
if (rv == 0) if (rv == 0)
{ {
log_debug("clipboard_event_selection_notify: wnd 0x%lx prop %s", log_debug("clipboard_event_selection_notify: wnd 0x%lx prop %s",
lxevent->requestor, lxevent->requestor,
get_atom_text(lxevent->property)); get_atom_text(lxevent->property));
rv = clipboard_get_window_property(lxevent->requestor, lxevent->property, rv = clipboard_get_window_property(lxevent->requestor, lxevent->property,
&type, &fmt, &type, &fmt,
&n_items, &data, &data_size); &n_items, &data, &data_size);
if (rv != 0) if (rv != 0)
{ {
log_error("clipboard_event_selection_notify: " log_error("clipboard_event_selection_notify: "
"clipboard_get_window_property failed error %d", rv); "clipboard_get_window_property failed error %d", rv);
return 0; return 0;
} }
//g_hexdump(data, data_size); //g_hexdump(data, data_size);
@ -1896,9 +1899,9 @@ clipboard_event_selection_notify(XEvent *xevent)
/* nothing more to do here, the data is coming in through /* nothing more to do here, the data is coming in through
PropertyNotify */ PropertyNotify */
log_debug("clipboard_event_selection_notify: type is INCR " log_debug("clipboard_event_selection_notify: type is INCR "
"data_size %d property name %s type %s", data_size, "data_size %d property name %s type %s", data_size,
get_atom_text(lxevent->property), get_atom_text(lxevent->property),
get_atom_text(lxevent->type)); get_atom_text(lxevent->type));
g_clip_s2c.incr_in_progress = 1; g_clip_s2c.incr_in_progress = 1;
g_clip_s2c.property = lxevent->property; g_clip_s2c.property = lxevent->property;
g_clip_s2c.type = lxevent->target; g_clip_s2c.type = lxevent->target;
@ -1928,7 +1931,7 @@ clipboard_event_selection_notify(XEvent *xevent)
"clipboard_event_selection_notify: 0x%lx %s 0x%lx", "clipboard_event_selection_notify: 0x%lx %s 0x%lx",
atom, get_atom_text(atom), XA_STRING)); atom, get_atom_text(atom), XA_STRING));
log_debug("clipboard_event_selection_notify: 0x%lx %s", log_debug("clipboard_event_selection_notify: 0x%lx %s",
atom, get_atom_text(atom)); atom, get_atom_text(atom));
if (atom == g_utf8_atom) if (atom == g_utf8_atom)
{ {
got_utf8 = 1; got_utf8 = 1;
@ -1955,16 +1958,16 @@ clipboard_event_selection_notify(XEvent *xevent)
else else
{ {
log_error("clipboard_event_selection_notify: error, " log_error("clipboard_event_selection_notify: error, "
"target is 'TARGETS' and type[%ld] or fmt[%d] not right, " "target is 'TARGETS' and type[%ld] or fmt[%d] not right, "
"should be type[%ld], fmt[%d]", type, fmt, XA_ATOM, 32); "should be type[%ld], fmt[%d]", type, fmt, XA_ATOM, 32);
} }
} }
else if (lxevent->target == g_utf8_atom) else if (lxevent->target == g_utf8_atom)
{ {
log_debug("clipboard_event_selection_notify: UTF8_STRING " log_debug("clipboard_event_selection_notify: UTF8_STRING "
"data_size %d", data_size); "data_size %d", data_size);
log_debug("clipboard_event_selection_notify: UTF8_STRING " log_debug("clipboard_event_selection_notify: UTF8_STRING "
"data_size %d", data_size); "data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0)) if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
{ {
g_free(g_clip_s2c.data); g_free(g_clip_s2c.data);
@ -1987,9 +1990,9 @@ clipboard_event_selection_notify(XEvent *xevent)
else if (lxevent->target == XA_STRING) else if (lxevent->target == XA_STRING)
{ {
log_debug("clipboard_event_selection_notify: XA_STRING " log_debug("clipboard_event_selection_notify: XA_STRING "
"data_size %d", data_size); "data_size %d", data_size);
log_debug("clipboard_event_selection_notify: XA_STRING " log_debug("clipboard_event_selection_notify: XA_STRING "
"data_size %d", data_size); "data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0)) if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
{ {
g_free(g_clip_s2c.data); g_free(g_clip_s2c.data);
@ -2004,9 +2007,9 @@ clipboard_event_selection_notify(XEvent *xevent)
else if (lxevent->target == g_image_bmp_atom) else if (lxevent->target == g_image_bmp_atom)
{ {
log_debug("clipboard_event_selection_notify: image/bmp " log_debug("clipboard_event_selection_notify: image/bmp "
"data_size %d", data_size); "data_size %d", data_size);
log_debug("clipboard_event_selection_notify: image/bmp " log_debug("clipboard_event_selection_notify: image/bmp "
"data_size %d", data_size); "data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 14)) if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 14))
{ {
g_free(g_clip_s2c.data); g_free(g_clip_s2c.data);
@ -2020,9 +2023,9 @@ clipboard_event_selection_notify(XEvent *xevent)
else if (lxevent->target == g_file_atom1) else if (lxevent->target == g_file_atom1)
{ {
log_debug("clipboard_event_selection_notify: text/uri-list " log_debug("clipboard_event_selection_notify: text/uri-list "
"data_size %d", data_size); "data_size %d", data_size);
log_debug("clipboard_event_selection_notify: text/uri-list " log_debug("clipboard_event_selection_notify: text/uri-list "
"data_size %d", data_size); "data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0)) if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
{ {
g_free(g_clip_s2c.data); g_free(g_clip_s2c.data);
@ -2037,9 +2040,9 @@ clipboard_event_selection_notify(XEvent *xevent)
else if (lxevent->target == g_file_atom2) else if (lxevent->target == g_file_atom2)
{ {
log_debug("clipboard_event_selection_notify: text/uri-list " log_debug("clipboard_event_selection_notify: text/uri-list "
"data_size %d", data_size); "data_size %d", data_size);
log_debug("clipboard_event_selection_notify: text/uri-list " log_debug("clipboard_event_selection_notify: text/uri-list "
"data_size %d", data_size); "data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0)) if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
{ {
g_free(g_clip_s2c.data); g_free(g_clip_s2c.data);
@ -2054,13 +2057,13 @@ clipboard_event_selection_notify(XEvent *xevent)
else else
{ {
log_error("clipboard_event_selection_notify: " log_error("clipboard_event_selection_notify: "
"unknown target"); "unknown target");
} }
} }
else else
{ {
log_error("clipboard_event_selection_notify: " log_error("clipboard_event_selection_notify: "
"unknown selection"); "unknown selection");
} }
} }
@ -2145,24 +2148,24 @@ clipboard_event_selection_request(XEvent *xevent)
lxev = (XSelectionRequestEvent *)xevent; lxev = (XSelectionRequestEvent *)xevent;
log_debug("clipboard_event_selection_request: 0x%lx", lxev->property); log_debug("clipboard_event_selection_request: 0x%lx", lxev->property);
log_debug("clipboard_event_selection_request: g_wnd %ld, " log_debug("clipboard_event_selection_request: g_wnd %ld, "
".requestor %ld .owner %ld .selection %ld '%s' .target %ld .property %ld", ".requestor %ld .owner %ld .selection %ld '%s' .target %ld .property %ld",
g_wnd, lxev->requestor, lxev->owner, lxev->selection, g_wnd, lxev->requestor, lxev->owner, lxev->selection,
get_atom_text(lxev->selection), get_atom_text(lxev->selection),
lxev->target, lxev->property); lxev->target, lxev->property);
if (lxev->property == None) if (lxev->property == None)
{ {
log_debug("clipboard_event_selection_request: lxev->property " log_debug("clipboard_event_selection_request: lxev->property "
"is None"); "is None");
log_debug("clipboard_event_selection_request: " log_debug("clipboard_event_selection_request: "
"lxev->property is None"); "lxev->property is None");
} }
else if (lxev->target == g_targets_atom) else if (lxev->target == g_targets_atom)
{ {
log_debug("clipboard_event_selection_request: g_targets_atom"); log_debug("clipboard_event_selection_request: g_targets_atom");
/* requestor is asking what the selection can be converted to */ /* requestor is asking what the selection can be converted to */
log_debug("clipboard_event_selection_request: " log_debug("clipboard_event_selection_request: "
"g_targets_atom"); "g_targets_atom");
atom_buf[0] = g_targets_atom; atom_buf[0] = g_targets_atom;
atom_buf[1] = g_timestamp_atom; atom_buf[1] = g_timestamp_atom;
atom_buf[2] = g_multiple_atom; atom_buf[2] = g_multiple_atom;
@ -2193,7 +2196,7 @@ clipboard_event_selection_request(XEvent *xevent)
{ {
/* requestor is asking the time I got the selection */ /* requestor is asking the time I got the selection */
log_debug("clipboard_event_selection_request: " log_debug("clipboard_event_selection_request: "
"g_timestamp_atom"); "g_timestamp_atom");
atom_buf[0] = g_selection_time; atom_buf[0] = g_selection_time;
atom_buf[1] = 0; atom_buf[1] = 0;
return clipboard_provide_selection(lxev, XA_INTEGER, 32, return clipboard_provide_selection(lxev, XA_INTEGER, 32,
@ -2203,7 +2206,7 @@ clipboard_event_selection_request(XEvent *xevent)
{ {
/* target, property pairs */ /* target, property pairs */
log_debug("clipboard_event_selection_request: " log_debug("clipboard_event_selection_request: "
"g_multiple_atom"); "g_multiple_atom");
xdata = 0; xdata = 0;
if (clipboard_get_window_property(lxev->requestor, lxev->property, if (clipboard_get_window_property(lxev->requestor, lxev->property,
@ -2211,7 +2214,7 @@ clipboard_event_selection_request(XEvent *xevent)
&xdata_size) == 0) &xdata_size) == 0)
{ {
log_debug("clipboard_event_selection_request: g_multiple_atom " log_debug("clipboard_event_selection_request: g_multiple_atom "
"n_items %d", n_items); "n_items %d", n_items);
/* todo */ /* todo */
g_free(xdata); g_free(xdata);
} }
@ -2276,7 +2279,7 @@ clipboard_event_selection_request(XEvent *xevent)
else else
{ {
log_debug("clipboard_event_selection_request: unknown " log_debug("clipboard_event_selection_request: unknown "
"target %s", get_atom_text(lxev->target)); "target %s", get_atom_text(lxev->target));
LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_request: unknown " LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_request: unknown "
"target %s", get_atom_text(lxev->target))); "target %s", get_atom_text(lxev->target)));
} }
@ -2332,9 +2335,9 @@ clipboard_event_property_notify(XEvent *xevent)
log_debug("clipboard_event_property_notify:"); log_debug("clipboard_event_property_notify:");
log_debug("clipboard_event_property_notify: PropertyNotify .window %ld " log_debug("clipboard_event_property_notify: PropertyNotify .window %ld "
".state %d .atom %ld %s", xevent->xproperty.window, ".state %d .atom %ld %s", xevent->xproperty.window,
xevent->xproperty.state, xevent->xproperty.atom, xevent->xproperty.state, xevent->xproperty.atom,
get_atom_text(xevent->xproperty.atom)); get_atom_text(xevent->xproperty.atom));
if (g_clip_c2s.incr_in_progress && if (g_clip_c2s.incr_in_progress &&
(xevent->xproperty.window == g_clip_c2s.window) && (xevent->xproperty.window == g_clip_c2s.window) &&
@ -2353,7 +2356,7 @@ clipboard_event_property_notify(XEvent *xevent)
data = (tui8 *)(g_clip_c2s.data + g_clip_c2s.incr_bytes_done); data = (tui8 *)(g_clip_c2s.data + g_clip_c2s.incr_bytes_done);
data_bytes = g_clip_c2s.read_bytes_done - g_clip_c2s.incr_bytes_done; data_bytes = g_clip_c2s.read_bytes_done - g_clip_c2s.incr_bytes_done;
if ((data_bytes < 1) && if ((data_bytes < 1) &&
(g_clip_c2s.read_bytes_done < g_clip_c2s.total_bytes)) (g_clip_c2s.read_bytes_done < g_clip_c2s.total_bytes))
{ {
g_clip_c2s.incr_in_progress = 0; g_clip_c2s.incr_in_progress = 0;
return 0; return 0;
@ -2423,7 +2426,7 @@ clipboard_event_property_notify(XEvent *xevent)
else else
{ {
log_error("clipboard_event_property_notify: error unknown type %ld", log_error("clipboard_event_property_notify: error unknown type %ld",
g_clip_s2c.type); g_clip_s2c.type);
clipboard_send_data_response_failed(); clipboard_send_data_response_failed();
} }
@ -2484,6 +2487,8 @@ clipboard_xevent(void *xevent)
{ {
XEvent *lxevent; XEvent *lxevent;
log_debug("clipboard_xevent: event detected");
if (!g_clip_up) if (!g_clip_up)
{ {
return 1; return 1;
@ -2494,7 +2499,15 @@ clipboard_xevent(void *xevent)
switch (lxevent->type) switch (lxevent->type)
{ {
case SelectionNotify: case SelectionNotify:
clipboard_event_selection_notify(lxevent); if (g_restrict_outbound_clipboard == 0)
{
clipboard_event_selection_notify(lxevent);
}
else
{
log_debug("outbound clipboard is restricted because of config");
return 1;
}
break; break;
case SelectionRequest: case SelectionRequest:
clipboard_event_selection_request(lxevent); clipboard_event_selection_request(lxevent);

View File

@ -91,6 +91,13 @@
} \ } \
} }
/*
* Size of structs supported by IRP_MJ_QUERY_INFORMATION without
* trailing RESERVED fields (MS-RDPEFS 2.2.3.3.8)
*/
#define FILE_BASIC_INFORMATION_SIZE 36
#define FILE_STD_INFORMATION_SIZE 22
/* globals */ /* globals */
extern int g_rdpdr_chan_id; /* in chansrv.c */ extern int g_rdpdr_chan_id; /* in chansrv.c */
int g_is_printer_redir_supported = 0; int g_is_printer_redir_supported = 0;
@ -106,7 +113,26 @@ tui32 g_device_id; /* unique device ID - announced by client */
tui16 g_client_rdp_version; /* returned by client */ tui16 g_client_rdp_version; /* returned by client */
struct stream *g_input_stream = NULL; struct stream *g_input_stream = NULL;
void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length); /*
* Local functions called from dev_redir_proc_device_iocompletion()
*/
static void devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus);
static void devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus);
static void devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus);
static void devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus);
static void devredir_proc_cid_lookup_basic_entry(IRP *irp, tui32 IoStatus);
static void devredir_proc_cid_lookup_basic_entry_resp(
IRP *irp,
struct stream *s_in,
tui32 IoStatus);
static void devredir_proc_cid_lookup_std_entry_resp(
IRP *irp,
struct stream *s_in,
tui32 DeviceId,
tui32 CompletionId,
tui32 IoStatus);
/* Other local functions */
static void lookup_std_entry(IRP *irp);
/*****************************************************************************/ /*****************************************************************************/
int int
@ -816,7 +842,8 @@ dev_redir_proc_device_iocompletion(struct stream *s)
} }
else else
{ {
xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length); xfuse_devredir_cb_write_file(fuse_data->data_ptr, IoStatus,
s->p, Length);
devredir_irp_delete(irp); devredir_irp_delete(irp);
} }
break; break;
@ -866,6 +893,27 @@ dev_redir_proc_device_iocompletion(struct stream *s)
devredir_proc_cid_rename_file_resp(irp, IoStatus); devredir_proc_cid_rename_file_resp(irp, IoStatus);
break; break;
case CID_LOOKUP_BASIC_ENTRY:
log_debug("got CID_LOOKUP_BASIC_ENTRY");
xstream_rd_u32_le(s, irp->FileId);
/* Issue a call to get the FileBasicInformation */
devredir_proc_cid_lookup_basic_entry(irp, IoStatus);
break;
case CID_LOOKUP_STD_ENTRY:
log_debug("got CID_LOOKUP_STD_ENTRY");
/* Parse the FileBasicInformation and request the
* FileStandardInformation */
devredir_proc_cid_lookup_basic_entry_resp(irp, s, IoStatus);
break;
case CID_LOOKUP_ENTRY_RESP:
/* Parse the FileStandardInformation and respond to caller */
log_debug("got CID_LOOKUP_ENTRY_RESP");
devredir_proc_cid_lookup_std_entry_resp(irp, s, DeviceId,
CompletionId, IoStatus);
break;
default: default:
log_error("got unknown CompletionID: DeviceId=0x%x " log_error("got unknown CompletionID: DeviceId=0x%x "
"CompletionId=0x%x IoStatus=0x%x", "CompletionId=0x%x IoStatus=0x%x",
@ -892,7 +940,6 @@ dev_redir_proc_query_dir_response(IRP *irp,
tui32 IoStatus) tui32 IoStatus)
{ {
FUSE_DATA *fuse_data = NULL; FUSE_DATA *fuse_data = NULL;
XRDP_INODE *xinode;
tui32 Length; tui32 Length;
tui64 CreationTime; tui64 CreationTime;
@ -902,6 +949,7 @@ dev_redir_proc_query_dir_response(IRP *irp,
tui32 FileAttributes; tui32 FileAttributes;
tui32 FileNameLength; tui32 FileNameLength;
tui32 status; tui32 status;
struct file_attr fattr;
char filename[256]; char filename[256];
unsigned int i = 0; unsigned int i = 0;
@ -967,25 +1015,16 @@ dev_redir_proc_query_dir_response(IRP *irp,
//log_debug("FileNameLength: %d", FileNameLength); //log_debug("FileNameLength: %d", FileNameLength);
log_debug("FileName: %s", filename); log_debug("FileName: %s", filename);
xinode = g_new0(struct xrdp_inode, 1); fattr.name = filename;
if (xinode == NULL) fattr.mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes);
{ fattr.size = (size_t) EndOfFile;
log_error("system out of memory"); fattr.atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
fuse_data = devredir_fuse_data_peek(irp); fattr.mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, NULL); fattr.ctime = WINDOWS_TO_LINUX_TIME(CreationTime);
return;
}
strcpy(xinode->name, filename);
xinode->size = (size_t) EndOfFile;
xinode->mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes);
xinode->atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
xinode->mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
xinode->ctime = WINDOWS_TO_LINUX_TIME(CreationTime);
/* add this entry to xrdp file system */ /* add this entry to xrdp file system */
fuse_data = devredir_fuse_data_peek(irp); fuse_data = devredir_fuse_data_peek(irp);
xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, xinode); (void)xfuse_devredir_add_file_or_dir(fuse_data->data_ptr, &fattr);
} }
dev_redir_send_drive_dir_request(irp, DeviceId, 0, NULL); dev_redir_send_drive_dir_request(irp, DeviceId, 0, NULL);
@ -1048,6 +1087,78 @@ dev_redir_get_dir_listing(void *fusep, tui32 device_id, const char *path)
return rval; return rval;
} }
/**
* FUSE calls this function whenever it wants us to lookup a file or directory
*
* @param fusep opaque data struct that we just pass back to FUSE when done
* @param device_id device_id of the redirected share
* @param path the name of the directory containing the file
* @param file the filename
*
* @return 0 on success, -1 on failure
*****************************************************************************/
int
dev_redir_lookup_entry(void *fusep, tui32 device_id, const char *dirpath,
const char *entry)
{
tui32 DesiredAccess;
tui32 CreateOptions;
tui32 CreateDisposition;
int rval = -1;
IRP *irp;
size_t pathlen;
log_debug("fusep=%p", fusep);
/* Check the qualified name of the file fits in the IRP */
pathlen = strlen(dirpath) + strlen(entry);
if (!dev_redir_string_ends_with(dirpath,'/'))
{
++pathlen;
}
if (pathlen < sizeof(irp->pathname))
{
if ((irp = devredir_irp_new()) != NULL)
{
strcpy(irp->pathname, dirpath);
if (!dev_redir_string_ends_with(dirpath, '/'))
{
strcat(irp->pathname, "/");
}
strcat(irp->pathname, entry);
/* convert / to windows compatible \ */
devredir_cvt_slash(irp->pathname);
/*
* Allocate an IRP to open the file, read the basic attributes,
* read the standard attributes, and then close the file
*/
irp->CompletionId = g_completion_id++;
irp->completion_type = CID_LOOKUP_BASIC_ENTRY;
irp->DeviceId = device_id;
devredir_fuse_data_enqueue(irp, fusep);
DesiredAccess = DA_FILE_READ_ATTRIBUTES | DA_SYNCHRONIZE;
CreateOptions = 0x020; /* Same as rmdir or file */
CreateDisposition = CD_FILE_OPEN;
log_debug("lookup for device_id=%d path=%s",
device_id, irp->pathname);
rval = dev_redir_send_drive_create_request(device_id,
irp->pathname,
DesiredAccess, CreateOptions,
CreateDisposition,
irp->CompletionId);
}
}
return rval;
}
int int
dev_redir_file_open(void *fusep, tui32 device_id, const char *path, dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
int mode, int type, const char *gen_buf) int mode, int type, const char *gen_buf)
@ -1066,7 +1177,7 @@ dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
if (type & OP_RENAME_FILE) if (type & OP_RENAME_FILE)
{ {
irp->completion_type = CID_RENAME_FILE; irp->completion_type = CID_RENAME_FILE;
strncpy(irp->gen_buf, gen_buf, 1023); strncpy(irp->gen.buf, gen_buf, 1023);
} }
else else
{ {
@ -1101,14 +1212,30 @@ dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
} }
else else
{ {
log_debug("open file in O_RDWR");
#if 1 #if 1
/* without the 0x00000010 rdesktop opens files in */ switch(mode & O_ACCMODE)
/* O_RDONLY instead of O_RDWR mode */ {
if (mode & O_RDWR) case O_RDONLY:
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010; log_debug("open file in O_RDONLY");
else DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE; break;
case O_WRONLY:
log_debug("open file in O_WRONLY");
DesiredAccess = DA_FILE_WRITE_DATA | DA_SYNCHRONIZE;
break;
default:
/*
* The access mode could conceivably be invalid here,
* but we assume this has been checked by the caller
*/
log_debug("open file in O_RDWR");
/* without the 0x00000010 rdesktop opens files in */
/* O_RDONLY instead of O_RDWR mode */
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA |
DA_SYNCHRONIZE | 0x00000010;
}
CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT; CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT;
CreateDisposition = CD_FILE_OPEN; // WAS 1 CreateDisposition = CD_FILE_OPEN; // WAS 1
@ -1277,7 +1404,7 @@ dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL) if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
{ {
log_error("no IRP found with FileId = %d", FileId); log_error("no IRP found with FileId = %d", FileId);
xfuse_devredir_cb_write_file(fusep, NULL, 0); xfuse_devredir_cb_write_file(fusep, NT_STATUS_UNSUCCESSFUL, NULL, 0);
xstream_free(s); xstream_free(s);
return -1; return -1;
} }
@ -1286,7 +1413,7 @@ dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
if ((new_irp = devredir_irp_clone(irp)) == NULL) if ((new_irp = devredir_irp_clone(irp)) == NULL)
{ {
/* system out of memory */ /* system out of memory */
xfuse_devredir_cb_write_file(fusep, NULL, 0); xfuse_devredir_cb_write_file(fusep, NT_STATUS_UNSUCCESSFUL, NULL, 0);
xstream_free(s); xstream_free(s);
return -1; return -1;
} }
@ -1514,12 +1641,12 @@ devredir_cvt_from_unicode_len(char *path, char *unicode, int len)
} }
int int
dev_redir_string_ends_with(char *string, char c) dev_redir_string_ends_with(const char *string, char c)
{ {
int len; size_t len;
len = strlen(string); len = strlen(string);
return (string[len - 1] == c) ? 1 : 0; return (len > 0 && string[len - 1] == c) ? 1 : 0;
} }
void void
@ -1530,7 +1657,7 @@ devredir_insert_RDPDR_header(struct stream *s, tui16 Component,
xstream_wr_u16_le(s, PacketId); xstream_wr_u16_le(s, PacketId);
} }
void static void
devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus) devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
{ {
struct stream *s; struct stream *s;
@ -1567,7 +1694,7 @@ devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
return; return;
} }
void static void
devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus) devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
{ {
FUSE_DATA *fuse_data; FUSE_DATA *fuse_data;
@ -1594,7 +1721,7 @@ devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
IRP_MJ_CLOSE, 0, 32); IRP_MJ_CLOSE, 0, 32);
} }
void static void
devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus) devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
{ {
struct stream *s; struct stream *s;
@ -1618,7 +1745,7 @@ devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
} }
/* Path in unicode needs this much space */ /* Path in unicode needs this much space */
flen = ((g_mbstowcs(NULL, irp->gen_buf, 0) * sizeof(twchar)) / 2) + 2; flen = ((g_mbstowcs(NULL, irp->gen.buf, 0) * sizeof(twchar)) / 2) + 2;
sblen = 6 + flen; sblen = 6 + flen;
xstream_new(s, 1024 + flen); xstream_new(s, 1024 + flen);
@ -1636,7 +1763,7 @@ devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
xstream_wr_u32_le(s, flen); /* FileNameLength */ xstream_wr_u32_le(s, flen); /* FileNameLength */
/* filename in unicode */ /* filename in unicode */
devredir_cvt_to_unicode(s->p, irp->gen_buf); /* UNICODE_TODO */ devredir_cvt_to_unicode(s->p, irp->gen.buf); /* UNICODE_TODO */
xstream_seek(s, flen); xstream_seek(s, flen);
/* send to client */ /* send to client */
@ -1647,7 +1774,7 @@ devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
return; return;
} }
void static void
devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus) devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
{ {
FUSE_DATA *fuse_data; FUSE_DATA *fuse_data;
@ -1675,3 +1802,192 @@ devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
irp->CompletionId, irp->CompletionId,
IRP_MJ_CLOSE, 0, 32); IRP_MJ_CLOSE, 0, 32);
} }
static void
devredir_proc_cid_lookup_basic_entry(IRP *irp, tui32 IoStatus)
{
struct stream *s;
int bytes;
if (IoStatus != NT_STATUS_SUCCESS)
{
log_debug("lookup returned with IoStatus=0x%08x", IoStatus);
FUSE_DATA *fuse_data = devredir_fuse_data_dequeue(irp);
if (fuse_data)
{
xfuse_devredir_cb_lookup_entry(fuse_data->data_ptr, IoStatus, NULL);
free(fuse_data);
}
devredir_irp_delete(irp);
}
else
{
xstream_new(s, 1024);
irp->completion_type = CID_LOOKUP_STD_ENTRY;
devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
irp->CompletionId,
IRP_MJ_QUERY_INFORMATION, 0);
xstream_wr_u32_le(s, FileBasicInformation);
xstream_wr_u32_le(s, FILE_BASIC_INFORMATION_SIZE);
/* buffer length */
xstream_seek(s, 24); /* padding */
xstream_seek(s, FILE_BASIC_INFORMATION_SIZE);
/* buffer */
/* send to client */
bytes = xstream_len(s);
send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s);
}
}
static void
devredir_proc_cid_lookup_basic_entry_resp(IRP *irp,
struct stream *s_in,
tui32 IoStatus)
{
tui32 Length = 0;
tui64 CreationTime;
tui64 LastAccessTime;
tui64 LastWriteTime;
tui32 FileAttributes;
log_debug("basic_lookup returned with IoStatus=0x%08x", IoStatus);
/* Data as we expect? */
if (IoStatus == NT_STATUS_SUCCESS)
{
xstream_rd_u32_le(s_in, Length);
if (Length != FILE_BASIC_INFORMATION_SIZE)
{
log_error("Expected FILE_BASIC_OPEN_INFORMATION data but len=%d",
Length);
}
}
if (IoStatus != NT_STATUS_SUCCESS ||
Length != FILE_BASIC_INFORMATION_SIZE)
{
/* Return a lookup fail to the FUSE caller */
FUSE_DATA *fuse_data = devredir_fuse_data_dequeue(irp);
if (fuse_data)
{
xfuse_devredir_cb_lookup_entry(fuse_data->data_ptr, IoStatus, NULL);
free(fuse_data);
}
devredir_irp_delete(irp);
}
else
{
log_debug("processing FILE_BASIC_INFORMATION");
xstream_rd_u64_le(s_in, CreationTime);
xstream_rd_u64_le(s_in, LastAccessTime);
xstream_rd_u64_le(s_in, LastWriteTime);
xstream_seek(s_in, 8); /* ChangeTime */
xstream_rd_u32_le(s_in, FileAttributes);
//log_debug("CreationTime: 0x%llx",
// (unsigned long long)CreationTime);
//log_debug("LastAccessTime: 0x%llx",
// (unsigned long long)LastAccessTime);
//log_debug("LastWriteTime: 0x%llx",
// (unsigned long long)LastWriteTime);
//log_debug("FileAttributes: 0x%x", (unsigned int)FileAttributes);
/* Save the basic attributes in the IRP */
irp->gen.fattr.mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes);
irp->gen.fattr.atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
irp->gen.fattr.mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
irp->gen.fattr.ctime = WINDOWS_TO_LINUX_TIME(CreationTime);
/* Re-use the IRP to lookup the FileStandardInformation */
lookup_std_entry(irp);
}
}
static void
lookup_std_entry(IRP *irp)
{
struct stream *s;
int bytes;
xstream_new(s, 1024);
irp->completion_type = CID_LOOKUP_ENTRY_RESP;
devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
irp->CompletionId,
IRP_MJ_QUERY_INFORMATION, 0);
xstream_wr_u32_le(s, FileStandardInformation);
xstream_wr_u32_le(s, FILE_STD_INFORMATION_SIZE);
/* buffer length */
xstream_seek(s, 24); /* padding */
xstream_seek(s, FILE_STD_INFORMATION_SIZE);
/* buffer */
/* send to client */
bytes = xstream_len(s);
send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s);
}
static void
devredir_proc_cid_lookup_std_entry_resp(IRP *irp,
struct stream *s_in,
tui32 DeviceId,
tui32 CompletionId,
tui32 IoStatus)
{
FUSE_DATA *fuse_data;
tui32 Length;
tui64 EndOfFile;
struct xrdp_inode *xinode = NULL;
fuse_data = devredir_fuse_data_dequeue(irp);
if (!fuse_data)
{
log_error("fuse_data unexpectedly NULL!");
}
else
{
if (IoStatus == NT_STATUS_SUCCESS)
{
/* Data as we expect? */
xstream_rd_u32_le(s_in, Length);
if (Length != FILE_STD_INFORMATION_SIZE)
{
log_error("Expected FILE_STD_OPEN_INFORMATION data but len=%d",
Length);
}
else
{
log_debug("processing FILE_STD_INFORMATION");
xstream_seek(s_in, 8); /* AllocationSize */
xstream_rd_u64_le(s_in, EndOfFile);
//log_debug("EndOfFile: %lld",
// (unsigned long long)EndOfFile);
/* Finish the attribute block off and add the file */
irp->gen.fattr.size = EndOfFile;
irp->gen.fattr.name = strrchr(irp->pathname,'\\') + 1;
xinode = xfuse_devredir_add_file_or_dir(fuse_data->data_ptr,
&irp->gen.fattr);
}
}
xfuse_devredir_cb_lookup_entry(fuse_data->data_ptr, IoStatus, xinode);
free(fuse_data);
}
/* Close the file handle */
irp->completion_type = CID_CLOSE;
dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
PAKID_CORE_DEVICE_IOREQUEST,
irp->DeviceId,
irp->FileId,
irp->CompletionId,
IRP_MJ_CLOSE, 0, 32);
}

View File

@ -84,19 +84,17 @@ void devredir_insert_DeviceIoRequest(struct stream *s,
void devredir_cvt_slash(char *path); void devredir_cvt_slash(char *path);
void devredir_cvt_to_unicode(char *unicode, const char *path); void devredir_cvt_to_unicode(char *unicode, const char *path);
void devredir_cvt_from_unicode_len(char *path, char *unicode, int len); void devredir_cvt_from_unicode_len(char *path, char *unicode, int len);
int dev_redir_string_ends_with(char *string, char c); int dev_redir_string_ends_with(const char *string, char c);
void devredir_insert_RDPDR_header(struct stream *s, tui16 Component, void devredir_insert_RDPDR_header(struct stream *s, tui16 Component,
tui16 PacketId); tui16 PacketId);
void devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus);
void devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus);
void devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus);
void devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus);
/* called from FUSE module */ /* called from FUSE module */
int dev_redir_get_dir_listing(void *fusep, tui32 device_id, const char *path); int dev_redir_get_dir_listing(void *fusep, tui32 device_id, const char *path);
int dev_redir_lookup_entry(void *fusep, tui32 device_id, const char *dirpath,
const char *entry);
int dev_redir_file_open(void *fusep, tui32 device_id, const char *path, int dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
int mode, int type, const char *gen_buf); int mode, int type, const char *gen_buf);
@ -260,11 +258,15 @@ enum CREATE_OPTIONS
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002 #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002
/* /*
* NTSTATUS codes (used by IoStatus) * NTSTATUS codes (used by IoStatus) - see section 2.3 of MS-ERREF
*/ */
#define NT_STATUS_SUCCESS 0x00000000 #define NT_STATUS_SUCCESS 0x00000000
#define NT_STATUS_UNSUCCESSFUL 0xC0000001 #define NT_STATUS_UNSUCCESSFUL 0xC0000001
#define NT_STATUS_NO_SUCH_FILE 0xC000000F
#define NT_STATUS_ACCESS_DENIED 0xC0000022
#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000033
#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034
/* /*
* File system ioctl codes * File system ioctl codes
@ -289,12 +291,16 @@ enum COMPLETION_ID
CID_RMDIR_OR_FILE, CID_RMDIR_OR_FILE,
CID_RMDIR_OR_FILE_RESP, CID_RMDIR_OR_FILE_RESP,
CID_RENAME_FILE, CID_RENAME_FILE,
CID_RENAME_FILE_RESP CID_RENAME_FILE_RESP,
CID_LOOKUP_BASIC_ENTRY,
CID_LOOKUP_STD_ENTRY,
CID_LOOKUP_ENTRY_RESP
}; };
enum FS_INFORMATION_CLASS enum FS_INFORMATION_CLASS
{ {
FileBasicInformation = 0x00000004, /* set atime, mtime, ctime etc */ FileBasicInformation = 0x00000004, /* set atime, mtime, ctime etc */
FileStandardInformation = 0x00000005, /* Alloc size, EOF #links, etc */
FileEndOfFileInformation = 0x00000014, /* set EOF info */ FileEndOfFileInformation = 0x00000014, /* set EOF info */
FileDispositionInformation = 0x0000000D, /* mark a file for deletion */ FileDispositionInformation = 0x0000000D, /* mark a file for deletion */
FileRenameInformation = 0x0000000A, /* rename a file */ FileRenameInformation = 0x0000000A, /* rename a file */

View File

@ -24,6 +24,8 @@
#ifndef __IRP_H #ifndef __IRP_H
#define __IRP_H #define __IRP_H
#include "chansrv_fuse.h"
typedef struct fuse_data FUSE_DATA; typedef struct fuse_data FUSE_DATA;
struct fuse_data struct fuse_data
{ {
@ -42,7 +44,11 @@ struct irp
tui32 FileId; /* RDP client provided unique number */ tui32 FileId; /* RDP client provided unique number */
char completion_type; /* describes I/O type */ char completion_type; /* describes I/O type */
char pathname[256]; /* absolute pathname */ char pathname[256]; /* absolute pathname */
char gen_buf[1024]; /* for general use */ union
{
char buf[1024]; /* General character data */
struct file_attr fattr; /* Used to assemble file attributes */
} gen; /* for general use */
int type; int type;
FUSE_DATA *fd_head; /* point to first FUSE opaque object */ FUSE_DATA *fd_head; /* point to first FUSE opaque object */
FUSE_DATA *fd_tail; /* point to last FUSE opaque object */ FUSE_DATA *fd_tail; /* point to last FUSE opaque object */

View File

@ -34,8 +34,6 @@
#include "sesman.h" #include "sesman.h"
#include "log.h" #include "log.h"
extern struct config_sesman *g_cfg; /* in sesman.c */
/******************************************************************************/ /******************************************************************************/
@ -185,11 +183,11 @@ config_read_globals(int file, struct config_sesman *cf, struct list *param_n,
if (cf->default_wm[0] != '/') if (cf->default_wm[0] != '/')
{ {
/* sizeof operator returns string length including null terminator */ /* sizeof operator returns string length including null terminator */
length = sizeof(XRDP_CFG_PATH) + g_strlen(g_cfg->default_wm) + 1; /* '/' */ length = sizeof(XRDP_CFG_PATH) + g_strlen(cf->default_wm) + 1; /* '/' */
buf = (char *)g_malloc(length, 0); buf = (char *)g_malloc(length, 0);
g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, g_cfg->default_wm); g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, cf->default_wm);
g_free(g_cfg->default_wm); g_free(cf->default_wm);
g_cfg->default_wm = g_strdup(buf); cf->default_wm = g_strdup(buf);
g_free(buf); g_free(buf);
} }
@ -206,14 +204,23 @@ config_read_globals(int file, struct config_sesman *cf, struct list *param_n,
if (cf->reconnect_sh[0] != '/') if (cf->reconnect_sh[0] != '/')
{ {
/* sizeof operator returns string length including null terminator */ /* sizeof operator returns string length including null terminator */
length = sizeof(XRDP_CFG_PATH) + g_strlen(g_cfg->reconnect_sh) + 1; /* '/' */ length = sizeof(XRDP_CFG_PATH) + g_strlen(cf->reconnect_sh) + 1; /* '/' */
buf = (char *)g_malloc(length, 0); buf = (char *)g_malloc(length, 0);
g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, g_cfg->reconnect_sh); g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, cf->reconnect_sh);
g_free(g_cfg->reconnect_sh); g_free(cf->reconnect_sh);
g_cfg->reconnect_sh = g_strdup(buf); cf->reconnect_sh = g_strdup(buf);
g_free(buf); g_free(buf);
} }
log_message(LOG_LEVEL_TRACE, "config loaded in %s at %s:%d", __func__, __FILE__, __LINE__);
log_message(LOG_LEVEL_TRACE, " listen_address = %s", cf->listen_address);
log_message(LOG_LEVEL_TRACE, " listen_port = %s", cf->listen_port);
log_message(LOG_LEVEL_TRACE, " enable_user_wm = %d", cf->enable_user_wm);
log_message(LOG_LEVEL_TRACE, " default_wm = %s", cf->default_wm);
log_message(LOG_LEVEL_TRACE, " user_wm = %s", cf->user_wm);
log_message(LOG_LEVEL_TRACE, " reconnect_sh = %s", cf->reconnect_sh);
log_message(LOG_LEVEL_TRACE, " auth_file_path = %s", cf->auth_file_path);
return 0; return 0;
} }
@ -235,6 +242,7 @@ config_read_security(int file, struct config_security *sc,
sc->login_retry = 3; sc->login_retry = 3;
sc->ts_users_enable = 0; sc->ts_users_enable = 0;
sc->ts_admins_enable = 0; sc->ts_admins_enable = 0;
sc->restrict_outbound_clipboard = 0;
file_read_section(file, SESMAN_CFG_SECURITY, param_n, param_v); file_read_section(file, SESMAN_CFG_SECURITY, param_n, param_v);
@ -273,6 +281,12 @@ config_read_security(int file, struct config_security *sc,
{ {
sc->ts_always_group_check = g_text2bool((char *)list_get_item(param_v, i)); sc->ts_always_group_check = g_text2bool((char *)list_get_item(param_v, i));
} }
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD))
{
sc->restrict_outbound_clipboard = g_text2bool((char *)list_get_item(param_v, i));
}
} }
return 0; return 0;
@ -481,7 +495,7 @@ config_dump(struct config_sesman *config)
g_writeln(" DefaultWindowManager: %s", config->default_wm); g_writeln(" DefaultWindowManager: %s", config->default_wm);
g_writeln(" ReconnectScript: %s", config->reconnect_sh); g_writeln(" ReconnectScript: %s", config->reconnect_sh);
g_writeln(" AuthFilePath: %s", g_writeln(" AuthFilePath: %s",
((config->auth_file_path) ? (config->auth_file_path) : ("disabled"))); ((config->auth_file_path) ? (config->auth_file_path) : ("disabled")));
/* Session configuration */ /* Session configuration */
g_writeln("Session configuration:"); g_writeln("Session configuration:");
@ -497,6 +511,7 @@ config_dump(struct config_sesman *config)
g_writeln(" AllowRootLogin: %d", sc->allow_root); g_writeln(" AllowRootLogin: %d", sc->allow_root);
g_writeln(" MaxLoginRetry: %d", sc->login_retry); g_writeln(" MaxLoginRetry: %d", sc->login_retry);
g_writeln(" AlwaysGroupCheck: %d", sc->ts_always_group_check); g_writeln(" AlwaysGroupCheck: %d", sc->ts_always_group_check);
g_writeln(" RestrictOutboundClipboard: %d", sc->restrict_outbound_clipboard);
g_printf( " TSUsersGroup: "); g_printf( " TSUsersGroup: ");
if (sc->ts_users_enable) if (sc->ts_users_enable)
@ -530,7 +545,7 @@ config_dump(struct config_sesman *config)
for (i = 0; i < config->xorg_params->count; i++) for (i = 0; i < config->xorg_params->count; i++)
{ {
g_writeln(" Parameter %02d %s", g_writeln(" Parameter %02d %s",
i, (char *) list_get_item(config->xorg_params, i)); i, (char *) list_get_item(config->xorg_params, i));
} }
/* Xvnc */ /* Xvnc */
@ -542,7 +557,7 @@ config_dump(struct config_sesman *config)
for (i = 0; i < config->vnc_params->count; i++) for (i = 0; i < config->vnc_params->count; i++)
{ {
g_writeln(" Parameter %02d %s", g_writeln(" Parameter %02d %s",
i, (char *)list_get_item(config->vnc_params, i)); i, (char *)list_get_item(config->vnc_params, i));
} }
/* X11rdp */ /* X11rdp */
@ -554,7 +569,7 @@ config_dump(struct config_sesman *config)
for (i = 0; i < config->rdp_params->count; i++) for (i = 0; i < config->rdp_params->count; i++)
{ {
g_writeln(" Parameter %02d %s", g_writeln(" Parameter %02d %s",
i, (char *)list_get_item(config->rdp_params, i)); i, (char *)list_get_item(config->rdp_params, i));
} }
/* SessionVariables */ /* SessionVariables */
@ -567,7 +582,7 @@ config_dump(struct config_sesman *config)
{ {
g_writeln(" Parameter %02d %s=%s", g_writeln(" Parameter %02d %s=%s",
i, (char *) list_get_item(config->env_names, i), i, (char *) list_get_item(config->env_names, i),
(char *) list_get_item(config->env_values, i)); (char *) list_get_item(config->env_values, i));
} }
} }

View File

@ -54,12 +54,13 @@
#define SESMAN_CFG_LOG_ENABLE_SYSLOG "EnableSyslog" #define SESMAN_CFG_LOG_ENABLE_SYSLOG "EnableSyslog"
#define SESMAN_CFG_LOG_SYSLOG_LEVEL "SyslogLevel" #define SESMAN_CFG_LOG_SYSLOG_LEVEL "SyslogLevel"
*/ */
#define SESMAN_CFG_SECURITY "Security" #define SESMAN_CFG_SECURITY "Security"
#define SESMAN_CFG_SEC_LOGIN_RETRY "MaxLoginRetry" #define SESMAN_CFG_SEC_LOGIN_RETRY "MaxLoginRetry"
#define SESMAN_CFG_SEC_ALLOW_ROOT "AllowRootLogin" #define SESMAN_CFG_SEC_ALLOW_ROOT "AllowRootLogin"
#define SESMAN_CFG_SEC_USR_GROUP "TerminalServerUsers" #define SESMAN_CFG_SEC_USR_GROUP "TerminalServerUsers"
#define SESMAN_CFG_SEC_ADM_GROUP "TerminalServerAdmins" #define SESMAN_CFG_SEC_ADM_GROUP "TerminalServerAdmins"
#define SESMAN_CFG_SEC_ALWAYSGROUPCHECK "AlwaysGroupCheck" #define SESMAN_CFG_SEC_ALWAYSGROUPCHECK "AlwaysGroupCheck"
#define SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD "RestrictOutboundClipboard"
#define SESMAN_CFG_SESSIONS "Sessions" #define SESMAN_CFG_SESSIONS "Sessions"
#define SESMAN_CFG_SESS_MAX "MaxSessions" #define SESMAN_CFG_SESS_MAX "MaxSessions"
@ -126,6 +127,11 @@ struct config_security
* @brief if the Groups are not found deny access * @brief if the Groups are not found deny access
*/ */
int ts_always_group_check; int ts_always_group_check;
/**
* @var restrict_outbound_clipboard
* @brief if the clipboard should be enforced restricted. If true only allow client -> server, not vice versa.
*/
int restrict_outbound_clipboard;
}; };
/** /**

View File

@ -133,7 +133,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION *c, struct SCP_SES
in_uint16_be(c->in_s, cmd); in_uint16_be(c->in_s, cmd);
scp_session_set_height(session, cmd); scp_session_set_height(session, cmd);
in_uint16_be(c->in_s, cmd); in_uint16_be(c->in_s, cmd);
scp_session_set_height(session, cmd); scp_session_set_width(session, cmd);
in_uint8(c->in_s, sz); in_uint8(c->in_s, sz);
if (0 != scp_session_set_bpp(session, sz)) if (0 != scp_session_set_bpp(session, sz))
{ {

View File

@ -19,6 +19,9 @@ TerminalServerAdmins=tsadmins
; When AlwaysGroupCheck=false access will be permitted ; When AlwaysGroupCheck=false access will be permitted
; if the group TerminalServerUsers is not defined. ; if the group TerminalServerUsers is not defined.
AlwaysGroupCheck=false AlwaysGroupCheck=false
; When RestrictOutboundClipboard=true clipboard from the
; server is not pushed to the client.
RestrictOutboundClipboard=false
[Sessions] [Sessions]
;; X11DisplayOffset - x11 display number offset ;; X11DisplayOffset - x11 display number offset

View File

@ -374,6 +374,11 @@ session_start_chansrv(char *username, int display)
g_cfg->env_names, g_cfg->env_names,
g_cfg->env_values); g_cfg->env_values);
if (g_cfg->sec.restrict_outbound_clipboard == 1)
{
g_setenv("CHANSRV_RESTRICT_OUTBOUND_CLIPBOARD", "1", 1);
}
/* executing chansrv */ /* executing chansrv */
g_execvp(exe_path, (char **) (chansrv_params->items)); g_execvp(exe_path, (char **) (chansrv_params->items));
/* should not get here */ /* should not get here */

View File

@ -59,6 +59,7 @@ layouts_map=default_layouts_map
[default_rdp_layouts] [default_rdp_layouts]
rdp_layout_us=0x00000409 rdp_layout_us=0x00000409
rdp_layout_us_dvorak=0x00010409 rdp_layout_us_dvorak=0x00010409
rdp_layout_dk=0x00000406
rdp_layout_de=0x00000407 rdp_layout_de=0x00000407
rdp_layout_es=0x0000040A rdp_layout_es=0x0000040A
rdp_layout_fi=0x0000040B rdp_layout_fi=0x0000040B
@ -84,6 +85,7 @@ rdp_layout_pt=0x00000816
[default_layouts_map] [default_layouts_map]
rdp_layout_us=us rdp_layout_us=us
rdp_layout_us_dvorak=dvorak rdp_layout_us_dvorak=dvorak
rdp_layout_dk=dk
rdp_layout_de=de rdp_layout_de=de
rdp_layout_es=es rdp_layout_es=es
rdp_layout_fi=fi rdp_layout_fi=fi
@ -120,6 +122,7 @@ layouts_map=default_layouts_map
[rdp_layouts_map_mac] [rdp_layouts_map_mac]
rdp_layout_us=us rdp_layout_us=us
rdp_layout_us_dvorak=dvorak rdp_layout_us_dvorak=dvorak
rdp_layout_dk=dk
rdp_layout_de=de rdp_layout_de=de
rdp_layout_es=es rdp_layout_es=es
rdp_layout_fi=fi rdp_layout_fi=fi

View File

@ -1440,7 +1440,10 @@ xrdp_mm_connect_chansrv(struct xrdp_mm *self, const char *ip, const char *port)
self->chan_trans_up = 1; self->chan_trans_up = 1;
break; break;
} }
if (g_is_term())
{
break;
}
g_sleep(1000); g_sleep(1000);
log_message(LOG_LEVEL_ERROR,"xrdp_mm_connect_chansrv: connect failed " log_message(LOG_LEVEL_ERROR,"xrdp_mm_connect_chansrv: connect failed "
"trying again..."); "trying again...");
@ -2275,7 +2278,10 @@ xrdp_mm_connect(struct xrdp_mm *self)
ok = 1; ok = 1;
break; break;
} }
if (g_is_term())
{
break;
}
g_sleep(1000); g_sleep(1000);
g_writeln("xrdp_mm_connect: connect failed " g_writeln("xrdp_mm_connect: connect failed "
"trying again..."); "trying again...");

View File

@ -351,7 +351,7 @@ main(int argc, char **argv)
g_writeln("%s", ""); g_writeln("%s", "");
g_writeln("xrdp: A Remote Desktop Protocol server."); g_writeln("xrdp: A Remote Desktop Protocol server.");
g_writeln("Copyright (C) Jay Sorg 2004-2011"); g_writeln("Copyright (C) Jay Sorg 2004-2011");
g_writeln("See http://xrdp.sourceforge.net for more information."); g_writeln("See http://www.xrdp.org for more information.");
g_writeln("%s", ""); g_writeln("%s", "");
g_writeln("Usage: xrdp [options]"); g_writeln("Usage: xrdp [options]");
g_writeln(" -h: show help"); g_writeln(" -h: show help");
@ -506,7 +506,7 @@ main(int argc, char **argv)
g_writeln("%s", ""); g_writeln("%s", "");
g_writeln("xrdp: A Remote Desktop Protocol server."); g_writeln("xrdp: A Remote Desktop Protocol server.");
g_writeln("Copyright (C) Jay Sorg 2004-2011"); g_writeln("Copyright (C) Jay Sorg 2004-2011");
g_writeln("See http://xrdp.sourceforge.net for more information."); g_writeln("See http://www.xrdp.org for more information.");
g_writeln("%s", ""); g_writeln("%s", "");
g_writeln("Usage: xrdp [options]"); g_writeln("Usage: xrdp [options]");
g_writeln(" -h: show help"); g_writeln(" -h: show help");
@ -521,7 +521,7 @@ main(int argc, char **argv)
g_writeln("%s", ""); g_writeln("%s", "");
g_writeln("xrdp: A Remote Desktop Protocol server."); g_writeln("xrdp: A Remote Desktop Protocol server.");
g_writeln("Copyright (C) Jay Sorg 2004-2011"); g_writeln("Copyright (C) Jay Sorg 2004-2011");
g_writeln("See http://xrdp.sourceforge.net for more information."); g_writeln("See http://www.xrdp.org for more information.");
g_writeln("Version %s", PACKAGE_VERSION); g_writeln("Version %s", PACKAGE_VERSION);
g_writeln("%s", ""); g_writeln("%s", "");
g_exit(0); g_exit(0);