Files
heimdal/tests/kdc/check-mit-kdc.in
Nicolas Williams b9773f7839 tests: Add another MIT Kerberos interop test
We do a small amount of MIT interop testing in tests/kdc/check-fast.in,
which tests some MIT clients against Heimdal KDCs.  This commit adds
more testing via tests/kdc/check-mit-kdc.in, wherein we set up and run
an MIT Kerberos realm and KDCs and test Heimdal clients against it.
2026-01-18 19:06:16 -06:00

409 lines
12 KiB
Bash

#!/bin/sh
#
# Copyright (c) 2006 - 2024 Kungliga Tekniska Högskolan
# (Royal Institute of Technology, Stockholm, Sweden).
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# Test Heimdal clients against MIT Kerberos KDC
#
top_builddir="@top_builddir@"
env_setup="@env_setup@"
objdir="@objdir@"
. ${env_setup}
# Skip if MIT Kerberos is not available
if [ -z "$MITKRB5" ] || [ ! -d "$MITKRB5" ]; then
echo "MIT Kerberos not available, skipping"
exit 77
fi
# Check for required MIT binaries
for prog in kdb5_util krb5kdc kadmin.local; do
if [ ! -x "${MITKRB5}/sbin/${prog}" ] && [ ! -x "${MITKRB5}/bin/${prog}" ]; then
echo "MIT ${prog} not found, skipping"
exit 77
fi
done
# Check for PKINIT support
rsa=yes
pkinit=no
if ${hxtool} info | grep 'rsa: hx509 null RSA' > /dev/null ; then
rsa=no
fi
if ${hxtool} info | grep 'rand: not available' > /dev/null ; then
rsa=no
fi
if ${kinit} --help 2>&1 | grep "CA certificates" > /dev/null; then
pkinit=yes
fi
testfailed="echo test failed; cat messages.log; exit 1"
R=MIT-TEST.H5L.SE
port=@port@
admport=@admport@
mitdir="${objdir}/mit-kdc"
cache="FILE:${objdir}/mit-cache.krb5"
keytab="${objdir}/mit-server.keytab"
keyfile="${hx509_data}/key.der"
keyfile2="${hx509_data}/key2.der"
kinit="${kinit} -c $cache ${afs_no_afslog}"
klist="${klist} -c $cache"
kgetcred="${kgetcred} -c $cache"
kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
server=host/localhost
KRB5_CONFIG="${objdir}/krb5-mit-kdc.conf"
export KRB5_CONFIG
# Clean up from previous runs
rm -rf "${mitdir}"
rm -f "${objdir}/krb5-mit-kdc.conf"
rm -f "${objdir}/mit-kdc.conf"
rm -f "${cache#FILE:}"
rm -f "${keytab}"
rm -f "${objdir}/mit-ca.crt"
rm -f "${objdir}/mit-kdc.crt"
rm -f "${objdir}/mit-user.crt"
rm -f "${objdir}/mit-user.pem"
rm -f "${objdir}/mit-kdc-key.pem"
rm -f req-mit-kdc.der req-mit-user.der
mkdir -p "${mitdir}"
> messages.log
ec=0
kdcpid=
cleanup() {
if [ -n "$kdcpid" ]; then
echo "Killing MIT KDC (pid $kdcpid)"
kill $kdcpid 2>/dev/null
wait $kdcpid 2>/dev/null
fi
trap '' EXIT INT TERM
# cat messages.log
exit $ec
}
trap cleanup EXIT INT TERM
#
# Set up certificates for PKINIT
#
if [ "$pkinit" = yes ] && [ "$rsa" = yes ]; then
echo "Setting up PKINIT certificates"
${hxtool} request-create \
--subject="CN=MIT KDC,DC=mit-test,DC=h5l,DC=se" \
--key=FILE:${keyfile2} \
req-mit-kdc.der || exit 1
${hxtool} request-create \
--subject="CN=foo,DC=mit-test,DC=h5l,DC=se" \
--key=FILE:${keyfile2} \
req-mit-user.der || exit 1
echo "Issuing self-signed CA cert"
${hxtool} issue-certificate \
--self-signed \
--issue-ca \
--ca-private-key=FILE:${keyfile} \
--subject="CN=MIT Test CA,DC=mit-test,DC=h5l,DC=se" \
--certificate="PEM-FILE:${objdir}/mit-ca.crt" || exit 1
echo "Issuing MIT KDC certificate"
${hxtool} issue-certificate \
--ca-certificate=PEM-FILE:${objdir}/mit-ca.crt,${keyfile} \
--type="pkinit-kdc" \
--pk-init-principal="krbtgt/${R}@${R}" \
--req="PKCS10:req-mit-kdc.der" \
--certificate="PEM-FILE:${objdir}/mit-kdc.crt" || exit 1
echo "Issuing user certificate"
${hxtool} issue-certificate \
--ca-certificate=PEM-FILE:${objdir}/mit-ca.crt,${keyfile} \
--type="pkinit-client" \
--pk-init-principal="foo@${R}" \
--req="PKCS10:req-mit-user.der" \
--certificate="PEM-FILE:${objdir}/mit-user.crt" || exit 1
# Create combined PEM file for user PKINIT
cat ${objdir}/mit-user.crt > ${objdir}/mit-user.pem
openssl rsa -in ${keyfile2} -outform PEM >> ${objdir}/mit-user.pem 2>/dev/null || \
${hxtool} print --content FILE:${keyfile2} >> ${objdir}/mit-user.pem
# Create KDC key PEM file for MIT PKINIT
openssl rsa -in ${keyfile2} -outform PEM > ${objdir}/mit-kdc-key.pem 2>/dev/null || \
${hxtool} print --content FILE:${keyfile2} > ${objdir}/mit-kdc-key.pem
pkinit_configured=yes
else
pkinit_configured=no
fi
#
# Create krb5.conf for Heimdal clients (and MIT tools)
#
cat > ${objdir}/krb5-mit-kdc.conf <<EOF
[libdefaults]
default_realm = ${R}
dns_lookup_realm = false
dns_lookup_kdc = false
rdns = false
ticket_lifetime = 24h
forwardable = true
[realms]
${R} = {
kdc = localhost:${port}
admin_server = localhost:${admport}
EOF
if [ "$pkinit_configured" = yes ]; then
cat >> ${objdir}/krb5-mit-kdc.conf <<EOF
pkinit_anchors = FILE:${objdir}/mit-ca.crt
}
[appdefaults]
pkinit_anchors = FILE:${objdir}/mit-ca.crt
EOF
else
cat >> ${objdir}/krb5-mit-kdc.conf <<EOF
}
EOF
fi
cat >> ${objdir}/krb5-mit-kdc.conf <<EOF
[domain_realm]
.mit-test.h5l.se = ${R}
mit-test.h5l.se = ${R}
[logging]
kdc = FILE:${objdir}/messages.log
admin_server = FILE:${objdir}/messages.log
default = FILE:${objdir}/messages.log
EOF
#
# Create MIT kdc.conf
#
cat > ${objdir}/mit-kdc.conf <<EOF
[kdcdefaults]
kdc_ports = ${port}
kdc_tcp_ports = ${port}
[realms]
${R} = {
database_name = ${mitdir}/principal
key_stash_file = ${mitdir}/.k5.${R}
acl_file = ${mitdir}/kadm5.acl
max_life = 1d 0h 0m 0s
max_renewable_life = 7d 0h 0m 0s
supported_enctypes = aes256-cts:normal aes128-cts:normal
EOF
if [ "$pkinit_configured" = yes ]; then
cat >> ${objdir}/mit-kdc.conf <<EOF
pkinit_identity = FILE:${objdir}/mit-kdc.crt,${objdir}/mit-kdc-key.pem
pkinit_anchors = FILE:${objdir}/mit-ca.crt
EOF
fi
cat >> ${objdir}/mit-kdc.conf <<EOF
}
[logging]
kdc = FILE:${objdir}/messages.log
admin_server = FILE:${objdir}/messages.log
default = FILE:${objdir}/messages.log
EOF
#
# Create MIT KDC database
#
echo "Creating MIT KDC database"
KDB5_UTIL="${MITKRB5}/sbin/kdb5_util"
if [ ! -x "$KDB5_UTIL" ]; then
KDB5_UTIL="${MITKRB5}/bin/kdb5_util"
fi
KADMIN_LOCAL="${MITKRB5}/sbin/kadmin.local"
if [ ! -x "$KADMIN_LOCAL" ]; then
KADMIN_LOCAL="${MITKRB5}/bin/kadmin.local"
fi
MIT_KDC="${MITKRB5}/sbin/krb5kdc"
if [ ! -x "$MIT_KDC" ]; then
MIT_KDC="${MITKRB5}/bin/krb5kdc"
fi
KRB5_KDC_PROFILE="${objdir}/mit-kdc.conf"
export KRB5_KDC_PROFILE
# Create kadm5.acl file (required by MIT)
cat > ${mitdir}/kadm5.acl <<EOF
*/admin@${R} *
EOF
${KDB5_UTIL} -r ${R} create -s -P masterkey || { echo "Failed to create MIT database"; exit 1; }
echo "Adding principals"
${KADMIN_LOCAL} -r ${R} -q "addprinc -pw foo foo@${R}" || exit 1
${KADMIN_LOCAL} -r ${R} -q "addprinc -pw bar bar@${R}" || exit 1
${KADMIN_LOCAL} -r ${R} -q "addprinc -randkey ${server}@${R}" || exit 1
${KADMIN_LOCAL} -r ${R} -q "ktadd -k ${keytab} ${server}@${R}" || exit 1
#
# Start MIT KDC
#
echo "Starting MIT KDC"
${MIT_KDC} -r ${R} -n -P ${objdir}/mit-kdc.pid &
kdcpid=$!
sleep 2
# Verify KDC is running
if ! kill -0 $kdcpid 2>/dev/null; then
echo "MIT KDC failed to start"
cat messages.log
exit 1
fi
echo "MIT KDC running with PID $kdcpid"
#
# Test 1: Password authentication with Heimdal kinit
#
echo ""
echo "=== Test 1: Heimdal kinit with password against MIT KDC ==="
echo foo > ${objdir}/foopassword
${kinit} --password-file=${objdir}/foopassword foo@${R} || \
{ ec=1; eval "${testfailed}"; }
echo "Verifying ticket"
${klist} || { ec=1; eval "${testfailed}"; }
${klist} | grep "krbtgt/${R}@${R}" > /dev/null || { ec=1; echo "No TGT found"; eval "${testfailed}"; }
echo "Getting service ticket"
${kgetcred} ${server}@${R} || { ec=1; eval "${testfailed}"; }
${klist} | grep "${server}@${R}" > /dev/null || { ec=1; echo "No service ticket found"; eval "${testfailed}"; }
${kdestroy}
echo "Test 1 PASSED"
#
# Test 2: PKINIT authentication with Heimdal kinit
#
echo "=== Test 2: Heimdal kinit with PKINIT against MIT KDC (negotiate ECDH curve) ==="
# Note that MIT does not support X25519, but Heimdal prefers X225519, but we
# should negotiate to P-256:
${kinit} -C FILE:${objdir}/mit-user.pem foo@${R} 2>/dev/null || { ec=1; eval "${testfailed}"; }
${klist} || { ec=1; eval "${testfailed}"; }
${klist} | grep "krbtgt/${R}@${R}" > /dev/null || { ec=1; echo "No TGT found"; eval "${testfailed}"; }
${kgetcred} ${server}@${R} || { ec=1; eval "${testfailed}"; }
${kdestroy}
echo "Test 2 PASSED"
#
# Test 3: PKINIT authentication with Heimdal kinit with a preference for an EC
# DH curve (P-256)
#
echo "=== Test 3: Heimdal kinit with PKINIT against MIT KDC (P-256) ==="
${kinit} --key-agreement=P-256 -C FILE:${objdir}/mit-user.pem foo@${R} 2>/dev/null || { ec=1; eval "${testfailed}"; }
${klist} || { ec=1; eval "${testfailed}"; }
${klist} | grep "krbtgt/${R}@${R}" > /dev/null || { ec=1; echo "No TGT found"; eval "${testfailed}"; }
${kgetcred} ${server}@${R} || { ec=1; eval "${testfailed}"; }
${kdestroy}
echo "Test 3 PASSED"
#
# Test 4: PKINIT authentication with Heimdal kinit with a preference for an EC
# DH curve (P-521)
#
echo "=== Test 4: Heimdal kinit with PKINIT against MIT KDC (P-521) ==="
${kinit} --key-agreement=P-521 -C FILE:${objdir}/mit-user.pem foo@${R} 2>/dev/null || { ec=1; eval "${testfailed}"; }
${klist} || { ec=1; eval "${testfailed}"; }
${klist} | grep "krbtgt/${R}@${R}" > /dev/null || { ec=1; echo "No TGT found"; eval "${testfailed}"; }
${kgetcred} ${server}@${R} || { ec=1; eval "${testfailed}"; }
${kdestroy}
echo "Test 4 PASSED"
#
# Test 5: PKINIT authentication with Heimdal kinit with a preference for an EC
# DH curve (P-521)
#
echo "=== Test 5: Heimdal kinit with PKINIT against MIT KDC (modp 2048) ==="
${kinit} --key-agreement=modp_2048 -C FILE:${objdir}/mit-user.pem foo@${R} 2>/dev/null || { ec=1; eval "${testfailed}"; }
${klist} || { ec=1; eval "${testfailed}"; }
${klist} | grep "krbtgt/${R}@${R}" > /dev/null || { ec=1; echo "No TGT found"; eval "${testfailed}"; }
${kgetcred} ${server}@${R} || { ec=1; eval "${testfailed}"; }
${kdestroy}
echo "Test 5 PASSED"
#
# Test 6: FAST with Heimdal kinit (if MIT KDC supports it)
#
echo ""
echo "=== Test 6: Testing with FAST armor ==="
# Get armor ticket
${kinit} --password-file=${objdir}/foopassword foo@${R} || \
{ ec=1; eval "${testfailed}"; }
acache="FILE:${objdir}/mit-acache.krb5"
${kinit} -c ${acache} --password-file=${objdir}/foopassword bar@${R} --fast-armor-cache=$cache || \
{ echo "FAST kinit failed (may be expected if MIT KDC does not support it)"; }
rm -f "${acache#FILE:}"
${kdestroy}
echo "Test 6 completed"
#
# Done
#
echo ""
echo "All tests passed!"
ec=0
exit 0