From 02c8c266b374f0c4c10a06d60f78e4186e9324fe Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Tue, 4 Dec 2018 11:57:44 +1100 Subject: [PATCH 1/6] [Kerberos] Find if port is available before using it for Kdc server If the randomly selected port was already in use the kerberos tests would fail. This commit adds check to see if the network port is available and if not continue to find one for kdc server. If it does not find port after 100 retries it throws an exception. Closes #34261 --- .../authc/kerberos/SimpleKdcLdapServer.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java index 13601d2fe202f..b9e09d1954572 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java @@ -22,6 +22,9 @@ import org.elasticsearch.test.ESTestCase; import java.io.IOException; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.ServerSocket; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -31,6 +34,8 @@ import java.util.Locale; import java.util.concurrent.TimeUnit; +import javax.net.ServerSocketFactory; + /** * Utility wrapper around Apache {@link SimpleKdcServer} backed by Unboundid * {@link InMemoryDirectoryServer}.
@@ -129,6 +134,14 @@ private void prepareKdcServerAndStart() throws Exception { simpleKdc.setKdcRealm(realm); if (kdcPort == 0) { kdcPort = NetworkUtil.getServerPort(); + int tries = 0; + while (isPortAvailable(kdcPort, transport) == false) { + if (tries > 100) { + throw new IllegalArgumentException("Could not find available port for KDC server"); + } + kdcPort = NetworkUtil.getServerPort(); + tries++; + } } if (transport != null) { if (transport.trim().equals("TCP")) { @@ -221,4 +234,21 @@ public Void run() throws Exception { logger.info("SimpleKdcServer stoppped."); } + private boolean isPortAvailable(int port, String transport) { + if (transport != null && transport.trim().equalsIgnoreCase("tcp")) { + try (ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(port, 1, + InetAddress.getByName("127.0.0.1"))) { + return true; + } catch (Exception ex) { + return false; + } + } else if (transport != null && transport.trim().equalsIgnoreCase("udp")) { + try (DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("127.0.0.1"))) { + return true; + } catch (Exception ex) { + return false; + } + } + return false; + } } From ef933c3c0135141083635c452b5f3263ae101829 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Tue, 4 Dec 2018 13:53:16 +1100 Subject: [PATCH 2/6] Fix compile error --- .../xpack/security/authc/kerberos/SimpleKdcLdapServer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java index b9e09d1954572..a112236122bb0 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java @@ -238,13 +238,13 @@ private boolean isPortAvailable(int port, String transport) { if (transport != null && transport.trim().equalsIgnoreCase("tcp")) { try (ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("127.0.0.1"))) { - return true; + return serverSocket.isBound(); } catch (Exception ex) { return false; } } else if (transport != null && transport.trim().equalsIgnoreCase("udp")) { try (DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("127.0.0.1"))) { - return true; + return socket.isBound(); } catch (Exception ex) { return false; } From 4c38ab1de67d7fa0a222453d884d52e9c8d04bda Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Tue, 4 Dec 2018 16:59:42 +1100 Subject: [PATCH 3/6] Address review feedback avoid use of `NetworkUtili#getServerPort()` function which does not correctly provide a random available port. --- .../authc/kerberos/SimpleKdcLdapServer.java | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java index a112236122bb0..7a53c4bcc4c8b 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java @@ -13,7 +13,6 @@ import org.apache.kerby.kerberos.kerb.client.KrbConfig; import org.apache.kerby.kerberos.kerb.server.KdcConfigKey; import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer; -import org.apache.kerby.util.NetworkUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.ExceptionsHelper; @@ -132,18 +131,10 @@ private void prepareKdcServerAndStart() throws Exception { simpleKdc.setWorkDir(workDir.toFile()); simpleKdc.setKdcHost(host); simpleKdc.setKdcRealm(realm); - if (kdcPort == 0) { - kdcPort = NetworkUtil.getServerPort(); - int tries = 0; - while (isPortAvailable(kdcPort, transport) == false) { - if (tries > 100) { - throw new IllegalArgumentException("Could not find available port for KDC server"); - } - kdcPort = NetworkUtil.getServerPort(); - tries++; - } - } if (transport != null) { + if (kdcPort == 0) { + kdcPort = randomServerPort(transport); + } if (transport.trim().equals("TCP")) { simpleKdc.setKdcTcpPort(kdcPort); simpleKdc.setAllowUdp(false); @@ -234,7 +225,19 @@ public Void run() throws Exception { logger.info("SimpleKdcServer stoppped."); } - private boolean isPortAvailable(int port, String transport) { + private static int randomServerPort(String transport) { + int tries = 0; + int port = -1; + do { + if (tries > 100) { + throw new IllegalArgumentException("Could not find available port for KDC server"); + } + port = ESTestCase.randomIntBetween(1024, 65535); + } while (isPortAvailable(port, transport) == false); + return port; + } + + private static boolean isPortAvailable(int port, String transport) { if (transport != null && transport.trim().equalsIgnoreCase("tcp")) { try (ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("127.0.0.1"))) { From 0420cef3a74ff692b1886cc4bd3b2cde6be63a66 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Tue, 4 Dec 2018 17:07:18 +1100 Subject: [PATCH 4/6] Fix the logic --- .../xpack/security/authc/kerberos/SimpleKdcLdapServer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java index 7a53c4bcc4c8b..7df218daa77d7 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java @@ -233,6 +233,7 @@ private static int randomServerPort(String transport) { throw new IllegalArgumentException("Could not find available port for KDC server"); } port = ESTestCase.randomIntBetween(1024, 65535); + tries++; } while (isPortAvailable(port, transport) == false); return port; } From 38978bd3febc6f57d9a7a73fa18c0475d2fa2461 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Tue, 4 Dec 2018 18:08:24 +1100 Subject: [PATCH 5/6] Let ServerSocket/DatagramSocket choose right port for TCP/UDP --- .../authc/kerberos/SimpleKdcLdapServer.java | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java index 7df218daa77d7..ec39b6259702d 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java @@ -133,7 +133,7 @@ private void prepareKdcServerAndStart() throws Exception { simpleKdc.setKdcRealm(realm); if (transport != null) { if (kdcPort == 0) { - kdcPort = randomServerPort(transport); + kdcPort = getServerPort(transport); } if (transport.trim().equals("TCP")) { simpleKdc.setKdcTcpPort(kdcPort); @@ -225,34 +225,21 @@ public Void run() throws Exception { logger.info("SimpleKdcServer stoppped."); } - private static int randomServerPort(String transport) { - int tries = 0; - int port = -1; - do { - if (tries > 100) { - throw new IllegalArgumentException("Could not find available port for KDC server"); - } - port = ESTestCase.randomIntBetween(1024, 65535); - tries++; - } while (isPortAvailable(port, transport) == false); - return port; - } - - private static boolean isPortAvailable(int port, String transport) { + private static int getServerPort(String transport) { if (transport != null && transport.trim().equalsIgnoreCase("tcp")) { - try (ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(port, 1, + try (ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(0, 1, InetAddress.getByName("127.0.0.1"))) { - return serverSocket.isBound(); + return serverSocket.getLocalPort(); } catch (Exception ex) { - return false; + throw new RuntimeException("Failed to get a tcp server socket point"); } } else if (transport != null && transport.trim().equalsIgnoreCase("udp")) { - try (DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("127.0.0.1"))) { - return socket.isBound(); + try (DatagramSocket socket = new DatagramSocket(0, InetAddress.getByName("127.0.0.1"))) { + return socket.getLocalPort(); } catch (Exception ex) { - return false; + throw new RuntimeException("Failed to get a udp server socket point"); } } - return false; + throw new IllegalArgumentException("Invalid transport: " + transport); } } From fcf1037872d29825edeb3578866897498dd6efb5 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Tue, 4 Dec 2018 18:15:13 +1100 Subject: [PATCH 6/6] Add case insensitive check at all places. --- .../security/authc/kerberos/SimpleKdcLdapServer.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java index ec39b6259702d..8888ce33be57f 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java @@ -135,10 +135,10 @@ private void prepareKdcServerAndStart() throws Exception { if (kdcPort == 0) { kdcPort = getServerPort(transport); } - if (transport.trim().equals("TCP")) { + if (transport.trim().equalsIgnoreCase("TCP")) { simpleKdc.setKdcTcpPort(kdcPort); simpleKdc.setAllowUdp(false); - } else if (transport.trim().equals("UDP")) { + } else if (transport.trim().equalsIgnoreCase("UDP")) { simpleKdc.setKdcUdpPort(kdcPort); simpleKdc.setAllowTcp(false); } else { @@ -226,18 +226,18 @@ public Void run() throws Exception { } private static int getServerPort(String transport) { - if (transport != null && transport.trim().equalsIgnoreCase("tcp")) { + if (transport != null && transport.trim().equalsIgnoreCase("TCP")) { try (ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(0, 1, InetAddress.getByName("127.0.0.1"))) { return serverSocket.getLocalPort(); } catch (Exception ex) { - throw new RuntimeException("Failed to get a tcp server socket point"); + throw new RuntimeException("Failed to get a TCP server socket point"); } - } else if (transport != null && transport.trim().equalsIgnoreCase("udp")) { + } else if (transport != null && transport.trim().equalsIgnoreCase("UDP")) { try (DatagramSocket socket = new DatagramSocket(0, InetAddress.getByName("127.0.0.1"))) { return socket.getLocalPort(); } catch (Exception ex) { - throw new RuntimeException("Failed to get a udp server socket point"); + throw new RuntimeException("Failed to get a UDP server socket point"); } } throw new IllegalArgumentException("Invalid transport: " + transport);