JDK-7092266 : property com.sun.jndi.ldap.read.timeout does not work if SSL is used.
  • Type: Bug
  • Component: core-libs
  • Sub-Component: javax.naming
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_10
  • CPU: sparc
  • Submitted: 2011-09-19
  • Updated: 2011-10-19
  • Resolved: 2011-10-19
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Server VM (build 17.1-b03, mixed mode)



ADDITIONAL OS VERSION INFORMATION :
SunOS 5.10 Generic_118833-33
Windows XP sp2


A DESCRIPTION OF THE PROBLEM :
Using a modified java from the jndi exemple ldap client provided on http://download.oracle.com/javase/tutorial/jndi/newstuff/readtimeout.html

if SSL is used, the client freeze with no response . The timeout is ignored.
if SSL is not used, the property is working.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
create a sample keystore:
keytool -keystore myKeystore -genkey -keyalg RSA -alias mycert


create a sample ldap jndi client and server (source given above in the testcase field).


run the exemple in non ssl
java ReadTimeoutTest

run the exemple in ssl
java -Djavax.net.ssl.keyStore=myKeystore -Djavax.net.ssl.keyStorePassword=changeme -Djavax.net.ssl.trustSto=myKeystore -Djavax.net.ssl.trustStorePassword=changeme  ReadTimeoutTest SSL


if server reads the socket, the bug does not appear (uncomment line 113 for test)




EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expect the timeout to work as specified and as in non ssl mode

javax.naming.NamingException: LDAP response read timed out, timeout used:2000ms.
	at com.sun.jndi.ldap.Connection.readReply(Connection.java:448)
	at com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:340)
	at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:170)
	at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2694)
	at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:293)
	at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
	at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
	at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
	at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
	at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
	at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
	at javax.naming.InitialContext.init(InitialContext.java:223)
	at javax.naming.InitialContext.<init>(InitialContext.java:197)
	at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:82)
	at ReadTimeoutTest.main(ReadTimeoutTest.java:79)

ACTUAL -
client is hanging indefinitely



REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

/*
 * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle or the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 */

import java.net.Socket;
import java.net.ServerSocket;
import javax.net.ServerSocketFactory;
import javax.net.ssl.SSLServerSocketFactory;
import java.io.*;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;

public class ReadTimeoutTest {
  
static boolean ssl = false;

    public static void main(String[] args) throws Exception {
  
	boolean passed = false;

	if (args.length > 0 && args[0].equalsIgnoreCase("SSL")) {
	  System.out.println("SSL on");
	  ssl = true;
	} else {
	  System.out.println("SSL off");
	  ssl = false;
	}
	
	// Set up the environment for creating the initial context
	Hashtable env = new Hashtable(11);
	env.put(Context.INITIAL_CONTEXT_FACTORY,
	    "com.sun.jndi.ldap.LdapCtxFactory");
	env.put("com.sun.jndi.ldap.read.timeout", "2000");
	if (ssl) {
        env.put(Context.PROVIDER_URL, "ldaps://localhost:2001");
  } else {
        env.put(Context.PROVIDER_URL, "ldap://localhost:2001");
  }

	Server s = new Server();

	try {

	    // start the server
	    s.start();

	    // Create initial context
	    DirContext ctx = new InitialDirContext(env);
	    System.out.println("LDAP Client: Connected to the Server");

	    // Close the context when we're done
	    ctx.close();
	} catch (NamingException e) {
	    e.printStackTrace();
	}
	s.interrupt();
    }

    static class Server extends Thread {

        static int serverPort = 2001;

	Server() {
	}

	public void run() {
	    try {
        ServerSocket serverSock;
        
        if (ssl) {
          SSLServerSocketFactory ssocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
          serverSock = ssocketFactory.createServerSocket(serverPort);
        } else {
          serverSock = new ServerSocket(serverPort);
        }
          	Socket socket = serverSock.accept();
            	System.out.println("Server: Connection accepted");

            	BufferedInputStream bin = new BufferedInputStream(socket.
                                getInputStream());
            	while (true) {
//                    bin.read();   // If uncommented, bug does not appear.
            	}
	    } catch (IOException e) {
	      e.printStackTrace();
		// ignore
	    }
       }
    }
}
---------- END SOURCE ----------