1#	$OpenBSD: cert-userkey.sh,v 1.11 2013/05/17 00:37:40 dtucker Exp $
2#	Placed in the Public Domain.
3
4tid="certified user keys"
5
6# used to disable ECC based tests on platforms without ECC
7ecdsa=""
8if test "x$TEST_SSH_ECC" = "xyes"; then
9	ecdsa=ecdsa
10fi
11
12rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
13cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
14
15# Create a CA key
16${SSHKEYGEN} -q -N '' -t rsa  -f $OBJ/user_ca_key ||\
17	fail "ssh-keygen of user_ca_key failed"
18
19# Generate and sign user keys
20for ktype in rsa dsa $ecdsa ; do 
21	verbose "$tid: sign user ${ktype} cert"
22	${SSHKEYGEN} -q -N '' -t ${ktype} \
23	    -f $OBJ/cert_user_key_${ktype} || \
24		fail "ssh-keygen of cert_user_key_${ktype} failed"
25	${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
26	    -z $$ -n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype} ||
27		fail "couldn't sign cert_user_key_${ktype}"
28	# v00 ecdsa certs do not exist
29	test "${ktype}" = "ecdsa" && continue
30	cp $OBJ/cert_user_key_${ktype} $OBJ/cert_user_key_${ktype}_v00
31	cp $OBJ/cert_user_key_${ktype}.pub $OBJ/cert_user_key_${ktype}_v00.pub
32	${SSHKEYGEN} -q -t v00 -s $OBJ/user_ca_key -I \
33	    "regress user key for $USER" \
34	    -n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype}_v00 ||
35		fail "couldn't sign cert_user_key_${ktype}_v00"
36done
37
38# Test explicitly-specified principals
39for ktype in rsa dsa $ecdsa rsa_v00 dsa_v00 ; do 
40	for privsep in yes no ; do
41		_prefix="${ktype} privsep $privsep"
42
43		# Setup for AuthorizedPrincipalsFile
44		rm -f $OBJ/authorized_keys_$USER
45		(
46			cat $OBJ/sshd_proxy_bak
47			echo "UsePrivilegeSeparation $privsep"
48			echo "AuthorizedPrincipalsFile " \
49			    "$OBJ/authorized_principals_%u"
50			echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
51		) > $OBJ/sshd_proxy
52
53		# Missing authorized_principals
54		verbose "$tid: ${_prefix} missing authorized_principals"
55		rm -f $OBJ/authorized_principals_$USER
56		${SSH} -2i $OBJ/cert_user_key_${ktype} \
57		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
58		if [ $? -eq 0 ]; then
59			fail "ssh cert connect succeeded unexpectedly"
60		fi
61
62		# Empty authorized_principals
63		verbose "$tid: ${_prefix} empty authorized_principals"
64		echo > $OBJ/authorized_principals_$USER
65		${SSH} -2i $OBJ/cert_user_key_${ktype} \
66		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
67		if [ $? -eq 0 ]; then
68			fail "ssh cert connect succeeded unexpectedly"
69		fi
70	
71		# Wrong authorized_principals
72		verbose "$tid: ${_prefix} wrong authorized_principals"
73		echo gregorsamsa > $OBJ/authorized_principals_$USER
74		${SSH} -2i $OBJ/cert_user_key_${ktype} \
75		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
76		if [ $? -eq 0 ]; then
77			fail "ssh cert connect succeeded unexpectedly"
78		fi
79
80		# Correct authorized_principals
81		verbose "$tid: ${_prefix} correct authorized_principals"
82		echo mekmitasdigoat > $OBJ/authorized_principals_$USER
83		${SSH} -2i $OBJ/cert_user_key_${ktype} \
84		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
85		if [ $? -ne 0 ]; then
86			fail "ssh cert connect failed"
87		fi
88
89		# authorized_principals with bad key option
90		verbose "$tid: ${_prefix} authorized_principals bad key opt"
91		echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
92		${SSH} -2i $OBJ/cert_user_key_${ktype} \
93		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
94		if [ $? -eq 0 ]; then
95			fail "ssh cert connect succeeded unexpectedly"
96		fi
97
98		# authorized_principals with command=false
99		verbose "$tid: ${_prefix} authorized_principals command=false"
100		echo 'command="false" mekmitasdigoat' > \
101		    $OBJ/authorized_principals_$USER
102		${SSH} -2i $OBJ/cert_user_key_${ktype} \
103		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
104		if [ $? -eq 0 ]; then
105			fail "ssh cert connect succeeded unexpectedly"
106		fi
107
108
109		# authorized_principals with command=true
110		verbose "$tid: ${_prefix} authorized_principals command=true"
111		echo 'command="true" mekmitasdigoat' > \
112		    $OBJ/authorized_principals_$USER
113		${SSH} -2i $OBJ/cert_user_key_${ktype} \
114		    -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
115		if [ $? -ne 0 ]; then
116			fail "ssh cert connect failed"
117		fi
118
119		# Setup for principals= key option
120		rm -f $OBJ/authorized_principals_$USER
121		(
122			cat $OBJ/sshd_proxy_bak
123			echo "UsePrivilegeSeparation $privsep"
124		) > $OBJ/sshd_proxy
125
126		# Wrong principals list
127		verbose "$tid: ${_prefix} wrong principals key option"
128		(
129			printf 'cert-authority,principals="gregorsamsa" '
130			cat $OBJ/user_ca_key.pub
131		) > $OBJ/authorized_keys_$USER
132		${SSH} -2i $OBJ/cert_user_key_${ktype} \
133		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
134		if [ $? -eq 0 ]; then
135			fail "ssh cert connect succeeded unexpectedly"
136		fi
137
138		# Correct principals list
139		verbose "$tid: ${_prefix} correct principals key option"
140		(
141			printf 'cert-authority,principals="mekmitasdigoat" '
142			cat $OBJ/user_ca_key.pub
143		) > $OBJ/authorized_keys_$USER
144		${SSH} -2i $OBJ/cert_user_key_${ktype} \
145		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
146		if [ $? -ne 0 ]; then
147			fail "ssh cert connect failed"
148		fi
149	done
150done
151
152basic_tests() {
153	auth=$1
154	if test "x$auth" = "xauthorized_keys" ; then
155		# Add CA to authorized_keys
156		(
157			printf 'cert-authority '
158			cat $OBJ/user_ca_key.pub
159		) > $OBJ/authorized_keys_$USER
160	else
161		echo > $OBJ/authorized_keys_$USER
162		extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
163	fi
164	
165	for ktype in rsa dsa $ecdsa rsa_v00 dsa_v00 ; do 
166		for privsep in yes no ; do
167			_prefix="${ktype} privsep $privsep $auth"
168			# Simple connect
169			verbose "$tid: ${_prefix} connect"
170			(
171				cat $OBJ/sshd_proxy_bak
172				echo "UsePrivilegeSeparation $privsep"
173				echo "$extra_sshd"
174			) > $OBJ/sshd_proxy
175	
176			${SSH} -2i $OBJ/cert_user_key_${ktype} \
177			    -F $OBJ/ssh_proxy somehost true
178			if [ $? -ne 0 ]; then
179				fail "ssh cert connect failed"
180			fi
181
182			# Revoked keys
183			verbose "$tid: ${_prefix} revoked key"
184			(
185				cat $OBJ/sshd_proxy_bak
186				echo "UsePrivilegeSeparation $privsep"
187				echo "RevokedKeys $OBJ/cert_user_key_revoked"
188				echo "$extra_sshd"
189			) > $OBJ/sshd_proxy
190			cp $OBJ/cert_user_key_${ktype}.pub \
191			    $OBJ/cert_user_key_revoked
192			${SSH} -2i $OBJ/cert_user_key_${ktype} \
193			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
194			if [ $? -eq 0 ]; then
195				fail "ssh cert connect succeeded unexpecedly"
196			fi
197			verbose "$tid: ${_prefix} revoked via KRL"
198			rm $OBJ/cert_user_key_revoked
199			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \
200			    $OBJ/cert_user_key_${ktype}.pub
201			${SSH} -2i $OBJ/cert_user_key_${ktype} \
202			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
203			if [ $? -eq 0 ]; then
204				fail "ssh cert connect succeeded unexpecedly"
205			fi
206			verbose "$tid: ${_prefix} empty KRL"
207			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked
208			${SSH} -2i $OBJ/cert_user_key_${ktype} \
209			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
210			if [ $? -ne 0 ]; then
211				fail "ssh cert connect failed"
212			fi
213		done
214	
215		# Revoked CA
216		verbose "$tid: ${ktype} $auth revoked CA key"
217		(
218			cat $OBJ/sshd_proxy_bak
219			echo "RevokedKeys $OBJ/user_ca_key.pub"
220			echo "$extra_sshd"
221		) > $OBJ/sshd_proxy
222		${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
223		    somehost true >/dev/null 2>&1
224		if [ $? -eq 0 ]; then
225			fail "ssh cert connect succeeded unexpecedly"
226		fi
227	done
228	
229	verbose "$tid: $auth CA does not authenticate"
230	(
231		cat $OBJ/sshd_proxy_bak
232		echo "$extra_sshd"
233	) > $OBJ/sshd_proxy
234	verbose "$tid: ensure CA key does not authenticate user"
235	${SSH} -2i $OBJ/user_ca_key \
236	    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
237	if [ $? -eq 0 ]; then
238		fail "ssh cert connect with CA key succeeded unexpectedly"
239	fi
240}
241
242basic_tests authorized_keys
243basic_tests TrustedUserCAKeys
244
245test_one() {
246	ident=$1
247	result=$2
248	sign_opts=$3
249	auth_choice=$4
250	auth_opt=$5
251
252	if test "x$auth_choice" = "x" ; then
253		auth_choice="authorized_keys TrustedUserCAKeys"
254	fi
255
256	for auth in $auth_choice ; do
257		for ktype in rsa rsa_v00 ; do
258			case $ktype in
259			*_v00) keyv="-t v00" ;;
260			*) keyv="" ;;
261			esac
262
263			cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
264			if test "x$auth" = "xauthorized_keys" ; then
265				# Add CA to authorized_keys
266				(
267					printf "cert-authority${auth_opt} "
268					cat $OBJ/user_ca_key.pub
269				) > $OBJ/authorized_keys_$USER
270			else
271				echo > $OBJ/authorized_keys_$USER
272				echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
273				    >> $OBJ/sshd_proxy
274				if test "x$auth_opt" != "x" ; then
275					echo $auth_opt >> $OBJ/sshd_proxy
276				fi
277			fi
278			
279			verbose "$tid: $ident auth $auth expect $result $ktype"
280			${SSHKEYGEN} -q -s $OBJ/user_ca_key \
281			    -I "regress user key for $USER" \
282			    $sign_opts $keyv \
283			    $OBJ/cert_user_key_${ktype} ||
284				fail "couldn't sign cert_user_key_${ktype}"
285
286			${SSH} -2i $OBJ/cert_user_key_${ktype} \
287			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
288			rc=$?
289			if [ "x$result" = "xsuccess" ] ; then
290				if [ $rc -ne 0 ]; then
291					fail "$ident failed unexpectedly"
292				fi
293			else
294				if [ $rc -eq 0 ]; then
295					fail "$ident succeeded unexpectedly"
296				fi
297			fi
298		done
299	done
300}
301
302test_one "correct principal"	success "-n ${USER}"
303test_one "host-certificate"	failure "-n ${USER} -h"
304test_one "wrong principals"	failure "-n foo"
305test_one "cert not yet valid"	failure "-n ${USER} -V20200101:20300101"
306test_one "cert expired"		failure "-n ${USER} -V19800101:19900101"
307test_one "cert valid interval"	success "-n ${USER} -V-1w:+2w"
308test_one "wrong source-address"	failure "-n ${USER} -Osource-address=10.0.0.0/8"
309test_one "force-command"	failure "-n ${USER} -Oforce-command=false"
310
311# Behaviour is different here: TrustedUserCAKeys doesn't allow empty principals
312test_one "empty principals"	success "" authorized_keys
313test_one "empty principals"	failure "" TrustedUserCAKeys
314
315# Check explicitly-specified principals: an empty principals list in the cert
316# should always be refused.
317
318# AuthorizedPrincipalsFile
319rm -f $OBJ/authorized_keys_$USER
320echo mekmitasdigoat > $OBJ/authorized_principals_$USER
321test_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \
322    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
323test_one "AuthorizedPrincipalsFile no principals" failure "" \
324    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
325
326# principals= key option
327rm -f $OBJ/authorized_principals_$USER
328test_one "principals key option principals" success "-n mekmitasdigoat" \
329    authorized_keys ',principals="mekmitasdigoat"'
330test_one "principals key option no principals" failure "" \
331    authorized_keys ',principals="mekmitasdigoat"'
332
333# Wrong certificate
334cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
335for ktype in rsa dsa $ecdsa rsa_v00 dsa_v00 ; do 
336	case $ktype in
337	*_v00) args="-t v00" ;;
338	*) args="" ;;
339	esac
340	# Self-sign
341	${SSHKEYGEN} $args -q -s $OBJ/cert_user_key_${ktype} -I \
342	    "regress user key for $USER" \
343	    -n $USER $OBJ/cert_user_key_${ktype} ||
344		fail "couldn't sign cert_user_key_${ktype}"
345	verbose "$tid: user ${ktype} connect wrong cert"
346	${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
347	    somehost true >/dev/null 2>&1
348	if [ $? -eq 0 ]; then
349		fail "ssh cert connect $ident succeeded unexpectedly"
350	fi
351done
352
353rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
354rm -f $OBJ/authorized_principals_$USER
355
356