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