session management: Allow for restricted shells

Allows the AlternateShell specified by the user in the TS_INFO_PACKET
to be passed to startwm.sh as an environment variable.
This commit is contained in:
matt335672
2025-10-17 11:33:26 +01:00
parent 23e12403e3
commit 6b6edca8ca
6 changed files with 47 additions and 1 deletions
+7
View File
@@ -365,6 +365,13 @@ because the system is unable to check whether the user is an administrator.
\fBAllowAlternateShell\fR=\fI[true|false]\fR \fBAllowAlternateShell\fR=\fI[true|false]\fR
If set to \fB0\fR, \fBfalse\fR or \fBno\fR, prevent usage of alternate shells by users. If set to \fB0\fR, \fBfalse\fR or \fBno\fR, prevent usage of alternate shells by users.
.TP
\fBPassShellAsEnv\fR=\fI<name-of-environment-variable>\fR
If this is set, alternate shells are not actioned directly, but
passed in to the default window manager in the specified environment
variable. This allows the system manager more control over exactly
what alternate shells are permitted.
.TP .TP
\fBXorgNoNewPrivileges\fR=\fI[true|false]\fR \fBXorgNoNewPrivileges\fR=\fI[true|false]\fR
Only applicable on Linux. If set to \fB0\fR, \fBfalse\fR or \fBno\fR, do Only applicable on Linux. If set to \fB0\fR, \fBfalse\fR or \fBno\fR, do
+9
View File
@@ -72,6 +72,7 @@
#define SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD "RestrictOutboundClipboard" #define SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD "RestrictOutboundClipboard"
#define SESMAN_CFG_SEC_RESTRICT_INBOUND_CLIPBOARD "RestrictInboundClipboard" #define SESMAN_CFG_SEC_RESTRICT_INBOUND_CLIPBOARD "RestrictInboundClipboard"
#define SESMAN_CFG_SEC_ALLOW_ALTERNATE_SHELL "AllowAlternateShell" #define SESMAN_CFG_SEC_ALLOW_ALTERNATE_SHELL "AllowAlternateShell"
#define SESMAN_CFG_SEC_PASS_SHELL_AS_ENV "PassShellAsEnv"
#define SESMAN_CFG_SEC_XORG_NO_NEW_PRIVILEGES "XorgNoNewPrivileges" #define SESMAN_CFG_SEC_XORG_NO_NEW_PRIVILEGES "XorgNoNewPrivileges"
#define SESMAN_CFG_SEC_SESSION_SOCKDIR_GROUP "SessionSockdirGroup" #define SESMAN_CFG_SEC_SESSION_SOCKDIR_GROUP "SessionSockdirGroup"
@@ -319,6 +320,7 @@ config_read_security(int file, struct config_security *sc,
sc->restrict_outbound_clipboard = 0; sc->restrict_outbound_clipboard = 0;
sc->restrict_inbound_clipboard = 0; sc->restrict_inbound_clipboard = 0;
sc->allow_alternate_shell = 1; sc->allow_alternate_shell = 1;
sc->pass_shell_as_env = g_strdup("");
sc->xorg_no_new_privileges = 1; sc->xorg_no_new_privileges = 1;
sc->ts_users = g_strdup(""); sc->ts_users = g_strdup("");
sc->ts_admins = g_strdup(""); sc->ts_admins = g_strdup("");
@@ -390,6 +392,11 @@ config_read_security(int file, struct config_security *sc,
sc->allow_alternate_shell = sc->allow_alternate_shell =
g_text2bool(value); g_text2bool(value);
} }
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_PASS_SHELL_AS_ENV))
{
g_free(sc->pass_shell_as_env);
sc->pass_shell_as_env = g_strdup(value);
}
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_XORG_NO_NEW_PRIVILEGES)) else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_XORG_NO_NEW_PRIVILEGES))
{ {
sc->xorg_no_new_privileges = sc->xorg_no_new_privileges =
@@ -705,6 +712,7 @@ config_dump(struct config_sesman *config)
g_writeln(" XAuthorityInSystemDir: %d", sc->xauth_in_sysdir); g_writeln(" XAuthorityInSystemDir: %d", sc->xauth_in_sysdir);
g_writeln(" AlwaysGroupCheck: %d", sc->ts_always_group_check); g_writeln(" AlwaysGroupCheck: %d", sc->ts_always_group_check);
g_writeln(" AllowAlternateShell: %d", sc->allow_alternate_shell); g_writeln(" AllowAlternateShell: %d", sc->allow_alternate_shell);
g_writeln(" PassShellAsEnv: %s", sc->pass_shell_as_env);
#ifdef HAVE_SYS_PRCTL_H #ifdef HAVE_SYS_PRCTL_H
g_writeln(" XorgNoNewPrivileges: %d", sc->xorg_no_new_privileges); g_writeln(" XorgNoNewPrivileges: %d", sc->xorg_no_new_privileges);
#endif #endif
@@ -773,6 +781,7 @@ config_free(struct config_sesman *cs)
list_delete(cs->xorg_params); list_delete(cs->xorg_params);
list_delete(cs->env_names); list_delete(cs->env_names);
list_delete(cs->env_values); list_delete(cs->env_values);
g_free(cs->sec.pass_shell_as_env);
g_free(cs->sec.ts_users); g_free(cs->sec.ts_users);
g_free(cs->sec.ts_admins); g_free(cs->sec.ts_admins);
g_free(cs->sec.session_sockdir_group); g_free(cs->sec.session_sockdir_group);
+7
View File
@@ -110,6 +110,13 @@ struct config_security
*/ */
int allow_alternate_shell; int allow_alternate_shell;
/**
* @var pass_shell_as_env
* @brief Passes alternate shells in the environment
* @details name of environment variable to receive alternate shell
*/
char *pass_shell_as_env;
/* /*
* @var xorg_no_new_privileges * @var xorg_no_new_privileges
* @brief if the Xorg X11 server should be started with no_new_privs (Linux only) * @brief if the Xorg X11 server should be started with no_new_privs (Linux only)
+14 -1
View File
@@ -257,8 +257,21 @@ start_window_manager(const struct login_info *login_info,
} }
} }
if (s->shell[0] != '\0') if (g_cfg->sec.allow_alternate_shell &&
g_cfg->sec.pass_shell_as_env != NULL &&
g_cfg->sec.pass_shell_as_env[0] != '0')
{ {
// Pass the shell in to the standard startwm scripts
// in an environment variable
LOG(LOG_LEVEL_INFO,
"Setting variable '%s' to the specified shell of '%s'",
g_cfg->sec.pass_shell_as_env,
s->shell);
g_setenv(g_cfg->sec.pass_shell_as_env, s->shell, 1);
}
else if (s->shell[0] != '\0')
{
// Try to execute the shell directly (if permitted)
if (g_cfg->sec.allow_alternate_shell) if (g_cfg->sec.allow_alternate_shell)
{ {
if (g_strchr(s->shell, ' ') != 0 || g_strchr(s->shell, '\t') != 0) if (g_strchr(s->shell, ' ') != 0 || g_strchr(s->shell, '\t') != 0)
+7
View File
@@ -45,6 +45,13 @@ RestrictOutboundClipboard=none
RestrictInboundClipboard=none RestrictInboundClipboard=none
; Set to 'no' to prevent users from logging in with alternate shells ; Set to 'no' to prevent users from logging in with alternate shells
#AllowAlternateShell=true #AllowAlternateShell=true
; Normally, alternate shells (if permitted) are executed directly, as
; specified.
; If this is set, alternate shells are not actioned directly, but
; passed in to the default window manager in the specified environment
; variable. This allows the system manager more control over exactly
; what alternate shells are permitted.
#PassShellAsEnv=XRDP_ALTERNATE_SHELL
; On Linux systems, the Xorg X11 server is normally invoked using ; On Linux systems, the Xorg X11 server is normally invoked using
; no_new_privs to avoid problems if the executable is suid. This may, ; no_new_privs to avoid problems if the executable is suid. This may,
; however, interfere with the use of security modules such as AppArmor. ; however, interfere with the use of security modules such as AppArmor.
+3
View File
@@ -93,6 +93,9 @@ wm_start()
# <your preferred desktop> shall be one of "ls -1 /usr/share/xsessions/|cut -d. -f1" # <your preferred desktop> shall be one of "ls -1 /usr/share/xsessions/|cut -d. -f1"
# e.g. [ -n "$XRDP_SESSION" ] && export DESKTOP_SESSION=ubuntu # e.g. [ -n "$XRDP_SESSION" ] && export DESKTOP_SESSION=ubuntu
# Alternatively, set "PassShellAsEnv=DESKTOP_SESSION" in sesman.ini, which
# lets the user specify the required session directly.
# STARTUP is the default startup command. # STARTUP is the default startup command.
# if $1 is empty and STARTUP was not set # if $1 is empty and STARTUP was not set
# /etc/X11/Xsession.d/50x11-common_determine-startup will fallback to # /etc/X11/Xsession.d/50x11-common_determine-startup will fallback to