RFR 8239385: KerberosTicket client name refers wrongly to sAMAccountName in AD

Martin Balao mbalao at redhat.com
Sun Mar 29 00:12:11 UTC 2020


Hi Max,

I'd like to propose a fix for 8239385 [1].

Webrev.00:

 * http://cr.openjdk.java.net/~mbalao/webrevs/8239385/8239385.webrev.00/

The goal behind these changes is to align the Kerberos client default
'canonicalize' behavior to the MIT's one -an analysis of the latter is
available at the end of this email for reference-. There are a couple of
reasons for that:

 1) many applications are not ready to deal with cname changes in their
authorization schemes, so the previous default behavior may be too
disruptive; and,

 2) old KDCs -such as Windows AD 2008- may change the cname when
'canonicalize' is sent from the client but do not include a ENC-PA-REP
flag (nor the associated data structure) in the response. Note: cname
changes without proper authentication should not be allowed.

This change set us apart from a strict interpretation of the RFC 6806
[2], but will enhance compatibility and should not pose a security risk.

Changes per file:

 * src/java.security.jgss/share/classes/sun/security/krb5/Config.java
  * When a krb5 configuration refresh happens, we need to update the
cached 'canonicalize' value stored in ReferralsState class. Same pattern
than for other krb5 configurations.

 *
src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java
  * Read and cache-store of krb5 'canonicalize' configuration value.
  * 'canonicalize' flag will be sent in AS-REQs only if set to true in
the krb5 configuration. false by default.
  * AS referrals allowed only if 'canonicalize' was sent or an
NT-ENTERPRISE cname was used
   * Usage of NT-ENTERPRISE implies 'canonicalize' (despite the actual
flag may not be set). This mimics the MIT client behavior.
    * Note: OpenJDK will bring APIs for using NT-ENTERPRISE clients on a
separate enhancement.
  * If there is an unexpected KDC failure, the number of max referrals
has not been exceeded and 'canonicalize' was set, retry without it.
Given that we are not tightening 'canonicalize' to NT-ENTERPRISE (as we
would do in a strict interpretation of RFC 6806), we no longer need to
check that the cname type is different than NT-ENTERPRISE to retry.
  * Improved debug output and comments

 * src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java
  * When checking the AS-REP, the usage of an NT-ENTERPRISE cname is
considered equal to sending 'canonicalize' (same as in
KrbAsReqBuilder.java).
  * When checking ENC-PA-REP in line 141, 'canonicalize' is not
relevant: whether or not ENC-PA-REP is required in the KDC response has
been already checked before. In fact, 'canonicalize' may be not sent but
we require a ENC-PA-REP in the AS-REP because an NT-ENTERPRISE cname was
used and the cname was changed by the KDC.
   * Note: from a client side, sending an NT-ENTERPRISE cname means that
the cname can change in the response. Windows AD 2016, however, does not
change it unless 'canonicalize' flag is explicitly set in the request.
  * Improved comments

 * test/jdk/sun/security/krb5/auto/ReferralsTest.java
  * Test for the use-case in which 'canonicalize' is not set, and a
referral must fail. Contributed by Max (@weijun), with enhanced comments
and cleanup function.

Testing:

 * No regressions observed in jdk/sun/security/krb5
 * ReferralsTest extended to cover the new use case
 * No regressions found in my internal Windows AD 2016 environment

In parallel to this RFR, I'll initiate a CSR process to introduce the
"canonicalize" krb5 configuration (whose default value is 'false').

Thanks,
Martin.-

--
[1] - https://bugs.openjdk.java.net/browse/JDK-8239385
[2] - https://tools.ietf.org/html/rfc6806

--

MIT Kerberos client analysis

AS-REQs analysis
........................................

When requesting a TGT (through the AS protocol), CANONICALIZE flag is
set in the AS-REQ only if 'canonicalize' parameter or configuration
options are set [2] (false is the default value).

When receiving a KDC_ERR_WRONG_REALM referral response from a KDC, the
referral will be followed only if CANONICALIZE was set in the
corresponding AS-REQ or if the cname principal was of NT-ENTERPRISE type
[3] [4]. When analyzing the final AS-REP (after all referrals), there is
a check to enforce that either CANONICALIZE was set in the AS-REQ or the
client is a NT-ENTERPRISE principal (among other checks) [5].

kinit's documentation states that -E (for NT-ENTERPRISE principals)
implies CANONICALIZE. "Implies" does not mean that the CANONICALIZE flag
is set; only that referrals will be followed and cname changes are
accepted as if CANONICALIZE were set. In my observations, the Windows
2016 AD does not change the cname unless CANONICALIZE flag is explicitly
set in the AS-REQ.

In conclusion, referrals are followed only if 'canonicalize' is set or
if the cname is an NT-ENTERPRISE principal. Given that OpenJDK does not
currently support NT-ENTERPRISE principals in its user interface, the
MIT equivalent behavior would be to disable AS-REQ referrals by default
(when CANONICALIZE is not set).


AP-REQs analysis
........................................

When requesting a TGS, the MIT kvno client tries with referrals first
[6] [7]. If there is an error -there are some checks to deal with old
Active Directories-, a fallback without referrals is tried [8].
Depending on whether referrals are enabled (STATE_REFERRALS) or not
(STATE_NON_REFERRAL), the CANONICALIZE flag may be set in the request
here [9].

It's worth noticing that:

1) referrals processing requires to be in STATE_REFERRALS state and that
means that CANONICALIZE was set in the AP-REQ;

2) CANONICALIZE value for TGSs does not seem to come from a
user-configurable option (as it was for AS-REQs) and is set by default; and

3) there is a fallback mechanism as we already have in OpenJDK.


--
[1] -
https://github.com/krb5/krb5/tree/97e3c42b2a89a2ec60eb93d3f974769e3e3cbdc5
[2] -
https://github.com/krb5/krb5/blob/97e3c42b2a89a2ec60eb93d3f974769e3e3cbdc5/src/lib/krb5/krb/get_in_tkt.c#L969
[3] -
https://github.com/krb5/krb5/blob/97e3c42b2a89a2ec60eb93d3f974769e3e3cbdc5/src/lib/krb5/krb/get_in_tkt.c#L1536
[4] -
https://github.com/krb5/krb5/blob/97e3c42b2a89a2ec60eb93d3f974769e3e3cbdc5/src/lib/krb5/krb/get_in_tkt.c#L1587
[5] -
https://github.com/krb5/krb5/blob/97e3c42b2a89a2ec60eb93d3f974769e3e3cbdc5/src/lib/krb5/krb/get_in_tkt.c#L227
[6] -
https://github.com/krb5/krb5/blob/97e3c42b2a89a2ec60eb93d3f974769e3e3cbdc5/src/lib/krb5/krb/get_creds.c#L1072
[7] -
https://github.com/krb5/krb5/blob/97e3c42b2a89a2ec60eb93d3f974769e3e3cbdc5/src/lib/krb5/krb/get_creds.c#L620
[8] -
https://github.com/krb5/krb5/blob/97e3c42b2a89a2ec60eb93d3f974769e3e3cbdc5/src/lib/krb5/krb/get_creds.c#L479
[9] -
https://github.com/krb5/krb5/blob/97e3c42b2a89a2ec60eb93d3f974769e3e3cbdc5/src/lib/krb5/krb/get_creds.c#L338



More information about the security-dev mailing list