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