2 Replies Latest reply on Oct 20, 2003 3:43 AM by semi

    RMI over SSL, Tips and Code

    Will Newbie

      RMIServerSocketFactory.java

      package jboss;
      
      import java.io.*;
      import java.net.*;
      import java.rmi.server.*;
      import java.security.*;
      import javax.net.*;
      import javax.net.ssl.*;
      import com.sun.net.ssl.*;
      
      /**
       * An RMIServerSocket factory that uses JSSE to produce SSL encrypted
       * sockets.
       *
       * @author Will
       * @version 1.00a 09/21/2001
       */
      public class RMISSLServerSocketFactory implements RMIServerSocketFactory,
       Serializable {
      
       protected transient static ServerSocketFactory socketFactory;
      
       static {
       Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
      
       try {
       char[] passphrase = "password".toCharArray();
      
       KeyStore ks = KeyStore.getInstance("JKS");
       ks.load(new FileInputStream(
       System.getProperty("user.home")+"/.keystore"),
       passphrase
       );
      
       KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
       kmf.init(ks, passphrase);
      
       SSLContext ctx = SSLContext.getInstance("TLS");
       ctx.init(kmf.getKeyManagers(), null, null);
      
       socketFactory = ctx.getServerSocketFactory();
       } catch (Exception e) {
       throw new RuntimeException(e.toString());
       }
      
       }
      
       public ServerSocket createServerSocket(int port) throws IOException {
       return socketFactory.createServerSocket(port);
       }
      
       public boolean equals(Object o) {
       return o instanceof RMISSLServerSocketFactory;
       }
      
       public int hashCode() {
       return RMISSLServerSocketFactory.class.getName().hashCode();
       }
      }
      


      RMISSLClientSocketFactory.java
      package jboss;
      
      import java.io.*;
      import java.net.*;
      import java.rmi.server.*;
      import java.security.Security;
      import javax.net.*;
      import javax.net.ssl.*;
      
      /**
       * An RMIClientSocket factory that uses JSSE to produce SSL encrypted
       * sockets.
       *
       * @author Will
       * @version 1.00a 09/21/2001
       */
      public class RMISSLClientSocketFactory implements RMIClientSocketFactory,
       Serializable {
      
       protected transient static SocketFactory socketFactory;
      
       static {
       Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
       socketFactory = SSLSocketFactory.getDefault();
      
       }
      
       public Socket createSocket(String host, int port) throws IOException {
       return socketFactory.createSocket(host, port);
       }
      
       public boolean equals(Object o) {
       return o instanceof RMISSLClientSocketFactory;
       }
      
       public int hashCode() {
       return RMISSLClientSocketFactory.class.getName().hashCode();
       }
      }
      


      You'll have to edit the RMISSLServerSocketFactory.java to point to the right keystore with a valid certificate that the client will recognize.

      Compile these two classes and place them in the JBoss classpath, along with Sun's jsse.jar.

      Modify standardjboss.xml and add the following lines to the <container-invoker-conf> section for each container you want to use SSL:

      4446
      jboss.RMISSLClientSocketFactory
      jboss.RMISSLServerSocketFactory

      All of your containers configured like this can use the same RMIObjectPort, but non SSL containers must be on a different port.

      Thanks to Scott Stark for pointing out the trick of implementing equals(Object) and hashCode() for the underlying JRMP impl to reuse existing SocketFactories.