JDK-4425728 : rmi server closes the connection early
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 1.0.2,1.4.1_02,1.4.2
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,linux,solaris_8
  • CPU: generic,x86
  • Submitted: 2001-03-14
  • Updated: 2012-10-09
  • Resolved: 2004-10-11
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0u1 01Fixed
Related Reports
Duplicate :  
Description
Name: krC82822			Date: 03/14/2001


rmi 1193>java -version
java version "1.3.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0_01)
Java HotSpot(TM) Client VM (build 1.3.0_01, mixed mode)

Replacing the rmi/RMISSLServerSocketFactory class with one
that uses a default SSLServerSocketFactory instance causes
the example to fail. Here is the RMISSLServerSocketFactory2
replacement:

import java.io.IOException;
import java.io.Serializable;
import java.net.ServerSocket;
import java.rmi.server.RMIServerSocketFactory;
import java.security.KeyStore;
import javax.net.ServerSocketFactory;
import javax.net.ssl.SSLServerSocketFactory;

public class RMISSLServerSocketFactory2 implements Serializable,
RMIServerSocketFactory
{
    /** Create a server socket on the specified port.
     * @param  port the port number, 0 indicates an anonymous port
     * @return the server socket on the specified port
     * @exception IOException if an I/O error occurs during server socket
     * creation
    */
    public ServerSocket createServerSocket(int port) throws IOException
    {
        ServerSocketFactory ssf = null;
        try
        {
            ssf = SSLServerSocketFactory.getDefault();
System.out.println("Got default SSLServerSocketFactory");
        }
        catch(Exception e)
        {
            e.printStackTrace();
            throw new IOException("Failed to get default
SSLServerSocketFactory, "+e.getMessage());
        }
	ServerSocket ss = ssf.createServerSocket(port);
System.out.println("Created ss="+ss);
        return ss;
    }

}

Running the client and server with javax.net.debug=all on the
server shows it sitting in some loop trying to register the
server and the client fails to find the server in the registry.

rmi 1195>java -Djava.rmi.server.codebase="file:/usr/local/Java/jsse1.0.2/sample
s/rmi/"  -Djavax.net.debug=all HelloImpl
...
Got default SSLServerSocketFactory
Created ss=[SSL: ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=3088]]
Finalizer, SEND SSL v3.1 ALERT:  warning, description = close_notify
Finalizer, WRITE:  SSL v3.1 Alert, length = 2
Finalizer, SEND SSL v3.1 ALERT:  warning, description = close_notify
Finalizer, WRITE:  SSL v3.1 Alert, length = 2


lib 1353>rmiregistry
SSLSocket =504653[SSL_NULL_WITH_NULL_NULL: Socket[addr=succubus-si/172.17.66.54,
port=3088,localport=3090]]

rmi 1477>java HelloClient
HelloClient exception: HelloServer
java.rmi.NotBoundException: HelloServer
        at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Stream
RemoteCall.java:245)
        at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:
220)
        at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:354)
        at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
        at java.rmi.Naming.lookup(Naming.java:84)
        at HelloClient.main(HelloClient.java:29)
rmi 1478>

The original example RMISSLServerSocketFactory works fine. What
in the RMISSLServerSocketFactory setup steps are required for the
example to work with rmiregistry?
(Review ID: 118270) 
======================================================================
###@###.### 10/11/04 17:29 GMT

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger-beta2
02-09-2004

EVALUATION This example works for me. If they are going to use the default context, they have to supply the proper keystore/truststores to the default context's initialization routines. java -Djava.rmi.server.codebase="file:/`pwd`/" -Djavax.net.ssl.keyStore=testkeys -Djavax.net.ssl.keyStorePassword=passphrase HelloImpl bradford.wetmore@eng 2001-03-14 In reading some of the JDC forums, the critical piece that may be missing is: Author: kerrrjt Jun 6, 2001 2:13 PM I downloaded JSSE 1.0.2 and have the RMI/SSL "Hello World" example working. However, if I leave the server running, it stops after about 10 -15 minutes. No messages as to why it was stopped are displayed. Any hints as to what I am doing wrong would be greatly appreciated. I verified the sample rmi examples with jsse1.0.2 and jdk1.3.1 I noticed that the rmiserver would close the connection after appx 15 minutes and sometimes after 30-45 minutes. The debug output from ssl and rmi logs didn't yeild any interesting results. The connections lasted long with the use of plain sockets though. Need to investigate as to determine if this is a SSLSocket related problem or not. I am changing the synopsis to reflect the right problem. ###@###.### 2002-01-11 One person said that if they ran a thread in the background, it wouldn't have a problem. http://forum.java.sun.com/thread.jsp?forum=2&thread=134569 Let's get a handle on this for merlin, or at least 1.0.3. ###@###.### 2002-01-24 After some investigation, it turned out that this problem is not specific to JSSE at all and very easy to reproduce on 1.4.x. Peter Jones from the RMI group was kind enough to look at the problem: ============ The server VM terminates because there are no non-daemon threads running because the remote object gets garbage collected-- the RMI runtime maintains its own non-daemon thread in the background while there are any remote objects exported, but after none remain exported, there are no other non-daemon threads in this application (the main thread terminates after binding the remote object in the registry. So why does the remote object get garbage collected? After the "main" method terminates, the application has no local references to the remote object to keep it locally reachable. A binding in the registry normally keeps a remote object reachable through DGC (distributed GC), because the rmiregistry implementation holds its bindings with live remote references. Without the use of the custom socket factories, this works as expected. With the use of custom socket factories, however, the DGC communication that the registry must undertake to tell the HelloImpl VM that it is holding a live remote reference must go through the client socket factory, which is application code (not in boot class path). This code will be on the stack when the DGC communication is made, so it needs to be granted sufficient permissions to make that communication (SocketPermission "connect", at least). If the custom socket factory code were downloaded from an HTTP server on the same host as the remote object, then it would automatically be granted the necessary "connect" SocketPermission, but as this code is loaded from the rmiregistry's class path here, such permissions must be granted in the rmiregistry's policy (which it appears that you are not setting). So solutions include: - grant the necessary permissions to the socket factory code in the rmiregistry's security policy - let the rmiregistry's DGC communication fail and just hold a strong local reference to the remote object in a thread or static variable - arrange for the socket factory code to be downloadable from an HTTP server and use RMI's dynamic class loading functionality (and put stub class there too while you're at it) Hope this helps, -- Peter ================ We need to update the example description to explain this fact. We will do this with the Mantis documentation update. ###@###.### 2002-10-03 I was trying to rewrite this for inclusion with the user docs, so the below may not be 100% correct. However, I was unable to get this working by giving all permissions, so I have a note into Peter/Luis for more info. * For more details read on: * * A binding in the rmiregistry normally keeps a remote object * reachable via the distributed garbage collection (DGC) * mechanism. When using regular socket factories, the necessary * communications take place in the context of the bootclass path, * and has full permissions. * * When using custom socket factories, however, the necessary DGC * communications goes through the client socket factory, which is * application code (not in boot class path). This code would need * to be granted sufficient permissions to make that communication * happen (SocketPermission "connect", at least). In previous * releases of this sample code, the DGC communications were silently * failing, the object was eventually GC'd, and the server exited. * * There were a couple of options for solving this issue: * * - let the rmiregistry's DGC communication fail and just hold a * strong local reference to the remote object in a thread or static * variable, * * - grant the necessary permissions to the socket factory code in * the rmiregistry's security policy, or * * - arrange for the socket factory code to be downloadable from an * HTTP server and use RMI's dynamic class loading functionality * (and put stub class there too while you're at it) * * In this example, for simplicity, we'll just hold a copy of the * obj statically. */ ======== IMHO, I think just grabbing a static local copy of the obj is the best immediate solution, but let's remove the remainder of the fix. Alison, can you back out the change you made, and insert the following attached? /* * To prevent this example RMI server from terminating after all non- * daemon threads (including this one) are garbage collected, we'll * hold a static local copy of the HelloImpl object. */ However Peter/Luis, I was unable to get the application to work when granting full permissions to the rmiregistry. Are we sure this is the cause of the Server prematurely exiting? I tried to put in a grant of AllPermission, and first using: rmiregistry -J-Djava.security.policy=policy Looking at the output of -J-Djava.security.debug=policy, the file was never loaded. Is this because we're using the RMISecurityManager? I looked the code for RMISecurityManager, it doesn't look like it's doing anything special. Anyway, I went to jre/lib/security/java.policy, and added the AllPermission grant there instead. Anyway, I then went to see if there were any access failures in the rmiregistry, but rmiregistry -J-Djava.security.policy=access,failure didn't report any failures, and I still had the same problem. I actually had the same results with or without the AllPermission. Are you sure this is a permissions problems, or am I doing something obviously wrong? What do I need to get this working? Brad ###@###.### 2004-07-20 This took a bit of doing, but we finally have all of the pieces lined up. There were two problems: rmiregistry couldn't communicate with the server to keep the Distributed Garbage Collection piece going. We had to give it the proper policy, and all give it the proper pointer to samplecacerts. We also updated HelloImpl to keep a static pointer to the obj around, which will keep it working, even if the person doesn't give the right pointer to samplecacerts. Peter wants to update this example in mustang, I agree. Anyway, we have updated the source, plus the readme, it should be a lot easier to use now. ###@###.### 2004-07-23 The source code and ReadMe were updated and rebundled for the RC release. ###@###.### 2004-10-10 ###@###.### 10/11/04 17:29 GMT
23-07-2004