#!/bin/bash
set -e
set -o pipefail
set -u
#
# This test tests the bconsole against the bareos-dir using PAM authentication.
#
# Requires:
# on Debian following packages must be installed:
#   libpam-modules (for pam_exec.so),
#   libpam-wrapper,
#   pamtester
# On Fedora, the names are similar: pam, pam-wrapper, pamtester.
#
# If they are not available, the test will be disabled by cmake.
#
# PAM is configured to accept all users where USERNAME = PASSWORD.
#
# Interactive PAM login in bconsole does not work,
# as the configured PAM module does not ask for the username.
# However, providing the PAM credentials to bconsole as file (bconsole -p CREDENTIALS_FILE) does work.
#
TestName="$(basename "$(pwd)")"
export TestName

#shellcheck source=../../environment.in
. ./environment

usepam_and_acl_config=$conf/bareos-dir.d/console/has_usepam_and_profile_with_acl.conf
rm -f $usepam_and_acl_config

JobName=backup-bareos-fd
#shellcheck source=../../scripts/functions
. "${rscripts}"/functions
"${rscripts}"/cleanup
"${rscripts}"/setup

start_test

export PAM_WRAPPER=1
export PAM_WRAPPER_SERVICE_DIR=${current_test_directory}/etc/pam.d/bareos
# PAM_WRAPPER creates extra environments in /tmp/pam.*/
# However, these are removed when bareos-dir daemonized.
# This settings keeps them all.
# Other workaround: don't let bareos-dir daemonize itself,
# but use foreground and ampersand (-f and &)
#export PAM_WRAPPER_KEEP_DIR=1

# PAM_WRAPPER_LIBRARIES has to set be cmake

# check if we linked to libasan, if so we'll need to preload that library first
libasan="$(ldd "${BAREOS_DIRECTOR_BINARY}" | awk '/libasan.so/ { print $3 }')"

preload_libs="${PAM_WRAPPER_LIBRARIES}"
if [ -n "$libasan" ]; then
  preload_libs="${libasan}:${preload_libs}"
fi

output=/dev/null
if is_debug; then
  export PAM_WRAPPER_DEBUGLEVEL=4
  output=/dev/stdout
  LD_PRELOAD="${preload_libs}" "${BAREOS_DIRECTOR_BINARY}" -c "${conf}" -f -d 200 >$output 2>&1 &
else
  LD_PRELOAD="${preload_libs}" "${BAREOS_DIRECTOR_BINARY}" -c "${conf}" -f >$output 2>&1 &
fi

sleep 1

cat <<END_OF_DATA >"$tmp"/bconcmds
@$out $tmp/log1.out
status director
quit
END_OF_DATA

if ! "${BAREOS_BCONSOLE_BINARY}" -c "${conf}" -p etc/user1.cred <"$tmp"/bconcmds >"${tmp}"/log1.out 2>"${tmp}"/err1.out; then
  cat "${tmp}"/log1.out
  cat "${tmp}"/err1.out
  set_error "Failed to login as user user1."
  exit 1
fi

if ! grep -q "Running Jobs:" "${tmp}"/log1.out; then
  cat "${tmp}"/log1.out
  set_error "Unexpected output in user1 session."
  exit 1
fi

print_debug "OK: login as user1 succeeded."

if "${BAREOS_BCONSOLE_BINARY}" -c "${conf}" -p etc/user2.cred <"$tmp"/bconcmds >"${tmp}"/log2.out 2>"${tmp}"/err2.out; then
  cat "${tmp}"/log2.out
  cat "${tmp}"/err2.out
  set_error "Login as user user2 succeeded. This should NOT happen."
  exit 1
fi

print_debug "OK: login as user2 failed."

cat <<END_OF_DATA >"$tmp"/bconcmds-add-user
@$out $tmp/log3.out
configure add user name=user3 description="script configured user" profile=operator
reload
quit
END_OF_DATA

## create user3
if ! "${BAREOS_BCONSOLE_BINARY}" -c "${conf}" -p etc/user1.cred <"$tmp"/bconcmds-add-user >"${tmp}"/log4.out 2>"${tmp}"/err4.out; then
  cat "${tmp}"/log4.out
  cat "${tmp}"/err4.out
  set_error "Failed to login as user user1 and add new user3."
  exit 1
fi

cat <<END_OF_DATA >"$tmp"/bconcmds-user3
@$out $tmp/log5.out
status director
quit
END_OF_DATA

##login as user 3
if ! "${BAREOS_BCONSOLE_BINARY}" -c "${conf}" -p etc/user3.cred <"$tmp"/bconcmds-user3 >"${tmp}"/log6.out 2>"${tmp}"/err6.out; then
  cat "${tmp}"/log6.out
  cat "${tmp}"/err6.out
  set_error "Failed to login as user user3."
  exit 1
fi

if ! grep -q "Running Jobs:" "${tmp}"/log5.out; then
  cat "${tmp}"/log5.out
  set_error "Unexpected output in user3 session."
  exit 1
fi

if "${BAREOS_BCONSOLE_BINARY}" -c "${conf}" -p etc/user4locked.cred <"$tmp"/bconcmds >"${tmp}"/log7.out 2>"${tmp}"/err7.out; then
  cat "${tmp}"/log7.out
  cat "${tmp}"/err7.out
  set_error "Login as user user4locked succeeded. This should NOT happen."
  exit 1
fi

print_debug "OK: login as user4locked failed."

if ! ${rscripts}/bareos-ctl-dir status >/dev/null; then
  set_error "Director does not run anymore. This should not happen."
  exit 1
fi

echo "Console {
  Name = \"usepam_acl\"
  Password = \"secret\"
  UsePamAuthentication = yes
  Profile = \"operator\"
}" >$usepam_and_acl_config

cat <<END_OF_DATA >"$tmp"/bconcmds
@$out ${NULL_DEV}
messages
@$out $tmp/usepam_acl.out
reload
messages
quit
END_OF_DATA

${BAREOS_BCONSOLE_BINARY} -c ${conf} -p etc/user1.cred <$tmp/bconcmds >${tmp}/log1.out 2>${tmp}/err1.out

expect_not_grep "reloaded" \
  "$tmp/usepam_acl.out" \
  "Reload was succesful. This should not happen"

expect_grep "Combining \`Use Pam Authentication\` with ACL commands or \`Profile\` in Console(s) \`usepam_acl\` is not allowed" \
  "$tmp/usepam_acl.out" \
  "Use Pam Authentication with ACL error was not shown"

stop_bareos >$output 2>&1

end_test
