JAVA Toolkit
| home | contact




rmi notes

We will first explain how to get the demo working and then move on
to some explanation, usage recommendations, and JDK version notes.
It is recommended that you read this entire document even if some
sections may not seem to apply to you at the moment.

General

There are no special requirements RMI has about the socket layer that
transports its calls. In other words, the core SSL library does not know
or care about RMI, it is an add-on on top of it. All we do is provide
a description and a demo of how we think our library should be used
to secure RMI.
If you want to do
something differently, just do it.

There are three players in RMI: the server, who offers
services to remote programs; the client, who uses those services; and
the registry, which helps clients find servers.
These player communicate using sockets and all this communication can
be secured using SSL/TLS. This is what is done in the demo,
where all communication between any of these players is encrypted using
strong cryptography and clients and servers are authenticated using certificates.

The RMI Demo

To run the demo follow these steps:

  1. Get yourself the required software. You of course need a JDK, either
    a 1.1 version (1.1.7 or later recommended) or 1.2 (1.2.2 or later
    recommended), 1.3 or later, which one you use is up to you. If you
    use a JDK version greater than 1.3 (1.4, 1.5, 1.6) you must have the
    signed version of iaik_jce_(full).jar in your classpath.
    Make sure that iaik_ssl.jar, iaik_ssl_demo.jar (demo classes),
    iaik_jce(_full).jar (most appropriate IAIK JCE 3.142 or later) and
    jdk11x_update.jar (from IAIK JCE, only for JDK 1.1) as well as the current
    directory are in your CLASSPATH. For example:

    set CLASSPATH=%CLASSPATH%;.;lib\iaik_ssl.jar;lib\iaik_ssl_demo.jar;lib\iaik_jce_full.jar;lib\jdk11x_update.jar

    Use this CLASSPATH for all the steps given below!

  2. Next execute

    rmic -d . demo.rmi.SSLHelloImpl

    with the
    rmi compiler of your JDK. This will generate the required RMI stub and
    skeleton classes. If you use JDK 1.2 or later you can also select RMI compatibility
    options, the demo works with all of them.

  3. Make sure the SSL keystore isasilk.keystore is in the
    current directory. If not run

    java demo.SetupKeyStore
  4. Start the RMI registry. Because it is SSL secured you cannot
    use the standard registry, start

    java demo.rmi.SSLRMIUtil

    instead. It should print the success message

    SSL rmiregistry started successfully...
  5. From another window start our RMI server using the same CLASSPATH:

    java demo.rmi.SSLHelloImpl

    It will register with the RMI registry and then print

    SSLHelloImpl created and bound in the registry to the name SSLHelloServer
  6. From yet another window start our client using the same CLASSPATH:

    java demo.rmi.SSLHelloClient

    It will first contact the RMI registry to find out where to find the
    SSLHelloServer, then contact the server and execute its sayHello()
    method. That call is transparently made via RMI, which in turn
    transparently makes use of SSL. The program then prints

    Message from RMI Server: Hello World over SSL!

As mentioned before, the entire communication was secured via SSL/TLS.
See below for more information.

Securing the RMI in an Existing Application

Actually using RMI over SSL is extremely simple. Done in the way
explained in this document the only changes required are in the
setup code, and possibly in the use of a different RMI registry.

In short, all that is required is that at the beginning of each
application that starts RMI clients, servers, or a registry
the SSL policies are set via SSLContexts and a custom socket
factory is activated. That's all. As implemented in the demo
this requires just three additional methods which could be
used in almost exactly the same way in real world applications,
only the certificates and private keys used should be
parametrized there.

The assumptions the statements above are based on are:

  • You are using RMI over SSL in the way described in this document.
  • All code is available locally, no code download occurs.
  • You are using SSL for all calls and are using identical
    SSL security parameters for all calls.

For more information about the setup required please see the demo
source code, especially the class SSLRMIUtil.

RMI Communication and the Demo Explained

RMI uses sockets for all network communication. As such it is well suited
to be secured using SSL. Because the designers had that in mind and do not
instantiate sockets directly and use a SocketFactory instead this is also
fairly easy to do. Before we get into that, let us first explain how
RMI uses sockets.

Who talks to whom in RMI?

This section describes who uses what type of sockets for what purpose.
It assumes that no code downloading occurs, see also the note below.

  • RMI registry
    ServerSockets: it uses a ServerSocket, per default on port 1099.
    It waits for requests by servers binding,re-binding, un-binding, etc. implementations or clients
    who want to locate servers. client Sockets: the registry also uses
    client sockets to establish connectionsto servers right after they have registered.
  • ServerSockets: ServerSocket, per default a random local port. It is used
    to accept connections from the client and receive requests and send responses.
  • client Sockets: a client socket is used for communication
    with the RMI registry, in particular to register the server implementation.
  • ServerSockets: not used.
  • client Sockets: client sockets are used for the communication
    with the RMI registry (to find the server implementation it wants to talk
    to) and to make the actual RMI call to the server.

Types of Traffic

As can be seen from the explanation above, there are two types of
RMI traffic:

  1. Communication with the registry
  2. Communication with the actual RMI server

In principle both are worth protecting, the second obviously more than
the first, after all this is what we are here to do. The communication
with the RMI registry is not as critical as might appear at first.

Assume an attacker posing as the RMI registry to redirect calls
to its own server. If the RMI registry traffic is not secured it
can of course easily do so, but the client would detect the
tampering in the server authentication phase of the actual RMI call
as that call is secured.
That means, all that can really be achieved is a denial of service
attack that prevents the client from making some or any RMI calls,
but the same effect can be achieved by preventing the client from
connecting to the registry in the first place. The difference is
only when that tampering is detected.

Leaving RMI Traffic Unprotected

In environments where this is not a concern it is possible to leave
RMI registry traffic unprotected. Although there is no immediate way
in the RMI API for a SocketFactory to distinguish between sockets
created for the RMI registry and sockets created for ordinary RMI
calls this can be done by simply checking the port number, assuming
the default port 1099 or another port number known in
advance is used for the RMI registry. This is demonstrated
in the SocketFactory implementation supplied with the demo, see its
source.

In case you decide to leave RMI registry traffic unsecured there
is actually no longer a need to use the customized registry
supplied with the demo. Although the registry's call to the
server in reponse to its registration request will fail
(talking plain instead of SSL/TLS) the
registration is successful nevertheless. In other words, you
can use the standard RMI registry or whatever other registry
you want to use, which also allows you to use a common registry
for secured and not secured RMI calls. However, remember that
using a secured RMI registry provides some additional security.

Setup Needed

As shown, all of the three partners involved in RMI all
except the client, which uses client sockets only, use both
client and server sockets. That means, assuming strong client
and server authentication is always used, they all require the
respective certificates. This is reflected in the setup code the
demos use.

In the demo implementation this setup is achieved
using a single call to SSLRMIRegistry.setSSLSocketFactory()
which performs three things:

  • If selected, sets up the client side SSL parameters. This
    includes loading the necessary private key and certificates for
    client authentication, setting the servers which to trust, and making
    all other settings to the SSLContext.
  • If selected, sets up the server side SSL parameters.
    The equivalent of the client side setup is performed.
  • Initializes and activates the custom RMI SocketFactory,
    which returns the SSL sockets.

Again, note that strictly speaking the SSL RMI registry does
not need a client certificate, as noted before. Also note
that if you decide to leave RMI traffic unprotected, the
server certificates for the RMI registry and the client certificate
for the RMI server are not required either. In other words,
in that case you only need client certificates on clients
and server certificates on servers.

RMI in JDK 1.2 or later

Some improvements have been made to RMI 1.2. In particular,
it is possible to use different SocketFactories
for different remote objects. This also makes it possible to use
secured and non-secured calls within a single VM.

However, the current
demo does not make use of these improvements. As mentioned
before this does preclude you from using them in your own
applications.

Usage Recommendations and Notes

  • The demo uses certificates from the demo SSL keystore, the same server
    and client certificates for all programs. This is of course generally
    not advisable, you should use unique certificates for each communication
    partner.
  • RMI supports methods of tunneling RMI calls through firewalls. This
    feature will not work for RMI over SSL. The reason is that the
    JDK firewall tunneling mechanisms operate on top of the sockets and
    assume they can talk plain HTTP etc. over them. This of course cannot
    work for any type of custom sockets (like SSLSockets), as they
    perform additional encodings on the data. This could be considered
    a design flaw in the RMI implementation.
  • Using code downloading is generally not recommended. Any code in a
    security application should be obtained in a way compliant with
    the security policy used. In our case, for automatic code downloading
    this would mean that the code should be obtained in a way as secure
    as the RMI calls that are later made. This could be achieved by either
    also downloading the code using strong SSL with authentication
    or possibly using code signing (if appropriately configured). Unless
    that is done code downloading over e.g. plain HTTP introduces an
    obvious security hole.
  • The RMI SocketFactory setting is global and can only be made once.
    This means that it is not easily possible to use secured and non
    secured RMI calls at the same time. This limitation was lifted in
    JDK 1.2, see the section above.
 

 
print    tip a friend
back to previous page back  |  top to the top of the page