diff --git a/common/xrdp_sockets.h b/common/xrdp_sockets.h index 1a625ef7..6402798c 100644 --- a/common/xrdp_sockets.h +++ b/common/xrdp_sockets.h @@ -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 diff --git a/configure.ac b/configure.ac index 83663c85..c6d4ced2 100644 --- a/configure.ac +++ b/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 "" diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 18574346..b55919fe 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -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' diff --git a/docs/man/sesman.ini.5.in b/docs/man/sesman.ini.5.in index 7291038f..af3be2a7 100644 --- a/docs/man/sesman.ini.5.in +++ b/docs/man/sesman.ini.5.in @@ -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 diff --git a/docs/man/xrdp-sesadmin.8.in b/docs/man/xrdp-sesadmin.8.in index ab540fca..6727772b 100644 --- a/docs/man/xrdp-sesadmin.8.in +++ b/docs/man/xrdp-sesadmin.8.in @@ -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 diff --git a/docs/man/xrdp-sesman.8.in b/docs/man/xrdp-sesman.8.in index 03ebd47d..08e30ecb 100644 --- a/docs/man/xrdp-sesman.8.in +++ b/docs/man/xrdp-sesman.8.in @@ -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 diff --git a/docs/man/xrdp-sesrun.8.in b/docs/man/xrdp-sesrun.8.in index 1cbd88dd..256c4f7a 100644 --- a/docs/man/xrdp-sesrun.8.in +++ b/docs/man/xrdp-sesrun.8.in @@ -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 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 - one of Xorg, Xvnc or X11rdp. Alternatively, for testing only, use the numeric session code. diff --git a/libipm/Makefile.am b/libipm/Makefile.am index f0592442..2957182b 100644 --- a/libipm/Makefile.am +++ b/libipm/Makefile.am @@ -1,5 +1,6 @@ AM_CPPFLAGS = \ + -DSESMAN_RUNTIME_PATH=\"${sesmanruntimedir}\" \ -I$(top_srcdir)/common module_LTLIBRARIES = \ diff --git a/libipm/scp.c b/libipm/scp.c index b3f4fbf6..a6cfd827 100644 --- a/libipm/scp.c +++ b/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; diff --git a/libipm/scp.h b/libipm/scp.h index 7984a7b6..e2d87c3f 100644 --- a/libipm/scp.h +++ b/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)); /** diff --git a/sesman/Makefile.am b/sesman/Makefile.am index 181861af..7d7052a5 100644 --- a/sesman/Makefile.am +++ b/sesman/Makefile.am @@ -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 diff --git a/sesman/config.c b/sesman/config.c index 61e9e403..4eabdd46 100644 --- a/sesman/config.c +++ b/sesman/config.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:"); diff --git a/sesman/config.h b/sesman/config.h index c6b72f8a..b73ff46c 100644 --- a/sesman/config.h +++ b/sesman/config.h @@ -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 diff --git a/sesman/sesman.c b/sesman/sesman.c index b5c78f4c..96849379 100644 --- a/sesman/sesman.c +++ b/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); diff --git a/sesman/sesman.ini.in b/sesman/sesman.ini.in index 8c5f173f..15ef50ba 100644 --- a/sesman/sesman.ini.in +++ b/sesman/sesman.ini.in @@ -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 diff --git a/sesman/sig.c b/sesman/sig.c index 14d4c820..65c1d288 100644 --- a/sesman/sig.c +++ b/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 */ diff --git a/sesman/tools/sesadmin.c b/sesman/tools/sesadmin.c index e04e4ef2..4ef56a02 100644 --- a/sesman/tools/sesadmin.c +++ b/sesman/tools/sesadmin.c @@ -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) diff --git a/sesman/tools/sesrun.c b/sesman/tools/sesrun.c index cbdc7a46..1429376a 100644 --- a/sesman/tools/sesrun.c +++ b/sesman/tools/sesrun.c @@ -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 Default:%dx%d\n", DEFAULT_WIDTH, DEFAULT_HEIGHT); g_printf(" -b Default:%d\n", DEFAULT_BPP); - /* Don't encourage use of this one - we need to move to local sockets */ - g_printf(" -s Default:%s (Deprecated)\n", - DEFAULT_SERVER); g_printf(" -t Default:%s\n", DEFAULT_TYPE); g_printf(" -D Default: $HOME\n" " -S 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()); } diff --git a/xrdp/xrdp.ini.in b/xrdp/xrdp.ini.in index 3b6340f8..aee9bb28 100644 --- a/xrdp/xrdp.ini.in +++ b/xrdp/xrdp.ini.in @@ -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 diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index fa3f9396..fb3e341b 100644 --- a/xrdp/xrdp_mm.c +++ b/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) { diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 8ec731fa..d800370c 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -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;