Add xrdp-chkpriv script to check xrdp privileges

This commit is contained in:
matt335672 2024-03-01 14:40:35 +00:00
parent ce355fc235
commit 48255da29a
7 changed files with 301 additions and 5 deletions

View File

@ -646,6 +646,7 @@ AC_CONFIG_FILES([
tools/Makefile
tools/devel/Makefile
tools/devel/tcp_proxy/Makefile
tools/chkpriv/Makefile
vnc/Makefile
xrdpapi/Makefile
xrdp/Makefile

View File

@ -127,9 +127,21 @@ 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.
A suitable user and group can be added with a command like this (Linux):-
useradd xrdp -d / -c 'xrdp daemon' -s /usr/sbin/nologin
In order to establish secure connections, the xrdp daemon needs permission
to access sensitive cryptographic files. After changing either or both
of these values, check that xrdp has access to required files by running
this script:-
@xrdpdatadir@/xrdp-chkpriv
.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

@ -1,3 +1,4 @@
SUBDIRS = \
chkpriv \
devel

31
tools/chkpriv/Makefile.am Normal file
View File

@ -0,0 +1,31 @@
xrdppkgdatadir=$(datadir)/xrdp
pkglibexec_PROGRAMS = \
xrdp-droppriv
dist_xrdppkgdata_SCRIPTS = \
xrdp-chkpriv
AM_LDFLAGS =
AM_CPPFLAGS = \
-I$(top_srcdir)/common
xrdp_droppriv_SOURCES = xrdp-droppriv.c
xrdp_droppriv_LDADD = \
$(top_builddir)/common/libcommon.la
SUBST_VARS = sed \
-e 's|@pkglibexecdir[@]|$(pkglibexecdir)|g'
subst_verbose = $(subst_verbose_@AM_V@)
subst_verbose_ = $(subst_verbose_@AM_DEFAULT_V@)
subst_verbose_0 = @echo " SUBST $@";
SUFFIXES = .in
.in:
$(subst_verbose)$(SUBST_VARS) $< > $@
CLEANFILES = xrdp-chkpriv

205
tools/chkpriv/xrdp-chkpriv.in Executable file
View File

@ -0,0 +1,205 @@
#!/bin/sh
#
# xrdp: A Remote Desktop Protocol server.
#
# Copyright (C) Jay Sorg and contributors 2004-2024
#
# 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.
#
# Program to check permissions for xrdp when running in a non-privileged
# mode
# Change these if they do not match your installation
CONF_DIR=/etc/xrdp
XRDP_INI="$CONF_DIR"/xrdp.ini
SESMAN_INI="$CONF_DIR"/sesman.ini
RSAKEYS_INI="$CONF_DIR"/rsakeys.ini
DROPPRIV=@pkglibexecdir@/xrdp-droppriv
# -----------------------------------------------------------------------------
# G E T I N I V A L U E
#
# Gets a value from an ini file.
#
# Params [ini_file] [key]
# -----------------------------------------------------------------------------
GetIniValue()
{
# Look for a line matching 'key=' with optional whitespace
# either side of the key. When we find one, strip everything
# up to and including the first '=', print it, and quit
#
# This doesn't take sections into account
sed -n -e '/^ *'"$2"' *=/{
s/^[^=]*=//p
q
}' "$1"
}
# -----------------------------------------------------------------------------
# M A I N
# -----------------------------------------------------------------------------
if [ "$(id -u)" != 0 ]; then
echo "** Must run this script as root" >&2
exit 1
fi
OS=$(uname)
case "$OS" in
FreeBSD | Linux) ;;
*) echo "Unsupported operating system $OS" >&2
exit 1
esac
errors=0
runtime_user=$(GetIniValue "$XRDP_INI" runtime_user)
runtime_group=$(GetIniValue "$XRDP_INI" runtime_group)
certificate=$(GetIniValue "$XRDP_INI" certificate)
key_file=$(GetIniValue "$XRDP_INI" key_file)
SessionSockdirGroup=$(GetIniValue "$SESMAN_INI" SessionSockdirGroup)
case "$certificate" in
'') certificate="$CONF_DIR"/cert.pem ;;
/*) ;;
*) certificate="$CONF_DIR"/"$certificate"
esac
case "$key_file" in
'') key_file="$CONF_DIR"/key.pem ;;
/*) ;;
*) key_file="$CONF_DIR"/"$key_file"
esac
echo "Settings"
echo " - [xrdp.ini] runtime_user : $runtime_user"
echo " - [xrdp.ini] runtime_group : $runtime_group"
echo " - [xrdp.ini] certificate : $certificate"
echo " - [xrdp.ini] key_file : $key_file"
echo " - [sesman.ini] SessionSockdirGroup : $SessionSockdirGroup"
echo
# Basic checks on runtime user/group
if [ -z "$runtime_user" ] && [ -z "$runtime_group" ]; then
echo "-Info- This system is not configured to run xrdp without privilege"
exit 0
fi
if [ -z "$runtime_user" ] || [ -z "$runtime_group" ]; then
echo "-Error- Both 'runtime_user' and 'runtime_group' must be set"
errors=$(( errors + 1 ))
exit 1
fi
if getent passwd "$runtime_user" >/dev/null ; then
echo "-Info- runtime_user '$runtime_user' appears to exist"
else
echo "-Error- runtime_user '$runtime_user' does not exist"
errors=$(( errors + 1 ))
fi
GID=
if getent group "$runtime_group" >/dev/null ; then
echo "-Info- runtime_group '$runtime_group' appears to exist"
GID=$(getent group xrdp | cut -d: -f3)
else
echo "-Error- runtime_group '$runtime_group' does not exist"
errors=$(( errors + 1 ))
fi
# Groups agree between sesman and xrdp?
if [ "$runtime_user" = "$SessionSockdirGroup" ]; then
echo "-Info- xrdp.ini and sesman.ini agree on group ownbership"
else
echo "-Error- xrdp.ini and sesman.ini do not agree on group ownbership"
errors=$(( errors + 1 ))
fi
# Check we can access rsakeys.ini
#
# This is our file, so we can be completely prescriptive about
# the permissions
if [ -e $RSAKEYS_INI ]; then
# Only check if we have a GID
if [ -n "$GID" ]; then
# Get the permissions, UID and GID in $1..$3
case "$OS" in
FreeBSD)
# shellcheck disable=SC2046
set -- $(stat -f "%Lp %u %g" $RSAKEYS_INI)
;;
*)
# shellcheck disable=SC2046
set -- $(stat -c "%a %u %g" $RSAKEYS_INI)
esac
if [ "$1/$2/$3" = "640/0/$GID" ]; then
echo "-Info- $RSAKEYS_INI has correct permissions"
else
if [ "$1" != 640 ]; then
echo "-Error- $RSAKEYS_INI should have permissions -rw-r-----"
errors=$(( errors + 1 ))
fi
if [ "$2" != 0 ]; then
echo "-Error- $RSAKEYS_INI should be owned by root"
errors=$(( errors + 1 ))
fi
if [ "$3" != "$GID" ]; then
echo "-Error- $RSAKEYS_INI should be in the $runtime_group group"
errors=$(( errors + 1 ))
fi
fi
fi
else
echo "-Error- $RSAKEYS_INI does not exist"
errors=$(( errors + 1 ))
fi
# Are cert and key readable by the user?
#
# These aren't necessarily our files, so we can't be prescriptive about
# privileges. On Debian for example, we might be using the 'ssl-cert'
# group to obtain access to /etc/ssl/private/ssl-cert-snakeoil.key
if ! [ -e $certificate ]; then
echo "-Error- $certificate does not exist"
errors=$(( errors + 1 ))
elif $DROPPRIV "$runtime_user" "$runtime_group" sh -c '[ -r '"$certificate"' ]'
then
echo "-Info- $certificate is readable by $runtime_user:$runtime_group"
else
echo "-Error- $certificate is not readable by $runtime_user:$runtime_group"
errors=$(( errors + 1 ))
fi
if ! [ -e $key_file ]; then
echo "-Error- $key_file does not exist"
errors=$(( errors + 1 ))
elif $DROPPRIV "$runtime_user" "$runtime_group" sh -c '[ -r '"$key_file"' ]'
sh -c '[ -r '"$key_file"' ]'
then
echo "-Info- $key_file is readable by $runtime_user:$runtime_group"
else
echo "-Error- $key_file is not readable by $runtime_user:$runtime_group"
errors=$(( errors + 1 ))
fi
echo
if [ $errors -eq 0 ]; then
echo "-Summary- Permissions appear to be correct to run xrdp unprivileged"
status=0
else
echo "-Summary- $errors error(s) found. Please correct these and try again"
status=1
fi
exit $status

49
tools/chkpriv/xrdp-droppriv.c Executable file
View File

@ -0,0 +1,49 @@
/*
*
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg and contributors 2004-2024
*
* 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.
*
* Shell around the g_drop_privileges() call
*/
#if defined(HAVE_CONFIG_H)
#include "config_ac.h"
#endif
#include "os_calls.c"
#include "log.h"
int main(int argc, char *argv[])
{
struct log_config *logging;
int status = 1;
logging = log_config_init_for_console(LOG_LEVEL_WARNING,
g_getenv("DROPPRIV_LOG_LEVEL"));
log_start_from_param(logging);
log_config_free(logging);
if (argc < 4)
{
LOG(LOG_LEVEL_ERROR, "Usage : %s [user] [group] [cmd...]\n", argv[0]);
}
else if (g_drop_privileges(argv[1], argv[2]) == 0)
{
status = g_execvp(argv[3], &argv[3]);
}
log_end();
return status;
}

View File

@ -28,11 +28,8 @@ port=3389
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.
; It is HIGHLY RECOMMENDED you set these values. See the xrdp.ini(5)
; manpage for more information on setting and checking these.
#runtime_user=xrdp
#runtime_group=xrdp