#!/bin/sh

assert_ldap_tools() {
	local ret=0
	
	ldap_dn="$(which ldap-dn 2>/dev/null)" || ret=$?
	ldap_getent="$(which ldap-getent 2>/dev/null)" || ret=$?
	ldap_groupadd="$(which ldap-groupadd 2>/dev/null)" || ret=$?
	ldap_groupdel="$(which ldap-groupdel 2>/dev/null)" || ret=$?
	ldap_groupmod="$(which ldap-groupmod 2>/dev/null)" || ret=$?
	ldap_init="$(which ldap-init 2>/dev/null)" || ret=$?
	ldap_passwd="$(which ldap-passwd 2>/dev/null)" || ret=$?
	ldap_useradd="$(which ldap-useradd 2>/dev/null)" || ret=$?
	ldap_userdel="$(which ldap-userdel 2>/dev/null)" || ret=$?
	ldap_usermod="$(which ldap-usermod 2>/dev/null)" || ret=$?

	if [ $ret -ne 0 ]; then
		# FIXME: Earlier errors break ahttpd's workflow. It's probably a bug
		#write_error "$(answer_l10n "Package '%s' is not installed" 'ldap-user-tools')"
		printf "Package '%s' is not installed\\n" 'ldap-user-tools' >&2
	fi
	
	return $ret
}

assert_netcmdplus() {
	local ret=0
	netcmdplus="$(which samba-tool-plus 2>/dev/null)" || ret=$?
	if [ $ret -ne 0 ]; then
		# FIXME: Earlier errors break ahttpd's workflow. It's probably a bug
		#write_error "$(answer_l10n "Package '%s' is not installed" 'netcmdplus')"
		printf "Package '%s' is not installed\\n" 'netcmdplus' >&2
	fi
	return $ret
}

write_enum_nolabel() {
	while read ln; do
		write_enum_item "$ln" "$ln"
	done
}

ad_base() {
	local host="${1:-127.0.0.1}"
	assert_netcmdplus || return 1
	local domain="$($netcmdplus domain info "$host" | sed -n -e '/^Domain[[:space:]]/ { s/^[^:]\+[[:space:]]*:[[:space:]]*//; p }')"
	if [ -n "$domain" ]; then
		host_2_dn "$domain"
	fi
}

list_bases() {
	local mode="${1:-$mode}"
	local rem_host="${2:-${in_rem_host:-127.0.0.1}}"
	case "$mode" in
		ldap|krb5)
			assert_ldap_tools || return 1
			ldapsearch -x -H "ldap://$rem_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
			;;
		ad)
			assert_netcmdplus || return 1
			base_dn="$(ad_base "$rem_host")"
			if [ -n "$base_dn" ]; then
				write_enum_item "$base_dn" "$base_dn"
			fi
			;;
	esac
}

determine_mode() {
    [ -n "$mode" ] || set_dn_conf
    write_string_param mode "$mode"

    case "$mode" in
		ldap|krb5)
			write_string_param 'DN_CONF' "$DN_CONF"
			write_string_param 'host' "$host"
			write_string_param 'base' "$base"
			write_string_param 'rootdn' "$rootdn"
			write_string_param 'rootpw' "$rootpw"

			method="$(echo "$rootpw" | sed -n -e "s/^.*{\([^}]*\)}.*$/\1/p")"
			if [ -n "$method" ]; then
				write_string_param bind_info 'encoded'
			else
				write_string_param bind_info 'present'
			fi
			
			if [ "$mode" = "krb5" ]; then
				write_string_param enable_krb "yes"
			fi
			;;
		local)
			;;
		ad)
			;;
    esac
}

check_mode() {
	[ -n "$mode" ] || set_dn_conf
	write_string_param 'mode'      "$mode"
	write_string_param 'host'      "$host"
	write_string_param 'base'      "$base"
	write_string_param 'rootdn'    "$rootdn"
	write_string_param 'rootpw'    "$rootpw"
	write_string_param 'bind_info' "$bind_info"

	if assert_netcmdplus 2>/dev/null; then
		write_bool_param 'netcmdplus_available' 'yes'
	else
		write_bool_param 'netcmdplus_available' 'no'
	fi
}

set_new_source() {
    case "$in_newmode" in
		local)
			mode="local"
			host="localhost"
			base="tcb"
			rootdn="root"
			rootpw='*********'
			bind_info="present"
			export mode host base rootdn rootpw bind_info			
			;;
		ldap|krb5)
			host="$in_host"
			base="$in_new_base"
			DN_CONF="remote"
			mode="ldap"
			bind_info="encoded"
			export DN_CONF mode host base rootdn rootpw bind_info
			;;
		localldap)
			local role="$(shell_config_get /etc/sysconfig/system SERVER_ROLE)"
			if [ "$role" = 'master' ]; then
				mode="krb5"
			else
				mode="ldap"
			fi
			host="localhost"
			base="$in_new_base"
			assert_ldap_tools || return 1
			DN_CONF="$($ldap_dn find "$base")"
			rootdn="$(egrep "rootdn" "$DN_CONF" | cut -f2 -d' ' | tr -d '"')"
			rootpw="-w $(egrep "rootpw" "$DN_CONF" | cut -f2 -d' ')"
			method="$(echo "$rootpw" | sed -n -e "s/^.*{\([^}]*\)}.*$/\1/p")"
			if [ -n "$method" ]; then
				bind_info="encoded"
			else
				bind_info="present"
			fi
			export DN_CONF mode host base rootdn rootpw bind_info
			;;
		system)
			mode="system"
			set_dn_conf
			;;
		ad)
			mode="ad"
			host="localhost"
			base="${in_new_base:-$(ad_base)}"
			export mode host base
			;;
    esac

	in_minuid=; in_maxuid=
}

get_mode() {
	local mode="${1:-$mode}"
	if [ -z "$mode" -o "$mode" = 'system' ]; then
        mode="$(/usr/sbin/system-auth status | cut -f1 -d' ')"
		role="$(shell_config_get /etc/sysconfig/system SERVER_ROLE)"
		case "$mode" in
			ldap|localldap)
				if rpm -q samba-DC 2>/dev/null 1>&2 && \
					   service_control samba is-enabled
				then
					mode='ad'
				elif [ "$role" = 'master' ]; then
					mode='krb5'
				fi
				;;
		esac
	fi
	echo "$mode"
}

# test IP address or hostname: local or remote
is_local(){
	[ "$(traceroute -m2 $1 | wc -l)" -le 2 ]
}

set_dn_conf() {
    local data="$(/usr/sbin/system-auth status)"
    mode="$(get_mode)"

    case "$mode" in
		local)
			mode="local"
			host="localhost"
			base="tcb"
			rootdn="root"
			rootpw='*********'
			bind_info="present"
			export mode host base rootdn rootpw bind_info
			export ENABLE_KRB=
			;;
		ldap|krb5)
			assert_ldap_tools || return 1
			base="$(echo "$data" | cut -f2 -d' ')"
			urihost="$(echo "$data" | cut -f3 -d' ')"
			host="$(echo "$urihost" | sed -e 's/lda.*\/\///i')"
			if is_local "$host"; then
				host=127.0.0.1
				DN_CONF="$($ldap_dn find "$base")"
				rootdn="$(egrep "rootdn" "$DN_CONF" | cut -f2 -d' ' | tr -d '"')"
				rootpw="-w $(egrep "rootpw" "$DN_CONF"|cut -f2 -d' ')"
				bind_info="present"
				export DN_CONF
				export mode host base rootdn rootpw
				[ "$mode" = 'krb5' ] && export ENABLE_KRB="yes"
			fi
			return 0
			;;
		ad)
			export ENABLE_KRB=
			base="$(ad_base)"
			host="localhost"
			;;
    esac
}

set_new_bind() {
    mode="$(get_mode "$in_mode")"
    base="$in_base"
    host="$in_host"
    rootdn="$in_rootdn"
    rootpw="-w $in_rootpw"
    bind_info="$in_bind_info"
    DN_CONF="remote"
    export DN_CONF mode host base rootdn rootpw bind_info
}
