8

Good evening,

I have been facing this error for a couple of days by now, and despite looking for a solution all over the web, I coul'd fix this error.

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public class LDAPtest {
public static void main(String[] args) {
    
    try {
        
        String keystorePath = "C:/Program Files/Java/jdk-13.0.2/lib/security/cacerts";
        System.setProperty("javax.net.ssl.keyStore", keystorePath);
         
        System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
        
        Hashtable<String, String> ldapEnv = new Hashtable<>(); 
        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        ldapEnv.put(Context.PROVIDER_URL, "ldaps://localhost:10636");
        ldapEnv.put(Context.SECURITY_AUTHENTICATION,"simple");
        ldapEnv.put(Context.SECURITY_PRINCIPAL,"uid=admin,ou=system");
        ldapEnv.put(Context.SECURITY_CREDENTIALS,"secret");
        
        DirContext connection = new InitialDirContext(ldapEnv);
        System.out.println("Benvenuto " + connection);
        NamingEnumeration enm = connection.list("");

        while (enm.hasMore()) {
            System.out.println(enm.next());
        }

        enm.close();
        connection.close();
        
        
    }catch(Exception e) {
        e.printStackTrace();
    }
    
}

}

This code is actually working when SSL is not tested, replacing the

ldapEnv.put(Context.PROVIDER_URL, "ldaps://localhost:10636");

with

ldapEnv.put(Context.PROVIDER_URL, "ldap://localhost:10389");

I made the setup for the LDAP server with Apache Directory Studio, and followed this tutorial here in order to get the LDAPS to work: http://directory.apache.org/apacheds/basic-ug/3.3-enabling-ssl.html

So I made the certificate, even installed it and imported it with keytool into cacerts. I enabled portforwarding for the chosen port (10636), but still, I'm getting this exception:

javax.naming.CommunicationException: simple bind failed: localhost:10636 [Root exception is 
java.net.SocketException: Connection or outbound has closed]
at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:219)
at java.naming/com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2795)
at java.naming/com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:320)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxFromUrl(LdapCtxFactory.java:225)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:189)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:243)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:154)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:84)
at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:730)
at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
at java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
at java.naming/javax.naming.InitialContext.<init>(InitialContext.java:208)
at java.naming/javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:130)
at Prova3.main(Prova3.java:31)
Caused by: java.net.SocketException: Connection or outbound has closed
at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1246)
at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:398)
at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:371)
at java.naming/com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:359)
at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:214)
... 13 more

Thank you in advance

stefano542
  • 81
  • 1
  • 1
  • 2
  • I have the same issue in JDK8. It does not seem to be JDK version issue as answered in https://stackoverflow.com/questions/58911874/java-upgrade-8-to-11-causing-issue-with-ldaps-connection-connection-or-outbound – Shoner Sul Dec 09 '20 at 05:41

2 Answers2

11

For Googlers:

simple bind failed errors are almost always related to SSL connection.

With nc or telnet, check whether a connection can be established between client and remote host and port.

With SSLPoke.java (a simple Java class to check SSL connection), check whether certificates are correctly imported and used, also check correct TLS version. Use something like java -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 -Djavax.net.debug=all SSLPoke google.com 443 > log.txt 2>&1.

Look for:

  • Warning: no suitable certificate found - continuing without client authentication = check whether you have set javax.net.ssl.trustStore
  • Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking = could be mismatched TLS versions
  • Also check whether your intermediate CA is expired
dz902
  • 4,782
  • 38
  • 41
1

"Connection or outbound has closed" is a general exception with several possible causes. In order to find the main cause you should start your application with the SSL debugging enabled. You can do that by adding the following VM parameter on startup:

-Djavax.net.debug=ssl,handshake

In my case, with the SSL debug mode enabled I got "CertificateException: No name matching localhost found" which is explicit enough. The real problem was that the hostname configured in the self-signed certificate was not the one used to access the host. For the handshake not only the certificate validity is verified, but also the matching of host names.