<br><br>On Saturday, 26 September 2015, Sean Mullan <<a href="mailto:sean.mullan@oracle.com">sean.mullan@oracle.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">JDK-806769 doesn't exist, can you double-check what issue you think caused this? Looks like you are missing a digit.<br><br></blockquote><div><br></div><div>Hi Sean, hmm I don't know how I managed that ... the complete issue id is <span style="font-family:Arial,Helvetica,sans-serif;font-size:19.2036px;line-height:25.6048px">JDK-8067695</span><font face="Arial, Helvetica, sans-serif"><span style="font-size:19.2036px;line-height:25.6048px">.</span></font></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
On 9/24/15 10:46 PM, David Black wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
As I do not have an account on <a href="https://bugs.openjdk.java.net" target="_blank">https://bugs.openjdk.java.net</a>, yes I have<br>
submitted a standard oracle java bug report, I thought it might be of<br>
interest to those on this mailing list to forward information on how<br>
some java ldap users since the JDK-806769 fix may encounter invalid<br>
ldaps hostname issues.<br>
<br>
When an "ldaps" provider url is set in the environment and a custom<br>
SocketFactory, which sets the SSLSocket endpoint identification<br>
algorithm to "LDAPS", is set in the ldap environment hostname because of<br>
the way the fix for JDK-806769 was implemented some clients encounter a<br>
CertificateException. This occurs because the code inside the<br>
com.sun.jndi.ldap.Connection class createSocket method[0] "prefers" to<br>
invoke the socketFactory.createSocket() method instead of<br>
socketFactory.createSocket(String host, int port) when a connection<br>
timeout is set, which results in the host not being set in the created<br>
ssl socket instance.<br>
<br>
Steps to reproduce:<br>
1. git clone<br>
<a href="https://bitbucket.org/atlassian/cwd-4444-java-bug-reproducer.git" target="_blank">https://bitbucket.org/atlassian/cwd-4444-java-bug-reproducer.git</a><br>
2. build the code - `cd src/main/java && javac Broken.java Main.java<br>
Working.java`<br>
3. run the Main class and provide an ldaps url - `java Main<br>
ldaps://example.java:10636`<br>
4. Observe that when the "Broken" SocketFactory is in use a hostname<br>
verification error occurs.<br>
<br>
Workaround:<br>
Naturally, one can workaround the Connection class's "preference" for<br>
the no argument createSocket method by not having such a method in the<br>
SocketFactory set in the ldap environment.<br>
<br>
<br>
Untested potential patch:<br>
--- Connection.java.orig2015-09-25 11:39:26.323117929 +1000<br>
+++ Connection.java2015-09-25 12:41:04.175068697 +1000<br>
@@ -33,6 +33,7 @@<br>
import java.io.InputStream;<br>
import java.net.Socket;<br>
import javax.net.ssl.SSLSocket;<br>
+import javax.net.ssl.SSLSocketFactory;<br>
import javax.naming.CommunicationException;<br>
import javax.naming.ServiceUnavailableException;<br>
@@ -287,7 +288,40 @@<br>
Method createSocket = null;<br>
- if (connectTimeout > 0) {<br>
+ if (connectTimeout > 0 && socketFactoryClass instanceof<br>
SSLSocketFactory) {<br>
+<br>
+ try {<br>
+ Socket sock = null;<br>
+ createSocket =<br>
socketFactoryClass.getMethod("createSocket",<br>
+ new Class<?>[]{Socket.class, String.class,<br>
+ int.class, boolean.class});<br>
+ Constructor<Socket> socketCons =<br>
+ Socket.class.getConstructor(new Class<?>[]{});<br>
+<br>
+ Method connect = Socket.class.getMethod("connect",<br>
+ new<br>
Class<?>[]{Class.forName("java.net.SocketAddress"),<br>
+ int.class});<br>
+ Object endpoint = createInetSocketAddress(host, port);<br>
+<br>
+ // unconnected underlying socket<br>
+ sock = socketCons.newInstance(new Object[]{});<br>
+<br>
+ if (debug) {<br>
+ System.err.println("Connection: creating socket<br>
with " +<br>
+ "a timeout");<br>
+ }<br>
+ // connect the underlying socket<br>
+ connect.invoke(sock, new Object[]{<br>
+ endpoint, new Integer(connectTimeout)});<br>
+ // connect the ssl socket<br>
+ socket = createSocket(sock, host, port, true);<br>
+<br>
+ } catch (NoSuchMethodException e) {<br>
+ // continue<br>
+ }<br>
+ }<br>
+<br>
+ if (connectTimeout > 0 && socket == null) {<br>
try {<br>
createSocket =<br>
socketFactoryClass.getMethod("createSocket",<br>
<br>
<br>
<br>
[0]<br>
<a href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/7d1d5f4d019a/src/share/classes/com/sun/jndi/ldap/Connection.java#l272" target="_blank">http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/7d1d5f4d019a/src/share/classes/com/sun/jndi/ldap/Connection.java#l272</a><br>
<br>
--<br>
David Black / Security Engineer.<br>
</blockquote>
</blockquote><br><br>-- <br>David Black / Security Engineer.<br>