From 63283d403cea7f95b6f54223c6e9842424805fc0 Mon Sep 17 00:00:00 2001 From: "Andrew J. Hesford" Date: Thu, 10 Sep 2020 11:39:44 -0400 Subject: [PATCH] xbps-triggers: make system-accounts behave in altroots The system-accounts XBPS trigger originally used getent(1) to check for existing users or groups before attempting to create those entities defined by package templates. When invoked on an alternate root (for example, with `xbps-install -r /path/to/root`), this is incorrect because getent always looks for entries in host databases. There is no need to check for existing accounts before attempting to invoke useradd(8) or groupadd(8) because these programs will fail with a specific error code when the creation conflicts with an existing entity. The modified hook just attempts to create users and groups from the start, detecting the "already exists" return code and doing the right thing in that case (nothing further for groups, but modifying existing user entities). When the trigger acts on the system root, the useradd/groupadd/usermod invocations are aware of remote NIS or LDAP directories and should behave in these environments. In particular, the tools will not attempt to create entities defined in remote directories. In an alternate root, it isn't really appropriate to consider remote directories, because there is no guarantee that the alternate root will be using those directories. When the trigger acts on an alternate root, it uses the `--prefix|-P` argument to useradd/groupadd/usermod, which disregards NIS and LDAP and acts only on local files in the given prefix. Most importantly, this ensures that the hook will not attempt to create users or groups on the host when acting on an alternate root. Closes: #24812 --- srcpkgs/xbps-triggers/files/system-accounts | 168 +++++++++++--------- srcpkgs/xbps-triggers/template | 4 +- 2 files changed, 94 insertions(+), 78 deletions(-) diff --git a/srcpkgs/xbps-triggers/files/system-accounts b/srcpkgs/xbps-triggers/files/system-accounts index d48e9b7a2cf..f5028489995 100755 --- a/srcpkgs/xbps-triggers/files/system-accounts +++ b/srcpkgs/xbps-triggers/files/system-accounts @@ -16,29 +16,45 @@ UPDATE="$5" export PATH="usr/sbin:usr/bin:/usr/sbin:/usr/bin:/sbin:/bin" +# Determine whether useradd/groupadd/usermod need a prefix argument +if [ "$(readlink -f . 2>/dev/null || echo .)" != "/" ]; then + prefix="-P ." +else + prefix= +fi + +# show_acct_details [groups] +show_acct_details() { + echo " Account: $1" + echo " Description: '$2'" + echo " Homedir: '$3'" + echo " Shell: '$4'" + [ -n "$5" ] && echo " Additional groups: '$5'" +} + group_add() { - local _grname _gid use_gid + local _pretty_grname _grname _gid _prefix + + if ! command -v groupadd >/dev/null 2>&1; then + echo "WARNING: cannot create $1 system group (missing groupadd)" + echo "The following group must be created manually: $1" + return + fi _grname="${1%:*}" - _gid="${1#*:}" + _gid="${1##*:}" - if [ "${_gid}" != "${_grname}" ]; then - use_gid="gid ${_gid}" - fi + [ "${_grname}" = "${_gid}" ] && _gid= - if ! getent group ${_grname} >/dev/null; then - if [ -n "$use_gid" ]; then - groupadd -r ${_grname} -g ${_gid} >/dev/null 2>&1 - else - groupadd -r ${_grname} >/dev/null 2>&1 - fi - if [ $? -eq 0 ]; then - echo "Created ${_grname} ($use_gid) system group." - else - echo "Failed to create ${_grname} ($use_gid) system group!" - exit 1 - fi - fi + _pretty_grname="${_grname}${_gid:+ (gid: ${_gid})}" + + groupadd ${prefix} -r ${_grname} ${_gid:+-g ${_gid}} >/dev/null 2>&1 + + case $? in + 0) echo "Created ${_pretty_grname} system group." ;; + 9) ;; + *) echo "ERROR: failed to create system group ${_pretty_grname}!"; exit 1;; + esac } case "$ACTION" in @@ -46,108 +62,108 @@ targets) echo "post-install pre-remove" ;; run) - if [ -z "$system_accounts" -a -z "$system_groups" ]; then - exit 0 + [ -z "$system_accounts" -a -z "$system_groups" ] && exit 0 + + if command -v useradd >/dev/null 2>&1; then + USERADD="useradd ${prefix}" fi - if [ -x sbin/useradd -o -x bin/useradd ]; then - USERADD=1 - fi - if [ -x sbin/usermod -o -x bin/usermod ]; then - USERMOD=1 - fi - if [ -x sbin/groupadd -o -x bin/groupadd ]; then - GROUPADD=1 - fi - if [ -x bin/getent -o -x sbin/getent ]; then - GETENT=1 - fi - if [ -x bin/passwd -o -x sbin/passwd ]; then - PASSWD=1 + if command -v usermod >/dev/null 2>&1; then + USERMOD="usermod ${prefix}" fi case "$TARGET" in post-install) # System groups required by a package. for grp in ${system_groups}; do - if [ -z "$GROUPADD" -a -z "$GETENT" ]; then - echo "WARNING: cannot create ${grp} system group (missing groupadd/getent)" - echo "The following group must be created manually: $grp" - continue - fi group_add $grp done # System user/group required by a package. for acct in ${system_accounts}; do _uname="${acct%:*}" - _uid="${acct#*:}" + _uid="${acct##*:}" + + [ "${_uname}" = "${_uid}" ] && _uid= eval homedir="\$${_uname}_homedir" eval shell="\$${_uname}_shell" eval descr="\$${_uname}_descr" eval groups="\$${_uname}_groups" eval pgroup="\$${_uname}_pgroup" + [ -z "$homedir" ] && homedir="/var/empty" [ -z "$shell" ] && shell="/sbin/nologin" [ -z "$descr" ] && descr="${_uname} unprivileged user" [ -n "$groups" ] && user_groups="-G $groups" - [ "${_uid}" != "${_uname}" ] && + if [ -n "${_uid}" ]; then use_id="-u ${_uid} -g ${pgroup:-${_uid}}" + _pretty_uname="${_uname} (uid: ${_uid})" + else + use_id="-g ${pgroup:-${_uname}}" + _pretty_uname="${_uname}" + fi - if [ -z "$USERADD" -a -z "$GETENT" -a -z "$PASSWD" ]; then - echo "WARNING: cannot create ${acct} system user/group (missing useradd/getent/passwd)" + if [ -z "$USERADD" -o -z "$USERMOD" ]; then + echo "WARNING: cannot create ${_uname} system account (missing useradd or usermod)" echo "The following system account must be created:" - echo " Account: ${uname:-${_uid}} (uid: '${_uid}')" - echo " Description: '${descr}'" - echo " Homedir: '${homedir}'" - echo " Shell: '${shell}'" - echo " Additional groups: '${groups}'" + show_acct_details "${_pretty_uname}" "${descr}" "${homedir}" "${shell}" "${groups}" continue fi group_add ${pgroup:-${acct}} - if ! getent passwd ${_uname} >/dev/null; then - useradd -c "$descr" -d "$homedir" -s "$shell" ${user_groups} \ - ${pgroup:+-N} ${use_id:=-g ${pgroup:-${_uname}}} -r ${_uname} && \ - passwd -l ${_uname} >/dev/null 2>&1 - if [ $? -eq 0 ]; then - echo "Created ${_uname} (${_uid}) system user." - else - echo "Failed to create ${acct} system user!" + ${USERADD} -c "${descr}" -d "${homedir}" \ + ${use_id} ${pgroup:+-N} -s "${shell}" \ + ${user_groups} -r ${_uname} >/dev/null 2>&1 + + case $? in + 0) + echo "Created ${_pretty_uname} system user." + ${USERMOD} -L ${_uname} >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "WARNING: unable to lock password for ${_uname} system account" + fi + ;; + 9) + ${USERMOD} -c "${descr}" -d "${homedir}" \ + -s "${shell}" -g "${pgroup:-${_uname}}" \ + ${user_groups} ${_uname} >/dev/null 2>&1 + if [ $? -eq 0 ]; then + echo "Updated ${_uname} system user." + else + echo "WARNING: unable to modify ${_uname} system account" + echo "Please verify that account is compatible with these settings:" + show_acct_details "${_pretty_uname}" \ + "${descr}" "${homedir}" "${shell}" "${groups}" + continue + fi + ;; + *) + echo "ERROR: failed to create system user ${_pretty_uname}!" exit 1 - fi - else - if [ -z "$USERMOD" ]; then - echo "WARNING: cannot update ${acct} system user/group (missing usermod)" - continue - fi - usermod -c "${descr}" -d "${homedir}" -s "${shell}" ${user_groups} \ - -g "${pgroup:-${_uname}}" ${_uname} >/dev/null 2>&1 - if [ $? -eq 0 ]; then - echo "Updated ${_uname} (${_uid}) system user." - else - echo "Failed to update ${acct} system user!" - exit 1 - fi - fi + ;; + esac done ;; pre-remove) if [ "$UPDATE" = "no" ]; then for acct in ${system_accounts}; do _uname="${acct%:*}" - _uid="${acct#*:}" - comment="$(getent passwd "${_uname}" |cut -d: -f5 |head -n1) - for uninstalled package ${PKGNAME}" + + comment="$( (getent passwd "${_uname}" | cut -d: -f5 | head -n1) 2>/dev/null )" + comment="${comment:-unprivileged user} - for uninstalled package ${PKGNAME}" + if [ -z "$USERMOD" ]; then - echo "WARNING: cannot disable ${acct} system user/group (missing usermod)" + echo "WARNING: cannot disable ${_uname} system user (missing usermod)" continue fi - usermod -L -d /var/empty -s /bin/false -c "${comment}" ${_uname} >/dev/null 2>&1 + + ${USERMOD} -L -d /var/empty -s /bin/false \ + -c "${comment}" ${_uname} >/dev/null 2>&1 if [ $? -eq 0 ]; then - echo "Disabled ${_uname} (${_uid}) system user/group." + echo "Disabled ${_uname} system user." fi done fi diff --git a/srcpkgs/xbps-triggers/template b/srcpkgs/xbps-triggers/template index f316b269a7d..4131b479bef 100644 --- a/srcpkgs/xbps-triggers/template +++ b/srcpkgs/xbps-triggers/template @@ -1,7 +1,7 @@ # Template file for 'xbps-triggers' pkgname=xbps-triggers -version=0.116 -revision=2 +version=0.117 +revision=1 bootstrap=yes short_desc="XBPS triggers for Void Linux" maintainer="Enno Boland "