not-yet-commons-ssl
RMI over SSL (experimental)
3 points to consider:
- To run the RMI-SSL server, you must invoke
LocateRegistry.createRegistry( 1099 )
from within your own application. You must do this AFTER calling RMISocketFactory.setSocketFactory( impl )
.
RMISocketFactoryImpl will open the registry on 1099, and will open anonymous RMI servers (where port 0 is
specified) on port 31099.
RMI-SSL, as shown here, doesn't work with $JAVA_HOME/bin/rmiregistry
.
See the example code below for help with RMISocketFactory.setSocketFactory( impl )
.
- To run the RMI-SSL client, you need to find an RMI-SSL server to connect to. See #1, above. ;-)
- If you don't manage to find an RMI-SSL server, then the RMI-SSL client will automatically downgrade itself
to plain-socket. There is an important security consideration to consider regarding this: RMISocketFactoryImpl
at this time only guarantees the security of the registry and the server sockets it opens. Client sockets
it creates might be plain-socket.
RMI over SSL Example
import org.apache.commons.ssl.RMISocketFactoryImpl;
// RMISocketFactoryImpl tries to detect plain sockets, so you should be able to use
// this even in situations where not all of the RMI servers you are talking to are
// using SSL.
RMISocketFactoryImpl impl = new RMISocketFactoryImpl();
// Let's change some settings on our default SSL client.
SSLClient defaultClient = (SSLClient) impl.getDefaultClient();
client.setCheckHostname( false );
client.setCheckCRL( true );
client.setCheckExpiry( false );
// By default we trust Java's "cacerts", as well as whatever cert is on localhost:1099,
// so this is redundant: (Trusting localhost:1099 is some commons-ssl magic).
client.addTrustMaterial( TrustMaterial.DEFAULT );
// But if we had used setTrustMaterial() instead of addTrustMaterial(), we would (probably)
// no longer trust localhost:1099! Using set instead of add causes all previous "adds" to
// to be thrown out.
// Meanwhile, RMI calls to rmi://special.com:1099/ need to trust a self-signed certificate,
// but we don't want to pollute our default trust with this shoddy cert. So only calls
// specifically to "special.com" (any port) will use this.
SSLClient specialClient = new SSLClient();
TrustMaterial tm = new TrustMaterial( "special.pem" );
specialClient.addTrustMaterial( tm );
// Here's where the special cert gets associated with "special.com":
impl.setClient( "special.com", specialClient );
// We're might also want to be an RMI server ourselves!
// By default commons-ssl looks for "~/.keystore" and tries password "changeit",
// but we can change things if we want:
SSLServer server = (SSLServer) impl.getDefaultServer();
tm = new TrustMaterial( "trust_only_these_client_certs.pem" );
KeyMaterial km = new KeyMaterial( "/path/to/myKey.p12", "password".toCharArray() );
server.setTrustMaterial( tm );
server.setKeyMaterial( km );
// This particular RMI server will only accept connections with client certs!
server.setNeedClientAuth( true );
// Finally, we tell Java to use our new RMI socket factory!
RMISocketFactory.setSocketFactory( impl );