Added support for multiple homes in pam_zfs_key module (#18084)

This implemented support for having multiple datasets unlocked and
mounted when a session is opened.
Example: `homes=rpool/home,tank/users`

Extra unit tests have been added

A man page documents have been added `man 8 pam_zfs_key`. A few
references to the new man page have also been added in other documents.

Signed-off-by: Dennis Vestergaard Værum <github@varum.dk>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Tino Reichardt <milky-zfs@mcmilk.de>
This commit is contained in:
Dennis Værum
2026-02-04 01:09:10 +01:00
committed by GitHub
parent 7e33476a7c
commit 07ae463d1a
12 changed files with 528 additions and 94 deletions
@@ -51,4 +51,62 @@ references 0
log_mustnot ismounted "$TESTPOOL/pam/${username}"
keystatus unavailable
log_mustnot ismounted "$TESTPOOL/pam/${username}"
keystatus unavailable
log_mustnot ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh unavailable
genconfig "homes=$TESTPOOL/pam,$TESTPOOL/pam-multi-home runstatedir=${runstatedir}"
echo "testpass" | pamtester ${pamservice} ${username} open_session
references 1
log_must ismounted "$TESTPOOL/pam/${username}"
keystatus available
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh available
echo "testpass" | pamtester ${pamservice} ${username} open_session
references 2
log_must ismounted "$TESTPOOL/pam/${username}"
keystatus available
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh available
log_must pamtester ${pamservice} ${username} close_session
references 1
log_must ismounted "$TESTPOOL/pam/${username}"
keystatus available
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh available
log_must pamtester ${pamservice} ${username} close_session
references 0
log_mustnot ismounted "$TESTPOOL/pam/${username}"
keystatus unavailable
log_mustnot ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh unavailable
# Test a 'homes' with many entries
allhomes="$TESTPOOL/pam-multi-home1"
for i in {2..$PAM_MULTI_HOME_COUNT} ; do
allhomes="$allhomes,$TESTPOOL/pam-multi-home$i"
done
genconfig "homes=$allhomes runstatedir=${runstatedir}"
echo "testpass" | pamtester ${pamservice} ${username} open_session
for i in {1..$PAM_MULTI_HOME_COUNT} ; do
references 1
log_must ismounted "$TESTPOOL/pam-multi-home$i/${username}"
keystatus_mh available $i
done
log_must pamtester ${pamservice} ${username} close_session
for i in {1..$PAM_MULTI_HOME_COUNT} ; do
references 0
log_mustnot ismounted "$TESTPOOL/pam-multi-home$i/${username}"
keystatus_mh unavailable $i
done
log_pass "done."
@@ -29,28 +29,39 @@ fi
log_mustnot ismounted "$TESTPOOL/pam/${username}"
keystatus unavailable
log_mustnot ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh unavailable
genconfig "homes=$TESTPOOL/pam runstatedir=${runstatedir}"
genconfig "homes=$TESTPOOL/pam,$TESTPOOL/pam-multi-home runstatedir=${runstatedir}"
printf "testpass\nsecondpass\nsecondpass\n" | pamtester -v ${pamservice} ${username} chauthtok
log_mustnot ismounted "$TESTPOOL/pam/${username}"
keystatus unavailable
log_mustnot ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh unavailable
echo "secondpass" | pamtester ${pamservice} ${username} open_session
references 1
log_must ismounted "$TESTPOOL/pam/${username}"
keystatus available
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh available
printf "secondpass\ntestpass\ntestpass\n" | pamtester -v ${pamservice} ${username} chauthtok
log_must ismounted "$TESTPOOL/pam/${username}"
log_must ismounted "$TESTPOOL/pam/${username}"
keystatus available
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh available
log_must pamtester ${pamservice} ${username} close_session
references 0
log_mustnot ismounted "$TESTPOOL/pam/${username}"
keystatus unavailable
log_mustnot ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh unavailable
log_pass "done."
@@ -29,28 +29,40 @@ fi
log_mustnot ismounted "$TESTPOOL/pam/${username}"
keystatus unavailable
log_mustnot ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh unavailable
genconfig "homes=$TESTPOOL/pam runstatedir=${runstatedir} nounmount"
genconfig "homes=$TESTPOOL/pam,$TESTPOOL/pam-multi-home runstatedir=${runstatedir} nounmount"
echo "testpass" | pamtester ${pamservice} ${username} open_session
references 1
log_must ismounted "$TESTPOOL/pam/${username}"
keystatus available
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
keystatus_mh available
echo "testpass" | pamtester ${pamservice} ${username} open_session
references 2
keystatus available
log_must ismounted "$TESTPOOL/pam/${username}"
keystatus_mh available
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
log_must pamtester ${pamservice} ${username} close_session
references 1
keystatus available
log_must ismounted "$TESTPOOL/pam/${username}"
keystatus_mh available
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
log_must pamtester ${pamservice} ${username} close_session
references 0
keystatus available
keystatus_mh available
log_must ismounted "$TESTPOOL/pam/${username}"
log_must ismounted "$TESTPOOL/pam-multi-home/${username}"
log_must zfs unmount "$TESTPOOL/pam/${username}"
log_must zfs unmount "$TESTPOOL/pam-multi-home/${username}"
log_must zfs unload-key "$TESTPOOL/pam/${username}"
log_must zfs unload-key "$TESTPOOL/pam-multi-home/${username}"
log_pass "done."
@@ -30,6 +30,7 @@ DISK=${DISKS%% *}
create_pool $TESTPOOL "$DISK"
log_must zfs create -o mountpoint="$TESTDIR" "$TESTPOOL/pam"
log_must zfs create -o mountpoint="$TESTDIR-multi-home" "$TESTPOOL/pam-multi-home"
log_must add_group pamtestgroup
log_must add_user pamtestgroup ${username}
log_must mkdir -p "$runstatedir"
@@ -37,5 +38,15 @@ log_must mkdir -p "$runstatedir"
echo "testpass" | zfs create -o encryption=aes-256-gcm -o keyformat=passphrase -o keylocation=prompt "$TESTPOOL/pam/${username}"
log_must zfs unmount "$TESTPOOL/pam/${username}"
log_must zfs unload-key "$TESTPOOL/pam/${username}"
echo "testpass" | zfs create -o encryption=aes-256-gcm -o keyformat=passphrase -o keylocation=prompt "$TESTPOOL/pam-multi-home/${username}"
log_must zfs unmount "$TESTPOOL/pam-multi-home/${username}"
log_must zfs unload-key "$TESTPOOL/pam-multi-home/${username}"
for i in {1..$PAM_MULTI_HOME_COUNT} ; do
log_must zfs create -o mountpoint="$TESTDIR-multi-home$i" "$TESTPOOL/pam-multi-home$i"
echo "testpass" | zfs create -o encryption=aes-256-gcm -o keyformat=passphrase -o keylocation=prompt "$TESTPOOL/pam-multi-home$i/${username}"
log_must zfs unmount "$TESTPOOL/pam-multi-home$i/${username}"
log_must zfs unload-key "$TESTPOOL/pam-multi-home$i/${username}"
done
log_pass
@@ -28,11 +28,17 @@ runstatedir="${TESTDIR}_run"
pammodule="@pammoduledir@/pam_zfs_key.so"
pamservice="pam_zfs_key_test"
pamconfig="/etc/pam.d/${pamservice}"
PAM_MULTI_HOME_COUNT=20
function keystatus {
log_must [ "$(get_prop keystatus "$TESTPOOL/pam/${username}")" = "$1" ]
}
function keystatus_mh {
typeset suffix="${2:-}"
log_must [ "$(get_prop keystatus "$TESTPOOL/pam-multi-home${suffix}/${username}")" = "$1" ]
}
function genconfig {
printf '%s\trequired\tpam_permit.so\n%s\toptional\t%s\t%s\n' \
password password "$pammodule" "$1" \