#!/bin/bash

dbcheck_output="$(samba-tool dbcheck --attrs=member | grep '^ERROR: incorrect DN SID component for member in object')"
if [ -z "$dbcheck_output" ]; then
	echo "Nothing to do"
	exit 0
fi

target_primary_group_rid=513
echo "Trying to fix pimary group membership for group with RID $target_primary_group_rid"

echo "Stopping univention-s4-connector"
systemctl stop univention-s4-connector

privatedir=$(samba -b | sed -n 's/^   PRIVATE_DIR: //p')
samldb="$privatedir/sam.ldb"

base_ldif=$(ldbsearch -H "$samldb" -s base objectSid)
domain_sid=$(sed -n 's/^objectSid: //p' <<<"$base_ldif")
if [ -z "$domain_sid" ]; then
	echo "ERROR: Failed to look up domain sid"
	exit 1
fi

dummygroup="dummygroup3"

samba-tool group add "$dummygroup"
ldif=$(ldbsearch -H "$samldb" -d0 sAMAccountName="$dummygroup" objectSid)
dummygroup_rid=$(sed -n 's/^objectSid: S-1-5-21-.*-.*-.*-//p' <<<"$ldif")

dbcheck_output="$(samba-tool dbcheck --attrs=member | grep '^ERROR: incorrect DN SID component for member in object')"

dnlist=()

while read dbcheck_line; do
	group_dn="$(sed -n 's/^ERROR: incorrect DN SID component for member in object \(.*\) - \(<GUID=.*;<RMD_FLAGS=1>;.*\)$/\1/p' <<<"$dbcheck_line")"
	if [ -z "$group_dn" ]; then
		continue
	fi

	member_dn="$(sed -n 's/^ERROR: incorrect DN SID component for member in object \(.*\) - \(<GUID=.*;<RMD_FLAGS=1>;.*\)$/\2/p' <<<"$dbcheck_line")"
	member_ldif=$(ldbsearch -H "$samldb" -b "$member_dn")
	new_member_dn=$(sed -n s'/^dn: //p' <<<"$member_ldif")

	original_primary_group_rid=$(sed -n s'/^primaryGroupID: //p' <<<"$member_ldif")
	if [ -z "$original_primary_group_rid" ]; then
		echo "No primaryGroupID found for $member_dn"
		continue
	fi
	if [ "$original_primary_group_rid" != "$target_primary_group_rid" ]; then
		continue
	fi

	member_san=$(sed -n s'/^sAMAccountName: //p' <<<"$member_ldif")
	if [ -z "$member_san" ]; then
		echo "No sAMAccountName found for $member_dn"
		continue
	fi

	samba-tool group addmembers "$dummygroup" "$member_san"

	member_dn=$(sed -n s'/^dn: //p' <<<"$member_ldif")
	echo -e "\n### Change primaryGroupID to $dummygroup_rid"
	echo "LDIF: "
	cat <<-%EOF
	dn: $member_dn
	changetype: modify
	replace: primaryGroupID
	primaryGroupID: $dummygroup_rid
	%EOF

	ldbmodify -H "$samldb" -d0 <<-%EOF
	dn: $member_dn
	changetype: modify
	replace: primaryGroupID
	primaryGroupID: $dummygroup_rid
	%EOF

	## This seems to be necessary to update the indexed data
	ldbsearch -H "$samldb" -d0 --reveal --extended-dn --show-deleted --show-recycled -b "$new_member_dn" -s base >/dev/null 2>&1

	dnlist+=( "$member_dn" )
done <<<"$dbcheck_output"

## Now the problematic members of the group with RID $target_primary_group_rid are no more primary group members, so dbcheck should be able to fix.
samba-tool dbcheck --fix --yes

## Now restore the primary group membership of the problematic group members
original_primary_group_rid="$target_primary_group_rid"

for member_dn in "${dnlist[@]}"; do
	echo -e "\n### Change primaryGroupID back to $original_primary_group_rid"
	ldbmodify -H "$samldb" -d0 <<-%EOF
	dn: $member_dn
	changetype: modify
	replace: primaryGroupID
	primaryGroupID: $original_primary_group_rid
	%EOF
done <<<"$dbcheck_output"

## And remove the dummy group
samba-tool group delete "$dummygroup"

echo "Starting univention-s4-connector"
systemctl start univention-s4-connector
