#!/usr/bin/env bash
#
#   Script name: ubdomain-client
#   Description: Script for configure domain client
#   GitLab: https://gitlab.ublinux.ru/
#   Author: Dmitry Razumov asmeron@ublinux.ru
#   Contributors: asmeron@ublinux.ru
#
#   Copyright (c) 2021-2024 UBLinux Development Team <support@ublinux.ru>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.

VERSION_SCRIPT=1.22

# Exit Immediately if a command fails
#set -o errexit

#################################
###   :::   C O L O R S   :::   #
#################################
set_color(){
#http://abload.de/img/bash-color-chartmxjbp.png
    export BBC=$'\e[1;34m'
    export RBC=$'\e[1;31m'
    export WBC=$'\e[1m'
    export EC=$'\e[0m'

    export txtblk='\033[0;30m' # Black - Regular
    export txtred='\033[0;31m' # Red			# prompt: error color
    export txtgrn='\033[0;32m' # Green			# prompt: success color
    export txtylw='\033[0;33m' # Yellow			# prompt: waring color
    export txtblu='\033[0;34m' # Blue			
    export txtpur='\033[0;35m' # Purple
    export txtcyn='\033[0;36m' # Cyan			# prompt: info color
    export txtwht='\033[0;37m' # White
    export bldblk='\033[1;30m' # Black - Bold
    export bldred='\033[1;31m' # Red			# prompt: bold error color
    export bldgrn='\033[1;32m' # Green			# prompt: bold success color
    export bldylw="\033[1;33m" # Yellow                 # prompt: bold warning color
    export bldblu='\033[1;34m' # Blue				
    export bldpur='\033[1;35m' # Purple
    export bldcyn="\033[1;36m" # Cyan                   # prompt: bold info color
    export bldwht="\033[1;37m" # White			# prompt: bold default color

    export undblk='\033[4;30m' # Black - Underline
    export undred='\033[4;31m' # Red

    export bakblk='\033[40m'   # Black - Background
    export bakred='\033[41m'   # Red
    export badgrn='\033[42m'   # Green

    export txtrst='\033[0m'    # Text Reset		# prompt: default color
}


#######################################
###   :::   F U N C T I O N S   :::   #
#######################################

check_root(){
    [[ ${DEBUG} == @(yes|y|1) ]] && return 0
    if [[ ${EUID:-$(id -u)} > 0 ]]; then
	case ${1} in
	    -w  | --warning)	  shift; prompt -w "Please run as root! ${@}" && return 1 ;;
	    -wq | --warning-quit) shift; prompt -wq "Please run as root!" ;;
    	    *) 			  prompt -wq "Please run as root!" ;;
        esac
    fi
}

# Check command availability
has_command(){ command -v $1 &> /dev/null; }

# echo like ... with flag type and display message colors
prompt(){
    if [[ -z ${QUIET} ]]; then
	case ${1} in
	    -s  | --success)	  shift; echo -e "${txtgrn}${@}${txtrst}" ;;				# print success message
	    -sq | --success-quit) shift; echo -e "${txtgrn}${@}${txtrst}"; exit 1 ;;			# print success message
	    -e  | --error)   	  shift; echo -e "${txtred}ERROR:${@}${txtrst}" ;;			# print error message
	    -eq | --error-quit)   shift; echo -e "${txtred}ERROR:${@}${txtrst}"; exit 1 ;;		# print error message
	    -w  | --warning) 	  shift; echo -e "${txtylw}WARNING:${bldwht}${@}${txtrst}" ;;		# print warning message
	    -wq | --warning-quit) shift; echo -e "${txtylw}WARNING:${bldwht}${@}${txtrst}"; exit 1 ;;	# print warning message
	    -i  | --info)    	  shift; echo -e "${txtcyn}INFO:${txtcyn}${@}${txtrst}" ;;		# print info message
	    -iq | --info-quit)    shift; echo -e "${txtcyn}INFO:${txtcyn}${@}${txtrst}"; exit 1 ;;	# print info message
	    *)    		  echo -e "$@" ;;							# print all message
	esac
    else
	case ${1} in
	    -s  | --success)	  true ;;	# print success message
	    -sq | --success-quit) exit 1 ;;	# print success message
	    -e  | --error)   	  true ;;	# print error message
	    -eq | --error-quit)   exit 1 ;;	# print error message
	    -w  | --warning) 	  true ;;	# print warning message
	    -wq | --warning-quit) exit 1 ;;	# print warning message
	    -i  | --info)    	  true ;;	# print info message
	    -iq | --info-quit)    exit 1 ;;	# print info message
	    *)    		  true ;;	# print all message
	esac
    fi
}


usage(){
    printf "%s  %s\n" "${0##*/}" "version: ${VERSION_SCRIPT}"
    cat <<EOF
Configure connect to domain

Usage:  ${0##*/} {COMMAND} [OPTIONS...] ...
	${0##*/} list
	${0##*/} discover [--dns DNS] [--domain DOMAIN] [--domain_server DOMAIN_SERVER]
	${0##*/} join     [--dns DNS] [--user USER] [--password PASSWORD] --domain DOMAIN
	${0##*/} leave    [--dns DNS] [--user USER] [--password PASSWORD] [--domain DOMAIN]
	${0##*/} configure [--dns DNS]
	${0##*/} unconfigure
	${0##*/}
	${0##*/} permit [-ax] [-R realm] user ...
	${0##*/} deny --all [-R realm]

Commands:
  list 			List of known domains | Список известных доменов
  discover 		Discover available domain | Обнаружить домен
  join	   		Register a machine in a domain | Зарегистрировать машину в домене
  leave			Leave the machine from the domain | Вывести машину из домена
  configure		Only configure PAM, SSSD, KRD5, NSS | Провести только конфигурирование PAM, SSSD, KRD5, NSS
  unconfigure		Just clear the configuration PAM, SSSD, KRD5, NSS | Только удалить настройки и вернуться к настройкам по умолчанию PAM, SSSD, KRD5, NSS
Meta Commands:
  help          	Show this help

Options:
  -n, --noconfigure	Do not configure PAM, SSSD, KRD5, NSS
  -u, --user=<USER>	Пользователь домена, имеющие права на регистрацию машин
			A domain user who has rights to register machines
  -p, --password  	Password a user
  -d, --domain=<DOMAIN>	Domain name | Имя домена
      --domain_server=<SERVER>
    			Сервер Kerberos/AD домена, отключит автопоиск сервера и задаст статический
    			Domain Kerberos/AD server
        %SERVER_NAME%	Полное имя сервера, которое знает DNS
    	%SERVER_IP%	Адресс IP сервера
      --domain_client=<CLIENT>
    			Клиент для подключения к домену
      * realmd_sssd	Клиент sssd
        realmd_winbind	Клиент winbind
        samba		Клиент samba
        none		Отключить клиента или автоматически определить
      --dns=<DNS>	DNS сервер который опознает имя сервере Kerberos/AD, необходимо если в сети по DHCP получен другой домен и не определяет автопоиск
    			DNS server that knows about the server Kerberos/AD
  -a, --authpam_opt=<PROFILE_OPT1>,<PROFILE_OPTn>
			Дополнительные опции профиля аудентификации
			Возможные опции:
	wth-altfiles with-ecryptfs with-faillock with-files-access-provider with-files-domain with-pamaccess with-silent-lastlog with-sudo with-systemd-homed with-time without-nullok
        with-fingerprint with-pam-u2f with-pam-u2f-2fa without-nullokwithout-pam-u2f-nouserok.
        with-smartcard with-smartcard-lock-on-removal with-smartcard-required.
        with-mdns4 with-mdns6 with-mkhomedir with-mkhomedir-simple with-nispwquality
  -q, --quiet		Quiet mode
  -h, --help		Show this help
  -V, --version		Show package version

Examples:
${0##*/} discover --domain ubdc.ru
${0##*/} join --user Администратор --password my_password --domain ubdc.ru
${0##*/} leave --user Администратор --password my_password --domain ubdc.ru
EOF
    exit 0
}
arguments(){
# Pre-process options to:
# - expand -xyz into -x -y -z
# - expand --longopt=arg into --longopt arg
    local ARGV=()
    local END_OF_OPT=
    while [[ $# -gt 0 ]]; do
	arg="$1"; shift
	case "${END_OF_OPT}${arg}" in
	    --) ARGV+=("$arg"); END_OF_OPT=1 ;;
	    --*=*)ARGV+=("${arg%%=*}" "${arg#*=}") ;;
	    --*) ARGV+=("$arg") ;;
	    -*) for i in $(seq 2 ${#arg}); do ARGV+=("-${arg:i-1:1}"); done ;;
	    *) ARGV+=("$arg") ;;
	esac
    done
# Apply pre-processed options
    set -- "${ARGV[@]}"
# Parse options
    local END_OF_OPT=
    local POSITIONAL_ARGS=()
    [[ -z $@ ]] && usage && exit 0
    while [[ $# -gt 0 ]]; do
	case "${END_OF_OPT}${1}" in
	    list)		  COMMAND=list ;;
	    discover)		  COMMAND=discover ;;
	    join)		  COMMAND=join ;;
	    leave)		  COMMAND=leave ;;
	    configure)	  	  COMMAND=configure ;;
	    unconfigure)	  COMMAND=unconfigure ;;
	    -n | --noconfigure)	  NOCONFIGURE=1 ;;
	    -u | --user)	  shift; ARG_MUSER=$1 ;;
	    -p | --password)	  shift; ARG_MPASSWORD=$1 ;;
	    -d | --domain)	  shift; ARG_DOMAIN=$1 ;;
		 --domain_client) shift; ARG_DOMAIN[client]=$1 ;;
		 --domain_server) shift; ARG_DOMAIN[server]=$1 ;;
	    -a | --authpam_opt)	  shift; ARG_AUTHPAM_OPT=$1 ;;
		 --dns)		  shift; ARG_DOMAIN[dns]=$1 ;;
	    -h | --help | help)	  usage ;;
	    -q | --quiet)     	  QUIET=1; QUIET_ARG="-q" ;;
	    -V | --version)	  echo "Version: ${VERSION_SCRIPT}"; exit 0 ;;
	    --stdin)        	  READ_STDIN=1 ;;
	    --)             	  END_OF_OPT=1 ;;
	    -*|--*)         	  prompt -w "Unrecognized argument, skiped: $1" >&2  ;;
	    *)              	  POSITIONAL_ARGS+=("$1") ;;
	esac
	shift
    done
# Restore positional parameters
    set -- "${POSITIONAL_ARGS[@]}"
    [[ -z ${ARG_MUSER} && -n ${DOMAIN[admanger]} ]] && ARG_MUSER=${DOMAIN[admanger]%%:*}
    [[ -z ${ARG_MPASSWORD} && -n ${DOMAIN[admanger]} ]] && ARG_MPASSWORD=$(base64 -d <<< ${DOMAIN[admanger]##*:})
    [[ -z ${ARG_DOMAIN} && -n ${DOMAIN} ]] && ARG_DOMAIN=${DOMAIN}
    [[ -z ${ARG_DOMAIN[client]} && -n ${DOMAIN[client]} ]] && ARG_DOMAIN[client]=${DOMAIN[client]}
    [[ -z ${ARG_DOMAIN[server]} && -n ${DOMAIN[server]} ]] && ARG_DOMAIN[server]=${DOMAIN[server]}
    [[ -z ${ARG_DOMAIN[dns]} && -n ${DOMAIN[dns]} ]] && ARG_DOMAIN[dns]=${DOMAIN[dns]}

    [[ -z ${MUSER} && ${LANG} =~ "ru_RU.UTF-8" ]] && MUSER="Администратор"
    [[ -z ${MUSER} && ${LANG} =~ "en_US.UTF-8" ]] && MUSER="Administrator"
    [[ -z ${MUSER} ]] && MUSER="Administrator"
    [[ -z ${ARG_DOMAIN[hostname]} ]] && ARG_DOMAIN[hostname]=${HOSTNAME}
    [[ -z ${ARG_DOMAIN[client]} ]] && ARG_DOMAIN[client]="realmd_sssd"
}
set_authpam(){
    if [[ ${ARG_DOMAIN[client]} == "realmd_sssd" ]]; then
	[[ $(ubconfig --raw get system AUTHPAM) == "sssd" ]] || ubconfig set system AUTHPAM="sssd"
	[[ -n ${ARG_AUTHPAM_OPT} ]] && ubconfig set system "AUTHPAM[sssd]=${ARG_AUTHPAM_OPT}"
    elif [[ ${ARG_DOMAIN[client]} == "realmd_winbind" ]]; then
	[[ $(ubconfig --raw get system AUTHPAM) == "winbind" ]] || ubconfig set system AUTHPAM="winbind"
	[[ -n ${ARG_AUTHPAM_OPT} ]] && ubconfig set system "AUTHPAM[winbind]=${ARG_AUTHPAM_OPT}"
    elif [[ ${ARG_DOMAIN[client]} == "samba" ]]; then
	[[ $(ubconfig --raw get system AUTHPAM) == "winbind" ]] || ubconfig set system AUTHPAM="winbind"
	[[ -n ${ARG_AUTHPAM_OPT} ]] && ubconfig set system "AUTHPAM[winbind]=${ARG_AUTHPAM_OPT}"
    fi
}
set_dns(){
    if ! nmcli --get-values ip4.dns device show | grep -q "${ARG_DOMAIN[dns]}" &>/dev/null; then
    	for CONNECTION_UUID in $(nmcli --get-values uuid connection show); do
    	    nmcli connection modify uuid ${CONNECTION_UUID} +ipv4.dns "${ARG_DOMAIN[dns]}" \
    	        || prompt -w "Failed assign DNS ${ARG_DOMAIN[dns]} to connection uuid ${CONNECTION_UUID}"
    	    nmcli connection up uuid ${CONNECTION_UUID} \
    	        || prompt -w "Failed restart connection uuid ${CONNECTION_UUID}"
    	    ubconfig --noexecute set network DOMAIN[dns]="${ARG_DOMAIN[dns]}"
    	done
    fi
}
prepare_config(){
    if [[ ${ARG_DOMAIN[client]} == "realmd_sssd" ]]; then
	[[ ${ARG_DOMAIN} == "" ]] && prompt -qe " DOMAIN not set, unable to configure system"
	[[ ${ARG_DOMAIN[server]} == "" ]] && prompt -qe " DOMAIN[server] not set, unable to configure system"
	local DOMAIN_UP=${ARG_DOMAIN^^}
	local DOMAIN_SERVER_UP=${ARG_DOMAIN[server]^^}
	local KRB5_REALM=
	IFS= read -rd '' KRB5_REALM <<EOF
  ${DOMAIN_UP} = {
      kdc = ${DOMAIN_SERVER_UP}
      admin_server = ${DOMAIN_SERVER_UP}
      default_domain = ${DOMAIN_UP}
   }
   ${DOMAIN_UP%%.*} = {
      kdc = ${DOMAIN_SERVER_UP}
      admin_server = ${DOMAIN_SERVER_UP}
      default_domain = ${DOMAIN_UP}
   }
EOF
	local KRB5_DOMAIN_REALMS=
	IFS= read -rd '' KRB5_DOMAIN_REALMS <<EOF
   .${ARG_DOMAIN} = ${DOMAIN_UP}
    ${ARG_DOMAIN} = ${DOMAIN_UP}
EOF
	local REALMD_CONF=
	IFS= read -rd '' REALMD_CONF <<EOF
[active-directory]
os-name = ${OS_NAME}
os-version = ${OS_VERSION}
EOF

	cp -f "${FILE_KRB5}" "${PATH_CONF_KRB5}/"
	cp -f "${FILE_REALM_SNIPPET_001}" "${PATH_CONF_SSSD}/"
	cp -f "${FILE_REALM_SNIPPET_010}" "${PATH_CONF_SSSD}/"
	sed "s/\(ad_hostname =\).*/\1 ${ARG_DOMAIN[hostname]}/" -i "${PATH_CONF_SSSD}/${FILE_REALM_SNIPPET_010##*/}"
	sed "s/\[domain\/\]/\[domain\/${ARG_DOMAIN}\]/" -i "${PATH_CONF_SSSD}/${FILE_REALM_SNIPPET_010##*/}"
	sed "/\[realms\]/a\ ${KRB5_REALM//$'\n'/\\n}" -i "${PATH_CONF_KRB5}/${FILE_KRB5##*/}"
	sed "/\[domain_realm\]/a\ ${KRB5_DOMAIN_REALMS//$'\n'/\\n}" -i "${PATH_CONF_KRB5}/${FILE_KRB5##*/}"
	#sed '/\[realms\]/r'<(echo "${KRB5_REALM}") -i "${PATH_CONF_KRB5}/${FILE_KRB5##*/}"
	#sed '/\[domain_realm\]/r'<(echo "${KRB5_DOMAIN_REALMS}") -i "${PATH_CONF_KRB5}/${FILE_KRB5##*/}"

	[[ ${#REALM_SSSD[@]} -ne 0 ]] && for SELECT_REALM_SSSD in "${!REALM_SSSD[@]}"; do
	    SELECT_REALM_SSSD_PARAM=${SELECT_REALM_SSSD%%:*}
	    SELECT_REALM_SSSD_SECTION=${SELECT_REALM_SSSD#*:}
	    [[ ${SELECT_REALM_SSSD_PARAM} == ${SELECT_REALM_SSSD_SECTION} ]] && SELECT_REALM_SSSD_SECTION="domain/${ARG_DOMAIN}"
	    [[ $(cat ${PATH_CONF_SSSD}/${FILE_REALM_SNIPPET_010##*/}) =~ (^|$'\n')"[${SELECT_REALM_SSSD_SECTION}]"($|$'\n') ]] \
	    || echo -e "\n[${SELECT_REALM_SSSD_SECTION}]" >> "${PATH_CONF_SSSD}/${FILE_REALM_SNIPPET_010##*/}"
	    ESC_SELECT_REALM_SSSD_SECTION="$(sed 's/[^a-zA-Z0-9,_@%]/\\&/g' <<< "[${SELECT_REALM_SSSD_SECTION}]")"
 	    sed -E "/^${SELECT_REALM_SSSD_PARAM} = /d" -i "${PATH_CONF_SSSD}/${FILE_REALM_SNIPPET_010##*/}"
	    sed -E "/${ESC_SELECT_REALM_SSSD_SECTION}/a ${SELECT_REALM_SSSD_PARAM} = ${REALM_SSSD[${SELECT_REALM_SSSD}]}" -i "${PATH_CONF_SSSD}/${FILE_REALM_SNIPPET_010##*/}"
	done
    elif [[ ${ARG_DOMAIN[client]} == "realmd_winbind" ]]; then
	true
    elif [[ ${ARG_DOMAIN[client]} == "samba" ]]; then
	true
    fi
    echo "${REALMD_CONF}" > "${PATH_CONF_KRB5}/realmd.conf"
}
prepare_permit_config(){
    [[ -f ${PATH_CONF_SSSD}/sssd.conf ]] || return 0
    if [[ ${ARG_DOMAIN[client]} == "realmd_sssd" ]]; then
	if [[ -n ${REALM_PERMIT_USER} || -n ${REALM_PERMIT_GROUP} ]]; then
	    realm deny --all 2>/dev/null || true
	    [[ -n ${REALM_PERMIT_USER} ]] && realm permit "${REALM_PERMIT_USER//,/ }" 2>/dev/null || true
	    [[ -n ${REALM_PERMIT_GROUP} ]] && realm permit --groups "${REALM_PERMIT_GROUP//,/ }" 2>/dev/null || true
	else 
	    realm permit --all 2>/dev/null || true
	fi	
    elif [[ ${ARG_DOMAIN[client]} == "realmd_winbind" ]]; then
	true
    elif [[ ${ARG_DOMAIN[client]} == "samba" ]]; then
	true
    fi
}
# Найти контроллер домена в сети
find_domain(){
    if [[ -n ${ARG_DOMAIN[server]} ]]; then
	if grep -qoE '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' <<< ${ARG_DOMAIN[server]}; then
	    ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server]}
	    ARG_DOMAIN[server]=$(adcli info --domain-controller ${ARG_DOMAIN[server_ip]} 2>/dev/null | grep "domain-controller =" | cut -d= -f2 | xargs)
	fi
	[[ -n ${ARG_DOMAIN} ]] || ARG_DOMAIN=$(adcli info --domain-controller ${ARG_DOMAIN[server]} 2>/dev/null | grep "domain-name =" | cut -d= -f2 | xargs)
    fi
    [[ -n ${ARG_DOMAIN} ]] || ARG_DOMAIN=$(realm discover 2>/dev/null | awk '/domain-name: / { print $2 ; exit }')
    [[ -n ${ARG_DOMAIN} ]] || ARG_DOMAIN=$(hostname -d)
    [[ -n ${ARG_DOMAIN} && ${ARG_DOMAIN} != "(none)" ]] || prompt -wq " Global broadcast domains not found, unable to get broadcast domain name. Please set hostname with domain name."
}
get_domain_server(){
    if [[ -n ${ARG_DOMAIN[server]} ]]; then
	if [[ ${ARG_DOMAIN[server]} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
	    ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server]}
	    [[ $(adcli info --domain-controller ${ARG_DOMAIN[server_ip]} 2>/dev/null | grep "domain-controller =") =~ ' = '(.*)$ ]] \
	    && ARG_DOMAIN[server]=${BASH_REMATCH[1]}
	fi
    fi
    [[ ${ARG_DOMAIN[server]} == "" && $(adcli info --domain ${ARG_DOMAIN} 2>/dev/null | grep "domain-controller =") =~ ' = '(.*)$ ]] \
    && ARG_DOMAIN[server]=${BASH_REMATCH[1]}
    [[ ${ARG_DOMAIN[server]} == "" ]] && prompt -eq " Domain not found, unable to get domain controller name!"
#echo "1:ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server_ip]}"
    # Если не нашёл статус ОК
#    [[ -n ${ARG_DOMAIN[server_ip]} ]] || ARG_DOMAIN[server_ip]=$(drill TXT ${ARG_DOMAIN[server]} | grep -i server: | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
#echo "2:ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server_ip]}"
    [[ ${ARG_DOMAIN[server_ip]} == "" ]] \
    && [[ $(nslookup -timeout=5 -type=srv _ldap._tcp.${ARG_DOMAIN} 2>/dev/null) =~ "Server:"[[:blank:]]*([0-9.]+).*"service ="[[:blank:]0-9.]+'389' ]] \
    && ARG_DOMAIN[server_ip]=${BASH_REMATCH[1]}
#echo "3:ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server_ip]}"
    [[ ${ARG_DOMAIN[server_ip]} == "" ]] && [[ $(host -W 2 ${ARG_DOMAIN[server]} | tail -1  2>/dev/null) =~ " "([0-9.]+)$ ]] && DOMAIN_SERVER_IP=${BASH_REMATCH[1]}
#echo "4:ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server_ip]}"
    [[ ${ARG_DOMAIN[server_ip]} == "" ]] && [[ $(nslookup -timeout=2 ${ARG_DOMAIN[server]} 2>/dev/null) =~ "Name:"[[:blank:]]*${ARG_DOMAIN[server]}.*"Address:"[[:blank:]]*([0-9.]+) ]] \
    && ARG_DOMAIN[server_ip]=${BASH_REMATCH[1]}
#echo "5:ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server_ip]}"
    # Если не нашёл статус ОК
#    [[ -n ${ARG_DOMAIN[server_ip]} ]] || ARG_DOMAIN[server_ip]=$(dig ${ARG_DOMAIN[server]} | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
#echo "6:ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server_ip]}"
    [[ ${ARG_DOMAIN[server_ip]} == "" ]] && [[ $(getent hosts ${ARG_DOMAIN[server]} 2>/dev/null) =~ ^([0-9.]+)[[:blank:]]+ ]] && ARG_DOMAIN[server_ip]=${BASH_REMATCH[1]}
#echo "7:ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server_ip]}"
    [[ ${ARG_DOMAIN[server_ip]} == "" ]] && [[ $(ping ${ARG_DOMAIN[server]} -c 1 -W 0 -q 2>/dev/null) =~ 'PING '${ARG_DOMAIN[server]}' ('([0-9.]+)')' ]] \
    && ARG_DOMAIN[server_ip]=${BASH_REMATCH[1]}
#echo "8:ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server_ip]}"
    [[ ${ARG_DOMAIN[server_ip]} == "" ]] && prompt -eq "domain not found, unable to get domain controller ip address"
#echo "9:ARG_DOMAIN[server_ip]=${ARG_DOMAIN[server_ip]}"
}
discover_domain(){
    if [[ -n ${ARG_DOMAIN[server]} ]]; then
	prompt -i "request information by domain server name: ${ARG_DOMAIN[server]}"
        adcli info --domain-controller ${ARG_DOMAIN[server]} 2>/dev/null
        [[ $? == 0 ]] || prompt -w "not found information by domain server name: ${ARG_DOMAIN[server]}"
    fi
    if [[ -n ${ARG_DOMAIN[server_ip]} ]];then
	prompt -i "request information by domain server ip: ${ARG_DOMAIN[server_ip]}"
        adcli info --domain-controller ${ARG_DOMAIN[server_ip]} 2>/dev/null
        [[ $? == 0 ]] || prompt -w "not found information by domain server ip: ${ARG_DOMAIN[server_ip]}"
    fi
    if [[ -n ${ARG_DOMAIN} ]]; then
	prompt -i "request information by domain realm: ${ARG_DOMAIN[server]}"
        adcli info --domain ${ARG_DOMAIN} 2>/dev/null
        [[ $? == 0 ]] || prompt -w "not found information by domain realm: ${ARG_DOMAIN[server]}"
    fi
    prompt -i "request global search for a domain in the network: ${ARG_DOMAIN}"
    realm discover ${ARG_DOMAIN}  2>/dev/null
    [[ $? == 0 ]] || prompt -w "global domain not detected, timeout 30 seconds"
}
join_domain(){
    join_domain_sssd(){
	[[ -n ${ARG_MUSER} ]] && local ARG_MUSER="--user '${ARG_MUSER}'"
	[[ -n ${ARG_MPASSWORD} ]] && local ARG_MPASSWORD="echo '${ARG_MPASSWORD}' |"
 	eval "${ARG_MPASSWORD} /usr/bin/realm join --verbose ${ARG_MUSER} --os-name '${OS_NAME}' --os-version ${OS_VERSION} ${ARG_DOMAIN}"
 	[[ $? -eq 0 ]] || return 1
    }
    if [[ ${ARG_DOMAIN[client]} == "realmd_sssd" ]]; then
	join_domain_sssd
	STATUS_JOIN=$?
    elif [[ ${ARG_DOMAIN[client]} == "realmd_winbind" ]]; then
	true
	STATUS_JOIN=$?
    elif [[ ${ARG_DOMAIN[client]} == "samba" ]]; then
	true
	STATUS_JOIN=$?
    fi
    [[ ${STATUS_JOIN} -eq 0 ]] || return 1
}
leave_domain(){
    leave_domain_sssd(){
	[[ -f ${PATH_CONF_KRB5}/krb5.keytab ]] || return 0
	[[ -n ${ARG_MUSER} ]] && local ARG_MUSER="--user ${ARG_MUSER}"
	[[ -n ${ARG_MPASSWORD} ]] && local ARG_MPASSWORD="echo '${ARG_MPASSWORD}' |"
	eval "${ARG_MPASSWORD} /usr/bin/realm leave --verbose --remove ${ARG_MUSER} ${ARG_DOMAIN}"
    }
    if [[ ${ARG_DOMAIN[client]} == "realmd_sssd" ]]; then
	leave_domain_sssd
    elif [[ ${ARG_DOMAIN[client]} == "realmd_winbind" ]]; then
	true
    elif [[ ${ARG_DOMAIN[client]} == "samba" ]]; then
	true
    fi
}
etc_clean(){
    etc_clean_sssd(){
	find /etc/ -maxdepth 1 -type f -name "krb5.keytab" -delete
	find /etc/sssd/ -type f -name "sssd.conf" -delete
	find /etc/sssd/ -type f -name "*-ubdomain-*.conf" -delete
	find /var/lib/sss/db/ -type f -name "*" -delete
	find /tmp -maxdepth 1 -type f -name "krb5*" -delete
    }
    if [[ ${ARG_DOMAIN[client]} == "realmd_sssd" ]]; then
	etc_clean_sssd
    elif [[ ${ARG_DOMAIN[client]} == "realmd_winbind" ]]; then
	true
    elif [[ ${ARG_DOMAIN[client]} == "samba" ]]; then
	true
    fi
}
rootcopy_clean(){
# Удалить из rootcopy настройки
    rootcopy_clean_sssd(){
        if [[ -d ${PATH_ROOTCOPY}/etc ]]; then
	    #find ${PATH_ROOTCOPY}/etc/ -maxdepth 1 -type f -name "krb5.conf" -delete
	    #find ${PATH_ROOTCOPY}/etc/ -maxdepth 1 -type f -name "krb5.keytab" -delete
	    #find ${PATH_ROOTCOPY}/etc/ -maxdepth 1 -type f -name "realmd.conf" -delete
	    #[[ -d ${PATH_ROOTCOPY}/etc/sssd ]] && find ${PATH_ROOTCOPY}/etc/sssd/ -type f -name "*.conf" -delete
	    rm -f "${PATH_ROOTCOPY}/etc/krb5.conf" 2>/dev/null
	    rm -f "${PATH_ROOTCOPY}/etc/krb5.keytab" 2>/dev/null
	    rm -f "${PATH_ROOTCOPY}/etc/realmd.conf" 2>/dev/null
	    rm -rdf "${PATH_ROOTCOPY}/etc/sssd" 2>/dev/null
	fi
	[[ -d ${PATH_ROOTCOPY}/var/lib/sss ]] & rm -rdf "${PATH_ROOTCOPY}/var/lib/sss" 2>/dev/null
    }
    PATH_ROOTCOPY=$(find /memory/layer-base/*/ -maxdepth 1 -type d -name "rootcopy" | head -1)
    [[ -n ${PATH_ROOTCOPY} ]] || PATH_ROOTCOPY="$(find /memory/layer-base/*/ -maxdepth 1 -type f -name "ublinux-data*.sgn" | head -1 | xargs dirname)/rootcopy"
    [[ -w ${PATH_ROOTCOPY} ]] || return 1
    if [[ ${ARG_DOMAIN[client]} == "realmd_sssd" ]]; then
	rootcopy_clean_sssd
    elif [[ ${ARG_DOMAIN[client]} == "realmd_winbind" ]]; then
	true
    elif [[ ${ARG_DOMAIN[client]} == "samba" ]]; then
	true
    fi
}
get_lock() {
    eval "exec ${LOCK_FD}>${LOCK_FILE}"
    flock -n ${LOCK_FD}
}

###############################
###   :::   M A I N   :::   ###
###############################

    SELFNAME=${BASH_SOURCE##*/}

    LOCK_FILE=/tmp/.${USER}:${SELFNAME}.lock
    LOCK_FD=9
    get_lock || exit 0

    PATH_WORK=${PWD}
    set_color

    PATH_SHARE="/usr/share/ubdomain-client"
    PATH_CONF_KRB5="/etc"
#PATH_CONF_KRB5="/tmp/0/etc"
    PATH_CONF_SSSD="/etc/sssd/conf.d"
#PATH_CONF_SSSD="/tmp/0/etc/sssd/conf.d"
    FILE_KRB5="${PATH_SHARE}/krb5.conf"
    FILE_REALM_SNIPPET_001="${PATH_SHARE}/001-ubdomain-default.conf"
    FILE_REALM_SNIPPET_010="${PATH_SHARE}/010-ubdomain-domain.conf"

    SOURCE=/usr/lib/ublinux/default; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    SOURCE=${SYSCONF}/config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    SOURCE=${SYSCONF}/system; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    SOURCE=${SYSCONF}/network; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    SOURCE=${SYSCONF}/locale; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null

    if [[ ${OS_RELEASE_PRETTY_NAME} =~ ([[:alnum:]]+)" "([[:digit:]]+)" "(.+) ]]; then
	OS_NAME="${BASH_REMATCH[1]} ${BASH_REMATCH[3]}"
	OS_VERSION=${BASH_REMATCH[2]}
    else
	OS_NAME="UBLinux Unknown (x)"
	OS_VERSION="0000"
    fi
    MY_IP=$(ifconfig 2>/dev/null | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' 2>/dev/null) #'
    declare -p | grep -q "declare -A DOMAIN" || declare -A DOMAIN
    declare -p | grep -q "declare -A REALM_SSSD" || declare -A REALM_SSSD
    declare -p | grep -q "declare -A REALM_PERMIT" || declare -A REALM_PERMIT
    declare -A ARG_DOMAIN

    arguments "$@"

    if [[ ${COMMAND} == list ]]; then
	realm list
    elif [[ ${COMMAND} == discover ]]; then
	[[ -n ${ARG_DOMAIN[dns]} ]] && set_dns
	[[ -z ${ARG_DOMAIN} ]] && find_domain
	[[ -n ${ARG_DOMAIN} ]] && get_domain_server
	discover_domain
    elif [[ ${COMMAND} == join ]]; then
	[[ -n ${MY_IP} ]] || prompt -eq "Host ip address is missing!"
	[[ -n ${ARG_DOMAIN[dns]} ]] && set_dns
	[[ -z ${ARG_DOMAIN} ]] && find_domain
	[[ -n ${ARG_DOMAIN} ]] && get_domain_server
	if [[ -z ${NOCONFIGURE} ]] && check_root -w " The PAM, KRD5, NSS, SSSD is not configured. Root rights are required."; then
	    set_authpam
	    prepare_config
	fi
	[[ $(ubconfig --raw get network DOMAIN) == ${ARG_DOMAIN} ]] || ubconfig --noexecute set network DOMAIN="${ARG_DOMAIN}"
	[[ $(ubconfig --raw get network DOMAIN[server]) == ${ARG_DOMAIN[server]} ]] || ubconfig --noexecute set network DOMAIN[server]="${ARG_DOMAIN[server]}"
	[[ $(ubconfig --raw get system HOSTNAME) == "${HOSTNAME%%.*}.${ARG_DOMAIN}" ]] || ubconfig set system HOSTNAME="${HOSTNAME%%.*}.${ARG_DOMAIN}"
	join_domain
	if [[ -z ${NOCONFIGURE} ]] && check_root -w " The permit is not configured. Root rights are required."; then
	    prepare_permit_config
	fi
    elif [[ ${COMMAND} == leave ]]; then
	[[ -n ${MY_IP} ]] || prompt -eq "Host ip address is missing!"
	leave_domain
        [[ $(ubconfig --raw get network DOMAIN) == "(null)" ]] || ubconfig --noexecute remove network DOMAIN
        [[ $(ubconfig --raw get network DOMAIN[server]) == "(null)" ]] || ubconfig --noexecute remove network DOMAIN[server]
        [[ $(ubconfig --raw get network DOMAIN[dns]) == "(null)" ]] || ubconfig --noexecute remove network DOMAIN[dns]
        [[ $(ubconfig --raw get system HOSTNAME) == ${HOSTNAME%%.*} ]] || ubconfig set system HOSTNAME="${HOSTNAME%%.*}"
        etc_clean
        rootcopy_clean
    elif [[ ${COMMAND} == configure && -z ${NOCONFIGURE} ]]; then
	[[ -n ${MY_IP} && -n ${ARG_DOMAIN[dns]} ]] && set_dns
	[[ -n ${MY_IP} && -z ${ARG_DOMAIN} ]] && find_domain
	[[ -n ${MY_IP} && -n ${ARG_DOMAIN} ]] && get_domain_server
	check_root -wq " The PAM, KRB5, NSS, SSSD is not configured. Root rights are required."
	[[ ${ARG_DOMAIN} == ${DOMAIN} ]] || ubconfig --noexecute set network DOMAIN="${ARG_DOMAIN}"
	[[ ${ARG_DOMAIN[server]} == ${DOMAIN[server]} ]] || ubconfig --noexecute set network DOMAIN[server]="${ARG_DOMAIN[server]}"
	[[ -n ${MY_IP} ]] && set_authpam
	prepare_config
	prepare_permit_config
    elif [[ ${COMMAND} == unconfigure && -z ${NOCONFIGURE} ]]; then
	check_root -wq " The PAM, KRB5, NSS, SSSD is not configured. Root rights are required."
	[[ -n ${ARG_DOMAIN} ]] && ubconfig --noexecute remove network DOMAIN
	[[ -n ${ARG_DOMAIN[server]} ]] && ubconfig --noexecute remove network DOMAIN[server]
	ubconfig remove system AUTHPAM
	etc_clean
	rootcopy_clean
    fi
    true
