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)
> <[email protected]> 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 [email protected]
>
> 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/[email protected].
>> 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 [email protected]
>> Passwort für [email protected]:
>> $ klist
>> Ticketzwischenspeicher: FILE:/tmp/krb5cc_722
>> Standard-Principal: [email protected]
>> Valid starting Expires Service principal
>> 20.10.2021 10:02:14 20.10.2021 20:02:14
>> krbtgt/[email protected]
>> erneuern bis 21.10.2021 10:02:10
>
> Works as expected. Can someone explain? Shall I create a bug for this?
>
> Michael