changeset 8818:c27108976125

7162687: enhance KDC server availability detection Reviewed-by: valeriep
author weijun
date Fri, 24 Nov 2017 05:00:54 +0000
parents 512cfc54ab90
children 0c2c07d0864d
files src/share/classes/sun/security/krb5/KdcComm.java src/share/classes/sun/security/krb5/internal/NetClient.java test/ProblemList.txt test/sun/security/krb5/auto/BadKdc.java test/sun/security/krb5/auto/MaxRetries.java test/sun/security/krb5/auto/Unreachable.java test/sun/security/krb5/auto/unreachable.krb5.conf
diffstat 7 files changed, 117 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/krb5/KdcComm.java	Fri Nov 24 04:25:02 2017 +0000
+++ b/src/share/classes/sun/security/krb5/KdcComm.java	Fri Nov 24 05:00:54 2017 +0000
@@ -369,37 +369,36 @@
 
             for (int i=1; i <= retries; i++) {
                 String proto = useTCP?"TCP":"UDP";
-                NetClient kdcClient = NetClient.getInstance(
-                        proto, kdc, port, timeout);
-                if (DEBUG) {
-                    System.out.println(">>> KDCCommunication: kdc=" + kdc
-                           + " " + proto + ":"
-                           +  port +  ", timeout="
-                           + timeout
-                           + ",Attempt =" + i
-                           + ", #bytes=" + obuf.length);
-                }
-                try {
-                    /*
-                     * Send the data to the kdc.
-                     */
-                    kdcClient.send(obuf);
-                    /*
-                     * And get a response.
-                     */
-                    ibuf = kdcClient.receive();
-                    break;
-                } catch (SocketTimeoutException se) {
+                try (NetClient kdcClient = NetClient.getInstance(
+                        proto, kdc, port, timeout)) {
                     if (DEBUG) {
-                        System.out.println ("SocketTimeOutException with " +
-                                            "attempt: " + i);
+                        System.out.println(">>> KDCCommunication: kdc=" + kdc
+                            + " " + proto + ":"
+                            +  port +  ", timeout="
+                            + timeout
+                            + ",Attempt =" + i
+                            + ", #bytes=" + obuf.length);
                     }
-                    if (i == retries) {
-                        ibuf = null;
-                        throw se;
+                    try {
+                        /*
+                        * Send the data to the kdc.
+                        */
+                        kdcClient.send(obuf);
+                        /*
+                        * And get a response.
+                        */
+                        ibuf = kdcClient.receive();
+                        break;
+                    } catch (SocketTimeoutException se) {
+                        if (DEBUG) {
+                            System.out.println ("SocketTimeOutException with " +
+                                                "attempt: " + i);
+                        }
+                        if (i == retries) {
+                            ibuf = null;
+                            throw se;
+                        }
                     }
-                } finally {
-                    kdcClient.close();
                 }
             }
             return ibuf;
--- a/src/share/classes/sun/security/krb5/internal/NetClient.java	Fri Nov 24 04:25:02 2017 +0000
+++ b/src/share/classes/sun/security/krb5/internal/NetClient.java	Fri Nov 24 05:00:54 2017 +0000
@@ -36,7 +36,7 @@
 import java.io.*;
 import java.net.*;
 
-public abstract class NetClient {
+public abstract class NetClient implements AutoCloseable {
     public static NetClient getInstance(String protocol, String hostname, int port,
             int timeout) throws IOException {
         if (protocol.equals("TCP")) {
@@ -47,9 +47,7 @@
     }
 
     abstract public void send(byte[] data) throws IOException;
-
     abstract public byte[] receive() throws IOException;
-
     abstract public void close() throws IOException;
 }
 
@@ -190,6 +188,7 @@
         iport = port;
         dgSocket = new DatagramSocket();
         dgSocket.setSoTimeout(timeout);
+        dgSocket.connect(iaddr, iport);
     }
 
     @Override
@@ -207,6 +206,9 @@
             dgSocket.receive(dgPacketIn);
         }
         catch (SocketException e) {
+            if (e instanceof PortUnreachableException) {
+                throw e;
+            }
             dgSocket.receive(dgPacketIn);
         }
         byte[] data = new byte[dgPacketIn.getLength()];
--- a/test/ProblemList.txt	Fri Nov 24 04:25:02 2017 +0000
+++ b/test/ProblemList.txt	Fri Nov 24 05:00:54 2017 +0000
@@ -275,6 +275,9 @@
 # 7162118
 java/net/CookieHandler/CookieManagerTest.java			macosx-all
 
+# 7164518
+sun/security/krb5/auto/Unreachable.java                         macosx-all
+
 # JPRT needs to set 127.0.0.1 in proxy bypass list
 java/net/URLClassLoader/closetest/CloseTest.java		macosx-all
 
--- a/test/sun/security/krb5/auto/BadKdc.java	Fri Nov 24 04:25:02 2017 +0000
+++ b/test/sun/security/krb5/auto/BadKdc.java	Fri Nov 24 05:00:54 2017 +0000
@@ -109,6 +109,10 @@
             throws Exception {
         System.setProperty("sun.security.krb5.debug", "true");
 
+        // Idle UDP sockets will trigger a SocketTimeoutException, without it,
+        // a PortUnreachableException will be thrown.
+        DatagramSocket d1 = null, d2 = null, d3 = null;
+
         // 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);
@@ -131,6 +135,8 @@
         Config.refresh();
 
         // Turn on k3 only
+        d1 = new DatagramSocket(p1);
+        d2 = new DatagramSocket(p2);
         KDC k3 = on(p3);
 
         test(expected[0]);
@@ -139,10 +145,17 @@
         test(expected[2]);
 
         k3.terminate(); // shutdown k3
+        d3 = new DatagramSocket(p3);
+
+        d2.close();
         on(p2);         // k2 is on
+
         test(expected[3]);
+        d1.close();
         on(p1);         // k1 and k2 is on
         test(expected[4]);
+
+        d3.close();
     }
 
     private static KDC on(int p) throws Exception {
--- a/test/sun/security/krb5/auto/MaxRetries.java	Fri Nov 24 04:25:02 2017 +0000
+++ b/test/sun/security/krb5/auto/MaxRetries.java	Fri Nov 24 05:00:54 2017 +0000
@@ -24,11 +24,13 @@
 /*
  * @test
  * @bug 6844193
+ * @compile -XDignore.symbol.file MaxRetries.java
  * @run main/othervm/timeout=300 MaxRetries
  * @summary support max_retries in krb5.conf
  */
 
 import java.io.*;
+import java.net.DatagramSocket;
 import java.security.Security;
 
 public class MaxRetries {
@@ -37,6 +39,10 @@
 
         System.setProperty("sun.security.krb5.debug", "true");
         new OneKDC(null).writeJAASConf();
+
+        // An idle UDP socket to revent PortUnreachableException
+        DatagramSocket ds = new DatagramSocket(33333);
+
         System.setProperty("java.security.krb5.conf", "alternative-krb5.conf");
 
         // For tryLast
@@ -78,6 +84,8 @@
 
         rewriteUdpPrefLimit(10000, 10); // realm rules
         test2("TCP");
+
+        ds.close();
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/Unreachable.java	Fri Nov 24 05:00:54 2017 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 7162687
+ * @summary enhance KDC server availability detection
+ * @compile -XDignore.symbol.file Unreachable.java
+ * @run main/othervm/timeout=10 Unreachable
+ */
+
+import java.io.File;
+import javax.security.auth.login.LoginException;
+import sun.security.krb5.Config;
+
+public class Unreachable {
+
+    public static void main(String[] args) throws Exception {
+        File f = new File(
+                System.getProperty("test.src", "."), "unreachable.krb5.conf");
+        System.setProperty("java.security.krb5.conf", f.getPath());
+        Config.refresh();
+
+        // If PortUnreachableException is not received, the login will consume
+        // about 3*3*30 seconds and the test will timeout.
+        try {
+            Context.fromUserPass("name", "pass".toCharArray(), true);
+        } catch (LoginException le) {
+            // This is OK
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/unreachable.krb5.conf	Fri Nov 24 05:00:54 2017 +0000
@@ -0,0 +1,9 @@
+[libdefaults]
+   default_realm = RABBIT.HOLE
+[realms]
+
+RABBIT.HOLE = {
+   kdc = 127.0.0.1:13434
+   kdc = 127.0.0.1:13435
+   kdc = 127.0.0.1:13436
+}