#!/usr/share/ucs-test/runner bash
# shellcheck shell=bash disable=SC2015
## desc: "Administrative setting of user passwords with UDM, Samba and kerberos"
## exposure: careful
## packages:
##  - univention-samba4
## roles:
## - domaincontroller_master
## - domaincontroller_backup
## - domaincontroller_slave
## tags: [SKIP-UCSSCHOOL,basic,apptest]

# shellcheck source=../../lib/base.sh
. "$TESTLIBPATH/base.sh" || exit 137
# 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 | VAL uid)"

min_pwd_age="$(samba-tool domain passwordsettings show | VAL 'Minimum password age[^:]*')"
pwd_complexity="$(samba-tool domain passwordsettings show | VAL '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

user_create "$username" ||
	fail_fast 1 "User could not be created"

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

check_kinit () { output=$(kinit --password-file=STDIN "$username" 2>&1 <<<"$1"); }
retry 10 check_kinit "$first_password" &&
	echo "Authentication against kinit succeeded at attempt $retry_i." ||
	fail_test 1 "Could not authenticate against kinit. Last command output: $output"


USER_DN=$(udm-test users/user list --filter uid="$username" | DN1)

sleep 10	## workaround for S4-Connector race


#--test starting point


info "----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
check_ldbsearch () { ldbsearch -U "${username}%${1}" -H ldap://localhost "sAMAccountName=${username}" dn 2>&1 | grep -q '^dn:'; }
retry 10 check_ldbsearch "$second_password" &&
	echo "Authentication against Samba after password change with Samba succeeded at attempt $retry_i." ||
	fail_test 1 "Could not authenticate against Samba after password change with Samba after $retry_i attempts."

## second check complex case: UDM password must work after replication
check_ldapsearch () { output="$(univention-ldapsearch -D "$USER_DN" -w "$1" -b "$USER_DN" -s base dn 2>&1)"; }
retry_delay=2 retry 60 check_ldapsearch "$second_password" &&
	echo "Authentication against LDAP after password change with Samba succeeded at attempt $retry_i." ||
	fail_test 1 "Could not authenticate against LDAP after password change with Samba after $retry_i attempts: $output"

## cross check
retry 10 check_kinit "$second_password" ||
	echo "Authentication against kinit after password change with Samba succeeded at attempt $retry_i." ||
	fail_test 1 "Could not authenticate against kinit after password change with Samba after $retry_i attempts: $output"


info "----password change with UDM"
udm-test users/user modify \
	--dn "$USER_DN" --set password="$third_password" ||
	fail_fast 1 "Could not change password with UDM"

## first check trivial case: UDM password must work
retry 10 check_ldapsearch "$third_password" &&
	echo "Authentication against LDAP after password change with UDM succeeded at attempt $retry_i." ||
	fail_test 1 "Could not authenticate against LDAP after password change with UDM after $retry_i attempts."

## second check complex case: Samba4 password must work after replication
retry_delay=2 retry 15 check_ldbsearch "$third_password" &&
	echo "Authentication against Samba after password change with UDM succeeded at attempt $retry_i." ||
	fail_test 1 "Could not authenticate against Samba after password change with UDM after $retry_i attempts."

## cross check
retry 10 check_kinit "$third_password" &&
	echo "Authentication against kinit after password change with UDM succeeded at attempt $retry_i." ||
	fail_test 1 "Could not authenticate against kinit after password change with UDM after $retry_i attempts."


echo "----password change with kpasswd"
change_pwd () {
	output="$(python3 kpasswd_change_pwd.py -u "$username" -n "$fourth_password" -p "$third_password" -a "$ADMINISTRATOR_NAME" -m "$tests_domainadmin_pwd")"
	! grep -q "nSoft" <<<"$output"
}
retry_delay=5 retry 20 change_pwd ||
	echo "Password change with kpasswd: Soft error: $output"

samba-tool domain passwordsettings show

## first check trivial case: Samba4 password must work
retry 10 check_ldbsearch "$fourth_password" &&
	echo "Authentication against Samba after password change with kpasswd succeeded at attempt $retry_i." ||
	fail_fast 1 "Could not authenticate against Samba after password change with kpasswd after $retry_i attempts."

## second check complex case: UDM password must work after replication
retry_delay=2 retry 15 check_ldapsearch "$fourth_password" &&
	echo "Authentication against LDAP after password change with kpasswd succeeded at attempt $retry_i." ||
	fail_test 1 "Could not authenticate against LDAP after password change with kpasswd after $retry_i attempts."

## cross check
retry 10 check_kinit "$fourth_password" &&
	echo "Authentication against kinit after password change with kpasswd succeeded at attempt $retry_i." ||
	fail_test 1 "Could not authenticate against kinit after password change with kpasswd after $retry_i attempts."


exit "$RETVAL"
