1*bb23672eSdjm# $OpenBSD: agent-pkcs11-restrict.sh,v 1.1 2023/12/18 14:49:39 djm Exp $ 2*bb23672eSdjm# Placed in the Public Domain. 3*bb23672eSdjm 4*bb23672eSdjmtid="pkcs11 agent constraint test" 5*bb23672eSdjm 6*bb23672eSdjmp11_setup || skip "No PKCS#11 library found" 7*bb23672eSdjm 8*bb23672eSdjmrm -f $SSH_AUTH_SOCK $OBJ/agent.log $OBJ/host_[abcx]* $OBJ/user_[abcx]* 9*bb23672eSdjmrm -f $OBJ/sshd_proxy_host* $OBJ/ssh_output* $OBJ/expect_* 10*bb23672eSdjmrm -f $OBJ/ssh_proxy[._]* $OBJ/command $OBJ/authorized_keys_* 11*bb23672eSdjm 12*bb23672eSdjmtrace "generate host keys" 13*bb23672eSdjmfor h in a b x ca ; do 14*bb23672eSdjm $SSHKEYGEN -q -t ed25519 -C host_$h -N '' -f $OBJ/host_$h || \ 15*bb23672eSdjm fatal "ssh-keygen hostkey failed" 16*bb23672eSdjmdone 17*bb23672eSdjm 18*bb23672eSdjm# XXX test CA hostcerts too. 19*bb23672eSdjm 20*bb23672eSdjmkey_for() { 21*bb23672eSdjm case $h in 22*bb23672eSdjm a) K="${SSH_SOFTHSM_DIR}/RSA.pub" ;; 23*bb23672eSdjm b) K="${SSH_SOFTHSM_DIR}/EC.pub" ;; 24*bb23672eSdjm *) K="" ;; 25*bb23672eSdjm esac 26*bb23672eSdjm export K 27*bb23672eSdjm} 28*bb23672eSdjm 29*bb23672eSdjmSSH_AUTH_SOCK="$OBJ/agent.sock" 30*bb23672eSdjmexport SSH_AUTH_SOCK 31*bb23672eSdjmrm -f $SSH_AUTH_SOCK 32*bb23672eSdjmtrace "start agent" 33*bb23672eSdjm${SSHAGENT} ${EXTRA_AGENT_ARGS} -d -a $SSH_AUTH_SOCK > $OBJ/agent.log 2>&1 & 34*bb23672eSdjmAGENT_PID=$! 35*bb23672eSdjmtrap "kill $AGENT_PID" EXIT 36*bb23672eSdjmfor x in 0 1 2 3 4 ; do 37*bb23672eSdjm # Give it a chance to start 38*bb23672eSdjm ${SSHADD} -l > /dev/null 2>&1 39*bb23672eSdjm r=$? 40*bb23672eSdjm test $r -eq 1 && break 41*bb23672eSdjm sleep 1 42*bb23672eSdjmdone 43*bb23672eSdjmif [ $r -ne 1 ]; then 44*bb23672eSdjm fatal "ssh-add -l did not fail with exit code 1 (got $r)" 45*bb23672eSdjmfi 46*bb23672eSdjm 47*bb23672eSdjm# XXX a lot of this is a copy of agent-restrict.sh, but I couldn't see a nice 48*bb23672eSdjm# way to factor it out -djm 49*bb23672eSdjm 50*bb23672eSdjmtrace "prepare client config" 51*bb23672eSdjmegrep -vi '(identityfile|hostname|hostkeyalias|proxycommand)' \ 52*bb23672eSdjm $OBJ/ssh_proxy > $OBJ/ssh_proxy.bak 53*bb23672eSdjmcat << _EOF > $OBJ/ssh_proxy 54*bb23672eSdjmIdentitiesOnly yes 55*bb23672eSdjmForwardAgent yes 56*bb23672eSdjmExitOnForwardFailure yes 57*bb23672eSdjm_EOF 58*bb23672eSdjmcp $OBJ/ssh_proxy $OBJ/ssh_proxy_noid 59*bb23672eSdjmfor h in a b ; do 60*bb23672eSdjm key_for $h 61*bb23672eSdjm cat << _EOF >> $OBJ/ssh_proxy 62*bb23672eSdjmHost host_$h 63*bb23672eSdjm Hostname host_$h 64*bb23672eSdjm HostkeyAlias host_$h 65*bb23672eSdjm IdentityFile $K 66*bb23672eSdjm ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h 67*bb23672eSdjm_EOF 68*bb23672eSdjm # Variant with no specified keys. 69*bb23672eSdjm cat << _EOF >> $OBJ/ssh_proxy_noid 70*bb23672eSdjmHost host_$h 71*bb23672eSdjm Hostname host_$h 72*bb23672eSdjm HostkeyAlias host_$h 73*bb23672eSdjm ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h 74*bb23672eSdjm_EOF 75*bb23672eSdjmdone 76*bb23672eSdjmcat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy 77*bb23672eSdjmcat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy_noid 78*bb23672eSdjm 79*bb23672eSdjmLC_ALL=C 80*bb23672eSdjmexport LC_ALL 81*bb23672eSdjmecho "SetEnv LC_ALL=${LC_ALL}" >> sshd_proxy 82*bb23672eSdjm 83*bb23672eSdjmtrace "prepare known_hosts" 84*bb23672eSdjmrm -f $OBJ/known_hosts 85*bb23672eSdjmfor h in a b x ; do 86*bb23672eSdjm (printf "host_$h " ; cat $OBJ/host_${h}.pub) >> $OBJ/known_hosts 87*bb23672eSdjmdone 88*bb23672eSdjm 89*bb23672eSdjmtrace "prepare server configs" 90*bb23672eSdjmegrep -vi '(hostkey|pidfile)' $OBJ/sshd_proxy \ 91*bb23672eSdjm > $OBJ/sshd_proxy.bak 92*bb23672eSdjmfor h in a b ; do 93*bb23672eSdjm cp $OBJ/sshd_proxy.bak $OBJ/sshd_proxy_host_$h 94*bb23672eSdjm cat << _EOF >> $OBJ/sshd_proxy_host_$h 95*bb23672eSdjmExposeAuthInfo yes 96*bb23672eSdjmHostkey $OBJ/host_$h 97*bb23672eSdjm_EOF 98*bb23672eSdjm cp $OBJ/sshd_proxy_host_$h $OBJ/sshd_proxy_host_${h}.bak 99*bb23672eSdjmdone 100*bb23672eSdjm 101*bb23672eSdjmtrace "prepare authorized_keys" 102*bb23672eSdjmcat >> $OBJ/command << EOF 103*bb23672eSdjm#!/bin/sh 104*bb23672eSdjmecho USERAUTH 105*bb23672eSdjmcat \$SSH_USER_AUTH 106*bb23672eSdjmecho AGENT 107*bb23672eSdjmif $SSHADD -ql >/dev/null 2>&1 ; then 108*bb23672eSdjm $SSHADD -L | cut -d' ' -f1-2 | sort 109*bb23672eSdjmelse 110*bb23672eSdjm echo NONE 111*bb23672eSdjmfi 112*bb23672eSdjmEOF 113*bb23672eSdjmchmod a+x $OBJ/command 114*bb23672eSdjm>$OBJ/authorized_keys_$USER 115*bb23672eSdjmfor h in a b ; do 116*bb23672eSdjm key_for $h 117*bb23672eSdjm (printf "%s" "restrict,agent-forwarding,command=\"$OBJ/command\" "; 118*bb23672eSdjm cat $K) >> $OBJ/authorized_keys_$USER 119*bb23672eSdjmdone 120*bb23672eSdjm 121*bb23672eSdjmtrace "unrestricted keys" 122*bb23672eSdjm$SSHADD -qD >/dev/null || fatal "clear agent failed" 123*bb23672eSdjmp11_ssh_add -qs ${TEST_SSH_PKCS11} || 124*bb23672eSdjm fatal "failed to add keys" 125*bb23672eSdjmfor h in a b ; do 126*bb23672eSdjm key_for $h 127*bb23672eSdjm echo USERAUTH > $OBJ/expect_$h 128*bb23672eSdjm printf "publickey " >> $OBJ/expect_$h 129*bb23672eSdjm cat $K >> $OBJ/expect_$h 130*bb23672eSdjm echo AGENT >> $OBJ/expect_$h 131*bb23672eSdjm $SSHADD -L | cut -d' ' -f1-2 | sort >> $OBJ/expect_$h 132*bb23672eSdjm ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ 133*bb23672eSdjm host_$h true > $OBJ/ssh_output || fatal "test ssh $h failed" 134*bb23672eSdjm cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" 135*bb23672eSdjmdone 136*bb23672eSdjm 137*bb23672eSdjmtrace "restricted to different host" 138*bb23672eSdjm$SSHADD -qD >/dev/null || fatal "clear agent failed" 139*bb23672eSdjmp11_ssh_add -q -h host_x -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || 140*bb23672eSdjm fatal "failed to add keys" 141*bb23672eSdjmfor h in a b ; do 142*bb23672eSdjm key_for $h 143*bb23672eSdjm ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ 144*bb23672eSdjm host_$h true > $OBJ/ssh_output && fatal "test ssh $h succeeded" 145*bb23672eSdjmdone 146*bb23672eSdjm 147*bb23672eSdjmtrace "restricted to destination host" 148*bb23672eSdjm$SSHADD -qD >/dev/null || fatal "clear agent failed" 149*bb23672eSdjmp11_ssh_add -q -h host_a -h host_b -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || 150*bb23672eSdjm fatal "failed to add keys" 151*bb23672eSdjmfor h in a b ; do 152*bb23672eSdjm key_for $h 153*bb23672eSdjm echo USERAUTH > $OBJ/expect_$h 154*bb23672eSdjm printf "publickey " >> $OBJ/expect_$h 155*bb23672eSdjm cat $K >> $OBJ/expect_$h 156*bb23672eSdjm echo AGENT >> $OBJ/expect_$h 157*bb23672eSdjm echo NONE >> $OBJ/expect_$h 158*bb23672eSdjm ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ 159*bb23672eSdjm host_$h true > $OBJ/ssh_output || fatal "test ssh $h failed" 160*bb23672eSdjm cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" 161*bb23672eSdjmdone 162*bb23672eSdjm 163*bb23672eSdjmtrace "restricted multihop" 164*bb23672eSdjm$SSHADD -qD >/dev/null || fatal "clear agent failed" 165*bb23672eSdjmp11_ssh_add -q -h host_a -h "host_a>host_b" \ 166*bb23672eSdjm -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || fatal "failed to add keys" 167*bb23672eSdjmkey_for a 168*bb23672eSdjmAK=$K 169*bb23672eSdjmkey_for b 170*bb23672eSdjmBK=$K 171*bb23672eSdjm# Prepare authorized_keys file to additionally ssh to host_b 172*bb23672eSdjm_command="echo LOCAL ; ${OBJ}/command ; echo REMOTE; ${SSH} -AF $OBJ/ssh_proxy -oIdentityFile=$BK host_b" 173*bb23672eSdjm(printf "%s" "restrict,agent-forwarding,command=\"$_command\" "; 174*bb23672eSdjm cat $BK) > $OBJ/authorized_keys_a 175*bb23672eSdjmgrep -vi AuthorizedKeysFile $OBJ/sshd_proxy_host_a.bak > $OBJ/sshd_proxy_host_a 176*bb23672eSdjmecho "AuthorizedKeysFile $OBJ/authorized_keys_a" >> $OBJ/sshd_proxy_host_a 177*bb23672eSdjm# Prepare expected output from both hosts. 178*bb23672eSdjmecho LOCAL > $OBJ/expect_a 179*bb23672eSdjmecho USERAUTH >> $OBJ/expect_a 180*bb23672eSdjmprintf "publickey " >> $OBJ/expect_a 181*bb23672eSdjmcat $AK >> $OBJ/expect_a 182*bb23672eSdjmecho AGENT >> $OBJ/expect_a 183*bb23672eSdjm$SSHADD -L | cut -d' ' -f1-2 | sort >> $OBJ/expect_a 184*bb23672eSdjmecho REMOTE >> $OBJ/expect_a 185*bb23672eSdjmecho USERAUTH >> $OBJ/expect_a 186*bb23672eSdjmprintf "publickey " >> $OBJ/expect_a 187*bb23672eSdjmcat $BK >> $OBJ/expect_a 188*bb23672eSdjmecho AGENT >> $OBJ/expect_a 189*bb23672eSdjmecho NONE >> $OBJ/expect_a 190*bb23672eSdjm${SSH} -AF $OBJ/ssh_proxy -oIdentityFile=$AK \ 191*bb23672eSdjm host_a whatever > $OBJ/ssh_output || fatal "test ssh $h failed" 192*bb23672eSdjmcmp $OBJ/expect_a $OBJ/ssh_output || fatal "unexpected output" 193*bb23672eSdjm 194