1294464Sdes#	$OpenBSD: cert-userkey.sh,v 1.14 2015/07/10 06:23:25 markus Exp $
2204861Sdes#	Placed in the Public Domain.
3204861Sdes
4204861Sdestid="certified user keys"
5204861Sdes
6204861Sdesrm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
7204861Sdescp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
8294464Sdescp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
9204861Sdes
10261320SdesPLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
11261320Sdes
12294464Sdeskname() {
13294464Sdes	n=`echo "$1" | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/'`
14294464Sdes	echo "$n*,ssh-rsa*,ssh-ed25519*"
15261320Sdes}
16261320Sdes
17204861Sdes# Create a CA key
18204861Sdes${SSHKEYGEN} -q -N '' -t rsa  -f $OBJ/user_ca_key ||\
19204861Sdes	fail "ssh-keygen of user_ca_key failed"
20204861Sdes
21204861Sdes# Generate and sign user keys
22261320Sdesfor ktype in $PLAIN_TYPES ; do 
23204861Sdes	verbose "$tid: sign user ${ktype} cert"
24204861Sdes	${SSHKEYGEN} -q -N '' -t ${ktype} \
25204861Sdes	    -f $OBJ/cert_user_key_${ktype} || \
26204861Sdes		fail "ssh-keygen of cert_user_key_${ktype} failed"
27248613Sdes	${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
28248613Sdes	    -z $$ -n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype} ||
29204861Sdes		fail "couldn't sign cert_user_key_${ktype}"
30204861Sdesdone
31204861Sdes
32214979Sdes# Test explicitly-specified principals
33294464Sdesfor ktype in $PLAIN_TYPES ; do 
34294464Sdes	t=$(kname $ktype)
35214979Sdes	for privsep in yes no ; do
36214979Sdes		_prefix="${ktype} privsep $privsep"
37214979Sdes
38214979Sdes		# Setup for AuthorizedPrincipalsFile
39214979Sdes		rm -f $OBJ/authorized_keys_$USER
40214979Sdes		(
41214979Sdes			cat $OBJ/sshd_proxy_bak
42214979Sdes			echo "UsePrivilegeSeparation $privsep"
43214979Sdes			echo "AuthorizedPrincipalsFile " \
44214979Sdes			    "$OBJ/authorized_principals_%u"
45214979Sdes			echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
46294464Sdes			echo "PubkeyAcceptedKeyTypes ${t}"
47214979Sdes		) > $OBJ/sshd_proxy
48294464Sdes		(
49294464Sdes			cat $OBJ/ssh_proxy_bak
50294464Sdes			echo "PubkeyAcceptedKeyTypes ${t}"
51294464Sdes		) > $OBJ/ssh_proxy
52214979Sdes
53214979Sdes		# Missing authorized_principals
54214979Sdes		verbose "$tid: ${_prefix} missing authorized_principals"
55214979Sdes		rm -f $OBJ/authorized_principals_$USER
56214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
57214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
58214979Sdes		if [ $? -eq 0 ]; then
59214979Sdes			fail "ssh cert connect succeeded unexpectedly"
60214979Sdes		fi
61214979Sdes
62214979Sdes		# Empty authorized_principals
63214979Sdes		verbose "$tid: ${_prefix} empty authorized_principals"
64214979Sdes		echo > $OBJ/authorized_principals_$USER
65214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
66214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
67214979Sdes		if [ $? -eq 0 ]; then
68214979Sdes			fail "ssh cert connect succeeded unexpectedly"
69214979Sdes		fi
70214979Sdes	
71214979Sdes		# Wrong authorized_principals
72214979Sdes		verbose "$tid: ${_prefix} wrong authorized_principals"
73214979Sdes		echo gregorsamsa > $OBJ/authorized_principals_$USER
74214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
75214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
76214979Sdes		if [ $? -eq 0 ]; then
77214979Sdes			fail "ssh cert connect succeeded unexpectedly"
78214979Sdes		fi
79214979Sdes
80214979Sdes		# Correct authorized_principals
81214979Sdes		verbose "$tid: ${_prefix} correct authorized_principals"
82214979Sdes		echo mekmitasdigoat > $OBJ/authorized_principals_$USER
83214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
84214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
85214979Sdes		if [ $? -ne 0 ]; then
86214979Sdes			fail "ssh cert connect failed"
87214979Sdes		fi
88214979Sdes
89214979Sdes		# authorized_principals with bad key option
90214979Sdes		verbose "$tid: ${_prefix} authorized_principals bad key opt"
91214979Sdes		echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
92214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
93214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
94214979Sdes		if [ $? -eq 0 ]; then
95214979Sdes			fail "ssh cert connect succeeded unexpectedly"
96214979Sdes		fi
97214979Sdes
98214979Sdes		# authorized_principals with command=false
99214979Sdes		verbose "$tid: ${_prefix} authorized_principals command=false"
100214979Sdes		echo 'command="false" mekmitasdigoat' > \
101214979Sdes		    $OBJ/authorized_principals_$USER
102214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
103214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
104214979Sdes		if [ $? -eq 0 ]; then
105214979Sdes			fail "ssh cert connect succeeded unexpectedly"
106214979Sdes		fi
107214979Sdes
108214979Sdes
109214979Sdes		# authorized_principals with command=true
110214979Sdes		verbose "$tid: ${_prefix} authorized_principals command=true"
111214979Sdes		echo 'command="true" mekmitasdigoat' > \
112214979Sdes		    $OBJ/authorized_principals_$USER
113214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
114214979Sdes		    -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
115214979Sdes		if [ $? -ne 0 ]; then
116214979Sdes			fail "ssh cert connect failed"
117214979Sdes		fi
118214979Sdes
119214979Sdes		# Setup for principals= key option
120214979Sdes		rm -f $OBJ/authorized_principals_$USER
121214979Sdes		(
122214979Sdes			cat $OBJ/sshd_proxy_bak
123214979Sdes			echo "UsePrivilegeSeparation $privsep"
124294464Sdes			echo "PubkeyAcceptedKeyTypes ${t}"
125214979Sdes		) > $OBJ/sshd_proxy
126294464Sdes		(
127294464Sdes			cat $OBJ/ssh_proxy_bak
128294464Sdes			echo "PubkeyAcceptedKeyTypes ${t}"
129294464Sdes		) > $OBJ/ssh_proxy
130214979Sdes
131214979Sdes		# Wrong principals list
132214979Sdes		verbose "$tid: ${_prefix} wrong principals key option"
133214979Sdes		(
134255670Sdes			printf 'cert-authority,principals="gregorsamsa" '
135214979Sdes			cat $OBJ/user_ca_key.pub
136214979Sdes		) > $OBJ/authorized_keys_$USER
137214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
138214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
139214979Sdes		if [ $? -eq 0 ]; then
140214979Sdes			fail "ssh cert connect succeeded unexpectedly"
141214979Sdes		fi
142214979Sdes
143214979Sdes		# Correct principals list
144214979Sdes		verbose "$tid: ${_prefix} correct principals key option"
145214979Sdes		(
146255670Sdes			printf 'cert-authority,principals="mekmitasdigoat" '
147214979Sdes			cat $OBJ/user_ca_key.pub
148214979Sdes		) > $OBJ/authorized_keys_$USER
149214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
150214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
151214979Sdes		if [ $? -ne 0 ]; then
152214979Sdes			fail "ssh cert connect failed"
153214979Sdes		fi
154214979Sdes	done
155214979Sdesdone
156214979Sdes
157204861Sdesbasic_tests() {
158204861Sdes	auth=$1
159204861Sdes	if test "x$auth" = "xauthorized_keys" ; then
160204861Sdes		# Add CA to authorized_keys
161204861Sdes		(
162255670Sdes			printf 'cert-authority '
163204861Sdes			cat $OBJ/user_ca_key.pub
164204861Sdes		) > $OBJ/authorized_keys_$USER
165204861Sdes	else
166204861Sdes		echo > $OBJ/authorized_keys_$USER
167204861Sdes		extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
168204861Sdes	fi
169204861Sdes	
170294464Sdes	for ktype in $PLAIN_TYPES ; do 
171294464Sdes		t=$(kname $ktype)
172204861Sdes		for privsep in yes no ; do
173204861Sdes			_prefix="${ktype} privsep $privsep $auth"
174204861Sdes			# Simple connect
175204861Sdes			verbose "$tid: ${_prefix} connect"
176204861Sdes			(
177204861Sdes				cat $OBJ/sshd_proxy_bak
178204861Sdes				echo "UsePrivilegeSeparation $privsep"
179294464Sdes				echo "PubkeyAcceptedKeyTypes ${t}"
180204861Sdes				echo "$extra_sshd"
181204861Sdes			) > $OBJ/sshd_proxy
182294464Sdes			(
183294464Sdes				cat $OBJ/ssh_proxy_bak
184294464Sdes				echo "PubkeyAcceptedKeyTypes ${t}"
185294464Sdes			) > $OBJ/ssh_proxy
186204861Sdes	
187204861Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
188204861Sdes			    -F $OBJ/ssh_proxy somehost true
189204861Sdes			if [ $? -ne 0 ]; then
190204861Sdes				fail "ssh cert connect failed"
191204861Sdes			fi
192204861Sdes
193204861Sdes			# Revoked keys
194204861Sdes			verbose "$tid: ${_prefix} revoked key"
195204861Sdes			(
196204861Sdes				cat $OBJ/sshd_proxy_bak
197204861Sdes				echo "UsePrivilegeSeparation $privsep"
198248613Sdes				echo "RevokedKeys $OBJ/cert_user_key_revoked"
199294464Sdes				echo "PubkeyAcceptedKeyTypes ${t}"
200204861Sdes				echo "$extra_sshd"
201204861Sdes			) > $OBJ/sshd_proxy
202248613Sdes			cp $OBJ/cert_user_key_${ktype}.pub \
203248613Sdes			    $OBJ/cert_user_key_revoked
204204861Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
205204861Sdes			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
206204861Sdes			if [ $? -eq 0 ]; then
207204861Sdes				fail "ssh cert connect succeeded unexpecedly"
208204861Sdes			fi
209248613Sdes			verbose "$tid: ${_prefix} revoked via KRL"
210248613Sdes			rm $OBJ/cert_user_key_revoked
211248613Sdes			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \
212248613Sdes			    $OBJ/cert_user_key_${ktype}.pub
213248613Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
214248613Sdes			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
215248613Sdes			if [ $? -eq 0 ]; then
216248613Sdes				fail "ssh cert connect succeeded unexpecedly"
217248613Sdes			fi
218248613Sdes			verbose "$tid: ${_prefix} empty KRL"
219248613Sdes			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked
220248613Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
221248613Sdes			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
222248613Sdes			if [ $? -ne 0 ]; then
223248613Sdes				fail "ssh cert connect failed"
224248613Sdes			fi
225204861Sdes		done
226204861Sdes	
227204861Sdes		# Revoked CA
228204861Sdes		verbose "$tid: ${ktype} $auth revoked CA key"
229204861Sdes		(
230204861Sdes			cat $OBJ/sshd_proxy_bak
231204861Sdes			echo "RevokedKeys $OBJ/user_ca_key.pub"
232294464Sdes			echo "PubkeyAcceptedKeyTypes ${t}"
233204861Sdes			echo "$extra_sshd"
234204861Sdes		) > $OBJ/sshd_proxy
235204861Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
236204861Sdes		    somehost true >/dev/null 2>&1
237204861Sdes		if [ $? -eq 0 ]; then
238204861Sdes			fail "ssh cert connect succeeded unexpecedly"
239204861Sdes		fi
240204861Sdes	done
241204861Sdes	
242204861Sdes	verbose "$tid: $auth CA does not authenticate"
243204861Sdes	(
244204861Sdes		cat $OBJ/sshd_proxy_bak
245294464Sdes		echo "PubkeyAcceptedKeyTypes ${t}"
246204861Sdes		echo "$extra_sshd"
247204861Sdes	) > $OBJ/sshd_proxy
248204861Sdes	verbose "$tid: ensure CA key does not authenticate user"
249204861Sdes	${SSH} -2i $OBJ/user_ca_key \
250204861Sdes	    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
251204861Sdes	if [ $? -eq 0 ]; then
252204861Sdes		fail "ssh cert connect with CA key succeeded unexpectedly"
253204861Sdes	fi
254204861Sdes}
255204861Sdes
256204861Sdesbasic_tests authorized_keys
257204861Sdesbasic_tests TrustedUserCAKeys
258204861Sdes
259204861Sdestest_one() {
260204861Sdes	ident=$1
261204861Sdes	result=$2
262204861Sdes	sign_opts=$3
263204861Sdes	auth_choice=$4
264214979Sdes	auth_opt=$5
265204861Sdes
266204861Sdes	if test "x$auth_choice" = "x" ; then
267204861Sdes		auth_choice="authorized_keys TrustedUserCAKeys"
268204861Sdes	fi
269204861Sdes
270204861Sdes	for auth in $auth_choice ; do
271294464Sdes		for ktype in rsa ed25519 ; do
272214979Sdes			cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
273214979Sdes			if test "x$auth" = "xauthorized_keys" ; then
274214979Sdes				# Add CA to authorized_keys
275214979Sdes				(
276255670Sdes					printf "cert-authority${auth_opt} "
277214979Sdes					cat $OBJ/user_ca_key.pub
278214979Sdes				) > $OBJ/authorized_keys_$USER
279214979Sdes			else
280214979Sdes				echo > $OBJ/authorized_keys_$USER
281214979Sdes				echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
282214979Sdes				    >> $OBJ/sshd_proxy
283294464Sdes				echo "PubkeyAcceptedKeyTypes ${t}*" \
284294464Sdes				    >> $OBJ/sshd_proxy
285214979Sdes				if test "x$auth_opt" != "x" ; then
286214979Sdes					echo $auth_opt >> $OBJ/sshd_proxy
287214979Sdes				fi
288214979Sdes			fi
289214979Sdes			
290214979Sdes			verbose "$tid: $ident auth $auth expect $result $ktype"
291214979Sdes			${SSHKEYGEN} -q -s $OBJ/user_ca_key \
292214979Sdes			    -I "regress user key for $USER" \
293294464Sdes			    $sign_opts $OBJ/cert_user_key_${ktype} ||
294214979Sdes				fail "couldn't sign cert_user_key_${ktype}"
295204861Sdes
296214979Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
297214979Sdes			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
298214979Sdes			rc=$?
299214979Sdes			if [ "x$result" = "xsuccess" ] ; then
300214979Sdes				if [ $rc -ne 0 ]; then
301214979Sdes					fail "$ident failed unexpectedly"
302214979Sdes				fi
303214979Sdes			else
304214979Sdes				if [ $rc -eq 0 ]; then
305214979Sdes					fail "$ident succeeded unexpectedly"
306214979Sdes				fi
307204861Sdes			fi
308214979Sdes		done
309204861Sdes	done
310204861Sdes}
311204861Sdes
312204861Sdestest_one "correct principal"	success "-n ${USER}"
313204861Sdestest_one "host-certificate"	failure "-n ${USER} -h"
314204861Sdestest_one "wrong principals"	failure "-n foo"
315204861Sdestest_one "cert not yet valid"	failure "-n ${USER} -V20200101:20300101"
316204861Sdestest_one "cert expired"		failure "-n ${USER} -V19800101:19900101"
317204861Sdestest_one "cert valid interval"	success "-n ${USER} -V-1w:+2w"
318204861Sdestest_one "wrong source-address"	failure "-n ${USER} -Osource-address=10.0.0.0/8"
319204861Sdestest_one "force-command"	failure "-n ${USER} -Oforce-command=false"
320204861Sdes
321204861Sdes# Behaviour is different here: TrustedUserCAKeys doesn't allow empty principals
322204861Sdestest_one "empty principals"	success "" authorized_keys
323204861Sdestest_one "empty principals"	failure "" TrustedUserCAKeys
324204861Sdes
325214979Sdes# Check explicitly-specified principals: an empty principals list in the cert
326214979Sdes# should always be refused.
327214979Sdes
328214979Sdes# AuthorizedPrincipalsFile
329214979Sdesrm -f $OBJ/authorized_keys_$USER
330214979Sdesecho mekmitasdigoat > $OBJ/authorized_principals_$USER
331214979Sdestest_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \
332214979Sdes    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
333214979Sdestest_one "AuthorizedPrincipalsFile no principals" failure "" \
334214979Sdes    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
335214979Sdes
336214979Sdes# principals= key option
337214979Sdesrm -f $OBJ/authorized_principals_$USER
338214979Sdestest_one "principals key option principals" success "-n mekmitasdigoat" \
339214979Sdes    authorized_keys ',principals="mekmitasdigoat"'
340214979Sdestest_one "principals key option no principals" failure "" \
341214979Sdes    authorized_keys ',principals="mekmitasdigoat"'
342214979Sdes
343204861Sdes# Wrong certificate
344214979Sdescat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
345294464Sdesfor ktype in $PLAIN_TYPES ; do 
346294464Sdes	t=$(kname $ktype)
347204861Sdes	# Self-sign
348294464Sdes	${SSHKEYGEN} -q -s $OBJ/cert_user_key_${ktype} -I \
349204861Sdes	    "regress user key for $USER" \
350204861Sdes	    -n $USER $OBJ/cert_user_key_${ktype} ||
351204861Sdes		fail "couldn't sign cert_user_key_${ktype}"
352204861Sdes	verbose "$tid: user ${ktype} connect wrong cert"
353204861Sdes	${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
354204861Sdes	    somehost true >/dev/null 2>&1
355204861Sdes	if [ $? -eq 0 ]; then
356204861Sdes		fail "ssh cert connect $ident succeeded unexpectedly"
357204861Sdes	fi
358204861Sdesdone
359204861Sdes
360204861Sdesrm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
361214979Sdesrm -f $OBJ/authorized_principals_$USER
362204861Sdes
363