diff --git a/examples/provider/rmi/README.md b/examples/provider/rmi/README.md new file mode 100644 index 00000000..6dab8e9d --- /dev/null +++ b/examples/provider/rmi/README.md @@ -0,0 +1,88 @@ + +# Java Remote Method Invocation (RMI) Example Client and Server + +This is a simple example of Java Remote Method Invocation (RMI), including +the implementation of a very basic client (RmiClient.java) and server +(RmiServer.java) with associated remote object interface definition +(RmiRemoteInterface.java). These examples are set up to work over SSL/TLS. + +The `RmiRemoteInterface.java` file defines an interface with one public method +named `String getServerMessage() throws RemoteException;`. This method +should be implemented to one that returns a simple string message from the +server implementation. + +The `RmiServer.java` file implements a simple server, which implements the +`RemoteInterface` class and `getServerMessage()` method. The server binds +an object with the stub "RemoteInterface" to the local default registry at +localhost:1099. + +The `RmiClient.java` file gets an object stub from the remote registry, and +makes the remote method invocation for `getServerMessage()`. + +## Compiling Example Code + +The example code is set up to compile as part of the `ant examples` target: + +``` +$ cd wolfssljni +$ ./java.sh +$ ant +$ ant examples +``` + +## Start the Server + +To start the server, run the following helper script from the wolfSSL JNI/JSSE +root directory: + +``` +$ cd wolfssljni +$ ./examples/provider/rmi/RmiServer.sh +``` + +You should see the following message after the server has finished setting up +the RMI object: + +``` +Created server TrustManagerFactory +Created server KeyManagerFactory +Created server SSLContext +Created server SSLServerSocketFactory +Creating server Socket +Created server TrustManagerFactory +Created server KeyManagerFactory +Created server SSLContext +Created server SSLServerSocketFactory +Server started, listening for connections +``` + +## Connecting the Client + +To start the client, run the following helper script from the wolfSSL JNI/JSSE +root directory: + +``` +$ cd wolfssljni +$ ./examples/provider/rmi/RmiClient.sh +``` + +You should see the response sent back from the server method: + +``` +Created client TrustManagerFactory +Created client KeyManagerFactory +Created client SSLContext +Created client SocketFactory +Creating client Socket +Created client TrustManagerFactory +Created client KeyManagerFactory +Created client SSLContext +Created client SocketFactory +Creating client Socket +Message from server via RMI: Hello from server +``` + +## Support + +For support or questions with these examples, please email support@wolfssl.com. + diff --git a/examples/provider/rmi/RmiClient.java b/examples/provider/rmi/RmiClient.java new file mode 100644 index 00000000..8cb223e8 --- /dev/null +++ b/examples/provider/rmi/RmiClient.java @@ -0,0 +1,343 @@ +/* RmiClient.java + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +import java.util.Arrays; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; +import java.security.KeyStore; +import java.net.Socket; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLContext; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManagerFactory; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicIntegerArray; + +import java.net.InetAddress; +import java.rmi.server.RMIClientSocketFactory; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.security.Security; + +import com.wolfssl.WolfSSL; +import com.wolfssl.provider.jsse.WolfSSLProvider; + +/** + * Client class calling remote object interface on Server via RMI. + * + * This client is set up to make {N} number of connections to each + * RMI registry port broadcast by the server. For example, if the server + * has created 1 RMI registry entry, then this client will by default make + * 1 connection to it. {N} is controlled by the command line argument "-n XX". + * If started with "-n 2", this client would make 2 connections to the one + * server registry. + * + * If the server has registered more than one registry entry, 2 for example, + * then by default this client will make 2 connections (one to each port). If + * started with "-n 2", then the client will make 4 total connections (two to + * each of the two server RMI ports). + */ +public class RmiClient +{ + /* RMI registry port, needs to be same as RmiServer.java */ + private static final int registryStartingPort = 11115; + + /* Keystore files and passwords, holding certs/keys/CAs */ + private static String clientJKS = "../provider/client.jks"; + private static String caJKS = "../provider/ca-server.jks"; + private static String jksPass = "wolfSSL test"; + + /* Keystore file format */ + private static String keystoreFormat = "JKS"; + + /* TLS protocol version - "TLS" uses highest compiled in */ + private static String tlsVersion = "TLS"; + + /* JSSE provider to use for this example */ + private static String jsseProvider = "wolfJSSE"; + + /* Number of client connections rounds to start. One "round" consists + * of 3 connections, one each to registryPortA/B/C. */ + int numClientConnections = 1; + + /* Do random sleep before starting client threads */ + boolean doRandomSleep = false; + + /* Create new unique SocketFactory for each client, otherwise use + * same single SocketFactory across all */ + boolean useNewSF = false; + + /* Buffer size for test buffers sent/received */ + private static final int BUFFER_SIZE = 2048; + + /* Keep track of how many connections succeed or fail */ + final AtomicIntegerArray success = new AtomicIntegerArray(1); + final AtomicIntegerArray failures = new AtomicIntegerArray(1); + + /* Use single SSLContext across threads */ + private static SSLContext ctx = null; + /* Use single SocketFactory across threads if useCached true */ + private static SocketFactory sf = null; + + /** + * Create client SocketFactory for use with RMI over TLS. + * @return new SocketFactory object or null on error. + */ + private static SocketFactory createClientSocketFactory(boolean useCached) { + + TrustManagerFactory tm = null; + KeyManagerFactory km = null; + KeyStore cert, pKey = null; + + try { + /* Only create SSLContext once */ + if (ctx == null) { + /* Create TrustManagerFactory with certs to verify peer */ + tm = TrustManagerFactory.getInstance("SunX509", jsseProvider); + cert = KeyStore.getInstance(keystoreFormat); + cert.load(new FileInputStream(caJKS), jksPass.toCharArray()); + tm.init(cert); + System.out.println("Created client TrustManagerFactory"); + + /* Create KeyManagerFactory with client cert/key */ + pKey = KeyStore.getInstance(keystoreFormat); + pKey.load(new FileInputStream(clientJKS), jksPass.toCharArray()); + km = KeyManagerFactory.getInstance("SunX509", jsseProvider); + km.init(pKey, jksPass.toCharArray()); + System.out.println("Created client KeyManagerFactory"); + + /* Create SSLContext, doing peer auth */ + ctx = SSLContext.getInstance(tlsVersion, jsseProvider); + ctx.init(km.getKeyManagers(), tm.getTrustManagers(), null); + System.out.println("Created client SSLContext"); + } + + if (!useCached) { + return ctx.getSocketFactory(); + } + else { + if (sf == null) { + /* Create SocketFactory */ + sf = ctx.getSocketFactory(); + System.out.println("Created client SocketFactory"); + } + } + + } catch (Exception e) { + System.out.println("Exception when creating client SocketFactory"); + e.printStackTrace(); + return null; + } + + return sf; + } + + class ClientThread implements Runnable + { + private String host = null; + private int port = 0; + private SocketFactory sf = null; + private CountDownLatch latch = null; + + public ClientThread(String host, int port, SocketFactory sf, + CountDownLatch latch) { + + this.host = host; + this.port = port; + this.sf = sf; + this.latch = latch; + } + + public void run() { + + try { + /* Introduce a random sleep per thread, so all client + * threads are not started concurrently. Better tests + * session cache / resumption */ + if (doRandomSleep) { + Thread.sleep((long)((Math.random() * 2000) + 1000)); + } + + /* Get stub for the SSL/TLS registry on specified host */ + Registry registry = LocateRegistry.getRegistry(this.host, + this.port, new RmiTLSClientSocketFactory(this.sf)); + + /* Invoke lookup on remote registry to get remote object stub */ + RmiRemoteInterface ri = + (RmiRemoteInterface)registry.lookup("RmiRemoteInterface"); + + /* Send message to server, works over RMI */ + ri.sendMessage("Hello server from client"); + + /* Get back server response, works over RMI */ + String serverMessage = ri.getMessage(); + System.out.println( + "Message from server via RMI: " + serverMessage); + + /* Send byte array, works over RMI */ + byte[] tmp = new byte[BUFFER_SIZE]; + Arrays.fill(tmp, (byte)0x06); + ri.sendByteArray(tmp); + System.out.println("Sent byte array: " + tmp.length + " bytes"); + + /* Get byte array, works over RMI */ + byte[] recv = ri.getByteArray(); + System.out.println("Got byte array: " + recv.length + " bytes"); + + success.incrementAndGet(0); + + /* Can comment out next line if testing with Java System + * properties like below and want to test behavior around + * timeouts and how that changes connection dynamics: + * + * -Dsun.rmi.transport.connectionTimeout=1000 + * -Dsun.rmi.transport.tcp.readTimeout=1000 + * + * These system properties could be set in RmiClient.sh + * before starting the example. + */ + //Thread.sleep(2000); + + } catch (Exception e) { + failures.incrementAndGet(0); + e.printStackTrace(); + } finally { + this.latch.countDown(); + } + + } + } + + public RmiClient(String[] args) { + + int[] registryPorts = null; + + /* Register wolfJSSE as top priority JSSE provider */ + Security.insertProviderAt(new WolfSSLProvider(), 1); + + /* pull in command line options from user */ + for (int i = 0; i < args.length; i++) + { + String arg = args[i]; + + if (arg.equals("-n")) { + if (args.length < i+2) { + printUsage(); + } + numClientConnections = Integer.parseInt(args[++i]); + } + else if (arg.equals("-randsleep")) { + doRandomSleep = true; + } + else if (arg.equals("-newSF")) { + useNewSF = true; + } + else if (arg.equals("-jsseProv")) { + if (args.length < i+2) { + printUsage(); + } + jsseProvider = args[++i]; + + } else { + printUsage(); + } + } + + try { + /* Server hostname, null indicates localhost */ + String host = InetAddress.getLocalHost().getHostName(); + + /* Make single first client connection in order to get the + * list of registry ports that have been created. Then we can + * go and start client threads that connect and interact with + * each one. */ + Registry registry = LocateRegistry.getRegistry(host, + registryStartingPort, new RmiTLSClientSocketFactory( + createClientSocketFactory(useNewSF))); + RmiRemoteInterface ri = + (RmiRemoteInterface)registry.lookup("RmiRemoteInterface"); + registryPorts = ri.getRegistryPorts(); + System.out.println("Got list of server registry ports"); + for (int i = 0; i < registryPorts.length; i++) { + System.out.println(host + ": " + registryPorts[i]); + } + + List clientList = new ArrayList(); + CountDownLatch latch = new CountDownLatch( + numClientConnections * registryPorts.length); + + /* Reset static thread counters */ + success.set(0, 0); + failures.set(0, 0); + + for (int i = 0; i < numClientConnections; i++) { + for (int j = 0; j < registryPorts.length; j++) { + ClientThread client = + new ClientThread(host, registryPorts[j], + createClientSocketFactory(useNewSF), latch); + clientList.add(client); + } + } + + ExecutorService executor = Executors.newFixedThreadPool( + clientList.size()); + + for (final ClientThread c: clientList) { + executor.execute(c); + } + + latch.await(); + executor.shutdown(); + + } catch (Exception e) { + + System.out.println("Client exception: " + e.toString()); + e.printStackTrace(); + } + + System.out.println("================================================="); + System.out.println("All Client Connections Finished"); + System.out.println("Successful = " + success.get(0)); + System.out.println("Failed = " + failures.get(0)); + System.out.println("================================================="); + } + + public static void main(String[] args) { + new RmiClient(args); + } + + private void printUsage() { + System.out.println("Java RMI example threaded client usage:"); + System.out.println("-n \tNumber of client connection rounds"); + System.out.println("-randsleep\tRandom sleep before starting threads"); + System.out.println("-newSF\tUse new SocketFactory for each " + + "client connection"); + System.out.println("-jsseProv \tJSSE provider to use " + + "(ex: wolfJSSE, SunJSSE)"); + System.exit(1); + } +} + diff --git a/examples/provider/rmi/RmiClient.sh b/examples/provider/rmi/RmiClient.sh new file mode 100755 index 00000000..8a14bd59 --- /dev/null +++ b/examples/provider/rmi/RmiClient.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +cd ./examples/build +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../lib/:/usr/local/lib +java -classpath ../../lib/wolfssl.jar:../../lib/wolfssl-jsse.jar:./ -Dsun.boot.library.path=../../lib/ -Dwolfjsse.debug=true -Dsun.rmi.transport.connectionTimeout=1000 -Dsun.rmi.transport.tcp.readTimeout=1000 RmiClient "$@" +#java -classpath ../../lib/wolfssl.jar:../../lib/wolfssl-jsse.jar:./ -Dsun.boot.library.path=../../lib/ -Dwolfjsse.debug=true RmiClient "$@" + diff --git a/examples/provider/rmi/RmiRemoteInterface.java b/examples/provider/rmi/RmiRemoteInterface.java new file mode 100644 index 00000000..eb1c703f --- /dev/null +++ b/examples/provider/rmi/RmiRemoteInterface.java @@ -0,0 +1,37 @@ +/* RmiRemoteInterface.java + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +import java.util.List; +import java.rmi.Remote; +import java.rmi.RemoteException; + +/** + * Interface defining the remote object interface. + */ +public interface RmiRemoteInterface extends Remote { + String getMessage() throws RemoteException; + byte[] getByteArray() throws RemoteException; + void sendMessage(String message) throws RemoteException; + void sendByteArray(byte[] arr) throws RemoteException; + int[] getRegistryPorts() throws RemoteException; +} + + diff --git a/examples/provider/rmi/RmiServer.java b/examples/provider/rmi/RmiServer.java new file mode 100644 index 00000000..247ff6af --- /dev/null +++ b/examples/provider/rmi/RmiServer.java @@ -0,0 +1,316 @@ +/* RmiServer.java + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.net.Socket; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManagerFactory; + +import java.rmi.registry.Registry; +import java.rmi.registry.LocateRegistry; +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.security.Security; + +import com.wolfssl.WolfSSL; +import com.wolfssl.provider.jsse.WolfSSLProvider; + +/** + * Server class implementing RemoteInterface methods to operate over RMI. + * + * This server has been set up to register a dynamic number of services on + * different ports. By default, only one RMI registry entry will be created + * on the default port of "registryStartingPort". If the user starts the + * example with "-n XX", then this server will create and register that + * many RMI entries. Port numbers will increment from "registryStartingPort". + * For example, starting this example with "-n 3" will create RMI registry + * entries on ports 11115, 11116, and 11117. + * + * The client will create one RMI connection to the default port first, then + * call the RMI interface getRegistryPorts() to get an array of ports that + * this server has started. The client will then subsequently make connections + * to each of those ports. At least one connection, or maybe more if the client + * example was started with "-n XX" greater than 1. + */ +public class RmiServer extends UnicastRemoteObject implements RmiRemoteInterface +{ + /* RMI registry ports. We start by creating one registry, but the user + * can tell us how many registries/ports to create using cmd line args. + * The number of registries can be increased from 1 to simulate + * connecting to multiple server registries from a client. */ + private static final int registryStartingPort = 11115; + + /* Number of RMI registries to create */ + private int numRegistries = 1; + + /* List holding ports of registries created. Static so one across all + * RmiServer objects */ + private static List registryPorts = new ArrayList<>(); + + /* Keystore files and passwords, holding certs/keys/CAs */ + private static String clientJKS = "../provider/client.jks"; + private static String clientCaJKS = "../provider/ca-server.jks"; + private static String serverJKS = "../provider/server.jks"; + private static String serverCaJKS = "../provider/ca-client.jks"; + private static String jksPass = "wolfSSL test"; + + /* Keystore file format */ + private static String keystoreFormat = "JKS"; + + /* TLS protocol version - "TLS" uses highest compiled in */ + private static String tlsVersion = "TLS"; + + /* JSSE provider to use for this example */ + private static String jsseProvider = "wolfJSSE"; + + /* Buffer size for test buffers sent/received */ + private static final int BUFFER_SIZE = 2048; + + /** + * Return message from server. Implementation of + * RmiRemoteInterface.getMessage(), callable via RMI from client. + */ + public String getMessage() { + return "Hello from server"; + } + + /** + * Send message to server. Implementation of + * RmiRemoteInterface.sendMessage(), callable via RMI from client. + */ + public void sendMessage(String message) { + System.out.println("Message received: " + message); + } + + /** + * Get dummy byte array from server. Implementation of + * RmiRemoteInterface.getByteArray(), callable via RMI from client. + */ + public byte[] getByteArray() { + byte[] arr = new byte[BUFFER_SIZE]; + Arrays.fill(arr, (byte)0x05); + System.out.println("Sending byte array (length: " + arr.length + ")"); + return arr; + } + + /** + * Send dummy byte array to caller. Implementation of + * RmiRemoteInterface.sendByteArray(), callable via RMI from client. + */ + public void sendByteArray(byte[] arr) { + if (arr != null) { + System.out.println("Received byte array: size = " + arr.length); + } + else { + System.out.println("ERROR: received null byte array"); + } + } + + /** + * Get registry ports that we have created. Implementation of + * RmiRemoteInterface.getRegistryPorts(), callable via RMI from client. + */ + public int[] getRegistryPorts() { + int[] ret = new int[registryPorts.size()]; + for (int i = 0; i < registryPorts.size(); i++) { + ret[i] = registryPorts.get(i).intValue(); + } + return ret; + } + + /** + * Create client SocketFactory for use with RMI over TLS. + * @return new SocketFactory object or null on error. + */ + private static SocketFactory createClientSocketFactory() { + + SSLContext ctx = null; + TrustManagerFactory tm = null; + KeyManagerFactory km = null; + KeyStore cert, pKey = null; + SocketFactory sf = null; + + try { + /* Create TrustManagerFactory with certs to verify peer */ + tm = TrustManagerFactory.getInstance("SunX509", jsseProvider); + cert = KeyStore.getInstance(keystoreFormat); + cert.load(new FileInputStream(clientCaJKS), jksPass.toCharArray()); + tm.init(cert); + System.out.println("Created client TrustManagerFactory"); + + /* Create KeyManagerFactory with client cert/key */ + pKey = KeyStore.getInstance(keystoreFormat); + pKey.load(new FileInputStream(clientJKS), jksPass.toCharArray()); + km = KeyManagerFactory.getInstance("SunX509", jsseProvider); + km.init(pKey, jksPass.toCharArray()); + System.out.println("Created client KeyManagerFactory"); + + /* Create SSLContext, doing peer auth */ + ctx = SSLContext.getInstance(tlsVersion, jsseProvider); + ctx.init(km.getKeyManagers(), tm.getTrustManagers(), null); + System.out.println("Created client SSLContext"); + + /* Create SocketFactory */ + sf = ctx.getSocketFactory(); + System.out.println("Created client SocketFactory"); + + } catch (Exception e) { + System.out.println("Exception when creating client SocketFactory"); + e.printStackTrace(); + return null; + } + + return sf; + } + + /** + * Create server SSLServerSocketFactory for use with RMI over TLS. + * @return new SSLServerSocketFactory object or null on error. + */ + private static SSLServerSocketFactory createServerSocketFactory() { + + SSLContext ctx = null; + TrustManagerFactory tm = null; + KeyManagerFactory km = null; + KeyStore cert, pKey = null; + SSLServerSocketFactory sf = null; + + try { + /* Create TrustManagerFactory with certs to verify peer */ + tm = TrustManagerFactory.getInstance("SunX509", jsseProvider); + cert = KeyStore.getInstance(keystoreFormat); + cert.load(new FileInputStream(serverCaJKS), jksPass.toCharArray()); + tm.init(cert); + System.out.println("Created server TrustManagerFactory"); + + /* Create KeyManagerFactory with server cert/key */ + pKey = KeyStore.getInstance(keystoreFormat); + pKey.load(new FileInputStream(serverJKS), jksPass.toCharArray()); + km = KeyManagerFactory.getInstance("SunX509", jsseProvider); + km.init(pKey, jksPass.toCharArray()); + System.out.println("Created server KeyManagerFactory"); + + /* Create SSLContext, doing peer auth */ + ctx = SSLContext.getInstance(tlsVersion, jsseProvider); + ctx.init(km.getKeyManagers(), tm.getTrustManagers(), null); + System.out.println("Created server SSLContext"); + + /* Create SocketFactory */ + sf = (SSLServerSocketFactory)ctx.getServerSocketFactory(); + System.out.println("Created server SSLServerSocketFactory"); + + } catch (Exception e) { + System.out.println("Exception when creating server SocketFactory"); + e.printStackTrace(); + return null; + } + + return sf; + } + + public RmiServer() throws RemoteException { + /* RmiRemoteInterface default constructor throws RemoteException */ + super(); + } + + public RmiServer(String[] args) throws RemoteException { + + /* Register wolfJSSE as top priority JSSE provider */ + Security.insertProviderAt(new WolfSSLProvider(), 1); + + /* pull in command line options from user */ + for (int i = 0; i < args.length; i++) + { + String arg = args[i]; + + if (arg.equals("-n")) { + if (args.length < i+2) { + printUsage(); + } + numRegistries = Integer.parseInt(args[++i]); + } + else if (arg.equals("-jsseProv")) { + if (args.length < i+2) { + printUsage(); + } + jsseProvider = args[++i]; + } + else { + printUsage(); + } + } + + try { + /* Create one SocketFactory for server and one for client */ + SocketFactory cliSF = createClientSocketFactory(); + SSLServerSocketFactory srvSF = createServerSocketFactory(); + + /* Register object with Java RMI registry. Create new registry + * using SSL/TLS on specified port. If bind() fails, will throw + * a RemoteException. */ + for (int i = 0; i < numRegistries; i++) { + int port = registryStartingPort + i; + Registry registry = LocateRegistry.createRegistry(port, + new RmiTLSClientSocketFactory(cliSF), + new RmiTLSServerSocketFactory(srvSF)); + registry.bind("RmiRemoteInterface", new RmiServer()); + registryPorts.add(port); + } + + System.out.println("Registries created, listening for connections"); + System.out.println("Available registries:"); + for (int i = 0; i < registryPorts.size(); i++) { + System.out.println("port: " + registryPorts.get(i)); + } + + } catch (Exception e) { + System.out.println("Server exception: " + e.toString()); + e.printStackTrace(); + } + } + + public static void main(String[] args) { + try { + new RmiServer(args); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + private void printUsage() { + System.out.println("Java RMI example server usage:"); + System.out.println("-n \tNumber of server registries to create, " + + "port numbers increment from 11115"); + System.out.println("-jsseProv \tJSSE provider to use " + + "(ex: wolfJSSE, SunJSSE)"); + System.exit(1); + } +} + diff --git a/examples/provider/rmi/RmiServer.sh b/examples/provider/rmi/RmiServer.sh new file mode 100755 index 00000000..308b0d32 --- /dev/null +++ b/examples/provider/rmi/RmiServer.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +cd ./examples/build +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../lib/:/usr/local/lib +java -classpath ../../lib/wolfssl-jsse.jar:./ -Dsun.boot.library.path=../../lib/ -Dwolfjsse.debug=true RmiServer "$@" + diff --git a/examples/provider/rmi/RmiTLSClientSocketFactory.java b/examples/provider/rmi/RmiTLSClientSocketFactory.java new file mode 100644 index 00000000..8a4521a2 --- /dev/null +++ b/examples/provider/rmi/RmiTLSClientSocketFactory.java @@ -0,0 +1,67 @@ +/* RmiTLSClientSocketFactory.java + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +import java.rmi.server.RMIClientSocketFactory; +import java.io.Serializable; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.net.Socket; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLContext; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManagerFactory; + +public class RmiTLSClientSocketFactory + implements RMIClientSocketFactory, Serializable +{ + SocketFactory sf = null; + + public RmiTLSClientSocketFactory(SocketFactory sf) { + this.sf = sf; + } + + public Socket createSocket(String host, int port) throws IOException { + + if (this.sf == null) { + return null; + } + + System.out.println("Creating client Socket"); + return sf.createSocket(host, port); + } + + public int hashCode() { + return getClass().hashCode(); + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + else if (obj == null || (obj.getClass() != getClass())) { + return false; + } + return true; + } +} + diff --git a/examples/provider/rmi/RmiTLSServerSocketFactory.java b/examples/provider/rmi/RmiTLSServerSocketFactory.java new file mode 100644 index 00000000..828a536d --- /dev/null +++ b/examples/provider/rmi/RmiTLSServerSocketFactory.java @@ -0,0 +1,69 @@ +/* RmiTLSServerSocketFactory.java + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +import java.rmi.server.RMIServerSocketFactory; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.net.ServerSocket; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManagerFactory; + +public class RmiTLSServerSocketFactory implements RMIServerSocketFactory +{ + /* Create one SSLServerSocketFactory */ + private SSLServerSocketFactory sf = null; + + public RmiTLSServerSocketFactory(SSLServerSocketFactory sf) { + this.sf = sf; + } + + public ServerSocket createServerSocket(int port) throws IOException { + + if (sf == null) { + return null; + } + + System.out.println("Creating server Socket"); + return (ServerSocket)sf.createServerSocket(port); + + } + + public int hashCode() { + return getClass().hashCode(); + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + else if (obj == null || (obj.getClass() != getClass())) { + return false; + } + return true; + } +} + +