On Saturday, 26 September 2015, Sean Mullan <sean.mul...@oracle.com> wrote:
> JDK-806769 doesn't exist, can you double-check what issue you think caused > this? Looks like you are missing a digit. > > Hi Sean, hmm I don't know how I managed that ... the complete issue id is JDK-8067695. > > On 9/24/15 10:46 PM, David Black wrote: > >> As I do not have an account on https://bugs.openjdk.java.net, 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. >> >> 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. >> >> Steps to reproduce: >> 1. git clone >> https://bitbucket.org/atlassian/cwd-4444-java-bug-reproducer.git >> 2. build the code - `cd src/main/java && javac Broken.java Main.java >> Working.java` >> 3. run the Main class and provide an ldaps url - `java Main >> ldaps://example.java:10636` >> 4. Observe that when the "Broken" SocketFactory is in use a hostname >> verification error occurs. >> >> Workaround: >> 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. >> >> >> Untested potential patch: >> --- Connection.java.orig2015-09-25 11:39:26.323117929 +1000 >> +++ Connection.java2015-09-25 12:41:04.175068697 +1000 >> @@ -33,6 +33,7 @@ >> import java.io.InputStream; >> import java.net.Socket; >> import javax.net.ssl.SSLSocket; >> +import javax.net.ssl.SSLSocketFactory; >> import javax.naming.CommunicationException; >> import javax.naming.ServiceUnavailableException; >> @@ -287,7 +288,40 @@ >> Method createSocket = null; >> - if (connectTimeout > 0) { >> + if (connectTimeout > 0 && socketFactoryClass instanceof >> SSLSocketFactory) { >> + >> + try { >> + Socket sock = null; >> + createSocket = >> socketFactoryClass.getMethod("createSocket", >> + new Class<?>[]{Socket.class, String.class, >> + int.class, boolean.class}); >> + Constructor<Socket> socketCons = >> + Socket.class.getConstructor(new Class<?>[]{}); >> + >> + Method connect = Socket.class.getMethod("connect", >> + new >> Class<?>[]{Class.forName("java.net.SocketAddress"), >> + int.class}); >> + Object endpoint = createInetSocketAddress(host, >> port); >> + >> + // unconnected underlying socket >> + sock = socketCons.newInstance(new Object[]{}); >> + >> + if (debug) { >> + System.err.println("Connection: creating socket >> with " + >> + "a timeout"); >> + } >> + // connect the underlying socket >> + connect.invoke(sock, new Object[]{ >> + endpoint, new Integer(connectTimeout)}); >> + // connect the ssl socket >> + socket = createSocket(sock, host, port, true); >> + >> + } catch (NoSuchMethodException e) { >> + // continue >> + } >> + } >> + >> + if (connectTimeout > 0 && socket == null) { >> try { >> createSocket = >> socketFactoryClass.getMethod("createSocket", >> >> >> >> [0] >> >> http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/7d1d5f4d019a/src/share/classes/com/sun/jndi/ldap/Connection.java#l272 >> >> -- >> David Black / Security Engineer. >> > -- David Black / Security Engineer.