Files
xrdp/tools/chkpriv/xrdp-chkpriv.in
T
matt335672 8bcb14f79d Prefer SessionSockdirGroup to be set to 'root'
With recent changes to the SCP interface, the xrdp process no longer
needs read access to the user sockdir when sesman is in use.
2025-07-14 19:39:26 +01:00

261 lines
7.1 KiB
Bash

#!/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=@sysconfdir@/@sysconfsubdir@
XRDP_INI="$CONF_DIR"/xrdp.ini
SESMAN_INI="$CONF_DIR"/sesman.ini
RSAKEYS_INI="$CONF_DIR"/rsakeys.ini
DROPPRIV=@pkglibexecdir@/xrdp-droppriv
# Helper functions to print colored tag like "[ OK ]"
if [ -t 1 ]; then
print_ok()
{
printf "\033[1m[ \033[1;32mOK\033[0m ]\033[0m "
}
print_warn()
{
printf "\033[1m[ \033[1;33mWARN\033[0m ]\033[0m "
}
print_ng()
{
printf "\033[1m[ \033[1;31mNG\033[0m ]\033[0m "
}
else
print_ok()
{
printf "[ OK ] "
}
print_warn()
{
printf "[ WARN ] "
}
print_ng()
{
printf "[ NG ] "
}
fi
# -----------------------------------------------------------------------------
# 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
print_ng
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
print_warn
echo "This system is not configured to run xrdp without privilege"
exit 0
fi
if [ -z "$runtime_user" ] || [ -z "$runtime_group" ]; then
print_ng
echo "Both 'runtime_user' and 'runtime_group' must be set"
errors=$(( errors + 1 ))
exit 1
fi
if getent passwd "$runtime_user" >/dev/null ; then
print_ok
echo "runtime_user '$runtime_user' appears to exist"
else
print_ng
echo "runtime_user '$runtime_user' does not exist"
errors=$(( errors + 1 ))
fi
GID=
if getent group "$runtime_group" >/dev/null ; then
print_ok
echo "runtime_group '$runtime_group' appears to exist"
GID=$(getent group xrdp | cut -d: -f3)
else
print_ng
echo "runtime_group '$runtime_group' does not exist"
errors=$(( errors + 1 ))
fi
# Groups agree between sesman and xrdp?
if [ -z "$SessionSockdirGroup" ] || [ "$SessionSockdirGroup" = "root" ]; then
print_ok
echo "sesman.ini is configured for secure connections to sesman sessions."
elif [ "$SessionSockdirGroup" = "$runtime_group" ]; then
print_ok
echo "xrdp.ini and sesman.ini agree on group ownership"
print_warn
echo "consider setting SessionSockdirGroup = root for maximum security"
else
print_ng
echo "xrdp.ini and sesman.ini do not agree on group ownership"
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
print_ok
echo "$RSAKEYS_INI has correct permissions"
else
if [ "$1" != 640 ]; then
print_ng
echo "$RSAKEYS_INI should have permissions -rw-r-----"
errors=$(( errors + 1 ))
fi
if [ "$2" != 0 ]; then
print_ng
echo "$RSAKEYS_INI should be owned by root"
errors=$(( errors + 1 ))
fi
if [ "$3" != "$GID" ]; then
print_ng
echo "$RSAKEYS_INI should be in the $runtime_group group"
errors=$(( errors + 1 ))
fi
fi
fi
else
print_ng
echo "$RSAKEYS_INI does not exist"
errors=$(( errors + 1 ))
fi
# Are cert and key readable (but NOT writeable) by the user?
#
# These aren't necessarily our files, so we can't be too 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
for file in "$certificate" "$key_file"; do
if ! [ -e "$file" ]; then
print_ng
echo "$file does not exist"
errors=$(( errors + 1 ))
elif ! $DROPPRIV "$runtime_user" "$runtime_group" sh -c '[ -r '"$file"' ]'
then
print_ng
echo "$file is not readable by $runtime_user:$runtime_group"
errors=$(( errors + 1 ))
elif $DROPPRIV "$runtime_user" "$runtime_group" sh -c '[ -w '"$file"' ]'
then
print_ng
echo "$file is writeable by $runtime_user:$runtime_group"
errors=$(( errors + 1 ))
else
print_ok
echo "$file is read-only for $runtime_user:$runtime_group"
fi
done
echo
if [ $errors -eq 0 ]; then
print_ok
echo "-Summary- Permissions appear to be correct to run xrdp unprivileged"
status=0
else
print_ng
echo "-Summary- $errors error(s) found. Please correct these and try again"
status=1
fi
exit $status