75736f4853
This allows the `xrdp` part of the path `/etc/xrdp` where config files are placed to be customizable. This change is useful when trying the stable version and the devel version alternately.
249 lines
6.9 KiB
Bash
249 lines
6.9 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 ]"
|
|
|
|
print_ok()
|
|
{
|
|
if [ -t 1 ]; then
|
|
printf "\033[1m[ \033[1;32mOK\033[0m ]\033[0m "
|
|
else
|
|
printf "[ OK ] "
|
|
fi
|
|
}
|
|
|
|
print_warn()
|
|
{
|
|
if [ -t 1 ]; then
|
|
printf "\033[1m[ \033[1;33mWARN\033[0m ]\033[0m "
|
|
else
|
|
printf "[ WARN ] "
|
|
fi
|
|
}
|
|
|
|
print_ng()
|
|
{
|
|
if [ -t 1 ]; then
|
|
printf "\033[1m[ \033[1;31mNG\033[0m ]\033[0m "
|
|
else
|
|
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 [ "$runtime_user" = "$SessionSockdirGroup" ]; then
|
|
print_ok
|
|
echo "xrdp.ini and sesman.ini agree on group ownership"
|
|
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
|