Skip to content

Commit 58d2020

Browse files
committed
Add a GSSAPI authentication test
1 parent 91c4d42 commit 58d2020

File tree

3 files changed

+200
-3
lines changed

3 files changed

+200
-3
lines changed

.github/setup_ci.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ for TARGET in $TARGETS; do
102102
PACKAGES="$PACKAGES $compiler"
103103
;;
104104
krb5)
105-
PACKAGES="$PACKAGES libkrb5-dev"
105+
PACKAGES="$PACKAGES libkrb5-dev libnss-wrapper krb5-admin-server"
106106
;;
107107
heimdal)
108-
PACKAGES="$PACKAGES heimdal-dev"
108+
PACKAGES="$PACKAGES heimdal-dev libnss-wrapper krb5-admin-server"
109109
;;
110110
libedit)
111111
case "$PACKAGER" in

regress/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ LTESTS= connect \
117117
penalty-expire \
118118
connect-bigconf \
119119
ssh-pkcs11 \
120-
ssh-tty
120+
ssh-tty \
121+
gss-auth
121122

122123
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
123124
INTEROP_TESTS+= dropbear-ciphers dropbear-kex dropbear-server

regress/gss-auth.sh

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
tid="GSSAPI Authentication"
2+
3+
# Skip the test if GSSAPI support is not configured
4+
if ! grep -E '^#define GSSAPI' "$BUILDDIR/config.h" >/dev/null 2>&1; then
5+
skip "GSSAPI not enabled"
6+
fi
7+
8+
# We test with MIT Kerberos KDC, skip if not installed
9+
if ! which krb5kdc >/dev/null 2>&1; then
10+
skip "MIT Kerberos KDC not installed"
11+
fi
12+
13+
# The test needs nss_wrapper to emulate gethostname() and /etc/hosts,
14+
# we skip if the shared library is not installed
15+
nss_wrapper="libnss_wrapper.so"
16+
if ! ldconfig -p | grep "$nss_wrapper" >/dev/null 2>&1; then
17+
skip "$nss_wrapper not installed"
18+
fi
19+
20+
# Set up the username of the SSH client
21+
client="$LOGNAME"
22+
if [ "x$client" = "x" ]; then
23+
client="$(whoami)"
24+
fi
25+
26+
# Set up SSHD and KDC hostnames and resolve both to localhost
27+
sshd_hostname="sshd.example.org"
28+
bad_hostname="bad.example.org"
29+
kdc_hostname="kdc.example.org"
30+
kdc_port=2088
31+
hosts="$OBJ/hosts"
32+
echo "127.0.0.1 $sshd_hostname $kdc_hostname" > "$hosts"
33+
34+
# Set up a directory to store Kerberos data
35+
# (configuration, ticket cache,...)
36+
gssdir="$OBJ/gss"
37+
mkdir -p "$gssdir"
38+
export KRB5CCNAME="$gssdir/cc"
39+
export KRB5_CONFIG="$gssdir/krb5.conf"
40+
export KRB5_KDC_PROFILE="$gssdir/kdc.conf"
41+
export KRB5_KTNAME="$gssdir/ssh.keytab"
42+
export KRB5RCACHETYPE="none"
43+
kdc_pidfile="$gssdir/pid"
44+
45+
# Configure Kerberos
46+
cat<<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
57+
EOF
58+
59+
cat<<EOF > "$KRB5_CONFIG"
60+
[libdefaults]
61+
default_realm = EXAMPLE.ORG
62+
[realms]
63+
EXAMPLE.ORG = {
64+
kdc = $kdc_hostname:$kdc_port
65+
}
66+
EOF
67+
68+
# Back up the default sshd_config
69+
cp "$OBJ/sshd_config" "$OBJ/sshd_config.orig"
70+
71+
setup_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"
78+
PubkeyAuthentication No
79+
PasswordAuthentication No
80+
GSSAPIAuthentication Yes
81+
EOF
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+
100+
teardown_sshd() {
101+
TEST_SSH_SSHD_ENV="$test_ssh_sshd_env_backup"
102+
stop_sshd
103+
}
104+
105+
setup_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+
116+
teardown_kdc() {
117+
kill "$(cat "$kdc_pidfile")"
118+
kdestroy
119+
rm -f "$KRB5_KTNAME" "$kdc_pidfile"
120+
kdb5_util destroy -f
121+
}
122+
123+
setup_nss_emulation() {
124+
export LD_PRELOAD="$nss_wrapper"
125+
export NSS_WRAPPER_HOSTS="$hosts"
126+
}
127+
128+
teardown_nss_emulation() {
129+
unset LD_PRELOAD
130+
unset NSS_WRAPPER_HOSTS
131+
}
132+
133+
setup_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+
142+
setup_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+
152+
test_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
178+
test_gss_auth $sshd_hostname $sshd_hostname true true true 0 \
179+
|| fail "valid authentication attempt failed"
180+
test_gss_auth $sshd_hostname $sshd_hostname false true true 255 \
181+
|| fail "authentication succeeded without a keytab entry for the host"
182+
test_gss_auth $sshd_hostname $sshd_hostname true false true 255 \
183+
|| fail "authentication succeeded without a ticket-granting ticket"
184+
test_gss_auth $bad_hostname $sshd_hostname true true true 255 \
185+
|| fail "authentication succeeded with a hostname/principal mismatch on server side"
186+
test_gss_auth $bad_hostname $sshd_hostname true true false 0 \
187+
|| fail "valid authentication without strict acceptor check failed"
188+
test_gss_auth $bad_hostname $bad_hostname true true true 255 \
189+
|| fail "authentication succeeded with a hostname/principal mismatch on client side"
190+
191+
unset KRB5CCNAME
192+
unset KRB5_CONFIG
193+
unset KRB5_KDC_PROFILE
194+
unset KRB5_KTNAME
195+
unset KRB5RCACHETYPE
196+
rm -r "$gssdir"

0 commit comments

Comments
 (0)