9.2. Creating users and groups for software daemons
If your software runs a daemon that does not need root privileges, you need to create a user for it. There are two kind of Debian users that can be used by packages: static uids (assigned by
base-passwd, for a list of static users in Debian see
Section 12.1.1.12, “Operating system users and groups”) and dynamic uids in the range assigned to system users.
In the first case, you need to ask for a user or group id to the base-passwd. Once the user is available there the package needs to be distributed including a proper versioned depends to the base-passwd package.
In the second case, you need to create the system user either in the preinst or in the postinst and make the package depend on adduser (>= 3.11)
.
The following example code creates the user and group the daemon will run as when the package is installed or upgraded:
[...]
case "$1" in
install|upgrade)
# If the package has default file it could be sourced, so that
# the local admin can overwrite the defaults
[ -f "/etc/default/packagename
" ] && . /etc/default/packagename
# Sane defaults:
[ -z "$SERVER_HOME" ] && SERVER_HOME=server_dir
[ -z "$SERVER_USER" ] && SERVER_USER=server_user
[ -z "$SERVER_NAME" ] && SERVER_NAME="Server description
"
[ -z "$SERVER_GROUP" ] && SERVER_GROUP=server_group
# Groups that the user will be added to, if undefined, then none.
ADDGROUP=""
# create user to avoid running server as root
# 1. create group if not existing
if ! getent group | grep -q "^$SERVER_GROUP:" ; then
echo -n "Adding group $SERVER_GROUP.."
addgroup --quiet --system $SERVER_GROUP 2>/dev/null ||true
echo "..done"
fi
# 2. create homedir if not existing
test -d $SERVER_HOME || mkdir $SERVER_HOME
# 3. create user if not existing
if ! getent passwd | grep -q "^$SERVER_USER:"; then
echo -n "Adding system user $SERVER_USER.."
adduser --quiet \
--system \
--ingroup $SERVER_GROUP \
--no-create-home \
--disabled-password \
$SERVER_USER 2>/dev/null || true
echo "..done"
fi
# 4. adjust passwd entry
usermod -c "$SERVER_NAME" \
-d $SERVER_HOME \
-g $SERVER_GROUP \
$SERVER_USER
# 5. adjust file and directory permissions
if ! dpkg-statoverride --list $SERVER_HOME >/dev/null
then
chown -R $SERVER_USER:adm $SERVER_HOME
chmod u=rwx,g=rxs,o= $SERVER_HOME
fi
# 6. Add the user to the ADDGROUP group
if test -n $ADDGROUP
then
if ! groups $SERVER_USER | cut -d: -f2 | \
grep -qw $ADDGROUP; then
adduser $SERVER_USER $ADDGROUP
fi
fi
;;
configure)
[...]
You have to make sure that the init.d script file:
Starts the daemon dropping privileges: if the software does not do the setuid(2) or seteuid(2) call itself, you can use the --chuid
call of start-stop-daemon
.
Stops the daemon only if the user id matches, you can use the start-stop-daemon
--user
option for this.
Does not run if either the user or the group do not exist:
if ! getent passwd | grep -q "^server_user
:"; then
echo "Server user does not exist. Aborting" >&2
exit 1
fi
if ! getent group | grep -q "^server_group
:" ; then
echo "Server group does not exist. Aborting" >&2
exit 1
fi
If the package creates the system user it can remove it when it is purged in its
postrm. This has some drawbacks, however. For example, files created by it will be orphaned and might be taken over by a new system user in the future if it is assigned the same uid
. Consequently, removing system users on purge is not yet mandatory and depends on the package needs. If unsure, this action could be handled by asking the administrator for the prefered action when the package is installed (i.e. through
debconf
).
Maintainers that want to remove users in their postrm scripts are referred to the deluser
/deluser
--system
option.
Running programs with a user with limited privileges makes sure that any security issue will not be able to damage the full system. It also follows the principle of
least privilege. Also consider you can limit privileges in programs through other mechanisms besides running as non-root
. For more information, read the
http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/minimize-privileges.html chapter of the
Secure Programming for Linux and Unix HOWTO book.