#!/usr/bin/env bash # # Initial script for Live operating system # This script are launching before starting init from linux-live script. # Current dir allways must be set to root (/) # All system path must be relative, except initrd dirs ENABLED=yes [[ ${ENABLED} == "yes" ]] || exit 0 DEBUGMODE=no PATH=.:/:/usr/bin:/usr/local/bin:/usr/local/sbin [[ -d /usr/lib/ublinux ]] && { unset ROOTFS; unset CMD_CHROOT; } || { ROOTFS='.'; CMD_CHROOT='chroot . '; } SOURCE=${ROOTFS}/usr/lib/ublinux/functions; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0 SOURCE=${ROOTFS}/usr/lib/ublinux/os-config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0 debug_mode "$0" "$@" SYSCONF="${ROOTFS}${SYSCONF}" SOURCE=${SYSCONF}/config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null SOURCE=${SYSCONF}/system; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null FILE_PASSWD="${ROOTFS}/etc/passwd" FILE_SHADOW="${ROOTFS}/etc/shadow" FILE_GROUP="${ROOTFS}/etc/group" FILE_GSHADOW="${ROOTFS}/etc/gshadow" FILE_ACCOUNTS_CREDENTIAL="/tmp/.ublinux_accounts_credential" # /etc/shadow file format # user:$6$.n.:17736:0:99999:7::: # [--] [----] [---] - [---] ---- # | | | | | |||+-----------> 9. Неиспользованный # | | | | | ||+------------> 8. Срок годности # | | | | | |+-------------> 7. Период бездействия # | | | | | +--------------> 6. Период предупреждения # | | | | +------------------> 5. Максимальный возраст пароля # | | | +----------------------> 4. Минимальный возраст пароля # | | +--------------------------> 3. Последнее изменение пароля # | +---------------------------------> 2. Зашифрованный пароль # +----------------------------------------> 1. Имя пользователя # Если поле пароля содержит первый символ звездочку (*), то пользователь не сможет войти по паролю, но сможет другим способом (например по ключу через ssh) # Если поле пароля содержит первый символ восклицательный знак (!), то пользователь вообще не сможет войти, даже по ключу # Алгоритмы хеширования пароля: # $1$ - MD5 # $2a$ - Blowfish # $2y$ - Eksblowfish # $5$ - SHA-256 # $6$ - SHA-512 # $y$ - yescrypt set_passwd(){ USER_NAME="${1}" USER_PASS="${2}" [[ -n ${USER_NAME} ]] || return 1 [[ -n ${USER_PASS} ]] || USER_PASS="x" ESC_USER_PASS=$(sed 's/[^a-zA-Z0-9,._@%-]/\\&/g' <<< "${USER_PASS}") EPOCH_DAY=$(( $(date +%s)/(60*60*24) )) # (60*60*24)=18400 second on day USER_FROM_SHADOW=$(grep "^${USER_NAME}:" "${FILE_SHADOW}") if [[ -z ${USER_FROM_SHADOW} ]]; then echo "${USER_NAME}:${USER_PASS}:${EPOCH_DAY}:0:99999:7:::" >> "${FILE_SHADOW}" elif [[ ! ${USER_FROM_SHADOW} =~ ^"${USER_NAME}:${USER_PASS}:" ]]; then sed -E "s/^${USER_NAME}:[^:]+:[0-9]+:/${USER_NAME}:${ESC_USER_PASS}:${EPOCH_DAY}:/" -i "${FILE_SHADOW}" sed -E "s/${USER_NAME}:[!]*:/${USER_NAME}:\!\*:/" -i "${FILE_SHADOW}" #sed /^${USER_NAME}:/d -i "${FILE_SHADOW}" #echo "${USER_NAME}:${USER_PASS}:${EPOCH_DAY}:0:99999:7:::" >> "${FILE_SHADOW}" fi } copy_skel_home(){ local SELECT_USERNAME="${1}" [[ -n ${SELECT_USERNAME} ]] || return 1 cp -af ${ROOTFS}/etc/skel ${ROOTFS}/home/"${SELECT_USERNAME}" #rsync -rlpt --ignore-existing etc/skel/ home/"${SELECT_USERNAME}" ${CMD_CHROOT} ${ROOTFS}/usr/bin/chown -R "${SELECT_USERNAME}":"${SELECT_USERNAME}" ${ROOTFS}/home/"${SELECT_USERNAME}" ${CMD_CHROOT} ${ROOTFS}/usr/bin/chmod -fR u+rw,g-rwx,o-rwx ${ROOTFS}/home/"${SELECT_USERNAME}"/ ${CMD_CHROOT} ${ROOTFS}/usr/bin/chmod -f 700 ${ROOTFS}/home/"${SELECT_USERNAME}" } exec_get_users(){ if [[ -f ${FILE_ACCOUNTS_CREDENTIAL} ]]; then DEFAULTPASSWD=$(grep "DEFAULTPASSWD=" "${FILE_ACCOUNTS_CREDENTIAL}" | tail -1 | tr -d "\'\""); DEFAULTPASSWD=${DEFAULTPASSWD#*=} DEFAULTROOTPASSWD=$(grep "DEFAULTROOTPASSWD=" "${FILE_ACCOUNTS_CREDENTIAL}" | tail -1 | tr -d "\'\""); DEFAULTROOTPASSWD=${DEFAULTROOTPASSWD#*=} NEEDEDUSERS=$(grep "NEEDEDUSERS=" "${FILE_ACCOUNTS_CREDENTIAL}" | tail -1 | tr -d "\'\""); NEEDEDUSERS=${NEEDEDUSERS#*=} rm -f "${FILE_ACCOUNTS_CREDENTIAL}" fi [[ -z ${NEEDEDUSERS} ]] && NEEDEDUSERS="${DEFAULTUSER}:${ADMUID}:${DEFAULTPASSWD}:Администратор" [[ -z $(cmdline_value users) ]] || NEEDEDUSERS=$(cmdline_value users) [[ ${NOSECUREROOTPASSWD} == ${DEFAULTROOTPASSWD} ]] && ADDADM=yes } exec_add_groups(){ # Создаём группы из ${DEFAULTGROUP},${ADMGROUPS},${USERGROUPS} c ID из /usr/share/ublinux-sysusers/*.sysusers while read SELECT_GROUP; do FINDGROUP=$(grep -i "g\s*${SELECT_GROUP}\s*[[:digit:]]\s*" ${ROOTFS}/usr/share/ublinux-sysusers/*.sysusers 2>/dev/null | xargs) IFS=" " read -r NULL FINDGROUP_NAME FINDGROUP_ID NULL <<< "${FINDGROUP}" if [[ -n ${FINDGROUP} ]]; then if grep -q "^${SELECT_GROUP}:.*:${FINDGROUP_ID}:" ${FILE_GROUP} 2>/dev/null; then # Группа найдена, имя и id совпадают, пропускаем добавление continue elif grep -q "^${SELECT_GROUP}:" ${FILE_GROUP} 2>/dev/null; then # Группа найдена, имя и id несовпадают, удаляем группу echo "WARNING: the group '${SELECT_GROUP}' has an id different from the template /usr/share/ublinux-sysusers/*.sysusers and the id will be changed to '${SELECT_GROUP}:${FINDGROUP_ID}'" ${CMD_CHROOT} ${ROOTFS}/usr/bin/groupdel -f ${SELECT_GROUP} fi fi [[ ${FINDGROUP_ID} == "" ]] || [[ ${FINDGROUP_ID} == "-" ]] || FINDGROUP_ID="-g ${FINDGROUP_ID}" ${CMD_CHROOT} ${ROOTFS}/usr/bin/groupadd -f ${FINDGROUP_ID} ${SELECT_GROUP} done < <(tr ",;" "\n" <<< "${DEFAULTGROUP},${ADMGROUPS},${USERGROUPS}") } exec_neededusers(){ while read SELECT_USER; do IFS=: read -r SELECT_USERNAME SELECT_UID SELECT_PASS SELECT_GECOS NULL <<< "${SELECT_USER}" [[ ${SELECT_PASS} == "x" ]] && SELECT_PASS="${DEFAULTPASSWD}" ADDGROUPS="${USERGROUPS}" [[ ${SELECT_UID} == ${ADMUID} && ${ADDADM} == "yes" ]] && ADDGROUPS="${USERGROUPS},${ADMGROUPS}" # Создаём пользователя if ! grep -q ^"${SELECT_USERNAME}": ${FILE_PASSWD} 2>/dev/null; then [[ -n ${SELECT_UID} ]] && ARG_SELECT_UID="-u ${SELECT_UID}" || unset ARG_SELECT_UID [[ -n ${DEFAULTGROUP} ]] && ARG_DEFAULTGROUP="-G ${DEFAULTGROUP}" || unset ARG_DEFAULTGROUP if [[ -x ${ROOTFS}/usr/bin/useradd ]]; then [[ -n ${SELECT_GECOS} ]] && ARG_SELECT_GECOS="-c ${SELECT_GECOS}" || unset ARG_SELECT_GECOS ${CMD_CHROOT} ${ROOTFS}/usr/bin/useradd -M ${ARG_DEFAULTGROUP} ${ARG_SELECT_UID} ${ARG_SELECT_GECOS} ${SELECT_USERNAME} #>/dev/null 2>&1 elif [[ -x ${ROOTFS}/usr/bin/adduser ]]; then [[ -n ${SELECT_GECOS} ]] && ARG_SELECT_GECOS="-g ${SELECT_GECOS}" || unset ARG_SELECT_GECOS ${CMD_CHROOT} ${ROOTFS}/usr/bin/adduser -D -H "${ARG_DEFAULTGROUP}" "${ARG_SELECT_UID}" "${ARG_SELECT_GECOS}" "${SELECT_USERNAME}" >/dev/null 2>&1 fi fi # Добавляем пользователя в группу USER_GROUPS="${ADDGROUPS//;/,}" ${CMD_CHROOT} ${ROOTFS}/usr/bin/usermod -a -G ${USER_GROUPS%*,} ${SELECT_USERNAME} #>/dev/null 2>&1 # Задаём пароль пользователю set_passwd "${SELECT_USERNAME}" "${SELECT_PASS}" # Создаём домашний каталог if [[ ! -d ${ROOTFS}/home/"${SELECT_USERNAME}" ]]; then copy_skel_home "${SELECT_USERNAME}" elif [[ ${UPDATEHOME,,} == @(yes|y|enable) ]]; then copy_skel_home "${SELECT_USERNAME}" fi done < <(tr ",;" "\n" <<< "${NEEDEDUSERS}") } exec_set_root_pass(){ if [[ -n ${DEFAULTROOTPASSWD} && ! ${DEFAULTROOTPASSWD} =~ @(no|none|disable) ]]; then set_passwd root "${DEFAULTROOTPASSWD}" fi } exec_firststart(){ # Autodetect firstboot # Если пароли по умолчанию, то firstboot grep -q "^root:${DEFAULTROOTPASSWD}:" ${ROOTFS}/etc/shadow \ && grep -q "^$(cat ${ROOTFS}/etc/passwd | grep ".*:x:${ADMUID}:" | cut -d: -f1):${DEFAULTPASSWD}:" ${ROOTFS}/etc/shadow && touch ${SYSCONF}/firststart \ || rm -f ${SYSCONF}/firststart } exec_verify_passwd(){ if [[ -x ${ROOTFS}/usr/bin/pwck ]]; then #yes | ${ROOTFS}/usr/bin/pwck --root ${PWD} > /dev/null ${ROOTFS}/usr/bin/pwck -s --root ${PWD} fi if [[ -x ${ROOTFS}/usr/bin/grpck ]]; then #yes | ${ROOTFS}/usr/bin/grpck --root ${PWD} > /dev/null ${ROOTFS}/usr/bin/grpck -s --root ${PWD} fi } ################ ##### MAIN ##### ################ exec_get_users exec_add_groups exec_neededusers $@ exec_set_root_pass exec_firststart exec_verify_passwd