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