# $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"