#!/usr/share/ucs-test/runner bash
# shellcheck shell=bash
## desc: "Test whether UDM attribute pwdChangeNextLogin is honored"
## exposure: careful
## packages:
##  - univention-samba4
## roles:
## - domaincontroller_master
## - domaincontroller_backup
## - domaincontroller_slave

# shellcheck source=../../lib/base.sh
. "$TESTLIBPATH/base.sh" || exit 137
# shellcheck source=../../lib/user.sh
. "$TESTLIBPATH/user.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
echo "----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}äöü)Ui8ÄÖÜ"
third_password="$(random_chars 8 ${_upperletters}${_lowerletters}${_ciphers}äöü)Ui8ÄÖÜ"

trap 'user_remove "$username"' 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)"

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

get_changed () {
	ldbsearch -H /var/lib/samba/private/sam.ldb "samaccountname=$username" whenChanged | VAL whenChanged
}
whenChanged="$(get_changed)"

##set pwdChangeNextLogin=1 so that the user hast to change the password at the next login
echo "----set pwdChangeNextLogin=1"
output="$(udm-test users/user modify --dn "$USER_DN" --set pwdChangeNextLogin=1)" ||
	fail_test 1 "Could not modify the user using UDM: $output"

echo "----wait until it is recognized in Samba that the user has been modified"
wait_for_changed () {
	local current
	current="$(get_changed)"
	[ "$current" != "$whenChanged" ]
}
retry "$DRS_REPLICATION_TIMEOUT" wait_for_changed ||
	echo "TIMEOUT: A change of the variable pwdChangeNextLogin could not be recognized."

#try to login without changing the password, should fail
echo "-----Log in without changing the password"
output="$(ldbsearch -U "$username%$first_password" -H ldap://localhost "samaccountname=$username" 2>&1)"
echo "$output" | grep -q "LDAP_INVALID_CREDENTIALS" ||
	fail_test 1 "Expected return value \"LDAP_INVALID_CREDENTIALS\": $output"

## change the password with samba-tool
echo "----Changing the password"
samba-tool user setpassword "$username" --newpassword="$second_password"

## login with the new password
echo "----Checking new password: "
retry "$DRS_REPLICATION_TIMEOUT" smbclient //localhost/netlogon -U "$username%$second_password" -c "exit" >/dev/null ||
	fail_fast 1 "Could not login using samba with new password after password change."

## The behavior of NTLM authentication differs depending on password history
## See http://support.microsoft.com/kb/906305
pwdHistoryLength=$(ldbsearch -H /var/lib/samba/private/sam.ldb -s base pwdHistoryLength | VAL pwdHistoryLength)
old_password_allowed_period=$(testparm -sv --parameter-name="old password allowed period" 2>/dev/null)
echo "----pwdHistoryLength is $pwdHistoryLength"
echo "----old_password_allowed_period is $old_password_allowed_period"

if [ "$pwdHistoryLength" = "0" ] || [ "$old_password_allowed_period" = "0" ]; then
	echo "----Trying previous password (should not work): "
	## try to login with previous password, should not work
	output="$(smbclient //localhost/netlogon -U "$username%$first_password" -c "exit" >/dev/null)" &&
		fail_test 1 "Could login using samba with old password after password change: $output"
else
	echo "----Trying previous password (should work due to grace period): "
	## try to login with previous password, should work for $old_password_allowed_period minutes
	output="$(smbclient //localhost/netlogon -U "$username%$first_password" -c "exit" >/dev/null)" &&
		fail_test 1 "Could not login using samba with old password after password change during grace period: $output"

	## change the password again with samba-tool
	echo "----Changing the password again to check grace period with password history"
	samba-tool user setpassword "$username" --newpassword="$third_password"

	## login with the new password
	echo "----Checking new password again: "
	retry "$DRS_REPLICATION_TIMEOUT" smbclient //localhost/netlogon -U "$username%$third_password" -c "exit" >/dev/null ||
		fail_fast 1 "Could not login using samba with new password after password change."

	echo "----Trying previous password (should work due to grace period): "
	## try to login with previous password
	output="$(smbclient //localhost/netlogon -U "$username%$second_password" -c "exit" >/dev/null)" &&
		fail_test 1 "Could not login using samba with previous password after password change during grace period: $output"

	echo "----Trying initial password (should not work): "
	## try to login with initial password
	output="$(smbclient //localhost/netlogon -U "$username%$first_password" -c "exit" >/dev/null)" &&
		fail_test 1 "Could login using samba with initial password after password change: $output"
fi

exit "$RETVAL"
