104e50ef7SAaron LI#!/bin/sh 204e50ef7SAaron LI# 304e50ef7SAaron LI# Copyright (c) 2020 The DragonFly Project. 404e50ef7SAaron LI# All rights reserved. 504e50ef7SAaron LI# 604e50ef7SAaron LI# Redistribution and use in source and binary forms, with or without 704e50ef7SAaron LI# modification, are permitted provided that the following conditions 804e50ef7SAaron LI# are met: 904e50ef7SAaron LI# 1004e50ef7SAaron LI# 1. Redistributions of source code must retain the above copyright 1104e50ef7SAaron LI# notice, this list of conditions and the following disclaimer. 1204e50ef7SAaron LI# 2. Redistributions in binary form must reproduce the above copyright 1304e50ef7SAaron LI# notice, this list of conditions and the following disclaimer in 1404e50ef7SAaron LI# the documentation and/or other materials provided with the 1504e50ef7SAaron LI# distribution. 1604e50ef7SAaron LI# 3. Neither the name of The DragonFly Project nor the names of its 1704e50ef7SAaron LI# contributors may be used to endorse or promote products derived 1804e50ef7SAaron LI# from this software without specific, prior written permission. 1904e50ef7SAaron LI# 2004e50ef7SAaron LI# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2104e50ef7SAaron LI# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2204e50ef7SAaron LI# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2304e50ef7SAaron LI# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 2404e50ef7SAaron LI# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2504e50ef7SAaron LI# INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 2604e50ef7SAaron LI# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2704e50ef7SAaron LI# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2804e50ef7SAaron LI# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2904e50ef7SAaron LI# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 3004e50ef7SAaron LI# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3104e50ef7SAaron LI# SUCH DAMAGE. 3204e50ef7SAaron LI# 3304e50ef7SAaron LI 3404e50ef7SAaron LI# Exit if any untested command fails in non-interactive mode 3504e50ef7SAaron LIset -e 3604e50ef7SAaron LI# Exit when an undefined variable is referenced 3704e50ef7SAaron LIset -u 3804e50ef7SAaron LI 391bc30ec4SAaron LI# Usage: add_users <etcdir> <master.passwd> <group> 4004e50ef7SAaron LI# 4104e50ef7SAaron LI# Add new users and groups in <etcdir> according to the given <master.passwd> 4204e50ef7SAaron LI# and <group> files. 4304e50ef7SAaron LI# 4404e50ef7SAaron LI# NOTE: Existing users and groups are not modified. 4504e50ef7SAaron LI# 4604e50ef7SAaron LIadd_users() { 4704e50ef7SAaron LI local etcdir="$1" 4804e50ef7SAaron LI local fpasswd="$2" 4904e50ef7SAaron LI local fgroup="$3" 50*37c7698aSAaron LI local _name _pw _uid _gid _gids _group item 5104e50ef7SAaron LI local _class _change _expire _gecos _home _shell _members 5204e50ef7SAaron LI 5304e50ef7SAaron LI echo "===> Adding new users ..." 5404e50ef7SAaron LI _gids="" 5504e50ef7SAaron LI while IFS=':' read -r _name _pw _uid _gid _class \ 5604e50ef7SAaron LI _change _expire _gecos _home _shell; do 5704e50ef7SAaron LI case ${_name} in 5804e50ef7SAaron LI '' | \#*) continue ;; 5904e50ef7SAaron LI esac 6004e50ef7SAaron LI if pw -V ${etcdir} usershow ${_name} -q >/dev/null; then 6104e50ef7SAaron LI continue 6204e50ef7SAaron LI fi 6304e50ef7SAaron LI echo " * ${_name}: ${_uid}, ${_gid}, ${_gecos}, ${_home}, ${_shell}" 64*37c7698aSAaron LI 65*37c7698aSAaron LI _group=${_gid} 66*37c7698aSAaron LI if ! pw -V ${etcdir} groupshow ${_gid} -q >/dev/null; then 67*37c7698aSAaron LI # Primary group doesn't exist yet, so first assign to 68*37c7698aSAaron LI # the 'nogroup' group, and then adjust it after 69*37c7698aSAaron LI # creating the group. 70*37c7698aSAaron LI _group="nogroup" 71*37c7698aSAaron LI _gids="${_gids} ${_name}:${_gid}" 72*37c7698aSAaron LI fi 73*37c7698aSAaron LI 7454af8c6bSAaron LI # NOTE: The shell field can be empty (e.g., user 'toor') and 7554af8c6bSAaron LI # would default to '/bin/sh'. 7654af8c6bSAaron LI # NOTE: Use '-o' option to allow to create user of duplicate 7754af8c6bSAaron LI # UID, which is required by the 'toor' user (same UID 7854af8c6bSAaron LI # as 'root'). 7904e50ef7SAaron LI pw -V ${etcdir} useradd ${_name} \ 8054af8c6bSAaron LI -o \ 8104e50ef7SAaron LI -u ${_uid} \ 82*37c7698aSAaron LI -g ${_group} \ 8354af8c6bSAaron LI -d "${_home}" \ 8454af8c6bSAaron LI -s "${_shell}" \ 8504e50ef7SAaron LI -L "${_class}" \ 8604e50ef7SAaron LI -c "${_gecos}" 8704e50ef7SAaron LI done < ${fpasswd} 8804e50ef7SAaron LI 8904e50ef7SAaron LI echo "===> Adding new groups ..." 9004e50ef7SAaron LI while IFS=':' read -r _name _pw _gid _members; do 9104e50ef7SAaron LI case ${_name} in 9204e50ef7SAaron LI '' | \#*) continue ;; 9304e50ef7SAaron LI esac 9404e50ef7SAaron LI if pw -V ${etcdir} groupshow ${_name} -q >/dev/null; then 9504e50ef7SAaron LI continue 9604e50ef7SAaron LI fi 9704e50ef7SAaron LI echo " * ${_name}: ${_gid}, ${_members}" 9804e50ef7SAaron LI pw -V ${etcdir} groupadd ${_name} -g ${_gid} -M "${_members}" 9904e50ef7SAaron LI done < ${fgroup} 10004e50ef7SAaron LI 10104e50ef7SAaron LI echo "===> Adjusting the group of new users ..." 10204e50ef7SAaron LI for item in ${_gids}; do 10304e50ef7SAaron LI _name=${item%:*} 10404e50ef7SAaron LI _gid=${item#*:} 10504e50ef7SAaron LI echo " * ${_name}: ${_gid}" 10604e50ef7SAaron LI pw -V ${etcdir} usermod ${_name} -g ${_gid} 10704e50ef7SAaron LI done 10804e50ef7SAaron LI} 10904e50ef7SAaron LI 1101bc30ec4SAaron LI# Usage: update_user <user> <etcdir> <master.passwd> 1111bc30ec4SAaron LI# 1121bc30ec4SAaron LI# Update an existing user in <etcdir> according to the given <master.passwd>. 1131bc30ec4SAaron LI# 1141bc30ec4SAaron LIupdate_user() { 1151bc30ec4SAaron LI local user="$1" 1161bc30ec4SAaron LI local etcdir="$2" 1171bc30ec4SAaron LI local fpasswd="$3" 1181bc30ec4SAaron LI local _line 1191bc30ec4SAaron LI local _name _pw _uid _gid _class _change _expire _gecos _home _shell 1201bc30ec4SAaron LI 1211bc30ec4SAaron LI _line=$(grep "^${user}:" ${fpasswd}) || true 1221bc30ec4SAaron LI if [ -z "${_line}" ]; then 1231bc30ec4SAaron LI echo "ERROR: no such user '${user}'" >&2 1241bc30ec4SAaron LI exit 1 1251bc30ec4SAaron LI fi 1261bc30ec4SAaron LI 1271bc30ec4SAaron LI echo "${_line}" | { 1281bc30ec4SAaron LI IFS=':' read -r _name _pw _uid _gid _class \ 1291bc30ec4SAaron LI _change _expire _gecos _home _shell 1301bc30ec4SAaron LI echo "===> Updating user ${user} ..." 1311bc30ec4SAaron LI echo " * ${_name}: ${_uid}, ${_gid}, ${_gecos}, ${_home}, ${_shell}" 1321bc30ec4SAaron LI pw -V ${etcdir} usermod ${user} \ 1331bc30ec4SAaron LI -u ${_uid} \ 1341bc30ec4SAaron LI -g ${_gid} \ 1351bc30ec4SAaron LI -d ${_home} \ 1361bc30ec4SAaron LI -s ${_shell} \ 1371bc30ec4SAaron LI -L "${_class}" \ 1381bc30ec4SAaron LI -c "${_gecos}" 1391bc30ec4SAaron LI } 1401bc30ec4SAaron LI} 1411bc30ec4SAaron LI 1421bc30ec4SAaron LI# Usage: update_group <group> <etcdir> <group> 1431bc30ec4SAaron LI# 1441bc30ec4SAaron LI# Update an existing group in <etcdir> according to the given <group> file. 1451bc30ec4SAaron LI# 1461bc30ec4SAaron LIupdate_group() { 1471bc30ec4SAaron LI local group="$1" 1481bc30ec4SAaron LI local etcdir="$2" 1491bc30ec4SAaron LI local fgroup="$3" 1501bc30ec4SAaron LI local _line 1511bc30ec4SAaron LI local _name _pw _gid _members 1521bc30ec4SAaron LI 1531bc30ec4SAaron LI _line=$(grep "^${group}:" ${fgroup}) || true 1541bc30ec4SAaron LI if [ -z "${_line}" ]; then 1551bc30ec4SAaron LI echo "ERROR: no such group '${group}'" >&2 1561bc30ec4SAaron LI exit 1 1571bc30ec4SAaron LI fi 1581bc30ec4SAaron LI 1591bc30ec4SAaron LI echo "${_line}" | { 1601bc30ec4SAaron LI IFS=':' read -r _name _pw _gid _members 1611bc30ec4SAaron LI echo "===> Updating group ${group} ..." 1621bc30ec4SAaron LI echo " * ${_name}: ${_gid}, ${_members}" 1631bc30ec4SAaron LI pw -V ${etcdir} groupmod ${group} -g ${_gid} -M "${_members}" 1641bc30ec4SAaron LI } 1651bc30ec4SAaron LI} 1661bc30ec4SAaron LI 16704e50ef7SAaron LIusage() { 16804e50ef7SAaron LI cat > /dev/stderr << _EOF_ 1691bc30ec4SAaron LIAdd/update users and groups. 17004e50ef7SAaron LI 17104e50ef7SAaron LIUsage: ${0##*/} -d <etc-dir> -g <group-file> -p <master.passwd-file> 1721bc30ec4SAaron LI [-G group] [-U user] 17304e50ef7SAaron LI 17404e50ef7SAaron LI_EOF_ 17504e50ef7SAaron LI 17604e50ef7SAaron LI exit 1 17704e50ef7SAaron LI} 17804e50ef7SAaron LI 17904e50ef7SAaron LIETC_DIR= 18004e50ef7SAaron LIGROUP_FILE= 18104e50ef7SAaron LIPASSWD_FILE= 1821bc30ec4SAaron LIUPDATE_GROUP= 1831bc30ec4SAaron LIUPDATE_USER= 18404e50ef7SAaron LI 1851bc30ec4SAaron LIwhile getopts :d:G:g:hp:U: opt; do 18604e50ef7SAaron LI case ${opt} in 18704e50ef7SAaron LI d) 18804e50ef7SAaron LI ETC_DIR=${OPTARG} 18904e50ef7SAaron LI ;; 1901bc30ec4SAaron LI G) 1911bc30ec4SAaron LI UPDATE_GROUP=${OPTARG} 1921bc30ec4SAaron LI ;; 19304e50ef7SAaron LI g) 19404e50ef7SAaron LI GROUP_FILE=${OPTARG} 19504e50ef7SAaron LI ;; 19604e50ef7SAaron LI p) 19704e50ef7SAaron LI PASSWD_FILE=${OPTARG} 19804e50ef7SAaron LI ;; 1991bc30ec4SAaron LI U) 2001bc30ec4SAaron LI UPDATE_USER=${OPTARG} 2011bc30ec4SAaron LI ;; 20204e50ef7SAaron LI h | \? | :) 20304e50ef7SAaron LI usage 20404e50ef7SAaron LI ;; 20504e50ef7SAaron LI esac 20604e50ef7SAaron LIdone 20704e50ef7SAaron LI 20804e50ef7SAaron LIshift $((OPTIND - 1)) 20904e50ef7SAaron LI[ $# -eq 0 ] || usage 21004e50ef7SAaron LI[ -n "${ETC_DIR}" ] || usage 21104e50ef7SAaron LI[ -n "${GROUP_FILE}" ] || usage 21204e50ef7SAaron LI[ -n "${PASSWD_FILE}" ] || usage 21304e50ef7SAaron LI 2141bc30ec4SAaron LIif [ -z "${UPDATE_GROUP}" ] && [ -z "${UPDATE_USER}" ]; then 21504e50ef7SAaron LI add_users "${ETC_DIR}" "${PASSWD_FILE}" "${GROUP_FILE}" 2161bc30ec4SAaron LIelse 2171bc30ec4SAaron LI if [ -n "${UPDATE_GROUP}" ]; then 2181bc30ec4SAaron LI update_group "${UPDATE_GROUP}" "${ETC_DIR}" "${GROUP_FILE}" 2191bc30ec4SAaron LI fi 2201bc30ec4SAaron LI if [ -n "${UPDATE_USER}" ]; then 2211bc30ec4SAaron LI update_user "${UPDATE_USER}" "${ETC_DIR}" "${PASSWD_FILE}" 2221bc30ec4SAaron LI fi 2231bc30ec4SAaron LIfi 224