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
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
* 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 build with FDK AAC v2 #1257
* 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
* Dynamic channel improvements #1222 #1224
* Remove some deprecated sesman session types #1232
* Refactoring and cleanups
# Known issues
## 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

View File

@ -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.9
*Current Version:* 0.9.10
# 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();
if (now - start_time < timeout)
{
g_sleep(timeout / 5);
g_sleep(100);
}
else
{
self->status = TRANS_STATUS_DOWN;
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();
if (now - start_time < timeout)
{
g_sleep(timeout / 5);
g_sleep(100);
}
else
{
self->status = TRANS_STATUS_DOWN;
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
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)
AM_INIT_AUTOMAKE([1.7.2 foreign])
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
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
\fBAlwaysGroupCheck\fR=\fI[true|false]\fR
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.
.SH "FILES"
@bindir@/sesman
@bindir@/xrdp\-sesman
.br
@bindir@/sesrun
@bindir@/xrdp\-sesrun
.br
@sysconfdir@/xrdp/sesman.ini
.br
@localstatedir@/log/sesman.log
@localstatedir@/log/xrdp\-sesman.log
.br
@localstatedir@/run/sesman.pid
@localstatedir@/run/xrdp\-sesman.pid
.SH "AUTHORS"
Jay Sorg <jsorg71@users.sourceforge.net>

View File

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

View File

@ -30,6 +30,7 @@ SUFFIXES = .in
startscriptdir=$(sysconfdir)/xrdp
dist_startscript_DATA = \
km-00000406.ini \
km-00000407.ini \
km-00000409.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_rdpdr_chan_id = -1; /* rdpdr */
int g_rail_chan_id = -1; /* rail */
int g_restrict_outbound_clipboard = 0;
char *g_exec_name;
tbus g_exec_event;
@ -1780,7 +1781,7 @@ main(int argc, char **argv)
enum logReturns error;
struct log_config logconfig;
enum logLevels log_level;
char *restrict_outbound_clipboard_env;
g_init("xrdp-chansrv"); /* os_calls */
log_path[255] = 0;
@ -1791,6 +1792,15 @@ main(int argc, char **argv)
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();
pid = g_getpid();
display_text = g_getenv("DISPLAY");

View File

@ -24,7 +24,6 @@
* this is in func xfuse_check_wait_objs()
* o if fuse mount point is already mounted, I get segfault
* o in open, check for modes such as O_TRUNC, O_APPEND
* o copying over an existing file does not work
* o after a dir is created, the device cannot be unmounted on the client side
* so something is holding it up
* o in thunar, when I move a file by dragging to another folder, the file
@ -33,12 +32,9 @@
* o fuse ops to support
* o touch does not work
* o chmod must work
* o cat >> file is not working
*
*/
//#define USE_SYNC_FLAG
/* FUSE mount point */
char g_fuse_root_path[256] = "";
char g_fuse_clipboard_path[256] = ""; /* for clipboard use */
@ -74,10 +70,17 @@ int xfuse_file_contents_size(int stream_id, int file_size) { r
int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex) { return 0; }
int xfuse_create_share(tui32 device_id, const char *dirname) { return 0; }
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId) {}
void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length) {}
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) {}
int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) { return 0; }
struct xrdp_inode *xfuse_devredir_add_file_or_dir(
void *vp,
const struct file_attr *fattr)
{ return NULL;}
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_rmdir_or_file(void *vp, tui32 IoStatus) {}
void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus) {}
void xfuse_devredir_cb_file_close(void *vp) {}
@ -130,6 +133,9 @@ void xfuse_devredir_cb_file_close(void *vp) {}
#define LOG_DEBUG 2
#define LOG_LEVEL LOG_ERROR
/* Uncomment for detail of added entries */
/* #define XFUSE_DUMP_ADDED_ENTRIES */
#define log_error(_params...) \
{ \
g_write("[%10.10u]: FUSE %s: %d : ERROR: ", \
@ -166,6 +172,30 @@ void xfuse_devredir_cb_file_close(void *vp) {}
#define OP_RENAME_FILE 0x01
/* a file or dir entry in the xrdp file system */
struct xrdp_inode
{
tui32 parent_inode; /* Parent serial number. */
tui32 inode; /* File serial number. */
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. */
time_t atime; /* Time of last access. */
time_t mtime; /* Time of last modification. */
time_t ctime; /* Time of last status change. */
char name[1024]; /* Dir or filename */
tui32 device_id; /* for file system redirection */
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
/* the xrdp file system in memory */
struct xrdp_fs
{
@ -198,16 +228,13 @@ struct xfuse_info
fuse_req_t req;
fuse_ino_t inode;
fuse_ino_t new_inode;
int invoke_fuse;
char name[1024];
char new_name[1024];
tui32 device_id;
int reply_type;
int reply_type; /* RT_FUSE_REPLY_xxx */
int mode;
int type;
size_t size;
off_t off;
struct dirbuf1 dirbuf1;
};
typedef struct xfuse_info XFUSE_INFO;
@ -272,7 +299,7 @@ static void xfuse_create_file(fuse_req_t req, fuse_ino_t parent,
static void xfuse_dump_fs(void);
static tui32 xfuse_get_device_id_for_inode(fuse_ino_t ino, char *full_path);
static void fuse_reverse_pathname(char *full_path, char *reverse_path);
static void fuse_reverse_pathname(char *full_path, const char *reverse_path);
static struct xrdp_inode * xfuse_get_inode_from_pinode_name(fuse_ino_t pinode,
const char *name);
@ -287,11 +314,6 @@ static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode);
static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode);
static void xfuse_update_xrdpfs_size(void);
#ifdef USE_SYNC_FLAG
static void xfuse_enum_dir(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi);
#endif
/* forward declarations for FUSE callbacks */
static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent,
const char *name);
@ -363,6 +385,7 @@ static void xfuse_cb_releasedir(fuse_req_t req, fuse_ino_t ino,
/* misc calls */
static void xfuse_mark_as_stale(fuse_ino_t pinode);
static void xfuse_delete_stale_entries(fuse_ino_t pinode);
static void make_fuse_entry_reply(fuse_req_t req, const XRDP_INODE *xinode);
/*****************************************************************************/
int
@ -492,7 +515,14 @@ xfuse_init(void)
int
xfuse_deinit(void)
{
xfuse_deinit_xrdp_fs();
struct opendir_req *odreq;
/* Fail any waiting FUSE requests in the FIFO */
while (!fifo_is_empty(&g_fifo_opendir))
{
odreq = (struct opendir_req *)fifo_remove(&g_fifo_opendir);
fuse_reply_err(odreq->req, EBADF);
g_free(odreq);
}
fifo_deinit(&g_fifo_opendir);
if (g_ch != 0)
@ -520,6 +550,8 @@ xfuse_deinit(void)
g_req_list = 0;
}
xfuse_deinit_xrdp_fs();
g_xfuse_inited = 0;
return 0;
}
@ -969,6 +1001,28 @@ static int xfuse_init_xrdp_fs(void)
static int xfuse_deinit_xrdp_fs(void)
{
fuse_ino_t i;
struct xrdp_inode *xinode;
if (g_xrdp_fs.inode_table != NULL)
{
for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; ++i)
{
if ((xinode = g_xrdp_fs.inode_table[i]) != NULL)
{
g_xrdp_fs.inode_table[i] = NULL;
log_debug("Freeing %s",xinode->name);
free(xinode);
}
}
free(g_xrdp_fs.inode_table);
g_xrdp_fs.inode_table = NULL;
}
g_xrdp_fs.max_entries = 0;
g_xrdp_fs.num_entries = 0;
g_xrdp_fs.next_node = 1;
return 0;
}
@ -1078,9 +1132,9 @@ static void xfuse_dump_fs(void)
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
continue;
log_debug("pinode=%d inode=%d nentries=%d nopen=%d is_synced=%d name=%s",
log_debug("pinode=%d inode=%d nentries=%d nopen=%d name=%s",
xinode->parent_inode, xinode->inode,
xinode->nentries, xinode->nopen, xinode->is_synced,
xinode->nentries, xinode->nopen,
xinode->name);
}
log_debug("%s", "");
@ -1092,10 +1146,10 @@ static void xfuse_dump_fs(void)
* @param xino xinode structure to dump
*****************************************************************************/
#if 0
#ifdef XFUSE_DUMP_ADDED_ENTRIES
static void xfuse_dump_xrdp_inode(struct xrdp_inode *xino)
{
log_debug("--- dumping struct xinode ---");
log_debug("--- dumping struct xinode %p ---",xino);
log_debug("name: %s", xino->name);
log_debug("parent_inode: %d", xino->parent_inode);
log_debug("inode: %d", xino->inode);
@ -1170,19 +1224,35 @@ static tui32 xfuse_get_device_id_for_inode(fuse_ino_t ino, char *full_path)
* @param reverse_path path name in the reverse order
*****************************************************************************/
static void fuse_reverse_pathname(char *full_path, char *reverse_path)
static void fuse_reverse_pathname(char *full_path, const char *reverse_path)
{
char *cptr;
char *optr; /* Output pointer */
const char *start;/* Pointer to start of current element in input */
const char *end; /* Ditto for the end */
full_path[0] = 0;
/* Start writing the result from the end */
optr = full_path + strlen(reverse_path);
*optr = '\0';
while ((cptr = strrchr(reverse_path, '/')) != NULL)
start = reverse_path;
while ((end = strchr(start, '/')) != NULL)
{
strcat(full_path, cptr + 1);
strcat(full_path, "/");
cptr[0] = 0;
/* Copy current element to the end of the result... */
optr -= (end - start);
memcpy(optr, start, (end - start));
/* And precede with a '/' */
*--optr = '/';
/* Next element starts after the '/' */
start = end + 1;
}
strcat(full_path, reverse_path);
/* Last bit (if reverse_path doesn't end with a '/') */
if (optr != full_path)
{
memcpy(full_path, start, optr - full_path);
}
}
/**
@ -1257,7 +1327,6 @@ xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name,
xinode->mtime = cur_time;
xinode->ctime = cur_time;
xinode->device_id = device_id;
xinode->is_synced = 1;
strcpy(xinode->name, name);
if (type == S_IFDIR)
@ -1273,6 +1342,9 @@ xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name,
g_xrdp_fs.inode_table[xinode->inode] = xinode;
g_xrdp_fs.num_entries++;
#ifdef XFUSE_DUMP_ADDED_ENTRIES
xfuse_dump_xrdp_inode(xinode);
#endif
/* bump up lookup count in parent dir */
xinodep = g_xrdp_fs.inode_table[pinode];
@ -1450,45 +1522,89 @@ static void xfuse_update_xrdpfs_size(void)
/**
* Add a file or directory to xrdp file system
*
* If the file or directory already exists, its attributes are updated.
*
* Returns a pointer to the xinode if the object was added or updated
*****************************************************************************/
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 *fattr)
{
XFUSE_INFO *fip = (XFUSE_INFO *) vp;
XRDP_INODE *xip = NULL;
XRDP_INODE *xinode = NULL;
if ((fip == NULL) || (xinode == NULL))
if (fip == NULL)
{
log_error("fip or xinode are NULL");
return -1;
log_error("fip is NULL");
}
if (!xfuse_is_inode_valid(fip->inode))
else if (!xfuse_is_inode_valid(fip->inode))
{
log_error("inode %ld is not valid", fip->inode);
g_free(xinode);
return -1;
}
log_debug("parent_inode=%ld name=%s", fip->inode, xinode->name);
/* if filename is . or .. don't add it */
if ((strcmp(xinode->name, ".") == 0) || (strcmp(xinode->name, "..") == 0))
else if ((strcmp(fattr->name, ".") == 0) ||
(strcmp(fattr->name, "..") == 0))
{
g_free(xinode);
return -1;
; /* filename is . or .. - don't add it */
}
else
{
log_debug("parent_inode=%ld name=%s", fip->inode, fattr->name);
xfuse_dump_fs();
if ((xip = xfuse_get_inode_from_pinode_name(fip->inode, xinode->name)) != NULL)
/* Does the file already exist ? */
xinode = xfuse_get_inode_from_pinode_name(fip->inode, fattr->name);
if (xinode != NULL)
{
log_debug("inode=%ld name=%s already exists in xrdp_fs; not adding it",
/* Is the existing file the same type ? */
if ((xinode->mode & (S_IFREG | S_IFDIR)) ==
(fattr->mode & (S_IFREG | S_IFDIR)))
{
log_debug("inode=%ld name=%s already exists in xrdp_fs"
" - updating attributes",
fip->inode, xinode->name);
g_free(xinode);
xip->stale = 0;
return -1;
xinode->mode = fattr->mode;
xinode->size = fattr->size;
xinode->atime = fattr->atime;
xinode->mtime = fattr->mtime;
xinode->ctime = fattr->ctime;
xinode->stale = 0;
}
else
{
/* File type has changed */
log_debug("inode=%ld name=%s of different type in xrdp_fs"
" - removing",
fip->inode, xinode->name);
if (xinode->mode & S_IFREG)
{
xfuse_delete_file_with_xinode(xinode);
}
else
{
xfuse_delete_dir_with_xinode(xinode);
}
xinode = NULL;
}
}
if (xinode == NULL)
{
/* Add a new node to the file system */
xinode = g_new0(struct xrdp_inode, 1);
if (xinode == NULL)
{
log_debug("g_new0() failed");
}
else
{
strcpy(xinode->name, fattr->name);
xinode->mode = fattr->mode;
xinode->size = fattr->size;
xinode->atime = fattr->atime;
xinode->mtime = fattr->mtime;
xinode->ctime = fattr->ctime;
xinode->parent_inode = fip->inode;
xinode->inode = g_xrdp_fs.next_node++;
@ -1504,10 +1620,18 @@ int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
xfuse_update_xrdpfs_size();
xfuse_dump_fs();
return 0;
#ifdef XFUSE_DUMP_ADDED_ENTRIES
xfuse_dump_xrdp_inode(xinode);
#endif
}
}
}
return xinode;
}
/**
* This routine is called by devredir when the opendir_req entry at the
* front of the opendir FIFO has completed processing.
*****************************************************************************/
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
@ -1528,7 +1652,6 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
if (IoStatus != 0)
{
/* command failed */
if (fip->invoke_fuse)
fuse_reply_err(fip->req, ENOENT);
goto done;
}
@ -1537,14 +1660,15 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
if (!xfuse_is_inode_valid(fip->inode))
{
log_error("inode %ld is not valid", fip->inode);
if (fip->invoke_fuse)
fuse_reply_err(fip->req, EBADF);
goto done;
}
xfuse_delete_stale_entries(fip->inode);
/* this will be used by xfuse_cb_readdir() */
/* Generate a FUSE reply.
* The dir_info struct will be used by xfuse_cb_readdir()
*/
di = g_new0(struct dir_info, 1);
di->index = FIRST_INODE;
fip->fi->fh = (tintptr) di;
@ -1553,10 +1677,9 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
done:
if (fip)
free(fip);
/* remove current request */
/* remove completed request */
g_free(fifo_remove(&g_fifo_opendir));
while (1)
@ -1573,6 +1696,44 @@ done:
}
}
/**
* This routine is caused as a result of a devredir remote lookup
* instigated by xfuse_cb_lookup()
*
* If the IoStatus is good but there's no xinode, something has gone wrong
* in the devredir layer (no memory, unrecognised reply)
*****************************************************************************/
void xfuse_devredir_cb_lookup_entry(void *vp, tui32 IoStatus, struct xrdp_inode *xinode)
{
XFUSE_INFO *fip = (XFUSE_INFO *) vp;
if (IoStatus == NT_STATUS_SUCCESS)
{
if (xinode != NULL)
{
make_fuse_entry_reply(fip->req, xinode);
}
else
{
fuse_reply_err(fip->req, EIO);
}
}
else
{
switch (IoStatus)
{
case NT_STATUS_NO_SUCH_FILE:
fuse_reply_err(fip->req, ENOENT);
break;
default:
log_info("Error code %08x - fallthrough", (int) IoStatus);
fuse_reply_err(fip->req, EIO);
break;
}
}
}
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
tui32 FileId)
{
@ -1591,17 +1752,14 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
if (IoStatus != 0)
{
if (!fip->invoke_fuse)
goto done;
switch (IoStatus)
{
case 0xC0000022:
case NT_STATUS_ACCESS_DENIED:
fuse_reply_err(fip->req, EACCES);
break;
case 0xC0000033:
case 0xC0000034:
case NT_STATUS_OBJECT_NAME_INVALID:
case NT_STATUS_OBJECT_NAME_NOT_FOUND:
fuse_reply_err(fip->req, ENOENT);
break;
@ -1619,7 +1777,6 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
if (fh == NULL)
{
log_error("system out of memory");
if (fip->invoke_fuse)
fuse_reply_err(fip->req, ENOMEM);
free(fip);
@ -1635,8 +1792,6 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
fip, fip->fi, (long long) fip->fi->fh);
}
if (fip->invoke_fuse)
{
if (fip->reply_type == RT_FUSE_REPLY_OPEN)
{
log_debug("sending fuse_reply_open(); "
@ -1701,7 +1856,6 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
{
log_error("invalid reply type: %d", fip->reply_type);
}
}
done:
@ -1723,7 +1877,10 @@ void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length)
free(fip);
}
void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length)
void xfuse_devredir_cb_write_file(void *vp,
tui32 IoStatus,
const char *buf,
size_t length)
{
XRDP_INODE *xinode;
XFUSE_INFO *fip;
@ -1732,20 +1889,36 @@ void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length)
if ((fip == NULL) || (fip->req == NULL) || (fip->fi == NULL))
{
log_error("fip, fip->req or fip->fi is NULL");
return;
}
log_debug("+++ XFUSE_INFO=%p, XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
else
{
log_debug(
"+++ XFUSE_INFO=%p, XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
fip, fip->fi, (long long) fip->fi->fh);
if (IoStatus != NT_STATUS_SUCCESS)
{
log_error("Write NTSTATUS is %d", (int) IoStatus);
fuse_reply_err(fip->req, EIO);
}
else
{
fuse_reply_write(fip->req, length);
/* update file size */
/* ??? This needs to take into account the offset sent with
* the original request */
if ((xinode = g_xrdp_fs.inode_table[fip->inode]) != NULL)
{
xinode->size += length;
}
else
{
log_error("inode at inode_table[%ld] is NULL", fip->inode);
}
}
}
free(fip);
}
@ -1838,7 +2011,6 @@ void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus)
if (fip->inode != fip->new_inode)
{
/* file has been moved to a different dir */
old_xinode->is_synced = 1;
g_xrdp_fs.inode_table[fip->inode]->nentries--;
g_xrdp_fs.inode_table[fip->new_inode]->nentries++;
}
@ -1904,12 +2076,20 @@ void xfuse_devredir_cb_file_close(void *vp)
/**
* Look up a directory entry by name and get its attributes
*
* If the file can't be found, and it resides on a remote share, devredir
* is asked to look it up. This will result in the following
* callbacks:-
* - xfuse_devredir_add_file_or_dir() (only if the file is found)
* - xfuse_devredir_cb_lookup_entry() to return status to the caller
*****************************************************************************/
static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
XFUSE_INFO *fip;
XRDP_INODE *xinode;
struct fuse_entry_param e;
char full_path[4096];
tui32 device_id;
const char *cptr;
log_debug("looking for parent=%ld name=%s", parent, name);
xfuse_dump_fs();
@ -1921,33 +2101,60 @@ static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
return;
}
xinode = xfuse_get_inode_from_pinode_name(parent, name);
if (xinode == NULL)
if (parent == 1 ||
g_xrdp_fs.inode_table[parent]->is_loc_resource)
{
/* File cannot be remote - we either know about it or we don't */
xinode = xfuse_get_inode_from_pinode_name(parent, name);
if (xinode != NULL)
{
log_debug("did not find entry for parent=%ld name=%s", parent, name);
fuse_reply_err(req, ENOENT);
return;
}
memset(&e, 0, sizeof(e));
e.ino = xinode->inode;
e.attr_timeout = XFUSE_ATTR_TIMEOUT;
e.entry_timeout = XFUSE_ENTRY_TIMEOUT;
e.attr.st_ino = xinode->inode;
e.attr.st_mode = xinode->mode;
e.attr.st_nlink = xinode->nlink;
e.attr.st_uid = xinode->uid;
e.attr.st_gid = xinode->gid;
e.attr.st_size = xinode->size;
e.attr.st_atime = xinode->atime;
e.attr.st_mtime = xinode->mtime;
e.attr.st_ctime = xinode->ctime;
e.generation = 1;
fuse_reply_entry(req, &e);
log_debug("found entry for parent=%ld name=%s uid=%d gid=%d",
parent, name, xinode->uid, xinode->gid);
return;
make_fuse_entry_reply(req, xinode);
}
else
{
fuse_reply_err(req, ENOENT);
}
}
else
{
/*
* specified file resides on redirected share.
*
* We always look these up, as fuse caches stuff for us anyway, and
* it's pointless caching it twice
*/
fip = g_new0(XFUSE_INFO, 1);
if (fip == NULL)
{
log_error("system out of memory");
fuse_reply_err(req, ENOMEM);
}
else
{
device_id = xfuse_get_device_id_for_inode(parent, full_path);
/* we want path minus 'root node of the share' */
if ((cptr = strchr(full_path, '/')) == NULL)
{
cptr = "\\";
}
fip->req = req;
fip->inode = parent;
fip->device_id = device_id;
log_debug("Looking up %s in %s on %d", name, cptr, device_id);
if (dev_redir_lookup_entry((void *) fip, device_id,
cptr, name))
{
log_error("failed to send dev_redir_lookup_entry() cmd");
fuse_reply_err(req, EREMOTEIO);
free(fip);
}
}
}
}
/**
@ -2083,8 +2290,6 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
if (xinode->parent_inode != ino)
continue;
xinode->is_synced = 1;
if (first_time)
{
first_time = 0;
@ -2175,7 +2380,7 @@ static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
{
XFUSE_INFO *fip;
XRDP_INODE *xinode;
char *cptr;
const char *cptr;
char full_path[4096];
tui32 device_id;
@ -2242,7 +2447,6 @@ static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
fip->req = req;
fip->inode = parent;
fip->invoke_fuse = 1;
fip->device_id = device_id;
strncpy(fip->name, name, 1024);
fip->name[1023] = 0;
@ -2251,24 +2455,15 @@ static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
/* we want path minus 'root node of the share' */
if ((cptr = strchr(full_path, '/')) == NULL)
{
cptr = "\\";
}
/* get dev_redir to open the remote file */
if (devredir_rmdir_or_file((void *) fip, device_id, "\\", O_RDWR))
{
log_error("failed to send dev_redir_open_file() cmd");
fuse_reply_err(req, EREMOTEIO);
free(fip);
return;
}
}
else
{
if (devredir_rmdir_or_file((void *) fip, device_id, cptr, O_RDWR))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
log_error("failed to send devredir_rmdir_or_file() cmd");
fuse_reply_err(req, EREMOTEIO);
free(fip);
return;
}
}
}
@ -2279,7 +2474,7 @@ static void xfuse_cb_rename(fuse_req_t req,
XRDP_INODE *old_xinode;
XFUSE_INFO *fip;
tui32 new_device_id;
char *cptr;
const char *cptr;
char old_full_path[1024];
char new_full_path[1024];
const char *cp;
@ -2377,35 +2572,26 @@ static void xfuse_cb_rename(fuse_req_t req,
strncpy(fip->new_name, new_name, 1024);
fip->name[1023] = 0;
fip->new_name[1023] = 0;
fip->invoke_fuse = 1;
fip->device_id = device_id;
if ((cp = strchr(new_full_path, '/')) == NULL)
cp = "\\";
/* we want path minus 'root node of the share' */
if ((cptr = strchr(old_full_path, '/')) == NULL)
{
cptr = "\\";
}
if ((cp = strchr(new_full_path, '/')) == NULL)
{
cp = "\\";
}
/* get dev_redir to open the remote file */
if (dev_redir_file_open((void *) fip, device_id, "\\",
O_RDWR, S_IFREG | OP_RENAME_FILE, cp))
{
log_error("failed to send dev_redir_file_open() cmd");
fuse_reply_err(req, EREMOTEIO);
free(fip);
return;
}
}
else
{
if (dev_redir_file_open((void *) fip, device_id, cptr,
O_RDWR, S_IFREG | OP_RENAME_FILE, cp))
{
log_error("failed to send dev_redir_file_open() cmd");
fuse_reply_err(req, EREMOTEIO);
free(fip);
return;
}
}
}
@ -2425,7 +2611,7 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
struct fuse_file_info *fi, int type)
{
XFUSE_INFO *fip;
char *cptr;
const char *cptr;
char full_path[1024];
tui32 device_id;
@ -2478,7 +2664,6 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
fip->req = req;
fip->fi = fi;
fip->inode = parent;
fip->invoke_fuse = 1;
fip->device_id = device_id;
fip->mode = type;
fip->reply_type = RT_FUSE_REPLY_CREATE;
@ -2492,23 +2677,16 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
/* we want path minus 'root node of the share' */
if ((cptr = strchr(full_path, '/')) == NULL)
{
cptr = "\\";
}
/* get dev_redir to open the remote file */
if (dev_redir_file_open((void *) fip, device_id, "\\",
O_CREAT, type, NULL))
{
log_error("failed to send dev_redir_open_file() cmd");
fuse_reply_err(req, EREMOTEIO);
}
}
else
{
if (dev_redir_file_open((void *) fip, device_id, cptr,
O_CREAT, type, NULL))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
log_error("failed to send dev_redir_file_open() cmd");
fuse_reply_err(req, EREMOTEIO);
}
}
}
/**
@ -2520,7 +2698,7 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
{
XRDP_INODE *xinode;
XFUSE_INFO *fip;
char *cptr;
const char *cptr;
char full_path[4096];
tui32 device_id;
@ -2543,11 +2721,24 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
}
if (xinode->mode & S_IFDIR)
{
log_debug("reading a dir not allowed!");
log_debug("reading/writing a dir not allowed!");
fuse_reply_err(req, EISDIR);
return;
}
switch (fi->flags & O_ACCMODE)
{
case O_RDONLY:
case O_WRONLY:
case O_RDWR:
break;
default:
log_debug("Invalid access mode specified");
fuse_reply_err(req, EINVAL);
return;
}
device_id = xfuse_get_device_id_for_inode(ino, full_path);
if (xinode->is_loc_resource)
@ -2572,7 +2763,6 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
fip->req = req;
fip->inode = ino;
fip->invoke_fuse = 1;
fip->device_id = device_id;
fip->fi = fi;
@ -2585,23 +2775,20 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
/* we want path minus 'root node of the share' */
if ((cptr = strchr(full_path, '/')) == NULL)
{
/* get dev_redir to open the remote file */
if (dev_redir_file_open((void *) fip, device_id, "\\",
fi->flags, S_IFREG, NULL))
{
log_error("failed to send dev_redir_open_file() cmd");
fuse_reply_err(req, EREMOTEIO);
cptr = "\\";
}
}
else
{
/* get dev_redir to open the remote file
*
* For a successful call, if the caller has set O_TRUNC when writing
* the file, fuse should call us back via fuse_cb_setattr() to set
* the size to zero - we don't need to do this ourselves.
*/
if (dev_redir_file_open((void *) fip, device_id, cptr,
fi->flags, S_IFREG, NULL))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
log_error("failed to send dev_redir_file_open() cmd");
fuse_reply_err(req, EREMOTEIO);
}
}
}
static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct
@ -2656,7 +2843,6 @@ static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct
fip->req = req;
fip->inode = ino;
fip->invoke_fuse = 1;
fip->device_id = handle->DeviceId;
fip->fi = fi;
@ -2743,7 +2929,6 @@ static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size,
}
fusep->req = req;
fusep->inode = ino;
fusep->invoke_fuse = 1;
fusep->device_id = fh->DeviceId;
fusep->fi = fi;
@ -2792,7 +2977,6 @@ static void xfuse_cb_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
fusep->req = req;
fusep->inode = ino;
fusep->invoke_fuse = 1;
fusep->device_id = fh->DeviceId;
fusep->fi = fi;
@ -2956,7 +3140,7 @@ static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
XFUSE_INFO *fip;
tui32 device_id;
char full_path[4096];
char *cptr;
const char *cptr;
log_debug("inode=%ld", ino);
@ -2983,22 +3167,6 @@ static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
goto done;
/* enumerate resources on a remote device */
#ifdef USE_SYNC_FLAG
if (xinode->is_synced)
{
xfuse_enum_dir(req, ino, size, off, fi);
g_free(fifo_remove(&g_fifo_opendir));
return -1;
}
else
{
goto do_remote_lookup;
}
do_remote_lookup:
#endif
xfuse_mark_as_stale(ino);
log_debug("did not find entry; redirecting call to dev_redir");
@ -3018,32 +3186,21 @@ do_remote_lookup:
fip->req = req;
fip->inode = ino;
fip->size = 0;
fip->off = 0;
fip->fi = fi;
fip->dirbuf1.first_time = 1;
fip->dirbuf1.bytes_in_buf = 0;
fip->invoke_fuse = 1;
fip->device_id = device_id;
/* we want path minus 'root node of the share' */
if ((cptr = strchr(full_path, '/')) == NULL)
{
/* enumerate root dir */
if (dev_redir_get_dir_listing((void *) fip, device_id, "\\"))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
fuse_reply_buf(req, NULL, 0);
cptr = "\\";
}
}
else
{
if (dev_redir_get_dir_listing((void *) fip, device_id, cptr))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
fuse_reply_buf(req, NULL, 0);
}
}
return 0;
@ -3141,4 +3298,26 @@ xfuse_delete_stale_entries(fuse_ino_t pinode)
}
}
static void make_fuse_entry_reply(fuse_req_t req, const XRDP_INODE *xinode)
{
struct fuse_entry_param e;
memset(&e, 0, sizeof(e));
e.ino = xinode->inode;
e.attr_timeout = XFUSE_ATTR_TIMEOUT;
e.entry_timeout = XFUSE_ENTRY_TIMEOUT;
e.attr.st_ino = xinode->inode;
e.attr.st_mode = xinode->mode;
e.attr.st_nlink = xinode->nlink;
e.attr.st_uid = xinode->uid;
e.attr.st_gid = xinode->gid;
e.attr.st_size = xinode->size;
e.attr.st_atime = xinode->atime;
e.attr.st_mtime = xinode->mtime;
e.attr.st_ctime = xinode->ctime;
e.generation = 1;
fuse_reply_entry(req, &e);
}
#endif /* end else #ifndef XRDP_FUSE */

View File

@ -19,31 +19,27 @@
#ifndef _CHANSRV_FUSE_H
#define _CHANSRV_FUSE_H
/* a file or dir entry in the xrdp file system */
struct xrdp_inode
#include "arch.h"
/*
* 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. */
tui32 inode; /* File serial number. */
const char *name; /* Name of file or directory */
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. */
time_t atime; /* Time of last access. */
time_t mtime; /* Time of last modification. */
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_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);
/* 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_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_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_rmdir_or_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_error(_params...) \
{ \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ERROR: ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
}
}
#define log_always(_params...) \
{ \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ALWAYS: ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
}
}
#define log_info(_params...) \
{ \
{ \
if (LOG_INFO <= LOG_LEVEL) \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
} \
}
}
#define log_debug(_params...) \
{ \
{ \
if (LOG_DEBUG <= LOG_LEVEL) \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
} \
}
}
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 int g_screen_num; /* in xcommon.c */
extern int g_restrict_outbound_clipboard; /* in chansrv.c */
int g_clip_up = 0;
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*
static char *
get_atom_text(Atom atom)
{
char* name;
char *name;
int failed;
failed = 0;
@ -1717,7 +1719,8 @@ clipboard_event_selection_owner_notify(XEvent *xevent)
g_got_selection = 0;
if (lxevent->owner != 0) /* nil owner comes when selection */
{ /* window is closed */
{
/* window is closed */
XConvertSelection(g_display, g_clipboard_atom, g_targets_atom,
g_clip_property_atom, g_wnd, lxevent->timestamp);
}
@ -2484,6 +2487,8 @@ clipboard_xevent(void *xevent)
{
XEvent *lxevent;
log_debug("clipboard_xevent: event detected");
if (!g_clip_up)
{
return 1;
@ -2494,7 +2499,15 @@ clipboard_xevent(void *xevent)
switch (lxevent->type)
{
case SelectionNotify:
if (g_restrict_outbound_clipboard == 0)
{
clipboard_event_selection_notify(lxevent);
}
else
{
log_debug("outbound clipboard is restricted because of config");
return 1;
}
break;
case SelectionRequest:
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 */
extern int g_rdpdr_chan_id; /* in chansrv.c */
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 */
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
@ -816,7 +842,8 @@ dev_redir_proc_device_iocompletion(struct stream *s)
}
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);
}
break;
@ -866,6 +893,27 @@ dev_redir_proc_device_iocompletion(struct stream *s)
devredir_proc_cid_rename_file_resp(irp, IoStatus);
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:
log_error("got unknown CompletionID: DeviceId=0x%x "
"CompletionId=0x%x IoStatus=0x%x",
@ -892,7 +940,6 @@ dev_redir_proc_query_dir_response(IRP *irp,
tui32 IoStatus)
{
FUSE_DATA *fuse_data = NULL;
XRDP_INODE *xinode;
tui32 Length;
tui64 CreationTime;
@ -902,6 +949,7 @@ dev_redir_proc_query_dir_response(IRP *irp,
tui32 FileAttributes;
tui32 FileNameLength;
tui32 status;
struct file_attr fattr;
char filename[256];
unsigned int i = 0;
@ -967,25 +1015,16 @@ dev_redir_proc_query_dir_response(IRP *irp,
//log_debug("FileNameLength: %d", FileNameLength);
log_debug("FileName: %s", filename);
xinode = g_new0(struct xrdp_inode, 1);
if (xinode == NULL)
{
log_error("system out of memory");
fuse_data = devredir_fuse_data_peek(irp);
xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, NULL);
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);
fattr.name = filename;
fattr.mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes);
fattr.size = (size_t) EndOfFile;
fattr.atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
fattr.mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
fattr.ctime = WINDOWS_TO_LINUX_TIME(CreationTime);
/* add this entry to xrdp file system */
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);
@ -1048,6 +1087,78 @@ dev_redir_get_dir_listing(void *fusep, tui32 device_id, const char *path)
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
dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
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)
{
irp->completion_type = CID_RENAME_FILE;
strncpy(irp->gen_buf, gen_buf, 1023);
strncpy(irp->gen.buf, gen_buf, 1023);
}
else
{
@ -1101,14 +1212,30 @@ dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
}
else
{
log_debug("open file in O_RDWR");
#if 1
switch(mode & O_ACCMODE)
{
case O_RDONLY:
log_debug("open file in O_RDONLY");
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 */
if (mode & O_RDWR)
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010;
else
DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA |
DA_SYNCHRONIZE | 0x00000010;
}
CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT;
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)
{
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);
return -1;
}
@ -1286,7 +1413,7 @@ dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
if ((new_irp = devredir_irp_clone(irp)) == NULL)
{
/* 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);
return -1;
}
@ -1514,12 +1641,12 @@ devredir_cvt_from_unicode_len(char *path, char *unicode, int len)
}
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);
return (string[len - 1] == c) ? 1 : 0;
return (len > 0 && string[len - 1] == c) ? 1 : 0;
}
void
@ -1530,7 +1657,7 @@ devredir_insert_RDPDR_header(struct stream *s, tui16 Component,
xstream_wr_u16_le(s, PacketId);
}
void
static void
devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
{
struct stream *s;
@ -1567,7 +1694,7 @@ devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
return;
}
void
static void
devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
{
FUSE_DATA *fuse_data;
@ -1594,7 +1721,7 @@ devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
IRP_MJ_CLOSE, 0, 32);
}
void
static void
devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
{
struct stream *s;
@ -1618,7 +1745,7 @@ devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
}
/* 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;
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 */
/* 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);
/* send to client */
@ -1647,7 +1774,7 @@ devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
return;
}
void
static void
devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
{
FUSE_DATA *fuse_data;
@ -1675,3 +1802,192 @@ devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
irp->CompletionId,
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_to_unicode(char *unicode, const char *path);
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,
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 */
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 mode, int type, const char *gen_buf);
@ -260,11 +258,15 @@ enum CREATE_OPTIONS
#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_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
@ -289,12 +291,16 @@ enum COMPLETION_ID
CID_RMDIR_OR_FILE,
CID_RMDIR_OR_FILE_RESP,
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
{
FileBasicInformation = 0x00000004, /* set atime, mtime, ctime etc */
FileStandardInformation = 0x00000005, /* Alloc size, EOF #links, etc */
FileEndOfFileInformation = 0x00000014, /* set EOF info */
FileDispositionInformation = 0x0000000D, /* mark a file for deletion */
FileRenameInformation = 0x0000000A, /* rename a file */

View File

@ -24,6 +24,8 @@
#ifndef __IRP_H
#define __IRP_H
#include "chansrv_fuse.h"
typedef struct fuse_data FUSE_DATA;
struct fuse_data
{
@ -42,7 +44,11 @@ struct irp
tui32 FileId; /* RDP client provided unique number */
char completion_type; /* describes I/O type */
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;
FUSE_DATA *fd_head; /* point to first FUSE opaque object */
FUSE_DATA *fd_tail; /* point to last FUSE opaque object */

View File

@ -34,8 +34,6 @@
#include "sesman.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] != '/')
{
/* 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);
g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, g_cfg->default_wm);
g_free(g_cfg->default_wm);
g_cfg->default_wm = g_strdup(buf);
g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, cf->default_wm);
g_free(cf->default_wm);
cf->default_wm = g_strdup(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] != '/')
{
/* 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);
g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, g_cfg->reconnect_sh);
g_free(g_cfg->reconnect_sh);
g_cfg->reconnect_sh = g_strdup(buf);
g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, cf->reconnect_sh);
g_free(cf->reconnect_sh);
cf->reconnect_sh = g_strdup(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;
}
@ -235,6 +242,7 @@ config_read_security(int file, struct config_security *sc,
sc->login_retry = 3;
sc->ts_users_enable = 0;
sc->ts_admins_enable = 0;
sc->restrict_outbound_clipboard = 0;
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));
}
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;
@ -497,6 +511,7 @@ config_dump(struct config_sesman *config)
g_writeln(" AllowRootLogin: %d", sc->allow_root);
g_writeln(" MaxLoginRetry: %d", sc->login_retry);
g_writeln(" AlwaysGroupCheck: %d", sc->ts_always_group_check);
g_writeln(" RestrictOutboundClipboard: %d", sc->restrict_outbound_clipboard);
g_printf( " TSUsersGroup: ");
if (sc->ts_users_enable)

View File

@ -60,6 +60,7 @@
#define SESMAN_CFG_SEC_USR_GROUP "TerminalServerUsers"
#define SESMAN_CFG_SEC_ADM_GROUP "TerminalServerAdmins"
#define SESMAN_CFG_SEC_ALWAYSGROUPCHECK "AlwaysGroupCheck"
#define SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD "RestrictOutboundClipboard"
#define SESMAN_CFG_SESSIONS "Sessions"
#define SESMAN_CFG_SESS_MAX "MaxSessions"
@ -126,6 +127,11 @@ struct config_security
* @brief if the Groups are not found deny access
*/
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);
scp_session_set_height(session, 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);
if (0 != scp_session_set_bpp(session, sz))
{

View File

@ -19,6 +19,9 @@ TerminalServerAdmins=tsadmins
; When AlwaysGroupCheck=false access will be permitted
; if the group TerminalServerUsers is not defined.
AlwaysGroupCheck=false
; When RestrictOutboundClipboard=true clipboard from the
; server is not pushed to the client.
RestrictOutboundClipboard=false
[Sessions]
;; 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_values);
if (g_cfg->sec.restrict_outbound_clipboard == 1)
{
g_setenv("CHANSRV_RESTRICT_OUTBOUND_CLIPBOARD", "1", 1);
}
/* executing chansrv */
g_execvp(exe_path, (char **) (chansrv_params->items));
/* should not get here */

View File

@ -59,6 +59,7 @@ layouts_map=default_layouts_map
[default_rdp_layouts]
rdp_layout_us=0x00000409
rdp_layout_us_dvorak=0x00010409
rdp_layout_dk=0x00000406
rdp_layout_de=0x00000407
rdp_layout_es=0x0000040A
rdp_layout_fi=0x0000040B
@ -84,6 +85,7 @@ rdp_layout_pt=0x00000816
[default_layouts_map]
rdp_layout_us=us
rdp_layout_us_dvorak=dvorak
rdp_layout_dk=dk
rdp_layout_de=de
rdp_layout_es=es
rdp_layout_fi=fi
@ -120,6 +122,7 @@ layouts_map=default_layouts_map
[rdp_layouts_map_mac]
rdp_layout_us=us
rdp_layout_us_dvorak=dvorak
rdp_layout_dk=dk
rdp_layout_de=de
rdp_layout_es=es
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;
break;
}
if (g_is_term())
{
break;
}
g_sleep(1000);
log_message(LOG_LEVEL_ERROR,"xrdp_mm_connect_chansrv: connect failed "
"trying again...");
@ -2275,7 +2278,10 @@ xrdp_mm_connect(struct xrdp_mm *self)
ok = 1;
break;
}
if (g_is_term())
{
break;
}
g_sleep(1000);
g_writeln("xrdp_mm_connect: connect failed "
"trying again...");

View File

@ -351,7 +351,7 @@ main(int argc, char **argv)
g_writeln("%s", "");
g_writeln("xrdp: A Remote Desktop Protocol server.");
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("Usage: xrdp [options]");
g_writeln(" -h: show help");
@ -506,7 +506,7 @@ main(int argc, char **argv)
g_writeln("%s", "");
g_writeln("xrdp: A Remote Desktop Protocol server.");
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("Usage: xrdp [options]");
g_writeln(" -h: show help");
@ -521,7 +521,7 @@ main(int argc, char **argv)
g_writeln("%s", "");
g_writeln("xrdp: A Remote Desktop Protocol server.");
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("%s", "");
g_exit(0);