Allow FuseMountName for chansrv to be absolute path

This commit is contained in:
matt335672 2020-08-22 18:05:24 +01:00
parent 785db575ca
commit 5523847540
18 changed files with 386 additions and 39 deletions

View File

@ -54,11 +54,12 @@ libcommon_la_SOURCES = \
log.h \
os_calls.c \
os_calls.h \
os_calls.h \
parse.h \
rail.h \
ssl_calls.c \
ssl_calls.h \
string_calls.c \
string_calls.h \
thread_calls.c \
thread_calls.h \
trans.c \

View File

@ -31,6 +31,7 @@
#include "file.h"
#include "os_calls.h"
#include "thread_calls.h"
#include "string_calls.h"
/* Add a define here so that the log.h will hold more information
* when compiled from this C file.

View File

@ -3307,6 +3307,17 @@ g_setsid(void)
#endif
}
/*****************************************************************************/
int
g_getlogin(char *name, unsigned int len)
{
#if defined(_WIN32)
return -1;
#else
return getlogin_r(name, len);
#endif
}
/*****************************************************************************/
int
g_setlogin(const char *name)
@ -3760,21 +3771,6 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
return 0;
}
/*****************************************************************************/
/* returns boolean */
int
g_text2bool(const char *s)
{
if ( (g_atoi(s) != 0) ||
(0 == g_strcasecmp(s, "true")) ||
(0 == g_strcasecmp(s, "on")) ||
(0 == g_strcasecmp(s, "yes")))
{
return 1;
}
return 0;
}
/*****************************************************************************/
/* returns pointer or nil on error */
void *

View File

@ -162,6 +162,7 @@ int g_getuid(void);
int g_getgid(void);
int g_setuid(int pid);
int g_setsid(void);
int g_getlogin(char *name, unsigned int len);
int g_setlogin(const char *name);
int g_waitchild(void);
int g_waitpid(int pid);
@ -180,7 +181,6 @@ int g_time2(void);
int g_time3(void);
int g_save_to_bmp(const char* filename, char* data, int stride_bytes,
int width, int height, int depth, int bits_per_pixel);
int g_text2bool(const char *s);
void * g_shmat(int shmid);
int g_shmdt(const void *shmaddr);
int g_gethostname(char *name, int len);

136
common/string_calls.c Normal file
View File

@ -0,0 +1,136 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2020
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* generic string handling calls
*/
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "string_calls.h"
unsigned int
g_format_info_string(char* dest, unsigned int len,
const char* format,
const struct info_string_tag map[])
{
unsigned int result = 0;
const char *copy_from; /* Data to add to output */
unsigned int copy_len; /* Length of above */
unsigned int skip; /* Date to skip over in format string */
const char *p;
const struct info_string_tag *m;
for ( ; *format != '\0'; format += skip)
{
if (*format == '%')
{
char ch= *(format + 1);
if (ch== '%')
{
/* '%%' in format - replace with single '%' */
copy_from = format;
copy_len= 1;
skip = 2;
}
else if (ch== '\0')
{
/* Percent at end of string - ignore */
copy_from = NULL;
copy_len= 0;
skip = 1;
}
else
{
/* Look up the character in the map, assuming failure */
copy_from = NULL;
copy_len= 0;
skip = 2;
for (m = map ; m->ch != '\0' ; ++m)
{
if (ch == m->ch)
{
copy_from = m->val;
copy_len = strlen(copy_from);
break;
}
}
}
}
else if ((p = strchr(format, '%')) != NULL)
{
/* Copy up to the next '%' */
copy_from = format;
copy_len = p - format;
skip = copy_len;
}
else
{
/* Copy the rest of the format string */
copy_from = format;
copy_len = strlen(format);
skip = copy_len;
}
/* Update the result before any truncation */
result += copy_len;
/* Do we have room in the output buffer for any more data? We
* must always write a terminator if possible */
if (len > 1)
{
if (copy_len > (len - 1))
{
copy_len = len - 1;
}
memcpy(dest, copy_from, copy_len);
dest += copy_len;
len -= copy_len;
}
}
/* Room for a terminator? */
if (len > 0)
{
*dest = '\0';
}
return result;
}
/******************************************************************************/
const char *
g_bool2text(int value)
{
return value ? "true" : "false";
}
/*****************************************************************************/
int
g_text2bool(const char *s)
{
if ( (atoi(s) != 0) ||
(0 == strcasecmp(s, "true")) ||
(0 == strcasecmp(s, "on")) ||
(0 == strcasecmp(s, "yes")))
{
return 1;
}
return 0;
}

81
common/string_calls.h Normal file
View File

@ -0,0 +1,81 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2020
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* generic string handling calls
*/
#if !defined(STRING_CALLS_H)
#define STRING_CALLS_H
/**
* Map a character to a string value
*
* This structure is used by g_format_info_string() to specify the
* string which chould be output for %'ch', where ch is a character
*/
struct info_string_tag
{
char ch;
const char *val;
};
#define INFO_STRING_END_OF_LIST { '\0', NULL }
/**
* Processes a format string for general info
*
* @param[out] dest Destination buffer
* @param[in] len Length of buffer, including space for a terminator
* @param[in] format Format string to process
* @param[in] map Array of struct info_string_tag.
*
* Where a '%<ch>' is encountered in the format string, the map is scanned
* and the corresponding string is copied instead of '%<ch>'.
*
* '%%' is always replaced with a single '%' in the output. %<ch> strings
* not present in the map are ignored.
*
* The map is terminated with INFO_STRING_END_OF_LIST
*
* Caller can check for buffer truncation by comparing the result with
* the buffer length (as in snprintf())
*/
unsigned int
g_format_info_string(char* dest, unsigned int len,
const char* format,
const struct info_string_tag map[]);
/**
* Converts a boolean to a string for output
*
* @param[in] value Value to convert
* @return String representation
*/
const char *
g_bool2text(int value);
/**
* Converts a string to a boolean value
*
* @param[in] s String to convert
* @return machine representation
*/
int
g_text2bool(const char *s);
#endif

View File

@ -246,8 +246,27 @@ Following parameters can be used in the \fB[Chansrv]\fR section.
.TP
\fBFuseMountName\fR=\fIstring\fR
Directory for drive redirection, relative to the user home directory.
Directory for drive redirection.
Created if it doesn't exist. If not specified, defaults to \fIxrdp_client\fR.
If first character is not a '/', this is relative to $HOME.
.P
.RS
If first character is a '/' this is an absolute path. The following
substitutions are made in this string:-
%U - Username
%u - Numeric UID
%% - Percent character
.P
If this format is used:-
.HP 3
1) The directory path permissions MUST be configured correctly by
the system administrator or the system itself - xrdp-chansrv will not
do this for you (although it will create the final directories owned by
the user).
.HP 3
2) The desktop may not automatically display a link for the redirected
drive. To fix this, consult the docs for your chosen desktop.
.RE
.TP
\fBFileUmask\fR=\fImode\fR
@ -257,6 +276,21 @@ files on your redirected drives. This may not be approprate for all
environents, and so you can change this value to allow other users to
access your remote files if required.
.TP
\fBEnableFuseMount\fR=\fI[true|false]\fR
Defaults to \fItrue\fR.
Set to \fIfalse\fR to disable xrdp-chansrv's use of the FUSE system
feature, even if it has been built with this feature enabled.
.P
.RS
Setting this value to \fIfalse\fR will disable the following application
features:-
.P
- drive redirection
.P
- copying-and-pasting of files
.RE
.SH "SESSIONS VARIABLES"
All entries in the \fB[SessionVariables]\fR section are set as
environment variables in the user's session.

View File

@ -26,6 +26,7 @@
#include "ms-rdpbcgr.h"
#include "log.h"
#include "ssl_calls.h"
#include "string_calls.h"
#if defined(XRDP_NEUTRINORDP)
#include <freerdp/codec/rfx.h>

View File

@ -26,6 +26,7 @@
#include "xrdp_rail.h"
#include "trans.h"
#include "log.h"
#include "string_calls.h"
#include <freerdp/settings.h>
#if defined(VERSION_STRUCT_RDP_FREERDP)

View File

@ -31,10 +31,12 @@
#include "os_calls.h"
#include "chansrv_config.h"
#include "string_calls.h"
/* Default settings */
#define DEFAULT_USE_UNIX_SOCKET 0
#define DEFAULT_RESTRICT_OUTBOUND_CLIPBOARD 0
#define DEFAULT_ENABLE_FUSE_MOUNT 1
#define DEFAULT_FUSE_MOUNT_NAME "xrdp-client"
#define DEFAULT_FILE_UMASK 077
@ -155,6 +157,10 @@ read_config_chansrv(log_func_t logmsg,
const char *name = (const char *)list_get_item(names, index);
const char *value = (const char *)list_get_item(values, index);
if (g_strcasecmp(name, "EnableFuseMount") == 0)
{
cfg->enable_fuse_mount = g_text2bool(value);
}
if (g_strcasecmp(name, "FuseMountName") == 0)
{
g_free(cfg->fuse_mount_name);
@ -196,6 +202,7 @@ new_config(void)
else
{
cfg->use_unix_socket = DEFAULT_USE_UNIX_SOCKET;
cfg->enable_fuse_mount = DEFAULT_ENABLE_FUSE_MOUNT;
cfg->restrict_outbound_clipboard = DEFAULT_RESTRICT_OUTBOUND_CLIPBOARD;
cfg->fuse_mount_name = fuse_mount_name;
cfg->file_umask = DEFAULT_FILE_UMASK;
@ -271,13 +278,16 @@ void
config_dump(struct config_chansrv *config)
{
g_writeln("Global configuration:");
g_writeln(" UseUnixSocket (derived): %d", config->use_unix_socket);
g_writeln(" UseUnixSocket (derived): %s",
g_bool2text(config->use_unix_socket));
g_writeln("\nSecurity configuration:");
g_writeln(" RestrictOutboundClipboard: %d",
config->restrict_outbound_clipboard);
g_writeln(" RestrictOutboundClipboard: %s",
g_bool2text(config->restrict_outbound_clipboard));
g_writeln("\nChansrv configuration:");
g_writeln(" EnableFuseMount %s",
g_bool2text(config->enable_fuse_mount));
g_writeln(" FuseMountName: %s", config->fuse_mount_name);
g_writeln(" FileMask: 0%o", config->file_umask);
}

View File

@ -26,6 +26,9 @@ struct config_chansrv
/** Whether to use a UNIX socket for chansrv */
int use_unix_socket;
/** Whether the FUSE mount is enabled or not */
int enable_fuse_mount;
/** RestrictOutboundClipboard setting from sesman.ini */
int restrict_outbound_clipboard;

View File

@ -144,6 +144,7 @@ void xfuse_devredir_cb_file_close(struct state_close *fip)
#include "arch.h"
#include "os_calls.h"
#include "string_calls.h"
#include "clipboard_file.h"
#include "chansrv_fuse.h"
#include "chansrv_xfs.h"
@ -392,6 +393,8 @@ static const char *filename_on_device(const char *full_path);
static void update_inode_file_attributes(const struct file_attr *fattr,
tui32 change_mask, XFS_INODE *xinode);
static char *get_name_for_entry_in_parent(fuse_ino_t parent, const char *name);
static unsigned int format_user_info(char *dest, unsigned int len,
const char *format);
/*****************************************************************************/
int
@ -446,7 +449,7 @@ xfuse_handle_from_fuse_handle(uint64_t handle)
/**
* Initialize FUSE subsystem
*
* @return 0 on success, -1 on failure
* @return 0 on success, -1 on failure, 1 for feature disabled
*****************************************************************************/
int
@ -458,6 +461,21 @@ xfuse_init(void)
if (g_xfuse_inited)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "already inited");
return 0;
}
/* This feature may be disabled */
if (!g_cfg->enable_fuse_mount)
{
/*
* Only log the 'disabled mounts' message one time
*/
static int disabled_mounts_msg_shown = 0;
if (!disabled_mounts_msg_shown)
{
LOG(LOG_LEVEL_INFO, "FUSE mounts are disabled by config");
disabled_mounts_msg_shown = 1;
}
return 1;
}
@ -469,13 +487,27 @@ xfuse_init(void)
load_fuse_config();
/* define FUSE mount point to ~/xrdp_client, ~/thinclient_drives */
g_snprintf(g_fuse_root_path, 255, "%s/%s", g_getenv("HOME"), g_cfg->fuse_mount_name);
/* define FUSE mount point */
if (g_cfg->fuse_mount_name[0] == '/')
{
/* String is an absolute path to the mount point containing
* %u or %U characters */
format_user_info(g_fuse_root_path, sizeof(g_fuse_root_path),
g_cfg->fuse_mount_name);
}
else
{
/* mount_name is relative to $HOME, e.g. ~/xrdp_client,
* or ~/thinclient_drives */
g_snprintf(g_fuse_root_path, sizeof(g_fuse_root_path), "%s/%s",
g_getenv("HOME"), g_cfg->fuse_mount_name);
}
g_snprintf(g_fuse_clipboard_path, 255, "%s/.clipboard", g_fuse_root_path);
/* if FUSE mount point does not exist, create it */
if (!g_directory_exist(g_fuse_root_path))
{
(void)g_create_path(g_fuse_root_path);
if (!g_create_dir(g_fuse_root_path))
{
LOG_DEVEL(LOG_LEVEL_ERROR, "mkdir %s failed. If %s is already mounted, you must "
@ -748,23 +780,38 @@ xfuse_file_contents_range(int stream_id, const char *data, int data_bytes)
int
xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "entered: filename=%s flags=%d size=%d lindex=%d",
LOG_DEVEL(LOG_LEVEL_DEBUG,
"entered: filename=%s flags=%d size=%d lindex=%d",
filename, flags, size, lindex);
/* add entry to xrdp_fs */
XFS_INODE *xinode = xfs_add_entry( g_xfs,
g_clipboard_inum, /* parent inode */
filename,
(0666 | S_IFREG));
if (xinode == NULL)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "failed to create file in xrdp filesystem");
return -1;
}
xinode->size = size;
xinode->lindex = lindex;
int result = -1;
return 0;
if (g_xfs == NULL)
{
LOG_DEVEL(LOG_LEVEL_ERROR,
"xfuse_add_clip_dir_item() called with no filesystem")
}
else
{
/* add entry to xrdp_fs */
XFS_INODE *xinode = xfs_add_entry( g_xfs,
g_clipboard_inum, /* parent inode */
filename,
(0666 | S_IFREG));
if (xinode == NULL)
{
LOG(LOG_LEVEL_INFO,
"failed to create file %s in xrdp filesystem", filename);
}
else
{
xinode->size = size;
xinode->lindex = lindex;
result = 0;
}
}
return result;
}
/**
@ -2609,4 +2656,30 @@ static char *get_name_for_entry_in_parent(fuse_ino_t parent, const char *name)
return result;
}
/*
* Scans a user-provided string substituting %u/%U for UID/username
*/
static unsigned int format_user_info(char *dest, unsigned int len,
const char *format)
{
char uidstr[64];
char username[64];
const struct info_string_tag map[] =
{
{'u', uidstr},
{'U', username},
INFO_STRING_END_OF_LIST
};
int uid = g_getuid();
g_snprintf(uidstr, sizeof(uidstr), "%d", uid);
if (g_getlogin(username, sizeof(username)) != 0)
{
/* Fall back to UID */
g_strncpy(username, uidstr, sizeof(username) - 1);
}
return g_format_info_string(dest, len, format, map);
}
#endif /* end else #ifndef XRDP_FUSE */

View File

@ -33,6 +33,7 @@
#include "file.h"
#include "sesman.h"
#include "log.h"
#include "string_calls.h"
/***************************************************************************//**
*

View File

@ -114,11 +114,16 @@ param=-dpi
param=96
[Chansrv]
; drive redirection, defaults to xrdp_client if not set
; drive redirection
; See sesman.ini(5) for the format of this parameter
#FuseMountName=/run/user/%u/thinclient_drives
#FuseMountName=/media/thinclient_drives/%U/thinclient_drives
FuseMountName=thinclient_drives
; this value allows only the user to acess their own mapped drives.
; Make this more permissive (e.g. 022) if required.
FileUmask=077
; Can be used to disable FUSE functionality - see sesman.ini(5)
#EnableFuseMount=false
[ChansrvLogging]
; Note: one log file is created per display and the LogFile config value

View File

@ -24,6 +24,7 @@
#include "xrdp.h"
#include "log.h"
#include "string_calls.h"
/* 'g_process' is protected by the semaphore 'g_process_sem'. One thread sets
g_process and waits for the other to process it */

View File

@ -25,6 +25,7 @@
#include "base64.h"
#include "xrdp.h"
#include "log.h"
#include "string_calls.h"
#define ASK "ask"
#define ASK_LEN g_strlen(ASK)

View File

@ -23,6 +23,7 @@
#endif
#include "xrdp.h"
#include "log.h"
#include "string_calls.h"
#ifndef USE_NOPAM
#if defined(HAVE__PAM_TYPES_H)

View File

@ -27,6 +27,7 @@
#include "xrdp.h"
#include "ms-rdpbcgr.h"
#include "log.h"
#include "string_calls.h"
#define LLOG_LEVEL 1
#define LLOGLN(_level, _args) \