cert-userkey.sh revision 295367
1#	$OpenBSD: cert-userkey.sh,v 1.14 2015/07/10 06:23:25 markus Exp $
2#	Placed in the Public Domain.
3
4tid="certified user keys"
5
6rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
7cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
8cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
9
10PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
11
12kname() {
13	n=`echo "$1" | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/'`
14	echo "$n*,ssh-rsa*,ssh-ed25519*"
15}
16
17# Create a CA key
18${SSHKEYGEN} -q -N '' -t rsa  -f $OBJ/user_ca_key ||\
19	fail "ssh-keygen of user_ca_key failed"
20
21# Generate and sign user keys
22for ktype in $PLAIN_TYPES ; do 
23	verbose "$tid: sign user ${ktype} cert"
24	${SSHKEYGEN} -q -N '' -t ${ktype} \
25	    -f $OBJ/cert_user_key_${ktype} || \
26		fail "ssh-keygen of cert_user_key_${ktype} failed"
27	${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
28	    -z $$ -n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype} ||
29		fail "couldn't sign cert_user_key_${ktype}"
30done
31
32# Test explicitly-specified principals
33for ktype in $PLAIN_TYPES ; do 
34	t=$(kname $ktype)
35	for privsep in yes no ; do
36		_prefix="${ktype} privsep $privsep"
37
38		# Setup for AuthorizedPrincipalsFile
39		rm -f $OBJ/authorized_keys_$USER
40		(
41			cat $OBJ/sshd_proxy_bak
42			echo "UsePrivilegeSeparation $privsep"
43			echo "AuthorizedPrincipalsFile " \
44			    "$OBJ/authorized_principals_%u"
45			echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
46			echo "PubkeyAcceptedKeyTypes ${t}"
47		) > $OBJ/sshd_proxy
48		(
49			cat $OBJ/ssh_proxy_bak
50			echo "PubkeyAcceptedKeyTypes ${t}"
51		) > $OBJ/ssh_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			echo "PubkeyAcceptedKeyTypes ${t}"
125		) > $OBJ/sshd_proxy
126		(
127			cat $OBJ/ssh_proxy_bak
128			echo "PubkeyAcceptedKeyTypes ${t}"
129		) > $OBJ/ssh_proxy
130
131		# Wrong principals list
132		verbose "$tid: ${_prefix} wrong principals key option"
133		(
134			printf 'cert-authority,principals="gregorsamsa" '
135			cat $OBJ/user_ca_key.pub
136		) > $OBJ/authorized_keys_$USER
137		${SSH} -2i $OBJ/cert_user_key_${ktype} \
138		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
139		if [ $? -eq 0 ]; then
140			fail "ssh cert connect succeeded unexpectedly"
141		fi
142
143		# Correct principals list
144		verbose "$tid: ${_prefix} correct principals key option"
145		(
146			printf 'cert-authority,principals="mekmitasdigoat" '
147			cat $OBJ/user_ca_key.pub
148		) > $OBJ/authorized_keys_$USER
149		${SSH} -2i $OBJ/cert_user_key_${ktype} \
150		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
151		if [ $? -ne 0 ]; then
152			fail "ssh cert connect failed"
153		fi
154	done
155done
156
157basic_tests() {
158	auth=$1
159	if test "x$auth" = "xauthorized_keys" ; then
160		# Add CA to authorized_keys
161		(
162			printf 'cert-authority '
163			cat $OBJ/user_ca_key.pub
164		) > $OBJ/authorized_keys_$USER
165	else
166		echo > $OBJ/authorized_keys_$USER
167		extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
168	fi
169	
170	for ktype in $PLAIN_TYPES ; do 
171		t=$(kname $ktype)
172		for privsep in yes no ; do
173			_prefix="${ktype} privsep $privsep $auth"
174			# Simple connect
175			verbose "$tid: ${_prefix} connect"
176			(
177				cat $OBJ/sshd_proxy_bak
178				echo "UsePrivilegeSeparation $privsep"
179				echo "PubkeyAcceptedKeyTypes ${t}"
180				echo "$extra_sshd"
181			) > $OBJ/sshd_proxy
182			(
183				cat $OBJ/ssh_proxy_bak
184				echo "PubkeyAcceptedKeyTypes ${t}"
185			) > $OBJ/ssh_proxy
186	
187			${SSH} -2i $OBJ/cert_user_key_${ktype} \
188			    -F $OBJ/ssh_proxy somehost true
189			if [ $? -ne 0 ]; then
190				fail "ssh cert connect failed"
191			fi
192
193			# Revoked keys
194			verbose "$tid: ${_prefix} revoked key"
195			(
196				cat $OBJ/sshd_proxy_bak
197				echo "UsePrivilegeSeparation $privsep"
198				echo "RevokedKeys $OBJ/cert_user_key_revoked"
199				echo "PubkeyAcceptedKeyTypes ${t}"
200				echo "$extra_sshd"
201			) > $OBJ/sshd_proxy
202			cp $OBJ/cert_user_key_${ktype}.pub \
203			    $OBJ/cert_user_key_revoked
204			${SSH} -2i $OBJ/cert_user_key_${ktype} \
205			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
206			if [ $? -eq 0 ]; then
207				fail "ssh cert connect succeeded unexpecedly"
208			fi
209			verbose "$tid: ${_prefix} revoked via KRL"
210			rm $OBJ/cert_user_key_revoked
211			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \
212			    $OBJ/cert_user_key_${ktype}.pub
213			${SSH} -2i $OBJ/cert_user_key_${ktype} \
214			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
215			if [ $? -eq 0 ]; then
216				fail "ssh cert connect succeeded unexpecedly"
217			fi
218			verbose "$tid: ${_prefix} empty KRL"
219			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked
220			${SSH} -2i $OBJ/cert_user_key_${ktype} \
221			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
222			if [ $? -ne 0 ]; then
223				fail "ssh cert connect failed"
224			fi
225		done
226	
227		# Revoked CA
228		verbose "$tid: ${ktype} $auth revoked CA key"
229		(
230			cat $OBJ/sshd_proxy_bak
231			echo "RevokedKeys $OBJ/user_ca_key.pub"
232			echo "PubkeyAcceptedKeyTypes ${t}"
233			echo "$extra_sshd"
234		) > $OBJ/sshd_proxy
235		${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
236		    somehost true >/dev/null 2>&1
237		if [ $? -eq 0 ]; then
238			fail "ssh cert connect succeeded unexpecedly"
239		fi
240	done
241	
242	verbose "$tid: $auth CA does not authenticate"
243	(
244		cat $OBJ/sshd_proxy_bak
245		echo "PubkeyAcceptedKeyTypes ${t}"
246		echo "$extra_sshd"
247	) > $OBJ/sshd_proxy
248	verbose "$tid: ensure CA key does not authenticate user"
249	${SSH} -2i $OBJ/user_ca_key \
250	    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
251	if [ $? -eq 0 ]; then
252		fail "ssh cert connect with CA key succeeded unexpectedly"
253	fi
254}
255
256basic_tests authorized_keys
257basic_tests TrustedUserCAKeys
258
259test_one() {
260	ident=$1
261	result=$2
262	sign_opts=$3
263	auth_choice=$4
264	auth_opt=$5
265
266	if test "x$auth_choice" = "x" ; then
267		auth_choice="authorized_keys TrustedUserCAKeys"
268	fi
269
270	for auth in $auth_choice ; do
271		for ktype in rsa ed25519 ; do
272			cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
273			if test "x$auth" = "xauthorized_keys" ; then
274				# Add CA to authorized_keys
275				(
276					printf "cert-authority${auth_opt} "
277					cat $OBJ/user_ca_key.pub
278				) > $OBJ/authorized_keys_$USER
279			else
280				echo > $OBJ/authorized_keys_$USER
281				echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
282				    >> $OBJ/sshd_proxy
283				echo "PubkeyAcceptedKeyTypes ${t}*" \
284				    >> $OBJ/sshd_proxy
285				if test "x$auth_opt" != "x" ; then
286					echo $auth_opt >> $OBJ/sshd_proxy
287				fi
288			fi
289			
290			verbose "$tid: $ident auth $auth expect $result $ktype"
291			${SSHKEYGEN} -q -s $OBJ/user_ca_key \
292			    -I "regress user key for $USER" \
293			    $sign_opts $OBJ/cert_user_key_${ktype} ||
294				fail "couldn't sign cert_user_key_${ktype}"
295
296			${SSH} -2i $OBJ/cert_user_key_${ktype} \
297			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
298			rc=$?
299			if [ "x$result" = "xsuccess" ] ; then
300				if [ $rc -ne 0 ]; then
301					fail "$ident failed unexpectedly"
302				fi
303			else
304				if [ $rc -eq 0 ]; then
305					fail "$ident succeeded unexpectedly"
306				fi
307			fi
308		done
309	done
310}
311
312test_one "correct principal"	success "-n ${USER}"
313test_one "host-certificate"	failure "-n ${USER} -h"
314test_one "wrong principals"	failure "-n foo"
315test_one "cert not yet valid"	failure "-n ${USER} -V20200101:20300101"
316test_one "cert expired"		failure "-n ${USER} -V19800101:19900101"
317test_one "cert valid interval"	success "-n ${USER} -V-1w:+2w"
318test_one "wrong source-address"	failure "-n ${USER} -Osource-address=10.0.0.0/8"
319test_one "force-command"	failure "-n ${USER} -Oforce-command=false"
320
321# Behaviour is different here: TrustedUserCAKeys doesn't allow empty principals
322test_one "empty principals"	success "" authorized_keys
323test_one "empty principals"	failure "" TrustedUserCAKeys
324
325# Check explicitly-specified principals: an empty principals list in the cert
326# should always be refused.
327
328# AuthorizedPrincipalsFile
329rm -f $OBJ/authorized_keys_$USER
330echo mekmitasdigoat > $OBJ/authorized_principals_$USER
331test_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \
332    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
333test_one "AuthorizedPrincipalsFile no principals" failure "" \
334    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
335
336# principals= key option
337rm -f $OBJ/authorized_principals_$USER
338test_one "principals key option principals" success "-n mekmitasdigoat" \
339    authorized_keys ',principals="mekmitasdigoat"'
340test_one "principals key option no principals" failure "" \
341    authorized_keys ',principals="mekmitasdigoat"'
342
343# Wrong certificate
344cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
345for ktype in $PLAIN_TYPES ; do 
346	t=$(kname $ktype)
347	# Self-sign
348	${SSHKEYGEN} -q -s $OBJ/cert_user_key_${ktype} -I \
349	    "regress user key for $USER" \
350	    -n $USER $OBJ/cert_user_key_${ktype} ||
351		fail "couldn't sign cert_user_key_${ktype}"
352	verbose "$tid: user ${ktype} connect wrong cert"
353	${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
354	    somehost true >/dev/null 2>&1
355	if [ $? -eq 0 ]; then
356		fail "ssh cert connect $ident succeeded unexpectedly"
357	fi
358done
359
360rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
361rm -f $OBJ/authorized_principals_$USER
362
363