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/ldap-access.sh
2022-09-19 14:45:11 -04:00

294 lines
11 KiB
Bash

# -*- indent-tabs-mode: t; tab-width: 4; -*-
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####
#
# Access assertions:
# service accounts, except management:
# can bind but not change passwords, including their own
# can read all attributes of all users but not userPassword, totpSecret, totpMruTokenTime, totpMruToken, totpLabel
# can not write any user attributes, including shadowLastChange
# can read config subtree (permitted-senders, domains)
# no access to services subtree, except their own dn
# users:
# can bind and change their own password
# can read and change their own shadowLastChange
# no read or write access to user's own totpSecret, totpMruToken, totpMruTokenTime or totpLabel
# can read attributess of all users except:
# mailaccess, totpSecret, totpMruToken, totpMruTokenTime, totpLabel
# no access to config subtree
# no access to services subtree
# other:
# no anonymous binds to root DSE
# no anonymous binds to database
#
# Exception: the nextcloud service account is allowed to change user
# passwords until this issue is fixed:
#
# https://github.com/nextcloud/server/issues/18406
test_user_change_password() {
# users should be able to change their own passwords
test_start "user-change-password"
# create regular user with password "alice"
local alice="alice@somedomain.com"
create_user "$alice" "alice"
local alice_dn="$ATTR_DN"
# bind as alice and update userPassword
assert_w_access "$alice_dn" "$alice_dn" "alice" write "userPassword=$(slappasswd_hash "alice-new")"
delete_user "$alice"
test_end
}
test_user_access() {
# 1. can read attributess of all users except mailaccess, totpSecret, totpMruToken, totpMruTokenTime, totpLabel
# 2. can read and change their own shadowLastChange
# 3. no access to config subtree
# 4. no access to services subtree
# 5. no read or write access to own totpSecret, totpMruToken, totpMruTokenTime, or totpLabel
test_start "user-access"
local totpSecret="12345678901234567890"
local totpMruToken="94287082"
local totpLabel="my phone"
# create regular user's alice and bob
local alice="alice@somedomain.com"
create_user "alice@somedomain.com" "alice" "" "$totpSecret,$totpMruToken,$totpLabel"
local alice_dn="$ATTR_DN"
local bob="bob@somedomain.com"
create_user "bob@somedomain.com" "bob" "" "$totpSecret,$totpMruToken,$totpLabel"
local bob_dn="$ATTR_DN"
# alice should be able to set her own shadowLastChange
assert_w_access "$alice_dn" "$alice_dn" "alice" write "shadowLastChange=0"
# test that alice can read her own attributes
assert_r_access "$alice_dn" "$alice_dn" "alice" read mail maildrop cn sn shadowLastChange
# alice should not have access to her own mailaccess, totpSecret, totpMruToken, totpMruTokenTime or totpLabel, though
assert_r_access "$alice_dn" "$alice_dn" "alice" no-read mailaccess totpSecret totpMruToken totpMruTokenTime totpLabel
# test that alice cannot change her own select attributes
assert_w_access "$alice_dn" "$alice_dn" "alice"
# test that alice cannot change her own totpSecret, totpMruToken, totpMruTokenTime or totpLabel
assert_w_access "$alice_dn" "$alice_dn" "alice" no-write "totpSecret=ABC" "totpMruToken=123456" "totpMruTokenTime=123" "totpLabel=x-phone"
# test that alice can read bob's attributes
assert_r_access "$bob_dn" "$alice_dn" "alice" read mail maildrop cn sn
# alice should not have access to bob's mailaccess, totpSecret, totpMruToken, totpMruTokenTime, or totpLabel
assert_r_access "$bob_dn" "$alice_dn" "alice" no-read mailaccess totpSecret totpMruToken totpMruTokenTime totpLabel
# test that alice cannot change bob's select attributes
assert_w_access "$bob_dn" "$alice_dn" "alice"
# test that alice cannot change bob's attributes
assert_w_access "$bob_dn" "$alice_dn" "alice" no-write "totpSecret=ABC" "totpMruToken=123456" "totpMruTokenTime=345" "totpLabel=x-phone"
# test that alice cannot read a service account's attributes
assert_r_access "$LDAP_POSTFIX_DN" "$alice_dn" "alice"
# test that alice cannot read config entries
assert_r_access "dc=somedomain.com,$LDAP_DOMAINS_BASE" "$alice_dn" "alice"
assert_r_access "$LDAP_PERMITTED_SENDERS_BASE" "$alice_dn" "alice"
# test that alice cannot find anything searching config
test_search "$LDAP_CONFIG_BASE" "$alice_dn" "alice"
[ $SEARCH_DN_COUNT -gt 0 ] && test_failure "Users should not be able to search config"
# test that alice cannot find anything searching config domains
test_search "$LDAP_DOMAINS_BASE" "$alice_dn" "alice"
[ $SEARCH_DN_COUNT -gt 0 ] && test_failure "Users should not be able to search config domains"
# test that alice cannot find anything searching services
test_search "$LDAP_SERVICES_BASE" "$alice_dn" "alice"
[ $SEARCH_DN_COUNT -gt 0 ] && test_failure "Users should not be able to search services"
delete_user "$alice"
delete_user "$bob"
test_end
}
test_nextcloud_service_access() {
# The nextcloud service account is allowed to change user
# passwords until issue #18406 is fixed
test_start "nextcloud-service-access"
# create regular user with password "alice"
local alice="alice@somedomain.com"
create_user "alice@somedomain.com" "alice"
local alice_dn="$ATTR_DN"
# allowed: update userPassword of a user account
assert_w_access "$alice_dn" "$LDAP_NEXTCLOUD_DN" "$LDAP_NEXTCLOUD_PASSWORD" write "userPassword=$(slappasswd_hash "alice-new")"
# not allowed: update userPassword of service account
assert_w_access "$LDAP_POSTFIX_DN" "$LDAP_NEXTCLOUD_DN" "$LDAP_NEXTCLOUD_PASSWORD" no-write "userPassword=$(slappasswd_hash "test-new")"
# not allowed: update userPassword of own account
assert_w_access "$LDAP_NEXTCLOUD_DN" "$LDAP_NEXTCLOUD_DN" "$LDAP_NEXTCLOUD_PASSWORD" no-write "userPassword=$(slappasswd_hash "test-new")"
delete_user "$alice"
test_end
}
test_service_change_password() {
# service accounts should not be able to change other user's
# passwords
# service accounts should not be able to change their own password
test_start "service-change-password"
# create regular user with password "alice"
local alice="alice@somedomain.com"
create_user "alice@somedomain.com" "alice"
local alice_dn="$ATTR_DN"
# create a test service account
create_service_account "test" "test"
local service_dn="$ATTR_DN"
# update userPassword of user using service account
assert_w_access "$alice_dn" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD" no-write "userPassword=$(slappasswd_hash "alice-new")"
# update userPassword of service account using service account
assert_w_access "$service_dn" "$service_dn" "test" no-write "userPassword=$(slappasswd_hash "test-new")"
delete_user "$alice"
delete_service_account "test"
test_end
}
test_service_access() {
# service accounts should have read-only access to all attributes
# of all users except userPassword
# can not write any user attributes, include shadowLastChange
# can read config subtree (permitted-senders, domains)
# no access to services subtree, except their own dn
test_start "service-access"
local totpSecret="12345678901234567890"
local totpMruToken="94287082"
local totpLabel="my phone"
# create regular user with password "alice"
local alice="alice@somedomain.com"
create_user "alice@somedomain.com" "alice" "" "$totpSecret,$totpMruToken,$totpLabel"
# create a test service account
create_service_account "test" "test"
local service_dn="$ATTR_DN"
# Use service account to find alice
record "[Use service account to find alice]"
get_attribute "$LDAP_USERS_BASE" "mail=${alice}" dn sub "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD"
if [ -z "$ATTR_DN" ]; then
test_failure "Unable to search for user account using service account"
else
local alice_dn="$ATTR_DN"
# set shadowLastChange on alice's entry (to test reading it back)
assert_w_access "$alice_dn" "$alice_dn" "alice" write "shadowLastChange=0"
# check that service account can read user attributes
assert_r_access "$alice_dn" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD" read mail maildrop uid cn sn shadowLastChange
# service account should not be able to read user's userPassword, totpSecret, totpMruToken, totpMruTokenTime, or totpLabel
assert_r_access "$alice_dn" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD" no-read userPassword totpSecret totpMruToken totpMruTokenTime totpLabel
# service accounts cannot change user attributes
assert_w_access "$alice_dn" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD"
assert_w_access "$alice_dn" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD" no-write "shadowLastChange=1" "totpSecret=ABC" "totpMruToken=333333" "totpMruTokenTime=123" "totpLabel=x-phone"
fi
# service accounts can read config subtree (permitted-senders, domains)
assert_r_access "dc=somedomain.com,$LDAP_DOMAINS_BASE" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD" read dc
# service accounts can search and find things in the config subtree
test_search "$LDAP_CONFIG_BASE" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD" sub
[ $SEARCH_DN_COUNT -lt 4 ] && test_failure "Service accounts should be able to search config"
# service accounts can read attributes in their own dn
assert_r_access "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD" read cn description
# ... but not userPassword
assert_r_access "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD" no-read userPassword
# services cannot read other service's attributes
assert_r_access "$service_dn" "$LDAP_POSTFIX_DN" "$LDAP_POSTFIX_PASSWORD" no-read cn description userPassword
delete_user "$alice"
delete_service_account "test"
test_end
}
test_root_dse() {
# no anonymous binds to root dse
test_start "root-dse"
record "[bind anonymously to root dse]"
ldapsearch -H $LDAP_URL -x -b "" -s base >>$TEST_OF 2>&1
local r=$?
if [ $r -eq 0 ]; then
test_failure "Anonymous access to root dse should not be permitted"
elif [ $r -eq 48 ]; then
# 48=inappropriate authentication (anon binds not allowed)
test_success
else
die "Error accessing root dse"
fi
test_end
}
test_anon_bind() {
test_start "anon-bind"
record "[bind anonymously to $LDAP_BASE]"
ldapsearch -H $LDAP_URL -x -b "$LDAP_BASE" -s base >>$TEST_OF 2>&1
local r=$?
if [ $r -eq 0 ]; then
test_failure "Anonymous access should not be permitted"
elif [ $r -eq 48 ]; then
# 48=inappropriate authentication (anon binds not allowed)
test_success
else
die "Error accessing $LDAP_BASE"
fi
test_end
}
suite_start "ldap-access"
test_user_change_password
test_user_access
test_service_change_password
test_service_access
test_nextcloud_service_access
test_root_dse
test_anon_bind
suite_end