From 2f512f862df1d5f456f82a0334c9e8cc7208a2a1 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 18 Dec 2023 14:49:39 +0000 Subject: upstream: regress test for constrained PKCS#11 keys OpenBSD-Regress-ID: b2f26ae95d609d12257b43aef7cd7714c82618ff --- regress/Makefile | 5 +- regress/agent-pkcs11-restrict.sh | 193 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 regress/agent-pkcs11-restrict.sh diff --git a/regress/Makefile b/regress/Makefile index e6f187f5..6394a2ad 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.129 2023/10/26 18:52:45 anton Exp $ +# $OpenBSD: Makefile,v 1.130 2023/12/18 14:49:39 djm Exp $ tests: prep file-tests t-exec unit @@ -107,7 +107,8 @@ LTESTS= connect \ hostbased \ channel-timeout \ connection-timeout \ - match-subsystem + match-subsystem \ + agent-pkcs11-restrict INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers INTEROP_TESTS+= dropbear-ciphers dropbear-kex diff --git a/regress/agent-pkcs11-restrict.sh b/regress/agent-pkcs11-restrict.sh new file mode 100644 index 00000000..86725321 --- /dev/null +++ b/regress/agent-pkcs11-restrict.sh @@ -0,0 +1,193 @@ +# $OpenBSD: agent-pkcs11-restrict.sh,v 1.1 2023/12/18 14:49:39 djm Exp $ +# Placed in the Public Domain. + +tid="pkcs11 agent constraint test" + +p11_setup || skip "No PKCS#11 library found" + +rm -f $SSH_AUTH_SOCK $OBJ/agent.log $OBJ/host_[abcx]* $OBJ/user_[abcx]* +rm -f $OBJ/sshd_proxy_host* $OBJ/ssh_output* $OBJ/expect_* +rm -f $OBJ/ssh_proxy[._]* $OBJ/command $OBJ/authorized_keys_* + +trace "generate host keys" +for h in a b x ca ; do + $SSHKEYGEN -q -t ed25519 -C host_$h -N '' -f $OBJ/host_$h || \ + fatal "ssh-keygen hostkey failed" +done + +# XXX test CA hostcerts too. + +key_for() { + case $h in + a) K="${SSH_SOFTHSM_DIR}/RSA.pub" ;; + b) K="${SSH_SOFTHSM_DIR}/EC.pub" ;; + *) K="" ;; + esac + export K +} + +SSH_AUTH_SOCK="$OBJ/agent.sock" +export SSH_AUTH_SOCK +rm -f $SSH_AUTH_SOCK +trace "start agent" +${SSHAGENT} ${EXTRA_AGENT_ARGS} -d -a $SSH_AUTH_SOCK > $OBJ/agent.log 2>&1 & +AGENT_PID=$! +trap "kill $AGENT_PID" EXIT +for x in 0 1 2 3 4 ; do + # Give it a chance to start + ${SSHADD} -l > /dev/null 2>&1 + r=$? + test $r -eq 1 && break + sleep 1 +done +if [ $r -ne 1 ]; then + fatal "ssh-add -l did not fail with exit code 1 (got $r)" +fi + +# XXX a lot of this is a copy of agent-restrict.sh, but I couldn't see a nice +# way to factor it out -djm + +trace "prepare client config" +egrep -vi '(identityfile|hostname|hostkeyalias|proxycommand)' \ + $OBJ/ssh_proxy > $OBJ/ssh_proxy.bak +cat << _EOF > $OBJ/ssh_proxy +IdentitiesOnly yes +ForwardAgent yes +ExitOnForwardFailure yes +_EOF +cp $OBJ/ssh_proxy $OBJ/ssh_proxy_noid +for h in a b ; do + key_for $h + cat << _EOF >> $OBJ/ssh_proxy +Host host_$h + Hostname host_$h + HostkeyAlias host_$h + IdentityFile $K + ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h +_EOF + # Variant with no specified keys. + cat << _EOF >> $OBJ/ssh_proxy_noid +Host host_$h + Hostname host_$h + HostkeyAlias host_$h + ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h +_EOF +done +cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy +cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy_noid + +LC_ALL=C +export LC_ALL +echo "SetEnv LC_ALL=${LC_ALL}" >> sshd_proxy + +trace "prepare known_hosts" +rm -f $OBJ/known_hosts +for h in a b x ; do + (printf "host_$h " ; cat $OBJ/host_${h}.pub) >> $OBJ/known_hosts +done + +trace "prepare server configs" +egrep -vi '(hostkey|pidfile)' $OBJ/sshd_proxy \ + > $OBJ/sshd_proxy.bak +for h in a b ; do + cp $OBJ/sshd_proxy.bak $OBJ/sshd_proxy_host_$h + cat << _EOF >> $OBJ/sshd_proxy_host_$h +ExposeAuthInfo yes +Hostkey $OBJ/host_$h +_EOF + cp $OBJ/sshd_proxy_host_$h $OBJ/sshd_proxy_host_${h}.bak +done + +trace "prepare authorized_keys" +cat >> $OBJ/command << EOF +#!/bin/sh +echo USERAUTH +cat \$SSH_USER_AUTH +echo AGENT +if $SSHADD -ql >/dev/null 2>&1 ; then + $SSHADD -L | cut -d' ' -f1-2 | sort +else + echo NONE +fi +EOF +chmod a+x $OBJ/command +>$OBJ/authorized_keys_$USER +for h in a b ; do + key_for $h + (printf "%s" "restrict,agent-forwarding,command=\"$OBJ/command\" "; + cat $K) >> $OBJ/authorized_keys_$USER +done + +trace "unrestricted keys" +$SSHADD -qD >/dev/null || fatal "clear agent failed" +p11_ssh_add -qs ${TEST_SSH_PKCS11} || + fatal "failed to add keys" +for h in a b ; do + key_for $h + echo USERAUTH > $OBJ/expect_$h + printf "publickey " >> $OBJ/expect_$h + cat $K >> $OBJ/expect_$h + echo AGENT >> $OBJ/expect_$h + $SSHADD -L | cut -d' ' -f1-2 | sort >> $OBJ/expect_$h + ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ + host_$h true > $OBJ/ssh_output || fatal "test ssh $h failed" + cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" +done + +trace "restricted to different host" +$SSHADD -qD >/dev/null || fatal "clear agent failed" +p11_ssh_add -q -h host_x -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || + fatal "failed to add keys" +for h in a b ; do + key_for $h + ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ + host_$h true > $OBJ/ssh_output && fatal "test ssh $h succeeded" +done + +trace "restricted to destination host" +$SSHADD -qD >/dev/null || fatal "clear agent failed" +p11_ssh_add -q -h host_a -h host_b -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || + fatal "failed to add keys" +for h in a b ; do + key_for $h + echo USERAUTH > $OBJ/expect_$h + printf "publickey " >> $OBJ/expect_$h + cat $K >> $OBJ/expect_$h + echo AGENT >> $OBJ/expect_$h + echo NONE >> $OBJ/expect_$h + ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ + host_$h true > $OBJ/ssh_output || fatal "test ssh $h failed" + cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" +done + +trace "restricted multihop" +$SSHADD -qD >/dev/null || fatal "clear agent failed" +p11_ssh_add -q -h host_a -h "host_a>host_b" \ + -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || fatal "failed to add keys" +key_for a +AK=$K +key_for b +BK=$K +# Prepare authorized_keys file to additionally ssh to host_b +_command="echo LOCAL ; ${OBJ}/command ; echo REMOTE; ${SSH} -AF $OBJ/ssh_proxy -oIdentityFile=$BK host_b" +(printf "%s" "restrict,agent-forwarding,command=\"$_command\" "; + cat $BK) > $OBJ/authorized_keys_a +grep -vi AuthorizedKeysFile $OBJ/sshd_proxy_host_a.bak > $OBJ/sshd_proxy_host_a +echo "AuthorizedKeysFile $OBJ/authorized_keys_a" >> $OBJ/sshd_proxy_host_a +# Prepare expected output from both hosts. +echo LOCAL > $OBJ/expect_a +echo USERAUTH >> $OBJ/expect_a +printf "publickey " >> $OBJ/expect_a +cat $AK >> $OBJ/expect_a +echo AGENT >> $OBJ/expect_a +$SSHADD -L | cut -d' ' -f1-2 | sort >> $OBJ/expect_a +echo REMOTE >> $OBJ/expect_a +echo USERAUTH >> $OBJ/expect_a +printf "publickey " >> $OBJ/expect_a +cat $BK >> $OBJ/expect_a +echo AGENT >> $OBJ/expect_a +echo NONE >> $OBJ/expect_a +${SSH} -AF $OBJ/ssh_proxy -oIdentityFile=$AK \ + host_a whatever > $OBJ/ssh_output || fatal "test ssh $h failed" +cmp $OBJ/expect_a $OBJ/ssh_output || fatal "unexpected output" + -- cgit v1.2.3