Hello,
Following up on our earlier report about "clockskew" duration-string
parsing - while investigating that, we also noticed a gap in KDC
request timeout handling that we'd like to raise as a separate
feature request.
Summary
-------
MIT krb5 (since 1.22) supports "request_timeout" in krb5.conf: a
single absolute deadline (duration string, default 0 = no maximum)
for the *entire* KDC request, including retries and failover across
multiple KDCs. The JDK has no equivalent. It only has "kdc_timeout"
and "max_retries" - both JDK-only keys (no MIT krb5 equivalent),
read as plain integers (ms, or seconds with an "s" suffix), and both
scoped per-KDC-attempt rather than as a total deadline for the whole
operation.
The practical gap: once a TCP connection to a KDC is established and
is actively waiting on a reply, the JDK's per-attempt kdc_timeout
still bounds that specific read. MIT krb5's own sendto_kdc.c has (or
had, pre-request_timeout) the same per-connection-only bound, which is
exactly the scenario request_timeout was introduced to cover: a
connection that connects fine, partially replies, then goes silent,
with no further retries or KDC failover ever kicking in because the
connection still "looks" alive. We hit this exact failure mode in
production (TCP established, request fully ACKed, one data segment
back, then nothing for 11+ minutes - full writeup available if
useful) against a MIT krb5 client; we have not yet reproduced it
against JDK's Kerberos stack specifically, but the underlying
per-attempt-only timeout model is the same, so we'd expect it to be
equally exposed.
Proposal
--------
Add "request_timeout" support to KdcComm, with this fallback
behavior: if "request_timeout" is set in krb5.conf, use it as an
absolute deadline for the whole KDC communication (as MIT does). If
it is not set, fall back to the existing kdc_timeout/max_retries
behavior unchanged - so this is purely additive, with no change to
current defaults or behavior for configs that don't set it.
This looks cheap to implement: the JDK already has a fully
MIT-compatible duration-string parser (Config.duration(String)), used
correctly today for "ticket_lifetime" and "renew_lifetime" (see our
earlier clockskew report for exact locations). It would just need
wiring into KdcComm the same way kdc_timeout currently is.
Where this lives today (pinned to commit
569b05addf69698fc93026b4dca69bc6ca0920b6):
KdcComm.initStatic() - reads "kdc_timeout" / "max_retries", this is
where a "request_timeout" read + fallback would be added:
https://github.com/openjdk/jdk/blob/569b05addf69698fc93026b4dca69bc6ca0920b6/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java#L145-L162
Config.duration(String) - existing MIT-compatible duration parser,
already proven via ticket_lifetime/renew_lifetime in KrbAsReq:
https://github.com/openjdk/jdk/blob/569b05addf69698fc93026b4dca69bc6ca0920b6/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReq.java
MIT reference (for the behavior being proposed as a fallback target):
https://web.mit.edu/kerberos/krb5-latest/doc/admin/conf_files/kdc_conf.html
https://web.mit.edu/kerberos/krb5-latest/doc/basic/date_format.html
We don't have a JBS account / can't file issues ourselves. If this
seems worth pursuing, could someone with filing access open an
enhancement request (or point us to one that already covers this)?
Happy to provide more detail on the production incident that
motivated this, or help test a patch.
Thanks,
Michael Osipov