xref: /freebsd/crypto/openssh/regress/gss-auth.sh (revision 2574974648c68c738aec3ff96644d888d7913a37)
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