1262566Sdes#	$OpenBSD: cert-userkey.sh,v 1.12 2013/12/06 13:52:46 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
8204861Sdes
9262566SdesPLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
10262566Sdes
11262566Sdestype_has_legacy() {
12262566Sdes	case $1 in
13262566Sdes		ed25519*|ecdsa*) return 1 ;;
14262566Sdes	esac
15262566Sdes	return 0
16262566Sdes}
17262566Sdes
18204861Sdes# Create a CA key
19204861Sdes${SSHKEYGEN} -q -N '' -t rsa  -f $OBJ/user_ca_key ||\
20204861Sdes	fail "ssh-keygen of user_ca_key failed"
21204861Sdes
22204861Sdes# Generate and sign user keys
23262566Sdesfor ktype in $PLAIN_TYPES ; do 
24204861Sdes	verbose "$tid: sign user ${ktype} cert"
25204861Sdes	${SSHKEYGEN} -q -N '' -t ${ktype} \
26204861Sdes	    -f $OBJ/cert_user_key_${ktype} || \
27204861Sdes		fail "ssh-keygen of cert_user_key_${ktype} failed"
28248613Sdes	${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
29248613Sdes	    -z $$ -n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype} ||
30204861Sdes		fail "couldn't sign cert_user_key_${ktype}"
31262566Sdes	type_has_legacy $ktype || continue
32214979Sdes	cp $OBJ/cert_user_key_${ktype} $OBJ/cert_user_key_${ktype}_v00
33214979Sdes	cp $OBJ/cert_user_key_${ktype}.pub $OBJ/cert_user_key_${ktype}_v00.pub
34262566Sdes	verbose "$tid: sign host ${ktype}_v00 cert"
35214979Sdes	${SSHKEYGEN} -q -t v00 -s $OBJ/user_ca_key -I \
36214979Sdes	    "regress user key for $USER" \
37214979Sdes	    -n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype}_v00 ||
38262566Sdes		fatal "couldn't sign cert_user_key_${ktype}_v00"
39204861Sdesdone
40204861Sdes
41214979Sdes# Test explicitly-specified principals
42262566Sdesfor ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do 
43214979Sdes	for privsep in yes no ; do
44214979Sdes		_prefix="${ktype} privsep $privsep"
45214979Sdes
46214979Sdes		# Setup for AuthorizedPrincipalsFile
47214979Sdes		rm -f $OBJ/authorized_keys_$USER
48214979Sdes		(
49214979Sdes			cat $OBJ/sshd_proxy_bak
50214979Sdes			echo "UsePrivilegeSeparation $privsep"
51214979Sdes			echo "AuthorizedPrincipalsFile " \
52214979Sdes			    "$OBJ/authorized_principals_%u"
53214979Sdes			echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
54214979Sdes		) > $OBJ/sshd_proxy
55214979Sdes
56214979Sdes		# Missing authorized_principals
57214979Sdes		verbose "$tid: ${_prefix} missing authorized_principals"
58214979Sdes		rm -f $OBJ/authorized_principals_$USER
59214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
60214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
61214979Sdes		if [ $? -eq 0 ]; then
62214979Sdes			fail "ssh cert connect succeeded unexpectedly"
63214979Sdes		fi
64214979Sdes
65214979Sdes		# Empty authorized_principals
66214979Sdes		verbose "$tid: ${_prefix} empty authorized_principals"
67214979Sdes		echo > $OBJ/authorized_principals_$USER
68214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
69214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
70214979Sdes		if [ $? -eq 0 ]; then
71214979Sdes			fail "ssh cert connect succeeded unexpectedly"
72214979Sdes		fi
73214979Sdes	
74214979Sdes		# Wrong authorized_principals
75214979Sdes		verbose "$tid: ${_prefix} wrong authorized_principals"
76214979Sdes		echo gregorsamsa > $OBJ/authorized_principals_$USER
77214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
78214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
79214979Sdes		if [ $? -eq 0 ]; then
80214979Sdes			fail "ssh cert connect succeeded unexpectedly"
81214979Sdes		fi
82214979Sdes
83214979Sdes		# Correct authorized_principals
84214979Sdes		verbose "$tid: ${_prefix} correct authorized_principals"
85214979Sdes		echo mekmitasdigoat > $OBJ/authorized_principals_$USER
86214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
87214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
88214979Sdes		if [ $? -ne 0 ]; then
89214979Sdes			fail "ssh cert connect failed"
90214979Sdes		fi
91214979Sdes
92214979Sdes		# authorized_principals with bad key option
93214979Sdes		verbose "$tid: ${_prefix} authorized_principals bad key opt"
94214979Sdes		echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
95214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
96214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
97214979Sdes		if [ $? -eq 0 ]; then
98214979Sdes			fail "ssh cert connect succeeded unexpectedly"
99214979Sdes		fi
100214979Sdes
101214979Sdes		# authorized_principals with command=false
102214979Sdes		verbose "$tid: ${_prefix} authorized_principals command=false"
103214979Sdes		echo 'command="false" mekmitasdigoat' > \
104214979Sdes		    $OBJ/authorized_principals_$USER
105214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
106214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
107214979Sdes		if [ $? -eq 0 ]; then
108214979Sdes			fail "ssh cert connect succeeded unexpectedly"
109214979Sdes		fi
110214979Sdes
111214979Sdes
112214979Sdes		# authorized_principals with command=true
113214979Sdes		verbose "$tid: ${_prefix} authorized_principals command=true"
114214979Sdes		echo 'command="true" mekmitasdigoat' > \
115214979Sdes		    $OBJ/authorized_principals_$USER
116214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
117214979Sdes		    -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
118214979Sdes		if [ $? -ne 0 ]; then
119214979Sdes			fail "ssh cert connect failed"
120214979Sdes		fi
121214979Sdes
122214979Sdes		# Setup for principals= key option
123214979Sdes		rm -f $OBJ/authorized_principals_$USER
124214979Sdes		(
125214979Sdes			cat $OBJ/sshd_proxy_bak
126214979Sdes			echo "UsePrivilegeSeparation $privsep"
127214979Sdes		) > $OBJ/sshd_proxy
128214979Sdes
129214979Sdes		# Wrong principals list
130214979Sdes		verbose "$tid: ${_prefix} wrong principals key option"
131214979Sdes		(
132255670Sdes			printf 'cert-authority,principals="gregorsamsa" '
133214979Sdes			cat $OBJ/user_ca_key.pub
134214979Sdes		) > $OBJ/authorized_keys_$USER
135214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
136214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
137214979Sdes		if [ $? -eq 0 ]; then
138214979Sdes			fail "ssh cert connect succeeded unexpectedly"
139214979Sdes		fi
140214979Sdes
141214979Sdes		# Correct principals list
142214979Sdes		verbose "$tid: ${_prefix} correct principals key option"
143214979Sdes		(
144255670Sdes			printf 'cert-authority,principals="mekmitasdigoat" '
145214979Sdes			cat $OBJ/user_ca_key.pub
146214979Sdes		) > $OBJ/authorized_keys_$USER
147214979Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} \
148214979Sdes		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
149214979Sdes		if [ $? -ne 0 ]; then
150214979Sdes			fail "ssh cert connect failed"
151214979Sdes		fi
152214979Sdes	done
153214979Sdesdone
154214979Sdes
155204861Sdesbasic_tests() {
156204861Sdes	auth=$1
157204861Sdes	if test "x$auth" = "xauthorized_keys" ; then
158204861Sdes		# Add CA to authorized_keys
159204861Sdes		(
160255670Sdes			printf 'cert-authority '
161204861Sdes			cat $OBJ/user_ca_key.pub
162204861Sdes		) > $OBJ/authorized_keys_$USER
163204861Sdes	else
164204861Sdes		echo > $OBJ/authorized_keys_$USER
165204861Sdes		extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
166204861Sdes	fi
167204861Sdes	
168262566Sdes	for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do 
169204861Sdes		for privsep in yes no ; do
170204861Sdes			_prefix="${ktype} privsep $privsep $auth"
171204861Sdes			# Simple connect
172204861Sdes			verbose "$tid: ${_prefix} connect"
173204861Sdes			(
174204861Sdes				cat $OBJ/sshd_proxy_bak
175204861Sdes				echo "UsePrivilegeSeparation $privsep"
176204861Sdes				echo "$extra_sshd"
177204861Sdes			) > $OBJ/sshd_proxy
178204861Sdes	
179204861Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
180204861Sdes			    -F $OBJ/ssh_proxy somehost true
181204861Sdes			if [ $? -ne 0 ]; then
182204861Sdes				fail "ssh cert connect failed"
183204861Sdes			fi
184204861Sdes
185204861Sdes			# Revoked keys
186204861Sdes			verbose "$tid: ${_prefix} revoked key"
187204861Sdes			(
188204861Sdes				cat $OBJ/sshd_proxy_bak
189204861Sdes				echo "UsePrivilegeSeparation $privsep"
190248613Sdes				echo "RevokedKeys $OBJ/cert_user_key_revoked"
191204861Sdes				echo "$extra_sshd"
192204861Sdes			) > $OBJ/sshd_proxy
193248613Sdes			cp $OBJ/cert_user_key_${ktype}.pub \
194248613Sdes			    $OBJ/cert_user_key_revoked
195204861Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
196204861Sdes			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
197204861Sdes			if [ $? -eq 0 ]; then
198204861Sdes				fail "ssh cert connect succeeded unexpecedly"
199204861Sdes			fi
200248613Sdes			verbose "$tid: ${_prefix} revoked via KRL"
201248613Sdes			rm $OBJ/cert_user_key_revoked
202248613Sdes			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \
203248613Sdes			    $OBJ/cert_user_key_${ktype}.pub
204248613Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
205248613Sdes			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
206248613Sdes			if [ $? -eq 0 ]; then
207248613Sdes				fail "ssh cert connect succeeded unexpecedly"
208248613Sdes			fi
209248613Sdes			verbose "$tid: ${_prefix} empty KRL"
210248613Sdes			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked
211248613Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
212248613Sdes			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
213248613Sdes			if [ $? -ne 0 ]; then
214248613Sdes				fail "ssh cert connect failed"
215248613Sdes			fi
216204861Sdes		done
217204861Sdes	
218204861Sdes		# Revoked CA
219204861Sdes		verbose "$tid: ${ktype} $auth revoked CA key"
220204861Sdes		(
221204861Sdes			cat $OBJ/sshd_proxy_bak
222204861Sdes			echo "RevokedKeys $OBJ/user_ca_key.pub"
223204861Sdes			echo "$extra_sshd"
224204861Sdes		) > $OBJ/sshd_proxy
225204861Sdes		${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
226204861Sdes		    somehost true >/dev/null 2>&1
227204861Sdes		if [ $? -eq 0 ]; then
228204861Sdes			fail "ssh cert connect succeeded unexpecedly"
229204861Sdes		fi
230204861Sdes	done
231204861Sdes	
232204861Sdes	verbose "$tid: $auth CA does not authenticate"
233204861Sdes	(
234204861Sdes		cat $OBJ/sshd_proxy_bak
235204861Sdes		echo "$extra_sshd"
236204861Sdes	) > $OBJ/sshd_proxy
237204861Sdes	verbose "$tid: ensure CA key does not authenticate user"
238204861Sdes	${SSH} -2i $OBJ/user_ca_key \
239204861Sdes	    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
240204861Sdes	if [ $? -eq 0 ]; then
241204861Sdes		fail "ssh cert connect with CA key succeeded unexpectedly"
242204861Sdes	fi
243204861Sdes}
244204861Sdes
245204861Sdesbasic_tests authorized_keys
246204861Sdesbasic_tests TrustedUserCAKeys
247204861Sdes
248204861Sdestest_one() {
249204861Sdes	ident=$1
250204861Sdes	result=$2
251204861Sdes	sign_opts=$3
252204861Sdes	auth_choice=$4
253214979Sdes	auth_opt=$5
254204861Sdes
255204861Sdes	if test "x$auth_choice" = "x" ; then
256204861Sdes		auth_choice="authorized_keys TrustedUserCAKeys"
257204861Sdes	fi
258204861Sdes
259204861Sdes	for auth in $auth_choice ; do
260214979Sdes		for ktype in rsa rsa_v00 ; do
261218767Sdes			case $ktype in
262218767Sdes			*_v00) keyv="-t v00" ;;
263218767Sdes			*) keyv="" ;;
264218767Sdes			esac
265218767Sdes
266214979Sdes			cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
267214979Sdes			if test "x$auth" = "xauthorized_keys" ; then
268214979Sdes				# Add CA to authorized_keys
269214979Sdes				(
270255670Sdes					printf "cert-authority${auth_opt} "
271214979Sdes					cat $OBJ/user_ca_key.pub
272214979Sdes				) > $OBJ/authorized_keys_$USER
273214979Sdes			else
274214979Sdes				echo > $OBJ/authorized_keys_$USER
275214979Sdes				echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
276214979Sdes				    >> $OBJ/sshd_proxy
277214979Sdes				if test "x$auth_opt" != "x" ; then
278214979Sdes					echo $auth_opt >> $OBJ/sshd_proxy
279214979Sdes				fi
280214979Sdes			fi
281214979Sdes			
282214979Sdes			verbose "$tid: $ident auth $auth expect $result $ktype"
283214979Sdes			${SSHKEYGEN} -q -s $OBJ/user_ca_key \
284214979Sdes			    -I "regress user key for $USER" \
285218767Sdes			    $sign_opts $keyv \
286214979Sdes			    $OBJ/cert_user_key_${ktype} ||
287214979Sdes				fail "couldn't sign cert_user_key_${ktype}"
288204861Sdes
289214979Sdes			${SSH} -2i $OBJ/cert_user_key_${ktype} \
290214979Sdes			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
291214979Sdes			rc=$?
292214979Sdes			if [ "x$result" = "xsuccess" ] ; then
293214979Sdes				if [ $rc -ne 0 ]; then
294214979Sdes					fail "$ident failed unexpectedly"
295214979Sdes				fi
296214979Sdes			else
297214979Sdes				if [ $rc -eq 0 ]; then
298214979Sdes					fail "$ident succeeded unexpectedly"
299214979Sdes				fi
300204861Sdes			fi
301214979Sdes		done
302204861Sdes	done
303204861Sdes}
304204861Sdes
305204861Sdestest_one "correct principal"	success "-n ${USER}"
306204861Sdestest_one "host-certificate"	failure "-n ${USER} -h"
307204861Sdestest_one "wrong principals"	failure "-n foo"
308204861Sdestest_one "cert not yet valid"	failure "-n ${USER} -V20200101:20300101"
309204861Sdestest_one "cert expired"		failure "-n ${USER} -V19800101:19900101"
310204861Sdestest_one "cert valid interval"	success "-n ${USER} -V-1w:+2w"
311204861Sdestest_one "wrong source-address"	failure "-n ${USER} -Osource-address=10.0.0.0/8"
312204861Sdestest_one "force-command"	failure "-n ${USER} -Oforce-command=false"
313204861Sdes
314204861Sdes# Behaviour is different here: TrustedUserCAKeys doesn't allow empty principals
315204861Sdestest_one "empty principals"	success "" authorized_keys
316204861Sdestest_one "empty principals"	failure "" TrustedUserCAKeys
317204861Sdes
318214979Sdes# Check explicitly-specified principals: an empty principals list in the cert
319214979Sdes# should always be refused.
320214979Sdes
321214979Sdes# AuthorizedPrincipalsFile
322214979Sdesrm -f $OBJ/authorized_keys_$USER
323214979Sdesecho mekmitasdigoat > $OBJ/authorized_principals_$USER
324214979Sdestest_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \
325214979Sdes    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
326214979Sdestest_one "AuthorizedPrincipalsFile no principals" failure "" \
327214979Sdes    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
328214979Sdes
329214979Sdes# principals= key option
330214979Sdesrm -f $OBJ/authorized_principals_$USER
331214979Sdestest_one "principals key option principals" success "-n mekmitasdigoat" \
332214979Sdes    authorized_keys ',principals="mekmitasdigoat"'
333214979Sdestest_one "principals key option no principals" failure "" \
334214979Sdes    authorized_keys ',principals="mekmitasdigoat"'
335214979Sdes
336204861Sdes# Wrong certificate
337214979Sdescat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
338262566Sdesfor ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do 
339214979Sdes	case $ktype in
340214979Sdes	*_v00) args="-t v00" ;;
341214979Sdes	*) args="" ;;
342214979Sdes	esac
343204861Sdes	# Self-sign
344214979Sdes	${SSHKEYGEN} $args -q -s $OBJ/cert_user_key_${ktype} -I \
345204861Sdes	    "regress user key for $USER" \
346204861Sdes	    -n $USER $OBJ/cert_user_key_${ktype} ||
347204861Sdes		fail "couldn't sign cert_user_key_${ktype}"
348204861Sdes	verbose "$tid: user ${ktype} connect wrong cert"
349204861Sdes	${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
350204861Sdes	    somehost true >/dev/null 2>&1
351204861Sdes	if [ $? -eq 0 ]; then
352204861Sdes		fail "ssh cert connect $ident succeeded unexpectedly"
353204861Sdes	fi
354204861Sdesdone
355204861Sdes
356204861Sdesrm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
357214979Sdesrm -f $OBJ/authorized_principals_$USER
358204861Sdes
359