#!/bin/sh

#common part
po_domain="alterator-auth"
alterator_api_version=1
ldap_uri_re='^(ldap|ldapi|ldaps)://[.a-zA-Z0-9_-]+$'
rdelim='[[:space:]]\+'
wdelim=' '

#pam configuration
pamldapfile="/etc/pam_ldap.conf"

#nss configuration
nssldapfile=
nssldapfile1="/etc/nss_ldap.conf"
nssldapfile2="/etc/nslcd.conf"
nsswitchfile="/etc/nsswitch.conf"

#select between nss_ldap and nss_ldapd
[ -f "$nssldapfile1" ] && nssldapfile="$nssldapfile1"
[ -f "$nssldapfile2" ] && nssldapfile="$nssldapfile2"


. alterator-sh-functions
. alterator-openldap-functions
. alterator-service-functions
. shell-config
. shell-quote

#turn off auto expansion
set -f

host_2_dn()
{
    local host="$1" ; shift
    host="$(echo $host|sed -e "s/^/dc=/"|sed -e "s/\./,dc=/g")"
    echo "$host"
}

local_bases(){
    if [ -n "$in_ldap_host" ]; then
	if test_bool "$in_ldap_ssl"; then
	    ldap_uri="ldaps://"
	else
	    ldap_uri="ldap://"
	fi
	echo "$in_ldap_ssl: $ldap_uri$in_ldap_host" >> /root/alt_test.txt
    	ldapsearch -x -H "$ldap_uri$in_ldap_host" -LLL -b "" -s base namingContexts | grep naming | cut -f2 -d ' '| \
        while read base_dn ; do
    	    write_enum_item "$base_dn" "$base_dn"
        done 2>/dev/null
    else
        test -e "$SLAPD_CONF" || return
        for conf in $(read_slapd_conf include|egrep -i "slapd-[.a-z0-9_-]+\.conf[[:blank:]]*$") ;do
            local basedn="$(read_config "$conf" suffix)"
            [ -z "$suffix" ] || write_enum_item "$basedn" "$basedn"
        done
    fi
}

list_domain()
{
	local __ prefix ip txt role domain

    # Check if avahi-daemon is running for browse domain
    status=
    service avahi-daemon status &>/dev/null && status="running"
    if [ "$status" != "running" ]; then
        write_error "error_browse"
        return 1
    fi

	write_enum_item "local" "$(_ "local")"

    # Lookup available domains in Zeroconf
	avahi-browse -prtk _server._tcp 2>/dev/null|
		while IFS=';' read prefix __ __ __ __ __ __ ip __ txt; do
			[ "$prefix" = "=" ] || continue
			role="$(txt_record role "$txt")"
			[ "$role" = "master" ] || continue
			domain="$(txt_record domain "$txt")"
        		write_enum_item "$domain" "$domain ($ip)"
		done
#    write_enum_item "custom" "$(_ "custom")"
}

txt_record()
{
	echo "$2" |
		sed -n "s/\(^\|.*[[:space:]]\)\"$(quote_sed_regexp "$1")=\([^\"]*\)\".*/\2/p"
}

dn_2_host()
{
    local dn="$1"
    local host=

    echo "$dn"|sed -e 's/^dc=//i'|sed -e 's/,dc=/\./g'
}

read_current()
{
    local data="$(/usr/sbin/system-auth status)"
    local status="$(echo "$data"|cut -f1 -d' ')"
    local dn

    echo "$status" | grep -q "^krb5" \
	&& dn="$(echo "$data"|cut -f2 -d' ')" \
	&& dn_2_host "$dn" \
	&& return

    echo "`_ "Kerberos domain is not used"`"
}

read_ldap()
{
    shell_config_get "$1" "$2" "$rdelim"
}

read_ldap2()
{
    local f
    f=
    [ -f "$nssldapfile" ] && f="$nssldapfile"
    [ -f "$pamldapfile" ] && f="$pamldapfile"
    [ -n "$f" ] && read_ldap "$f" "$1"
}

get_ldap()
{
		local ldap_uri="$(read_ldap2 uri)"

		local ldap_proto="${ldap_uri%%://*}"
		local ldap_host="${ldap_uri#$ldap_proto://}"
		local ldap_port="${ldap_host##*:}"

		ldap_host="${ldap_host%%:*}"
		[ "$ldap_port" != "$ldap_host" ] || ldap_port=

		write_string_param ldap_host "$ldap_host"
		#write_string_param ldap_port "$ldap_port"

		[ "$ldap_proto" != "ldaps" ]
		write_bool_param ldap_ssl "$?"

		write_string_param ldap_basedn "$(read_ldap2 base)"
}

get_ad_info()
{
		read auth_type domain hostname workgroup << EOF
$(/usr/sbin/system-auth status)
EOF
		#echo "auth: a=$auth_type d=$domain h=$hostname w=$workgroup" >&2
		write_string_param ad_domain    "$domain"
		write_string_param ad_host      "$hostname"
		write_string_param ad_workgroup "$workgroup"
		write_string_param current_domain "$domain"
}

get_freeipa_info()
{
		read auth_type domain hostname << EOF
$(/usr/sbin/system-auth status)
EOF
		#echo "auth: a=$auth_type d=$domain h=$hostname" >&2
		write_string_param freeipa_domain    "$domain"
		write_string_param freeipa_host      "$hostname"
		write_string_param current_domain    "$domain"
}

get_domain_from_dns()
{
	resolvconf -l 2>/dev/null | sed -n 's/^\(domain\|search\) //p'|sed 's/ localdomain//' | tr ' ' '\n' | head -1
}

gpupdate_setup()
{
	rpm -q gpupdate &>/dev/null || return 0

	if [ "$1" = "#t" ]; then
		/usr/sbin/gpupdate-setup enable
	elif [ "$1" = "local" ]; then
		if [ -f /etc/gpupdate/gpupdate.ini ]; then
			/usr/sbin/gpupdate-setup set-backend local
		fi
	else
		/usr/sbin/gpupdate-setup disable
	fi
}

on_message()
{
	case "$in_action" in
	    type)
    		write_type_item domain_name hostname
    		write_type_item domain hostname
		    ;;
	    list)
		    [ "$in__objects" = "avail_domain" ] && list_domain || return
    		[ "$in__objects" = "local_bases" ] && local_bases
	    	;;
	    read)
		    local domain=''
		    auth_type="$(/usr/sbin/system-auth status |cut -f1 -d ' ')"
		    write_string_param "auth_type" "$auth_type"
		    get_ldap
		    write_bool_param "ccreds" $(echo "$auth_type" | sed 's/krb5_ccreds/true/')
		    write_string_param hostname "$(hostname -s)"
		    if [ "$auth_type" = "ad" ]; then
                	get_ad_info
		    else
			write_string_param ad_domain "$(get_domain_from_dns)"
		    fi
		    if [ "$auth_type" = "freeipa" ]; then
			get_freeipa_info
		    else
			write_string_param freeipa_domain "$(get_domain_from_dns)"
			if [ "$auth_type" = "ldap" -o "$auth_type" = "krb5" ]; then
			    domain="$(read_current)"
			    write_string_param current_domain "$domain"
                        elif [ "$auth_type" = "local" ]; then
                            write_string_param current_domain ""
			fi
		    fi
		    if [ -z "$domain" ]; then
		        domain="$(get_domain_from_dns)"
		    fi
                    write_string_param ldap_domain "$domain"
		    srv="false"
		    #rpm -q task-auth-ad &>/dev/null && srv="true"
		    rpm -q task-auth-ad-sssd &>/dev/null && srv="true"
		    write_bool_param "type_ad_available" "$srv"
                    srv="false"
		    rpm -q gpupdate &>/dev/null && srv="true"
		    write_bool_param "gpupdate_available" "$srv"
		    srv="false"
		    rpm -q task-auth-freeipa &>/dev/null && srv="true"
		    write_bool_param "type_freeipa_available" "$srv"
		    ;;
	    write)
              #echo "$(set|grep -a "in_")" >&2
              case "$in_auth_type" in
                local)
                    /usr/sbin/system-auth write local
                    gpupdate_setup local
                    ;;
                ldap)
                    [ "$in_ldap_ssl" == "on" ] && ldap_uri="ldaps://" || ldap_uri="ldap://"
                    /usr/sbin/system-auth write ldap "$in_ldap_basedn" "$ldap_uri$in_ldap_host"
                    ;;
                krb5)
                    if [ "$in_ldap_domain" = "local" ]; then
                        /usr/sbin/system-auth write local
                    else
                        if [ "$in_ccreds" = "#t" ]; then
                            auth_type=krb5_ccreds
                        else
                            auth_type=krb5
                        fi
                        if [ -n "$in_ldap_domain" ]; then
                            # Test domain available
                            if ! resolve "$in_ldap_domain" &>/dev/null ;then
                                write_error "`_ "Unable to find specified domain"`"
                            else
                                # Test Astra Linux Directory
                                ldap_server="ldap://$in_ldap_domain"
                                if ! ldapsearch -x -H "$ldap_server" -s base &>/dev/null ;then
                                    ldap_server="ldaps://ldap.$in_ldap_domain"
                                fi
                                err="$(/usr/sbin/system-auth write $auth_type "$(host_2_dn "$in_ldap_domain")" "$ldap_server" 2>&1)"
                                if [ $? -ne 0 ]; then
                                    write_error "`_ "Domain does not set:"` $err"
                                fi
                            fi
                        fi
                    fi
                    ;;
                multi)
                    ;;
                pkcs11)
                    ;;
                ad)
                    output="$(/usr/sbin/system-auth write ad "$in_ad_domain" "$in_ad_host" "$in_ad_workgroup" "$in_admin_username" "$in_admin_password" 2>&1)"
                    [ "$output" = "Netbios name should not be more 15 chars" ] && output="`_ "Netbios name should not be more 15 chars"`"
                    [ "$output" = "Unable to find specified domain" ] && output="`_ "Unable to find specified domain"`"
                    [ "$output" = "Cannot contact KDC for realm" ] && output="`_ "Cannot contact KDC for realm"`"
                    [ "$output" = "Unknown administrator name" ] && output="`_ "Unknown administrator name"`"
                    [ "$output" = "Preauthentication failed" ] && output="`_ "Preauthentication failed"`"
                    [ "$output" = "Wrong password" ] && output="`_ "Wrong password"`"
                    (echo "$output" | grep "^Joined '.*' to dns domain '.*'$" && gpupdate_setup "$in_group_policy") || write_error "`_ "Unable to join to Active Directory domain:"` $output"
                    ;;
                freeipa)
                    output="$(/usr/sbin/system-auth write freeipa "$in_ad_domain" "$in_ad_host" "$in_admin_username" "$in_admin_password" 2>&1)"
                    echo "$output" | grep "Unable to find specified domain" ] && output="`_ "Unable to find specified domain"`"
                    echo "$output" | grep "^Unable to find IPA Server to join" && output="`_ "Unable to find IPA Server to join"`"
                    echo "$output" | grep "Password incorrect while getting initial credentials" && output="`_ "Incorrect administrator password"`"
                    echo "$output" | grep "^Client configuration complete.$" || write_error "`_ "Unable to join to FreeIPA domain:"` $output"
                    ;;
                *)
                    ;;
              esac
              ;;
	esac
}
message_loop
