1tid="GSSAPI Authentication" 2 3# Skip the test if GSSAPI support is not configured 4if ! grep -E '^#define GSSAPI' "$BUILDDIR/config.h" >/dev/null 2>&1; then 5 skip "GSSAPI not enabled" 6fi 7 8# We test with MIT Kerberos KDC, skip if not installed 9if ! which krb5kdc >/dev/null 2>&1; then 10 skip "MIT Kerberos KDC not installed" 11fi 12 13# The test needs nss_wrapper to emulate gethostname() and /etc/hosts, 14# we skip if the shared library is not installed 15nss_wrapper="libnss_wrapper.so" 16if ! ldconfig -p | grep "$nss_wrapper" >/dev/null 2>&1; then 17 skip "$nss_wrapper not installed" 18fi 19 20# Set up the username of the SSH client 21client="$LOGNAME" 22if [ "x$client" = "x" ]; then 23 client="$(whoami)" 24fi 25 26# Set up SSHD and KDC hostnames and resolve both to localhost 27sshd_hostname="sshd.example.org" 28bad_hostname="bad.example.org" 29kdc_hostname="kdc.example.org" 30kdc_port=2088 31hosts="$OBJ/hosts" 32echo "127.0.0.1 $sshd_hostname $kdc_hostname" > "$hosts" 33 34# Set up a directory to store Kerberos data 35# (configuration, ticket cache,...) 36gssdir="$OBJ/gss" 37mkdir -p "$gssdir" 38export KRB5CCNAME="$gssdir/cc" 39export KRB5_CONFIG="$gssdir/krb5.conf" 40export KRB5_KDC_PROFILE="$gssdir/kdc.conf" 41export KRB5_KTNAME="$gssdir/ssh.keytab" 42export KRB5RCACHETYPE="none" 43kdc_pidfile="$gssdir/pid" 44 45# Configure Kerberos 46cat<<EOF > "$KRB5_KDC_PROFILE" 47[realms] 48 EXAMPLE.ORG = { 49 database_name = $gssdir/principal 50 key_stash_file = $gssdir/stash 51 kdc_listen = $kdc_hostname:$kdc_port 52 kdc_tcp_listen = $kdc_hostname:$kdc_port 53 } 54[logging] 55 kdc = FILE:$gssdir/kdc.log 56 debug = true 57EOF 58 59cat<<EOF > "$KRB5_CONFIG" 60[libdefaults] 61 default_realm = EXAMPLE.ORG 62[realms] 63 EXAMPLE.ORG = { 64 kdc = $kdc_hostname:$kdc_port 65 } 66EOF 67 68# Back up the default sshd_config 69cp "$OBJ/sshd_config" "$OBJ/sshd_config.orig" 70 71setup_sshd() { 72 mock_hostname="$1" 73 strict_acceptor="$2" 74 75 cp "$OBJ/sshd_config.orig" "$OBJ/sshd_config" 76 77 cat<<EOF >> "$OBJ/sshd_config" 78PubkeyAuthentication No 79PasswordAuthentication No 80GSSAPIAuthentication Yes 81EOF 82 83 if ! $strict_acceptor; then 84 echo "GSSAPIStrictAcceptorCheck No" >> "$OBJ/sshd_config" 85 fi 86 87 test_ssh_sshd_env_backup="$TEST_SSH_SSHD_ENV" 88 TEST_SSH_SSHD_ENV="$TEST_SSH_SSHD_ENV \ 89 LD_PRELOAD=$nss_wrapper \ 90 NSS_WRAPPER_HOSTS=$hosts \ 91 NSS_WRAPPER_HOSTNAME=$mock_hostname \ 92 KRB5_CONFIG=$KRB5_CONFIG \ 93 KRB5_KDC_PROFILE=$KRB5_KDC_PROFILE \ 94 KRB5CCNAME=$KRB5CCNAME \ 95 KRB5_KTNAME=$KRB5_KTNAME \ 96 KRB5RCACHETYPE=$KRB5RCACHETYPE" 97 start_sshd 98} 99 100teardown_sshd() { 101 TEST_SSH_SSHD_ENV="$test_ssh_sshd_env_backup" 102 stop_sshd 103} 104 105setup_kdc() { 106 kdb5_util create -P "foo" -s 107 krb5kdc -w 1 -P "$kdc_pidfile" 108 i=0; 109 while [ ! -f "$kdc_pidfile" -a $i -lt 10 ]; do 110 i=$((i + 1)) 111 sleep 1 112 done 113 test -f "$kdc_pidfile" || fatal "KDC failed to start" 114} 115 116teardown_kdc() { 117 kill "$(cat "$kdc_pidfile")" 118 kdestroy 119 rm -f "$KRB5_KTNAME" "$kdc_pidfile" 120 kdb5_util destroy -f 121} 122 123setup_nss_emulation() { 124 export LD_PRELOAD="$nss_wrapper" 125 export NSS_WRAPPER_HOSTS="$hosts" 126} 127 128teardown_nss_emulation() { 129 unset LD_PRELOAD 130 unset NSS_WRAPPER_HOSTS 131} 132 133setup_krb_principal_with_key() { 134 name="$1" 135 add_to_keytab="$2" 136 kadmin.local add_principal -randkey "$name" 137 if $add_to_keytab; then 138 kadmin.local ktadd "$name" 139 fi 140} 141 142setup_krb_principal_with_pw() { 143 name="$1" 144 password="$2" 145 authenticate="$3" 146 kadmin.local add_principal -pw "$password" "$name" 147 if $authenticate; then 148 echo "$password" | kinit "$name" 149 fi 150} 151 152test_gss_auth() { 153 sshd_mock_hostname="$1" # the name that gethostname() will return within sshd 154 sshd_principal="$2" # the hostname for which a Kerberos principal will be created 155 auth_sshd="$3" # whether sshd will be authenticated via a keytab 156 auth_client="$4" # whether the client will be authenticated via kinit 157 strict_acceptor="$5" # whether to be strict about the identity of the sshd server 158 expect="$6" # the expected return value of the sshd command 159 160 setup_sshd "$sshd_mock_hostname" "$strict_acceptor" 161 setup_nss_emulation 162 setup_kdc 163 164 setup_krb_principal_with_key "host/$sshd_principal" "$auth_sshd" 165 setup_krb_principal_with_pw "$client" "foo" "$auth_client" 166 167 ${SSH} -F "$OBJ/ssh_config" -o "GSSAPIAuthentication Yes" "$client@$sshd_hostname" true 168 status=$? 169 170 teardown_kdc 171 teardown_nss_emulation 172 teardown_sshd 173 174 [ $status -eq $expect ] 175} 176 177# sshd_mock_hostname sshd_principal auth_sshd auth_client strict_acceptor expect 178test_gss_auth $sshd_hostname $sshd_hostname true true true 0 \ 179 || fail "valid authentication attempt failed" 180test_gss_auth $sshd_hostname $sshd_hostname false true true 255 \ 181 || fail "authentication succeeded without a keytab entry for the host" 182test_gss_auth $sshd_hostname $sshd_hostname true false true 255 \ 183 || fail "authentication succeeded without a ticket-granting ticket" 184test_gss_auth $bad_hostname $sshd_hostname true true true 255 \ 185 || fail "authentication succeeded with a hostname/principal mismatch on server side" 186test_gss_auth $bad_hostname $sshd_hostname true true false 0 \ 187 || fail "valid authentication without strict acceptor check failed" 188test_gss_auth $bad_hostname $bad_hostname true true true 255 \ 189 || fail "authentication succeeded with a hostname/principal mismatch on client side" 190 191unset KRB5CCNAME 192unset KRB5_CONFIG 193unset KRB5_KDC_PROFILE 194unset KRB5_KTNAME 195unset KRB5RCACHETYPE 196rm -r "$gssdir" 197