# HG changeset patch # User weijun # Date 1261634179 -28800 # Node ID 3a9206343ab28bf13379569c5b602b9d8decf2de # Parent cff832a17f52d3262e734a93c7dde998dbc01d72 6843127: krb5 should not try to access unavailable kdc too often Reviewed-by: valeriep, mullan diff -r cff832a17f52 -r 3a9206343ab2 jdk/src/share/classes/sun/security/krb5/Config.java --- a/jdk/src/share/classes/sun/security/krb5/Config.java Wed Dec 23 15:57:14 2009 -0800 +++ b/jdk/src/share/classes/sun/security/krb5/Config.java Thu Dec 24 13:56:19 2009 +0800 @@ -109,6 +109,7 @@ public static synchronized void refresh() throws KrbException { singleton = new Config(); KeyTab.refresh(); + KrbKdcReq.KdcAccessibility.reset(); } diff -r cff832a17f52 -r 3a9206343ab2 jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java --- a/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java Wed Dec 23 15:57:14 2009 -0800 +++ b/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java Thu Dec 24 13:56:19 2009 +0800 @@ -31,25 +31,26 @@ package sun.security.krb5; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.Security; +import java.util.Locale; import sun.security.krb5.internal.Krb5; import sun.security.krb5.internal.UDPClient; import sun.security.krb5.internal.TCPClient; import java.io.IOException; -import java.io.InterruptedIOException; import java.net.SocketTimeoutException; -import java.net.UnknownHostException; import java.util.StringTokenizer; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.HashSet; public abstract class KrbKdcReq { - /** - * Default port for a KDC. - */ - private static final int DEFAULT_KDC_PORT = Krb5.KDC_INET_DEFAULT_PORT; - // Currently there is no option to specify retries // in the kerberos configuration file @@ -66,7 +67,48 @@ private static int udpPrefLimit = -1; + private static final String BAD_POLICY_KEY = "krb5.kdc.bad.policy"; + + /** + * What to do when a KDC is unavailable, specified in the + * java.security file with key krb5.kdc.bad.policy. + * Possible values can be TRY_LAST or TRY_LESS + */ + private enum BpType { + NONE, TRY_LAST, TRY_LESS + } + private static int tryLessMaxRetries = 1; + private static int tryLessTimeout = 5000; + + private static final BpType badPolicy; + static { + String value = AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return Security.getProperty(BAD_POLICY_KEY); + } + }); + if (value != null) { + value = value.toLowerCase(Locale.ENGLISH); + String[] ss = value.split(":"); + if ("tryless".equals(ss[0])) { + if (ss.length > 1) { + String[] params = ss[1].split(","); + tryLessMaxRetries = Integer.parseInt(params[0]); + if (params.length > 1) { + tryLessTimeout = Integer.parseInt(params[1]); + } + } + badPolicy = BpType.TRY_LESS; + } else if ("trylast".equals(ss[0])) { + badPolicy = BpType.TRY_LAST; + } else { + badPolicy = BpType.NONE; + } + } else { + badPolicy = BpType.NONE; + } /* * Get default timeout. @@ -131,22 +173,16 @@ } } - /* - * Get timeout. - */ - - int timeout = getKdcTimeout(realm); - String kdcList = cfg.getKDCList(realm); if (kdcList == null) { throw new KrbException("Cannot get kdc for realm " + realm); } String tempKdc = null; // may include the port number also - StringTokenizer st = new StringTokenizer(kdcList); - while (st.hasMoreTokens()) { - tempKdc = st.nextToken(); + for (String tmp: KdcAccessibility.list(kdcList)) { + tempKdc = tmp; try { send(realm,tempKdc,useTCP); + KdcAccessibility.removeBad(tempKdc); break; } catch (Exception e) { if (DEBUG) { @@ -154,6 +190,7 @@ tempKdc); e.printStackTrace(System.out); } + KdcAccessibility.addBad(tempKdc); savedException = e; } } @@ -174,16 +211,21 @@ if (obuf == null) return; - PrivilegedActionException savedException = null; + int port = Krb5.KDC_INET_DEFAULT_PORT; + int retries = DEFAULT_KDC_RETRY_LIMIT; + int timeout = getKdcTimeout(realm); - /* - * Get timeout. - */ - int timeout = getKdcTimeout(realm); - /* - * Get port number for this KDC. - */ + if (badPolicy == BpType.TRY_LESS && + KdcAccessibility.isBad(tempKdc)) { + if (retries > tryLessMaxRetries) { + retries = tryLessMaxRetries; // less retries + } + if (timeout > tryLessTimeout) { + timeout = tryLessTimeout; // less time + } + } + String kdc = null; String portStr = null; @@ -225,12 +267,12 @@ + port + ", timeout=" + timeout + ", number of retries =" - + DEFAULT_KDC_RETRY_LIMIT + + retries + ", #bytes=" + obuf.length); } KdcCommunication kdcCommunication = - new KdcCommunication(kdc, port, useTCP, timeout, obuf); + new KdcCommunication(kdc, port, useTCP, timeout, retries, obuf); try { ibuf = AccessController.doPrivileged(kdcCommunication); if (DEBUG) { @@ -258,14 +300,16 @@ private int port; private boolean useTCP; private int timeout; + private int retries; private byte[] obuf; public KdcCommunication(String kdc, int port, boolean useTCP, - int timeout, byte[] obuf) { + int timeout, int retries, byte[] obuf) { this.kdc = kdc; this.port = port; this.useTCP = useTCP; this.timeout = timeout; + this.retries = retries; this.obuf = obuf; } @@ -294,7 +338,7 @@ } else { // For each KDC we try DEFAULT_KDC_RETRY_LIMIT (3) times to // get the response - for (int i=1; i <= DEFAULT_KDC_RETRY_LIMIT; i++) { + for (int i=1; i <= retries; i++) { UDPClient kdcClient = new UDPClient(kdc, port, timeout); if (DEBUG) { @@ -310,7 +354,7 @@ * Send the data to the kdc. */ - kdcClient.send(obuf); + kdcClient.send(obuf); /* * And get a response. @@ -323,7 +367,7 @@ System.out.println ("SocketTimeOutException with " + "attempt: " + i); } - if (i == DEFAULT_KDC_RETRY_LIMIT) { + if (i == retries) { ibuf = null; throw se; } @@ -385,4 +429,67 @@ return -1; } + + /** + * Maintains a KDC accessible list. Unavailable KDCs are put into a + * blacklist, when a KDC in the blacklist is available, it's removed + * from there. No insertion order in the blacklist. + * + * There are two methods to deal with KDCs in the blacklist. 1. Only try + * them when there's no KDC not on the blacklist. 2. Still try them, but + * with lesser number of retries and smaller timeout value. + */ + static class KdcAccessibility { + // Known bad KDCs + private static Set bads = new HashSet(); + + private static synchronized void addBad(String kdc) { + if (DEBUG) { + System.out.println(">>> KdcAccessibility: add " + kdc); + } + bads.add(kdc); + } + + private static synchronized void removeBad(String kdc) { + if (DEBUG) { + System.out.println(">>> KdcAccessibility: remove " + kdc); + } + bads.remove(kdc); + } + + private static synchronized boolean isBad(String kdc) { + return bads.contains(kdc); + } + + public static synchronized void reset() { + if (DEBUG) { + System.out.println(">>> KdcAccessibility: reset"); + } + bads.clear(); + } + + // Returns a preferred KDC list by putting the bad ones at the end + private static synchronized String[] list(String kdcList) { + StringTokenizer st = new StringTokenizer(kdcList); + List list = new ArrayList(); + if (badPolicy == BpType.TRY_LAST) { + List badkdcs = new ArrayList(); + while (st.hasMoreTokens()) { + String t = st.nextToken(); + if (bads.contains(t)) badkdcs.add(t); + else list.add(t); + } + // Bad KDCs are put at last + list.addAll(badkdcs); + } else { + // All KDCs are returned in their original order, + // This include TRY_LESS and NONE + while (st.hasMoreTokens()) { + list.add(st.nextToken()); + } + } + return list.toArray(new String[list.size()]); + } + } } + diff -r cff832a17f52 -r 3a9206343ab2 jdk/src/share/lib/security/java.security --- a/jdk/src/share/lib/security/java.security Wed Dec 23 15:57:14 2009 -0800 +++ b/jdk/src/share/lib/security/java.security Thu Dec 24 13:56:19 2009 +0800 @@ -55,10 +55,10 @@ # # Select the source of seed data for SecureRandom. By default an -# attempt is made to use the entropy gathering device specified by +# attempt is made to use the entropy gathering device specified by # the securerandom.source property. If an exception occurs when -# accessing the URL then the traditional system/thread activity -# algorithm is used. +# accessing the URL then the traditional system/thread activity +# algorithm is used. # # On Solaris and Linux systems, if file:/dev/urandom is specified and it # exists, a special SecureRandom implementation is activated by default. @@ -72,7 +72,7 @@ # The entropy gathering device is described as a URL and can also # be specified with the system property "java.security.egd". For example, # -Djava.security.egd=file:/dev/urandom -# Specifying this system property will override the securerandom.source +# Specifying this system property will override the securerandom.source # setting. # @@ -149,7 +149,7 @@ security.overridePropertiesFile=true # -# Determines the default key and trust manager factory algorithms for +# Determines the default key and trust manager factory algorithms for # the javax.net.ssl package. # ssl.KeyManagerFactory.algorithm=SunX509 @@ -168,10 +168,10 @@ # is to cache for 30 seconds. # # NOTE: setting this to anything other than the default value can have -# serious security implications. Do not set it unless +# serious security implications. Do not set it unless # you are sure you are not exposed to DNS spoofing attack. # -#networkaddress.cache.ttl=-1 +#networkaddress.cache.ttl=-1 # The Java-level namelookup cache policy for failed lookups: # @@ -183,7 +183,7 @@ # the WINS name service in addition to DNS, name service lookups # that fail may take a noticeably long time to return (approx. 5 seconds). # For this reason the default caching policy is to maintain these -# results for 10 seconds. +# results for 10 seconds. # # networkaddress.cache.negative.ttl=10 @@ -192,7 +192,7 @@ # Properties to configure OCSP for certificate revocation checking # -# Enable OCSP +# Enable OCSP # # By default, OCSP is not used for certificate revocation checking. # This property enables the use of OCSP when set to the value "true". @@ -201,7 +201,7 @@ # # Example, # ocsp.enable=true - + # # Location of the OCSP responder # @@ -213,15 +213,15 @@ # # Example, # ocsp.responderURL=http://ocsp.example.net:80 - + # # Subject name of the OCSP responder's certificate # # By default, the certificate of the OCSP responder is that of the issuer # of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. In cases where +# of the OCSP responder when the default does not apply. Its value is a string +# distinguished name (defined in RFC 2253) which identifies a certificate in +# the set of certificates supplied during cert path validation. In cases where # the subject name alone is not sufficient to uniquely identify the certificate # then both the "ocsp.responderCertIssuerName" and # "ocsp.responderCertSerialNumber" properties must be used instead. When this @@ -237,14 +237,14 @@ # of the certificate being validated. This property identifies the certificate # of the OCSP responder when the default does not apply. Its value is a string # distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. When this -# property is set then the "ocsp.responderCertSerialNumber" property must also -# be set. When the "ocsp.responderCertSubjectName" property is set then this +# the set of certificates supplied during cert path validation. When this +# property is set then the "ocsp.responderCertSerialNumber" property must also +# be set. When the "ocsp.responderCertSubjectName" property is set then this # property is ignored. # # Example, # ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp" - + # # Serial number of the OCSP responder's certificate # @@ -259,4 +259,31 @@ # # Example, # ocsp.responderCertSerialNumber=2A:FF:00 - + +# +# Policy for failed Kerberos KDC lookups: +# +# When a KDC is unavailable (network error, service failure, etc), it is +# put inside a blacklist and accessed less often for future requests. The +# value (case-insensitive) for this policy can be: +# +# tryLast +# KDCs in the blacklist are always tried after those not on the list. +# +# tryLess[:max_retries,timeout] +# KDCs in the blacklist are still tried by their order in the configuration, +# but with smaller max_retries and timeout values. max_retries and timeout +# are optional numerical parameters (default 1 and 5000, which means once +# and 5 seconds). Please notes that if any of the values defined here is +# more than what is defined in krb5.conf, it will be ignored. +# +# Whenever a KDC is detected as available, it is removed from the blacklist. +# The blacklist is reset when krb5.conf is reloaded. You can add +# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is +# reloaded whenever a JAAS authentication is attempted. +# +# Example, +# krb5.kdc.bad.policy = tryLast +# krb5.kdc.bad.policy = tryLess:2,2000 +krb5.kdc.bad.policy = tryLast + diff -r cff832a17f52 -r 3a9206343ab2 jdk/test/sun/security/krb5/auto/BadKdc.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc.java Thu Dec 24 13:56:19 2009 +0800 @@ -0,0 +1,113 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.security.krb5.Config; + +public class BadKdc { + + // Matches the krb5 debug output: + // >>> KDCCommunication: kdc=kdc.rabbit.hole UDP:14319, timeout=2000,... + // ^ kdc# ^ timeout + static final Pattern re = Pattern.compile( + ">>> KDCCommunication: kdc=kdc.rabbit.hole UDP:(\\d)...., " + + "timeout=(\\d)000,"); + public static void go(int[]... expected) + throws Exception { + System.setProperty("sun.security.krb5.debug", "true"); + + // Make sure KDCs' ports starts with 1 and 2 and 3, + // useful for checking debug output. + int p1 = 10000 + new java.util.Random().nextInt(10000); + int p2 = 20000 + new java.util.Random().nextInt(10000); + int p3 = 30000 + new java.util.Random().nextInt(10000); + + FileWriter fw = new FileWriter("alternative-krb5.conf"); + + fw.write("[libdefaults]\n" + + "default_realm = " + OneKDC.REALM + "\n" + + "kdc_timeout = 2000\n"); + fw.write("[realms]\n" + OneKDC.REALM + " = {\n" + + "kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" + + "kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" + + "kdc = " + OneKDC.KDCHOST + ":" + p3 + "\n" + + "}\n"); + + fw.close(); + System.setProperty("java.security.krb5.conf", "alternative-krb5.conf"); + Config.refresh(); + + // Turn on k3 only + KDC k3 = on(p3); + + test(expected[0]); + test(expected[1]); + Config.refresh(); + test(expected[2]); + + k3.terminate(); // shutdown k3 + on(p2); // k2 is on + test(expected[3]); + on(p1); // k1 and k2 is on + test(expected[4]); + } + + private static KDC on(int p) throws Exception { + KDC k = new KDC(OneKDC.REALM, OneKDC.KDCHOST, p, true); + k.addPrincipal(OneKDC.USER, OneKDC.PASS); + k.addPrincipalRandKey("krbtgt/" + OneKDC.REALM); + return k; + } + + /** + * One round of test for max_retries and timeout. + * @param timeout the expected timeout + * @param expected the expected kdc# timeout kdc# timeout... + */ + private static void test(int... expected) throws Exception { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + PrintStream oldout = System.out; + System.setOut(new PrintStream(bo)); + Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); + System.setOut(oldout); + + String[] lines = new String(bo.toByteArray()).split("\n"); + System.out.println("----------------- TEST -----------------"); + int count = 0; + for (String line: lines) { + Matcher m = re.matcher(line); + if (m.find()) { + System.out.println(line); + if (Integer.parseInt(m.group(1)) != expected[count++] || + Integer.parseInt(m.group(2)) != expected[count++]) { + throw new Exception("Fail here"); + } + } + } + if (count != expected.length) { + throw new Exception("Less rounds"); + } + } +} diff -r cff832a17f52 -r 3a9206343ab2 jdk/test/sun/security/krb5/auto/BadKdc1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc1.java Thu Dec 24 13:56:19 2009 +0800 @@ -0,0 +1,53 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6843127 + * @run main/timeout=300 BadKdc1 + * @summary krb5 should not try to access unavailable kdc too often + */ + +import java.io.*; +import java.security.Security; + +public class BadKdc1 { + + public static void main(String[] args) + throws Exception { + Security.setProperty("krb5.kdc.bad.policy", "tryLess"); + BadKdc.go( + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2 + // The above line means try kdc1 for 2 seconds, then kdc1 + // for 2 seconds,..., finally kdc3 for 2 seconds. + new int[]{1,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2 + // refresh + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2 + // k3 off, k2 on + new int[]{1,2,2,2,1,2,2,2}, // 1 + // k1 on + new int[]{1,2,1,2} // empty + ); + } +} + diff -r cff832a17f52 -r 3a9206343ab2 jdk/test/sun/security/krb5/auto/BadKdc2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc2.java Thu Dec 24 13:56:19 2009 +0800 @@ -0,0 +1,50 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6843127 + * @run main/timeout=300 BadKdc2 + * @summary krb5 should not try to access unavailable kdc too often + */ + +import java.io.*; +import java.security.Security; + +public class BadKdc2 { + + public static void main(String[] args) + throws Exception { + Security.setProperty("krb5.kdc.bad.policy", "tryLess:2,1000"); + BadKdc.go( + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2 + new int[]{1,1,1,1,2,1,2,1,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2 + // refresh + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2 + // k3 off, k2 on + new int[]{1,1,1,1,2,1,1,1,1,1,2,2}, // 1 + // k1 on + new int[]{1,1,1,2} // empty + ); + } +} diff -r cff832a17f52 -r 3a9206343ab2 jdk/test/sun/security/krb5/auto/BadKdc3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc3.java Thu Dec 24 13:56:19 2009 +0800 @@ -0,0 +1,50 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6843127 + * @run main/timeout=300 BadKdc3 + * @summary krb5 should not try to access unavailable kdc too often + */ + +import java.io.*; +import java.security.Security; + +public class BadKdc3 { + + public static void main(String[] args) + throws Exception { + Security.setProperty("krb5.kdc.bad.policy", "tryLast"); + BadKdc.go( + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2 + new int[]{3,2,3,2}, // 1, 2 + // refresh + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2 + // k3 off, k2 on + new int[]{3,2,3,2,3,2,1,2,1,2,1,2,2,2,2,2}, // 1, 3 + // k1 on + new int[]{2,2,2,2} // 1, 3 + ); + } +} diff -r cff832a17f52 -r 3a9206343ab2 jdk/test/sun/security/krb5/auto/BadKdc4.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc4.java Thu Dec 24 13:56:19 2009 +0800 @@ -0,0 +1,50 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6843127 + * @run main/timeout=300 BadKdc4 + * @summary krb5 should not try to access unavailable kdc too often + */ + +import java.io.*; +import java.security.Security; + +public class BadKdc4 { + + public static void main(String[] args) + throws Exception { + Security.setProperty("krb5.kdc.bad.policy", ""); + BadKdc.go( + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2}, + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2}, + // refresh + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2}, + // k3 off, k2 on + new int[]{1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2}, + // k1 on + new int[]{1,2,1,2} + ); + } +} diff -r cff832a17f52 -r 3a9206343ab2 jdk/test/sun/security/krb5/auto/KDC.java --- a/jdk/test/sun/security/krb5/auto/KDC.java Wed Dec 23 15:57:14 2009 -0800 +++ b/jdk/test/sun/security/krb5/auto/KDC.java Thu Dec 24 13:56:19 2009 +0800 @@ -141,6 +141,10 @@ // Options private Map options = new HashMap(); + private Thread thread1, thread2, thread3; + DatagramSocket u1 = null; + ServerSocket t1 = null; + /** * Option names, to be expanded forever. */ @@ -940,8 +944,6 @@ * @throws java.io.IOException for any communication error */ protected void startServer(int port, boolean asDaemon) throws IOException { - DatagramSocket u1 = null; - ServerSocket t1 = null; if (port > 0) { u1 = new DatagramSocket(port, InetAddress.getByName("127.0.0.1")); t1 = new ServerSocket(port); @@ -966,7 +968,7 @@ this.port = port; // The UDP consumer - Thread thread = new Thread() { + thread1 = new Thread() { public void run() { while (true) { try { @@ -982,11 +984,11 @@ } } }; - thread.setDaemon(asDaemon); - thread.start(); + thread1.setDaemon(asDaemon); + thread1.start(); // The TCP consumer - thread = new Thread() { + thread2 = new Thread() { public void run() { while (true) { try { @@ -1004,11 +1006,11 @@ } } }; - thread.setDaemon(asDaemon); - thread.start(); + thread2.setDaemon(asDaemon); + thread2.start(); // The dispatcher - thread = new Thread() { + thread3 = new Thread() { public void run() { while (true) { try { @@ -1018,10 +1020,21 @@ } } }; - thread.setDaemon(true); - thread.start(); + thread3.setDaemon(true); + thread3.start(); } + public void terminate() { + try { + thread1.stop(); + thread2.stop(); + thread3.stop(); + u1.close(); + t1.close(); + } catch (Exception e) { + // OK + } + } /** * Helper class to encapsulate a job in a KDC. */ diff -r cff832a17f52 -r 3a9206343ab2 jdk/test/sun/security/krb5/auto/OneKDC.java --- a/jdk/test/sun/security/krb5/auto/OneKDC.java Wed Dec 23 15:57:14 2009 -0800 +++ b/jdk/test/sun/security/krb5/auto/OneKDC.java Thu Dec 24 13:56:19 2009 +0800 @@ -24,8 +24,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; import java.security.Security; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler;