#!/usr/share/ucs-test/runner bash
# shellcheck shell=bash
## desc: "Administrative setting of user passwords with udm, samba and kerberos"
## exposure: safe
## packages:
##  - univention-samba4
## roles:
## - domaincontroller_master
## - domaincontroller_backup
## - domaincontroller_slave
## tags: [SKIP-UCSSCHOOL,basic,apptest]
# shellcheck source=../../lib/user.sh
. "$TESTLIBPATH/user.sh" || exit 137
# shellcheck source=../../lib/shares.sh
. "$TESTLIBPATH/shares.sh" || exit 137
# shellcheck source=../../lib/random.sh
. "$TESTLIBPATH/random.sh" || exit 137
# shellcheck source=../../lib/samba.sh
. "$TESTLIBPATH/samba.sh" || exit 137

#----create User
SAMBA="true"
MAIL="false"
KERBEROS="true"
PERSON="false"
POSIX="true"

username="$(user_randomname)"
first_password=univention
second_password="$(random_chars 8 ${_upperletters}${_lowerletters}${_ciphers}äöü)z1AÄÖÜ"
third_password="$(random_chars 8 ${_upperletters}${_lowerletters}${_ciphers}äöü)z1AÄÖÜ"
fourth_password="$(random_chars 8 ${_upperletters}${_lowerletters}${_ciphers}äöü)z1AÄÖÜ"

check_domainadmin_credentials || fail_fast 77 "UCR variables for admin credentials are not set"
ADMINISTRATOR_NAME="$(univention-ldapsearch -b "$tests_domainadmin_account" uid | grep uid | sed -ne 's/^uid: //p')"

min_pwd_age="$(samba-tool domain passwordsettings show | grep "Minimum password age" | sed s/[^0-9]*/""/)"
pwd_complexity="$(samba-tool domain passwordsettings show | grep complexity | sed "s/Password complexity: //")"
samba-tool domain passwordsettings set --complexity=off --min-pwd-age=0
trap 'user_remove "$username"; samba-tool domain passwordsettings set --min-pwd-age="$min_pwd_age" --complexity="$pwd_complexity"' INT TERM EXIT

if ! user_create "$username"; then
	fail_fast 1 "User could not be created"
fi

wait_for_replication
# force_drs_replication
wait_for_drs_replication "(sAMAccountName=$username)"

max_i=10
delta_t=1
i=0
while ! command_output=$(echo "$first_password" | kinit --password-file=STDIN "$username" 2>&1)
do
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		fail_test 1 "Could not authenticate against kinit. Last command output:"
		echo "$command_output"
		break
	fi
	sleep "$delta_t"
done
echo "Authentication against kinit succeeded at attempt $((i+1))."

USER_DN=$(udm-test users/user list --filter uid="$username" | sed -ne 's/^DN: //p')

sleep 10	## workaround for S4-Connector race

#--test starting point
#----password change with samba-tool
echo "----password change with samba-tool"
samba-tool user setpassword "$username" --newpassword="$second_password"

force_drs_replication -o

## first check trivial case: Samba4 password must work
max_i=10
delta_t=1
i=0
while ! ldbsearch -U "$username%$second_password" -H ldap://localhost "sAMAccountName=$username" dn 2>&1 | grep -q '^dn:'
do
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		fail_test 1 "Could not authenticate against samba after password change with samba."
		break
	fi
	sleep "$delta_t"
done
if [ "$i" -ne 0 ]; then
	echo -n "WARNING: "
fi
if [ "$i" -ne "$max_i" ]; then
	echo "Authentication against samba after password change with samba succeeded at attempt $((i+1))."
fi


## second check complex case: UDM password must work after replication
max_i=60
delta_t=2
i=0
while ! output="$(univention-ldapsearch -D "$USER_DN" -w "$second_password" -b "$USER_DN" dn 2>&1 )"
do
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		echo "$output"
		fail_test 1 "Could not authenticate against LDAP after password change with samba after $i attempts."
		break
	fi
	sleep "$delta_t"
done
if [ "$i" -ne "$max_i" ]; then
	echo "Authentication against LDAP after password change with samba succeeded at attempt $((i+1))."
fi

## cross check
max_i=10
delta_t=1
i=0
while ! command_output=$(echo "$second_password" | kinit --password-file=STDIN "$username" 2>&1)
do
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		fail_test 1 "Could not authenticate against kinit after password change with samba after $i attempts."
		echo "$command_output"
		break
	fi
	sleep "$delta_t"
done
if [ "$i" -ne "$max_i" ]; then
	echo "Authentication against kinit after password change with samba succeeded at attempt $((i+1))."
fi

echo "----password change with udm"
#----password change with udm
udm-test users/user modify \
	--dn "$USER_DN" --set password="$third_password"
if [ "$?" != 0 ]; then
	fail_fast 1 "Could not change password with UDM"
fi

## first check trivial case: UDM password must work
max_i=10
delta_t=1
i=0
while ! output="$(univention-ldapsearch -D "$USER_DN" -w "$third_password" -b "$USER_DN" dn 2>&1 )"
do
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		echo "$output"
		fail_test 1 "Could not authenticate against LDAP after password change with UDM after $i attempts."
		break
	fi
	sleep "$delta_t"
done
if [ "$i" -ne 0 ]; then
	echo -n "WARNING: "
fi
if [ "$i" -ne "$max_i" ]; then
	echo "Authentication against LDAP after password change with UDM succeeded at attempt $((i+1))."
fi

## second check complex case: Samba4 password must work after replication
max_i=15
delta_t=2
i=0
while ! ldbsearch -U "$username%$third_password" -H ldap://localhost "sAMAccountName=$username" dn 2>&1 | grep -q '^dn:'
do
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		fail_test 1 "Could not authenticate against samba after password change with UDM after $i attempts."
		break
	fi
	sleep "$delta_t"
done
if [ "$i" -ne "$max_i" ]; then
	echo "Authentication against samba after password change with UDM succeeded at attempt $((i+1))."
fi

## cross check
max_i=10
delta_t=1
i=0
while ! output="$(echo "$third_password" | kinit --password-file=STDIN "$username" 2>&1)"
do
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		echo "$output"
		fail_test 1 "Could not authenticate against kinit after password change with UDM after $i attempts."
		break
	fi
	sleep "$delta_t"
done
if [ "$i" -ne "$max_i" ];then
	echo "Authentication against kinit after password change with UDM succeeded at attempt $((i+1))."
fi
echo "----password change with kpasswd"
#----password change with kpassword
max_i=20
delta_t=5
i=0
while true
do
	retval="$(python3 kpasswd_change_pwd.py -u "$username" -n "$fourth_password" -p "$third_password" -a "$ADMINISTRATOR_NAME" -m "$tests_domainadmin_pwd")"
	echo "$retval" | grep "nSoft" || break
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		echo "Password change with kpasswd: Soft error."
		break
	fi
	sleep "$delta_t"
done

samba-tool domain passwordsettings show

## first check trivial case: Samba4 password must work
max_i=10
delta_t=1
i=0
while ! ldbsearch -U "$username%$fourth_password" -H ldap://localhost "sAMAccountName=$username" dn 2>&1 | grep -q '^dn:'
do
	let i=$i+1
	if [ "$i" = "$max_i" ]; then
		fail_fast 1 "Could not authenticate against samba after password change with kpasswd after $i attempts."
		break
	fi
	sleep "$delta_t"
done
if [ "$i" -ne 0 ]; then
	echo -n "WARNING: "
fi
if [ "$i" -ne "$max_i" ]; then
	echo "Authentication against samba after password change with kpasswd succeeded at attempt $((i+1))."
fi

## second check complex case: UDM password must work after replication
max_i=15
delta_t=2
i=0
while ! output="$(univention-ldapsearch -D "$USER_DN" -w "$fourth_password" -b "$USER_DN" dn 2>&1 )"
do
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		echo "$output"
		fail_test 1 "Could not authenticate against UDM after password change with kpasswd after $i attempts."
		break
	fi
	sleep "$delta_t"
done
if [ "$i" -ne "$max_i" ]; then
	echo "Authentication against LDAP after password change with kpasswd succeeded at attempt $((i+1))."
fi

## cross check
max_i=10
delta_t=1
i=0
while ! output="$(echo "$fourth_password" | kinit --password-file=STDIN "$username" 2>&1)"
do
	let i="$i"+1
	if [ "$i" = "$max_i" ]; then
		echo "$output"
		fail_test 1 "Could not authenticate against kinit after password change with kpasswd after $i attempts."
		break
	fi
	sleep "$delta_t"
done
if [ "$i" -ne "$max_i" ]; then
	echo "Authentication against kinit after password change with kpasswd succeeded at attempt $((i+1))."
fi

exit $RETVAL
