#!/usr/share/ucs-test/runner bash 
# shellcheck shell=bash
## desc: "Test password change on next logon"
## exposure: dangerous
## packages:
## - univention-ad-connector
## tags:
##  - skip_admember
## bugs:
##  - 51298

# shellcheck source=../../lib/base.sh
. "$TESTLIBPATH/base.sh" || exit 137
# shellcheck source=../../lib/udm.sh
. "$TESTLIBPATH/udm.sh" || exit 137
# shellcheck source=../../lib/random.sh
. "$TESTLIBPATH/random.sh" || exit 137

. "adconnector.sh" || exit 137
test -n "$connector_ad_ldap_host" || exit 137

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

function ad_create_user_with_must_change_at_next_login () {
	local username="$1"
	local password="$2"
	local host="$(ucr get connector/ad/ldap/host)"
	local admin="$(ucr get connector/ad/ldap/binddn | sed 's/,.*//;s/cn=//i')"
	local pass="$(cat $(ucr get connector/ad/ldap/bindpw))"
	samba-tool user create --must-change-at-next-login --use-username-as-cn "$username" "$password" --URL="ldap://$host" -U"$admin"%"$pass"
	return $?
}

function ad_create_user_with_password () {
	local username="$1"
	local password="$2"
	local host="$(ucr get connector/ad/ldap/host)"
	local admin="$(ucr get connector/ad/ldap/binddn | sed 's/,.*//;s/cn=//i')"
	local pass="$(cat $(ucr get connector/ad/ldap/bindpw))"
	samba-tool user create --use-username-as-cn "$username" "$password" --URL="ldap://$host" -U"$admin"%"$pass"
	return $?
}

ad_reset_user_password () {
	local username="$1"
	local password="$2"
	local host="$(ucr get connector/ad/ldap/host)"
	local admin="$(ucr get connector/ad/ldap/binddn | sed 's/,.*//;s/cn=//i')"
	local pass="$(cat $(ucr get connector/ad/ldap/bindpw))"
	samba-tool user setpassword --must-change-at-next-login --newpassword="$password" "$username" --URL="ldap://$host" -U"$admin"%"$pass"
	return $?
}

test_smbclient_pwd_must_change () {
	local username="$1"
	local password="$2"
	local retval=0
	info "EXECUTING smbclient -U $username ... | grep NT_STATUS_PASSWORD_MUST_CHANGE"
	smbclient -U"$username%$password" //$(ucr get connector/ad/ldap/host)/sysvol -c ls | grep NT_STATUS_PASSWORD_MUST_CHANGE
	retval=$?
	info "SMBCLIENT: got $retval for grep NT_STATUS_PASSWORD_MUST_CHANGE"
	return $retval
}

test_ldap_pwd_must_change () {
	local username="$1"
	local password="$2"
	local retval=0
	info "EXECUTING univention-ldapsearch -D uid=$username, ... | grep password expired"
	univention-ldapsearch -D "uid=$username,cn=users,$(ucr get ldap/base)" -w "$password" uid="$username" 2>&1 | grep "password expired"
	retval=$?
	info "LDAP: got $retval for grep password expired"
	return $retval
}
test_umc_login () {
	local username="$1"
	local password="$2"
	info "EXECUTING umc-command -U username -P password and check if still expired after authentication (Bug #51462)"
	umc-command -U "$username" -P "$password"
	udm_verify_ldap_attribute "shadowMax" "1" "users/user" || fail_test 110
	udm_verify_ldap_attribute "krb5PasswordEnd" "$(date +%Y%m%d000000Z)" "users/user" || fail_test 110

}

test_kinit_pwd_must_change () {
	local username="$1"
	local password="$2"
	local retval=0
	info "EXECUTING kinit --password-file= ...$username | grep password will expire"
	kinit --password-file="/tmp/$username" "$username" &>> "/tmp/""$username""out.log" &
	pid=$!
	sleep 3
	kill $pid
	cat "/tmp/""$username""out.log" | grep "expire"
	retval=$?
	info "KINIT: got $retval for grep password expired"
	return $retval
}

SYNCMODE="$(ad_get_sync_mode)"
ad_set_sync_mode "sync"

user1="$(random_chars)"
user2="$(random_chars)"
user3="$(random_chars)"
user4="$(random_chars)"

echo -e "\n##################################################"
echo 'section "AD user with --must-change-at-next-login"'
echo -e "##################################################\n"
UDM_users_user_username="$user1"
UDM_users_user_password="Univention.99"
AD_DN="CN=$UDM_users_user_username,CN=users,$(ad_get_base)"
ad_create_user_with_must_change_at_next_login "$UDM_users_user_username" "$UDM_users_user_password"
echo "$UDM_users_user_password" >> "/tmp/$UDM_users_user_username"
ad_wait_for_synchronization; fail_bool 0 110
# check ad user
ad_verify_attribute "$AD_DN" "pwdLastSet" "0" || fail_test 110
test_smbclient_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
# check ucs user
udm_verify_ldap_attribute "shadowMax" "1" "users/user" || fail_test 110
udm_verify_ldap_attribute "krb5PasswordEnd" "$(date +%Y%m%d000000Z)" "users/user" || fail_test 110
test_umc_login "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
test_kinit_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
test_smbclient_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
test_ldap_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110

echo -e "\n##################################################"
echo 'section "New AD user, sync, only change --must-change-at-next-login in ad"'
echo -e "##################################################\n"
UDM_users_user_username="$user2"
UDM_users_user_password="Univention.99"
AD_DN="CN=$UDM_users_user_username,CN=users,$(ad_get_base)"
ad_create_user_with_password "$UDM_users_user_username" "$UDM_users_user_password"
echo "$UDM_users_user_password" >> "/tmp/$UDM_users_user_username"
ad_wait_for_synchronization; fail_bool 0 110
# check ad user - attribute should NOT be set this way
ad_verify_attribute "$AD_DN" "pwdLastSet" "0" && fail_test 110
test_smbclient_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" && fail_test 110
# set must-change-at-next-login
ad_set_attribute "$AD_DN" "pwdLastSet" "0" || fail_test 110
# check ad user
ad_wait_for_synchronization; fail_bool 0 110
ad_verify_attribute "$AD_DN" "pwdLastSet" "0" || fail_test 110
test_smbclient_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
# check ucs user
udm_verify_ldap_attribute "shadowMax" "1" "users/user" || fail_test 110
udm_verify_ldap_attribute "krb5PasswordEnd" "$(date +%Y%m%d000000Z)" "users/user" || fail_test 110
test_umc_login "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
test_kinit_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
test_smbclient_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
test_ldap_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110

echo -e "\n##################################################"
echo 'section "UCS user with --pwdChangeNextLogin"'
echo -e "###################################################\n"
UDM_users_user_username="$user3"
UDM_users_user_lastname="lastname"
UDM_users_user_password="Univention.99"
AD_DN="CN=$UDM_users_user_username,CN=users,$(ad_get_base)"
UDM_users_user_pwdChangeNextLogin="1"
udm_create "users/user" || fail_test 110
echo "$UDM_users_user_password" >> "/tmp/$UDM_users_user_username"
ad_wait_for_synchronization; fail_bool 0 110
# check ucs user
udm_verify_ldap_attribute "shadowMax" "1" "users/user" || fail_test 110
udm_verify_ldap_attribute "krb5PasswordEnd" "$(date +%Y%m%d000000Z)" "users/user" || fail_test 110
# check ad user
ad_verify_attribute "$AD_DN" "pwdLastSet" "0"
test_kinit_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
test_smbclient_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110
test_ldap_pwd_must_change "$UDM_users_user_username" "$UDM_users_user_password" || fail_test 110

echo -e "\n##################################################"
echo 'section "AD user with --pwdChangeNextLogin change password twice without resetting pwdChangeNextLogin"'
echo -e "###################################################\n"
irrelevant="$(ucr get connector/ad/mapping/attributes/irrelevant)"
ucr unset connector/ad/mapping/attributes/irrelevant
invoke-rc.d univention-ad-connector restart
UDM_users_user_username="$user4"
UDM_users_user_password="Univention.99"
AD_DN="CN=$UDM_users_user_username,CN=users,$(ad_get_base)"
ad_create_user_with_must_change_at_next_login "$UDM_users_user_username" "$UDM_users_user_password"
new_password="Laberrhababer123"
echo "$new_password" >> "/tmp/$UDM_users_user_username"
ad_wait_for_synchronization; fail_bool 0 110
ad_reset_user_password "$UDM_users_user_username" "$new_password"
ad_wait_for_synchronization; fail_bool 0 110
# check ad user
ad_verify_attribute "$AD_DN" "pwdLastSet" "0" || fail_test 110
test_smbclient_pwd_must_change "$UDM_users_user_username" "$new_password" || fail_test 110
# check ucs user
udm_verify_ldap_attribute "shadowMax" "1" "users/user" || fail_test 110
udm_verify_ldap_attribute "krb5PasswordEnd" "$(date +%Y%m%d000000Z)" "users/user" || fail_test 110
test_umc_login "$UDM_users_user_username" "$new_password" || fail_test 110
test_kinit_pwd_must_change "$UDM_users_user_username" "$new_password" || fail_test 110
test_smbclient_pwd_must_change "$UDM_users_user_username" "$new_password" || fail_test 110
test_ldap_pwd_must_change "$UDM_users_user_username" "$new_password" || fail_test 110
#################
section "Cleanup"
#################

UDM_users_user_username="$user1"
udm_remove "users/user" || fail_test 110
UDM_users_user_username="$user2"
udm_remove "users/user" || fail_test 110
UDM_users_user_username="$user3"
udm_remove "users/user" || fail_test 110
UDM_users_user_username="$user4"
udm_remove "users/user" || fail_test 110
ad_wait_for_synchronization; fail_bool 0 110
udm_exists "users/user"; fail_bool 1 110
ad_exists "$AD_DN"; fail_bool 1 110
ucr set connector/ad/mapping/attributes/irrelevant="$irrelevant"
invoke-rc.d univention-ad-connector restart
ad_set_sync_mode "$SYNCMODE"

exit "$RETVAL"
