cert-hostkey.sh revision 294332
1#	$OpenBSD: cert-hostkey.sh,v 1.11 2015/01/19 06:01:32 djm Exp $
2#	Placed in the Public Domain.
3
4tid="certified host keys"
5
6rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/host_revoked_*
7rm -f $OBJ/cert_host_key* $OBJ/host_krl_*
8cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
9
10HOSTS='localhost-with-alias,127.0.0.1,::1'
11
12# Create a CA key and add it to known hosts. Ed25519 chosed for speed.
13${SSHKEYGEN} -q -N '' -t ed25519  -f $OBJ/host_ca_key ||\
14	fail "ssh-keygen of host_ca_key failed"
15(
16	printf '@cert-authority '
17	printf "$HOSTS "
18	cat $OBJ/host_ca_key.pub
19) > $OBJ/known_hosts-cert.orig
20cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
21
22# Plain text revocation files
23touch $OBJ/host_revoked_empty
24touch $OBJ/host_revoked_plain
25touch $OBJ/host_revoked_cert
26cp $OBJ/host_ca_key.pub $OBJ/host_revoked_ca
27
28PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
29
30type_has_legacy() {
31	case $1 in
32		ed25519*|ecdsa*) return 1 ;;
33	esac
34	return 0
35}
36
37# Prepare certificate, plain key and CA KRLs
38${SSHKEYGEN} -kf $OBJ/host_krl_empty || fatal "KRL init failed"
39${SSHKEYGEN} -kf $OBJ/host_krl_plain || fatal "KRL init failed"
40${SSHKEYGEN} -kf $OBJ/host_krl_cert || fatal "KRL init failed"
41${SSHKEYGEN} -kf $OBJ/host_krl_ca $OBJ/host_ca_key.pub \
42	|| fatal "KRL init failed"
43
44# Generate and sign host keys
45serial=1
46for ktype in $PLAIN_TYPES ; do 
47	verbose "$tid: sign host ${ktype} cert"
48	# Generate and sign a host key
49	${SSHKEYGEN} -q -N '' -t ${ktype} \
50	    -f $OBJ/cert_host_key_${ktype} || \
51		fatal "ssh-keygen of cert_host_key_${ktype} failed"
52	${SSHKEYGEN} -ukf $OBJ/host_krl_plain \
53	    $OBJ/cert_host_key_${ktype}.pub || fatal "KRL update failed"
54	cat $OBJ/cert_host_key_${ktype}.pub >> $OBJ/host_revoked_plain
55	${SSHKEYGEN} -h -q -s $OBJ/host_ca_key -z $serial \
56	    -I "regress host key for $USER" \
57	    -n $HOSTS $OBJ/cert_host_key_${ktype} ||
58		fatal "couldn't sign cert_host_key_${ktype}"
59	${SSHKEYGEN} -ukf $OBJ/host_krl_cert \
60	    $OBJ/cert_host_key_${ktype}-cert.pub || \
61		fatal "KRL update failed"
62	cat $OBJ/cert_host_key_${ktype}-cert.pub >> $OBJ/host_revoked_cert
63	serial=`expr $serial + 1`
64	type_has_legacy $ktype || continue
65	cp $OBJ/cert_host_key_${ktype} $OBJ/cert_host_key_${ktype}_v00
66	cp $OBJ/cert_host_key_${ktype}.pub $OBJ/cert_host_key_${ktype}_v00.pub
67	verbose "$tid: sign host ${ktype}_v00 cert"
68	${SSHKEYGEN} -t v00 -h -q -s $OBJ/host_ca_key \
69	    -I "regress host key for $USER" \
70	    -n $HOSTS $OBJ/cert_host_key_${ktype}_v00 ||
71		fatal "couldn't sign cert_host_key_${ktype}_v00"
72	${SSHKEYGEN} -ukf $OBJ/host_krl_cert \
73	    $OBJ/cert_host_key_${ktype}_v00-cert.pub || \
74		fatal "KRL update failed"
75	cat $OBJ/cert_host_key_${ktype}_v00-cert.pub >> $OBJ/host_revoked_cert
76done
77
78attempt_connect() {
79	_ident="$1"
80	_expect_success="$2"
81	shift; shift
82	verbose "$tid: $_ident expect success $_expect_success"
83	cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
84	${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
85	    -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
86	    "$@" -F $OBJ/ssh_proxy somehost true
87	_r=$?
88	if [ "x$_expect_success" = "xyes" ] ; then
89		if [ $_r -ne 0 ]; then
90			fail "ssh cert connect $_ident failed"
91		fi
92	else
93		if [ $_r -eq 0 ]; then
94			fail "ssh cert connect $_ident succeeded unexpectedly"
95		fi
96	fi
97}
98
99# Basic connect and revocation tests.
100for privsep in yes no ; do
101	for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do 
102		verbose "$tid: host ${ktype} cert connect privsep $privsep"
103		(
104			cat $OBJ/sshd_proxy_bak
105			echo HostKey $OBJ/cert_host_key_${ktype}
106			echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
107			echo UsePrivilegeSeparation $privsep
108		) > $OBJ/sshd_proxy
109
110		#               test name                         expect success
111		attempt_connect "$ktype basic connect"			"yes"
112		attempt_connect "$ktype empty KRL"			"yes" \
113		    -oRevokedHostKeys=$OBJ/host_krl_empty
114		attempt_connect "$ktype KRL w/ plain key revoked"	"no" \
115		    -oRevokedHostKeys=$OBJ/host_krl_plain
116		attempt_connect "$ktype KRL w/ cert revoked"		"no" \
117		    -oRevokedHostKeys=$OBJ/host_krl_cert
118		attempt_connect "$ktype KRL w/ CA revoked"		"no" \
119		    -oRevokedHostKeys=$OBJ/host_krl_ca
120		attempt_connect "$ktype empty plaintext revocation"	"yes" \
121		    -oRevokedHostKeys=$OBJ/host_revoked_empty
122		attempt_connect "$ktype plain key plaintext revocation"	"no" \
123		    -oRevokedHostKeys=$OBJ/host_revoked_plain
124		attempt_connect "$ktype cert plaintext revocation"	"no" \
125		    -oRevokedHostKeys=$OBJ/host_revoked_cert
126		attempt_connect "$ktype CA plaintext revocation"	"no" \
127		    -oRevokedHostKeys=$OBJ/host_revoked_ca
128	done
129done
130
131# Revoked certificates with key present
132(
133	printf '@cert-authority '
134	printf "$HOSTS "
135	cat $OBJ/host_ca_key.pub
136	for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do
137		test -f "$OBJ/cert_host_key_${ktype}.pub" || fatal "no pubkey"
138		printf "@revoked * `cat $OBJ/cert_host_key_${ktype}.pub`\n"
139	done
140) > $OBJ/known_hosts-cert.orig
141cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
142for privsep in yes no ; do
143	for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do 
144		verbose "$tid: host ${ktype} revoked cert privsep $privsep"
145		(
146			cat $OBJ/sshd_proxy_bak
147			echo HostKey $OBJ/cert_host_key_${ktype}
148			echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
149			echo UsePrivilegeSeparation $privsep
150		) > $OBJ/sshd_proxy
151
152		cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
153		${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
154		    -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
155			-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
156		if [ $? -eq 0 ]; then
157			fail "ssh cert connect succeeded unexpectedly"
158		fi
159	done
160done
161
162# Revoked CA
163(
164	printf '@cert-authority '
165	printf "$HOSTS "
166	cat $OBJ/host_ca_key.pub
167	printf '@revoked '
168	printf "* "
169	cat $OBJ/host_ca_key.pub
170) > $OBJ/known_hosts-cert.orig
171cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
172for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do 
173	verbose "$tid: host ${ktype} revoked cert"
174	(
175		cat $OBJ/sshd_proxy_bak
176		echo HostKey $OBJ/cert_host_key_${ktype}
177		echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
178	) > $OBJ/sshd_proxy
179	cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
180	${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
181	    -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
182		-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
183	if [ $? -eq 0 ]; then
184		fail "ssh cert connect succeeded unexpectedly"
185	fi
186done
187
188# Create a CA key and add it to known hosts
189(
190	printf '@cert-authority '
191	printf "$HOSTS "
192	cat $OBJ/host_ca_key.pub
193) > $OBJ/known_hosts-cert.orig
194cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
195
196test_one() {
197	ident=$1
198	result=$2
199	sign_opts=$3
200
201	for kt in rsa rsa_v00 ; do
202		case $kt in
203		*_v00) args="-t v00" ;;
204		*) args="" ;;
205		esac
206
207		verbose "$tid: host cert connect $ident $kt expect $result"
208		${SSHKEYGEN} -q -s $OBJ/host_ca_key \
209		    -I "regress host key for $USER" \
210		    $sign_opts $args \
211		    $OBJ/cert_host_key_${kt} ||
212			fail "couldn't sign cert_host_key_${kt}"
213		(
214			cat $OBJ/sshd_proxy_bak
215			echo HostKey $OBJ/cert_host_key_${kt}
216			echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
217		) > $OBJ/sshd_proxy
218	
219		cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
220		${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
221		    -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
222		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
223		rc=$?
224		if [ "x$result" = "xsuccess" ] ; then
225			if [ $rc -ne 0 ]; then
226				fail "ssh cert connect $ident failed unexpectedly"
227			fi
228		else
229			if [ $rc -eq 0 ]; then
230				fail "ssh cert connect $ident succeeded unexpectedly"
231			fi
232		fi
233	done
234}
235
236test_one "user-certificate"	failure "-n $HOSTS"
237test_one "empty principals"	success "-h"
238test_one "wrong principals"	failure "-h -n foo"
239test_one "cert not yet valid"	failure "-h -V20200101:20300101"
240test_one "cert expired"		failure "-h -V19800101:19900101"
241test_one "cert valid interval"	success "-h -V-1w:+2w"
242test_one "cert has constraints"	failure "-h -Oforce-command=false"
243
244# Check downgrade of cert to raw key when no CA found
245for v in v01 v00 ;  do 
246	for ktype in $PLAIN_TYPES ; do 
247		type_has_legacy $ktype || continue
248		rm -f $OBJ/known_hosts-cert $OBJ/cert_host_key*
249		verbose "$tid: host ${ktype} ${v} cert downgrade to raw key"
250		# Generate and sign a host key
251		${SSHKEYGEN} -q -N '' -t ${ktype} \
252		    -f $OBJ/cert_host_key_${ktype} || \
253			fail "ssh-keygen of cert_host_key_${ktype} failed"
254		${SSHKEYGEN} -t ${v} -h -q -s $OBJ/host_ca_key \
255		    -I "regress host key for $USER" \
256		    -n $HOSTS $OBJ/cert_host_key_${ktype} ||
257			fail "couldn't sign cert_host_key_${ktype}"
258		(
259			printf "$HOSTS "
260			cat $OBJ/cert_host_key_${ktype}.pub
261		) > $OBJ/known_hosts-cert
262		(
263			cat $OBJ/sshd_proxy_bak
264			echo HostKey $OBJ/cert_host_key_${ktype}
265			echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
266		) > $OBJ/sshd_proxy
267		
268		${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
269		    -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
270			-F $OBJ/ssh_proxy somehost true
271		if [ $? -ne 0 ]; then
272			fail "ssh cert connect failed"
273		fi
274	done
275done
276
277# Wrong certificate
278(
279	printf '@cert-authority '
280	printf "$HOSTS "
281	cat $OBJ/host_ca_key.pub
282) > $OBJ/known_hosts-cert.orig
283cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
284for v in v01 v00 ;  do 
285	for kt in $PLAIN_TYPES ; do 
286		type_has_legacy $kt || continue
287		rm -f $OBJ/cert_host_key*
288		# Self-sign key
289		${SSHKEYGEN} -q -N '' -t ${kt} \
290		    -f $OBJ/cert_host_key_${kt} || \
291			fail "ssh-keygen of cert_host_key_${kt} failed"
292		${SSHKEYGEN} -t ${v} -h -q -s $OBJ/cert_host_key_${kt} \
293		    -I "regress host key for $USER" \
294		    -n $HOSTS $OBJ/cert_host_key_${kt} ||
295			fail "couldn't sign cert_host_key_${kt}"
296		verbose "$tid: host ${kt} connect wrong cert"
297		(
298			cat $OBJ/sshd_proxy_bak
299			echo HostKey $OBJ/cert_host_key_${kt}
300			echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
301		) > $OBJ/sshd_proxy
302	
303		cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
304		${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
305		    -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
306			-F $OBJ/ssh_proxy -q somehost true >/dev/null 2>&1
307		if [ $? -eq 0 ]; then
308			fail "ssh cert connect $ident succeeded unexpectedly"
309		fi
310	done
311done
312
313rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/cert_host_key*
314