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.