xref: /freebsd/crypto/openssh/regress/hostkey-rotate.sh (revision 1323ec571215a77ddd21294f0871979d5ad6b992)
1*1323ec57SEd Maste#	$OpenBSD: hostkey-rotate.sh,v 1.10 2022/01/05 08:25:05 djm Exp $
2bc5531deSDag-Erling Smørgrav#	Placed in the Public Domain.
3bc5531deSDag-Erling Smørgrav
4bc5531deSDag-Erling Smørgravtid="hostkey rotate"
5bc5531deSDag-Erling Smørgrav
6e9e8876aSEd Maste#
7e9e8876aSEd Maste# GNU (f)grep <=2.18, as shipped by FreeBSD<=12 and NetBSD<=9 will occasionally
8e9e8876aSEd Maste# fail to find ssh host keys in the hostkey-rotate test.  If we have those
9e9e8876aSEd Maste# versions, use awk instead.
10e9e8876aSEd Maste# See # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=258616
11e9e8876aSEd Maste#
12e9e8876aSEd Mastecase `grep --version 2>&1 | awk '/GNU grep/{print $4}'` in
13e9e8876aSEd Maste2.19)			fgrep=good ;;
14e9e8876aSEd Maste1.*|2.?|2.?.?|2.1?)	fgrep=bad ;;	# stock GNU grep
15e9e8876aSEd Maste2.5.1*)			fgrep=bad ;;	# FreeBSD and NetBSD
16e9e8876aSEd Maste*)			fgrep=good ;;
17e9e8876aSEd Masteesac
18e9e8876aSEd Masteif test "x$fgrep" = "xbad"; then
19e9e8876aSEd Maste	fgrep()
20e9e8876aSEd Maste{
21e9e8876aSEd Maste	awk 'BEGIN{e=1} {if (index($0,"'$1'")>0){e=0;print}} END{exit e}' $2
22e9e8876aSEd Maste}
23e9e8876aSEd Mastefi
24e9e8876aSEd Maste
2519261079SEd Masterm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig $OBJ/ssh_proxy.orig
26bc5531deSDag-Erling Smørgrav
27bc5531deSDag-Erling Smørgravgrep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
2819261079SEd Mastemv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
2919261079SEd Mastegrep -vi 'globalknownhostsfile' $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
30bc5531deSDag-Erling Smørgravecho "UpdateHostkeys=yes" >> $OBJ/ssh_proxy
3119261079SEd Masteecho "GlobalKnownHostsFile=none" >> $OBJ/ssh_proxy
32bc5531deSDag-Erling Smørgravrm $OBJ/known_hosts
33bc5531deSDag-Erling Smørgrav
3419261079SEd Maste# The "primary" key type is ed25519 since it's supported even when built
3519261079SEd Maste# without OpenSSL.  The secondary is RSA if it's supported.
3619261079SEd Masteprimary="ssh-ed25519"
3719261079SEd Mastesecondary="$primary"
3819261079SEd Maste
39bc5531deSDag-Erling Smørgravtrace "prepare hostkeys"
40bc5531deSDag-Erling Smørgravnkeys=0
41bc5531deSDag-Erling Smørgravall_algs=""
4219261079SEd Mastefor k in $SSH_HOSTKEY_TYPES; do
43bc5531deSDag-Erling Smørgrav	${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k"
44bc5531deSDag-Erling Smørgrav	echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig
45bc5531deSDag-Erling Smørgrav	nkeys=`expr $nkeys + 1`
46bc5531deSDag-Erling Smørgrav	test "x$all_algs" = "x" || all_algs="${all_algs},"
4719261079SEd Maste	case "$k" in
48*1323ec57SEd Maste	ssh-rsa)
49*1323ec57SEd Maste		secondary="ssh-rsa"
50*1323ec57SEd Maste		all_algs="${all_algs}rsa-sha2-256,rsa-sha2-512,$k"
51*1323ec57SEd Maste		;;
52*1323ec57SEd Maste	*)
53*1323ec57SEd Maste		all_algs="${all_algs}$k"
54*1323ec57SEd Maste		;;
5519261079SEd Maste	esac
56bc5531deSDag-Erling Smørgravdone
57bc5531deSDag-Erling Smørgrav
58bc5531deSDag-Erling Smørgravdossh() {
59bc5531deSDag-Erling Smørgrav	# All ssh should succeed in this test
60bc5531deSDag-Erling Smørgrav	${SSH} -F $OBJ/ssh_proxy "$@" x true || fail "ssh $@ failed"
61bc5531deSDag-Erling Smørgrav}
62bc5531deSDag-Erling Smørgrav
63bc5531deSDag-Erling Smørgravexpect_nkeys() {
64bc5531deSDag-Erling Smørgrav	_expected=$1
65bc5531deSDag-Erling Smørgrav	_message=$2
66bc5531deSDag-Erling Smørgrav	_n=`wc -l $OBJ/known_hosts | awk '{ print $1 }'` || fatal "wc failed"
67bc5531deSDag-Erling Smørgrav	[ "x$_n" = "x$_expected" ] || fail "$_message (got $_n wanted $_expected)"
68bc5531deSDag-Erling Smørgrav}
69bc5531deSDag-Erling Smørgrav
70bc5531deSDag-Erling Smørgravcheck_key_present() {
71bc5531deSDag-Erling Smørgrav	_type=$1
72bc5531deSDag-Erling Smørgrav	_kfile=$2
73bc5531deSDag-Erling Smørgrav	test "x$_kfile" = "x" && _kfile="$OBJ/hkr.${_type}.pub"
74bc5531deSDag-Erling Smørgrav	_kpub=`awk "/$_type /"' { print $2 }' < $_kfile` || \
75bc5531deSDag-Erling Smørgrav		fatal "awk failed"
76bc5531deSDag-Erling Smørgrav	fgrep "$_kpub" $OBJ/known_hosts > /dev/null
77bc5531deSDag-Erling Smørgrav}
78bc5531deSDag-Erling Smørgrav
79bc5531deSDag-Erling Smørgravcp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
80bc5531deSDag-Erling Smørgrav
81bc5531deSDag-Erling Smørgrav# Connect to sshd with StrictHostkeyChecking=no
82bc5531deSDag-Erling Smørgravverbose "learn hostkey with StrictHostKeyChecking=no"
83bc5531deSDag-Erling Smørgrav>$OBJ/known_hosts
8419261079SEd Mastedossh -oHostKeyAlgorithms=$primary -oStrictHostKeyChecking=no
85bc5531deSDag-Erling Smørgrav# Verify no additional keys learned
86bc5531deSDag-Erling Smørgravexpect_nkeys 1 "unstrict connect keys"
8719261079SEd Mastecheck_key_present $primary || fail "unstrict didn't learn key"
88bc5531deSDag-Erling Smørgrav
89bc5531deSDag-Erling Smørgrav# Connect to sshd as usual
90bc5531deSDag-Erling Smørgravverbose "learn additional hostkeys"
91eccfee6eSDag-Erling Smørgravdossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$all_algs
92bc5531deSDag-Erling Smørgrav# Check that other keys learned
93bc5531deSDag-Erling Smørgravexpect_nkeys $nkeys "learn hostkeys"
9419261079SEd Mastefor k in $SSH_HOSTKEY_TYPES; do
9519261079SEd Maste	check_key_present $k || fail "didn't learn keytype $k"
9619261079SEd Mastedone
97bc5531deSDag-Erling Smørgrav
98bc5531deSDag-Erling Smørgrav# Check each key type
9919261079SEd Mastefor k in $SSH_HOSTKEY_TYPES; do
100*1323ec57SEd Maste	case "$k" in
101*1323ec57SEd Maste	ssh-rsa) alg="rsa-sha2-256,rsa-sha2-512,ssh-rsa" ;;
102*1323ec57SEd Maste	*) alg="$k" ;;
103*1323ec57SEd Maste	esac
104bc5531deSDag-Erling Smørgrav	verbose "learn additional hostkeys, type=$k"
105*1323ec57SEd Maste	dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$alg,$all_algs
106bc5531deSDag-Erling Smørgrav	expect_nkeys $nkeys "learn hostkeys $k"
10719261079SEd Maste	check_key_present $k || fail "didn't learn $k correctly"
108bc5531deSDag-Erling Smørgravdone
109bc5531deSDag-Erling Smørgrav
110bc5531deSDag-Erling Smørgrav# Change one hostkey (non primary) and relearn
11119261079SEd Masteif [ "$primary" != "$secondary" ]; then
11219261079SEd Maste	verbose "learn changed non-primary hostkey type=${secondary}"
11319261079SEd Maste	mv $OBJ/hkr.${secondary}.pub $OBJ/hkr.${secondary}.pub.old
11419261079SEd Maste	rm -f $OBJ/hkr.${secondary}
11519261079SEd Maste	${SSHKEYGEN} -qt ${secondary} -f $OBJ/hkr.${secondary} -N '' || \
11619261079SEd Maste	    fatal "ssh-keygen $secondary"
117eccfee6eSDag-Erling Smørgrav	dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$all_algs
118bc5531deSDag-Erling Smørgrav	# Check that the key was replaced
119bc5531deSDag-Erling Smørgrav	expect_nkeys $nkeys "learn hostkeys"
12019261079SEd Maste	check_key_present ${secondary} $OBJ/hkr.${secondary}.pub.old && \
12119261079SEd Maste	    fail "old key present"
12219261079SEd Maste	check_key_present ${secondary} || fail "didn't learn changed key"
12319261079SEd Mastefi
124bc5531deSDag-Erling Smørgrav
125bc5531deSDag-Erling Smørgrav# Add new hostkey (primary type) to sshd and connect
126bc5531deSDag-Erling Smørgravverbose "learn new primary hostkey"
12719261079SEd Maste${SSHKEYGEN} -qt ${primary} -f $OBJ/hkr.${primary}-new -N '' || fatal "ssh-keygen ed25519"
12819261079SEd Maste( cat $OBJ/sshd_proxy.orig ; echo HostKey $OBJ/hkr.${primary}-new ) \
129bc5531deSDag-Erling Smørgrav    > $OBJ/sshd_proxy
130bc5531deSDag-Erling Smørgrav# Check new hostkey added
13119261079SEd Mastedossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=${primary},$all_algs
132bc5531deSDag-Erling Smørgravexpect_nkeys `expr $nkeys + 1` "learn hostkeys"
13319261079SEd Mastecheck_key_present ${primary} || fail "current key missing"
13419261079SEd Mastecheck_key_present ${primary} $OBJ/hkr.${primary}-new.pub || fail "new key missing"
135bc5531deSDag-Erling Smørgrav
136bc5531deSDag-Erling Smørgrav# Remove old hostkey (primary type) from sshd
137bc5531deSDag-Erling Smørgravverbose "rotate primary hostkey"
138bc5531deSDag-Erling Smørgravcp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
13919261079SEd Mastemv $OBJ/hkr.${primary}.pub $OBJ/hkr.${primary}.pub.old
14019261079SEd Mastemv $OBJ/hkr.${primary}-new.pub $OBJ/hkr.${primary}.pub
14119261079SEd Mastemv $OBJ/hkr.${primary}-new $OBJ/hkr.${primary}
142bc5531deSDag-Erling Smørgrav# Check old hostkey removed
14319261079SEd Mastedossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=${primary},$all_algs
144bc5531deSDag-Erling Smørgravexpect_nkeys $nkeys "learn hostkeys"
14519261079SEd Mastecheck_key_present ${primary} $OBJ/hkr.${primary}.pub.old && fail "old key present"
14619261079SEd Mastecheck_key_present ${primary} || fail "didn't learn changed key"
147bc5531deSDag-Erling Smørgrav
148bc5531deSDag-Erling Smørgrav# Connect again, forcing rotated key
149bc5531deSDag-Erling Smørgravverbose "check rotate primary hostkey"
15019261079SEd Mastedossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=${primary}
151bc5531deSDag-Erling Smørgravexpect_nkeys 1 "learn hostkeys"
15219261079SEd Mastecheck_key_present ${primary} || fail "didn't learn changed key"
153