#!/usr/bin/bash
exec 1> /var/log/crypto-cmc/auth.log 2>&1
set -x
# Скрипт настройки профиля authselect для crypto-policy
# Примеры запуска:
# auth_apply.sh -e - восстановить конфигурацию без указания auth профиля
# auth_apply.sh -p tmp/ - считать что конфигурационные файлы authselect лежат в каталоге tmp
# auth_apply.sh -p /tmp -t /tmpconf - аналигично предыдущему, но еще не вызывать authselect
#                                и считать, что сгенерированный конфиг лежит в каталоге tmpconf

CONF_PATH=/etc/authselect/
AUTH_SEL_BAK=authselect.conf.policy
AUTH_CONFIG=authselect.conf
EMPTY=0
TEST=""
AUTH_BACKUP_NAME="auth_saved_profile"
USE_PATCH="$CONF_PATH/autheslect.patch"

function set_gost
{
    /usr/bin/sed --in-place --follow-symlinks 's/sha512\|\byescrypt\b/gost_yescrypt/' /etc/pam.d/system-auth
    /usr/bin/sed --in-place --follow-symlinks 's/sha512\|\byescrypt\b/gost_yescrypt/' /etc/pam.d/password-auth

}

function set_no_gost
{
    /usr/bin/sed --in-place --follow-symlinks 's/sha512\|gost_yescrypt/yescrypt/' /etc/pam.d/system-auth
    /usr/bin/sed --in-place --follow-symlinks 's/sha512\|gost_yescrypt/yescrypt/' /etc/pam.d/password-auth
}

function get_auth_options
{
    /usr/bin/cat /etc/crypto-policies/back-ends/auth.config | tr '\n' ' '
}

function save_restored_profile
{
    if [ ! -e /etc/authselect/custom/restored ];then
        /usr/bin/authselect create-profile restored
        [ -e /etc/pam.d/fingerprint-auth ] && /usr/bin/cp -f /etc/pam.d/fingerprint-auth /etc/authselect/custom/restored/
        [ -e /etc/pam.d/password-auth ] && /usr/bin/cp -f /etc/pam.d/password-auth /etc/authselect/custom/restored/
        [ -e /etc/pam.d/postlogin ] && /usr/bin/cp -f /etc/pam.d/postlogin /etc/authselect/custom/restored/
        [ -e /etc/pam.d/smartcard-auth ] && /usr/bin/cp -f /etc/pam.d/smartcard-auth /etc/authselect/custom/restored/
        [ -e /etc/pam.d/system-auth ] && /usr/bin/cp -f /etc/pam.d/system-auth /etc/authselect/custom/restored/
        [ -e /etc/authselect/user-nsswitch.conf ] && /usr/bin/cp -f /etc/authselect/user-nsswitch.conf /etc/authselect/custom/restored/nsswitch.conf
    fi
}

while getopts ':et:p:h' VAL ; do
    case $VAL in
        e ) EMPTY=1 ;;
        p ) CONF_PATH="$OPTARG" ;;
        t ) TEST="$OPTARG" ;;
        : ) 
            echo "Необходим параметр - путь к опции $OPTARG"
            exit 255 
        ;;
        * ) 
            echo "Неизвестный параметр $OPTARG"
            exit 255
        ;;
    esac
done
shift $((OPTIND -1))

# Если заданный путь к кинфигурации authselect заканчивается на /
# то удалим этот символ
LAST_SYMBOL=${CONF_PATH: -1}
if [ "$LAST_SYMBOL" = "/" ];then
    CONF_PATH=${CONF_PATH%?}
fi
LAST_SYMBOL=${TEST: -1}
if [ "$LAST_SYMBOL" = "/" ];then
    TEST=${TEST%?}
fi

if [ -z "$TEST" ];then
    POLICY_CONFIG=/etc/crypto-policies/back-ends/auth.config
else
    POLICY_CONFIG="$TEST/auth.config"
    if [[ "$POLICY_CONFIG" == "/*" ]];then
        :
    else
        CUR_DIR=$(pwd)
        POLICY_CONFIG="$CUR_DIR/$POLICY_CONFIG"
    fi
fi

PATH_TO_AUTH_SEL_BAK="$CONF_PATH/$AUTH_SEL_BAK"
PATH_TO_AUTH_CONFIG="$CONF_PATH/$AUTH_CONFIG"

# Дополнительная проверка, файл authselect.conf не должен быть пустым
# или соедржать слово empty--data, иначе это признак empty
if [ -e "$PATH_TO_AUTH_CONFIG" ];then
    AUTH_CONF_CONT=$(/usr/bin/cat "$POLICY_CONFIG" | /usr/bin/xargs)
    if [ -z "$AUTH_CONF_CONT" -o "$AUTH_CONF_CONT" = "empty--data" ];then
        EMPTY=1
    fi
else
    EMPTY=2
fi

# Проверим, нужно ли накладывать патч. Установлено ли это конфигурацией
NEED_PATCH=0
if [ -e "$POLICY_CONFIG" ];then
   RES=$(cat "$POLICY_CONFIG")
   if [ "$RES" = "patch" ];then
       NEED_PATCH=1
   fi
fi

# Если задан параметр empty, это значит, что применяется профиль
# без настройки для authselect, в этом случае нужно восстановить
# старый заданный профиль
# TODO: возможно даже воспользоватьс командой
# authselect backup-restore auth_saved_profile
# данный снимок создается при профиля через crypto-policy
if [ "$EMPTY" = "1" ];then
# Если есть файл authselect.patch, значит профиль был пропатчен,
# а не установлен через профиль
    if [ -e "$USE_PATCH" ];then
        set_no_gost
        /usr/bin/mv -f "$USE_PATCH" "$USE_PATCH.removed"
    else
        if [ -e "$PATH_TO_AUTH_SEL_BAK" ];then
# Только root может восстанавливать конфигурацию из резервной копии
# дабыизбежать подлога и восстановления файла, созданного пользователем
            OWNER_UID=$(/usr/bin/stat -c "%u" "$PATH_TO_AUTH_SEL_BAK")
            if [ "$OWNER_UID" = "0" ];then
                /usr/bin/mv -f "$PATH_TO_AUTH_SEL_BAK" "$PATH_TO_AUTH_CONFIG"
            fi
            AUTH_CONT=$(cat "$PATH_TO_AUTH_CONFIG")
# Есди файл настроек authselect пустой после восстановления
# значит он создан ранее скриптом и его нужно убрать
            if [ -z "$AUTH_CONT" ];then
                /usr/bin/mv -f "$PATH_TO_AUTH_CONFIG" "$PATH_TO_AUTH_CONFIG.removed"
            fi
        else
            /usr/bin/mv -f "$PATH_TO_AUTH_CONFIG" "$PATH_TO_AUTH_CONFIG.removed"
        fi
        if [ -e "$PATH_TO_AUTH_CONFIG" ];then
            /usr/bin/authselect apply-changes
        else
            if [ -e /var/lib/authselect/backups/"$AUTH_BACKUP_NAME" ];then
                /usr/bin/authselect backup-restore "$AUTH_BACKUP_NAME"
            else
                if [ -e /etc/authselect/custom/resored ];then
                    /usr/bin/authselect select custom/restored --force
                fi
            fi
        fi
    fi
    exit 0
fi

# Здесь проверяется куда указывает симлинк(если создан) конфигурационного файла
# если он смотрит на policy конфигурационный файл, то ничего не делаем, т.к. все уже сделано до нас
if [ "$EMPTY" = "2" ];then
    if [ "$NEED_PATCH" = "1" ];then
        set_gost
        touch "$USE_PATCH"
    else
        OPTS_FOR_EXECUTE=$(get_auth_options)
        if [ -n "$OPTS_FOR_EXECUTE" ];then
            save_restored_profile
            if [ -e /var/lib/authselect/backups/"$AUTH_BACKUP_NAME" ];then
                /usr/bin/authselect select $OPTS_FOR_EXECUTE --force
            else
                /usr/bin/authselect select $OPTS_FOR_EXECUTE --force --backup=auth_saved_profile
            fi
            #/usr/bin/ln -sf "$POLICY_CONFIG" "$PATH_TO_AUTH_CONFIG"
            /usr/bin/cp -f "$POLICY_CONFIG" "$PATH_TO_AUTH_CONFIG"
            /usr/bin/authselect apply-changes
            touch "$PATH_TO_AUTH_SEL_BAK"
        fi
    fi
else
    if [ "$NEED_PATCH" = "1" ];then
        set_gost
        touch "$USE_PATCH"
    else
# Если не найден файл маркер, то создается файл бэкапа для authselect
# а так же создается файл маркер
        if [ ! -e "$PATH_TO_AUTH_SEL_BAK" ];then
            /usr/bin/mv -f "$PATH_TO_AUTH_CONFIG" "$PATH_TO_AUTH_SEL_BAK"
            EMPTY_AUTH=$(/usr/bin/cat "$PATH_TO_AUTH_CONFIG")
            if [ -n "$EMPTY_AUTH" ];then
                if [ ! -e /var/lib/authselect/backups/"$AUTH_BACKUP_NAME" ];then
                    /usr/bin/authselect apply-changes --backup="$AUTH_BACKUP_NAME"
                fi
            fi
        fi

        #LINK_VALUE=$(/usr/bin/readlink "$PATH_TO_AUTH_CONFIG")
        #if [ "$LINK_VALUE" != "$POLICY_CONFIG" ];then
        #    #/usr/bin/ln -sf "$POLICY_CONFIG" "$PATH_TO_AUTH_CONFIG"
        #fi
        /usr/bin/cp -f "$POLICY_CONFIG" "$PATH_TO_AUTH_CONFIG"
        /usr/bin/authselect apply-changes
    fi
fi

exit 0