KrbKdcReq throws the exception on line 55, so it is the previous check if (isAsReq && !req.reqBody.cname.equals(rep.cname) && ((!req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) && req.reqBody.cname.getNameType() != PrincipalName.KRB_NT_ENTERPRISE) || !rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP))) { rep.encKDCRepPart.key.destroy(); >>> throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED); }
So maybe it's the cname was changed, but I'm not sure about the flags. Can you send me some packets? Hopefully with a key tab or password so I can look into rep.encKDCRepPart. Thanks, Max > On Oct 20, 2021, at 4:03 AM, Osipov, Michael (LDA IT PLM) > <michael.osi...@siemens.com> wrote: > > Hi folks, > > we have recently noticed the following with Java's kinit (tested with Zulu 8 > and 13, code is identical in 18 as well): > >> C:\Users\osipovmi>kinit osipo...@ad001.siemens.net > > I have intentionally written the realm in lowercase to rely on > canonicalization of the AD KDC. krb5.conf contains "canonicalize = true" as > well. > > Wireshark shows me in the AS-REQ: > as-req/req-body/sname: name-type KRB5-NT-SRV-INST (2), sname-string (2): > krbtgt and ad001.siemens.net > > AS-REP: > as-rep/ticket/sname: name-type KRB5-NT-SRV-INST (2), sname-string (2): krbtgt > and AD001.SIEMENS.NET > > Hence, the KDC has properly canonicalized the sname. Java gives me: > >> Exception: krb_error 41 Message stream modified (41) Message stream modified >> KrbException: Message stream modified (41) >> at sun.security.krb5.KrbKdcRep.check(KrbKdcRep.java:55) >> at sun.security.krb5.KrbAsRep.decrypt(KrbAsRep.java:159) >> at sun.security.krb5.KrbAsRep.decryptUsingPassword(KrbAsRep.java:139) >> at sun.security.krb5.KrbAsReqBuilder.resolve(KrbAsReqBuilder.java:312) >> at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:498) >> at sun.security.krb5.internal.tools.Kinit.acquire(Kinit.java:248) >> at sun.security.krb5.internal.tools.Kinit.<init>(Kinit.java:134) >> at sun.security.krb5.internal.tools.Kinit.main(Kinit.java:96) > > Referrals aren't involved here, same realm. > The failing code block is from: > * > https://github.com/AdoptOpenJDK/openjdk-jdk8u/blob/9a751dc19fae78ce58fb0eb176522070c992fb6f/jdk/src/share/classes/sun/security/krb5/KrbKdcRep.java#L58-L71 > * > https://github.com/AdoptOpenJDK/openjdk-jdk/blob/ff4997014fe5462dca2b313f3f483400ffee5b62/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java#L58-L71 > >> // sname change in TGS-REP is allowed only if client >> // sent CANONICALIZE and new sname is a referral of >> // the form krbtgt/to-realm....@from-realm.com. >> if (!req.reqBody.sname.equals(rep.encKDCRepPart.sname)) { >> String[] snameStrings = rep.encKDCRepPart.sname.getNameStrings(); >> if (isAsReq || >> !req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) || >> snameStrings == null || snameStrings.length != 2 || >> >> !snameStrings[0].equals(PrincipalName.TGS_DEFAULT_SRV_NAME) || >> !rep.encKDCRepPart.sname.getRealmString().equals( >> req.reqBody.sname.getRealmString())) { >> rep.encKDCRepPart.key.destroy(); >> throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED); >> } >> } > > So it either fails for >> isAsReq > or >> !rep.encKDCRepPart.sname.getRealmString().equals( >>> req.reqBody.sname.getRealmString()) > > Here is MIT Kerberos: >> $ kinit osipo...@ad001.siemens.net >> Passwort für osipo...@ad001.siemens.net: >> $ klist >> Ticketzwischenspeicher: FILE:/tmp/krb5cc_722 >> Standard-Principal: osipo...@ad001.siemens.net >> Valid starting Expires Service principal >> 20.10.2021 10:02:14 20.10.2021 20:02:14 >> krbtgt/ad001.siemens....@ad001.siemens.net >> erneuern bis 21.10.2021 10:02:10 > > Works as expected. Can someone explain? Shall I create a bug for this? > > Michael