ldaps:// ignores alternative DNS names / SNA (Subject Alternative Name) certs if hostname != CN name

Heiko Jakob heiko.jakob at gediegos.de
Sun Feb 10 01:34:30 UTC 2019


Hi,

connecting to a secure ldap server with a SNA certificate fails with
"javax.naming.CommunicationException: simple bind failed: 
ldap.foo.bar:636 [Root exception is javax.net.ssl.SSLHandshakeException: 
No subject alternative DNS name matching ldap.foo.bar found.]"

The certificate is valid and i've tested it on https on the same machine 
which works flawlessly. The problem does not effect the Oracle JDK/JRE, 
only OpenJDK. I've testen OpenJDK 1.8.0_181, 11.0.1, 11.0.2 and all are 
affected.


With best regards

Heiko Jakob


How to reproduce:
Have a valid certificate for a host named CN "realhost.foo.bar" with 
x509 SNA extension for DNS.1 "realhost.foo.bar" DNS.2 "ldap.foo.bar". 
Use the same certificate for https & ldap on the same host.

Examine the certificate to have CN="realhost.foo.bar" and x509 SNA 
extension for ldap.foo.bar
$ openssl x509 -in my.crt -text -noout | less
Certificate:

...

        Validity
             Not Before: Feb  8 11:28:53 2019 GMT
             Not After : Feb  7 11:28:53 2024 GMT
         Subject: C = DE, ST = BW, L = Stuttgart, O = foo.bar, OU = IT 
Department, CN = realhost.foo.bar
...
             X509v3 Subject Alternative Name:
                 DNS:realhost.foo.bar, DNS:ldap.foo.bar


Run the following small test program to reproduce the problem.

package testSSL;

import java.net.URL;
import java.net.URLConnection;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public final class TestSSL {

     public static void main(String[] args) {
         String url_l = "ldaps://ldap.foo.bar:636";
         String url_h = "https://ldap.foo.bar";

         System.out.println("TestSSL");
         URL url;
         try {
             System.out.println("Test " + url_h);
             url = new URL(url_h);
             URLConnection conn = url.openConnection();
             conn.connect();
         } catch (Exception e) {
             e.printStackTrace();
             System.out.println("Failed " + url_h);
             System.exit(-1);
         }
         System.out.println("https:// OK");


         System.out.println("Test " + url_l);
         Hashtable env = new Hashtable();
         env.put(Context.INITIAL_CONTEXT_FACTORY,
             "com.sun.jndi.ldap.LdapCtxFactory");
         env.put(Context.PROVIDER_URL, url_l);
         env.put(Context.SECURITY_PROTOCOL, "ssl");
         env.put(Context.SECURITY_AUTHENTICATION, "simple");
         env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=foo,dc=bar");
         env.put(Context.SECURITY_CREDENTIALS, "mysecret");
         try {
             DirContext ctx = new InitialDirContext(env);
         } catch (Exception e) {
             e.printStackTrace();
             System.out.println("Failed " + url_l);
             System.exit(-1);
         }
         System.out.println("ldaps:// OK");
     }
}

Test it against various JDKs

$ (for j in $(find /opt/java/ -type f -name 'java' 2> /dev/null); do 
echo $j; $j -version; $j -classpath ./ testSSL.TestSSL; echo""; echo 
"##############################################";echo ""; sleep 30; done 
) 2>&1 | tee -a testSSL.out

Reference output from oracle JDK

opt/java/jdk1.8.0_73/bin/java
java version "1.8.0_73"
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.73-b02, mixed mode)
TestSSL
https://ldap.foo.bar
https:// OK
ldaps://ldap.foo.bar:636
ldaps:// OK

##############################################
....
##############################################

/opt/java/jdk-11.0.2/bin/java
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
TestSSL
https://ldap.foo.bar
https:// OK
ldaps://ldap.foo.bar:636
javax.naming.CommunicationException: simple bind failed: 
ldap.foo.bar:636 [Root exception is javax.net.ssl.SSLHandshakeException: 
No subject alternative DNS name matching ldap.foo.bar found.]
         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 testSSL.TestSSL.main(TestSSL.java:57)
Caused by: javax.net.ssl.SSLHandshakeException: No subject alternative 
DNS name matching ldap.foo.bar found.
         at 
java.base/sun.security.ssl.Alert.createSSLException(Alert.java:128)
         at 
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
         at 
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
         at 
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:259)
         at 
java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:642)
         at 
java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:461)
         at 
java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:361)
         at 
java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
         at 
java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)
         at 
java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
         at 
java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178)
         at 
java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
         at 
java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
         at 
java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
         at 
java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
         at 
java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:716)
         at 
java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:970)
         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)
         ... 12 more




More information about the security-dev mailing list