#!/usr/share/ucs-test/runner bash
# shellcheck shell=bash
## desc: "Testing directory ACL preservation for sysvol replication"
## bugs: [33751]
## exposure: dangerous
## packages:
##  - univention-samba4
## roles:
## - domaincontroller_backup
## - domaincontroller_slave
## tags:
##  - SKIP-UCSSCHOOL
##  - basic
##  - apptest

# shellcheck source=../../lib/base.sh
. "$TESTLIBPATH/base.sh" || exit 137
# shellcheck source=../../lib/ucr.sh
. "$TESTLIBPATH/ucr.sh" || exit 137
# shellcheck source=../../lib/random.sh
. "$TESTLIBPATH/random.sh" || exit 137
. /usr/share/univention-lib/ldap.sh || exit 137

check_domainadmin_credentials || fail_fast 77 "UCR variables for admin credentials are not set"
admin_account="$(ucs_convertDN2UID "$tests_domainadmin_account")"

gpo_name=$(random_string)

### Temporarily disable rsync login for the samba4/sysvol/sync/host
### And temporarily disable regular sysvol sync on this host
ucr set \
	samba4/sysvol/sync/cron="# */5 * * * *" \
	auth/sshd/group/'DC Backup Hosts'=no \
	auth/sshd/group/'DC Slave Hosts'=no \
	auth/sshd/group/'Computers'=no

### Cleanup function
cleanup () {
	ucr_restore

	[ -n "$gpo_cn" ] || exit 0
	samba-tool gpo del "$gpo_cn" -U "$admin_account%$tests_domainadmin_pwd"
	[ -n "$gpo_path" ] && rm -rf "$gpo_path"

	smbclient "//${samba4_sysvol_sync_host:?}/sysvol" \
		-U "${admin_account}%${tests_domainadmin_pwd}" \
		-c "deltree ${domainname}/Policies/${gpo_cn}"
}
trap cleanup EXIT

### create a new GPO remotely on the samba4/sysvol/sync/host:
test_output=$(samba-tool gpo create "$gpo_name" \
	-U "$admin_account%$tests_domainadmin_pwd" \
	-H "ldap://$samba4_sysvol_sync_host") ||
	fail_fast 110 "samba-tool gpo create exited with status $?"
gpo_cn=$(sed -n "s/GPO '$gpo_name' created as \(.*\)$/\1/p" <<<"$test_output")
[ -n "$gpo_cn" ] ||
	fail_fast 110 "GPO creation failed"
echo "Test GPO created: $gpo_cn"


### Replicate the new GPO to the local system
/usr/share/univention-samba4/scripts/sysvol-sync.sh

### for additional fun add a test file to the GPO dir on the samba4/sysvol/sync/host:
smbclient "//${samba4_sysvol_sync_host:?}/sysvol" \
	-U "${admin_account}%${tests_domainadmin_pwd}" \
	-c "put /etc/hosts ${domainname}/Policies/${gpo_cn}/testfile1" ||
	fail_fast 110 "smbclient //$samba4_sysvol_sync_host/sysvol exited with status $?"


### Now modify the ACLs on the local GPO copy
gpo_path="/var/lib/samba/sysvol/$domainname/Policies/$gpo_cn"
start_gpo_ntacl=$(samba-tool ntacl get --as-sddl "$gpo_path")


test_account=join-backup
test_account_sid=$(univention-s4search samaccountname="$test_account" objectSid | VAL objectSid)

## This sleep 1 seems necessary to avoid occasional test failures where rsync
## is not considering the local modification time to be more recent than the
## remote one due to a "same second" issue
sleep 1

### Update the NTACLs on the local SYSVOL share via SMB
test_ntace="(A;OICI;0x1200a9;;;$test_account_sid)"
tmp_gpo_ntacl="${start_gpo_ntacl}$test_ntace"
smbcacls //localhost/sysvol "$domainname/Policies/$gpo_cn" -U "$admin_account%$tests_domainadmin_pwd" -S "$tmp_gpo_ntacl" --sddl

custom_gpo_modification_time=$(stat --printf '%y' "$gpo_path")
custom_gpo_metadata_change_time=$(stat --printf '%z' "$gpo_path")
custom_gpo_ntacl=$(samba-tool ntacl get --as-sddl "$gpo_path")	## get in canonical order
custom_gpo_facl=$(getfacl "$gpo_path")
custom_gpo_fattr=$(getfattr -d -m - "$gpo_path")
echo "Start with GPO NTACL: $start_gpo_ntacl"
echo "Customized GPO NTACL: $custom_gpo_ntacl"

grep -q "$test_ntace" <<<"$custom_gpo_ntacl" ||
	fail_fast 110 "NTACL set via SMB failed"

### Updating the DS ACLs is a bit useless here, but this is how we could do it:
# test_output=$(univention-s4search "(&(objectClass=groupPolicyContainer)(cn=$gpo_cn))" nTSecurityDescriptor | ldapsearch-wrapper)
# gpo_dn=$(VAL dn <<"$test_output")
# gpo_sd=$(VAL nTSecurityDescriptor <<"$test_output")
# new_gpo_sd="${gpo_sd}(A;CI;RPLCRC;;;$test_account_sid)(OA;CI;CR;edacfd8f-ffb3-11d1-b41d-00a0c968f939;;$test_account_sid)"
# ldbmodify -H /var/lib/samba/private/sam.ldb "(&(objectClass=groupPolicyContainer)(cn=$gpo_cn))" <<%EOF
# dn: $gpo_dn
# changetype: modify
# nTSecurityDescriptor: $new_gpo_sd
# %EOF

### Now replicate the GPO again to the local system
/usr/share/univention-samba4/scripts/sysvol-sync.sh

## verify that the testfile1 has been copied to the local system:
[ -f "$gpo_path/testfile1" ] ||
	fail_fast 110 "The GPO has not been copied to the local server"

replicated_gpo_modification_time=$(stat --printf '%y' "$gpo_path")
replicated_gpo_metadata_change_time=$(stat --printf '%z' "$gpo_path")
replicated_gpo_ntacl=$(samba-tool ntacl get --as-sddl "$gpo_path")
replicated_gpo_facl=$(getfacl "$gpo_path")
replicated_gpo_fattr=$(getfattr -d -m - "$gpo_path")
echo "Customized GPO modification time: $custom_gpo_modification_time"
echo "Replicated GPO modification time: $replicated_gpo_modification_time"
echo "Customized GPO metadata time: $custom_gpo_metadata_change_time"
echo "Replicated GPO metadata time: $replicated_gpo_metadata_change_time"
echo "Customized GPO NTACL: $custom_gpo_ntacl"
echo "Replicated GPO NTACL: $replicated_gpo_ntacl"

grep -q "$test_ntace" <<<"$replicated_gpo_ntacl" ||
	fail_test 110 "The GPO NTACL has been modified"
[ "$replicated_gpo_facl" = "$custom_gpo_facl" ] ||
	fail_test 110 "The GPO fACL has been modified"
[ "$replicated_gpo_fattr" = "$custom_gpo_fattr" ] ||
	fail_test 110 "The GPO fattrs have been modified"

exit "$RETVAL"
