From f5f96d44fdec7c9ea74d4e598d75593ee35365c3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 25 Nov 2025 09:50:36 +0900 Subject: [PATCH] TEST-46-HOMED: split into small testcases This also replace long IDENTITY= line with pretty json string. --- test/units/TEST-46-HOMED.sh | 1337 ++++++++++++++++++----------------- 1 file changed, 700 insertions(+), 637 deletions(-) diff --git a/test/units/TEST-46-HOMED.sh b/test/units/TEST-46-HOMED.sh index 8eee967d7c6..b18e05f1536 100755 --- a/test/units/TEST-46-HOMED.sh +++ b/test/units/TEST-46-HOMED.sh @@ -1,10 +1,12 @@ #!/usr/bin/env bash # SPDX-License-Identifier: LGPL-2.1-or-later # shellcheck disable=SC2016,SC2209 - set -eux set -o pipefail +# shellcheck source=test/units/test-control.sh +. "$(dirname "$0")"/test-control.sh + # Check if homectl is installed, and if it isn't bail out early instead of failing if ! command -v homectl >/dev/null; then echo "no homed" >/skipped @@ -47,300 +49,300 @@ mount -t tmpfs tmpfs /home -o size=290M # Make sure systemd-homed takes notice of the overmounted /home/ systemctl kill -sUSR1 systemd-homed -TMP_SKEL=$(mktemp -d) -echo hogehoge >"$TMP_SKEL"/hoge - -# we enable --luks-discard= since we run our tests in a tight VM, hence don't -# needlessly pressure for storage. We also set the cheapest KDF, since we don't -# want to waste CI CPU cycles on it. We also effectively disable rate-limiting on -# the user by allowing 1000 logins per second -NEWPASSWORD=xEhErW0ndafV4s homectl create test-user \ - --disk-size=min \ - --luks-discard=yes \ - --image-path=/home/test-user.home \ - --luks-pbkdf-type=pbkdf2 \ - --luks-pbkdf-time-cost=1ms \ - --rate-limit-interval=1s \ - --rate-limit-burst=1000 \ - --skel="$TMP_SKEL" -inspect test-user - -PASSWORD=xEhErW0ndafV4s homectl authenticate test-user - -PASSWORD=xEhErW0ndafV4s homectl activate test-user -inspect test-user - -PASSWORD=xEhErW0ndafV4s homectl update test-user --real-name="Inline test" -inspect test-user - -homectl deactivate test-user -inspect test-user - -PASSWORD=xEhErW0ndafV4s NEWPASSWORD=yPN4N0fYNKUkOq homectl passwd test-user -inspect test-user - -PASSWORD=yPN4N0fYNKUkOq homectl activate test-user -inspect test-user - -SYSTEMD_LOG_LEVEL=debug PASSWORD=yPN4N0fYNKUkOq NEWPASSWORD=xEhErW0ndafV4s homectl passwd test-user -inspect test-user - -homectl deactivate test-user -inspect test-user - -homectl update test-user --real-name "Offline test" --offline -inspect test-user - -PASSWORD=xEhErW0ndafV4s homectl activate test-user -inspect test-user - -# Ensure that the offline changes were propagated in -grep "Offline test" /home/test-user/.identity - -homectl deactivate test-user -inspect test-user - -PASSWORD=xEhErW0ndafV4s homectl update test-user --real-name="Inactive test" -inspect test-user - -PASSWORD=xEhErW0ndafV4s homectl activate test-user -inspect test-user +testcase_basic() { + local TMP_SKEL + + TMP_SKEL=$(mktemp -d) + echo hogehoge >"$TMP_SKEL"/hoge + + # we enable --luks-discard= since we run our tests in a tight VM, hence don't + # needlessly pressure for storage. We also set the cheapest KDF, since we don't + # want to waste CI CPU cycles on it. We also effectively disable rate-limiting on + # the user by allowing 1000 logins per second + NEWPASSWORD=xEhErW0ndafV4s \ + homectl create test-user \ + --disk-size=min \ + --luks-discard=yes \ + --image-path=/home/test-user.home \ + --luks-pbkdf-type=pbkdf2 \ + --luks-pbkdf-time-cost=1ms \ + --rate-limit-interval=1s \ + --rate-limit-burst=1000 \ + --skel="$TMP_SKEL" + inspect test-user -homectl deactivate test-user -inspect test-user + PASSWORD=xEhErW0ndafV4s homectl authenticate test-user -# Do some keyring tests, but only on real kernels, since keyring access inside of containers will fail -# (See: https://github.com/systemd/systemd/issues/17606) -if ! systemd-detect-virt -cq ; then PASSWORD=xEhErW0ndafV4s homectl activate test-user inspect test-user - # Key should now be in the keyring - homectl update test-user --real-name "Keyring Test" + PASSWORD=xEhErW0ndafV4s homectl update test-user --real-name="Inline test" inspect test-user - # These commands shouldn't use the keyring - (! timeout 5s homectl authenticate test-user ) - (! NEWPASSWORD="foobar" timeout 5s homectl passwd test-user ) - - homectl lock test-user + homectl deactivate test-user inspect test-user - # Key should be gone from keyring - (! timeout 5s homectl update test-user --real-name "Keyring Test 2" ) - - PASSWORD=xEhErW0ndafV4s homectl unlock test-user + PASSWORD=xEhErW0ndafV4s NEWPASSWORD=yPN4N0fYNKUkOq homectl passwd test-user inspect test-user - # Key should have been re-instantiated into the keyring - homectl update test-user --real-name "Keyring Test 3" + PASSWORD=yPN4N0fYNKUkOq homectl activate test-user inspect test-user - homectl deactivate test-user + SYSTEMD_LOG_LEVEL=debug PASSWORD=yPN4N0fYNKUkOq NEWPASSWORD=xEhErW0ndafV4s homectl passwd test-user inspect test-user -fi -# Do some resize tests, but only if we run on real kernels and are on btrfs, as quota inside of containers -# will fail and minimizing while active only works on btrfs. -if ! systemd-detect-virt -cq && [[ "$FSTYPE" == "btrfs" ]]; then - # grow while inactive - PASSWORD=xEhErW0ndafV4s homectl resize test-user 300M + homectl deactivate test-user inspect test-user - # minimize while inactive - PASSWORD=xEhErW0ndafV4s homectl resize test-user min + homectl update test-user --real-name "Offline test" --offline inspect test-user PASSWORD=xEhErW0ndafV4s homectl activate test-user inspect test-user - # grow while active - PASSWORD=xEhErW0ndafV4s homectl resize test-user max - inspect test-user + # Ensure that the offline changes were propagated in + grep "Offline test" /home/test-user/.identity - # minimize while active - PASSWORD=xEhErW0ndafV4s homectl resize test-user 0 + homectl deactivate test-user inspect test-user - # grow while active - PASSWORD=xEhErW0ndafV4s homectl resize test-user 300M + PASSWORD=xEhErW0ndafV4s homectl update test-user --real-name="Inactive test" inspect test-user - # shrink to original size while active - PASSWORD=xEhErW0ndafV4s homectl resize test-user 256M + PASSWORD=xEhErW0ndafV4s homectl activate test-user inspect test-user - # minimize again - PASSWORD=xEhErW0ndafV4s homectl resize test-user min + homectl deactivate test-user inspect test-user - # Increase space, so that we can reasonably rebalance free space between to home dirs - mount /home -o remount,size=800M - - # create second user - NEWPASSWORD=uuXoo8ei homectl create test-user2 \ - --disk-size=min \ - --luks-discard=yes \ - --image-path=/home/test-user2.home \ - --luks-pbkdf-type=pbkdf2 \ - --luks-pbkdf-time-cost=1ms \ - --rate-limit-interval=1s \ - --rate-limit-burst=1000 - inspect test-user2 - - # activate second user - PASSWORD=uuXoo8ei homectl activate test-user2 - inspect test-user2 - - # set second user's rebalance weight to 100 - PASSWORD=uuXoo8ei homectl update test-user2 --rebalance-weight=100 - inspect test-user2 - - # set first user's rebalance weight to quarter of that of the second - PASSWORD=xEhErW0ndafV4s homectl update test-user --rebalance-weight=25 - inspect test-user + # Do some keyring tests, but only on real kernels, since keyring access inside of containers will fail + # (See: https://github.com/systemd/systemd/issues/17606) + if ! systemd-detect-virt -cq ; then + PASSWORD=xEhErW0ndafV4s homectl activate test-user + inspect test-user - # synchronously rebalance - homectl rebalance - inspect test-user - inspect test-user2 + # Key should now be in the keyring + homectl update test-user --real-name "Keyring Test" + inspect test-user - wait_for_state test-user2 active - homectl deactivate test-user2 - wait_for_state test-user2 inactive - homectl remove test-user2 -fi + # These commands shouldn't use the keyring + (! timeout 5s homectl authenticate test-user ) + (! NEWPASSWORD="foobar" timeout 5s homectl passwd test-user ) + + homectl lock test-user + inspect test-user + + # Key should be gone from keyring + (! timeout 5s homectl update test-user --real-name "Keyring Test 2" ) + + PASSWORD=xEhErW0ndafV4s homectl unlock test-user + inspect test-user + + # Key should have been re-instantiated into the keyring + homectl update test-user --real-name "Keyring Test 3" + inspect test-user + + homectl deactivate test-user + inspect test-user + fi -PASSWORD=xEhErW0ndafV4s homectl with test-user -- test ! -f /home/test-user/xyz -(! PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz) -PASSWORD=xEhErW0ndafV4s homectl with test-user -- touch /home/test-user/xyz -PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz -PASSWORD=xEhErW0ndafV4s homectl with test-user -- rm /home/test-user/xyz -PASSWORD=xEhErW0ndafV4s homectl with test-user -- test ! -f /home/test-user/xyz -(! PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz) -[[ $(PASSWORD=xEhErW0ndafV4s homectl with test-user -- stat -c %U /home/test-user/hoge) == "test-user" ]] -[[ $(PASSWORD=xEhErW0ndafV4s homectl with test-user -- cat /home/test-user/hoge) == "$(cat "$TMP_SKEL"/hoge)" ]] - -# Regression tests -wait_for_state test-user inactive -/usr/lib/systemd/tests/unit-tests/manual/test-homed-regression-31896 test-user - -wait_for_state test-user inactive -homectl remove test-user - -# blob directory tests -# See docs/USER_RECORD_BLOB_DIRS.md -checkblob() { - test -f "/var/cache/systemd/home/blob-user/$1" - stat -c "%u %#a" "/var/cache/systemd/home/blob-user/$1" | grep "^0 0644" - test -f "/home/blob-user/.identity-blob/$1" - stat -c "%u %#a" "/home/blob-user/.identity-blob/$1" | grep "^12345 0644" - - diff "/var/cache/systemd/home/blob-user/$1" "$2" - diff "/var/cache/systemd/home/blob-user/$1" "/home/blob-user/.identity-blob/$1" + # Do some resize tests, but only if we run on real kernels and are on btrfs, as quota inside of containers + # will fail and minimizing while active only works on btrfs. + if ! systemd-detect-virt -cq && [[ "$FSTYPE" == "btrfs" ]]; then + # grow while inactive + PASSWORD=xEhErW0ndafV4s homectl resize test-user 300M + inspect test-user + + # minimize while inactive + PASSWORD=xEhErW0ndafV4s homectl resize test-user min + inspect test-user + + PASSWORD=xEhErW0ndafV4s homectl activate test-user + inspect test-user + + # grow while active + PASSWORD=xEhErW0ndafV4s homectl resize test-user max + inspect test-user + + # minimize while active + PASSWORD=xEhErW0ndafV4s homectl resize test-user 0 + inspect test-user + + # grow while active + PASSWORD=xEhErW0ndafV4s homectl resize test-user 300M + inspect test-user + + # shrink to original size while active + PASSWORD=xEhErW0ndafV4s homectl resize test-user 256M + inspect test-user + + # minimize again + PASSWORD=xEhErW0ndafV4s homectl resize test-user min + inspect test-user + + # Increase space, so that we can reasonably rebalance free space between to home dirs + mount /home -o remount,size=800M + + # create second user + NEWPASSWORD=uuXoo8ei \ + homectl create test-user2 \ + --disk-size=min \ + --luks-discard=yes \ + --image-path=/home/test-user2.home \ + --luks-pbkdf-type=pbkdf2 \ + --luks-pbkdf-time-cost=1ms \ + --rate-limit-interval=1s \ + --rate-limit-burst=1000 + inspect test-user2 + + # activate second user + PASSWORD=uuXoo8ei homectl activate test-user2 + inspect test-user2 + + # set second user's rebalance weight to 100 + PASSWORD=uuXoo8ei homectl update test-user2 --rebalance-weight=100 + inspect test-user2 + + # set first user's rebalance weight to quarter of that of the second + PASSWORD=xEhErW0ndafV4s homectl update test-user --rebalance-weight=25 + inspect test-user + + # synchronously rebalance + homectl rebalance + inspect test-user + inspect test-user2 + + wait_for_state test-user2 active + homectl deactivate test-user2 + wait_for_state test-user2 inactive + homectl remove test-user2 + fi + + PASSWORD=xEhErW0ndafV4s homectl with test-user -- test ! -f /home/test-user/xyz + (! PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz) + PASSWORD=xEhErW0ndafV4s homectl with test-user -- touch /home/test-user/xyz + PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz + PASSWORD=xEhErW0ndafV4s homectl with test-user -- rm /home/test-user/xyz + PASSWORD=xEhErW0ndafV4s homectl with test-user -- test ! -f /home/test-user/xyz + (! PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz) + [[ "$(PASSWORD=xEhErW0ndafV4s homectl with test-user -- stat -c %U /home/test-user/hoge)" == "test-user" ]] + [[ "$(PASSWORD=xEhErW0ndafV4s homectl with test-user -- cat /home/test-user/hoge)" == "$(cat "$TMP_SKEL"/hoge)" ]] + + # Regression tests + wait_for_state test-user inactive + /usr/lib/systemd/tests/unit-tests/manual/test-homed-regression-31896 test-user + + wait_for_state test-user inactive + homectl remove test-user } -mkdir /tmp/blob1 /tmp/blob2 -echo data1 blob1 >/tmp/blob1/test1 -echo data1 blob2 >/tmp/blob2/test1 -echo data2 blob1 >/tmp/blob1/test2 -echo data2 blob2 >/tmp/blob2/test2 -echo invalid filename >/tmp/blob1/файл -echo data3 >/tmp/external-test3 -echo avatardata >/tmp/external-avatar -ln -s /tmp/external-avatar /tmp/external-avatar-lnk -dd if=/dev/urandom of=/tmp/external-barely-fits bs=1M count=64 -dd if=/dev/urandom of=/tmp/external-toobig bs=1M count=65 - -# create w/ prepopulated blob dir -NEWPASSWORD=EMJuc3zQaMibJo homectl create blob-user \ - --disk-size=min --luks-discard=yes \ - --luks-pbkdf-type=pbkdf2 --luks-pbkdf-time-cost=1ms \ - --rate-limit-interval=1s --rate-limit-burst=1000 \ - --uid=12345 \ - --blob=/tmp/blob1 -inspect blob-user -PASSWORD=EMJuc3zQaMibJo homectl activate blob-user -inspect blob-user - -test -d /var/cache/systemd/home/blob-user -stat -c "%u %#a" /var/cache/systemd/home/blob-user | grep "^0 0755" -test -d /home/blob-user/.identity-blob -stat -c "%u %#a" /home/blob-user/.identity-blob | grep "^12345 0700" - -checkblob test1 /tmp/blob1/test1 -(! checkblob test1 /tmp/blob2/test1 ) -checkblob test2 /tmp/blob1/test2 -(! checkblob test2 /tmp/blob2/test2 ) -(! checkblob фаил /tmp/blob1/фаил ) -(! checkblob test3 /tmp/external-test3 ) -(! checkblob avatar /tmp/external-avatar ) - -# append files to existing blob, both well-known and other -PASSWORD=EMJuc3zQaMibJo homectl update blob-user \ +testcase_blob() { + # blob directory tests + # See docs/USER_RECORD_BLOB_DIRS.md + checkblob() { + test -f "/var/cache/systemd/home/blob-user/$1" + stat -c "%u %#a" "/var/cache/systemd/home/blob-user/$1" | grep "^0 0644" + test -f "/home/blob-user/.identity-blob/$1" + stat -c "%u %#a" "/home/blob-user/.identity-blob/$1" | grep "^12345 0644" + + diff "/var/cache/systemd/home/blob-user/$1" "$2" + diff "/var/cache/systemd/home/blob-user/$1" "/home/blob-user/.identity-blob/$1" + } + + mkdir /tmp/blob1 /tmp/blob2 + echo data1 blob1 >/tmp/blob1/test1 + echo data1 blob2 >/tmp/blob2/test1 + echo data2 blob1 >/tmp/blob1/test2 + echo data2 blob2 >/tmp/blob2/test2 + echo invalid filename >/tmp/blob1/файл + echo data3 >/tmp/external-test3 + echo avatardata >/tmp/external-avatar + ln -s /tmp/external-avatar /tmp/external-avatar-lnk + dd if=/dev/urandom of=/tmp/external-barely-fits bs=1M count=64 + dd if=/dev/urandom of=/tmp/external-toobig bs=1M count=65 + + # create w/ prepopulated blob dir + NEWPASSWORD=EMJuc3zQaMibJo \ + homectl create blob-user \ + --disk-size=min --luks-discard=yes \ + --luks-pbkdf-type=pbkdf2 --luks-pbkdf-time-cost=1ms \ + --rate-limit-interval=1s --rate-limit-burst=1000 \ + --uid=12345 \ + --blob=/tmp/blob1 + inspect blob-user + PASSWORD=EMJuc3zQaMibJo homectl activate blob-user + inspect blob-user + + test -d /var/cache/systemd/home/blob-user + stat -c "%u %#a" /var/cache/systemd/home/blob-user | grep "^0 0755" + test -d /home/blob-user/.identity-blob + stat -c "%u %#a" /home/blob-user/.identity-blob | grep "^12345 0700" + + checkblob test1 /tmp/blob1/test1 + (! checkblob test1 /tmp/blob2/test1 ) + checkblob test2 /tmp/blob1/test2 + (! checkblob test2 /tmp/blob2/test2 ) + (! checkblob фаил /tmp/blob1/фаил ) + (! checkblob test3 /tmp/external-test3 ) + (! checkblob avatar /tmp/external-avatar ) + + # append files to existing blob, both well-known and other + PASSWORD=EMJuc3zQaMibJo \ + homectl update blob-user \ -b test3=/tmp/external-test3 --avatar=/tmp/external-avatar -inspect blob-user -checkblob test1 /tmp/blob1/test1 -(! checkblob test1 /tmp/blob2/test1 ) -checkblob test2 /tmp/blob1/test2 -(! checkblob test2 /tmp/blob2/test2 ) -(! checkblob фаил /tmp/blob1/фаил ) -checkblob test3 /tmp/external-test3 -checkblob avatar /tmp/external-avatar - -# delete files from existing blob, both well-known and other -PASSWORD=EMJuc3zQaMibJo homectl update blob-user \ + inspect blob-user + checkblob test1 /tmp/blob1/test1 + (! checkblob test1 /tmp/blob2/test1 ) + checkblob test2 /tmp/blob1/test2 + (! checkblob test2 /tmp/blob2/test2 ) + (! checkblob фаил /tmp/blob1/фаил ) + checkblob test3 /tmp/external-test3 + checkblob avatar /tmp/external-avatar + + # delete files from existing blob, both well-known and other + PASSWORD=EMJuc3zQaMibJo \ + homectl update blob-user \ -b test3= --avatar= -inspect blob-user -checkblob test1 /tmp/blob1/test1 -(! checkblob test1 /tmp/blob2/test1 ) -checkblob test2 /tmp/blob1/test2 -(! checkblob test2 /tmp/blob2/test2 ) -(! checkblob фаил /tmp/blob1/фаил ) -(! checkblob test3 /tmp/external-test3 ) -(! checkblob avatar /tmp/external-avatar ) - -# swap entire blob directory -PASSWORD=EMJuc3zQaMibJo homectl update blob-user \ + inspect blob-user + checkblob test1 /tmp/blob1/test1 + (! checkblob test1 /tmp/blob2/test1 ) + checkblob test2 /tmp/blob1/test2 + (! checkblob test2 /tmp/blob2/test2 ) + (! checkblob фаил /tmp/blob1/фаил ) + (! checkblob test3 /tmp/external-test3 ) + (! checkblob avatar /tmp/external-avatar ) + + # swap entire blob directory + PASSWORD=EMJuc3zQaMibJo \ + homectl update blob-user \ -b /tmp/blob2 -inspect blob-user -(! checkblob test1 /tmp/blob1/test1 ) -checkblob test1 /tmp/blob2/test1 -(! checkblob test2 /tmp/blob1/test2 ) -checkblob test2 /tmp/blob2/test2 -(! checkblob фаил /tmp/blob1/фаил ) -(! checkblob test3 /tmp/external-test3 ) -(! checkblob avatar /tmp/external-avatar ) - -# create and delete files while swapping blob directory. Also symlinks. -PASSWORD=EMJuc3zQaMibJo homectl update blob-user \ + inspect blob-user + (! checkblob test1 /tmp/blob1/test1 ) + checkblob test1 /tmp/blob2/test1 + (! checkblob test2 /tmp/blob1/test2 ) + checkblob test2 /tmp/blob2/test2 + (! checkblob фаил /tmp/blob1/фаил ) + (! checkblob test3 /tmp/external-test3 ) + (! checkblob avatar /tmp/external-avatar ) + + # create and delete files while swapping blob directory. Also symlinks. + PASSWORD=EMJuc3zQaMibJo \ + homectl update blob-user \ -b /tmp/blob1 -b test2= -b test3=/tmp/external-test3 --avatar=/tmp/external-avatar-lnk -inspect blob-user -checkblob test1 /tmp/blob1/test1 -(! checkblob test1 /tmp/blob2/test1 ) -(! checkblob test2 /tmp/blob1/test2 ) -(! checkblob test2 /tmp/blob2/test2 ) -(! checkblob фаил /tmp/blob1/фаил ) -checkblob test3 /tmp/external-test3 -checkblob avatar /tmp/external-avatar # target of the link - -# clear the blob directory -PASSWORD=EMJuc3zQaMibJo homectl update blob-user \ + inspect blob-user + checkblob test1 /tmp/blob1/test1 + (! checkblob test1 /tmp/blob2/test1 ) + (! checkblob test2 /tmp/blob1/test2 ) + (! checkblob test2 /tmp/blob2/test2 ) + (! checkblob фаил /tmp/blob1/фаил ) + checkblob test3 /tmp/external-test3 + checkblob avatar /tmp/external-avatar # target of the link + + # clear the blob directory + PASSWORD=EMJuc3zQaMibJo \ + homectl update blob-user \ -b /tmp/blob2 -b test3=/tmp/external-test3 --blob= -inspect blob-user -(! checkblob test1 /tmp/blob1/test1 ) -(! checkblob test1 /tmp/blob2/test1 ) -(! checkblob test2 /tmp/blob1/test2 ) -(! checkblob test2 /tmp/blob2/test2 ) -(! checkblob фаил /tmp/blob1/фаил ) -(! checkblob test3 /tmp/external-test3 ) -(! checkblob avatar /tmp/external-avatar ) - -# file that's exactly 64M still fits -# FIXME: Figure out why this fails on ext4. -if [[ "$FSTYPE" != "ext2/ext3" ]]; then - PASSWORD=EMJuc3zQaMibJo homectl update blob-user \ - -b barely-fits=/tmp/external-barely-fits + inspect blob-user (! checkblob test1 /tmp/blob1/test1 ) (! checkblob test1 /tmp/blob2/test1 ) (! checkblob test2 /tmp/blob1/test2 ) @@ -348,46 +350,62 @@ if [[ "$FSTYPE" != "ext2/ext3" ]]; then (! checkblob фаил /tmp/blob1/фаил ) (! checkblob test3 /tmp/external-test3 ) (! checkblob avatar /tmp/external-avatar ) - checkblob barely-fits /tmp/external-barely-fits -fi -# error out if the file is too big -(! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b huge=/tmp/external-toobig ) - -# error out if filenames are invalid -(! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b .hidden=/tmp/external-test3 ) -(! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b "with spaces=/tmp/external-test3" ) -(! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b with=equals=/tmp/external-test3 ) -(! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b файл=/tmp/external-test3 ) -(! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b special@chars=/tmp/external-test3 ) - -# Make sure offline updates to blobs get propagated in -homectl deactivate blob-user -inspect blob-user -homectl update blob-user --offline -b barely-fits= -b propagated=/tmp/external-test3 -inspect blob-user -PASSWORD=EMJuc3zQaMibJo homectl activate blob-user -inspect blob-user -(! checkblob barely-fits /tmp/external-barely-fits ) -checkblob propagated /tmp/external-test3 - -homectl deactivate blob-user -wait_for_state blob-user inactive -homectl remove blob-user - -# userdbctl tests -export PAGER= - -# Create a couple of user/group records to test io.systemd.DropIn -# See docs/USER_RECORD.md and docs/GROUP_RECORD.md -mkdir -p /run/userdb/ -cat >"/run/userdb/dropingroup.group" <<\EOF + # file that's exactly 64M still fits + # FIXME: Figure out why this fails on ext4. + if [[ "$FSTYPE" != "ext2/ext3" ]]; then + PASSWORD=EMJuc3zQaMibJo \ + homectl update blob-user \ + -b barely-fits=/tmp/external-barely-fits + (! checkblob test1 /tmp/blob1/test1 ) + (! checkblob test1 /tmp/blob2/test1 ) + (! checkblob test2 /tmp/blob1/test2 ) + (! checkblob test2 /tmp/blob2/test2 ) + (! checkblob фаил /tmp/blob1/фаил ) + (! checkblob test3 /tmp/external-test3 ) + (! checkblob avatar /tmp/external-avatar ) + checkblob barely-fits /tmp/external-barely-fits + fi + + # error out if the file is too big + (! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b huge=/tmp/external-toobig ) + + # error out if filenames are invalid + (! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b .hidden=/tmp/external-test3 ) + (! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b "with spaces=/tmp/external-test3" ) + (! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b with=equals=/tmp/external-test3 ) + (! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b файл=/tmp/external-test3 ) + (! PASSWORD=EMJuc3zQaMibJo homectl update blob-user -b special@chars=/tmp/external-test3 ) + + # Make sure offline updates to blobs get propagated in + homectl deactivate blob-user + inspect blob-user + homectl update blob-user --offline -b barely-fits= -b propagated=/tmp/external-test3 + inspect blob-user + PASSWORD=EMJuc3zQaMibJo homectl activate blob-user + inspect blob-user + (! checkblob barely-fits /tmp/external-barely-fits ) + checkblob propagated /tmp/external-test3 + + homectl deactivate blob-user + wait_for_state blob-user inactive + homectl remove blob-user +} + +testcase_userdbctl() { + # userdbctl tests + export PAGER= + + # Create a couple of user/group records to test io.systemd.DropIn + # See docs/USER_RECORD.md and docs/GROUP_RECORD.md + mkdir -p /run/userdb/ + cat >"/run/userdb/dropingroup.group" <<\EOF { "groupName" : "dropingroup", "gid" : 1000000 } EOF -cat >"/run/userdb/dropinuser.user" <<\EOF + cat >"/run/userdb/dropinuser.user" <<\EOF { "userName" : "dropinuser", "uid" : 2000000, @@ -397,7 +415,7 @@ cat >"/run/userdb/dropinuser.user" <<\EOF ] } EOF -cat >"/run/userdb/dropinuser.user-privileged" <<\EOF + cat >"/run/userdb/dropinuser.user-privileged" <<\EOF { "privileged" : { "hashedPassword" : [ @@ -410,161 +428,172 @@ cat >"/run/userdb/dropinuser.user-privileged" <<\EOF } } EOF -# Set permissions and create necessary symlinks as described in nss-systemd(8) -chmod 0600 "/run/userdb/dropinuser.user-privileged" -ln -svrf "/run/userdb/dropingroup.group" "/run/userdb/1000000.group" -ln -svrf "/run/userdb/dropinuser.user" "/run/userdb/2000000.user" -ln -svrf "/run/userdb/dropinuser.user-privileged" "/run/userdb/2000000.user-privileged" - -userdbctl -userdbctl --version -userdbctl --help --no-pager -userdbctl --no-legend -userdbctl --output=classic -userdbctl --output=friendly -userdbctl --output=table -userdbctl --output=json | jq -userdbctl -j --json=pretty | jq -userdbctl -j --json=short | jq -userdbctl --with-varlink=no - -userdbctl user -userdbctl user -S -userdbctl user -IS -userdbctl user -R -userdbctl user --disposition=regular --disposition=intrinsic -userdbctl user kkkk -z -userdbctl user --uid-min=100 --uid-max=100 -userdbctl user -B -userdbctl user testuser -userdbctl user root -userdbctl user testuser root -userdbctl user -j testuser root | jq -# Check only UID for the nobody user, since the name is build-configurable -userdbctl user --with-nss=no --synthesize=yes -userdbctl user --with-nss=no --synthesize=yes 0 root 65534 -userdbctl user dropinuser -userdbctl user 2000000 -userdbctl user --with-nss=no --with-varlink=no --synthesize=no --multiplexer=no dropinuser -userdbctl user --with-nss=no 2000000 -(! userdbctl user '') -(! userdbctl user 🐱) -(! userdbctl user 🐱 '' bar) -(! userdbctl user i-do-not-exist) -(! userdbctl user root i-do-not-exist testuser) -(! userdbctl user --with-nss=no --synthesize=no 0 root 65534) -(! userdbctl user -N root nobody) -(! userdbctl user --with-dropin=no dropinuser) -(! userdbctl user --with-dropin=no 2000000) - -userdbctl group -userdbctl group -S -userdbctl group -IS -userdbctl group -R -userdbctl group --disposition=regular --disposition=intrinsic -userdbctl group kkkk -z -userdbctl group --uid-min=100 --uid-max=100 -userdbctl group -B -userdbctl group testuser -userdbctl group root -userdbctl group testuser root -userdbctl group -j testuser root | jq -# Check only GID for the nobody group, since the name is build-configurable -userdbctl group --with-nss=no --synthesize=yes -userdbctl group --with-nss=no --synthesize=yes 0 root 65534 -userdbctl group dropingroup -userdbctl group 1000000 -userdbctl group --with-nss=no --with-varlink=no --synthesize=no --multiplexer=no dropingroup -userdbctl group --with-nss=no 1000000 -(! userdbctl group '') -(! userdbctl group 🐱) -(! userdbctl group 🐱 '' bar) -(! userdbctl group i-do-not-exist) -(! userdbctl group root i-do-not-exist testuser) -(! userdbctl group --with-nss=no --synthesize=no 0 root 65534) -(! userdbctl group --with-dropin=no dropingroup) -(! userdbctl group --with-dropin=no 1000000) - -userdbctl users-in-group -userdbctl users-in-group testuser -userdbctl users-in-group testuser root -userdbctl users-in-group -j testuser root | jq -userdbctl users-in-group 🐱 -(! userdbctl users-in-group '') -(! userdbctl users-in-group foo '' bar) - -userdbctl groups-of-user -userdbctl groups-of-user testuser -userdbctl groups-of-user testuser root -userdbctl groups-of-user -j testuser root | jq -userdbctl groups-of-user 🐱 -(! userdbctl groups-of-user '') -(! userdbctl groups-of-user foo '' bar) - -userdbctl services -userdbctl services -j | jq - -varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"testuser","service":"io.systemd.Multiplexer"}' -varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"root","service":"io.systemd.Multiplexer"}' -varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"dropinuser","service":"io.systemd.Multiplexer"}' -varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"uid":2000000,"service":"io.systemd.Multiplexer"}' -(! varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"","service":"io.systemd.Multiplexer"}') -(! varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"🐱","service":"io.systemd.Multiplexer"}') -(! varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"i-do-not-exist","service":"io.systemd.Multiplexer"}') - -userdbctl ssh-authorized-keys dropinuser | tee /tmp/authorized-keys -grep "ssh-ed25519" /tmp/authorized-keys -grep "ecdsa-sha2-nistp256" /tmp/authorized-keys -echo "my-top-secret-key 🐱" >/tmp/my-top-secret-key -userdbctl ssh-authorized-keys dropinuser --chain /usr/bin/cat /tmp/my-top-secret-key | tee /tmp/authorized-keys -grep "ssh-ed25519" /tmp/authorized-keys -grep "ecdsa-sha2-nistp256" /tmp/authorized-keys -grep "my-top-secret-key 🐱" /tmp/authorized-keys -(! userdbctl ssh-authorized-keys 🐱) -(! userdbctl ssh-authorized-keys dropin-user --chain) -(! userdbctl ssh-authorized-keys dropin-user --chain '') -(! SYSTEMD_LOG_LEVEL=debug userdbctl ssh-authorized-keys dropin-user --chain /usr/bin/false) - -(! userdbctl '') -for opt in json multiplexer output synthesize with-dropin with-nss with-varlink; do - (! userdbctl "--$opt=''") - (! userdbctl "--$opt='🐱'") - (! userdbctl "--$opt=foo") - (! userdbctl "--$opt=foo" "--$opt=''" "--$opt=🐱") -done - -# FIXME: sshd seems to crash inside asan currently, skip the actual ssh test hence -if command -v ssh >/dev/null && command -v sshd >/dev/null && ! [[ -v ASAN_OPTIONS ]]; then - at_exit() { - set +e - - systemctl is-active -q mysshserver.socket && systemctl stop mysshserver.socket - rm -f /tmp/homed.id_ecdsa /run/systemd/system/mysshserver{@.service,.socket} - systemctl daemon-reload - wait_for_state homedsshtest inactive - homectl remove homedsshtest - for dir in /etc /usr/lib; do - if [[ -f "$dir/pam.d/sshd.bak" ]]; then - mv "$dir/pam.d/sshd.bak" "$dir/pam.d/sshd" - fi - done - } + # Set permissions and create necessary symlinks as described in nss-systemd(8) + chmod 0600 "/run/userdb/dropinuser.user-privileged" + ln -svrf "/run/userdb/dropingroup.group" "/run/userdb/1000000.group" + ln -svrf "/run/userdb/dropinuser.user" "/run/userdb/2000000.user" + ln -svrf "/run/userdb/dropinuser.user-privileged" "/run/userdb/2000000.user-privileged" + + userdbctl + userdbctl --version + userdbctl --help --no-pager + userdbctl --no-legend + userdbctl --output=classic + userdbctl --output=friendly + userdbctl --output=table + userdbctl --output=json | jq + userdbctl -j --json=pretty | jq + userdbctl -j --json=short | jq + userdbctl --with-varlink=no + + userdbctl user + userdbctl user -S + userdbctl user -IS + userdbctl user -R + userdbctl user --disposition=regular --disposition=intrinsic + userdbctl user kkkk -z + userdbctl user --uid-min=100 --uid-max=100 + userdbctl user -B + userdbctl user testuser + userdbctl user root + userdbctl user testuser root + userdbctl user -j testuser root | jq + # Check only UID for the nobody user, since the name is build-configurable + userdbctl user --with-nss=no --synthesize=yes + userdbctl user --with-nss=no --synthesize=yes 0 root 65534 + userdbctl user dropinuser + userdbctl user 2000000 + userdbctl user --with-nss=no --with-varlink=no --synthesize=no --multiplexer=no dropinuser + userdbctl user --with-nss=no 2000000 + (! userdbctl user '') + (! userdbctl user 🐱) + (! userdbctl user 🐱 '' bar) + (! userdbctl user i-do-not-exist) + (! userdbctl user root i-do-not-exist testuser) + (! userdbctl user --with-nss=no --synthesize=no 0 root 65534) + (! userdbctl user -N root nobody) + (! userdbctl user --with-dropin=no dropinuser) + (! userdbctl user --with-dropin=no 2000000) + + userdbctl group + userdbctl group -S + userdbctl group -IS + userdbctl group -R + userdbctl group --disposition=regular --disposition=intrinsic + userdbctl group kkkk -z + userdbctl group --uid-min=100 --uid-max=100 + userdbctl group -B + userdbctl group testuser + userdbctl group root + userdbctl group testuser root + userdbctl group -j testuser root | jq + # Check only GID for the nobody group, since the name is build-configurable + userdbctl group --with-nss=no --synthesize=yes + userdbctl group --with-nss=no --synthesize=yes 0 root 65534 + userdbctl group dropingroup + userdbctl group 1000000 + userdbctl group --with-nss=no --with-varlink=no --synthesize=no --multiplexer=no dropingroup + userdbctl group --with-nss=no 1000000 + (! userdbctl group '') + (! userdbctl group 🐱) + (! userdbctl group 🐱 '' bar) + (! userdbctl group i-do-not-exist) + (! userdbctl group root i-do-not-exist testuser) + (! userdbctl group --with-nss=no --synthesize=no 0 root 65534) + (! userdbctl group --with-dropin=no dropingroup) + (! userdbctl group --with-dropin=no 1000000) + + userdbctl users-in-group + userdbctl users-in-group testuser + userdbctl users-in-group testuser root + userdbctl users-in-group -j testuser root | jq + userdbctl users-in-group 🐱 + (! userdbctl users-in-group '') + (! userdbctl users-in-group foo '' bar) + + userdbctl groups-of-user + userdbctl groups-of-user testuser + userdbctl groups-of-user testuser root + userdbctl groups-of-user -j testuser root | jq + userdbctl groups-of-user 🐱 + (! userdbctl groups-of-user '') + (! userdbctl groups-of-user foo '' bar) + + userdbctl services + userdbctl services -j | jq + + varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"testuser","service":"io.systemd.Multiplexer"}' + varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"root","service":"io.systemd.Multiplexer"}' + varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"dropinuser","service":"io.systemd.Multiplexer"}' + varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"uid":2000000,"service":"io.systemd.Multiplexer"}' + (! varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"","service":"io.systemd.Multiplexer"}') + (! varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"🐱","service":"io.systemd.Multiplexer"}') + (! varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"i-do-not-exist","service":"io.systemd.Multiplexer"}') + + userdbctl ssh-authorized-keys dropinuser | tee /tmp/authorized-keys + grep "ssh-ed25519" /tmp/authorized-keys + grep "ecdsa-sha2-nistp256" /tmp/authorized-keys + echo "my-top-secret-key 🐱" >/tmp/my-top-secret-key + userdbctl ssh-authorized-keys dropinuser --chain /usr/bin/cat /tmp/my-top-secret-key | tee /tmp/authorized-keys + grep "ssh-ed25519" /tmp/authorized-keys + grep "ecdsa-sha2-nistp256" /tmp/authorized-keys + grep "my-top-secret-key 🐱" /tmp/authorized-keys + (! userdbctl ssh-authorized-keys 🐱) + (! userdbctl ssh-authorized-keys dropin-user --chain) + (! userdbctl ssh-authorized-keys dropin-user --chain '') + (! SYSTEMD_LOG_LEVEL=debug userdbctl ssh-authorized-keys dropin-user --chain /usr/bin/false) + + (! userdbctl '') + for opt in json multiplexer output synthesize with-dropin with-nss with-varlink; do + (! userdbctl "--$opt=''") + (! userdbctl "--$opt='🐱'") + (! userdbctl "--$opt=foo") + (! userdbctl "--$opt=foo" "--$opt=''" "--$opt=🐱") + done +} + +cleanup_ssh() ( + set +e + + systemctl is-active -q mysshserver.socket && systemctl stop mysshserver.socket + rm -f /tmp/homed.id_ecdsa /run/systemd/system/mysshserver{@.service,.socket} + systemctl daemon-reload + wait_for_state homedsshtest inactive + homectl remove homedsshtest + for dir in /etc /usr/lib; do + if [[ -f "$dir/pam.d/sshd.bak" ]]; then + mv "$dir/pam.d/sshd.bak" "$dir/pam.d/sshd" + fi + done +) + +testcase_ssh() { + # FIXME: sshd seems to crash inside asan currently, skip the actual ssh test hence + if [[ -v ASAN_OPTIONS ]]; then + return 0 + fi - trap at_exit EXIT + if ! command -v ssh >/dev/null || ! command -v sshd >/dev/null; then + echo "ssh/sshd is not installed, skipping the ssh test." + return 0 + fi + + trap cleanup_ssh RETURN ERR EXIT # Test that SSH logins work with delayed unlocking ssh-keygen -N '' -C '' -t ecdsa -f /tmp/homed.id_ecdsa - NEWPASSWORD=hunter4711 homectl create \ - --disk-size=min \ - --luks-discard=yes \ - --luks-pbkdf-type=pbkdf2 \ - --luks-pbkdf-time-cost=1ms \ - --rate-limit-interval=1s \ - --rate-limit-burst=1000 \ - --enforce-password-policy=no \ - --ssh-authorized-keys=@/tmp/homed.id_ecdsa.pub \ - --stop-delay=0 \ - homedsshtest + NEWPASSWORD=hunter4711 \ + homectl create \ + --disk-size=min \ + --luks-discard=yes \ + --luks-pbkdf-type=pbkdf2 \ + --luks-pbkdf-time-cost=1ms \ + --rate-limit-interval=1s \ + --rate-limit-burst=1000 \ + --enforce-password-policy=no \ + --ssh-authorized-keys=@/tmp/homed.id_ecdsa.pub \ + --stop-delay=0 \ + homedsshtest homectl inspect homedsshtest mkdir -p /etc/ssh @@ -628,82 +657,84 @@ EOF ssh -t -t -4 -p 4711 -i /tmp/homed.id_ecdsa \ -o "SetEnv PASSWORD=hunter4711" -o "StrictHostKeyChecking no" \ homedsshtest@localhost env +} - trap - EXIT - at_exit -fi +testcase_alias() { + NEWPASSWORD=hunter4711 homectl create aliastest --storage=directory --alias=aliastest2 --alias=aliastest3 --realm=myrealm + + homectl inspect aliastest + homectl inspect aliastest2 + homectl inspect aliastest3 + homectl inspect aliastest@myrealm + homectl inspect aliastest2@myrealm + homectl inspect aliastest3@myrealm + + userdbctl user aliastest + userdbctl user aliastest2 + userdbctl user aliastest3 + userdbctl user aliastest@myrealm + userdbctl user aliastest2@myrealm + userdbctl user aliastest3@myrealm + + getent passwd aliastest + getent passwd aliastest2 + getent passwd aliastest3 + getent passwd aliastest@myrealm + getent passwd aliastest2@myrealm + getent passwd aliastest3@myrealm + + homectl remove aliastest +} -NEWPASSWORD=hunter4711 homectl create aliastest --storage=directory --alias=aliastest2 --alias=aliastest3 --realm=myrealm - -homectl inspect aliastest -homectl inspect aliastest2 -homectl inspect aliastest3 -homectl inspect aliastest@myrealm -homectl inspect aliastest2@myrealm -homectl inspect aliastest3@myrealm - -userdbctl user aliastest -userdbctl user aliastest2 -userdbctl user aliastest3 -userdbctl user aliastest@myrealm -userdbctl user aliastest2@myrealm -userdbctl user aliastest3@myrealm - -getent passwd aliastest -getent passwd aliastest2 -getent passwd aliastest3 -getent passwd aliastest@myrealm -getent passwd aliastest2@myrealm -getent passwd aliastest3@myrealm - -homectl remove aliastest - -NEWPASSWORD=quux homectl create tmpfsquota --storage=subvolume --dev-shm-limit=50K --tmp-limit=50K -P -for p in /dev/shm /tmp; do - if findmnt -n -o options "$p" | grep -q usrquota; then - # Check if we can display the quotas. If we cannot, than it's likely - # that PID1 was also not able to set the limits and we should not fail - # in the tests below. - /usr/lib/systemd/tests/unit-tests/manual/test-display-quota tmpfsquota "$p" || set +e - - run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota dd if=/dev/zero of="$p/quotatestfile1" bs=1024 count=30 - (! run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota dd if=/dev/zero of="$p/quotatestfile2" bs=1024 count=30) - run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota rm "$p/quotatestfile1" "$p/quotatestfile2" - run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota dd if=/dev/zero of="$p/quotatestfile1" bs=1024 count=30 - run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota rm "$p/quotatestfile1" - - set -e - fi -done - -systemctl stop user@"$(id -u tmpfsquota)".service -wait_for_state tmpfsquota inactive -homectl remove tmpfsquota - -NEWPASSWORD=quux homectl create subareatest --storage=subvolume -P -run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest mkdir Areas -run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest cp -av /etc/skel Areas/furb -run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest cp -av /etc/skel Areas/molb -run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest ln -s /home/srub Areas/srub -run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest ln -s /root Areas/root - -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $HOME')" = "/home/subareatest" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo x$XDG_AREA')" = "x" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $HOME')" = "/home/subareatest/Areas/furb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_AREA')" = "furb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/furb" - -PASSWORD=quux homectl update subareatest --default-area=molb -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $HOME')" = "/home/subareatest/Areas/molb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $XDG_AREA')" = "molb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/molb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $HOME')" = "/home/subareatest/Areas/furb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_AREA')" = "furb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/furb" - -# Install a PK rule that allows 'subareatest' user to invoke run0 without password, just for testing -cat >/usr/share/polkit-1/rules.d/subareatest.rules <<'EOF' +testcase_quota() { + NEWPASSWORD=quux homectl create tmpfsquota --storage=subvolume --dev-shm-limit=50K --tmp-limit=50K -P + for p in /dev/shm /tmp; do + if findmnt -n -o options "$p" | grep -q usrquota; then + # Check if we can display the quotas. If we cannot, than it's likely + # that PID1 was also not able to set the limits and we should not fail + # in the tests below. + /usr/lib/systemd/tests/unit-tests/manual/test-display-quota tmpfsquota "$p" || set +e + + run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota dd if=/dev/zero of="$p/quotatestfile1" bs=1024 count=30 + (! run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota dd if=/dev/zero of="$p/quotatestfile2" bs=1024 count=30) + run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota rm "$p/quotatestfile1" "$p/quotatestfile2" + run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota dd if=/dev/zero of="$p/quotatestfile1" bs=1024 count=30 + run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u tmpfsquota rm "$p/quotatestfile1" + + set -e + fi + done + + systemctl stop user@"$(id -u tmpfsquota)".service + wait_for_state tmpfsquota inactive + homectl remove tmpfsquota +} + +testcase_subarea() { + NEWPASSWORD=quux homectl create subareatest --storage=subvolume -P + run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest mkdir Areas + run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest cp -av /etc/skel Areas/furb + run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest cp -av /etc/skel Areas/molb + run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest ln -s /home/srub Areas/srub + run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest ln -s /root Areas/root + + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $HOME')" = "/home/subareatest" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo x$XDG_AREA')" = "x" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $HOME')" = "/home/subareatest/Areas/furb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_AREA')" = "furb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/furb" + + PASSWORD=quux homectl update subareatest --default-area=molb + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $HOME')" = "/home/subareatest/Areas/molb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $XDG_AREA')" = "molb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/molb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $HOME')" = "/home/subareatest/Areas/furb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_AREA')" = "furb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/furb" + + # Install a PK rule that allows 'subareatest' user to invoke run0 without password, just for testing + cat >/usr/share/polkit-1/rules.d/subareatest.rules <<'EOF' polkit.addRule(function(action, subject) { if (action.id == "org.freedesktop.systemd1.manage-units" && subject.user == "subareatest") { @@ -712,137 +743,169 @@ polkit.addRule(function(action, subject) { }); EOF -# Test "recursive" operation -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb bash -c 'echo $HOME')" = "/home/subareatest/Areas/molb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb bash -c 'echo $XDG_AREA')" = "molb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/molb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $HOME')" = "/home/subareatest/Areas/furb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_AREA')" = "furb" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/furb" - -# Test symlinked area -mkdir -p /home/srub -chown subareatest:subareatest /home/srub -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=srub bash -c 'echo $HOME')" = "/home/srub" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=srub bash -c 'echo $XDG_AREA')" = "srub" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=srub bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/srub" - -# Verify that login into an area not owned by target user will be redirected to main area -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=root bash -c 'echo $HOME')" = "/home/subareatest" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=root bash -c 'echo x$XDG_AREA')" = "x" -test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=root bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)" - -systemctl stop user@"$(id -u subareatest)".service - -wait_for_state subareatest inactive -homectl remove subareatest + # Test "recursive" operation + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb bash -c 'echo $HOME')" = "/home/subareatest/Areas/molb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb bash -c 'echo $XDG_AREA')" = "molb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/molb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $HOME')" = "/home/subareatest/Areas/furb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_AREA')" = "furb" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=molb run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=furb bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/furb" + + # Test symlinked area + mkdir -p /home/srub + chown subareatest:subareatest /home/srub + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=srub bash -c 'echo $HOME')" = "/home/srub" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=srub bash -c 'echo $XDG_AREA')" = "srub" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=srub bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)/Areas/srub" + + # Verify that login into an area not owned by target user will be redirected to main area + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=root bash -c 'echo $HOME')" = "/home/subareatest" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=root bash -c 'echo x$XDG_AREA')" = "x" + test "$(run0 --property=SetCredential=pam.authtok.systemd-run0:quux -u subareatest --area=root bash -c 'echo $XDG_RUNTIME_DIR')" = "/run/user/$(id -u subareatest)" + + systemctl stop user@"$(id -u subareatest)".service + + wait_for_state subareatest inactive + homectl remove subareatest +} -# Test signing key logic -homectl list-signing-keys | grep -q local.public -(! (homectl list-signing-keys | grep -q signtest.public)) +testcase_sign() { + # Test signing key logic + homectl list-signing-keys | grep -q local.public + (! (homectl list-signing-keys | grep -q signtest.public)) -IDENTITY='{"userName":"signtest","storage":"directory","disposition":"regular","privileged":{"hashedPassword":["$y$j9T$I5Wxfm.fyg.RRWlgWw.rI1$gnQqGtbpPexqxZJkWMq8FxQi5Swc.CWeKtM8LwvEUB6"]},"enforcePasswordPolicy":false,"lastChangeUSec":1740677608017608,"lastPasswordChangeUSec":1740677608017608,"signature":[{"data":"Gl4wtc0sMjVnsH6FQwG/0M+x0nLI5cvvdtSSCttUu1gNtXqYn0UI4wZi/7zX35ERht6XHWDlP4d6V8HiAst4Dg==","key":"-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA6uvVaP1vh7O6nIbiOcvyIHRl4ihYSs0R7ctxtz2Zu7E=\n-----END PUBLIC KEY-----\n"}],"secret":{"password":["test"]}}' + print_identity() { + cat <<\EOF +{ + "userName" : "signtest", + "storage" : "directory", + "disposition" : "regular", + "privileged" : { + "hashedPassword" : [ + "$y$j9T$I5Wxfm.fyg.RRWlgWw.rI1$gnQqGtbpPexqxZJkWMq8FxQi5Swc.CWeKtM8LwvEUB6" + ] + }, + "enforcePasswordPolicy" : false, + "lastChangeUSec" : 1740677608017608, + "lastPasswordChangeUSec" : 1740677608017608, + "signature" : [ + { + "data" : "Gl4wtc0sMjVnsH6FQwG/0M+x0nLI5cvvdtSSCttUu1gNtXqYn0UI4wZi/7zX35ERht6XHWDlP4d6V8HiAst4Dg==", + "key" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA6uvVaP1vh7O6nIbiOcvyIHRl4ihYSs0R7ctxtz2Zu7E=\n-----END PUBLIC KEY-----\n" + } + ], + "secret" : { + "password" : [ + "test" + ] + } +} +EOF + } -# Try with stripping the foreign signature first, this should just work -echo "$IDENTITY" | homectl create -P --identity=- --seize=yes -wait_for_state signtest inactive -homectl remove signtest + # Try with stripping the foreign signature first, this should just work + print_identity | homectl create -P --identity=- --seize=yes + wait_for_state signtest inactive + homectl remove signtest -# No try again, and don't strip the signature. It will be refused. -(! (echo "$IDENTITY" | homectl create -P --identity=- --seize=no)) + # No try again, and don't strip the signature. It will be refused. + (! (print_identity | homectl create -P --identity=- --seize=no)) -print_public_key() { - cat <