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