Search code examples
javaldap

Java upgrade 8 to 11 causing issue with LDAPS connection (Connection or outbound has closed)


This issue seen after java upgrade. LDAP with DNS alias does not connect with java 11.0.2 where as it worked with java 8

DNS alias as below this remain same no change here only change is java upgrade 8 to 11:

$ nslookup ad1.XXXXX.zz

    Server:         10.222.249.209
    Address:        10.222.249.209#53
    
    Name:   ad1.XXXXX.zz
    Address: 10.222.249.205
    Name:   ad1.XXXXX.zz
    Address: 10.222.249.204
    Name:   ad1.XXXXX.zz
    Address: 10.222.249.210

LDAP direct IP with java 11.0.2 it works no issue:

$ nslookup qdegsf.XXXXX.zz

    Server:         10.222.249.209
    Address:        10.222.249.209#53
    
    Name:   qdegsf.XXXXX.zz
    Address: 10.222.249.210

Process parameters:

/opt/3rdparty/jdk_installed/jdk-11.0.2/bin/java -Dsserver -Djdk.serialFilter=*  -Dfile.encoding=UTF8  -Djavax.net.ssl.trustStore=/opt/3rdparty/tomcat/conf/svrtrust -Djavax.net.ssl.trustStorePassword=XXXX -Djavax.net.ssl.keyStore=/opt/3rdparty/tomcat/conf/svrkeystore.jks    

Below is the issue traces when ldap connection is made

java.lang.RuntimeException: connection to ldap server failed;url;ldaps://ad1.XXXXX.zz:636;authDN;[email protected]
javax.naming.CommunicationException: simple bind failed: ad1.XXXXX.zz:636 [Root exception is java.net.SocketException: Connection or outbound has closed]
java.net.SocketException: Connection or outbound has closed
Trace for the thrown exceptions:
java.lang.RuntimeException: connection to ldap server failed;url;ldaps://ad1.XXXXX.zz:636;authDN;[email protected]
    at auth.ldap.LdapConnection.testConnection(LdapConnection.java:46)

    
Caused by: javax.naming.CommunicationException: simple bind failed: ad1.XXXXX.zz:636 [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.getUsingURL(LdapCtxFactory.java:192)
    at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
    at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
    at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
    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:101)
    at auth.ldap.LdapConnection.testConnection(LdapConnection.java:41)
    ... 3 more
Caused by: java.net.SocketException: Connection or outbound has closed
    at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:976)
    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)
    ... 15 more
javax.naming.CommunicationException: simple bind failed: ad1.XXXXX.zz:636 [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.getUsingURL(LdapCtxFactory.java:192)
    at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
    at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
    at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
    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:101)
    at auth.ldap.LdapConnection.testConnection(LdapConnection.java:41)
Caused by: java.net.SocketException: Connection or outbound has closed
    at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:976)
    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)
    ... 15 more
java.net.SocketException: Connection or outbound has closed
    at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:976)
    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)
    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.getUsingURL(LdapCtxFactory.java:192)
    at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
    at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
    at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
    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:101)
    at nims.auth.ldap.LdapConnection.testConnection(LdapConnection.java:41)
    at auth.LdapAuthenticationService.doTestConnection(LdapAuthenticationService.java:50)

Update getting below error when:

$ openssl s_client -connect  ad1.XXXXX-ru.zz:636

CONNECTED(00000003)
depth=0 
verify error:num=20:**unable to get local issuer certificate**
verify return:1
depth=0 
verify error:num=27:**certificate not trusted**
verify return:1
depth=0 
verify error:num=21:**unable to verify the first certificate**
verify return:1

Certificate chain
 0 s:
   i:/DC=zz/DC=XXXXX-ru/CN=XXXXX-ru-ROOT-CA

Server certificate
-----BEGIN CERTIFICATE-----
MIIFfjCCBGagAwIBAgITLwAAAKgllUHEZUjzRwAAAAAAqDANBgkqhkiG9w0BA.................

APpwNrloBJjZo2bJ7pqe4gXN
-----END CERTIFICATE-----

subject=
issuer=/DC=zz/DC=XXXXX-ru/CN=XXXXX-ru-ROOT-CA

No client certificate CA names sent
Server Temp Key: ECDH, prime256v1, 256 bits

SSL handshake has read 1980 bytes and written 441 bytes

New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-SHA384
    Session-ID: C51900006745E495E1C8CA132C0EDF901C3638DE9E5EEA506551E298E2374372
    Session-ID-ctx: 
    Master-Key: A8B4C4E2B01FE11822CE047D3B7D692EE1C001DA551DFE63FBC314737177BE7A285F79D6FF36B67D3E1AFF72C1402D2D
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1574232095
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)

Solution

  • wrote a test script to connect with ldap ( with ssl logs enable) @ jdk 11

    /opt/soft/jdk_installed/jdk-11.0.2/bin/java -XX:+UseSerialGC -DLdapsConnect -Djavax.net.debug=all -Djavax.net.ssl.trustStore=/opt/soft/tomcat/conf/svrtrust -Djavax.net.ssl.trustStorePassword=hsqlIiza -Djavax.net.ssl.keyStore=/opt/soft/tomcat/conf/svrkeystore.jks -Djavax.net.ssl.keyStorePassword=hsqlIiza -classpath /tmp/ LdapsConnect $*
    

    found that below error in ssl logs

    javax.net.ssl|ERROR|1D|Thread-0|2020-01-22 10:55:21.632 CET|TransportContext.java:313|Fatal (CERTIFICATE_UNKNOWN): No subject alternative DNS name matching ad1.xxxx.zz found.
    

    Conclusion/Solution : Ldap certificate should be modified to have ad1.ngssm-ru.zz which is missing. As Java 8u181 has changes as below in ldap support which does not allow old way after java version 8u181 and above.

    Java is trying to make sure the host name in your connection configuration matches the host names in the remote LDAPS TLS server certificate and that those host names in the certificate are valid. The correct solution for a secure connection is to have your LDAP server administrators correct the LDAPs certificate the ldap server is using so that the improved endpoint identification algorithms work. This is for our protection.

    https://www.oracle.com/technetwork/java/javase/8u181-relnotes-4479407.html Changes core-libs/javax.naming ? Improve LDAP support Endpoint identification has been enabled on LDAPS connections.

    To improve the robustness of LDAPS (secure LDAP over TLS) connections, endpoint identification algorithms have been enabled by default.

    Note that there may be situations where some applications that were previously able to successfully connect to an LDAPS server may no longer be able to do so. Such applications may, if they deem appropriate, disable endpoint identification using a new system property: com.sun.jndi.ldap.object.disableEndpointIdentification.

    Define this system property (or set it to true) to disable endpoint identification algorithms.