SSL handshake hangs on slow connection
826883Dec 27 2010 — edited Jan 20 2011I tried posting this question on the Spring/Acegi security forums with no luck, so maybe I'll have better luck here.
We are using Acegi Security to connect to a LDAP server for our application. Recently, the LDAP server was overloaded, and I expected the app to throw a connection timeout error so that Acegi could attempt to connect to our failover LDAP server. Instead, we saw the app hang.
To repro the scenario, I am using 'redir' to simulate a slow connection to the LDAP server (redir lport=3890 cport=389 caddr=lab-ldap.lab random_wait=8000 bufsize=16, redir lport=6360 cport=636 caddr=lab-ldap.lab random_wait=8000 bufsize=16).
When I start the app using ldap url "ldaps://localhost:6360/dc=company,dc=com", I experience a hang after the Socket has been opened and connected to, but before an attempted read. It appears to hang during the handshake. However, when I use the insecure url "ldap://localhost:3890/dc=company,dc=com)", I see a message in the console about a read timeout. I have a connect and read timeout configured to 5000ms. Is there another timeout I need to specify? Am I missing something here?
Here is the main class that I've been using to test:
public static void main(String[] args) {
Hashtable env = new Hashtable();
env.put("java.naming.provider.url", "ldaps://localhost:6360/dc=company,dc=com");
env.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
env.put("com.sun.jndi.ldap.connect.timeout", "5000");
env.put("java.naming.security.principal", "uid=user,ou=people,dc=company,dc=com");
env.put("java.naming.security.authentication", "simple");
env.put("java.naming.security.credentials", "password");
env.put("com.sun.jndi.ldap.read.timeout", "5000");
env.put("com.sun.jndi.ldap.trace.ber", System.out);
env.put("com.sun.jndi.ldap.connect.pool", "true");
try {
// Create initial context
DirContext ctx = new InitialDirContext(env);
System.out.println("LDAP Client: Connected to the Server");
} catch (Exception e) {
e.printStackTrace();
}
}
Here is the stack I pulled from the app during the hang:
at java.net.SocketInputStream.socketRead0(SocketInputStream.java:-1)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
at com.sun.net.ssl.internal.ssl.InputRecord.readV3Record(InputRecord.java:405)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:357)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1,138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:632)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at com.sun.jndi.ldap.Connection.writeRequest(Connection.java:396)
at com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:334)
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:192)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2,694)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:293)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.InitialContext.<init>(InitialContext.java:197)
at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:82)
Any help would be appreciated!