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