diff --git a/jdk/src/share/classes/sun/security/krb5/KdcComm.java b/jdk/src/share/classes/sun/security/krb5/KdcComm.java index a4dbf2903bb..0d88cf938f0 100644 --- a/jdk/src/share/classes/sun/security/krb5/KdcComm.java +++ b/jdk/src/share/classes/sun/security/krb5/KdcComm.java @@ -257,9 +257,14 @@ private byte[] sendIfPossible(byte[] obuf, String tempKdc, boolean useTCP) } catch (Exception e) { // OK } - if (ke != null && ke.getErrorCode() == + if (ke != null) { + if (ke.getErrorCode() == Krb5.KRB_ERR_RESPONSE_TOO_BIG) { - ibuf = send(obuf, tempKdc, true); + ibuf = send(obuf, tempKdc, true); + } else if (ke.getErrorCode() == + Krb5.KDC_ERR_SVC_UNAVAILABLE) { + throw new KrbException("A service is not available"); + } } KdcAccessibility.removeBad(tempKdc); return ibuf; diff --git a/jdk/src/share/classes/sun/security/krb5/internal/Krb5.java b/jdk/src/share/classes/sun/security/krb5/internal/Krb5.java index 9730bf2c851..436ed7564cc 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/Krb5.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/Krb5.java @@ -248,6 +248,7 @@ public class Krb5 { public static final int KDC_ERR_KEY_EXPIRED = 23; //Password has expired - change password to reset public static final int KDC_ERR_PREAUTH_FAILED = 24; //Pre-authentication information was invalid public static final int KDC_ERR_PREAUTH_REQUIRED = 25; //Additional pre-authentication required + public static final int KDC_ERR_SVC_UNAVAILABLE = 29; //A service is not available public static final int KRB_AP_ERR_BAD_INTEGRITY = 31; //Integrity check on decrypted field failed public static final int KRB_AP_ERR_TKT_EXPIRED = 32; //Ticket expired public static final int KRB_AP_ERR_TKT_NYV = 33; //Ticket not yet valid diff --git a/jdk/test/sun/security/krb5/auto/TestHosts b/jdk/test/sun/security/krb5/auto/TestHosts new file mode 100644 index 00000000000..1fe0422a5a5 --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/TestHosts @@ -0,0 +1,16 @@ +127.0.0.1 host.rabbit.hole +127.0.0.1 kdc.rabbit.hole +127.0.0.1 kdc.snake.hole +127.0.0.1 kdc.web.domain +127.0.0.1 host.web.domain +127.0.0.1 host.proxy.domain +127.0.0.1 kdc.proxy.domain +127.0.0.1 client.rabbit.hole +127.0.0.1 localhost +127.0.0.1 host.r3.local +127.0.0.1 kdc.r1 +127.0.0.1 kdc.r2 +127.0.0.1 kdc.r3 +127.0.0.1 host.realm +127.0.0.1 realm +127.0.0.1 irlga09 diff --git a/jdk/test/sun/security/krb5/auto/Unavailable.java b/jdk/test/sun/security/krb5/auto/Unavailable.java new file mode 100644 index 00000000000..c673e30305a --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/Unavailable.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021, 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8274205 + * @summary Handle KDC_ERR_SVC_UNAVAILABLE error code from KDC + * @library /test/lib + * @compile -XDignore.symbol.file Unavailable.java + * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Djdk.net.hosts.file=TestHosts Unavailable + */ + +import sun.security.krb5.Config; +import sun.security.krb5.PrincipalName; +import sun.security.krb5.internal.KRBError; +import sun.security.krb5.internal.KerberosTime; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Locale; + +public class Unavailable { + + public static void main(String[] args) throws Exception { + + // Good KDC + KDC kdc1 = KDC.create(OneKDC.REALM); + kdc1.addPrincipal(OneKDC.USER, OneKDC.PASS); + kdc1.addPrincipalRandKey("krbtgt/" + OneKDC.REALM); + + // The "not available" KDC + KDC kdc2 = new KDC(OneKDC.REALM, "kdc." + OneKDC.REALM.toLowerCase(Locale.US), 0, true) { + @Override + protected byte[] processAsReq(byte[] in) throws Exception { + KRBError err = new KRBError(null, null, null, + KerberosTime.now(), 0, + 29, // KDC_ERR_SVC_UNAVAILABLE + null, new PrincipalName("krbtgt/" + OneKDC.REALM), + null, null); + return err.asn1Encode(); + } + }; + + Files.write(Paths.get(OneKDC.KRB5_CONF), String.format( + "[libdefaults]\n" + + "default_realm = RABBIT.HOLE\n" + + "\n" + + "[realms]\n" + + "RABBIT.HOLE = {\n" + + " kdc = kdc.rabbit.hole:%d\n" + + " kdc = kdc.rabbit.hole:%d\n" + + "}\n", + kdc2.getPort(), kdc1.getPort()).getBytes()); + System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF); + Config.refresh(); + + Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); + } +}