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:
RMIClientSocketFactory, RMIServerSocketFactory

public class RMISocketFactoryImpl
extends 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  Map clientMap
           
private  SocketFactory defaultClient
           
private  String localBindAddress
           
private static LogWrapper log
           
private  SocketFactory plainClient
           
static String RMI_HOSTNAME_KEY
           
private  Map serverSockets
           
private  ServerSocketFactory sslServer
           
 
Constructor Summary
RMISocketFactoryImpl()
           
RMISocketFactoryImpl(boolean createDefaultServer)
           
 
Method Summary
 ServerSocket createServerSocket(int port)
           
 Socket createSocket(String host, int port)
           
 SocketFactory getClient(String host)
           
 SocketFactory getDefaultClient()
           
static String getMyDefaultIP()
           
static SortedSet getMyInternetFacingIPs()
           
 ServerSocketFactory getServer()
           
private  Set hostnamePossibilities(String host)
           
 void removeClient(SocketFactory sf)
           
 void removeClient(String host)
           
 void setAnonymousPort(int port)
           
 void setClient(String host, SocketFactory f)
           
 void setDefaultClient(SocketFactory f)
           
 void setLocalBindAddress(String localBindAddress)
           
 void setServer(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 String RMI_HOSTNAME_KEY
See Also:
Constant Field Values

log

private static final LogWrapper log

defaultClient

private volatile SocketFactory defaultClient

sslServer

private volatile ServerSocketFactory sslServer

localBindAddress

private volatile String localBindAddress

anonymousPort

private volatile int anonymousPort

clientMap

private Map clientMap

serverSockets

private Map serverSockets

plainClient

private final SocketFactory plainClient
Constructor Detail

RMISocketFactoryImpl

public RMISocketFactoryImpl()
                     throws GeneralSecurityException,
                            IOException
Throws:
GeneralSecurityException
IOException

RMISocketFactoryImpl

public RMISocketFactoryImpl(boolean createDefaultServer)
                     throws GeneralSecurityException,
                            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:
GeneralSecurityException - bad things
IOException - bad things
Method Detail

setServer

public void setServer(ServerSocketFactory f)
               throws GeneralSecurityException,
                      IOException
Throws:
GeneralSecurityException
IOException

setLocalBindAddress

public void setLocalBindAddress(String localBindAddress)

setAnonymousPort

public void setAnonymousPort(int port)

setDefaultClient

public void setDefaultClient(SocketFactory f)
                      throws GeneralSecurityException,
                             IOException
Throws:
GeneralSecurityException
IOException

setClient

public void setClient(String host,
                      SocketFactory f)
               throws GeneralSecurityException,
                      IOException
Throws:
GeneralSecurityException
IOException

removeClient

public void removeClient(String host)

removeClient

public void removeClient(SocketFactory sf)

hostnamePossibilities

private Set hostnamePossibilities(String host)

trustOurself

private void trustOurself()
                   throws GeneralSecurityException,
                          IOException
Throws:
GeneralSecurityException
IOException

trustEachOther

private void trustEachOther(SSLClient client,
                            SSLServer server)
                     throws GeneralSecurityException,
                            IOException
Throws:
GeneralSecurityException
IOException

getServer

public ServerSocketFactory getServer()

getDefaultClient

public SocketFactory getDefaultClient()

getClient

public SocketFactory getClient(String host)

createServerSocket

public ServerSocket createServerSocket(int port)
                                throws IOException
Specified by:
createServerSocket in interface RMIServerSocketFactory
Specified by:
createServerSocket in class RMISocketFactory
Throws:
IOException

createSocket

public Socket createSocket(String host,
                           int port)
                    throws IOException
Specified by:
createSocket in interface RMIClientSocketFactory
Specified by:
createSocket in class RMISocketFactory
Throws:
IOException

getMyDefaultIP

public static String getMyDefaultIP()

getMyInternetFacingIPs

public static SortedSet getMyInternetFacingIPs()
                                        throws SocketException
Throws:
SocketException