Skip to content

Commit 61a4127

Browse files
committedOct 3, 2024
8251188: Update LDAP tests not to use wildcard addresses
Reviewed-by: yan, mbalao, andrew Backport-of: a75edc29c6ce41116cc99530aa1710efb62c6d5a
1 parent b4264bc commit 61a4127

File tree

5 files changed

+258
-69
lines changed

5 files changed

+258
-69
lines changed
 

‎jdk/test/com/sun/jndi/ldap/BalancedParentheses.java

+20-3
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,23 @@
2424
/**
2525
* @test
2626
* @bug 6449574
27+
* @library /lib/testlibrary
2728
* @summary Invalid ldap filter is accepted and processed
2829
*/
2930

3031
import java.io.*;
3132
import javax.naming.*;
3233
import javax.naming.directory.*;
33-
import java.util.Properties;
34+
import java.net.InetAddress;
35+
import java.net.InetSocketAddress;
36+
import java.net.SocketAddress;
3437
import java.util.Hashtable;
3538

3639
import java.net.Socket;
3740
import java.net.ServerSocket;
3841

42+
import jdk.testlibrary.net.URIBuilder;
43+
3944
public class BalancedParentheses {
4045
// Should we run the client or server in a separate thread?
4146
//
@@ -54,7 +59,13 @@ public class BalancedParentheses {
5459
// If the server prematurely exits, serverReady will be set to true
5560
// to avoid infinite hangs.
5661
void doServerSide() throws Exception {
57-
ServerSocket serverSock = new ServerSocket(serverPort);
62+
// Create unbound server socket
63+
ServerSocket serverSock = new ServerSocket();
64+
65+
// And bind it to the loopback address
66+
SocketAddress sockAddr = new InetSocketAddress(
67+
InetAddress.getLoopbackAddress(), 0);
68+
serverSock.bind(sockAddr);
5869

5970
// signal client, it's ready to accecpt connection
6071
serverPort = serverSock.getLocalPort();
@@ -106,7 +117,13 @@ void doClientSide() throws Exception {
106117
Hashtable<Object, Object> env = new Hashtable<Object, Object>();
107118
env.put(Context.INITIAL_CONTEXT_FACTORY,
108119
"com.sun.jndi.ldap.LdapCtxFactory");
109-
env.put(Context.PROVIDER_URL, "ldap://localhost:" + serverPort);
120+
// Construct the provider URL
121+
String providerURL = URIBuilder.newBuilder()
122+
.scheme("ldap")
123+
.loopback()
124+
.port(serverPort)
125+
.build().toString();
126+
env.put(Context.PROVIDER_URL, providerURL);
110127
env.put("com.sun.jndi.ldap.read.timeout", "1000");
111128

112129
// env.put(Context.SECURITY_AUTHENTICATION, "simple");

‎jdk/test/com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java

+113-57
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,35 @@
2121
* questions.
2222
*/
2323

24-
/**
24+
/*
2525
* @test
26-
* @run main/othervm DeadSSLLdapTimeoutTest
2726
* @bug 8141370
2827
* @key intermittent
28+
* @library /lib/testlibrary
29+
* @build DeadSSLSocketFactory
30+
* @run main/othervm DeadSSLLdapTimeoutTest
2931
*/
3032

31-
import java.net.Socket;
33+
import java.io.EOFException;
34+
import java.io.IOException;
35+
import java.net.InetAddress;
36+
import java.net.InetSocketAddress;
3237
import java.net.ServerSocket;
38+
import java.net.Socket;
39+
import java.net.SocketAddress;
3340
import java.net.SocketTimeoutException;
34-
import java.io.*;
35-
import javax.naming.*;
36-
import javax.naming.directory.*;
37-
import java.util.List;
41+
import javax.naming.Context;
42+
import javax.naming.InitialContext;
43+
import javax.naming.NamingException;
3844
import java.util.Hashtable;
39-
import java.util.ArrayList;
4045
import java.util.concurrent.Callable;
41-
import java.util.concurrent.ExecutionException;
42-
import java.util.concurrent.Executors;
43-
import java.util.concurrent.ExecutorService;
44-
import java.util.concurrent.Future;
45-
import java.util.concurrent.ScheduledExecutorService;
46-
import java.util.concurrent.ScheduledFuture;
47-
import java.util.concurrent.TimeoutException;
46+
import java.util.concurrent.CountDownLatch;
4847
import java.util.concurrent.TimeUnit;
48+
import javax.naming.directory.InitialDirContext;
4949
import javax.net.ssl.SSLHandshakeException;
5050

51-
import static java.util.concurrent.TimeUnit.MILLISECONDS;
51+
import jdk.testlibrary.net.URIBuilder;
52+
5253
import static java.util.concurrent.TimeUnit.NANOSECONDS;
5354

5455

@@ -57,26 +58,26 @@ class DeadServerTimeoutSSLTest implements Callable {
5758
Hashtable env;
5859
DeadSSLServer server;
5960
boolean passed = false;
60-
private int HANGING_TEST_TIMEOUT = 20_000;
6161

6262
public DeadServerTimeoutSSLTest(Hashtable env) throws IOException {
63-
this.server = new DeadSSLServer();
63+
SocketAddress sockAddr = new InetSocketAddress(
64+
InetAddress.getLoopbackAddress(), 0);
65+
this.server = new DeadSSLServer(sockAddr);
6466
this.env = env;
6567
}
6668

67-
public void performOp(InitialContext ctx) throws NamingException {}
68-
69-
public void handleNamingException(NamingException e, long start, long end) {
69+
public void handleNamingException(NamingException e) {
7070
if (e.getCause() instanceof SocketTimeoutException
7171
|| e.getCause().getCause() instanceof SocketTimeoutException) {
7272
// SSL connect will timeout via readReply using
7373
// SocketTimeoutException
74-
e.printStackTrace();
74+
System.out.println("PASS: Observed expected SocketTimeoutException");
7575
pass();
7676
} else if (e.getCause() instanceof SSLHandshakeException
7777
&& e.getCause().getCause() instanceof EOFException) {
7878
// test seems to be failing intermittently on some
7979
// platforms.
80+
System.out.println("PASS: Observed expected SSLHandshakeException/EOFException");
8081
pass();
8182
} else {
8283
fail(e);
@@ -92,6 +93,7 @@ public void fail() {
9293
}
9394

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

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

107109
public Boolean call() {
108110
InitialContext ctx = null;
109-
ScheduledFuture killer = null;
110-
long start = System.nanoTime();
111111

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

117-
env.put(Context.PROVIDER_URL, "ldap://localhost:" +
118-
server.getLocalPort());
116+
env.put(Context.PROVIDER_URL,
117+
URIBuilder.newBuilder()
118+
.scheme("ldap")
119+
.loopback()
120+
.port(server.getLocalPort())
121+
.buildUnchecked().toString()
122+
);
119123

124+
long start = System.nanoTime();
120125
try {
121126
ctx = new InitialDirContext(env);
122-
performOp(ctx);
123127
fail();
124128
} catch (NamingException e) {
125129
long end = System.nanoTime();
126130
System.out.println(this.getClass().toString() + " - elapsed: "
127131
+ NANOSECONDS.toMillis(end - start));
128-
handleNamingException(e, start, end);
132+
handleNamingException(e);
129133
} finally {
130-
if (killer != null && !killer.isDone())
131-
killer.cancel(true);
134+
// Stop the server side thread
135+
server.testDone.countDown();
132136
shutItDown(ctx);
133137
server.close();
134138
}
135139
return passed;
136-
} catch (IOException|InterruptedException e) {
140+
} catch (IOException | InterruptedException e) {
137141
throw new RuntimeException(e);
138142
}
139143
}
140144
}
141145

142146
class DeadSSLServer extends Thread {
143147
ServerSocket serverSock;
144-
boolean accepting = false;
145-
146-
public DeadSSLServer() throws IOException {
147-
this.serverSock = new ServerSocket(0);
148+
// Latch to be used by client to wait for server to start
149+
CountDownLatch serverStarted = new CountDownLatch(1);
150+
151+
// Latch to be used by server thread to wait for client to finish testing
152+
CountDownLatch testDone = new CountDownLatch(1);
153+
154+
public DeadSSLServer(SocketAddress socketAddress) throws IOException {
155+
// create unbound server socket
156+
ServerSocket srvSock = new ServerSocket();
157+
// bind it to the address provided
158+
srvSock.bind(socketAddress);
159+
this.serverSock = srvSock;
148160
start();
149161
}
150162

151163
public void run() {
152-
while(true) {
153-
try {
154-
accepting = true;
155-
Socket socket = serverSock.accept();
164+
// Signal client to proceed with the test
165+
serverStarted.countDown();
166+
while (true) {
167+
try (Socket acceptedSocket = serverSock.accept()) {
168+
System.err.println("Accepted connection:" + acceptedSocket);
169+
int iteration = 0;
170+
// Wait for socket to get opened by DeadSSLSocketFactory and connected to the test server
171+
while (iteration++ < 20) {
172+
if (DeadSSLSocketFactory.firstCreatedSocket.get() != null &&
173+
DeadSSLSocketFactory.firstCreatedSocket.get().isConnected()) {
174+
break;
175+
}
176+
try {
177+
TimeUnit.MILLISECONDS.sleep(50);
178+
} catch (InterruptedException ie) {
179+
}
180+
}
181+
Socket clientSideSocket = DeadSSLSocketFactory.firstCreatedSocket.get();
182+
System.err.printf("Got SSLSocketFactory connection after %d iterations: %s%n",
183+
iteration, clientSideSocket);
184+
185+
if (clientSideSocket == null || !clientSideSocket.isConnected()) {
186+
// If after 1000 ms client side connection is not opened - probably other local process
187+
// tried to connect to the test server socket. Close current connection and retry accept.
188+
continue;
189+
} else {
190+
// Check if accepted socket is connected to the LDAP client
191+
if (acceptedSocket.getLocalPort() == clientSideSocket.getPort() &&
192+
acceptedSocket.getPort() == clientSideSocket.getLocalPort() &&
193+
acceptedSocket.getInetAddress().equals(clientSideSocket.getLocalAddress())) {
194+
System.err.println("Accepted connection is originated from LDAP client:" + acceptedSocket);
195+
try {
196+
// Give LDAP client time to fully establish the connection.
197+
// When client is done - the accepted socket will be closed
198+
testDone.await();
199+
} catch (InterruptedException e) {
200+
}
201+
break;
202+
} else {
203+
// If accepted socket is not from the LDAP client - the accepted connection will be closed and new
204+
// one will be accepted
205+
System.err.println("SSLSocketFactory connection has been established, but originated not from" +
206+
" the test's LDAP client:" + acceptedSocket);
207+
}
208+
}
156209
} catch (Exception e) {
157-
break;
210+
System.err.println("Server socket. Failure to accept connection:" + e.getMessage());
158211
}
159212
}
160213
}
@@ -163,28 +216,26 @@ public int getLocalPort() {
163216
return serverSock.getLocalPort();
164217
}
165218

166-
public boolean accepting() {
167-
return accepting;
168-
}
169-
170219
public void close() throws IOException {
171220
serverSock.close();
172221
}
173222
}
174223

175224
public class DeadSSLLdapTimeoutTest {
225+
// com.sun.jndi.ldap.connect.timeout value to set
226+
static final String CONNECT_TIMEOUT_MS = "10";
227+
228+
// com.sun.jndi.ldap.read.timeout value to set
229+
static final String READ_TIMEOUT_MS = "3000";
176230

177231
static Hashtable createEnv() {
178232
Hashtable env = new Hashtable(11);
179233
env.put(Context.INITIAL_CONTEXT_FACTORY,
180-
"com.sun.jndi.ldap.LdapCtxFactory");
234+
"com.sun.jndi.ldap.LdapCtxFactory");
181235
return env;
182236
}
183237

184238
public static void main(String[] args) throws Exception {
185-
186-
InitialContext ctx = null;
187-
188239
//
189240
// Running this test serially as it seems to tickle a problem
190241
// on older kernels
@@ -193,19 +244,24 @@ public static void main(String[] args) throws Exception {
193244
// and ssl enabled
194245
// this should exit with a SocketTimeoutException as the root cause
195246
// it should also use the connect timeout instead of the read timeout
196-
System.out.println("Running connect timeout test with 10ms connect timeout, 3000ms read timeout & SSL");
247+
System.out.printf("Running connect timeout test with %sms connect timeout," +
248+
" %sms read timeout & SSL%n",
249+
CONNECT_TIMEOUT_MS, READ_TIMEOUT_MS);
250+
197251
Hashtable sslenv = createEnv();
198-
sslenv.put("com.sun.jndi.ldap.connect.timeout", "10");
199-
sslenv.put("com.sun.jndi.ldap.read.timeout", "3000");
252+
// Setup connect timeout environment property
253+
sslenv.put("com.sun.jndi.ldap.connect.timeout", CONNECT_TIMEOUT_MS);
254+
// Setup read timeout environment property
255+
sslenv.put("com.sun.jndi.ldap.read.timeout", READ_TIMEOUT_MS);
256+
// Setup DeadSSLSocketFactory to track the client's first LDAP connection
257+
sslenv.put("java.naming.ldap.factory.socket", "DeadSSLSocketFactory");
258+
// Use SSL protocol
200259
sslenv.put(Context.SECURITY_PROTOCOL, "ssl");
201-
boolean testFailed =
202-
(new DeadServerTimeoutSSLTest(sslenv).call()) ? false : true;
203260

261+
boolean testFailed = !new DeadServerTimeoutSSLTest(sslenv).call();
204262
if (testFailed) {
205263
throw new AssertionError("some tests failed");
206264
}
207-
208265
}
209-
210266
}
211267

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import javax.net.SocketFactory;
25+
import javax.net.ssl.SSLSocket;
26+
import javax.net.ssl.SSLSocketFactory;
27+
import java.io.IOException;
28+
import java.net.InetAddress;
29+
import java.net.Socket;
30+
import java.util.concurrent.atomic.AtomicBoolean;
31+
import java.util.concurrent.atomic.AtomicReference;
32+
33+
/*
34+
* A custom socket factory used to override the default socket factory and track the LDAP client connection.
35+
* Factory can create only one SSLSocket. See the DeadServerTimeoutSSLTest test.
36+
*/
37+
public class DeadSSLSocketFactory extends SocketFactory {
38+
// Client socket that is used by LDAP connection
39+
public static AtomicReference<SSLSocket> firstCreatedSocket = new AtomicReference<>();
40+
41+
// Boolean to track if connection socket has been opened
42+
public static AtomicBoolean isConnectionOpened = new AtomicBoolean(false);
43+
44+
// Default SSLSocketFactory that will be used for SSL socket creation
45+
final SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
46+
47+
// Create unconnected socket
48+
public Socket createSocket() throws IOException {
49+
if (!isConnectionOpened.getAndSet(true)) {
50+
System.err.println("DeadSSLSocketFactory: Creating unconnected socket");
51+
firstCreatedSocket.set((SSLSocket) factory.createSocket());
52+
return firstCreatedSocket.get();
53+
} else {
54+
throw new RuntimeException("DeadSSLSocketFactory only allows creation of one SSL socket");
55+
}
56+
}
57+
58+
public DeadSSLSocketFactory() {
59+
System.err.println("DeadSSLSocketFactory: Constructor call");
60+
}
61+
62+
public static SocketFactory getDefault() {
63+
System.err.println("DeadSSLSocketFactory: acquiring DeadSSLSocketFactory as default socket factory");
64+
return new DeadSSLSocketFactory();
65+
}
66+
67+
@Override
68+
public Socket createSocket(String host, int port) throws IOException {
69+
// Not used by DeadSSLLdapTimeoutTest
70+
return factory.createSocket(host, port);
71+
}
72+
73+
@Override
74+
public Socket createSocket(String host, int port, InetAddress localHost,
75+
int localPort) throws IOException {
76+
// Not used by DeadSSLLdapTimeoutTest
77+
return factory.createSocket(host, port, localHost, localPort);
78+
}
79+
80+
@Override
81+
public Socket createSocket(InetAddress host, int port) throws IOException {
82+
// Not used by DeadSSLLdapTimeoutTest
83+
return factory.createSocket(host, port);
84+
}
85+
86+
@Override
87+
public Socket createSocket(InetAddress address, int port,
88+
InetAddress localAddress, int localPort) throws IOException {
89+
// Not used by DeadSSLLdapTimeoutTest
90+
return factory.createSocket(address, port, localAddress, localPort);
91+
}
92+
}
93+

‎jdk/test/com/sun/jndi/ldap/blits/AddTests/AddNewEntry.java

+21-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* @bug 8196770
2727
* @summary Verify capability to add a new entry to the directory using the
2828
* ADD operation.
29-
* @library ../../lib/
29+
* @library /lib/testlibrary ../../lib/
3030
* @build LDAPServer LDAPTestUtils
3131
* @run main/othervm AddNewEntry
3232
*/
@@ -39,19 +39,36 @@
3939
import javax.naming.directory.DirContext;
4040
import javax.naming.directory.InitialDirContext;
4141
import javax.naming.directory.SearchControls;
42+
import java.net.InetAddress;
43+
import java.net.InetSocketAddress;
4244
import java.net.ServerSocket;
45+
import java.net.SocketAddress;
4346
import java.util.Hashtable;
47+
import jdk.testlibrary.net.URIBuilder;
4448

4549
public class AddNewEntry {
4650

4751
public static void main(String[] args) throws Exception {
48-
ServerSocket serverSocket = new ServerSocket(0);
52+
// Create unbound server socket
53+
ServerSocket serverSocket = new ServerSocket();
54+
55+
// Bind it to the loopback address
56+
SocketAddress sockAddr = new InetSocketAddress(
57+
InetAddress.getLoopbackAddress(), 0);
58+
serverSocket.bind(sockAddr);
59+
60+
// Construct the provider URL for LDAPTestUtils
61+
String providerURL = URIBuilder.newBuilder()
62+
.scheme("ldap")
63+
.loopback()
64+
.port(serverSocket.getLocalPort())
65+
.buildUnchecked().toString();
4966

5067
Hashtable<Object, Object> env;
5168

5269
// initialize test
53-
env = LDAPTestUtils
54-
.initEnv(serverSocket, AddNewEntry.class.getName(), args, true);
70+
env = LDAPTestUtils.initEnv(serverSocket, providerURL,
71+
AddNewEntry.class.getName(), args, true);
5572

5673
/* Build attribute set */
5774
String[] ids = { "objectClass", "sn", "cn", "telephoneNumber", "mail",

‎jdk/test/com/sun/jndi/ldap/lib/LDAPTestUtils.java

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -50,12 +50,17 @@ public class LDAPTestUtils {
5050
* Process command line arguments and return properties in a Hashtable.
5151
*/
5252
public static Hashtable<Object, Object> initEnv(String testname,
53-
String[] args) {
53+
String[] args) {
5454
return initEnv(null, testname, args, false);
5555
}
5656

5757
public static Hashtable<Object, Object> initEnv(ServerSocket socket,
58-
String testname, String[] args, boolean authInfo) {
58+
String testname, String[] args, boolean authInfo) {
59+
return initEnv(socket, null, testname, args, authInfo);
60+
}
61+
62+
public static Hashtable<Object, Object> initEnv(ServerSocket socket, String providerUrl,
63+
String testname, String[] args, boolean authInfo) {
5964

6065
Hashtable<Object, Object> env = new Hashtable<>();
6166
String root = "o=IMC,c=US";
@@ -103,8 +108,9 @@ public static Hashtable<Object, Object> initEnv(ServerSocket socket,
103108
if (socket != null) {
104109
env.put(TEST_LDAP_SERVER_THREAD,
105110
startLDAPServer(socket, getCaptureFile(testname)));
106-
env.put("java.naming.provider.url",
107-
"ldap://localhost:" + socket.getLocalPort());
111+
String url = providerUrl != null ? providerUrl :
112+
"ldap://localhost:" + socket.getLocalPort();
113+
env.put("java.naming.provider.url", url);
108114
} else {
109115
// for tests which run against remote server or no server
110116
// required

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Oct 3, 2024

@openjdk-notifier[bot]
Please sign in to comment.