Merge pull request #2207 from matt335672/move_to_uds
Move to Unix Domain Socket for SCP (sesman)
This commit is contained in:
commit
dd4abcb27a
@ -2322,6 +2322,55 @@ g_file_lock(int fd, int start, int len)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Converts a hex mask to a mode_t value */
|
||||
#if !defined(_WIN32)
|
||||
static mode_t
|
||||
hex_to_mode_t(int hex)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
|
||||
mode |= (hex & 0x4000) ? S_ISUID : 0;
|
||||
mode |= (hex & 0x2000) ? S_ISGID : 0;
|
||||
mode |= (hex & 0x1000) ? S_ISVTX : 0;
|
||||
mode |= (hex & 0x0400) ? S_IRUSR : 0;
|
||||
mode |= (hex & 0x0200) ? S_IWUSR : 0;
|
||||
mode |= (hex & 0x0100) ? S_IXUSR : 0;
|
||||
mode |= (hex & 0x0040) ? S_IRGRP : 0;
|
||||
mode |= (hex & 0x0020) ? S_IWGRP : 0;
|
||||
mode |= (hex & 0x0010) ? S_IXGRP : 0;
|
||||
mode |= (hex & 0x0004) ? S_IROTH : 0;
|
||||
mode |= (hex & 0x0002) ? S_IWOTH : 0;
|
||||
mode |= (hex & 0x0001) ? S_IXOTH : 0;
|
||||
return mode;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Converts a mode_t value to a hex mask */
|
||||
#if !defined(_WIN32)
|
||||
static int
|
||||
mode_t_to_hex(mode_t mode)
|
||||
{
|
||||
int hex = 0;
|
||||
|
||||
hex |= (mode & S_ISUID) ? 0x4000 : 0;
|
||||
hex |= (mode & S_ISGID) ? 0x2000 : 0;
|
||||
hex |= (mode & S_ISVTX) ? 0x1000 : 0;
|
||||
hex |= (mode & S_IRUSR) ? 0x0400 : 0;
|
||||
hex |= (mode & S_IWUSR) ? 0x0200 : 0;
|
||||
hex |= (mode & S_IXUSR) ? 0x0100 : 0;
|
||||
hex |= (mode & S_IRGRP) ? 0x0040 : 0;
|
||||
hex |= (mode & S_IWGRP) ? 0x0020 : 0;
|
||||
hex |= (mode & S_IXGRP) ? 0x0010 : 0;
|
||||
hex |= (mode & S_IROTH) ? 0x0004 : 0;
|
||||
hex |= (mode & S_IWOTH) ? 0x0002 : 0;
|
||||
hex |= (mode & S_IXOTH) ? 0x0001 : 0;
|
||||
|
||||
return hex;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int
|
||||
@ -2330,22 +2379,22 @@ g_chmod_hex(const char *filename, int flags)
|
||||
#if defined(_WIN32)
|
||||
return 0;
|
||||
#else
|
||||
int fl;
|
||||
mode_t m = hex_to_mode_t(flags);
|
||||
return chmod(filename, m);
|
||||
#endif
|
||||
}
|
||||
|
||||
fl = 0;
|
||||
fl |= (flags & 0x4000) ? S_ISUID : 0;
|
||||
fl |= (flags & 0x2000) ? S_ISGID : 0;
|
||||
fl |= (flags & 0x1000) ? S_ISVTX : 0;
|
||||
fl |= (flags & 0x0400) ? S_IRUSR : 0;
|
||||
fl |= (flags & 0x0200) ? S_IWUSR : 0;
|
||||
fl |= (flags & 0x0100) ? S_IXUSR : 0;
|
||||
fl |= (flags & 0x0040) ? S_IRGRP : 0;
|
||||
fl |= (flags & 0x0020) ? S_IWGRP : 0;
|
||||
fl |= (flags & 0x0010) ? S_IXGRP : 0;
|
||||
fl |= (flags & 0x0004) ? S_IROTH : 0;
|
||||
fl |= (flags & 0x0002) ? S_IWOTH : 0;
|
||||
fl |= (flags & 0x0001) ? S_IXOTH : 0;
|
||||
return chmod(filename, fl);
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int
|
||||
g_umask_hex(int flags)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return flags;
|
||||
#else
|
||||
mode_t m = hex_to_mode_t(flags);
|
||||
m = umask(m);
|
||||
return mode_t_to_hex(m);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,7 @@ int g_file_write(int fd, const char *ptr, int len);
|
||||
int g_file_seek(int fd, int offset);
|
||||
int g_file_lock(int fd, int start, int len);
|
||||
int g_chmod_hex(const char *filename, int flags);
|
||||
int g_umask_hex(int flags);
|
||||
int g_chown(const char *name, int uid, int gid);
|
||||
int g_mkdir(const char *dirname);
|
||||
char *g_get_current_dir(char *dirname, int maxlen);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define CHANSRV_API_BASE_STR "xrdpapi_%d"
|
||||
#define XRDP_X11RDP_BASE_STR "xrdp_display_%d"
|
||||
#define XRDP_DISCONNECT_BASE_STR "xrdp_disconnect_display_%d"
|
||||
#define SCP_LISTEN_PORT_BASE_STR "sesman.socket"
|
||||
|
||||
/* fullpath of sockets */
|
||||
#define XRDP_CHANSRV_STR XRDP_SOCKET_PATH "/" XRDP_CHANSRV_BASE_STR
|
||||
|
14
configure.ac
14
configure.ac
@ -52,10 +52,16 @@ AC_CHECK_SIZEOF([void *])
|
||||
|
||||
AC_ARG_WITH([socketdir],
|
||||
[AS_HELP_STRING([--with-socketdir=DIR],
|
||||
[Use directory for UNIX sockets (default: /tmp/.xrdp)])],
|
||||
[], [with_socketdir="/tmp/.xrdp"])
|
||||
[Use directory for UNIX sockets for XRDP sessions (default: RUNSTATEDIR/xrdp)])],
|
||||
[], [with_socketdir="$runstatedir/xrdp"])
|
||||
AC_SUBST([socketdir], [$with_socketdir])
|
||||
|
||||
AC_ARG_WITH([sesmanruntimedir],
|
||||
[AS_HELP_STRING([--with-sesmanruntimedir=DIR],
|
||||
[Use directory for sesman runtime data (default: RUNSTATEDIR/xrdp-sesman))])],
|
||||
[], [with_sesmanruntimedir="$runstatedir/xrdp-sesman"])
|
||||
AC_SUBST([sesmanruntimedir], [$with_sesmanruntimedir])
|
||||
|
||||
AC_ARG_WITH([systemdsystemunitdir],
|
||||
AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files, no to disable]),
|
||||
[], [
|
||||
@ -547,6 +553,10 @@ echo " exec_prefix $exec_prefix"
|
||||
echo " libdir $libdir"
|
||||
echo " bindir $bindir"
|
||||
echo " sysconfdir $sysconfdir"
|
||||
echo " localstatedir $localstatedir"
|
||||
echo " runstatedir $runstatedir"
|
||||
echo " socketdir $socketdir"
|
||||
echo " sesmanruntimedir $sesmanruntimedir"
|
||||
echo ""
|
||||
echo " unit tests performable $perform_unit_tests"
|
||||
echo ""
|
||||
|
@ -19,6 +19,7 @@ SUBST_VARS = sed \
|
||||
-e 's|@localstatedir[@]|$(localstatedir)|g' \
|
||||
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
|
||||
-e 's|@socketdir[@]|$(socketdir)|g' \
|
||||
-e 's|@sesmanruntimedir[@]|$(sesmanruntimedir)|g' \
|
||||
-e 's|@xrdpconfdir[@]|$(sysconfdir)/xrdp|g' \
|
||||
-e 's|@xrdphomeurl[@]|http://www.xrdp.org/|g'
|
||||
|
||||
|
@ -50,13 +50,19 @@ outside their proper section will be \fIignored\fR.
|
||||
Following parameters can be used in the \fB[Globals]\fR section.
|
||||
|
||||
.TP
|
||||
\fBListenAddress\fR=\fIip address\fR
|
||||
xrdp-sesman listening address. If not specified, defaults to \fI0.0.0.0\fR
|
||||
(all interfaces).
|
||||
|
||||
.TP
|
||||
\fBListenPort\fR=\fIport number\fR
|
||||
xrdp-sesman listening port. If not specified, defaults to \fI3350\fR.
|
||||
\fBListenPort\fR=\fIpath-to-socket\fR
|
||||
UNIX domain socket for xrdp-sesman(8) to listen on.
|
||||
.PP
|
||||
.RS
|
||||
The default value of this setting is 'sesman.socket'.
|
||||
.PP
|
||||
An absoute path can be specified by starting this parameter with a '/'.
|
||||
In this instance, the system administrator is responsible for ensuring
|
||||
the socket can only be created by a suitably privileged process.
|
||||
.PP
|
||||
If the parameter does not start with a '/', a name within
|
||||
@sesmanruntimedir@ is used.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
\fBEnableUserWindowManager\fR=\fI[true|false]\fR
|
||||
|
@ -26,15 +26,11 @@ Defaults to \fBroot\fP.
|
||||
The \fIpassword\fP to authenticate with.
|
||||
The default is to ask for the password interactively.
|
||||
|
||||
.TP
|
||||
.BI \-s= server
|
||||
The host address of the \fIserver\fP to connect to.
|
||||
Defaults to \fBlocalhost\fP.
|
||||
|
||||
.TP
|
||||
.BI \-i= port
|
||||
The TCP \fIport\fP number to connect to.
|
||||
Defaults to \fB3350\fP.
|
||||
The sesman \fIUNIX domain socket\fP to connect to.
|
||||
Defaults to \fBsesman.socket\fP.
|
||||
If no path is specified for the socket, a default of @sesmanruntimedir@ is used.
|
||||
|
||||
.TP
|
||||
.BI \-c= command
|
||||
|
@ -58,6 +58,8 @@ to read it.
|
||||
@localstatedir@/log/xrdp\-sesman.log
|
||||
.br
|
||||
@localstatedir@/run/xrdp\-sesman.pid
|
||||
.br
|
||||
@sesmanruntimedir@/sesman.socket
|
||||
|
||||
.SH "AUTHORS"
|
||||
Jay Sorg <jsorg71@users.sourceforge.net>
|
||||
|
@ -29,11 +29,6 @@ option may not do what you expect.
|
||||
Set session bits-per-pixel (colour depth). Some session types (i.e. Xorg)
|
||||
will ignore this setting.
|
||||
.TP
|
||||
.B -s <server>
|
||||
Server on which sesman is running (probably 'localhost').
|
||||
.br
|
||||
Use of this option is discouraged as it will be removed in the future.
|
||||
.TP
|
||||
.B -t <session-type>
|
||||
Session type - one of Xorg, Xvnc or X11rdp. Alternatively, for testing
|
||||
only, use the numeric session code.
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-DSESMAN_RUNTIME_PATH=\"${sesmanruntimedir}\" \
|
||||
-I$(top_srcdir)/common
|
||||
|
||||
module_LTLIBRARIES = \
|
||||
|
98
libipm/scp.c
98
libipm/scp.c
@ -33,6 +33,7 @@
|
||||
#include "trans.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
#include "xrdp_sockets.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
static const char *
|
||||
@ -66,28 +67,97 @@ scp_msgno_to_str(enum scp_msg_code n, char *buff, unsigned int buff_size)
|
||||
return buff;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
scp_port_to_unix_domain_path(const char *port, char *buff,
|
||||
unsigned int bufflen)
|
||||
{
|
||||
/* GOTCHA: Changes to this logic should be mirrored in
|
||||
* scp_port_to_display_string() */
|
||||
|
||||
int result;
|
||||
|
||||
/* Make sure we can safely de-reference 'port' */
|
||||
if (port == NULL)
|
||||
{
|
||||
port = "";
|
||||
}
|
||||
|
||||
if (port[0] == '/')
|
||||
{
|
||||
result = g_snprintf(buff, bufflen, "%s", port);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *sep;
|
||||
if ((sep = g_strrchr(port, '/')) != NULL && sep != port)
|
||||
{
|
||||
/* We allow the user to specify an absolute path, but not
|
||||
* a relative one with embedded '/' characters */
|
||||
LOG(LOG_LEVEL_WARNING, "Ignoring path elements of '%s'", port);
|
||||
port = sep + 1;
|
||||
}
|
||||
|
||||
if (port[0] == '\0')
|
||||
{
|
||||
port = SCP_LISTEN_PORT_BASE_STR;
|
||||
}
|
||||
else if (g_strcmp(port, "3350") == 0)
|
||||
{
|
||||
/* Version v0.9.x and earlier of xrdp used a TCP port
|
||||
* number. If we come across this, we'll ignore it for
|
||||
* compatibility with old config files */
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Ignoring obsolete SCP port value '%s'", port);
|
||||
port = SCP_LISTEN_PORT_BASE_STR;
|
||||
}
|
||||
|
||||
result = g_snprintf(buff, bufflen, SESMAN_RUNTIME_PATH "/%s", port);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
scp_port_to_display_string(const char *port, char *buff, unsigned int bufflen)
|
||||
{
|
||||
/* Make sure we can safely de-reference 'port' */
|
||||
if (port == NULL)
|
||||
{
|
||||
port = "";
|
||||
}
|
||||
|
||||
/* Ignore any directories for the display */
|
||||
const char *sep;
|
||||
if ((sep = g_strrchr(port, '/')) != NULL)
|
||||
{
|
||||
port = sep + 1;
|
||||
}
|
||||
|
||||
/* Check for a default */
|
||||
if (port[0] == '\0' || g_strcmp(port, "3350") == 0)
|
||||
{
|
||||
port = SCP_LISTEN_PORT_BASE_STR;
|
||||
}
|
||||
|
||||
return g_snprintf(buff, bufflen, "%s", port);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct trans *
|
||||
scp_connect(const char *host, const char *port,
|
||||
scp_connect(const char *port,
|
||||
int (*term_func)(void))
|
||||
{
|
||||
char sock_path[256];
|
||||
struct trans *t;
|
||||
if ((t = trans_create(TRANS_MODE_TCP, 128, 128)) != NULL)
|
||||
|
||||
(void)scp_port_to_unix_domain_path(port, sock_path, sizeof(sock_path));
|
||||
if ((t = trans_create(TRANS_MODE_UNIX, 128, 128)) != NULL)
|
||||
{
|
||||
if (host == NULL)
|
||||
{
|
||||
host = "localhost";
|
||||
}
|
||||
|
||||
if (port == NULL)
|
||||
{
|
||||
port = "3350";
|
||||
}
|
||||
|
||||
t->is_term = term_func;
|
||||
|
||||
trans_connect(t, host, port, 3000);
|
||||
if (t->status != TRANS_STATUS_UP)
|
||||
if (trans_connect(t, NULL, sock_path, 3000) != 0)
|
||||
{
|
||||
trans_delete(t);
|
||||
t = NULL;
|
||||
|
33
libipm/scp.h
33
libipm/scp.h
@ -65,11 +65,38 @@ scp_msgno_to_str(enum scp_msg_code n, char *buff, unsigned int buff_size);
|
||||
|
||||
/* Connection management facilities */
|
||||
|
||||
/**
|
||||
* Maps a port definition to a UNIX domain socket path
|
||||
* @param port Port definition (e.g. from sesman.ini). Can be "" or NULL
|
||||
* @param buff Buffer for result
|
||||
* @param bufflen Length of buff
|
||||
*
|
||||
* @return Number of chars needed for result, excluding the '\0'
|
||||
*/
|
||||
int
|
||||
scp_port_to_unix_domain_path(const char *port, char *buff,
|
||||
unsigned int bufflen);
|
||||
|
||||
/**
|
||||
* Maps a port definition to a displayable string
|
||||
* @param port Port definition (e.g. from sesman.ini). Can be "" or NULL
|
||||
* @param buff Buffer for result
|
||||
* @param bufflen Length of buff
|
||||
*
|
||||
* @return Number of chars needed for result, excluding the '\0'
|
||||
*
|
||||
* This differs from scp_port_to_unix_domain_path() in that the result is
|
||||
* for displaying to the user (i.e. in a status message), rather than for
|
||||
* connecting to. For log messages, use the result of
|
||||
* scp_port_to_unix_domain_path()
|
||||
*/
|
||||
int
|
||||
scp_port_to_display_string(const char *port, char *buff, unsigned int bufflen);
|
||||
|
||||
/**
|
||||
* Connect to an SCP server
|
||||
*
|
||||
* @param host Host providing SCP service
|
||||
* @param port TCP port for SCP service
|
||||
* @param port Port definition (e.g. from sesman.ini)
|
||||
* @param term_func Function to poll during connection for program
|
||||
* termination, or NULL for none.
|
||||
* @return Initialised SCP transport
|
||||
@ -77,7 +104,7 @@ scp_msgno_to_str(enum scp_msg_code n, char *buff, unsigned int buff_size);
|
||||
* The returned tranport has the is_term member set to term_func.
|
||||
*/
|
||||
struct trans *
|
||||
scp_connect(const char *host, const char *port,
|
||||
scp_connect(const char *port,
|
||||
int (*term_func)(void));
|
||||
|
||||
/**
|
||||
|
@ -8,6 +8,7 @@ AM_CPPFLAGS = \
|
||||
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
|
||||
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
|
||||
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
|
||||
-DSESMAN_RUNTIME_PATH=\"${sesmanruntimedir}\" \
|
||||
-I$(top_srcdir)/common \
|
||||
-I$(top_srcdir)/libipm
|
||||
|
||||
@ -45,6 +46,8 @@ xrdp_sesman_SOURCES = \
|
||||
config.h \
|
||||
env.c \
|
||||
env.h \
|
||||
lock_uds.c \
|
||||
lock_uds.h \
|
||||
scp_process.c \
|
||||
scp_process.h \
|
||||
sesman.c \
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "log.h"
|
||||
#include "string_calls.h"
|
||||
#include "chansrv/chansrv_common.h"
|
||||
#include "scp.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
*
|
||||
@ -51,14 +52,11 @@ config_read_globals(int file, struct config_sesman *cf, struct list *param_n,
|
||||
struct list *param_v)
|
||||
{
|
||||
int i;
|
||||
int length;
|
||||
char *buf;
|
||||
|
||||
list_clear(param_v);
|
||||
list_clear(param_n);
|
||||
|
||||
/* resetting the struct */
|
||||
cf->listen_address[0] = '\0';
|
||||
cf->listen_port[0] = '\0';
|
||||
cf->enable_user_wm = 0;
|
||||
cf->user_wm[0] = '\0';
|
||||
@ -70,47 +68,50 @@ config_read_globals(int file, struct config_sesman *cf, struct list *param_n,
|
||||
|
||||
for (i = 0; i < param_n->count; i++)
|
||||
{
|
||||
buf = (char *)list_get_item(param_n, i);
|
||||
const char *param = (const char *)list_get_item(param_n, i);
|
||||
const char *val = (const char *)list_get_item(param_v, i);
|
||||
|
||||
if (0 == g_strcasecmp(buf, SESMAN_CFG_DEFWM))
|
||||
if (0 == g_strcasecmp(param, SESMAN_CFG_DEFWM))
|
||||
{
|
||||
cf->default_wm = g_strdup((char *)list_get_item(param_v, i));
|
||||
cf->default_wm = g_strdup(val);
|
||||
}
|
||||
else if (0 == g_strcasecmp(buf, SESMAN_CFG_USERWM))
|
||||
else if (0 == g_strcasecmp(param, SESMAN_CFG_USERWM))
|
||||
{
|
||||
g_strncpy(cf->user_wm, (char *)list_get_item(param_v, i), 31);
|
||||
g_strncpy(cf->user_wm, val, sizeof(cf->user_wm) - 1);
|
||||
}
|
||||
else if (0 == g_strcasecmp(buf, SESMAN_CFG_ENABLE_USERWM))
|
||||
else if (0 == g_strcasecmp(param, SESMAN_CFG_ENABLE_USERWM))
|
||||
{
|
||||
cf->enable_user_wm = g_text2bool((char *)list_get_item(param_v, i));
|
||||
cf->enable_user_wm = g_text2bool(val);
|
||||
}
|
||||
else if (0 == g_strcasecmp(buf, SESMAN_CFG_PORT))
|
||||
else if (0 == g_strcasecmp(param, SESMAN_CFG_PORT))
|
||||
{
|
||||
g_strncpy(cf->listen_port, (char *)list_get_item(param_v, i), 15);
|
||||
scp_port_to_unix_domain_path(val, cf->listen_port,
|
||||
sizeof(cf->listen_port));
|
||||
}
|
||||
else if (0 == g_strcasecmp(buf, SESMAN_CFG_ADDRESS))
|
||||
else if (0 == g_strcasecmp(param, SESMAN_CFG_AUTH_FILE_PATH))
|
||||
{
|
||||
g_strncpy(cf->listen_address, (char *)list_get_item(param_v, i), 31);
|
||||
cf->auth_file_path = g_strdup(val);
|
||||
}
|
||||
else if (0 == g_strcasecmp(buf, SESMAN_CFG_AUTH_FILE_PATH))
|
||||
else if (g_strcasecmp(param, SESMAN_CFG_RECONNECT_SH) == 0)
|
||||
{
|
||||
cf->auth_file_path = g_strdup((char *)list_get_item(param_v, i));
|
||||
cf->reconnect_sh = g_strdup(val);
|
||||
}
|
||||
else if (g_strcasecmp(buf, SESMAN_CFG_RECONNECT_SH) == 0)
|
||||
else if (0 == g_strcasecmp(param, SESMAN_CFG_ADDRESS))
|
||||
{
|
||||
cf->reconnect_sh = g_strdup((char *)list_get_item(param_v, i));
|
||||
/* Config must be updated for Unix Domain Sockets */
|
||||
LOG(LOG_LEVEL_WARNING, "Obsolete setting' " SESMAN_CFG_ADDRESS
|
||||
"' in [" SESMAN_CFG_GLOBALS "] should be removed.");
|
||||
LOG(LOG_LEVEL_WARNING, "Review setting' " SESMAN_CFG_PORT "' in ["
|
||||
SESMAN_CFG_GLOBALS "]");
|
||||
}
|
||||
}
|
||||
|
||||
/* checking for missing required parameters */
|
||||
if ('\0' == cf->listen_address[0])
|
||||
{
|
||||
g_strncpy(cf->listen_address, "0.0.0.0", 8);
|
||||
}
|
||||
|
||||
if ('\0' == cf->listen_port[0])
|
||||
{
|
||||
g_strncpy(cf->listen_port, "3350", 5);
|
||||
/* Load the default value */
|
||||
scp_port_to_unix_domain_path(NULL, cf->listen_port,
|
||||
sizeof(cf->listen_port));
|
||||
}
|
||||
|
||||
if ('\0' == cf->user_wm[0])
|
||||
@ -118,46 +119,40 @@ config_read_globals(int file, struct config_sesman *cf, struct list *param_n,
|
||||
cf->enable_user_wm = 0;
|
||||
}
|
||||
|
||||
if (cf->default_wm == 0)
|
||||
{
|
||||
cf->default_wm = g_strdup("startwm.sh");
|
||||
}
|
||||
else if (g_strlen(cf->default_wm) == 0)
|
||||
if (cf->default_wm == 0 || cf->default_wm[0] == '\0')
|
||||
{
|
||||
g_free(cf->default_wm);
|
||||
cf->default_wm = g_strdup("startwm.sh");
|
||||
}
|
||||
/* if default_wm doesn't begin with '/', it's a relative path to XRDP_CFG_PATH */
|
||||
/* if default_wm doesn't begin with '/', it's a relative path to
|
||||
* XRDP_CFG_PATH */
|
||||
if (cf->default_wm[0] != '/')
|
||||
{
|
||||
/* sizeof operator returns string length including null terminator */
|
||||
length = sizeof(XRDP_CFG_PATH) + g_strlen(cf->default_wm) + 1; /* '/' */
|
||||
buf = (char *)g_malloc(length, 0);
|
||||
int length = (sizeof(XRDP_CFG_PATH) +
|
||||
g_strlen(cf->default_wm) + 1); /* '/' */
|
||||
char *buf = (char *)g_malloc(length, 0);
|
||||
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);
|
||||
cf->default_wm = buf;
|
||||
}
|
||||
|
||||
if (cf->reconnect_sh == 0)
|
||||
{
|
||||
cf->reconnect_sh = g_strdup("reconnectwm.sh");
|
||||
}
|
||||
else if (g_strlen(cf->reconnect_sh) == 0)
|
||||
if (cf->reconnect_sh == 0 || cf->reconnect_sh[0] == '\0')
|
||||
{
|
||||
g_free(cf->reconnect_sh);
|
||||
cf->reconnect_sh = g_strdup("reconnectwm.sh");
|
||||
}
|
||||
/* if reconnect_sh doesn't begin with '/', it's a relative path to XRDP_CFG_PATH */
|
||||
/* if reconnect_sh doesn't begin with '/', it's a relative path to
|
||||
* XRDP_CFG_PATH */
|
||||
if (cf->reconnect_sh[0] != '/')
|
||||
{
|
||||
/* sizeof operator returns string length including null terminator */
|
||||
length = sizeof(XRDP_CFG_PATH) + g_strlen(cf->reconnect_sh) + 1; /* '/' */
|
||||
buf = (char *)g_malloc(length, 0);
|
||||
int length = (sizeof(XRDP_CFG_PATH) +
|
||||
g_strlen(cf->reconnect_sh) + 1); /* '/' */
|
||||
char *buf = (char *)g_malloc(length, 0);
|
||||
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);
|
||||
cf->reconnect_sh = buf;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -530,6 +525,7 @@ config_read(const char *sesman_ini)
|
||||
param_n->auto_free = 1;
|
||||
param_v = list_create();
|
||||
param_v->auto_free = 1;
|
||||
all_ok = 1;
|
||||
|
||||
/* read global config */
|
||||
config_read_globals(fd, cfg, param_n, param_v);
|
||||
@ -552,7 +548,6 @@ config_read(const char *sesman_ini)
|
||||
list_delete(param_v);
|
||||
list_delete(param_n);
|
||||
g_file_close(fd);
|
||||
all_ok = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -579,14 +574,13 @@ config_dump(struct config_sesman *config)
|
||||
/* Global sesman configuration */
|
||||
g_writeln("Filename: %s", config->sesman_ini);
|
||||
g_writeln("Global configuration:");
|
||||
g_writeln(" ListenAddress: %s", config->listen_address);
|
||||
g_writeln(" ListenPort: %s", config->listen_port);
|
||||
g_writeln(" EnableUserWindowManager: %d", config->enable_user_wm);
|
||||
g_writeln(" UserWindowManager: %s", config->user_wm);
|
||||
g_writeln(" DefaultWindowManager: %s", config->default_wm);
|
||||
g_writeln(" ReconnectScript: %s", config->reconnect_sh);
|
||||
g_writeln(" AuthFilePath: %s",
|
||||
((config->auth_file_path) ? (config->auth_file_path) : ("disabled")));
|
||||
(config->auth_file_path ? config->auth_file_path : "disabled"));
|
||||
|
||||
/* Session configuration */
|
||||
g_writeln("Session configuration:");
|
||||
|
@ -201,16 +201,11 @@ struct config_sesman
|
||||
*/
|
||||
char *sesman_ini;
|
||||
|
||||
/**
|
||||
* @var listen_address
|
||||
* @brief Listening address
|
||||
*/
|
||||
char listen_address[32];
|
||||
/**
|
||||
* @var listen_port
|
||||
* @brief Listening port
|
||||
*/
|
||||
char listen_port[16];
|
||||
char listen_port[256];
|
||||
/**
|
||||
* @var enable_user_wm
|
||||
* @brief Flag that enables user specific wm
|
||||
|
146
sesman/lock_uds.c
Normal file
146
sesman/lock_uds.c
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) 2022 Matt Burt, all xrdp contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @file lock_uds.c
|
||||
* @brief Providing a locking facility for Unix Domain Sockets
|
||||
* @author Matt Burt
|
||||
*
|
||||
* It is difficult for a server to determine whether a socket it wishes
|
||||
* to listen on is already active or not. The purpose of this module is to
|
||||
* provide a locking facility which can be used as a proxy for this.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
#include "log.h"
|
||||
#include "lock_uds.h"
|
||||
|
||||
struct lock_uds
|
||||
{
|
||||
char *filename; ///<< Name of the lock file
|
||||
int fd; ///<< File decriptor for open file
|
||||
int pid; ///<< PID of process originally taking out lock
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
struct lock_uds *
|
||||
lock_uds(const char *sockname)
|
||||
{
|
||||
struct lock_uds *lock = NULL;
|
||||
char *filename = NULL;
|
||||
int fd = -1;
|
||||
|
||||
if (sockname == NULL || sockname[0] != '/')
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "Invalid sockname '%s'",
|
||||
(sockname == NULL) ? "<null>" : sockname);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate space for lock filename and result */
|
||||
filename = (char *)g_malloc(g_strlen(sockname) + 1 + 5 + 1, 0);
|
||||
lock = g_new0(struct lock_uds, 1);
|
||||
if (lock == NULL || filename == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s : Out of memory", __func__);
|
||||
}
|
||||
else
|
||||
{
|
||||
int saved_umask;
|
||||
/* Construct the filename */
|
||||
/* This call is guaranteed to succeed as we know that sockname
|
||||
* contains at least one '/' */
|
||||
char *p = filename;
|
||||
const char *basename = g_strrchr(sockname, '/') + 1;
|
||||
g_memcpy(p, sockname, basename - sockname);
|
||||
p += basename - sockname;
|
||||
*p++ = '.';
|
||||
g_strcpy(p, basename);
|
||||
p += g_strlen(p);
|
||||
*p++ = '.';
|
||||
*p++ = 'l';
|
||||
*p++ = 'o';
|
||||
*p++ = 'c';
|
||||
*p++ = 'k';
|
||||
*p++ = '\0';
|
||||
|
||||
saved_umask = g_umask_hex(0x77);
|
||||
fd = g_file_open(filename);
|
||||
g_umask_hex(saved_umask);
|
||||
if (fd < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to create '%s' [%s]",
|
||||
filename, g_get_strerror());
|
||||
}
|
||||
else if (g_file_lock(fd, 0, 0) == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to get lock for '%s' - "
|
||||
"program already running?", sockname);
|
||||
g_file_close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fd >= 0)
|
||||
{
|
||||
/* Success - finish off */
|
||||
lock->filename = filename;
|
||||
lock->fd = fd;
|
||||
lock->pid = g_getpid();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free(filename);
|
||||
g_free(lock);
|
||||
lock = NULL;
|
||||
}
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void
|
||||
unlock_uds(struct lock_uds *lock)
|
||||
{
|
||||
if (lock != NULL)
|
||||
{
|
||||
if (lock->fd >= 0)
|
||||
{
|
||||
g_file_close(lock->fd);
|
||||
lock->fd = -1; // In case of use-after-free
|
||||
}
|
||||
|
||||
/* Only delete the lock file if we are the process which
|
||||
* created it */
|
||||
if (g_getpid() == lock->pid)
|
||||
{
|
||||
g_file_delete(lock->filename);
|
||||
}
|
||||
g_free(lock->filename);
|
||||
lock->filename = NULL;
|
||||
g_free(lock);
|
||||
}
|
||||
}
|
59
sesman/lock_uds.h
Normal file
59
sesman/lock_uds.h
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) 2022 Matt Burt, all xrdp contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @file lock_uds.h
|
||||
* @brief Providing a locking facility for Unix Domain Sockets
|
||||
* @author Matt Burt
|
||||
*
|
||||
* It is difficult for a server to determine whether a socket it wishes
|
||||
* to listen on is already active or not. The purpose of this module is to
|
||||
* provide a locking facility which can be used as a proxy for this.
|
||||
*/
|
||||
|
||||
#ifndef LOCK_UDS_H
|
||||
#define LOCK_UDS_H
|
||||
|
||||
struct lock_uds;
|
||||
|
||||
/**
|
||||
* Take out a lock for the specified Unix Domain socket
|
||||
* @param sockname Name of socket. Must start with a '/'
|
||||
* @return A struct lock_uds instance if the lock was successfully acquired.
|
||||
*
|
||||
* A NULL return may indicate a lack of memory, or that another
|
||||
* process has the lock.
|
||||
*
|
||||
* A file is created in the same directory as the socket. The name
|
||||
* of the file is ".${basename}.lock", where basename is the base name
|
||||
* of the socket. THE file is removed when the lock is relinquished. */
|
||||
struct lock_uds *
|
||||
lock_uds(const char *sockname);
|
||||
|
||||
/**
|
||||
* Relinquish a lock on the specified Unix Domain Socket.
|
||||
* @param lock to relinquish
|
||||
*
|
||||
* If the process which has originally taken out the lock forks, this
|
||||
* routine should be called from the child process to prevent the lock
|
||||
* inadvertently being passed to the child. */
|
||||
void
|
||||
unlock_uds(struct lock_uds *lock);
|
||||
|
||||
#endif // LOCK_UDS_H
|
125
sesman/sesman.c
125
sesman/sesman.c
@ -36,6 +36,7 @@
|
||||
#include "trans.h"
|
||||
|
||||
#include "scp_process.h"
|
||||
#include "lock_uds.h"
|
||||
|
||||
/**
|
||||
* Maximum number of short-lived connections to sesman
|
||||
@ -70,6 +71,10 @@ struct sesman_con
|
||||
};
|
||||
|
||||
static struct trans *g_list_trans;
|
||||
|
||||
/* Variables used to lock g_list_trans */
|
||||
static struct lock_uds *g_list_trans_lock;
|
||||
|
||||
static struct list *g_con_list = NULL;
|
||||
static int g_pid;
|
||||
|
||||
@ -206,45 +211,52 @@ sesman_process_params(int argc, char **argv,
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int sesman_listen_test(struct config_sesman *cfg)
|
||||
static int
|
||||
create_sesman_runtime_dir(void)
|
||||
{
|
||||
int error;
|
||||
int sck;
|
||||
int rv = 0;
|
||||
int rv = -1;
|
||||
/* Make sure if we create the directory, there's no gap where it
|
||||
* may have the wrong permissions */
|
||||
int entry_umask = g_umask_hex(0x755);
|
||||
|
||||
sck = g_tcp_socket();
|
||||
if (sck < 0)
|
||||
if (!g_directory_exist(SESMAN_RUNTIME_PATH) &&
|
||||
!g_create_dir(SESMAN_RUNTIME_PATH))
|
||||
{
|
||||
return 1;
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Can't create runtime directory '"
|
||||
SESMAN_RUNTIME_PATH "' [%s]", g_get_strerror());
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "Testing if xrdp-sesman can listen on %s port %s.",
|
||||
cfg->listen_address, cfg->listen_port);
|
||||
g_tcp_set_non_blocking(sck);
|
||||
error = g_tcp_bind_address(sck, cfg->listen_port, cfg->listen_address);
|
||||
if (error == 0)
|
||||
else if (g_chown(SESMAN_RUNTIME_PATH, g_getuid(), g_getuid()) != 0)
|
||||
{
|
||||
/* try to listen */
|
||||
error = g_tcp_listen(sck);
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
/* if listen succeeded, stop listen immediately */
|
||||
g_sck_close(sck);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = 1;
|
||||
}
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Can't set ownership of sesman runtime directory [%s]",
|
||||
g_get_strerror());
|
||||
}
|
||||
else if (g_chmod_hex(SESMAN_RUNTIME_PATH, 0x755) != 0)
|
||||
{
|
||||
/* This might seem redundant, but there's a chance the
|
||||
* directory already exists */
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Can't set permissions of sesman runtime directory [%s]",
|
||||
g_get_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = 1;
|
||||
rv = 0;
|
||||
}
|
||||
g_umask_hex(entry_umask);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static int sesman_listen_test(struct config_sesman *cfg)
|
||||
{
|
||||
int status = sesman_create_listening_transport(cfg);
|
||||
sesman_delete_listening_transport();
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
sesman_close_all(void)
|
||||
@ -357,8 +369,18 @@ set_reload_event(int sig)
|
||||
void
|
||||
sesman_delete_listening_transport(void)
|
||||
{
|
||||
trans_delete(g_list_trans);
|
||||
if (g_getpid() == g_pid)
|
||||
{
|
||||
trans_delete(g_list_trans);
|
||||
}
|
||||
else
|
||||
{
|
||||
trans_delete_from_child(g_list_trans);
|
||||
}
|
||||
g_list_trans = NULL;
|
||||
|
||||
unlock_uds(g_list_trans_lock);
|
||||
g_list_trans_lock = NULL;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -366,26 +388,43 @@ int
|
||||
sesman_create_listening_transport(const struct config_sesman *cfg)
|
||||
{
|
||||
int rv = 1;
|
||||
g_list_trans = trans_create(TRANS_MODE_TCP, 8192, 8192);
|
||||
g_list_trans = trans_create(TRANS_MODE_UNIX, 8192, 8192);
|
||||
if (g_list_trans == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: trans_create failed", __func__);
|
||||
}
|
||||
else
|
||||
else if ((g_list_trans_lock = lock_uds(cfg->listen_port)) != NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "%s: address %s port %s",
|
||||
__func__, cfg->listen_address, cfg->listen_port);
|
||||
rv = trans_listen_address(g_list_trans, cfg->listen_port,
|
||||
cfg->listen_address);
|
||||
/* Make sure the file is always created with the correct
|
||||
* permissions, if it's not there */
|
||||
int entry_umask = g_umask_hex(0x666);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "%s: port %s", __func__, cfg->listen_port);
|
||||
rv = trans_listen_address(g_list_trans, cfg->listen_port, NULL);
|
||||
if (rv != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: trans_listen_address failed", __func__);
|
||||
sesman_delete_listening_transport();
|
||||
}
|
||||
else if (g_chown(cfg->listen_port, g_getuid(), g_getuid()) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Can't set ownership of '%s' [%s]",
|
||||
cfg->listen_port, g_get_strerror());
|
||||
}
|
||||
else if ((rv = g_chmod_hex(cfg->listen_port, 0x666)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: Can't set permissions on '%s' [%s]",
|
||||
__func__, cfg->listen_port, g_get_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
g_list_trans->trans_conn_in = sesman_listen_conn_in;
|
||||
}
|
||||
g_umask_hex(entry_umask);
|
||||
}
|
||||
|
||||
if (rv != 0)
|
||||
{
|
||||
sesman_delete_listening_transport();
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -422,6 +461,7 @@ sesman_main_loop(void)
|
||||
list_delete(g_con_list);
|
||||
return 1;
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO, "Sesman now listening on %s", g_cfg->listen_port);
|
||||
|
||||
error = 0;
|
||||
while (!error)
|
||||
@ -722,7 +762,6 @@ main(int argc, char **argv)
|
||||
|
||||
LOG(LOG_LEVEL_TRACE, "config loaded in %s at %s:%d", __func__, __FILE__, __LINE__);
|
||||
LOG(LOG_LEVEL_TRACE, " sesman_ini = %s", g_cfg->sesman_ini);
|
||||
LOG(LOG_LEVEL_TRACE, " listen_address = %s", g_cfg->listen_address);
|
||||
LOG(LOG_LEVEL_TRACE, " listen_port = %s", g_cfg->listen_port);
|
||||
LOG(LOG_LEVEL_TRACE, " enable_user_wm = %d", g_cfg->enable_user_wm);
|
||||
LOG(LOG_LEVEL_TRACE, " default_wm = %s", g_cfg->default_wm);
|
||||
@ -751,6 +790,16 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the runtime directory before we try to listen (or
|
||||
* test-listen), so there's somewhere for the default socket to live */
|
||||
if (create_sesman_runtime_dir() != 0)
|
||||
{
|
||||
config_free(g_cfg);
|
||||
log_end();
|
||||
g_deinit();
|
||||
g_exit(1);
|
||||
}
|
||||
|
||||
if (daemon)
|
||||
{
|
||||
/* start of daemonizing code */
|
||||
@ -759,6 +808,7 @@ main(int argc, char **argv)
|
||||
LOG(LOG_LEVEL_ERROR, "Failed to start xrdp-sesman daemon, "
|
||||
"possibly address already in use.");
|
||||
config_free(g_cfg);
|
||||
log_end();
|
||||
g_deinit();
|
||||
g_exit(1);
|
||||
}
|
||||
@ -766,14 +816,17 @@ main(int argc, char **argv)
|
||||
if (0 != g_fork())
|
||||
{
|
||||
config_free(g_cfg);
|
||||
log_end();
|
||||
g_deinit();
|
||||
g_exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* signal handling */
|
||||
/* Now we've forked (if necessary), we can get the prgram PID */
|
||||
g_pid = g_getpid();
|
||||
|
||||
/* signal handling */
|
||||
g_snprintf(text, 255, "xrdp_sesman_%8.8x_main_term", g_pid);
|
||||
g_term_event = g_create_wait_obj(text);
|
||||
g_snprintf(text, 255, "xrdp_sesman_%8.8x_sigchld", g_pid);
|
||||
|
@ -1,8 +1,8 @@
|
||||
;; See `man 5 sesman.ini` for details
|
||||
|
||||
[Globals]
|
||||
ListenAddress=127.0.0.1
|
||||
ListenPort=3350
|
||||
; listening port
|
||||
#ListenPort=sesman.socket
|
||||
EnableUserWindowManager=true
|
||||
; Give in relative path to user's home directory
|
||||
UserWindowManager=startwm.sh
|
||||
|
13
sesman/sig.c
13
sesman/sig.c
@ -47,16 +47,19 @@ sig_sesman_reload_cfg(void)
|
||||
}
|
||||
|
||||
/* Deal with significant config changes */
|
||||
if (g_strcmp(g_cfg->listen_address, cfg->listen_address) != 0 ||
|
||||
g_strcmp(g_cfg->listen_port, cfg->listen_port) != 0)
|
||||
if (g_strcmp(g_cfg->listen_port, cfg->listen_port) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "sesman listen address changed to %s:%s",
|
||||
cfg->listen_address, cfg->listen_port);
|
||||
LOG(LOG_LEVEL_INFO, "sesman listen port changed to %s",
|
||||
cfg->listen_port);
|
||||
|
||||
/* We have to delete the old port before listening to the new one
|
||||
* in case they overlap in scope */
|
||||
sesman_delete_listening_transport();
|
||||
sesman_create_listening_transport(cfg);
|
||||
if (sesman_create_listening_transport(cfg) == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Sesman now listening on %s",
|
||||
g_cfg->listen_port);
|
||||
}
|
||||
}
|
||||
|
||||
/* free old config data */
|
||||
|
@ -34,7 +34,6 @@
|
||||
char user[257];
|
||||
char pass[257];
|
||||
char cmnd[257];
|
||||
char serv[257];
|
||||
char port[257];
|
||||
|
||||
static int cmndList(struct trans *t);
|
||||
@ -55,7 +54,6 @@ int main(int argc, char **argv)
|
||||
user[0] = '\0';
|
||||
pass[0] = '\0';
|
||||
cmnd[0] = '\0';
|
||||
serv[0] = '\0';
|
||||
port[0] = '\0';
|
||||
|
||||
logging = log_config_init_for_console(LOG_LEVEL_INFO, NULL);
|
||||
@ -72,10 +70,6 @@ int main(int argc, char **argv)
|
||||
{
|
||||
g_strncpy(pass, (argv[idx]) + 3, 256);
|
||||
}
|
||||
else if (0 == g_strncmp(argv[idx], "-s=", 3))
|
||||
{
|
||||
g_strncpy(serv, (argv[idx]) + 3, 256);
|
||||
}
|
||||
else if (0 == g_strncmp(argv[idx], "-i=", 3))
|
||||
{
|
||||
g_strncpy(port, (argv[idx]) + 3, 256);
|
||||
@ -86,11 +80,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == g_strncmp(serv, "", 1))
|
||||
{
|
||||
g_strncpy(serv, "localhost", 256);
|
||||
}
|
||||
|
||||
if (0 == g_strncmp(port, "", 1))
|
||||
{
|
||||
g_strncpy(port, "3350", 256);
|
||||
@ -115,7 +104,7 @@ int main(int argc, char **argv)
|
||||
|
||||
}
|
||||
|
||||
t = scp_connect(serv, port, NULL);
|
||||
t = scp_connect(port, NULL);
|
||||
|
||||
|
||||
if (t == NULL)
|
||||
|
@ -63,10 +63,6 @@
|
||||
# define DEFAULT_BPP 32
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_SERVER
|
||||
# define DEFAULT_SERVER "localhost"
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_TYPE
|
||||
# define DEFAULT_TYPE "Xorg"
|
||||
#endif
|
||||
@ -95,7 +91,6 @@ struct session_params
|
||||
int height;
|
||||
int bpp;
|
||||
enum scp_session_type session_type;
|
||||
const char *server;
|
||||
|
||||
const char *directory;
|
||||
const char *shell;
|
||||
@ -175,9 +170,6 @@ usage(void)
|
||||
g_printf(" -g <geometry> Default:%dx%d\n",
|
||||
DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
g_printf(" -b <bits-per-pixel> Default:%d\n", DEFAULT_BPP);
|
||||
/* Don't encourage use of this one - we need to move to local sockets */
|
||||
g_printf(" -s <server> Default:%s (Deprecated)\n",
|
||||
DEFAULT_SERVER);
|
||||
g_printf(" -t <type> Default:%s\n", DEFAULT_TYPE);
|
||||
g_printf(" -D <directory> Default: $HOME\n"
|
||||
" -S <shell> Default: Defined window manager\n"
|
||||
@ -291,7 +283,6 @@ parse_program_args(int argc, char *argv[], struct session_params *sp,
|
||||
sp->height = DEFAULT_HEIGHT;
|
||||
sp->bpp = DEFAULT_BPP;
|
||||
(void)string_to_session_type(DEFAULT_TYPE, &sp->session_type);
|
||||
sp->server = DEFAULT_SERVER;
|
||||
|
||||
sp->directory = "";
|
||||
sp->shell = "";
|
||||
@ -315,11 +306,6 @@ parse_program_args(int argc, char *argv[], struct session_params *sp,
|
||||
sp->bpp = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
LOG(LOG_LEVEL_WARNING, "Using deprecated option '-s'");
|
||||
sp->server = optarg;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (string_to_session_type(optarg, &sp->session_type) != 0)
|
||||
{
|
||||
@ -419,10 +405,10 @@ send_create_session_request(struct trans *t, const struct session_params *sp)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"width:%d height:%d bpp:%d code:%d\n"
|
||||
"server:\"%s\" directory:\"%s\"\n"
|
||||
"directory:\"%s\"\n"
|
||||
"shell:\"%s\" connection_description:\"%s\"",
|
||||
sp->width, sp->height, sp->bpp, sp->session_type,
|
||||
sp->server, sp->directory,
|
||||
sp->directory,
|
||||
sp->shell, sp->connection_description);
|
||||
/* Only log the password in development builds */
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "password:\"%s\"", sp->password);
|
||||
@ -498,7 +484,7 @@ main(int argc, char **argv)
|
||||
LOG(LOG_LEVEL_ERROR, "error reading config file %s : %s",
|
||||
sesman_ini, g_get_strerror());
|
||||
}
|
||||
else if (!(t = scp_connect(sp.server, cfg->listen_port, NULL)))
|
||||
else if (!(t = scp_connect(cfg->listen_port, NULL)))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "connect error - %s", g_get_strerror());
|
||||
}
|
||||
|
@ -223,7 +223,6 @@ name=Xorg
|
||||
lib=libxup.@lib_extension@
|
||||
username=ask
|
||||
password=ask
|
||||
ip=127.0.0.1
|
||||
port=-1
|
||||
code=20
|
||||
|
||||
@ -232,7 +231,6 @@ name=Xvnc
|
||||
lib=libvnc.@lib_extension@
|
||||
username=ask
|
||||
password=ask
|
||||
ip=127.0.0.1
|
||||
port=-1
|
||||
#xserverbpp=24
|
||||
#delay_ms=2000
|
||||
@ -256,7 +254,6 @@ username=na
|
||||
password=ask
|
||||
#pamusername=asksame
|
||||
#pampassword=asksame
|
||||
#pamsessionmng=127.0.0.1
|
||||
#delay_ms=2000
|
||||
|
||||
; Generic RDP proxy using NeutrinoRDP
|
||||
@ -275,7 +272,6 @@ password=ask
|
||||
; connections.
|
||||
#pamusername=ask
|
||||
#pampassword=ask
|
||||
#pamsessionmng=127.0.0.1
|
||||
; Currently NeutrinoRDP doesn't support dynamic resizing. Uncomment
|
||||
; this line if you're using a client which does.
|
||||
#enable_dynamic_resizing=false
|
||||
|
159
xrdp/xrdp_mm.c
159
xrdp/xrdp_mm.c
@ -51,7 +51,7 @@ getPAMError(const int pamError, char *text, int text_bytes);
|
||||
static const char *
|
||||
getPAMAdditionalErrorInfo(const int pamError, struct xrdp_mm *self);
|
||||
static int
|
||||
xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *ip, const char *port);
|
||||
xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port);
|
||||
static void
|
||||
xrdp_mm_connect_sm(struct xrdp_mm *self);
|
||||
|
||||
@ -159,8 +159,6 @@ xrdp_mm_delete(struct xrdp_mm *self)
|
||||
|
||||
trans_delete(self->sesman_trans);
|
||||
self->sesman_trans = 0;
|
||||
trans_delete(self->pam_auth_trans);
|
||||
self->pam_auth_trans = 0;
|
||||
list_delete(self->login_names);
|
||||
list_delete(self->login_values);
|
||||
g_free(self);
|
||||
@ -229,7 +227,7 @@ xrdp_mm_send_gateway_login(struct xrdp_mm *self, const char *username,
|
||||
"sending login info to session manager, please wait...");
|
||||
|
||||
return scp_send_gateway_request(
|
||||
self->pam_auth_trans, username, password,
|
||||
self->sesman_trans, username, password,
|
||||
self->wm->client_info->connection_description);
|
||||
}
|
||||
|
||||
@ -475,7 +473,6 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self)
|
||||
int rv;
|
||||
int key_flags;
|
||||
int device_flags;
|
||||
int use_uds;
|
||||
|
||||
rv = 1; /* failure */
|
||||
g_memset(text, 0, sizeof(text));
|
||||
@ -500,22 +497,7 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self)
|
||||
}
|
||||
else if (self->code == 10 || self->code == 20) /* X11rdp/Xorg */
|
||||
{
|
||||
use_uds = 1;
|
||||
|
||||
if ((value = xrdp_mm_get_value(self, "ip")) != NULL &&
|
||||
g_strcmp(value, "127.0.0.1") != 0)
|
||||
{
|
||||
use_uds = 0;
|
||||
}
|
||||
|
||||
if (use_uds)
|
||||
{
|
||||
g_snprintf(text, 255, XRDP_X11RDP_STR, self->display);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(text, 255, "%d", 6200 + self->display);
|
||||
}
|
||||
g_snprintf(text, 255, XRDP_X11RDP_STR, self->display);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1691,10 +1673,9 @@ xrdp_mm_chan_data_in(struct trans *trans)
|
||||
|
||||
static void cleanup_sesman_connection(struct xrdp_mm *self)
|
||||
{
|
||||
/* Don't delete these transports here - we may be in
|
||||
/* Don't delete any transports here - we may be in
|
||||
* an auth callback from one of them */
|
||||
self->delete_sesman_trans = 1;
|
||||
self->delete_pam_auth_trans = 1;
|
||||
|
||||
if (self->wm->login_state != WMLS_CLEANUP)
|
||||
{
|
||||
@ -1861,16 +1842,12 @@ xrdp_mm_process_gateway_response(struct xrdp_mm *self)
|
||||
int auth_result;
|
||||
int rv;
|
||||
|
||||
rv = scp_get_gateway_response(self->pam_auth_trans, &auth_result);
|
||||
rv = scp_get_gateway_response(self->sesman_trans, &auth_result);
|
||||
if (rv == 0)
|
||||
{
|
||||
const char *additionalError;
|
||||
char pam_error[128];
|
||||
|
||||
/* We no longer need the pam_auth transport - it's only used
|
||||
* for the one message */
|
||||
self->delete_pam_auth_trans = 1;
|
||||
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
||||
"Reply from access control: %s",
|
||||
getPAMError(auth_result,
|
||||
@ -1987,11 +1964,8 @@ xrdp_mm_scp_data_in(struct trans *trans)
|
||||
{
|
||||
char buff[64];
|
||||
scp_msgno_to_str(msgno, buff, sizeof(buff));
|
||||
const char *src = (trans == self->pam_auth_trans)
|
||||
? "PAM authenticator"
|
||||
: "sesman";
|
||||
LOG(LOG_LEVEL_ERROR, "Ignored SCP message %s from %s",
|
||||
buff, src);
|
||||
LOG(LOG_LEVEL_ERROR, "Ignored SCP message %s from sesman",
|
||||
buff);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2015,10 +1989,8 @@ cleanup_states(struct xrdp_mm *self)
|
||||
self->use_chansrv = 0; /* true if chansrvport is set in xrdp.ini or using sesman */
|
||||
self->use_pam_auth = 0; /* true if we're to use the PAM authentication facility */
|
||||
self->sesman_trans = NULL; /* connection to sesman */
|
||||
self->pam_auth_trans = NULL; /* connection to PAM authenticator */
|
||||
self->chan_trans = NULL; /* connection to chansrv */
|
||||
self->delete_sesman_trans = 0;
|
||||
self->delete_pam_auth_trans = 0;
|
||||
self->display = 0; /* 10 for :10.0, 11 for :11.0, etc */
|
||||
guid_clear(&self->guid);
|
||||
self->code = 0; /* 0 Xvnc session, 10 X11rdp session, 20 Xorg session */
|
||||
@ -2304,28 +2276,31 @@ parse_chansrvport(const char *value, char *dest, int dest_size)
|
||||
|
||||
/*****************************************************************************/
|
||||
static struct trans *
|
||||
xrdp_mm_scp_connect(struct xrdp_mm *self, const char *target, const char *ip)
|
||||
xrdp_mm_scp_connect(struct xrdp_mm *self)
|
||||
{
|
||||
char port[128];
|
||||
char port_description[128];
|
||||
struct trans *t;
|
||||
|
||||
xrdp_mm_get_sesman_port(port, sizeof(port));
|
||||
scp_port_to_display_string(port,
|
||||
port_description, sizeof(port_description));
|
||||
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_DEBUG,
|
||||
"connecting to %s on %s:%s", target, ip, port);
|
||||
t = scp_connect(ip, port, g_is_term);
|
||||
"connecting to sesman on %s", port_description);
|
||||
t = scp_connect(port, g_is_term);
|
||||
if (t != NULL)
|
||||
{
|
||||
/* fully connected */
|
||||
t->trans_data_in = xrdp_mm_scp_data_in;
|
||||
t->callback_data = self;
|
||||
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s connect ok", target);
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "sesman connect ok");
|
||||
}
|
||||
else
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR,
|
||||
"Error connecting to %s on %s:%s",
|
||||
target, ip, port);
|
||||
"Error connecting to sesman on %s", port_description);
|
||||
trans_delete(t);
|
||||
t = NULL;
|
||||
}
|
||||
@ -2334,27 +2309,17 @@ xrdp_mm_scp_connect(struct xrdp_mm *self, const char *target, const char *ip)
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_mm_pam_auth_connect(struct xrdp_mm *self, const char *ip)
|
||||
{
|
||||
trans_delete(self->pam_auth_trans);
|
||||
self->pam_auth_trans = xrdp_mm_scp_connect(self, "PAM authenticator", ip);
|
||||
|
||||
return (self->pam_auth_trans == NULL); /* 0 for success */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_mm_sesman_connect(struct xrdp_mm *self, const char *ip)
|
||||
xrdp_mm_sesman_connect(struct xrdp_mm *self)
|
||||
{
|
||||
trans_delete(self->sesman_trans);
|
||||
self->sesman_trans = xrdp_mm_scp_connect(self, "sesman", ip);
|
||||
self->sesman_trans = xrdp_mm_scp_connect(self);
|
||||
|
||||
return (self->sesman_trans == NULL); /* 0 for success */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *ip, const char *port)
|
||||
xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port)
|
||||
{
|
||||
if (self->wm->client_info->channels_allowed == 0)
|
||||
{
|
||||
@ -2365,16 +2330,7 @@ xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *ip, const char *port)
|
||||
}
|
||||
|
||||
/* connect channel redir */
|
||||
if ((g_strcmp(ip, "127.0.0.1") == 0) || (ip[0] == 0))
|
||||
{
|
||||
/* unix socket */
|
||||
self->chan_trans = trans_create(TRANS_MODE_UNIX, 8192, 8192);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tcp */
|
||||
self->chan_trans = trans_create(TRANS_MODE_TCP, 8192, 8192);
|
||||
}
|
||||
self->chan_trans = trans_create(TRANS_MODE_UNIX, 8192, 8192);
|
||||
|
||||
self->chan_trans->is_term = g_is_term;
|
||||
self->chan_trans->si = &(self->wm->session->si);
|
||||
@ -2386,7 +2342,7 @@ xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *ip, const char *port)
|
||||
self->chan_trans->extra_flags = 0;
|
||||
|
||||
/* try to connect for up to 10 seconds */
|
||||
trans_connect(self->chan_trans, ip, port, 10 * 1000);
|
||||
trans_connect(self->chan_trans, NULL, port, 10 * 1000);
|
||||
if (self->chan_trans->status != TRANS_STATUS_UP)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_mm_chansrv_connect: error in "
|
||||
@ -2454,10 +2410,26 @@ xrdp_mm_connect(struct xrdp_mm *self)
|
||||
if (port != NULL && g_strcmp(port, "-1") == 0)
|
||||
{
|
||||
self->use_sesman = 1;
|
||||
/* Connecting to a remote sesman is no longer supported */
|
||||
if (xrdp_mm_get_value(self, "ip") != NULL)
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm,
|
||||
LOG_LEVEL_WARNING,
|
||||
"Parameter 'ip' is obsolete for sesman connections."
|
||||
" Please remove from config");
|
||||
}
|
||||
}
|
||||
|
||||
if (gateway_username != NULL)
|
||||
{
|
||||
/* Connecting to a remote sesman is no longer supported */
|
||||
if (xrdp_mm_get_value(self, "pamsessionmng") != NULL)
|
||||
{
|
||||
xrdp_wm_log_msg(self->wm,
|
||||
LOG_LEVEL_WARNING,
|
||||
"Parameter 'pamsessionmng' is obsolete."
|
||||
" Please remove from config");
|
||||
}
|
||||
#ifdef USE_PAM
|
||||
self->use_pam_auth = 1;
|
||||
#else
|
||||
@ -2499,22 +2471,10 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
|
||||
{
|
||||
case MMCS_CONNECT_TO_SESMAN:
|
||||
{
|
||||
if (self->use_sesman)
|
||||
if (self->use_sesman || self->use_pam_auth)
|
||||
{
|
||||
/* Synchronous call */
|
||||
const char *ip = xrdp_mm_get_value(self, "ip");
|
||||
status = xrdp_mm_sesman_connect(self, ip);
|
||||
}
|
||||
|
||||
if (status == 0 && self->use_pam_auth)
|
||||
{
|
||||
/* Synchronous call */
|
||||
const char *ip = xrdp_mm_get_value(self, "pamsessionmng");
|
||||
if (ip == NULL)
|
||||
{
|
||||
ip = xrdp_mm_get_value(self, "ip");
|
||||
}
|
||||
status = xrdp_mm_pam_auth_connect(self, ip);
|
||||
status = xrdp_mm_sesman_connect(self);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2589,25 +2549,12 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
|
||||
{
|
||||
if (self->use_chansrv)
|
||||
{
|
||||
const char *ip = "";
|
||||
char portbuff[256];
|
||||
|
||||
if (self->use_sesman)
|
||||
{
|
||||
ip = xrdp_mm_get_value(self, "ip");
|
||||
|
||||
/* connect channel redir */
|
||||
if (ip == NULL || (ip[0] == '\0') ||
|
||||
(g_strcmp(ip, "127.0.0.1") == 0))
|
||||
{
|
||||
g_snprintf(portbuff, sizeof(portbuff),
|
||||
XRDP_CHANSRV_STR, self->display);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(portbuff, sizeof(portbuff),
|
||||
"%d", 7200 + self->display);
|
||||
}
|
||||
g_snprintf(portbuff, sizeof(portbuff),
|
||||
XRDP_CHANSRV_STR, self->display);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2617,7 +2564,7 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
|
||||
|
||||
}
|
||||
xrdp_mm_update_allowed_channels(self);
|
||||
xrdp_mm_chansrv_connect(self, ip, portbuff);
|
||||
xrdp_mm_chansrv_connect(self, portbuff);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2668,12 +2615,6 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self,
|
||||
trans_get_wait_objs(self->sesman_trans, read_objs, rcount);
|
||||
}
|
||||
|
||||
if (self->pam_auth_trans != 0 &&
|
||||
self->pam_auth_trans->status == TRANS_STATUS_UP)
|
||||
{
|
||||
trans_get_wait_objs(self->pam_auth_trans, read_objs, rcount);
|
||||
}
|
||||
|
||||
if ((self->chan_trans != 0) && self->chan_trans->status == TRANS_STATUS_UP)
|
||||
{
|
||||
trans_get_wait_objs_rw(self->chan_trans, read_objs, rcount,
|
||||
@ -2898,22 +2839,6 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self)
|
||||
self->sesman_trans = NULL;
|
||||
}
|
||||
|
||||
if (self->pam_auth_trans != NULL &&
|
||||
!self->delete_pam_auth_trans &&
|
||||
self->pam_auth_trans->status == TRANS_STATUS_UP)
|
||||
{
|
||||
if (trans_check_wait_objs(self->pam_auth_trans) != 0)
|
||||
{
|
||||
self->delete_pam_auth_trans = 1;
|
||||
}
|
||||
}
|
||||
if (self->delete_pam_auth_trans)
|
||||
{
|
||||
trans_delete(self->pam_auth_trans);
|
||||
self->pam_auth_trans = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (self->chan_trans != NULL &&
|
||||
self->chan_trans->status == TRANS_STATUS_UP)
|
||||
{
|
||||
|
@ -322,7 +322,6 @@ struct xrdp_mm
|
||||
int use_pam_auth; /* True if we're to authenticate using PAM */
|
||||
int use_chansrv; /* true if chansrvport is set in xrdp.ini or using sesman */
|
||||
struct trans *sesman_trans; /* connection to sesman */
|
||||
struct trans *pam_auth_trans; /* connection to pam authenticator */
|
||||
struct trans *chan_trans; /* connection to chansrv */
|
||||
|
||||
/* We can't delete transports while we're in a callback for that
|
||||
@ -330,7 +329,6 @@ struct xrdp_mm
|
||||
* These flags mark transports as needing to be deleted when
|
||||
* we are definitely not in a transport callback */
|
||||
int delete_sesman_trans;
|
||||
int delete_pam_auth_trans;
|
||||
|
||||
struct list *login_names;
|
||||
struct list *login_values;
|
||||
|
Loading…
Reference in New Issue
Block a user