Skip to content

Commit

Permalink
8251188: Update LDAP tests not to use wildcard addresses
Browse files Browse the repository at this point in the history
Reviewed-by: yan, mbalao, andrew
Backport-of: a75edc29c6ce41116cc99530aa1710efb62c6d5a
  • Loading branch information
mrserb authored and gnu-andrew committed Oct 4, 2024
1 parent 9e795b5 commit 672104d
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 69 deletions.
23 changes: 20 additions & 3 deletions jdk/test/com/sun/jndi/ldap/BalancedParentheses.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,23 @@
/**
* @test
* @bug 6449574
* @library /lib/testlibrary
* @summary Invalid ldap filter is accepted and processed
*/

import java.io.*;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Properties;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Hashtable;

import java.net.Socket;
import java.net.ServerSocket;

import jdk.testlibrary.net.URIBuilder;

public class BalancedParentheses {
// Should we run the client or server in a separate thread?
//
Expand All @@ -54,7 +59,13 @@ public class BalancedParentheses {
// If the server prematurely exits, serverReady will be set to true
// to avoid infinite hangs.
void doServerSide() throws Exception {
ServerSocket serverSock = new ServerSocket(serverPort);
// Create unbound server socket
ServerSocket serverSock = new ServerSocket();

// And bind it to the loopback address
SocketAddress sockAddr = new InetSocketAddress(
InetAddress.getLoopbackAddress(), 0);
serverSock.bind(sockAddr);

// signal client, it's ready to accecpt connection
serverPort = serverSock.getLocalPort();
Expand Down Expand Up @@ -106,7 +117,13 @@ void doClientSide() throws Exception {
Hashtable<Object, Object> env = new Hashtable<Object, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:" + serverPort);
// Construct the provider URL
String providerURL = URIBuilder.newBuilder()
.scheme("ldap")
.loopback()
.port(serverPort)
.build().toString();
env.put(Context.PROVIDER_URL, providerURL);
env.put("com.sun.jndi.ldap.read.timeout", "1000");

// env.put(Context.SECURITY_AUTHENTICATION, "simple");
Expand Down
170 changes: 113 additions & 57 deletions jdk/test/com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,35 @@
* questions.
*/

/**
/*
* @test
* @run main/othervm DeadSSLLdapTimeoutTest
* @bug 8141370
* @key intermittent
* @library /lib/testlibrary
* @build DeadSSLSocketFactory
* @run main/othervm DeadSSLLdapTimeoutTest
*/

import java.net.Socket;
import java.io.EOFException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.io.*;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.naming.directory.InitialDirContext;
import javax.net.ssl.SSLHandshakeException;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import jdk.testlibrary.net.URIBuilder;

import static java.util.concurrent.TimeUnit.NANOSECONDS;


Expand All @@ -57,26 +58,26 @@ class DeadServerTimeoutSSLTest implements Callable {
Hashtable env;
DeadSSLServer server;
boolean passed = false;
private int HANGING_TEST_TIMEOUT = 20_000;

public DeadServerTimeoutSSLTest(Hashtable env) throws IOException {
this.server = new DeadSSLServer();
SocketAddress sockAddr = new InetSocketAddress(
InetAddress.getLoopbackAddress(), 0);
this.server = new DeadSSLServer(sockAddr);
this.env = env;
}

public void performOp(InitialContext ctx) throws NamingException {}

public void handleNamingException(NamingException e, long start, long end) {
public void handleNamingException(NamingException e) {
if (e.getCause() instanceof SocketTimeoutException
|| e.getCause().getCause() instanceof SocketTimeoutException) {
// SSL connect will timeout via readReply using
// SocketTimeoutException
e.printStackTrace();
System.out.println("PASS: Observed expected SocketTimeoutException");
pass();
} else if (e.getCause() instanceof SSLHandshakeException
&& e.getCause().getCause() instanceof EOFException) {
// test seems to be failing intermittently on some
// platforms.
System.out.println("PASS: Observed expected SSLHandshakeException/EOFException");
pass();
} else {
fail(e);
Expand All @@ -92,6 +93,7 @@ public void fail() {
}

public void fail(Exception e) {
System.err.println("FAIL: Unexpected exception was observed:" + e.getMessage());
throw new RuntimeException("Test failed", e);
}

Expand All @@ -106,55 +108,106 @@ boolean shutItDown(InitialContext ctx) {

public Boolean call() {
InitialContext ctx = null;
ScheduledFuture killer = null;
long start = System.nanoTime();

try {
while(!server.accepting())
Thread.sleep(200); // allow the server to start up
server.serverStarted.await(); // Wait for the server to start-up
Thread.sleep(200); // to be sure

env.put(Context.PROVIDER_URL, "ldap://localhost:" +
server.getLocalPort());
env.put(Context.PROVIDER_URL,
URIBuilder.newBuilder()
.scheme("ldap")
.loopback()
.port(server.getLocalPort())
.buildUnchecked().toString()
);

long start = System.nanoTime();
try {
ctx = new InitialDirContext(env);
performOp(ctx);
fail();
} catch (NamingException e) {
long end = System.nanoTime();
System.out.println(this.getClass().toString() + " - elapsed: "
+ NANOSECONDS.toMillis(end - start));
handleNamingException(e, start, end);
handleNamingException(e);
} finally {
if (killer != null && !killer.isDone())
killer.cancel(true);
// Stop the server side thread
server.testDone.countDown();
shutItDown(ctx);
server.close();
}
return passed;
} catch (IOException|InterruptedException e) {
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}

class DeadSSLServer extends Thread {
ServerSocket serverSock;
boolean accepting = false;

public DeadSSLServer() throws IOException {
this.serverSock = new ServerSocket(0);
// Latch to be used by client to wait for server to start
CountDownLatch serverStarted = new CountDownLatch(1);

// Latch to be used by server thread to wait for client to finish testing
CountDownLatch testDone = new CountDownLatch(1);

public DeadSSLServer(SocketAddress socketAddress) throws IOException {
// create unbound server socket
ServerSocket srvSock = new ServerSocket();
// bind it to the address provided
srvSock.bind(socketAddress);
this.serverSock = srvSock;
start();
}

public void run() {
while(true) {
try {
accepting = true;
Socket socket = serverSock.accept();
// Signal client to proceed with the test
serverStarted.countDown();
while (true) {
try (Socket acceptedSocket = serverSock.accept()) {
System.err.println("Accepted connection:" + acceptedSocket);
int iteration = 0;
// Wait for socket to get opened by DeadSSLSocketFactory and connected to the test server
while (iteration++ < 20) {
if (DeadSSLSocketFactory.firstCreatedSocket.get() != null &&
DeadSSLSocketFactory.firstCreatedSocket.get().isConnected()) {
break;
}
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException ie) {
}
}
Socket clientSideSocket = DeadSSLSocketFactory.firstCreatedSocket.get();
System.err.printf("Got SSLSocketFactory connection after %d iterations: %s%n",
iteration, clientSideSocket);

if (clientSideSocket == null || !clientSideSocket.isConnected()) {
// If after 1000 ms client side connection is not opened - probably other local process
// tried to connect to the test server socket. Close current connection and retry accept.
continue;
} else {
// Check if accepted socket is connected to the LDAP client
if (acceptedSocket.getLocalPort() == clientSideSocket.getPort() &&
acceptedSocket.getPort() == clientSideSocket.getLocalPort() &&
acceptedSocket.getInetAddress().equals(clientSideSocket.getLocalAddress())) {
System.err.println("Accepted connection is originated from LDAP client:" + acceptedSocket);
try {
// Give LDAP client time to fully establish the connection.
// When client is done - the accepted socket will be closed
testDone.await();
} catch (InterruptedException e) {
}
break;
} else {
// If accepted socket is not from the LDAP client - the accepted connection will be closed and new
// one will be accepted
System.err.println("SSLSocketFactory connection has been established, but originated not from" +
" the test's LDAP client:" + acceptedSocket);
}
}
} catch (Exception e) {
break;
System.err.println("Server socket. Failure to accept connection:" + e.getMessage());
}
}
}
Expand All @@ -163,28 +216,26 @@ public int getLocalPort() {
return serverSock.getLocalPort();
}

public boolean accepting() {
return accepting;
}

public void close() throws IOException {
serverSock.close();
}
}

public class DeadSSLLdapTimeoutTest {
// com.sun.jndi.ldap.connect.timeout value to set
static final String CONNECT_TIMEOUT_MS = "10";

// com.sun.jndi.ldap.read.timeout value to set
static final String READ_TIMEOUT_MS = "3000";

static Hashtable createEnv() {
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
"com.sun.jndi.ldap.LdapCtxFactory");
return env;
}

public static void main(String[] args) throws Exception {

InitialContext ctx = null;

//
// Running this test serially as it seems to tickle a problem
// on older kernels
Expand All @@ -193,19 +244,24 @@ public static void main(String[] args) throws Exception {
// and ssl enabled
// this should exit with a SocketTimeoutException as the root cause
// it should also use the connect timeout instead of the read timeout
System.out.println("Running connect timeout test with 10ms connect timeout, 3000ms read timeout & SSL");
System.out.printf("Running connect timeout test with %sms connect timeout," +
" %sms read timeout & SSL%n",
CONNECT_TIMEOUT_MS, READ_TIMEOUT_MS);

Hashtable sslenv = createEnv();
sslenv.put("com.sun.jndi.ldap.connect.timeout", "10");
sslenv.put("com.sun.jndi.ldap.read.timeout", "3000");
// Setup connect timeout environment property
sslenv.put("com.sun.jndi.ldap.connect.timeout", CONNECT_TIMEOUT_MS);
// Setup read timeout environment property
sslenv.put("com.sun.jndi.ldap.read.timeout", READ_TIMEOUT_MS);
// Setup DeadSSLSocketFactory to track the client's first LDAP connection
sslenv.put("java.naming.ldap.factory.socket", "DeadSSLSocketFactory");
// Use SSL protocol
sslenv.put(Context.SECURITY_PROTOCOL, "ssl");
boolean testFailed =
(new DeadServerTimeoutSSLTest(sslenv).call()) ? false : true;

boolean testFailed = !new DeadServerTimeoutSSLTest(sslenv).call();
if (testFailed) {
throw new AssertionError("some tests failed");
}

}

}

Loading

0 comments on commit 672104d

Please sign in to comment.