JGSS fails with KrbException: Message stream modified (41) on cross-realm intermediate/unexpected TGT

Osipov, Michael michael.osipov at siemens.com
Tue Apr 19 09:05:37 UTC 2016


Hi,

I am trying to obtain a service ticket for a cross-realm service within one hierarchy (forest).

The root realm is COMPANY.NET, my realm is R004.COMPANY.NET, target realm is R002.COMPANY.NET and
SPN ldap/server.r002.company.net.

Host to realm mapping in my krb5.conf:
[domain_realm]
    .r004.company.net = R004.COMPANY.NET
    r004.company.net = R004.COMPANY.NET
    .company.net = COMPANY.NET
    company.net = COMPANY.NET

I have tested the same case with MIT Kerberos and SSPI and both have a completely different approach
of requesting service tickets. They do:

TGS-REQ for ldap/server.r002.company.net to a KDC in my home realm
TGS-REP is krbtgt/r002.company.net at R004.COMPANY.NET
TGS-REQ for ldap/server.r002.company.net to a KDC in R002.COMPANY.NET with
	  krbtgt/r002.company.net at R004.COMPANY.NET
TGS-REP is ldap/server.r002.company.net at WW002.SIEMENS.NET

This works as desired.

JGSS in turn does this:
Match hostname to domain realm => COMPANY.NET
TGS-REQ for krbtgt/COMPANY.NET
TGS-REP is krbtgt/company.net at R004.COMPANY.NET
TGS-REQ for ldap/server.r002.company.net to a KDC in COMPANY.NET with
	  krbtgt/company.net at R004.COMPANY.NET
TGS-REP is krbtgt/r002.company.net at COMPANY.NET
and here happens the crash
KrbException: Message stream modified (41)
KrbException: Fail to create credential. (63) - No service creds
	at sun.security.krb5.internal.CredentialsUtil.acquireServiceCreds(CredentialsUtil.java:299)
	at sun.security.krb5.Credentials.acquireServiceCreds(Credentials.java:454)
	at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:641)
	at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:248)
	at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
in KrbKdcRep.java#check(), lines 54 to 56:
	if (!req.reqBody.sname.equalsWithoutRealm(rep.encKDCRepPart.sname)) {
		rep.encKDCRepPart.key.destroy();
		throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
	}

This code assumes that the ticket is already the final service ticket but it is an intermediate TGT
for the target realm. I would expect another TGS-REQ/TGS-REP from JGSS. Due to the logic implemented,
the only known workaround is to add another [domain_realm] mapping but this is daunting because we have
tens of those and I do not know all realms/hostnames upfront due to dynamic TGT referrals.

Another case is HTTP proxy (HTTP/proxyfarm.company.net). JGSS requests at COMPANY.NET but
receives a TGT for R002.COMPANY.NET. Especially in this case, I am not able to know the realm upfront.
Adding the domain realm mapping does not help because this file is used initially only or even worse,
direct hostname to realm mapping is hell. Removing [domain_realm] makes it immediately fail due to
the TGT referral. MIT Kerberos follows all TGT referrals as necessary.

The manpage for krb5.conf for [domain_realm] says:
"If no translation entry applies to a hostname used for a service principal for a service ticket request,
the library will try to get a referral to the appropriate realm from the client realm's KDC..."

I would expect that the TGS logic would resemble the one described above, follow all referrals until
it gets the desired service ticket. Ultimately, not [domain_realm] is necessary, at least with MIT Kerberos
and Active Directory.

Setup:
* KDCs are Windows Server 2008/2012
* Clients are Windows 7 Enterprise
* MIT Kerberos 1.14.1 on FreeBSD
* Oracle JDKs 1.7.0_72 and 1.80_72

All tests happen on Windows, deployment happens on HP-UX with HP JVM which is merely a repackaged Oracle
JVM with native patches for that OS.

I have already created a bundle with log files, krb5.conf and Wireshark pcap files, debug screenshots for
JGSS, MIT Kerberos and SSPI and will happily share in private. Also willing to assist as necessary.

This is actually an annoying blocker disabling us to use cross-domain and cross-forest services. I would
prefer a solution for Java 7 because we haven't migrated to Java 8 yet but willing to do so.

How can we resolve this issue?

Thanks and regards,

Michael Osipov




More information about the security-dev mailing list