Move SCP to a Unix Domain Socket

The TCP socket implementation of sesman has a number of limitations,
namely that it is affected by firewalls, and also that determining the
user on the other end requires a full authentication process.

The advantage of the TCP socket is that sesman and xrdp can be run on
separate machines. This is however not supported by the xorgxrdp
backend (shared memory), and is insecure, in that passwords are sent
in-the-clear, and the connection is susceptible to MitM attacks. This
architecture has been deprecated in release notes since xrdp v0.9.17,
and although it will continue to be supported in any further releases
in the x0.9.x series, it will not be supported in the next major
version.
This commit is contained in:
matt335672 2022-03-19 11:29:28 +00:00
parent 9c30d4c2f8
commit 0db849fc5c
21 changed files with 335 additions and 286 deletions

View File

@ -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

View File

@ -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 ""

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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.

View File

@ -1,5 +1,6 @@
AM_CPPFLAGS = \
-DSESMAN_RUNTIME_PATH=\"${sesmanruntimedir}\" \
-I$(top_srcdir)/common
module_LTLIBRARIES = \

View File

@ -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;

View File

@ -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));
/**

View File

@ -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

View File

@ -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:");

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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 */

View File

@ -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)

View File

@ -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());
}

View File

@ -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

View File

@ -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)
{

View File

@ -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;