#!/bin/bash

# BT-82842
shopt -s expand_aliases
alias GTEXT="gettext astra-domain-functions"

pam_remove() {
#===============================================================================
# Функция отключает заданный профайл ПAM-модуля, не удаляя его конфигурации из /usr/share/pam-configs
# Профайлы ПАМ-модулей используются для автоматического изменения поведения любых приложений, использующих ПАМ-модули.
#
# Почему: пока не найден нормальный инструмент для неинтерактивного отключения профайлов в скриптах.
# Так, команда pam-auth-update --remove <имя профайла> до конца его не отключает.
# А команда pam-auth-update <без параметров> позволяет вкл/выкл профайлы только интерактивном режиме.
# 
# В базе данных debconf (файл /var/cache/debconf/config.dat) для пакета libpam-runtime указаны следующие профайлы:
#  profile_names = cracklib, kiosk2, tally, unix, systemd, mkhomedir, gnome-keyring
#  profiles = Cracklib password strength checking, Kiosk2 user confinement, pam tally, Unix authentication, Register user sessions in the systemd control group hierarchy, Create home directory on login, GNOME Keyring Daemon - Login keyring management
# Входные параметры:
# $@ - имя отключаемого профайла ПАМ-модуля:
#      Может быть из списка: cracklib, kiosk2, tally, unix, systemd, mkhomedir, gnome-keyring
#===============================================================================
  RM_PROFILE_NAME=${@}
  # 1. Определить список наименований всех имеющихся профайлов ПАМ-модулей
  local IFS=", " ALL_NAMES_STR=$(grep --max-count=1 -A 10 "Template: libpam-runtime/profiles" /var/cache/debconf/config.dat | grep --max-count=1 "profile_names =")
  ALL_NAMES_LST=( ${ALL_NAMES_STR#*= } )

  # 2. В этом списке определить номер отключаемого профайла
  for ((i=0; i<=${#ALL_NAMES_LST[@]}; i++)) do

    if [[ "${ALL_NAMES_LST[$i]}" == "$RM_PROFILE_NAME" ]]; then
      EXIST=true
      RM_PROFILE_NUMBER=$i
      break
    fi
  done

  if [[ $EXIST != true ]]; then
    printf "$(GTEXT "Внимание! Имя профайла \'%s\' не найдено в настроках пакета libpam-runtime базы данных debconf или не задано в параметре вызова функции %s")\n" $RM_PROFILE_NAME $0
    printf "$(GTEXT "Проверьте имя отключаемого профайла ПАМ-модуля. Возможно, оно есть в списке: cracklib, kiosk2, tally, unix, systemd, mkhomedir, gnome-keyring")\n"
    printf "$(GTEXT "Профайл \'%s\' отключен не будет.")\n" $RM_PROFILE_NAME
    return 0
  fi

  # 3. Определить список имеющихся профайлов (не имен, а самих профайлов)
  local IFS=" " ALL_PROFILES_STR=$(grep --max-count=1 -A 10 "Template: libpam-runtime/profiles" /var/cache/debconf/config.dat | grep --max-count=1 "profiles =")
  local IFS="," ALL_PROFILES_LST=( ${ALL_PROFILES_STR#*= } )

  # 4. Определить отключаемый профайл
  for ((i=0; i<=${#ALL_PROFILES_LST[@]}; i++)) do
    if [[ "$i" == "$RM_PROFILE_NUMBER" ]]; then
      RM_PROFILE=${ALL_PROFILES_LST[$i]}
    fi
  done

  # 5. Создать в /tmp скрипт редактора конфигурации пакета
  cat << EOS | tee /tmp/pam_remove.sh >>/tmp/pam_remove.log
#!/bin/sh
# List pam modules to enable
# Параметры:
# $1 - отключаемый профайл ПАМ-модуля 
# $2 - имя скрипта едитора (вида /tmp/filemPZshk)

  if [ -n "\$1" ] && [ -f "\$2" ]; then
    EDITOR_STR=\$(grep -E "^libpam-runtime" \$2)
    EDITOR_STR=\${EDITOR_STR/\$1/&} # Удалить из строки название отключаемого модуля
    EDITOR_STR=\${EDITOR_STR/&, /} # Удалить из строки лишнюю запятую в начале и середине списка
    EDITOR_STR=\${EDITOR_STR/, &/} # Удалить из строки лишнюю запятую в конце списка
    cat << EOF | tee \$2
# PAM profiles to enable:
\$EDITOR_STR
EOF
fi
EOS
  chmod +x /tmp/pam_remove.sh

  # 6. Запустить этот скрипт:
  EDITOR_ENV="/tmp/pam_remove.sh \"${RM_PROFILE# }\""
  EDITOR=$EDITOR_ENV DEBIAN_FRONTEND=editor pam-auth-update &>>/tmp/pam_remove.log

  if [[ "$?" == "0" ]]; then
    printf "$(GTEXT "Профайл \'%s\' отключен")\n" ${RM_PROFILE}
  else
    printf "$(GTEXT "Возникли проблемы с отключением профайла \'%s\'. См. /tmp/pam_remove.log")\n" ${RM_PROFILE}
  fi
}
#pam_remove $1

find_timedaemon() {
#===============================================================================
# Определение используемого службы синхронизации времени
#  Входные параметры:
#   $LOG_FILE - путь к файлу журнала (глоб. переменная)
#  Выходные параметры:
#   $NTPD - имя демена синхронизации точного времени (глоб.переменная)
#===============================================================================
  if dpkg --status ntpsec 2>>$LOG_FILE | grep Status | grep installed &>> $LOG_FILE; then
    NTPD=ntpsec
  elif dpkg --status ntp 2>>$LOG_FILE | grep Status | grep installed &>> $LOG_FILE; then
    NTPD=ntp
  fi
  if dpkg --status chrony 2>>$LOG_FILE | grep Status | grep installed &>> $LOG_FILE; then
    NTPD=chrony
    return
  fi
  if [[ ! $NTPD ]]; then
    NTPD=systemd-timesyncd
  fi
  echo "$(GTEXT "Найден:") $NTPD" | tee -a $LOG_FILE
}

get_ntp_srv() {
#===============================================================================
# Определение списка серверов точного времени
#  Входные параметры:
#   $LOG_FILE - путь к файлу журнала (глоб. переменная)
#   $1 - имя домена (обязательный)
#   $2 - строка, разделенных через запятую доменных имен серверов т.вр. (из опции -n)
#   $DC - реалм/контроллер домена, переданный вызывающим скриптом (глоб. перем.)
#  Выходные параметры:
#   $NTP_SRV - массив серверов т.вр. (глоб. переменная)
#===============================================================================
  local IFS=' '$'\t'$'\n' # BT-61031
  if [[ -n "$2" ]]; then
    printf "$(GTEXT "получено из опции -n: %s")\n" $2
    NTP_SRV=(${2//,/ }) # BT-61031
  else
    # поиск серверов точного времени
    srv_out=$(host -t SRV _ntp._udp.${1}) # Сначала поисх ntp-серверов
    if [[ ${srv_out[@]} =~ "no servers" ]]; then 
        echo "$srv_out" >> $LOG_FILE
        echo "$(GTEXT "Сервер DNS недоступен")" | tee -a $LOG_FILE
    else
      # BT-86455 
      if [[ ${srv_out[@]} =~ "is an alias for" ]]; then
          alias=$(host -t SRV _ntp.udp.${1} | awk '{print $6}')
          srv_out=$(host -t SRV _ntp.udp.${alias})
      fi
      # -------
      if [[ ${srv_out[@]} =~ "not found" ]]; then # Потом поиск ldap-серверов
        echo " $(GTEXT "_ntp._udp записей не найдено")" | tee -a $LOG_FILE
        srv_out=$(host -t SRV _ldap._tcp.${1})
        if [[ ${srv_out[@]} =~ "not found" ]]; then
          echo " $(GTEXT "_ldap._tcp записей не найдено")" | tee -a $LOG_FILE
        else
          echo " $(GTEXT "получено из SRV записей _ldap._tcp:")" | tee -a $LOG_FILE
          srv_lst=$(host -t SRV _ldap._tcp.${1} | awk '{print $8}')
          echo " ${srv_lst[@]}" | tee -a $LOG_FILE
        fi
      else
        echo " $(GTEXT "получено из SRV записей _ntp._udp:")" | tee -a $LOG_FILE
        srv_lst=$(host -t SRV _ntp._udp.${1} | awk '{print $8}')
        echo " ${srv_lst[@]}" | tee -a $LOG_FILE
      fi
      for srv in ${srv_lst[@]} ; do 
        srv_str="${srv_str}${srv%.} "
      done
    fi
    if [[ -z "$srv_str" && -n "$DC" ]]; then
      printf "$(GTEXT "будет использоваться контроллер домена %s")\n" $DC | tee -a $LOG_FILE
      srv_str=$DC
    fi
    NTP_SRV=($srv_str) 
  fi
}

config_timedaemon() {
#===============================================================================
# Настройка службы синхронизации времени
#  Входные параметры:
#   $NTPD - имя демона (ntp, chrony, systemd-timesycd) (глоб. переменная)
#   $LOG_FILE - путь к файлу журнала (глоб. переменная)
#   $NTP_SRV - массив серверов точного времени
#  Выходные параметры: код возврата
#===============================================================================
if [[ -z "$NTP_SRV" ]]; then
  echo " $(GTEXT "Ошибка! Серверы точного времени не заданы")" | tee -a $LOG_FILE
  return 1
fi
case $NTPD in
  chrony)
    sed -i.`date +%G-%m-%d_%H-%M` -re 's/^\s*((peer|pool|server)\s.*)/# \1/' /etc/chrony/chrony.conf
    for srv in ${NTP_SRV[@]}; do
      echo "server ${srv} iburst" >> /etc/chrony/chrony.conf
    done
    ;;
  ntp)
    sed -i.`date +%G-%m-%d_%H-%M` -re 's/^\s*((peer|pool|server)\s.*)/# \1/' /etc/ntp.conf
    for srv in ${NTP_SRV[@]}; do
      echo "server ${srv} iburst" >> /etc/ntp.conf
    done
    ;;
  ntpsec)
    sed -i.`date +%G-%m-%d_%H-%M` -re 's/^\s*((peer|pool|server)\s.*)/# \1/' /etc/ntpsec/ntp.conf
    for srv in ${NTP_SRV[@]}; do
      echo "server ${srv} iburst" >> /etc/ntpsec/ntp.conf
    done
    sed -e 's/tos minclock 4 minsane 3/tos minclock 4 minsane 1/g' -i /etc/ntpsec/ntp.conf
    ;;
  systemd-timesyncd)
    mkdir -p /usr/lib/systemd/timesyncd.conf.d
    echo -e "[Time]\nNTP=${NTP_SRV[@]}\nRootDistanceMaxSec=30\n" > /usr/lib/systemd/timesyncd.conf.d/astra-domain-client.conf
    ;;
  * ) printf "$(GTEXT "Ошибка! Неизвестный сервис точного времени %s")\n" $NTPD | tee -a $LOG_FILE
    return 1
    ;;
esac

}

start_timedaemon() {
#===============================================================================
#                      Запуск службы синхронизации времени
#  Входные параметры:
#    $NTPD - имя демона (ntp, chrony, systemd-timesycd) (глоб. переменная)
#    $LOG_FILE - путь к файлу журнала (глоб. переменная)
#  Выходные параметры: код возврата
#===============================================================================
  if systemctl is-active $NTPD &>> $LOG_FILE ; then
    systemctl stop $NTPD &>> $LOG_FILE
    echo " systemctl stop  $NTPD -> $?" &>> $LOG_FILE
  fi
  systemctl unmask $NTPD &>> $LOG_FILE
  echo " systemctl unmask $NTPD -> $?" >> $LOG_FILE
  if ! systemctl is-enabled $NTPD &>> $LOG_FILE ; then
    systemctl enable $NTPD &>> $LOG_FILE
    echo " systemctl enable $NTPD -> $?" &>> $LOG_FILE
  fi
  systemctl start $NTPD &>> $LOG_FILE
  echo " systemctl start $NTPD -> $?" &>> $LOG_FILE
}


wait_timedaemon_sync() {
#===============================================================================
# Ожидание синхронизации демона точного времени
#  Входные параметры:
#   $1 - время (в сек.) ожидания, пока произойдет синхронизация т.вр. с сервером
#   $LOG_FILE - путь к файлу журнала (глоб. переменная)
#  Выходные параметры: код возврата
#===============================================================================
  local count=$1
  for (( i=1; i <= $count; i++ )); do
    if timedatectl show | grep -q "NTPSynchronized=no"; then
      echo -n "." | tee -a $LOG_FILE
      sleep 1
    else
      timedatectl show | grep "NTPSynchronized=yes" &>> $LOG_FILE
      echo $(GTEXT "- успешно") | tee -a $LOG_FILE
      return 0
    fi
  done
  echo $(GTEXT "- синхронизации не дождались") | tee -a $LOG_FILE
  return 1
}

set_ntp() {
#================================================================================
#                         Настройка синхронизации времени
# Входные параметры:
#   $1 - имя домена
#   $2 - имена серверов т.вр.
#================================================================================
  [[ $1 =~ ^[a-z.,0-9]*$ ]] && local domain=$1 || echo $(GTEXT "Ошибка имени домена")
  [[ $2 =~ ^[a-z.,0-9]*$ ]] && local ntp=$2 || echo $(GTEXT "Ошибка имен серверов т.вр.")

  echo " $(GTEXT "Определение сервиса синхронизации времени...")" | tee -a $LOG_FILE
  find_timedaemon
  echo " $NTPD" | tee -a $LOG_FILE

  echo " $(GTEXT "Определение серверов точного времени...")" | tee -a $LOG_FILE
  get_ntp_srv $domain $ntp 

  if [[ ${#NTP_SRV[@]} == 0 ]]; then 
    echo " $(GTEXT "- не успешно.")" | tee -a $LOG_FILE
    echo $(GTEXT "Сервер<ы> точного времени не задан<ы> и не определен<ы>") | tee -a $LOG_FILE
    exit 1 
  else
    ntp_str="${NTP_SRV[@]}" # Список серверов в виде строки, разделенных пробелом
  fi
  echo " $(GTEXT "Cинхронизация системного времени  с контроллером домена...")" | tee -a $LOG_FILE
  if [[ "$(systemctl is-active $NTPD)" == "active" ]]; then # BT-64975
      systemctl stop $NTPD
  fi
  ntpdate $ntp_str &>> $LOG_FILE
  [[ $? -eq 0 ]] && echo $(GTEXT "- успешно") || echo $(GTEXT "- не успешно") | tee -a $LOG_FILE

  echo " $(GTEXT "Настройка сервиса синхронизации времени") ${NTPD} ... " | tee -a $LOG_FILE
  config_timedaemon
  if [[ $? -eq 0 ]] ; then 
    echo " $(GTEXT "- успешно")" | tee -a $LOG_FILE
    echo " $(GTEXT "Запуск сервиса синхронизации времени") ${NTPD} ... " | tee -a $LOG_FILE
    start_timedaemon
    [[ $? -eq 0 ]] && echo $(GTEXT "- успешно") || echo $(GTEXT "- не успешно") 

    echo " $(GTEXT "Ожидание синхронизации времени") ${NTPD} ..." | tee -a $LOG_FILE
    #wait_timedaemon_sync 10 - нет особой необходимости и замедляет работу скрипта
    [[ $? -eq 0 ]] && echo $(GTEXT "- успешно") || echo $(GTEXT "- не успешно")
  else
    echo " $(GTEXT "- не успешно")"
    echo " $(GTEXT "Функционирование сервиса точного времени остается без изменений")" | tee -a $LOG_FILE
  fi
}

enable_fnames() { 
#===============================================================================
# Включить полные имена пользователей
#===============================================================================
    if ! grep -qE "^use_fully_qualified_names.*=.*" /etc/sssd/sssd.conf; then
        sed -e "/\[domain.*\]/a use_fully_qualified_names = True" -i "/etc/sssd/sssd.conf"
    else
        sed -e "s/.*use_fully_qualified_names[[:space:]]*=[[:space:]]*False.*/use_fully_qualified_names = True/" -i "/etc/sssd/sssd.conf"
    fi
}

disable_fnames() { 
#===============================================================================
# Отключить полные имена пользователей
#===============================================================================
    if ! grep -qE "^use_fully_qualified_names.*=.*" /etc/sssd/sssd.conf; then
        sed -e "/\[domain.*\]/a use_fully_qualified_names = False" -i "/etc/sssd/sssd.conf"
    else
        sed -e "s/.*use_fully_qualified_names[[:space:]]*=[[:space:]]*True.*/use_fully_qualified_names = False/" -i "/etc/sssd/sssd.conf"
    fi
}

sssd_clear_cache() {
#===============================================================================
# Очистить кэш sssd
#===============================================================================
    systemctl stop sssd
    rm /var/lib/sss/db/*
    systemctl start sssd
}

get_ip() {
#===============================================================================
# Функция определяет IP-адрес c которого происходит подключение к домену
# Результат выполнения возвращается в глобальную переменную ip
#===============================================================================
    declare -a res
    declare -a eth
    local IFS=$'\n' # BT-61031 add 'local'
    res=($(ip a | awk '{if( $0 ~ "^[0-9]+:") {
                    if( $2 == "lo:") {
                        nic=""
                        next
                    }
                    gsub( /:/, "", $2)
                    nic=$2
                    next
                } else {
                    if( $1 == "inet" ) {
                        if( nic == "" ) { next }
                        gsub( /\/.*/, "", $2)
                        printf ("%s %s ", nic, $2)
                        if( $0 ~ ".*[[:space:]]+dynamic[[:space:]]+.*") {
                            print "динамический/dynamic"
                        } else {
                            print "статический/static"
                        }
                        next
                    }
                }
            }')) 
#' # for mcedit
    if [[ ${#res[*]} > 1 ]] ; then
        echo " $(GTEXT "Обнаружено несколько сетевых интерфейсов:")"
        echo -e "\t# NIC\tIP\t\tType"
        for (( i=0; i<${#res[*]}; i++)) ; do
            echo -e "\t$((i+1)) ${res[i]}"
        done
        read -p $(GTEXT "Выберите номер сетевого интерфейса:") i
    else
        if [[ ${#res[*]} == 1 ]] ; then
            echo "$(GTEXT "Обнаружен только один сетевой интерфейс.")"
            i=1
        fi
    fi
    if [[ "$i" =~ ([1-9][[:digit:]]*) ]] ; then
        local IFS=$' ' # BT-61031 add 'local'
        eth=(${res[i-1]})
        ip=${eth[1]}
    fi

    if [ -z "$ip" ] ; then
        echo " $(GTEXT "Сетевой интерфейс не выбран.")"
        if [[ "$uninstall" != "true" ]] ; then
            exit 1
        fi
    fi
    printf "$(GTEXT "Будет использован сетевой интерфейс \"%s\", имеющий %s IP-адрес %s")\n" ${eth[0]} ${eth[2]} $ip
}
