Add xrdp-chkpriv script to check xrdp privileges
This commit is contained in:
parent
ce355fc235
commit
48255da29a
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
SUBDIRS = \
|
||||
chkpriv \
|
||||
devel
|
||||
|
31
tools/chkpriv/Makefile.am
Normal file
31
tools/chkpriv/Makefile.am
Normal 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
205
tools/chkpriv/xrdp-chkpriv.in
Executable 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
49
tools/chkpriv/xrdp-droppriv.c
Executable 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;
|
||||
}
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user