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