<div dir="ltr"><div>As I do not have an account on <a href="https://bugs.openjdk.java.net">https://bugs.openjdk.java.net</a>, yes I have submitted a standard oracle java bug report, I thought it might be of interest to those on this mailing list to forward information on how some java ldap users since the JDK-806769 fix may encounter invalid ldaps hostname issues.</div><div><br></div><div><div>When an "ldaps" provider url is set in the environment and a custom SocketFactory, which sets the SSLSocket endpoint identification algorithm to "LDAPS", is set in the ldap environment hostname because of the way the fix for JDK-806769 was implemented some clients encounter a CertificateException. This occurs because the code inside the com.sun.jndi.ldap.Connection class createSocket method[0] "prefers" to invoke the socketFactory.createSocket() method instead of socketFactory.createSocket(String host, int port) when a connection timeout is set, which results in the host not being set in the created ssl socket instance.</div></div><div><br></div><div>Steps to reproduce:</div><div><div>1. git clone <a href="https://bitbucket.org/atlassian/cwd-4444-java-bug-reproducer.git">https://bitbucket.org/atlassian/cwd-4444-java-bug-reproducer.git</a></div><div>2. build the code - `cd src/main/java && javac Broken.java Main.java Working.java`</div><div>3. run the Main class and provide an ldaps url - `java Main ldaps://example.java:10636`</div><div>4. Observe that when the "Broken" SocketFactory is in use a hostname verification error occurs.</div></div><div><br></div><div>Workaround:</div><div>Naturally, one can workaround the Connection class's "preference" for the no argument createSocket method by not having such a method in the SocketFactory set in the ldap environment.</div><div><br></div><div><br></div><div>Untested potential patch:</div><div><div>--- Connection.java.orig<span class="" style="white-space:pre">      </span>2015-09-25 11:39:26.323117929 +1000</div><div>+++ Connection.java<span class="" style="white-space:pre">     </span>2015-09-25 12:41:04.175068697 +1000</div><div>@@ -33,6 +33,7 @@</div><div> import java.io.InputStream;</div><div> import java.net.Socket;</div><div> import javax.net.ssl.SSLSocket;</div><div>+import javax.net.ssl.SSLSocketFactory;</div><div> </div><div> import javax.naming.CommunicationException;</div><div> import javax.naming.ServiceUnavailableException;</div><div>@@ -287,7 +288,40 @@</div><div> </div><div>             Method createSocket = null;</div><div> </div><div>-            if (connectTimeout > 0) {</div><div>+            if (connectTimeout > 0 && socketFactoryClass instanceof SSLSocketFactory) {</div><div>+</div><div>+                try {</div><div>+                    Socket sock = null;</div><div>+                    createSocket = socketFactoryClass.getMethod("createSocket",</div><div>+                            new Class<?>[]{Socket.class, String.class,</div><div>+                                int.class, boolean.class});</div><div>+                    Constructor<Socket> socketCons =</div><div>+                        Socket.class.getConstructor(new Class<?>[]{});</div><div>+</div><div>+                    Method connect = Socket.class.getMethod("connect",</div><div>+                        new Class<?>[]{Class.forName("java.net.SocketAddress"),</div><div>+                        int.class});</div><div>+                    Object endpoint = createInetSocketAddress(host, port);</div><div>+</div><div>+                    // unconnected underlying socket</div><div>+                    sock = socketCons.newInstance(new Object[]{});</div><div>+</div><div>+                    if (debug) {</div><div>+                        System.err.println("Connection: creating socket with " +</div><div>+                            "a timeout");</div><div>+                    }</div><div>+                    // connect the underlying socket</div><div>+                    connect.invoke(sock, new Object[]{</div><div>+                        endpoint, new Integer(connectTimeout)});</div><div>+                    // connect the ssl socket</div><div>+                    socket = createSocket(sock, host, port, true);</div><div>+</div><div>+                } catch (NoSuchMethodException e) {</div><div>+                    // continue</div><div>+                }</div><div>+            }</div><div>+</div><div>+            if (connectTimeout > 0 && socket == null) {</div><div> </div><div>                 try {</div><div>                     createSocket = socketFactoryClass.getMethod("createSocket",</div></div><div><br></div><div><br></div><div><br></div><div>[0] <a href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/7d1d5f4d019a/src/share/classes/com/sun/jndi/ldap/Connection.java#l272">http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/7d1d5f4d019a/src/share/classes/com/sun/jndi/ldap/Connection.java#l272</a><br></div><div><br></div>-- <br><div class="gmail_signature">David Black / Security Engineer.</div>
</div>