< prev index next >

src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java

Print this page
rev 54745 : 8215032: Support Kerberos cross-realm referrals (RFC 6806)
Reviewed-by: weijun

*** 1,7 **** /* ! * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 260,288 **** * @param key null (initial AS-REQ) or pakey (with preauth) * @return the KrbAsReq object * @throws KrbException * @throws IOException */ ! private KrbAsReq build(EncryptionKey key) throws KrbException, IOException { int[] eTypes; if (password != null) { eTypes = EType.getDefaults("default_tkt_enctypes"); } else { EncryptionKey[] ks = Krb5Util.keysFromJavaxKeyTab(ktab, cname); eTypes = EType.getDefaults("default_tkt_enctypes", ks); for (EncryptionKey k: ks) k.destroy(); } return new KrbAsReq(key, options, cname, sname, from, till, rtime, eTypes, ! addresses); } /** * Parses AS-REP, decrypts enc-part, retrieves ticket and session key * @throws KrbException --- 260,299 ---- * @param key null (initial AS-REQ) or pakey (with preauth) * @return the KrbAsReq object * @throws KrbException * @throws IOException */ ! private KrbAsReq build(EncryptionKey key, ReferralsState referralsState) ! throws KrbException, IOException { ! PAData[] extraPAs = null; int[] eTypes; if (password != null) { eTypes = EType.getDefaults("default_tkt_enctypes"); } else { EncryptionKey[] ks = Krb5Util.keysFromJavaxKeyTab(ktab, cname); eTypes = EType.getDefaults("default_tkt_enctypes", ks); for (EncryptionKey k: ks) k.destroy(); } + options = (options == null) ? new KDCOptions() : options; + if (referralsState.isEnabled()) { + options.set(KDCOptions.CANONICALIZE, true); + extraPAs = new PAData[]{ new PAData(Krb5.PA_REQ_ENC_PA_REP, + new byte[]{}) }; + } else { + options.set(KDCOptions.CANONICALIZE, false); + } return new KrbAsReq(key, options, cname, sname, from, till, rtime, eTypes, ! addresses, ! extraPAs); } /** * Parses AS-REP, decrypts enc-part, retrieves ticket and session key * @throws KrbException
*** 316,330 **** * @throws KrbException * @throws IOException */ private KrbAsReqBuilder send() throws KrbException, IOException { boolean preAuthFailedOnce = false; ! KdcComm comm = new KdcComm(cname.getRealmAsString()); EncryptionKey pakey = null; while (true) { try { ! req = build(pakey); rep = new KrbAsRep(comm.send(req.encoding())); return this; } catch (KrbException ke) { if (!preAuthFailedOnce && ( ke.returnCode() == Krb5.KDC_ERR_PREAUTH_FAILED || --- 327,345 ---- * @throws KrbException * @throws IOException */ private KrbAsReqBuilder send() throws KrbException, IOException { boolean preAuthFailedOnce = false; ! KdcComm comm = null; EncryptionKey pakey = null; + ReferralsState referralsState = new ReferralsState(); while (true) { + if (referralsState.refreshComm()) { + comm = new KdcComm(cname.getRealmAsString()); + } try { ! req = build(pakey, referralsState); rep = new KrbAsRep(comm.send(req.encoding())); return this; } catch (KrbException ke) { if (!preAuthFailedOnce && ( ke.returnCode() == Krb5.KDC_ERR_PREAUTH_FAILED ||
*** 349,364 **** --- 364,438 ---- PAData.getSaltAndParams( paEType, kerr.getPA())); } paList = kerr.getPA(); // Update current paList } else { + if (referralsState.handleError(ke)) { + continue; + } throw ke; } } } } + private final class ReferralsState { + private boolean enabled; + private int count; + private boolean refreshComm; + + ReferralsState() throws KrbException { + if (Config.DISABLE_REFERRALS) { + if (cname.getNameType() == PrincipalName.KRB_NT_ENTERPRISE) { + throw new KrbException("NT-ENTERPRISE principals only allowed" + + " when referrals are enabled."); + } + enabled = false; + } else { + enabled = true; + } + refreshComm = true; + } + + boolean handleError(KrbException ke) throws RealmException { + if (enabled) { + if (ke.returnCode() == Krb5.KRB_ERR_WRONG_REALM) { + Realm referredRealm = ke.getError().getClientRealm(); + if (req.getMessage().reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) && + referredRealm != null && referredRealm.toString().length() > 0 && + count < Config.MAX_REFERRALS) { + cname = new PrincipalName(cname.getNameString().replaceAll( + PrincipalName.NAME_REALM_SEPARATOR + "", "\\\\" + + PrincipalName.NAME_REALM_SEPARATOR), cname.getNameType(), + referredRealm.toString()); + refreshComm = true; + count++; + return true; + } + } + if (count < Config.MAX_REFERRALS && + cname.getNameType() != PrincipalName.KRB_NT_ENTERPRISE) { + // Server may raise an error if CANONICALIZE is true. + // Try CANONICALIZE false. + enabled = false; + return true; + } + } + return false; + } + + boolean refreshComm() { + boolean retRefreshComm = refreshComm; + refreshComm = false; + return retRefreshComm; + } + + boolean isEnabled() { + return enabled; + } + } + /** * Performs AS-REQ send and AS-REP receive. * Maybe a state is needed here, to divide prepare process and getCreds. * @throws KrbException * @throws Asn1Exception
< prev index next >