# Copyright (c) 2017 The NetBSD Foundation, Inc. # All rights reserved. # # This code is derived from software contributed to The NetBSD Foundation # by Johnny C. Lam. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # NAME # usergroup_exists.subr -- check for the existence of users and groups # # SYNOPSIS # task_group_exists [] # task_user_exists [] # # DESCRIPTION # The task_group_exists function checks that a group exists on the # system, and also matches the group ID if it is given. # # The task_user_exists function checks that a user exists on the # system, and also matches the user ID if it is given. # # NOTES # These functions test for the presence of groups and users in a # portable manner by using chgrp(1) and chown(1) to change the # ownership of a temporary file and checking the return values. # # RETURN VALUES # The task_group_exists function has the following return values: # # 0 if exists, and has gid if given # 1 if neither nor exist # 2 if or exist but don't match # 3 if an error occurs # # The task_user_exists function has the following return values: # # 0 if exists, and has uid if given # 1 if neither nor exist # 2 if or exist but don't match # 3 if an error occurs # # ENVIRONMENT # The following variables are used if they are set: # # CHOWN The name or path to the chown(8) utility. # # LS The name or path to the ls(1) utility. # # RM The name or path to the rm(1) utility. # __task_usergroup_exists__="yes" __task_usergroup_exists_init__="_usergroup_exists_init" task_load cleanup task_load createfile task_load echo task_load maketemp task_group_exists() { : ${CHOWN:=chown} : ${LS:=ls} local group="$1"; shift local groupid="$1"; [ $# -eq 0 ] || shift [ -n "$group" ] || return 3 # Check using chown(1) to work properly in an NSS/NIS environment. __group_tmpdir__=$( task_maketemp -dq -t "pkgtasks.group_exists" ) || return 3 local testpath="$__group_tmpdir__/group_exists" task_createfile "$testpath" local result=0 # # Redirect standarrd error below because failing to chgrp(2) is # part of the test and not actually an error. # if ${CHOWN} ":$group" "$testpath" >/dev/null 2>&1; then # group exists if [ -n "$groupid" ]; then ${LS} -dln "$testpath" 2>/dev/null | ( read __ __ __ gid __; [ "$groupid" = "$gid" ] ) if [ $? -gt 0 ]; then # group exists but doesn't match groupid result=2 else # group exists and groupid exists and match result=0 fi else # group exists and groupid is not set result=0 fi elif [ -z "$groupid" ]; then # group doesn't exist and groupid is not set result=1 elif ${CHOWN} ":$groupid" "$testpath" >/dev/null 2>&1; then # group doesn't exist ${LS} -dl "$testpath" 2>/dev/null | ( read __ __ __ name __ # # If the ls(1) output shows a group name instead of the # raw GID, then the GID must exist and map to a valid # group name on the system. # [ "$groupid" != "$name" ] ) if [ $? -gt 0 ]; then # group doesn't exist, groupid doesn't exist result=1 else # group doesn't exist, groupid exists result=2 fi else # group doesn't exist and groupid doesn't exist result=1 fi _task_group_exists_cleanup return $result } task_user_exists() { : ${CHOWN:=chown} : ${LS:=ls} local user="$1"; shift local userid="$1"; [ $# -eq 0 ] || shift [ -n "$user" ] || return 3 # Check using chown(1) to work properly in an NSS/NIS environment. __user_tmpdir__=$( task_maketemp -dq -t "pkgtasks.user_exists" ) || return 3 local testpath="$__user_tmpdir__/user_exists" task_createfile "$testpath" local result=0 # # Redirect standarrd error below because failing to chown(2) is # part of the test and not actually an error. # if ${CHOWN} "$user" "$testpath" >/dev/null 2>&1; then # user exists if [ -n "$userid" ]; then ${LS} -dln "$testpath" 2>/dev/null | ( read __ __ uid __; [ "$userid" = "$uid" ] ) if [ $? -gt 0 ]; then # user exists but doesn't match userid result=2 else # user exists and userid exists and match result=0 fi else # user exists and userid is not set result=0 fi elif [ -z "$userid" ]; then # user doesn't exist and userid is not set result=1 elif ${CHOWN} "$userid" "$testpath" >/dev/null 2>&1; then # user doesn't exist ${LS} -dl "$testpath" 2>/dev/null | ( read __ __ name __ # # If the ls(1) output shows a username instead of the # raw UID, then the UID must exist and map to a valid # username on the system. # [ "$userid" != "$name" ] ) if [ $? -gt 0 ]; then # user doesn't exist, userid doesn't exist result=1 else # user doesn't exist, userid exists result=2 fi else # user doesn't exist and userid doesn't exist result=1 fi _task_user_exists_cleanup return $result } _task_group_exists_cleanup() { : ${RM:=rm} # Sanity check before blowing away $__group_tmpdir__. case $__group_tmpdir__ in /tmp/*) ${RM} -fr "$__group_tmpdir__" ;; "") : "skip empty tmpdir" ;; *) task_echo "!!! WARNING: usergroup_exists: Remove directory $__group_tmpdir__" ;; esac __group_tmpdir__= } _task_user_exists_cleanup() { : ${RM:=rm} # Sanity check before blowing away $__user_tmpdir__. case $__user_tmpdir__ in /tmp/*) ${RM} -fr "$__user_tmpdir__" ;; "") : "skip empty tmpdir" ;; *) task_echo "!!! WARNING: usergroup_exists: Remove directory $__user_tmpdir__" ;; esac __user_tmpdir__= } _usergroup_exists_init() { task_cleanup_add_hook \ _task_group_exists_cleanup \ _task_user_exists_cleanup } # Static variables for temporary directories that should be removed if an # error occurs. # __group_tmpdir__= __user_tmpdir__=