summaryrefslogtreecommitdiffstats
path: root/regress/agent-pkcs11-restrict.sh
blob: 867253211714671e23b4bf41d97817091ab8f91b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
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"