#!/bin/bash
#
# Univention Join
#  joins a system into a UCS domain
#
# Copyright 2004-2014 Univention GmbH
#
# http://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.

# execute univention-server-join

export PATH="$PATH:/sbin:/usr/sbin:/bin:/usr/bin"

eval "$(univention-config-registry shell)"

. /usr/share/univention-lib/all.sh

SIMPLEGUI=""
TYPE=
USERTMP="$(mktemp -d)"
DCPWD="$USERTMP/dcpwd"
VERSION_CHECK=true
VERBOSE=false

trapOnExit() {
	rm -rf "$USERTMP"
	if [ -n "$VERBOSE" -a "$VERBOSE" = "true" ]; then
		if [ -n "$old_listener_debug_level" ]; then
			ucr set listener/debug/level="$old_listener_debug_level" >>/var/log/univention/join.log 2>&1
		fi
	fi
	echo "$(LC_ALL=C date): finish $0" >>/var/log/univention/join.log 2>&1
}

trap trapOnExit EXIT

display_help() {
	display_header
	cat <<-EOL
	Syntax:
	  univention-join [options]

	Options:
	  -dcname <fqdn>:                DC master fqdn
	  -dcaccount <account>:          Name of DC master account
	  -dcpwd <password file>:        File with DC master password
	  -type <type>:                  Type of computer, e.g. "client"
	  -ldapbase <ldap base>:         LDAP Base DN, e.g. dc=test,dc=local
	  -realm <kerberos realm>:       Kerberos realm, e.g. TEST.LOCAL
	  -windom <windows domain name>: Name of the windows (samba) domain
	  -disableVersionCheck           Disable version check against _dcname_
	  -verbose                       Enable verbose logging (/var/log/univention/join.log)

	  -h | --help | -?:              Print this usage message and exit program
	  --version:                     Print version information and exit program

	Description:
	  univention-join joins a computer to an ucs domain,
	  e.g. univention-join -dcaccount backup_join -dcpwd /tmp/pwd_secret

	EOL
}

display_header() {
	echo "univention-join: joins a computer to an ucs domain"
	echo "copyright (c) 2001-@%@copyright_lastyear@%@ Univention GmbH, Germany"
	echo ""
}

display_version() {
	echo "univention-join @%@package_version@%@"
}

failed_message () {
	echo ""
	echo ""
	echo "**************************************************************************"
	echo "* Join failed!                                                           *"
	echo "* Contact your system administrator                                      *"
	echo "**************************************************************************"
	echo "* Message:  $@"
	echo "**************************************************************************"
	exit 1
}

bashquote () { # quote arguments for eval
	declare -a escaped
	declare -r quote=\\\'
	local arg
	for arg in "$@"
	do
		escaped+=("'${arg//\'/'$quote'}'")
	done
	echo -n "${escaped[@]}"
}

download_host_certificate () {
	echo -n "Download host certificate: "
	local HOSTPWD="/etc/machine.secret"
	local HOSTACCOUNT="$hostname\$"
	while true
	do
		univention-scp "$HOSTPWD" -q -r \
			"$HOSTACCOUNT@$DCNAME:/etc/univention/ssl/$hostname" \
			"$HOSTACCOUNT@$DCNAME:/etc/univention/ssl/$hostname.$domainname" \
			/etc/univention/ssl/ >>/var/log/univention/join.log 2>&1
		[ -d "/etc/univention/ssl/$hostname" ] && [ -d "/etc/univention/ssl/$hostname.$domainname" ] && break
		echo -n "."
		sleep 20
	done

	echo -e "\033[60Gdone"
}

check_ldap_tls_connection () {
	echo -n "Check TLS connection: "

	eval "$(ucr shell ldap/master/port)"

	ldapsearch -x -ZZ -p "$ldap_master_port" -s base -h "$DCNAME" -D "$binddn" -w "$(<"$DCPWD")" dn >/dev/null
	if  [ $? != 0 ]; then
 		failed_message "Establishing a TLS connection with $DCNAME failed. Maybe you didn't specify a FQDN."
	fi

	echo -e "\033[60Gdone"
}

run_join_scripts () {

	LC_COLLATE="C"
	if test -d "/usr/lib/univention-install/"; then
		for i in /usr/lib/univention-install/*.{inst,uinst}; do
			test -e "$i" || continue
			echo -n "Configure $(basename "$i") "
			[ -n "$SIMPLEGUI" ] && echo
			echo "Configure $(basename "$i") $(LC_ALL=C date)" >>/var/log/univention/join.log
			bashVerbose=""
			if [ -n "$VERBOSE" -a "$VERBOSE" = "true" ]; then
				bashVerbose="bash -x"
			fi
			$bashVerbose "$i" --binddn "$binddn" --bindpwd "$(<"$DCPWD")" >>/var/log/univention/join.log 2>&1
			if [ $? -ne 0 ]; then
				echo -e "\033[60Gfailed"
				failed_message "FAILED: $(basename "$i")"
			else
				echo -e "\033[60Gdone"
				delete_unjoinscript "$(basename "$i")"
			fi
			if [ "$server_role" = "domaincontroller_slave" -o "$server_role" = "domaincontroller_backup" ]; then

				# check failed.ldif
				if [ "$(basename "$i")" = "03univention-directory-listener.inst" ]; then
					if [ -e /var/lib/univention-directory-replication/failed.ldif ]; then
						failed_message "FAILED: failed.ldif exists."
					fi

					# backup
					if [ "$server_role" = "domaincontroller_backup" ]; then
						univention-scp "$DCPWD" -r \
							"${DCACCOUNT}@${DCNAME}:/var/lib/univention-ldap/notify/transaction" \
							"$USERTMP/tlog" >/dev/null 2>&1
						if [ ! -e "$USERTMP/tlog" ]; then
							failed_message " FAILED: failed do copy /var/lib/univention-ldap/notify/transaction from the dc master. Please try again."
						fi

						id="$(</var/lib/univention-directory-listener/notifier_id)"
						awk -F ' ' '{ if ( $1 <= '$id') print }' "$USERTMP/tlog" >/var/lib/univention-ldap/notify/transaction
					fi

					# slave 
					if [ "$server_role" = "domaincontroller_slave" ]; then
						if [ -n "$listener_supply_notifier" -a "$listener_supply_notifier" = "yes" ]; then
							univention-scp "$DCPWD" -q \
								"${DCACCOUNT}@${DCNAME}:/var/lib/univention-ldap/notify/transaction" \
								"$USERTMP/tlog" >/dev/null 2>&1
							id="$(</var/lib/univention-directory-listener/notifier_id)"
							awk -F ' ' '{ if ( $1 <= '$id') print }' "$USERTMP/tlog" >/var/lib/univention-ldap/notify/transaction
						fi

					fi
				fi
			fi
		done
	fi

}

check_and_configure_ad_member_mode () {

	# switch to ad member mode
	if is_domain_in_admember_mode; then
		if ! is_localhost_in_admember_mode; then
			echo -n "Entering AD Member Mode: "
			configure_nonmaster_as_ad_member "$server_role" >>/var/log/univention/join.log 2>&1 || failed_message "could not set AD Member Mode"
			echo -e "\033[60Gdone"
		fi
	else
		if is_localhost_in_admember_mode; then
			echo -n "Leaving AD Member Mode: "
			revert_nonmaster_ad_member "$server_role" >>/var/log/univention/join.log 2>&1 || failed_message "could not revert AD Member Mode"
			echo -e "\033[60Gdone"
		fi
	fi
}

# log univention-join call
echo "$(LC_ALL=C date): starting $0 $*" >>/var/log/univention/join.log 2>&1

while [ $# -gt 0 ]
do
	case "$1" in
		"-dcname")
			DCNAME="${2:?missing DC master FQDN}"
			shift 2 || exit 2
			;;
		"-dcaccount")
			DCACCOUNT="${2:?missing DC master account}"
			shift 2 || exit 2
			;;
		"-dcpwd")
			dcpwd="${2:?missing DC password file}"
			shift 2 || exit 2
			cp "$dcpwd" "$DCPWD" || exit 2
			;;
		"-ldapbase")
			LDAPBASE="${2:?missing LDAP base}"
			shift 2 || exit 2
			;;
		"-realm")
			REALM="${2:?missing kerberos realm}"
			shift 2 || exit 2
			;;
		"-windom")
			WINDOM="${2:?missing windows domain name}"
			shift 2 || exit 2
			;;
		"-type")
			TYPE="${2:?missing computer role}"
			shift 2 || exit 2
			;;
		"-simplegui")
			# output simpler gui for univention-installer to be able to parse output
			shift
			SIMPLEGUI="yes"
			;;
		"-disableVersionCheck")
			shift
			VERSION_CHECK=false
			;;
		"--version")
			display_version
			exit 0
			;;
		"--help"|"-h"|"-?")
			display_help
			exit 0
			;;
		"-verbose")
			VERBOSE="true"
			shift
			;;
		*)
			display_help
			exit 1
			;;
	esac
done

# verbose logging for univention-join and listener
if [ -n "$VERBOSE" -a "$VERBOSE" = "true" ]; then
	exec 2>>/var/log/univention/join.log
	set -x
	if [ -n "$listener_debug_level" ]; then
		old_listener_debug_level="$listener_debug_level"
	else
		old_listener_debug_level="2"
	fi
	ucr set listener/debug/level=4 >>/var/log/univention/join.log 2>&1
	listener_debug_level=4
fi

display_header

if [ "$server_role" = "domaincontroller_master" ]; then
	echo "Join on DC Master impossible"
	exit 1
fi

if [ -z "$DCACCOUNT" ]; then
	echo -n "Enter DC Master Account : "
	read DCACCOUNT
fi
if [ ! -f "$DCPWD" ]; then
	echo -n "Enter DC Master Password: "
	read -s password
	echo -n "$password" >>"$DCPWD"
	echo ""
	echo ""
fi

if [ -n "$TYPE" ]; then
	server_role="$TYPE"
fi
if [ "$server_role" = "fatclient" ]; then
	server_role="client"
fi
if [ -z "$server_role" ]; then
	failed_message "No server role defined"
fi


if [ -z "$DCNAME" ]; then
	echo -n "Search DC Master: "
	DCNAME="$(host -t SRV "_domaincontroller_master._tcp.$domainname" | sed -ne '$s/.* \([^ ]\+\)\.$/\1/p')"
	if [ -n "$DCNAME" ]; then
		echo -e "\033[60Gdone"
	else
		for i in "$nameserver" "$nameserver1" "$nameserver2" "$nameserver3" "$dns_forwarder1" "$dns_forwarder2" "$dns_forwarder3"; do
			if [ -z "$i" ]; then continue; fi
			DCNAME="$(host -t SRV "_domaincontroller_master._tcp.$domainname" "$i" | sed -ne '$s/.* \([^ ]\+\)\.$/\1/p')"
			if [ -n "$DCNAME" ]; then
				echo -e "\033[60Gdone"
				echo "domain $domainname" >/etc/resolv.conf
				echo "nameserver $i" >>/etc/resolv.conf
				test -x /etc/init.d/nscd && /etc/init.d/nscd restart >>/var/log/univention/join.log 2>&1
				break
			fi
		done
	fi
fi

if [ -z "$DCNAME" ]; then
	failed_message "missing dns service record for _domaincontroller_master._tcp.$domainname"
fi


echo -n "Check DC Master: "

if ! ping -c 1 "$DCNAME" >/dev/null 2>&1 && ! ping6 -c 1 "$DCNAME" >/dev/null 2>&1; then
	failed_message "ping to $DCNAME failed"
fi

if ! univention-ssh "$DCPWD" "${DCACCOUNT}@${DCNAME}" echo ssh-check 2>>/var/log/univention/join.log | grep -qs ssh-check
then
	failed_message "ssh-login for ${DCACCOUNT}@${DCNAME} failed. Maybe you entered a wrong password."
fi


# get master versions
versions="$(univention-ssh "$DCPWD" "${DCACCOUNT}@${DCNAME}" /usr/sbin/ucr search --brief ^version/)"
OLDIFS=$IFS
IFS=$'\n'
for i in $versions; do
	key=${i%%: *}
	value=${i#*: }
	case "$key" in
		"version/version")
			master_version="$value"
			;;
		"version/patchlevel")
			master_patchlevel="$value"
			;;
		"version/releasename")
			master_releasename="$value"
			;;
	esac
done
IFS=$OLDIFS

# check join constraints
echo "running version check" >>/var/log/univention/join.log

mystatus="no"
if [ -n "$master_version" -a -n "$master_patchlevel" ]; then
	vmaster="$master_version$master_patchlevel"
	vmyself="$version_version$version_patchlevel"
	mystatus="$(echo "$vmaster" "$vmyself" | awk '{if ($1 >= $2) print "yes"; else print "no"}')"
fi

if [ "no" = "$mystatus" ]; then
	vmsg="Warning: UCS version on ${DCNAME} is lower ($vmaster) than local version ($vmyself)."
	vmsg="$vmsg This constellation is not supported."
	if $VERSION_CHECK; then
		failed_message "$vmsg"
	else
		echo "$vmsg Continuing anyway as requested with option (-disableVersionCheck)." >>/var/log/univention/join.log
	fi
else
	echo "OK: UCS version on ${DCNAME} is higher or equal ($vmaster) to the local version ($vmyself)." >>/var/log/univention/join.log
fi

echo -e "\033[60Gdone"

if [ -x /etc/init.d/slapd ]; then
	echo -n "Stop LDAP Server: "
	/etc/init.d/slapd stop >>/var/log/univention/join.log 2>&1
	echo -e "\033[60Gdone"
fi

if [ -x /etc/init.d/samba-ad-dc ]; then
	echo -n "Stop Samba 4 Server: "
	if [ "$dns_backend" = "samba4" ]; then
		ucr set dns/backend=ldap >>/var/log/univention/join.log 2>&1
		/etc/init.d/bind9 restart >>/var/log/univention/join.log 2>&1
	fi
	/etc/init.d/samba-ad-dc stop >>/var/log/univention/join.log 2>&1
	echo -e "\033[60Gdone"
fi

if [ -z "$LDAPBASE" ]; then
	echo -n "Search ldap/base"
	ldap_base="$(univention-ssh "$DCPWD" "${DCACCOUNT}@${DCNAME}" /usr/sbin/ucr search --brief ^ldap/base$ | sed -ne 's|^ldap/base: ||p')"
else
	ldap_base="$LDAPBASE"
fi

if [ -n "$ldap_base" ]; then
	univention-config-registry set ldap/base="$ldap_base" >/dev/null 2>&1
	echo -e "\033[60Gdone"
else
	failed_message "Failed to determine ldap/base."
fi

if [ -x /etc/init.d/slapd ]; then
	echo -n "Start LDAP Server: "
	/etc/init.d/slapd start >>/var/log/univention/join.log 2>&1
	echo -e "\033[60Gdone"
fi

echo -n "Search LDAP binddn "

# First use udm to search the user DN
binddn="$(univention-ssh "$DCPWD" "${DCACCOUNT}@${DCNAME}" \
	/usr/sbin/udm users/user list --filter uid="$DCACCOUNT" --logfile /dev/null | sed -ne 's|^DN: ||p')"

if [ -z "$binddn" ]; then
	# Next check is the local ldapi interface
	binddn="$(univention-ssh "$DCPWD" "${DCACCOUNT}@${DCNAME}" \
		ldapsearch -x -LLL -H ldapi:/// "\'(&(uid=$DCACCOUNT)(objectClass=person))\'" dn | ldapsearch-wrapper | ldapsearch-decode64 | sed -ne 's|^dn: ||p;s|^DN: ||p')"
fi

if [ -z "$binddn" ]; then
	# Check with anonymous bind
	binddn="$(univention-ssh "$DCPWD" "${DCACCOUNT}@${DCNAME}" \
		ldapsearch -x -LLL "\'(&(uid=$DCACCOUNT)(objectClass=person))\'" dn | ldapsearch-wrapper | ldapsearch-decode64 | sed -ne 's|^dn: ||p;s|^DN: ||p')"
fi

if [ -z "$binddn" ]; then
	failed_message "binddn for user $DCACCOUNT not found. "
else
	echo -e "\033[60Gdone"
fi

if [ $server_role != "domaincontroller_master" -a "$server_role" != "domaincontroller_backup" -a -z "$binddn" ]; then
	failed_message "binddn for user $DCACCOUNT not found"
fi

if [ -x /usr/bin/rdate ]; then
	echo -n "Sync time: "
	/usr/bin/rdate "$DCNAME" >/dev/null 2>&1
	echo -e "\033[60Gdone"
fi

args=()

if [ -n "$ldap_position" ]; then
	args+=(-position "$ldap_position")
fi


if [ "${master_version:0:1}" -lt 3 ]; then
	# UCS 2.x does not support the -binddn parameter
	args+=(-bindaccount "$DCACCOUNT")
else
	args+=(-binddn "$binddn")
fi

# TODO: Support multiple network interfaces
# Search for the standard IP:
IP="$(get_default_ip_address)"
if [ -n "$IP" ]; then
	args+=(-ip "$IP")
	if [ "${master_version:0:1}" -ge 3 ]; then
		NETMASK="$(get_default_netmask)"
		# Since UCS 3.0 it is possible to append the netmask
		args+=(-netmask "$NETMASK")
	fi
fi
mac_addr="$(LC_ALL=C ip link show | sed -rne 's|.*link/ether ([0-9a-fA-F:]+) brd .*|\1|p' | head -n1)"
if [ -n "$mac_addr" ]; then
	args+=(-mac "$mac_addr")
fi

# invalidate the nscd hosts cache
#  https://forge.univention.org/bugzilla/show_bug.cgi?id=30886
nscd -i hosts

echo -n "Join Computer Account: "
args+=(-role "$server_role" -hostname "$hostname" -domainname "$domainname")
# Copy local $DCPWD to remote $DCPWD' and invoke univention-join remotely
univention-ssh --no-split "$DCPWD" "${DCACCOUNT}@${DCNAME}" \
	'DCPWD=$(mktemp) && trap "rm -f \"$DCPWD\"" EXIT && cat >"$DCPWD" && /usr/share/univention-join/univention-server-join -bindpwfile "$DCPWD"' \
	"$(bashquote "${args[@]}")" <"$DCPWD" 2>&1 | tee "$USERTMP/log" >>/var/log/univention/join.log
res_message="$(sed -n '/^E:/ { s/^E:\s*// p }' "$USERTMP/log")"
if [ -z "$res_message" ]; then
	echo -e "\033[60Gdone"
fi

if [ -s "$USERTMP/log" ]
then
	echo "Join result = [$(<"$USERTMP/log")]" | sed -e 's/KerberosPasswd="[^"]*"//' | fromdos -fa >>/var/log/univention/join.log

	#try to get password
	kpwd="$(sed -ne 's|^KerberosPasswd="\(.*\)" *|\1|p' <"$USERTMP/log")"

	if [ -n "$kpwd" ]; then
		if [ -e /etc/machine.secret ]; then
			cat /etc/machine.secret >>/etc/machine.secret.SAVE
		fi

		echo -n "$kpwd" >/etc/machine.secret
		fromdos /etc/machine.secret
		chmod 600 /etc/machine.secret
		if [ -e /etc/machine.secret.SAVE ]; then
			chmod 600 /etc/machine.secret.SAVE
		fi
	else
		if [ -n "$res_message" ]; then
			failed_message "$res_message"
		else
			failed_message "$(<"$USERTMP/log")"
		fi
	fi

	ldap_dn="$(sed -ne 's|^ldap_dn="\(.*\)" *|\1|p' <"$USERTMP/log")"
	if [ -n "$ldap_dn" ]; then
		univention-config-registry set ldap/hostdn="$ldap_dn" >>/var/log/univention/join.log 2>&1
	else
		failed_message "No LDAP Host DN returned"
	fi
else
	failed_message "Nothing returned from join process"
fi

if [ -e "/usr/lib/univention-install/.index.txt" ]; then
	mkdir -p /var/univention-join/
	rm -rf /var/univention-join/status
	rm /usr/lib/univention-install/.index.txt
	touch /var/univention-join/status
fi

if [ ! -e "/usr/lib/univention-install/.index.txt" ]; then
	mkdir -p /var/univention-join/
	touch /var/univention-join/status
	ln -sf /var/univention-join/status /usr/lib/univention-install/.index.txt
fi


if [ -e "/etc/univention/ssl" ]; then
	mv /etc/univention/ssl "/etc/univention/ssl_$(date +"%y%m%d%H%M")"
	mkdir /etc/univention/ssl
fi

# Stop Notifier
notifier_pid="$(pidof univention-directory-notifier)"
if [ -n "$notifier_pid" -a -e /etc/runit/univention/univention-directory-notifier ]; then
	echo -n "Stopping univention-directory-notifier daemon: "
	/etc/init.d/univention-directory-notifier stop >/dev/null 2>&1
	while ! sv status univention-directory-notifier | grep -q "^down"
	do
		sleep 1
		/etc/init.d/univention-directory-notifier stop >/dev/null 2>&1
		echo -n "."
	done
	echo " done"
fi

# Stop Listener
listener_pid="$(pidof univention-directory-listener)"
if [ -e /etc/runit/univention/univention-directory-listener ]; then
	echo -n "Stopping univention-directory-listener daemon: "
	/etc/init.d/univention-directory-listener stop >/dev/null 2>&1
	while ! sv status univention-directory-listener | grep "^down" >/dev/null
	do
		sleep 1
		/etc/init.d/univention-directory-listener stop >/dev/null 2>&1
		echo -n "."
	done
	echo " done"
fi
rm -Rf /var/lib/univention-directory-listener/*

set_kerberos_realm () {
	local DCPWD="$1"
	local DCACCOUNT="$2"
	local DCNAME="$3"
	local realm="$4"
	if [ -z "$realm" ]; then
		realm="$(univention-ssh "$DCPWD" "${DCACCOUNT}@${DCNAME}" '/usr/sbin/univention-config-registry get kerberos/realm')" >>/var/log/univention/join.log 2>&1
		if [ $? != 0 -o -z "$realm" ]; then
			echo "Unable to retrieve the kerberos realm. Try to use option -realm <kerberos/realm>"
			exit 1
		fi
	fi
	univention-config-registry set kerberos/realm="$realm" >>/var/log/univention/join.log 2>&1
}

set_windows_domain () {

	local dcpwd="$1"
	local dcaccount="$2"
	local dcname="$3"
	local windom="$4"

	if [ -z "$windom" ]; then
		windom="$(univention-ssh "$dcpwd" "${dcaccount}@${dcname}" '/usr/sbin/univention-config-registry get windows/domain')" >>/var/log/univention/join.log 2>&1
		if [ $? != 0 -o -z "$windom" ]; then
			echo "Unable to retrieve the windows/domain. Try to use option -windom <windows/domain>"
			exit 1
		fi
	fi
	univention-config-registry set windows/domain="$windom" >>/var/log/univention/join.log 2>&1
}

# get forwarder from master
set_dns_forwarder () {

	local dcpwd="$1"
	local dcaccount="$2"
	local dcname="$3"

	forwarder="$(univention-ssh "$dcpwd" "${dcaccount}@${dcname}" /usr/sbin/univention-config-registry search --brief ^dns/forwarder)"
	OLDIFS=$IFS
	IFS=$'\n'
	for i in $forwarder; do
		key=${i%%: *}
		value=${i#*: }
		if [ -n "$value" -a -n "$key" -a ! "$value" = "<empty>" ]; then
			univention-config-registry set "$key"="$value" >>/var/log/univention/join.log 2>&1
		fi
	done
	IFS=$OLDIFS
}

if [ "$server_role" = "domaincontroller_backup" ]; then

	if [ -e "/etc/ldap.secret" ]; then cat /etc/ldap.secret >>/etc/ldap.secret.SAVE; fi
	if [ -e "/etc/ldap-backup.secret" ]; then cat /etc/ldap-backup.secret >>/etc/ldap-backup.secret.SAVE; fi

	echo -n "Sync ldap.secret: "
	univention-scp "$DCPWD" -q "${DCACCOUNT}@${DCNAME}:/etc/ldap.secret" /etc/ldap.secret >>/var/log/univention/join.log 2>&1
	if [ ! -e "/etc/ldap.secret" ]; then
		failed_message "/etc/ldap.secret not found"
	fi
	echo -e "\033[60Gdone"

	echo -n "Sync ldap-backup.secret: "
	univention-scp "$DCPWD" -q "${DCACCOUNT}@${DCNAME}:/etc/ldap-backup.secret" /etc/ldap-backup.secret >>/var/log/univention/join.log 2>&1
	if [ ! -e "/etc/ldap-backup.secret" ]; then
		failed_message "/etc/ldap-backup.secret not found"
	fi
	echo -e "\033[60Gdone"

	univention-config-registry set \
		ldap/server/name="$hostname.$domainname" \
		ldap/server/ip="$IP" \
		ldap/server/port?7389 \
		ldap/master="$DCNAME" \
		ldap/master/port?7389 \
		ldap/server/type=slave \
		>>/var/log/univention/join.log 2>&1

	echo -n "Sync SSL directory: "
	univention-ssh-rsync "$DCPWD" -az "${DCACCOUNT}@${DCNAME}:/etc/univention/ssl/*" /etc/univention/ssl/ >>/var/log/univention/join.log 2>&1
	echo -e "\033[60Gdone"

	# prevent join from failing if umask is modified (Bug #21587)
	chmod 755 /etc/univention/ssl
	chmod 755 /etc/univention/ssl/ucsCA
	chmod 644 /etc/univention/ssl/ucsCA/CAcert.pem

	check_ldap_tls_connection

	download_host_certificate

	if [ ! -d "/etc/univention/ssl/$hostname" ] &&  [ ! -d "/etc/univention/ssl/$hostname.$domainname" ]; then
		echo "failed to get host certificate"
		failed_message "failed to get host certificate"
	fi

	echo -n "Sync SSL settings: "
	eval "$(univention-ssh --no-split "$DCPWD" "${DCACCOUNT}@${DCNAME}" /usr/sbin/univention-config-registry shell ssl/country ssl/state ssl/locality ssl/organization ssl/organizationalunit ssl/common ssl/email)"
	univention-config-registry set \
		ssl/country="$ssl_country" \
		ssl/state="$ssl_state" \
		ssl/locality="$ssl_locality" \
		ssl/organization="$ssl_organization" \
		ssl/organizationalunit="$ssl_organizationalunit" \
		ssl/common="$ssl_common" \
		ssl/email="$ssl_email" \
		>>/var/log/univention/join.log 2>&1
	echo -e "\033[60Gdone"

	echo -n "Restart LDAP Server: "
	/etc/init.d/slapd restart >>/var/log/univention/join.log 2>&1
	echo -e "\033[60Gdone"

	#TODO: implement a real sync
	echo -n "Sync Kerberos settings: "
	univention-scp "$DCPWD" -r "${DCACCOUNT}@${DCNAME}:/var/lib/heimdal-kdc/*" /var/lib/heimdal-kdc/ >>/var/log/univention/join.log 2>&1
	echo -e "\033[60Gdone"


	# invalidate the nscd hosts cache
	nscd -i hosts

	univention-config-registry set \
		ldap/server/name?"$DCNAME" \
		ldap/master?"$DCNAME" \
		>>/var/log/univention/join.log 2>&1

	if ! is_domain_in_admember_mode; then
		univention-config-registry set kerberos/adminserver?"$DCNAME"
	fi

	set_kerberos_realm "$DCPWD" "$DCACCOUNT" "$DCNAME" "$REALM"
	set_windows_domain "$DCPWD" "$DCACCOUNT" "$DCNAME" "$WINDOM"
	set_dns_forwarder "$DCPWD" "$DCACCOUNT" "$DCNAME"
	eval "$(univention-config-registry shell)"

	mkdir -p /var/lib/univention-ldap/notify/

	touch /var/univention-join/joined
	ln -sf /var/univention-join/joined /usr/share/univention-join/.joined

	echo -n "0" >/var/lib/univention-ldap/schema/id/id
	chown listener /var/lib/univention-ldap/schema/id/id

	check_and_configure_ad_member_mode
	run_join_scripts

elif [ "$server_role" = "domaincontroller_slave" ]; then

	echo -n "Sync ldap-backup.secret: "

	if [ -e "/etc/ldap-backup.secret" ]; then cat /etc/ldap-backup.secret >>/etc/ldap-backup.secret.SAVE; fi

	univention-scp "$DCPWD" "${DCACCOUNT}@${DCNAME}:/etc/ldap-backup.secret /etc/ldap-backup.secret" >>/var/log/univention/join.log 2>&1

	echo -e "\033[60Gdone"

	univention-config-registry set \
		ldap/server/name="$hostname.$domainname" \
		ldap/server/ip="$IP" \
		ldap/server/port?7389 \
		ldap/master="$DCNAME" \
		ldap/master/port?7389 \
		ldap/server/type=slave \
		>>/var/log/univention/join.log 2>&1

	mkdir -p /etc/univention/ssl/ucsCA
	univention-scp "$DCPWD" -q "${DCACCOUNT}@${DCNAME}:/etc/univention/ssl/ucsCA/CAcert.pem" /etc/univention/ssl/ucsCA/ >>/var/log/univention/join.log 2>&1
	if [ ! -e /etc/univention/ssl/ucsCA/CAcert.pem ]; then
		univention-scp "$DCPWD" -q "${DCACCOUNT}@${DCNAME}:/etc/univention/ssl/udsCA/CAcert.pem" /etc/univention/ssl/ucsCA/ >>/var/log/univention/join.log 2>&1
	fi

	# prevent join from failing if umask is modified (Bug #21587)
	chmod 755 /etc/univention/ssl
	chmod 755 /etc/univention/ssl/ucsCA
	chmod 644 /etc/univention/ssl/ucsCA/CAcert.pem

	check_ldap_tls_connection

	download_host_certificate

	if [ ! -d "/etc/univention/ssl/$hostname" ] &&  [ ! -d "/etc/univention/ssl/$hostname.$domainname" ]; then
		failed_message "failed to get host certificate"
	fi

	echo -n "Restart LDAP Server: "
	/etc/init.d/slapd restart >>/var/log/univention/join.log 2>&1
	echo -e "\033[60Gdone"

	echo -n "Sync Kerberos settings: "
	univention-scp "$DCPWD" -q -r "${DCACCOUNT}@${DCNAME}:/var/lib/heimdal-kdc/*" /var/lib/heimdal-kdc/ >>/var/log/univention/join.log 2>&1
	echo -e "\033[60Gdone"

	mkdir -p /var/lib/univention-ldap/notify/

	# invalidate the nscd hosts cache
	nscd -i hosts

	univention-config-registry set \
		ldap/server/name?"$DCNAME" \
		ldap/master?"$DCNAME" \
		>>/var/log/univention/join.log 2>&1

	if ! is_domain_in_admember_mode; then
		univention-config-registry set kerberos/adminserver?"$DCNAME"
	fi

	set_kerberos_realm "$DCPWD" "$DCACCOUNT" "$DCNAME" "$REALM"
	set_windows_domain "$DCPWD" "$DCACCOUNT" "$DCNAME" "$WINDOM"
	set_dns_forwarder "$DCPWD" "$DCACCOUNT" "$DCNAME"
	eval "$(univention-config-registry shell)"

	echo -n "0" >/var/lib/univention-ldap/schema/id/id
	chown listener /var/lib/univention-ldap/schema/id/id

	touch /var/univention-join/joined
	ln -sf /var/univention-join/joined /usr/share/univention-join/.joined

	check_and_configure_ad_member_mode
	run_join_scripts

elif [ "$server_role" = "memberserver" ]; then
	mkdir -p /etc/univention/ssl/ucsCA
	univention-scp "$DCPWD" -q "${DCACCOUNT}@${DCNAME}:/etc/univention/ssl/ucsCA/CAcert.pem" /etc/univention/ssl/ucsCA/ >>/var/log/univention/join.log 2>&1
	if [ ! -e /etc/univention/ssl/ucsCA/CAcert.pem ]; then
		univention-scp "$DCPWD" -q "${DCACCOUNT}@${DCNAME}:/etc/univention/ssl/udsCA/CAcert.pem" /etc/univention/ssl/ucsCA/ >>/var/log/univention/join.log 2>&1
	fi

	# prevent join from failing if umask is modified (Bug #21587)
	chmod 755 /etc/univention/ssl
	chmod 755 /etc/univention/ssl/ucsCA
	chmod 644 /etc/univention/ssl/ucsCA/CAcert.pem

	check_ldap_tls_connection

	download_host_certificate

	univention-config-registry set \
		ldap/master="$DCNAME" \
		ldap/master/port?7389 \
		>>/var/log/univention/join.log 2>&1
	grep -q '^TLS_CACERT' /etc/ldap/ldap.conf || echo "TLS_CACERT /etc/univention/ssl/ucsCA/CAcert.pem" >>/etc/ldap/ldap.conf

	# invalidate the nscd hosts cache
	nscd -i hosts

	univention-config-registry set \
		ldap/server/name?"$DCNAME" \
		ldap/server/port?7389 \
		ldap/master?"$DCNAME" \
		ldap/master/port?7389 \
		>>/var/log/univention/join.log 2>&1
    
	if ! is_domain_in_admember_mode; then
		univention-config-registry set kerberos/adminserver?"$DCNAME"
	fi

	set_kerberos_realm "$DCPWD" "$DCACCOUNT" "$DCNAME" "$REALM"
	set_windows_domain "$DCPWD" "$DCACCOUNT" "$DCNAME" "$WINDOM"
	touch /var/univention-join/joined
	ln -sf /var/univention-join/joined /usr/share/univention-join/.joined

	check_and_configure_ad_member_mode
	run_join_scripts

else
# Client and Mobile Client


	mkdir -p /etc/univention/ssl/ucsCA

	univention-scp "$DCPWD" -q "${DCACCOUNT}@${DCNAME}:/etc/univention/ssl/ucsCA/CAcert.pem" /etc/univention/ssl/ucsCA/ >>/var/log/univention/join.log 2>&1
	if [ ! -e /etc/univention/ssl/ucsCA/CAcert.pem ]; then
		univention-scp "$DCPWD" -q "${DCACCOUNT}@${DCNAME}:/etc/univention/ssl/udsCA/CAcert.pem" /etc/univention/ssl/ucsCA/ >>/var/log/univention/join.log 2>&1
	fi

	# prevent join from failing if umask is modified (Bug #21587)
	chmod 755 /etc/univention/ssl
	chmod 755 /etc/univention/ssl/ucsCA
	chmod 644 /etc/univention/ssl/ucsCA/CAcert.pem

	check_ldap_tls_connection

	download_host_certificate

	# invalidate the nscd hosts cache
	nscd -i hosts

	univention-config-registry set \
		ldap/server/name="$DCNAME" \
		ldap/server/port?7389 \
		ldap/master="$DCNAME" \
		ldap/master/port?7389 \
		kerberos/adminserver="$DCNAME" \
		nsswitch/ldap=yes \
		>>/var/log/univention/join.log 2>&1
	set_kerberos_realm "$DCPWD" "$DCACCOUNT" "$DCNAME" "$REALM"
	set_windows_domain "$DCPWD" "$DCACCOUNT" "$DCNAME" "$WINDOM"
	grep -q '^TLS_CACERT' /etc/ldap/ldap.conf || echo "TLS_CACERT /etc/univention/ssl/ucsCA/CAcert.pem" >>/etc/ldap/ldap.conf

	touch /var/univention-join/joined
	ln -sf /var/univention-join/joined /usr/share/univention-join/.joined

	eval "$(univention-config-registry shell)"

	run_join_scripts
fi

if [ -d /etc/runit/univention-directory-notifier ]; then
	/etc/init.d/univention-directory-notifier restart >>/var/log/univention/join.log 2>&1
	sleep 3
fi

if [ -d /etc/runit/univention-directory-listener ]; then
	/etc/init.d/univention-directory-listener restart >>/var/log/univention/join.log 2>&1
fi

if [ "$interfaces_${interfaces_primary:-eth0}_type" != "dhcp" ]; then
	univention-config-registry commit /etc/resolv.conf >>/var/log/univention/join.log 2>&1
fi

exit 0
# vim:set sw=4 ts=4 noet:
