#!/bin/sh
# Provision a throw-away Samba AD DC listening only on localhost and run a
# few basic bloodyAD operations (read, add, modify, delete) against it.
set -eu

if [ "$(id -u)" -ne 0 ]; then
    echo "This test needs root (provisioning chowns files, samba binds port 389)." >&2
    echo "Run it with sudo or through autopkgtest." >&2
    exit 1
fi

REALM=BLOODY.CORP
DOMAIN=bloody.corp
ADMINPASS='Admin.Passw0rd!'
USERPASS='User.Passw0rd!'
NEWPASS='New.Passw0rd!'
TESTUSER=bloodytest
BASEDN='DC=bloody,DC=corp'

WORKDIR="${AUTOPKGTEST_TMP:-$(mktemp -d)}"
SMBCONF="$WORKDIR/samba/etc/smb.conf"
SAMBA_PID=

cleanup() {
    if [ -n "$SAMBA_PID" ]; then
        kill "$SAMBA_PID" 2>/dev/null || true
        wait "$SAMBA_PID" 2>/dev/null || true
    fi
}
trap cleanup EXIT

fail() {
    echo "FAIL: $*"
    echo "----- samba log -----"
    cat "$WORKDIR/samba.log" 2>/dev/null || true
    exit 1
}

# Run bloodyAD as $BUSER, print its output and keep it in $OUT
BUSER=Administrator BPASS="$ADMINPASS"
bloody() {
    echo "\$ bloodyad -u $BUSER $*"
    OUT=$(bloodyad -H 127.0.0.1 -d "$DOMAIN" -u "$BUSER" -p "$BPASS" "$@" 2>&1) \
        || { echo "$OUT"; fail "bloodyad $* exited with an error"; }
    echo "$OUT"
}

expect() {
    printf '%s\n' "$OUT" | grep -qF -- "$1" || fail "expected output: $1"
}

echo "### Provisioning Samba AD DC ($REALM)"
# Only the LDAP service is started, bound to the loopback interface.
# xattr_tdb keeps the sysvol NT ACLs in a tdb file, as writing security.*
# xattrs is not allowed in (unprivileged) containers.
samba-tool domain provision \
    --targetdir="$WORKDIR/samba" \
    --realm="$REALM" \
    --domain=BLOODY \
    --host-name=dc1 \
    --server-role=dc \
    --dns-backend=NONE \
    --adminpass="$ADMINPASS" \
    --option="interfaces = lo" \
    --option="bind interfaces only = yes" \
    --option="server services = ldap" \
    --option="vfs objects = dfs_samba4 acl_xattr xattr_tdb" \
    --option="xattr_tdb:file = $WORKDIR/samba/xattr.tdb" \
    >"$WORKDIR/provision.log" 2>&1 \
    || { cat "$WORKDIR/provision.log"; fail "samba-tool domain provision"; }

echo "### Starting samba"
samba -s "$SMBCONF" --foreground --no-process-group >"$WORKDIR/samba.log" 2>&1 &
SAMBA_PID=$!

for _ in $(seq 60); do
    python3 -c 'import socket; socket.create_connection(("127.0.0.1", 389), 1)' \
        2>/dev/null && break
    kill -0 "$SAMBA_PID" 2>/dev/null || fail "samba exited prematurely"
    sleep 1
done

echo "### Running bloodyAD"
bloody get search --filter "(sAMAccountName=Administrator)" --attr objectSid
expect "distinguishedName: CN=Administrator,CN=Users,$BASEDN"
expect "objectSid: S-1-5-21-"

bloody add user "$TESTUSER" "$USERPASS"
expect "$TESTUSER created"

bloody add groupMember "Domain Admins" "$TESTUSER"
expect "$TESTUSER added to Domain Admins"

bloody get search --filter "(sAMAccountName=$TESTUSER)" --attr memberOf
expect "distinguishedName: CN=$TESTUSER,CN=Users,$BASEDN"
expect "memberOf: CN=Domain Admins,CN=Users,$BASEDN"

bloody set password "$TESTUSER" "$NEWPASS"
expect "Password changed successfully"

# Authenticate as the test user with its new password
BUSER="$TESTUSER" BPASS="$NEWPASS"
bloody get search --filter "(sAMAccountName=$TESTUSER)" --attr sAMAccountName
expect "sAMAccountName: $TESTUSER"
BUSER=Administrator BPASS="$ADMINPASS"

bloody remove object "$TESTUSER"
expect "$TESTUSER has been removed"

echo "\$ bloodyad -u $BUSER get search --filter (sAMAccountName=$TESTUSER) (must fail)"
OUT=$(bloodyad -H 127.0.0.1 -d "$DOMAIN" -u "$BUSER" -p "$BPASS" \
    get search --filter "(sAMAccountName=$TESTUSER)" 2>&1) \
    && fail "$TESTUSER still exists after removal"
expect "No object found"

echo "OK"
