1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2025-04-04 00:17:06 +00:00
mailinabox/tests/suites/management-users.sh
downtownallday 66ac35871e Merge branch 'main' of https://github.com/mail-in-a-box/mailinabox
Upstream is adding handling for utf8 domains by creating a domain alias @utf8 -> @idna. I'm deviating from this approach by setting multiple email address (idna and utf8) per user and alias where a domain contains non-ascii characters. The maildrop (mailbox) remains the same - all mail goes to the user's mailbox regardless of which email address was used. This is more in line with how other systems (eg. active directory), handle multiple email addresses for a single user.

# Conflicts:
#	README.md
#	management/mailconfig.py
#	management/templates/index.html
#	setup/dns.sh
#	setup/mail-users.sh
2021-10-01 17:43:48 -04:00

364 lines
12 KiB
Bash

# -*- indent-tabs-mode: t; tab-width: 4; -*-
#
# User management tests
_test_mixed_case() {
# helper function sends multiple email messages to test mixed case
# input scenarios
local alices=($1) # list of mixed-case email addresses for alice
local bobs=($2) # list of mixed-case email addresses for bob
local aliases=($3) # list of mixed-case email addresses for an alias
start_log_capture
local alice_pw="$(generate_password 16)"
local bob_pw="$(generate_password 16)"
# create local user alice and alias group
if mgmt_assert_create_user "${alices[0]}" "$alice_pw"; then
# test that alice cannot also exist at the same time
if mgmt_create_user "${alices[1]}" "$alice_pw" no; then
test_failure "Creation of a user with the same email address, but different case, succeeded."
test_failure "${REST_ERROR}"
fi
# create an alias group with alice in it
mgmt_assert_create_alias_group "${aliases[0]}" "${alices[1]}"
fi
# create local user bob
mgmt_assert_create_user "${bobs[0]}" "$bob_pw"
assert_check_logs
# send mail from bob to alice
#
if ! have_test_failures; then
record "[Mailing to alice from bob]"
start_log_capture
local output
output="$($PYMAIL -to ${alices[2]} "$alice_pw" $PRIVATE_IP ${bobs[1]} "$bob_pw" 2>&1)"
assert_python_success $? "$output"
assert_check_logs
# send mail from bob to the alias, ensure alice got it
#
record "[Mailing to alias from bob]"
start_log_capture
local subject="Mail-In-A-Box test $(generate_uuid)"
output="$($PYMAIL -subj "$subject" -no-delete -to ${aliases[1]} na $PRIVATE_IP ${bobs[2]} "$bob_pw" 2>&1)"
assert_python_success $? "$output"
output="$($PYMAIL -subj "$subject" -no-send $PRIVATE_IP ${alices[3]} "$alice_pw" 2>&1)"
assert_python_success $? "$output"
assert_check_logs
# send mail from alice as the alias to bob, ensure bob got it
#
record "[Mailing to bob as alias from alice]"
start_log_capture
local subject="Mail-In-A-Box test $(generate_uuid)"
output="$($PYMAIL -subj "$subject" -no-delete -f ${aliases[2]} -to ${bobs[2]} "$bob_pw" $PRIVATE_IP ${alices[4]} "$alice_pw" 2>&1)"
assert_python_success $? "$output"
output="$($PYMAIL -subj "$subject" -no-send $PRIVATE_IP ${bobs[3]} "$bob_pw" 2>&1)"
assert_python_success $? "$output"
assert_check_logs
fi
mgmt_assert_delete_user "${alices[1]}"
mgmt_assert_delete_user "${bobs[1]}"
mgmt_assert_delete_alias_group "${aliases[1]}"
}
test_mixed_case_users() {
# create mixed-case user name
# add user to alias using different cases
# send mail from another user to that user - validates smtp, imap, delivery
# send mail from another user to the alias
# send mail from that user as the alias to the other user
test_start "mixed-case-users"
local alices=(alice@mgmt.somedomain.com
aLICE@mgmt.somedomain.com
aLiCe@mgmt.somedomain.com
ALICE@mgmt.somedomain.com
alIce@mgmt.somedomain.com)
local bobs=(bob@mgmt.somedomain.com
Bob@mgmt.somedomain.com
boB@mgmt.somedomain.com
BOB@mgmt.somedomain.com)
local aliases=(aLICE@mgmt.anotherdomain.com
aLiCe@mgmt.anotherdomain.com
ALICE@mgmt.anotherdomain.com)
_test_mixed_case "${alices[*]}" "${bobs[*]}" "${aliases[*]}"
test_end
}
test_mixed_case_domains() {
# create mixed-case domain names
# add user to alias using different cases
# send mail from another user to that user - validates smtp, imap, delivery
# send mail from another user to the alias
# send mail from that user as the alias to the other user
test_start "mixed-case-domains"
local alices=(alice@mgmt.somedomain.com
alice@MGMT.somedomain.com
alice@mgmt.SOMEDOMAIN.com
alice@mgmt.somedomain.COM
alice@Mgmt.SomeDomain.Com)
local bobs=(bob@mgmt.somedomain.com
bob@MGMT.somedomain.com
bob@mgmt.SOMEDOMAIN.com
bob@Mgmt.SomeDomain.com)
local aliases=(alice@MGMT.anotherdomain.com
alice@mgmt.ANOTHERDOMAIN.com
alice@Mgmt.AnotherDomain.Com)
_test_mixed_case "${alices[*]}" "${bobs[*]}" "${aliases[*]}"
test_end
}
test_intl_domains() {
test_start "intl-domains"
# local intl alias
local alias="alice@bücher.example"
local alias_idna="alice@xn--bcher-kva.example"
# remote intl user / forward-to
local intl_person="hans@bücher.example"
local intl_person_idna="hans@xn--bcher-kva.example"
local intl_person_domain=$(email_domainpart "$intl_person")
local intl_person_idna_domain=$(email_domainpart "$intl_person_idna")
# local users
local bob="bob@somedomain.com"
local bob_pw="$(generate_password 16)"
local mary="mary@somedomain.com"
local mary_pw="$(generate_password 16)"
start_log_capture
# international domains are not permitted for user accounts
if mgmt_create_user "$intl_person" "$bob_pw"; then
test_failure "A user account is not permitted to have an international domain"
# ensure user is removed as is expected by the remaining tests
mgmt_delete_user "$intl_person"
delete_user "$intl_person"
delete_user "$intl_person_idna"
fi
# given an idna encoded user - the user should have 2 mail addresses
if ! mgmt_create_user "$intl_person_idna" "$bob_pw"; then
test_failure "Could not create idna-encoded user account $intl_person_idna"
else
get_attribute "$LDAP_USERS_BASE" "(mail=$intl_person_idna)" "mail"
if [ -z "$ATTR_DN" ] || \
! array_contains "$intl_person" "${ATTR_VALUE[@]}" || \
! array_contains "$intl_person_idna" "${ATTR_VALUE[@]}"
then
test_failure "Alias's ($intl_person) mail attribute expected to have both the idna and utf8 names, got ${#ATTR_VALUE[@]}: ${ATTR_VALUE[*]}, expected: $intl_person,$intl_person_idna"
[ ! -z "$ATTR_DN" ] && record_search "$ATTR_DN"
else
record_search "$ATTR_DN"
# required aliases are automatically created and should
# have both mail addresses (idna and utf8)
get_attribute "$LDAP_ALIASES_BASE" "(mail=abuse@$intl_person_idna_domain)" "mail"
if [ -z "$ATTR_DN" ]; then
test_failure "Required alias not created!"
debug_search "(objectClass=mailGroup)" >>$TEST_OF
elif ! array_contains "abuse@$intl_person_domain" "${ATTR_VALUE[@]}" || \
! array_contains "abuse@$intl_person_idna_domain" "${ATTR_VALUE[@]}"
then
test_failure "Require alias abuse@$intl_person_idna_domain expected to contain both idna and utf8 mail addresses"
record_search "$ATTR_DN"
fi
# ensure user is removed as is expected by the remaining tests
mgmt_delete_user "$intl_person_idna"
fi
fi
# at this point intl_person does not exist, so all required aliases
# should also not be present
get_attribute "$LDAP_ALIASES_BASE" "(mail=*@$intl_person_idna_domain)"
if [ ! -z "$ATTR_DN" ]; then
test_failure "No required alias should not exist for the $intl_person_domain domain"
record_search "$ATTR_DN"
fi
# create local users bob and mary
mgmt_assert_create_user "$bob" "$bob_pw"
mgmt_assert_create_user "$mary" "$mary_pw"
# create intl alias with local user bob and intl_person in it
if mgmt_assert_create_alias_group "$alias" "$bob" "$intl_person"; then
# examine LDAP server to verify IDNA-encodings
# 1. the mail attribute for the alias should have both the
# idna and utf8 addresses
get_attribute "$LDAP_ALIASES_BASE" "(mail=$alias)" "mail"
if [ -z "$ATTR_DN" ] || \
! array_contains "$alias" "${ATTR_VALUE[@]}" || \
! array_contains "$alias_idna" "${ATTR_VALUE[@]}"
then
test_failure "Alias's ($alias) mail attribute expected to have both the idna and utf8 names, got: ${ATTR_VALUE[*]}, expected: $alias,$alias_idna"
[ ! -z "$ATTR_DN" ] && record_search "$ATTR_DN"
fi
record_search "$ATTR_DN"
# 2. the mailMember attribute for the alias should contain the
# idna encoded intl_person (who is external - not a system user)
get_attribute "$LDAP_ALIASES_BASE" "(mail=$alias_idna)" "mailMember"
if [ -z "$ATTR_DN" ]; then
test_failure "IDNA-encoded alias group not found! created as:$alias expected:$alias_idna"
elif [ "$ATTR_VALUE" != "$intl_person_idna" ]; then
test_failure "Alias group with user having an international domain was not encoded properly. added as:$intl_person expected:$intl_person_idna"
fi
fi
# re-create intl alias with local user bob only
mgmt_assert_create_alias_group "$alias" "$bob"
assert_check_logs
if ! have_test_failures; then
# send mail to alias from mary, ensure bob got it
record "[Sending to intl alias from mary]"
# note PYMAIL does not do idna conversion - it'll throw
# "UnicodeEncodeError: 'ascii' codec can't encode character
# '\xfc' in position 38".
#
# we'll have to send to the idna address directly
start_log_capture
local subject="Mail-In-A-Box test $(generate_uuid)"
local output
output="$($PYMAIL -subj "$subject" -no-delete -to "$alias_idna" na $PRIVATE_IP $mary "$mary_pw" 2>&1)"
assert_python_success $? "$output"
output="$($PYMAIL -subj "$subject" -no-send $PRIVATE_IP $bob "$bob_pw" 2>&1)"
assert_python_success $? "$output"
assert_check_logs
fi
mgmt_assert_delete_alias_group "$alias"
mgmt_assert_delete_user "$bob"
mgmt_assert_delete_user "$mary"
test_end
}
test_totp() {
test_start "totp"
# alice
local alice="alice@somedomain.com"
local alice_pw="$(generate_password 16)"
start_log_capture
# create alice
mgmt_assert_create_user "$alice" "$alice_pw"
# alice must be admin to use TOTP
if ! have_test_failures; then
if mgmt_totp_enable "$alice" "$alice_pw"; then
test_failure "User must be an admin to use TOTP, but server allowed it"
else
mgmt_assert_privileges_add "$alice" "admin"
fi
fi
# add totp to alice's account (if successful, secret is in TOTP_SECRET)
if ! have_test_failures; then
mgmt_assert_totp_enable "$alice" "$alice_pw"
# TOTP_SECRET and TOTP_TOKEN are now set...
fi
# logging in with just the password should now fail
if ! have_test_failures; then
record "Expect a login failure..."
mgmt_assert_admin_login "$alice" "$alice_pw" "missing-totp-token"
fi
# logging into /admin/me with a password and a token should
# succeed, and an api_key generated
local api_key
if ! have_test_failures; then
record "Try using a password and a token to get the user api key, we may have to wait 30 seconds to get a new token..."
local old_totp_token="$TOTP_TOKEN"
if ! mgmt_get_totp_token "$TOTP_SECRET" "$TOTP_TOKEN"; then
test_failure "Could not obtain a new TOTP token"
else
# we have a new token, try logging in ...
# the token must be placed in the header "x-auth-token"
if mgmt_assert_admin_login "$alice" "$alice_pw" "ok" "--header=x-auth-token: $TOTP_TOKEN"
then
api_key="$(/usr/bin/jq -r '.api_key' <<<"$REST_OUTPUT")"
record "Success: login with TOTP token successful. api_key=$api_key"
# ensure the totpMruToken was changed in LDAP
get_attribute "$LDAP_USERS_BASE" "(mail=$alice)" "totpMruToken"
if [ "$ATTR_VALUE" != "{0}$TOTP_TOKEN" ]; then
record_search "(mail=$alice)"
test_failure "totpMruToken wasn't updated in LDAP"
fi
fi
fi
fi
# we should be able to login using the user's api key
if ! have_test_failures; then
record "[Use the session key to enum users]"
if ! mgmt_rest_as_user "GET" "/admin/mail/users?format=json" "$alice" "$api_key"; then
test_failure "Unable to use the session key to issue a rest call: $REST_ERROR"
else
record "Success: $REST_OUTPUT"
fi
fi
# disable totp on the account - login should work with just the password
# and the ldap entry should not have the 'totpUser' objectClass
if ! have_test_failures; then
if mgmt_assert_mfa_disable "$alice" "$api_key"; then
mgmt_assert_admin_login "$alice" "$alice_pw" "ok"
fi
fi
# check for errors in system logs
if ! have_test_failures; then
assert_check_logs
else
check_logs
fi
mgmt_assert_delete_user "$alice"
test_end
}
suite_start "management-users" mgmt_start
test_totp
test_mixed_case_domains
test_mixed_case_users
test_intl_domains
suite_end mgmt_end