Add params to allow xrdp to be run as non-root

runtime_user and runtime_group are added to the xrdp.ini file
so that the service knows how to reduce privilege
This commit is contained in:
matt335672 2024-02-26 15:45:04 +00:00
parent 1d927add29
commit 17a56567d2
7 changed files with 83 additions and 48 deletions

View File

@ -315,7 +315,8 @@ transitions between confinement domains.
.TP
\fBSessionSockdirGroup\fR=\fIgroup\fR
Sets the group owner of the directories containing session sockets. This
is normally the GID of the xrdp process so xrdp can connect to user sessions.
MUST be the same as runtime_group in xrdp.ini, or xrdp will not
be able to connect to any sessions.
.SH "X11 SERVER"
Following parameters can be used in the \fB[Xvnc]\fR and

View File

@ -119,6 +119,17 @@ The default port for RDP is \fB3389\fP.
Multiple address:port instances must be separated by spaces or commas. Check the .ini file for examples.
Specifying interfaces requires said interfaces to be UP before xrdp starts.
.TP
\fBruntime_user\fP=\fIusername\fP
.TP
\fBruntime_group\fP=\fIgroupname\fP
User name and group to run the xrdp daemon under.
After xrdp starts, it sets its UID and GID to values derived from these
settings, so that it's running without system privilege.
The \fBruntime_group\fP MUST be set to the same value as
\fBSessionSockdirGroup\fP in \fBsesman.ini\fP if you want to run sessions.
.TP
\fBenable_token_login\fP=\fI[true|false]\fP
If set to \fB1\fP, \fBtrue\fP or \fByes\fP, \fBxrdp\fP will scan the user name provided by the

View File

@ -45,10 +45,10 @@ RestrictInboundClipboard=none
; Leave this unset unless you need to disable it.
#XorgNoNewPrivileges=true
; Specify the group which is to have read access to the directory where
; local sockets for the session are created. This is normally the GID
; which the xrdp process runs as.
; Default is 'root'
#SessionSockdirGroup=root
; local sockets for the session are created.
; This MUST be the same as runtime_group in xrdp.ini, or xrdp will not
; be able to connect to your sessions.
#SessionSockdirGroup=xrdp
[Sessions]

View File

@ -428,8 +428,6 @@ main(int argc, char **argv)
g_exit(1);
}
if (g_file_exist(pid_file)) /* xrdp.pid */
{
LOG(LOG_LEVEL_ALWAYS, "It looks like xrdp is already running.");

View File

@ -27,6 +27,15 @@ port=3389
; prefer use vsock://<cid>:<port> above
use_vsock=false
; Unprivileged User name and group to run the xrdp daemon.
; It is HIGHLY RECOMMENDED you set these values.
; A suitable user and group can be added with a command like this (Linux):-
; useradd xrdp -d / -c 'xrdp daemon' -s /usr/sbin/nologin
; Be aware that runtime_group here, and SessionSockdirGroup in sesman.ini
; MUST be the same if you want to run sessions.
#runtime_user=xrdp
#runtime_group=xrdp
; regulate if the listening socket use socket option tcp_nodelay
; no buffering will be performed in the TCP stack
tcp_nodelay=true

View File

@ -162,7 +162,8 @@ xrdp_listen_get_startup_params(struct xrdp_listen *self)
int index;
int port_override;
int fork_override;
char *val;
const char *name;
const char *val;
struct list *names;
struct list *values;
struct xrdp_startup_params *startup_params;
@ -181,56 +182,67 @@ xrdp_listen_get_startup_params(struct xrdp_listen *self)
{
for (index = 0; index < names->count; index++)
{
val = (char *)list_get_item(names, index);
if (val != 0)
name = (const char *)list_get_item(names, index);
val = (const char *)list_get_item(values, index);
if (name == 0 || val == 0)
{
if (g_strcasecmp(val, "port") == 0)
{
if (port_override == 0)
{
val = (char *) list_get_item(values, index);
g_strncpy(startup_params->port, val,
sizeof(startup_params->port) - 1);
}
}
if (g_strcasecmp(val, "fork") == 0)
{
if (fork_override == 0)
{
val = (char *) list_get_item(values, index);
startup_params->fork = g_text2bool(val);
}
}
continue;
}
if (g_strcasecmp(val, "tcp_nodelay") == 0)
if (g_strcasecmp(name, "port") == 0)
{
if (port_override == 0)
{
val = (char *)list_get_item(values, index);
startup_params->tcp_nodelay = g_text2bool(val);
g_strncpy(startup_params->port, val,
sizeof(startup_params->port) - 1);
}
}
if (g_strcasecmp(val, "tcp_keepalive") == 0)
else if (g_strcasecmp(name, "fork") == 0)
{
if (fork_override == 0)
{
val = (char *)list_get_item(values, index);
startup_params->tcp_keepalive = g_text2bool(val);
startup_params->fork = g_text2bool(val);
}
}
if (g_strcasecmp(val, "tcp_send_buffer_bytes") == 0)
{
val = (char *)list_get_item(values, index);
startup_params->tcp_send_buffer_bytes = g_atoi(val);
}
else if (g_strcasecmp(name, "tcp_nodelay") == 0)
{
startup_params->tcp_nodelay = g_text2bool(val);
}
if (g_strcasecmp(val, "tcp_recv_buffer_bytes") == 0)
{
val = (char *)list_get_item(values, index);
startup_params->tcp_recv_buffer_bytes = g_atoi(val);
}
else if (g_strcasecmp(name, "tcp_keepalive") == 0)
{
startup_params->tcp_keepalive = g_text2bool(val);
}
if (g_strcasecmp(val, "use_vsock") == 0)
{
val = (char *)list_get_item(values, index);
startup_params->use_vsock = g_text2bool(val);
}
else if (g_strcasecmp(name, "tcp_send_buffer_bytes") == 0)
{
startup_params->tcp_send_buffer_bytes = g_atoi(val);
}
else if (g_strcasecmp(name, "tcp_recv_buffer_bytes") == 0)
{
startup_params->tcp_recv_buffer_bytes = g_atoi(val);
}
else if (g_strcasecmp(name, "use_vsock") == 0)
{
startup_params->use_vsock = g_text2bool(val);
}
else if (g_strcasecmp(name, "runtime_user") == 0)
{
g_snprintf(startup_params->runtime_user,
sizeof(startup_params->runtime_user),
"%s", val);
}
else if (g_strcasecmp(name, "runtime_group") == 0)
{
g_snprintf(startup_params->runtime_group,
sizeof(startup_params->runtime_group),
"%s", val);
}
}
}

View File

@ -750,6 +750,10 @@ struct xrdp_startup_params
int tcp_nodelay;
int tcp_keepalive;
int use_vsock;
// These should be local users/groups, and so we shouldn't need
// a lot of storage for them.
char runtime_user[64];
char runtime_group[64];
};
/*