1294464Sdes# $OpenBSD: cert-userkey.sh,v 1.14 2015/07/10 06:23:25 markus Exp $ 2204861Sdes# Placed in the Public Domain. 3204861Sdes 4204861Sdestid="certified user keys" 5204861Sdes 6204861Sdesrm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key* 7204861Sdescp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak 8294464Sdescp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak 9204861Sdes 10261320SdesPLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` 11261320Sdes 12294464Sdeskname() { 13294464Sdes n=`echo "$1" | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/'` 14294464Sdes echo "$n*,ssh-rsa*,ssh-ed25519*" 15261320Sdes} 16261320Sdes 17204861Sdes# Create a CA key 18204861Sdes${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/user_ca_key ||\ 19204861Sdes fail "ssh-keygen of user_ca_key failed" 20204861Sdes 21204861Sdes# Generate and sign user keys 22261320Sdesfor ktype in $PLAIN_TYPES ; do 23204861Sdes verbose "$tid: sign user ${ktype} cert" 24204861Sdes ${SSHKEYGEN} -q -N '' -t ${ktype} \ 25204861Sdes -f $OBJ/cert_user_key_${ktype} || \ 26204861Sdes fail "ssh-keygen of cert_user_key_${ktype} failed" 27248613Sdes ${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \ 28248613Sdes -z $$ -n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype} || 29204861Sdes fail "couldn't sign cert_user_key_${ktype}" 30204861Sdesdone 31204861Sdes 32214979Sdes# Test explicitly-specified principals 33294464Sdesfor ktype in $PLAIN_TYPES ; do 34294464Sdes t=$(kname $ktype) 35214979Sdes for privsep in yes no ; do 36214979Sdes _prefix="${ktype} privsep $privsep" 37214979Sdes 38214979Sdes # Setup for AuthorizedPrincipalsFile 39214979Sdes rm -f $OBJ/authorized_keys_$USER 40214979Sdes ( 41214979Sdes cat $OBJ/sshd_proxy_bak 42214979Sdes echo "UsePrivilegeSeparation $privsep" 43214979Sdes echo "AuthorizedPrincipalsFile " \ 44214979Sdes "$OBJ/authorized_principals_%u" 45214979Sdes echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" 46294464Sdes echo "PubkeyAcceptedKeyTypes ${t}" 47214979Sdes ) > $OBJ/sshd_proxy 48294464Sdes ( 49294464Sdes cat $OBJ/ssh_proxy_bak 50294464Sdes echo "PubkeyAcceptedKeyTypes ${t}" 51294464Sdes ) > $OBJ/ssh_proxy 52214979Sdes 53214979Sdes # Missing authorized_principals 54214979Sdes verbose "$tid: ${_prefix} missing authorized_principals" 55214979Sdes rm -f $OBJ/authorized_principals_$USER 56214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 57214979Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 58214979Sdes if [ $? -eq 0 ]; then 59214979Sdes fail "ssh cert connect succeeded unexpectedly" 60214979Sdes fi 61214979Sdes 62214979Sdes # Empty authorized_principals 63214979Sdes verbose "$tid: ${_prefix} empty authorized_principals" 64214979Sdes echo > $OBJ/authorized_principals_$USER 65214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 66214979Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 67214979Sdes if [ $? -eq 0 ]; then 68214979Sdes fail "ssh cert connect succeeded unexpectedly" 69214979Sdes fi 70214979Sdes 71214979Sdes # Wrong authorized_principals 72214979Sdes verbose "$tid: ${_prefix} wrong authorized_principals" 73214979Sdes echo gregorsamsa > $OBJ/authorized_principals_$USER 74214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 75214979Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 76214979Sdes if [ $? -eq 0 ]; then 77214979Sdes fail "ssh cert connect succeeded unexpectedly" 78214979Sdes fi 79214979Sdes 80214979Sdes # Correct authorized_principals 81214979Sdes verbose "$tid: ${_prefix} correct authorized_principals" 82214979Sdes echo mekmitasdigoat > $OBJ/authorized_principals_$USER 83214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 84214979Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 85214979Sdes if [ $? -ne 0 ]; then 86214979Sdes fail "ssh cert connect failed" 87214979Sdes fi 88214979Sdes 89214979Sdes # authorized_principals with bad key option 90214979Sdes verbose "$tid: ${_prefix} authorized_principals bad key opt" 91214979Sdes echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER 92214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 93214979Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 94214979Sdes if [ $? -eq 0 ]; then 95214979Sdes fail "ssh cert connect succeeded unexpectedly" 96214979Sdes fi 97214979Sdes 98214979Sdes # authorized_principals with command=false 99214979Sdes verbose "$tid: ${_prefix} authorized_principals command=false" 100214979Sdes echo 'command="false" mekmitasdigoat' > \ 101214979Sdes $OBJ/authorized_principals_$USER 102214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 103214979Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 104214979Sdes if [ $? -eq 0 ]; then 105214979Sdes fail "ssh cert connect succeeded unexpectedly" 106214979Sdes fi 107214979Sdes 108214979Sdes 109214979Sdes # authorized_principals with command=true 110214979Sdes verbose "$tid: ${_prefix} authorized_principals command=true" 111214979Sdes echo 'command="true" mekmitasdigoat' > \ 112214979Sdes $OBJ/authorized_principals_$USER 113214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 114214979Sdes -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1 115214979Sdes if [ $? -ne 0 ]; then 116214979Sdes fail "ssh cert connect failed" 117214979Sdes fi 118214979Sdes 119214979Sdes # Setup for principals= key option 120214979Sdes rm -f $OBJ/authorized_principals_$USER 121214979Sdes ( 122214979Sdes cat $OBJ/sshd_proxy_bak 123214979Sdes echo "UsePrivilegeSeparation $privsep" 124294464Sdes echo "PubkeyAcceptedKeyTypes ${t}" 125214979Sdes ) > $OBJ/sshd_proxy 126294464Sdes ( 127294464Sdes cat $OBJ/ssh_proxy_bak 128294464Sdes echo "PubkeyAcceptedKeyTypes ${t}" 129294464Sdes ) > $OBJ/ssh_proxy 130214979Sdes 131214979Sdes # Wrong principals list 132214979Sdes verbose "$tid: ${_prefix} wrong principals key option" 133214979Sdes ( 134255670Sdes printf 'cert-authority,principals="gregorsamsa" ' 135214979Sdes cat $OBJ/user_ca_key.pub 136214979Sdes ) > $OBJ/authorized_keys_$USER 137214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 138214979Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 139214979Sdes if [ $? -eq 0 ]; then 140214979Sdes fail "ssh cert connect succeeded unexpectedly" 141214979Sdes fi 142214979Sdes 143214979Sdes # Correct principals list 144214979Sdes verbose "$tid: ${_prefix} correct principals key option" 145214979Sdes ( 146255670Sdes printf 'cert-authority,principals="mekmitasdigoat" ' 147214979Sdes cat $OBJ/user_ca_key.pub 148214979Sdes ) > $OBJ/authorized_keys_$USER 149214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 150214979Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 151214979Sdes if [ $? -ne 0 ]; then 152214979Sdes fail "ssh cert connect failed" 153214979Sdes fi 154214979Sdes done 155214979Sdesdone 156214979Sdes 157204861Sdesbasic_tests() { 158204861Sdes auth=$1 159204861Sdes if test "x$auth" = "xauthorized_keys" ; then 160204861Sdes # Add CA to authorized_keys 161204861Sdes ( 162255670Sdes printf 'cert-authority ' 163204861Sdes cat $OBJ/user_ca_key.pub 164204861Sdes ) > $OBJ/authorized_keys_$USER 165204861Sdes else 166204861Sdes echo > $OBJ/authorized_keys_$USER 167204861Sdes extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub" 168204861Sdes fi 169204861Sdes 170294464Sdes for ktype in $PLAIN_TYPES ; do 171294464Sdes t=$(kname $ktype) 172204861Sdes for privsep in yes no ; do 173204861Sdes _prefix="${ktype} privsep $privsep $auth" 174204861Sdes # Simple connect 175204861Sdes verbose "$tid: ${_prefix} connect" 176204861Sdes ( 177204861Sdes cat $OBJ/sshd_proxy_bak 178204861Sdes echo "UsePrivilegeSeparation $privsep" 179294464Sdes echo "PubkeyAcceptedKeyTypes ${t}" 180204861Sdes echo "$extra_sshd" 181204861Sdes ) > $OBJ/sshd_proxy 182294464Sdes ( 183294464Sdes cat $OBJ/ssh_proxy_bak 184294464Sdes echo "PubkeyAcceptedKeyTypes ${t}" 185294464Sdes ) > $OBJ/ssh_proxy 186204861Sdes 187204861Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 188204861Sdes -F $OBJ/ssh_proxy somehost true 189204861Sdes if [ $? -ne 0 ]; then 190204861Sdes fail "ssh cert connect failed" 191204861Sdes fi 192204861Sdes 193204861Sdes # Revoked keys 194204861Sdes verbose "$tid: ${_prefix} revoked key" 195204861Sdes ( 196204861Sdes cat $OBJ/sshd_proxy_bak 197204861Sdes echo "UsePrivilegeSeparation $privsep" 198248613Sdes echo "RevokedKeys $OBJ/cert_user_key_revoked" 199294464Sdes echo "PubkeyAcceptedKeyTypes ${t}" 200204861Sdes echo "$extra_sshd" 201204861Sdes ) > $OBJ/sshd_proxy 202248613Sdes cp $OBJ/cert_user_key_${ktype}.pub \ 203248613Sdes $OBJ/cert_user_key_revoked 204204861Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 205204861Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 206204861Sdes if [ $? -eq 0 ]; then 207204861Sdes fail "ssh cert connect succeeded unexpecedly" 208204861Sdes fi 209248613Sdes verbose "$tid: ${_prefix} revoked via KRL" 210248613Sdes rm $OBJ/cert_user_key_revoked 211248613Sdes ${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \ 212248613Sdes $OBJ/cert_user_key_${ktype}.pub 213248613Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 214248613Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 215248613Sdes if [ $? -eq 0 ]; then 216248613Sdes fail "ssh cert connect succeeded unexpecedly" 217248613Sdes fi 218248613Sdes verbose "$tid: ${_prefix} empty KRL" 219248613Sdes ${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked 220248613Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 221248613Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 222248613Sdes if [ $? -ne 0 ]; then 223248613Sdes fail "ssh cert connect failed" 224248613Sdes fi 225204861Sdes done 226204861Sdes 227204861Sdes # Revoked CA 228204861Sdes verbose "$tid: ${ktype} $auth revoked CA key" 229204861Sdes ( 230204861Sdes cat $OBJ/sshd_proxy_bak 231204861Sdes echo "RevokedKeys $OBJ/user_ca_key.pub" 232294464Sdes echo "PubkeyAcceptedKeyTypes ${t}" 233204861Sdes echo "$extra_sshd" 234204861Sdes ) > $OBJ/sshd_proxy 235204861Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ 236204861Sdes somehost true >/dev/null 2>&1 237204861Sdes if [ $? -eq 0 ]; then 238204861Sdes fail "ssh cert connect succeeded unexpecedly" 239204861Sdes fi 240204861Sdes done 241204861Sdes 242204861Sdes verbose "$tid: $auth CA does not authenticate" 243204861Sdes ( 244204861Sdes cat $OBJ/sshd_proxy_bak 245294464Sdes echo "PubkeyAcceptedKeyTypes ${t}" 246204861Sdes echo "$extra_sshd" 247204861Sdes ) > $OBJ/sshd_proxy 248204861Sdes verbose "$tid: ensure CA key does not authenticate user" 249204861Sdes ${SSH} -2i $OBJ/user_ca_key \ 250204861Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 251204861Sdes if [ $? -eq 0 ]; then 252204861Sdes fail "ssh cert connect with CA key succeeded unexpectedly" 253204861Sdes fi 254204861Sdes} 255204861Sdes 256204861Sdesbasic_tests authorized_keys 257204861Sdesbasic_tests TrustedUserCAKeys 258204861Sdes 259204861Sdestest_one() { 260204861Sdes ident=$1 261204861Sdes result=$2 262204861Sdes sign_opts=$3 263204861Sdes auth_choice=$4 264214979Sdes auth_opt=$5 265204861Sdes 266204861Sdes if test "x$auth_choice" = "x" ; then 267204861Sdes auth_choice="authorized_keys TrustedUserCAKeys" 268204861Sdes fi 269204861Sdes 270204861Sdes for auth in $auth_choice ; do 271294464Sdes for ktype in rsa ed25519 ; do 272214979Sdes cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy 273214979Sdes if test "x$auth" = "xauthorized_keys" ; then 274214979Sdes # Add CA to authorized_keys 275214979Sdes ( 276255670Sdes printf "cert-authority${auth_opt} " 277214979Sdes cat $OBJ/user_ca_key.pub 278214979Sdes ) > $OBJ/authorized_keys_$USER 279214979Sdes else 280214979Sdes echo > $OBJ/authorized_keys_$USER 281214979Sdes echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \ 282214979Sdes >> $OBJ/sshd_proxy 283294464Sdes echo "PubkeyAcceptedKeyTypes ${t}*" \ 284294464Sdes >> $OBJ/sshd_proxy 285214979Sdes if test "x$auth_opt" != "x" ; then 286214979Sdes echo $auth_opt >> $OBJ/sshd_proxy 287214979Sdes fi 288214979Sdes fi 289214979Sdes 290214979Sdes verbose "$tid: $ident auth $auth expect $result $ktype" 291214979Sdes ${SSHKEYGEN} -q -s $OBJ/user_ca_key \ 292214979Sdes -I "regress user key for $USER" \ 293294464Sdes $sign_opts $OBJ/cert_user_key_${ktype} || 294214979Sdes fail "couldn't sign cert_user_key_${ktype}" 295204861Sdes 296214979Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} \ 297214979Sdes -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 298214979Sdes rc=$? 299214979Sdes if [ "x$result" = "xsuccess" ] ; then 300214979Sdes if [ $rc -ne 0 ]; then 301214979Sdes fail "$ident failed unexpectedly" 302214979Sdes fi 303214979Sdes else 304214979Sdes if [ $rc -eq 0 ]; then 305214979Sdes fail "$ident succeeded unexpectedly" 306214979Sdes fi 307204861Sdes fi 308214979Sdes done 309204861Sdes done 310204861Sdes} 311204861Sdes 312204861Sdestest_one "correct principal" success "-n ${USER}" 313204861Sdestest_one "host-certificate" failure "-n ${USER} -h" 314204861Sdestest_one "wrong principals" failure "-n foo" 315204861Sdestest_one "cert not yet valid" failure "-n ${USER} -V20200101:20300101" 316204861Sdestest_one "cert expired" failure "-n ${USER} -V19800101:19900101" 317204861Sdestest_one "cert valid interval" success "-n ${USER} -V-1w:+2w" 318204861Sdestest_one "wrong source-address" failure "-n ${USER} -Osource-address=10.0.0.0/8" 319204861Sdestest_one "force-command" failure "-n ${USER} -Oforce-command=false" 320204861Sdes 321204861Sdes# Behaviour is different here: TrustedUserCAKeys doesn't allow empty principals 322204861Sdestest_one "empty principals" success "" authorized_keys 323204861Sdestest_one "empty principals" failure "" TrustedUserCAKeys 324204861Sdes 325214979Sdes# Check explicitly-specified principals: an empty principals list in the cert 326214979Sdes# should always be refused. 327214979Sdes 328214979Sdes# AuthorizedPrincipalsFile 329214979Sdesrm -f $OBJ/authorized_keys_$USER 330214979Sdesecho mekmitasdigoat > $OBJ/authorized_principals_$USER 331214979Sdestest_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \ 332214979Sdes TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u" 333214979Sdestest_one "AuthorizedPrincipalsFile no principals" failure "" \ 334214979Sdes TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u" 335214979Sdes 336214979Sdes# principals= key option 337214979Sdesrm -f $OBJ/authorized_principals_$USER 338214979Sdestest_one "principals key option principals" success "-n mekmitasdigoat" \ 339214979Sdes authorized_keys ',principals="mekmitasdigoat"' 340214979Sdestest_one "principals key option no principals" failure "" \ 341214979Sdes authorized_keys ',principals="mekmitasdigoat"' 342214979Sdes 343204861Sdes# Wrong certificate 344214979Sdescat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy 345294464Sdesfor ktype in $PLAIN_TYPES ; do 346294464Sdes t=$(kname $ktype) 347204861Sdes # Self-sign 348294464Sdes ${SSHKEYGEN} -q -s $OBJ/cert_user_key_${ktype} -I \ 349204861Sdes "regress user key for $USER" \ 350204861Sdes -n $USER $OBJ/cert_user_key_${ktype} || 351204861Sdes fail "couldn't sign cert_user_key_${ktype}" 352204861Sdes verbose "$tid: user ${ktype} connect wrong cert" 353204861Sdes ${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ 354204861Sdes somehost true >/dev/null 2>&1 355204861Sdes if [ $? -eq 0 ]; then 356204861Sdes fail "ssh cert connect $ident succeeded unexpectedly" 357204861Sdes fi 358204861Sdesdone 359204861Sdes 360204861Sdesrm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key* 361214979Sdesrm -f $OBJ/authorized_principals_$USER 362204861Sdes 363