org.apache.commons.ssl
Class RMISocketFactoryImpl

java.lang.Object
  extended by java.rmi.server.RMISocketFactory
      extended by org.apache.commons.ssl.RMISocketFactoryImpl
All Implemented Interfaces:
java.rmi.server.RMIClientSocketFactory, java.rmi.server.RMIServerSocketFactory

public class RMISocketFactoryImpl
extends java.rmi.server.RMISocketFactory

An RMISocketFactory ideal for using RMI over SSL. The server secures both the registry and the remote objects. The client assumes that either both the registry and the remote objects will use SSL, or both will use plain-socket. The client is able to auto detect plain-socket registries and downgrades itself to accomodate those.

Unlike most existing RMI over SSL solutions in use (including Java 5's javax.rmi.ssl.SslRMIClientSocketFactory), this one does proper SSL hostname verification. From the client perspective this is straighforward. From the server perspective we introduce a clever trick: we perform an initial "hostname verification" by trying the current value of "java.rmi.server.hostname" against our server certificate. If the "java.rmi.server.hostname" System Property isn't set, we set it ourselves using the CN value we extract from our server certificate! (Some complications arise should a wildcard certificate show up, but we try our best to deal with those).

An SSL server cannot be started without a private key. We have defined some default behaviour for trying to find a private key to use that we believe is convenient and sensible:

If running from inside Tomcat, we try to re-use Tomcat's private key and certificate chain (assuming Tomcat-SSL on port 8443 is enabled). If this isn't available, we look for the "javax.net.ssl.keyStore" System property. Finally, if that isn't available, we look for "~/.keystore" and assume a password of "changeit".

If after all these attempts we still failed to find a private key, the RMISocketFactoryImpl() constructor will throw an SSLException.

Since:
22-Apr-2005
Author:
Credit Union Central of British Columbia, www.cucbc.com, juliusdavies@cucbc.com

Field Summary
private  int anonymousPort
           
private  java.util.Map clientMap
           
private  javax.net.SocketFactory defaultClient
           
private  java.lang.String localBindAddress
           
private static LogWrapper log
           
private  javax.net.SocketFactory plainClient
           
static java.lang.String RMI_HOSTNAME_KEY
           
private  java.util.Map serverSockets
           
private  javax.net.ServerSocketFactory sslServer
           
 
Constructor Summary
RMISocketFactoryImpl()
           
RMISocketFactoryImpl(boolean createDefaultServer)
           
 
Method Summary
 java.net.ServerSocket createServerSocket(int port)
           
 java.net.Socket createSocket(java.lang.String host, int port)
           
 javax.net.SocketFactory getClient(java.lang.String host)
           
 javax.net.SocketFactory getDefaultClient()
           
static java.lang.String getMyDefaultIP()
           
static java.util.SortedSet getMyInternetFacingIPs()
           
 javax.net.ServerSocketFactory getServer()
           
private  java.util.Set hostnamePossibilities(java.lang.String host)
           
 void removeClient(javax.net.SocketFactory sf)
           
 void removeClient(java.lang.String host)
           
 void setAnonymousPort(int port)
           
 void setClient(java.lang.String host, javax.net.SocketFactory f)
           
 void setDefaultClient(javax.net.SocketFactory f)
           
 void setLocalBindAddress(java.lang.String localBindAddress)
           
 void setServer(javax.net.ServerSocketFactory f)
           
private  void trustEachOther(SSLClient client, SSLServer server)
           
private  void trustOurself()
           
 
Methods inherited from class java.rmi.server.RMISocketFactory
getDefaultSocketFactory, getFailureHandler, getSocketFactory, setFailureHandler, setSocketFactory
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

RMI_HOSTNAME_KEY

public static final java.lang.String RMI_HOSTNAME_KEY
See Also:
Constant Field Values

log

private static final LogWrapper log

defaultClient

private volatile javax.net.SocketFactory defaultClient

sslServer

private volatile javax.net.ServerSocketFactory sslServer

localBindAddress

private volatile java.lang.String localBindAddress

anonymousPort

private volatile int anonymousPort

clientMap

private java.util.Map clientMap

serverSockets

private java.util.Map serverSockets

plainClient

private final javax.net.SocketFactory plainClient
Constructor Detail

RMISocketFactoryImpl

public RMISocketFactoryImpl()
                     throws java.security.GeneralSecurityException,
                            java.io.IOException
Throws:
java.security.GeneralSecurityException
java.io.IOException

RMISocketFactoryImpl

public RMISocketFactoryImpl(boolean createDefaultServer)
                     throws java.security.GeneralSecurityException,
                            java.io.IOException
Parameters:
createDefaultServer - If false, then we only set the default client, and the default server is set to null. If true, then a default server is also created.
Throws:
java.security.GeneralSecurityException - bad things
java.io.IOException - bad things
Method Detail

setServer

public void setServer(javax.net.ServerSocketFactory f)
               throws java.security.GeneralSecurityException,
                      java.io.IOException
Throws:
java.security.GeneralSecurityException
java.io.IOException

setLocalBindAddress

public void setLocalBindAddress(java.lang.String localBindAddress)

setAnonymousPort

public void setAnonymousPort(int port)

setDefaultClient

public void setDefaultClient(javax.net.SocketFactory f)
                      throws java.security.GeneralSecurityException,
                             java.io.IOException
Throws:
java.security.GeneralSecurityException
java.io.IOException

setClient

public void setClient(java.lang.String host,
                      javax.net.SocketFactory f)
               throws java.security.GeneralSecurityException,
                      java.io.IOException
Throws:
java.security.GeneralSecurityException
java.io.IOException

removeClient

public void removeClient(java.lang.String host)

removeClient

public void removeClient(javax.net.SocketFactory sf)

hostnamePossibilities

private java.util.Set hostnamePossibilities(java.lang.String host)

trustOurself

private void trustOurself()
                   throws java.security.GeneralSecurityException,
                          java.io.IOException
Throws:
java.security.GeneralSecurityException
java.io.IOException

trustEachOther

private void trustEachOther(SSLClient client,
                            SSLServer server)
                     throws java.security.GeneralSecurityException,
                            java.io.IOException
Throws:
java.security.GeneralSecurityException
java.io.IOException

getServer

public javax.net.ServerSocketFactory getServer()

getDefaultClient

public javax.net.SocketFactory getDefaultClient()

getClient

public javax.net.SocketFactory getClient(java.lang.String host)

createServerSocket

public java.net.ServerSocket createServerSocket(int port)
                                         throws java.io.IOException
Specified by:
createServerSocket in interface java.rmi.server.RMIServerSocketFactory
Specified by:
createServerSocket in class java.rmi.server.RMISocketFactory
Throws:
java.io.IOException

createSocket

public java.net.Socket createSocket(java.lang.String host,
                                    int port)
                             throws java.io.IOException
Specified by:
createSocket in interface java.rmi.server.RMIClientSocketFactory
Specified by:
createSocket in class java.rmi.server.RMISocketFactory
Throws:
java.io.IOException

getMyDefaultIP

public static java.lang.String getMyDefaultIP()

getMyInternetFacingIPs

public static java.util.SortedSet getMyInternetFacingIPs()
                                                  throws java.net.SocketException
Throws:
java.net.SocketException