mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
621 lines
22 KiB
Bash
Executable File
621 lines
22 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
set -eux
|
|
set -o pipefail
|
|
|
|
# Check if homectl is installed, and if it isn't bail out early instead of failing
|
|
if ! test -x /usr/bin/homectl ; then
|
|
echo "no homed" >/skipped
|
|
exit 77
|
|
fi
|
|
|
|
inspect() {
|
|
# As updating disk-size-related attributes can take some time on some
|
|
# filesystems, let's drop these fields before comparing the outputs to
|
|
# avoid unexpected fails. To see the full outputs of both homectl &
|
|
# userdbctl (for debugging purposes) drop the fields just before the
|
|
# comparison.
|
|
local USERNAME="${1:?}"
|
|
homectl inspect "$USERNAME" | tee /tmp/a
|
|
userdbctl user "$USERNAME" | tee /tmp/b
|
|
|
|
# diff uses the grep BREs for pattern matching
|
|
diff -I '^\s*Disk \(Size\|Free\|Floor\|Ceiling\|Usage\):' /tmp/{a,b}
|
|
rm /tmp/{a,b}
|
|
|
|
homectl inspect --json=pretty "$USERNAME"
|
|
}
|
|
|
|
wait_for_state() {
|
|
for i in {1..10}; do
|
|
(( i > 1 )) && sleep 0.5
|
|
homectl inspect "$1" | grep -qF "State: $2" && break
|
|
done
|
|
}
|
|
|
|
FSTYPE="$(stat --file-system --format "%T" /)"
|
|
|
|
systemctl start systemd-homed.service systemd-userdbd.socket
|
|
|
|
systemd-analyze log-level debug
|
|
systemctl service-log-level systemd-homed debug
|
|
|
|
# Create a tmpfs to use as backing store for the home dir. That way we can enforce a size limit nicely.
|
|
mkdir -p /home
|
|
mount -t tmpfs tmpfs /home -o size=290M
|
|
|
|
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
|
|
|
|
homectl deactivate test-user
|
|
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
|
|
|
|
# Key should now be in the keyring
|
|
homectl update test-user --real-name "Keyring 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
|
|
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
|
|
|
|
# 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
|
|
|
|
# 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 \
|
|
-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 \
|
|
-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 \
|
|
-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 \
|
|
-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
|
|
(! 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
|
|
|
|
# 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
|
|
{
|
|
"userName" : "dropinuser",
|
|
"uid" : 2000000,
|
|
"realName" : "🐱",
|
|
"memberOf" : [
|
|
"dropingroup"
|
|
]
|
|
}
|
|
EOF
|
|
cat >"/run/userdb/dropinuser.user-privileged" <<\EOF
|
|
{
|
|
"privileged" : {
|
|
"hashedPassword" : [
|
|
"$6$WHBKvAFFT9jKPA4k$OPY4D4TczKN/jOnJzy54DDuOOagCcvxxybrwMbe1SVdm.Bbr.zOmBdATp.QrwZmvqyr8/SafbbQu.QZ2rRvDs/"
|
|
],
|
|
"sshAuthorizedKeys" : [
|
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA//dxI2xLg4MgxIKKZv1nqwTEIlE/fdakii2Fb75pG+ foo@bar.tld",
|
|
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMlaqG2rTMje5CQnfjXJKmoSpEVJ2gWtx4jBvsQbmee2XbU/Qdq5+SRisssR9zVuxgg5NA5fv08MgjwJQMm+csc= hello@world.tld"
|
|
]
|
|
}
|
|
}
|
|
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 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 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 /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 /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
|
|
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
|
|
}
|
|
|
|
trap at_exit 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
|
|
homectl inspect homedsshtest
|
|
|
|
mkdir -p /etc/ssh
|
|
test -f /etc/ssh/ssh_host_ecdsa_key || ssh-keygen -t ecdsa -C '' -N '' -f /etc/ssh/ssh_host_ecdsa_key
|
|
|
|
# ssh wants this dir around, but distros cannot agree on a common name for it, let's just create all that
|
|
# are aware of distros use
|
|
mkdir -p /usr/share/empty.sshd /var/empty /var/empty/sshd /run/sshd
|
|
|
|
for dir in /etc /usr/lib; do
|
|
if [[ -f "$dir/pam.d/sshd" ]]; then
|
|
mv "$dir/pam.d/sshd" "$dir/pam.d/sshd.bak"
|
|
cat >"$dir/pam.d/sshd" <<EOF
|
|
auth sufficient pam_unix.so nullok
|
|
auth sufficient pam_systemd_home.so debug
|
|
auth required pam_deny.so
|
|
account sufficient pam_systemd_home.so debug
|
|
account sufficient pam_unix.so
|
|
account required pam_permit.so
|
|
session optional pam_systemd_home.so debug
|
|
session optional pam_systemd.so
|
|
session required pam_unix.so
|
|
EOF
|
|
break
|
|
fi
|
|
done
|
|
|
|
mkdir -p /etc/sshd/
|
|
cat >/etc/ssh/sshd_config <<EOF
|
|
AuthorizedKeysCommand /usr/bin/userdbctl ssh-authorized-keys %u
|
|
AuthorizedKeysCommandUser root
|
|
UsePAM yes
|
|
AcceptEnv PASSWORD
|
|
LogLevel DEBUG3
|
|
EOF
|
|
|
|
cat >/run/systemd/system/mysshserver.socket <<EOF
|
|
[Socket]
|
|
ListenStream=4711
|
|
Accept=yes
|
|
EOF
|
|
|
|
cat >/run/systemd/system/mysshserver@.service <<EOF
|
|
[Service]
|
|
ExecStart=-/usr/sbin/sshd -i -d -e
|
|
StandardInput=socket
|
|
StandardOutput=socket
|
|
StandardError=journal
|
|
EOF
|
|
|
|
systemctl daemon-reload
|
|
systemctl start mysshserver.socket
|
|
|
|
userdbctl user -j homedsshtest
|
|
|
|
ssh -t -t -4 -p 4711 -i /tmp/homed.id_ecdsa \
|
|
-o "SetEnv PASSWORD=hunter4711" -o "StrictHostKeyChecking no" \
|
|
homedsshtest@localhost echo zzz | tr -d '\r' | tee /tmp/homedsshtest.out
|
|
grep -E "^zzz$" /tmp/homedsshtest.out
|
|
rm /tmp/homedsshtest.out
|
|
|
|
ssh -t -t -4 -p 4711 -i /tmp/homed.id_ecdsa \
|
|
-o "SetEnv PASSWORD=hunter4711" -o "StrictHostKeyChecking no" \
|
|
homedsshtest@localhost env
|
|
|
|
wait_for_state homedsshtest inactive
|
|
fi
|
|
|
|
systemd-analyze log-level info
|
|
|
|
touch /testok
|