kdc: Add param to derive max_life from client cert

This adds a KDC configuration parameter that can be used to indicate
that a PKINIT client's certificate's notAfter overrides the client
principal's HDB entry's max_life.  This parameter is a relative time
parameter, and it enables this only if set to a non-zero value (defaults
to zero).  The value of this parameter caps the max_life inferred from
the certificate.
This commit is contained in:
Nicolas Williams
2021-03-23 12:07:41 -05:00
parent dfdc6c3a06
commit 8e7c7209e8
7 changed files with 82 additions and 2 deletions

View File

@@ -53,6 +53,7 @@ restport = 49192
restport2 = 49193
ipropport = 49194
ipropport2 = 49195
pkinit_ticket_max_life_from_cert = 0
if HAVE_DLOPEN
do_dlopen = -e 's,[@]DLOPEN[@],true,g'
@@ -76,6 +77,7 @@ do_subst = $(heim_verbose)sed $(do_dlopen) \
-e 's,[@]objdir[@],$(top_builddir)/tests/kdc,g' \
-e 's,[@]top_builddir[@],$(top_builddir),g' \
-e 's,[@]db_type[@],$(db_type),g' \
-e 's,[@]max_life_from_cert[@],$(pkinit_ticket_max_life_from_cert),g' \
-e 's,[@]ENABLE_AFS_STRING_TO_KEY[@],$(ENABLE_AFS_STRING_TO_KEY),' \
-e 's,[@]EGREP[@],$(EGREP),g'
@@ -282,6 +284,12 @@ krb5-pkinit.conf: krb5-pkinit.conf.in Makefile
$(do_subst) -e 's,[@]w2k[@],no,g' < $(srcdir)/krb5-pkinit.conf.in > krb5-pkinit.conf.tmp && \
mv krb5-pkinit.conf.tmp krb5-pkinit.conf
krb5-pkinit2.conf : pkinit_ticket_max_life_from_cert = 30d
krb5-pkinit2.conf: krb5-pkinit.conf.in Makefile
$(do_subst) -e 's,[@]w2k[@],no,g' < $(srcdir)/krb5-pkinit.conf.in > krb5-pkinit2.conf.tmp && \
mv krb5-pkinit2.conf.tmp krb5-pkinit2.conf
krb5-bx509.conf: krb5-bx509.conf.in Makefile
$(do_subst) -e 's,[@]w2k[@],no,g' < $(srcdir)/krb5-bx509.conf.in > krb5-bx509.conf.tmp && \
mv krb5-bx509.conf.tmp krb5-bx509.conf

View File

@@ -55,6 +55,8 @@ keyfile="${hx509_data}/key.der"
keyfile2="${hx509_data}/key2.der"
kinit="${kinit} -c $cache ${afs_no_afslog}"
klistjson="${klist} --json -c $cache"
klistplain="${klist} -c $cache"
klist="${klist} --hidden -v -c $cache"
kgetcred="${kgetcred} -c $cache"
kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
@@ -95,6 +97,7 @@ ${kadmin} \
--realm-max-renewable-life=1month \
${R} || exit 1
${kadmin} modify --max-ticket-life=5d krbtgt/${R}@${R} || exit 1
${kadmin} add -p foo --use-defaults foo@${R} || exit 1
${kadmin} add -p bar --use-defaults bar@${R} || exit 1
${kadmin} add -p baz --use-defaults baz@${R} || exit 1
@@ -150,6 +153,7 @@ ${hxtool} issue-certificate \
--type="pkinit-client" \
--pk-init-principal="bar@TEST.H5L.SE" \
--req="PKCS10:req-pkinit.der" \
--lifetime=7d \
--certificate="FILE:pkinit.crt" || exit 1
echo "issue user 2 certificate (no san)"
@@ -198,6 +202,27 @@ ${kinit} -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \
{ ec=1 ; eval "${testfailed}"; }
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
${klist}
${kdestroy}
echo "Restarting kdc (${kdcpid}) for longer max_life test"
sh ${leaks_kill} kdc $kdcpid || ec=1
KRB5_CONFIG="${objdir}/krb5-pkinit2.conf"
${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
kdcpid=`getpid kdc`
echo "Trying pk-init (principal in cert; longer max_life)"; > messages.log
base="${objdir}"
${kinit} --lifetime=5d -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \
{ ec=1 ; eval "${testfailed}"; }
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
${klist}
if jq --version >/dev/null 2>&1 && jq -ne true >/dev/null 2>&1; then
${klistjson} |
jq -e '(((.tickets[0].Expires|
strptime("%b %d %H:%M:%S %Y")|mktime) - now) / 86400) |
(floor < 4)' >/dev/null &&
{ ec=1 ; eval "${testfailed}"; }
fi
echo "Check kx509 certificate acquisition"
${kx509} -s || { ec=1 ; eval "${testfailed}"; }

View File

@@ -19,6 +19,7 @@
pkinit_identity = FILE:@objdir@/kdc.crt,@srcdir@/../../lib/hx509/data/key2.der
pkinit_anchors = FILE:@objdir@/ca.crt
pkinit_mappings_file = @srcdir@/pki-mapping
pkinit_ticket_max_life_from_cert = @max_life_from_cert@
plugin_dir = @objdir@/../../kdc/.libs