001: /*
002: * Copyright (C) The MX4J Contributors.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the MX4J License version 1.0.
006: * See the terms of the MX4J License in the documentation provided with this software.
007: */
008:
009: package mx4j.examples.remote.rmi.ssl;
010:
011: import java.io.IOException;
012: import java.io.InputStream;
013: import java.security.KeyStore;
014: import java.util.HashMap;
015: import java.util.Map;
016: import javax.management.MBeanServer;
017: import javax.management.MBeanServerFactory;
018: import javax.management.ObjectName;
019: import javax.management.remote.JMXConnectorServer;
020: import javax.management.remote.JMXConnectorServerFactory;
021: import javax.management.remote.JMXServiceURL;
022: import javax.management.remote.rmi.RMIConnectorServer;
023: import javax.net.ssl.KeyManagerFactory;
024: import javax.net.ssl.SSLContext;
025:
026: import mx4j.tools.remote.rmi.SSLRMIClientSocketFactory;
027: import mx4j.tools.remote.rmi.SSLRMIServerSocketFactory;
028:
029: /**
030: * This example shows how to setup a JSR 160 RMIConnectorServer over SSL. <br />
031: * An RMI server that has been setup to use SSL uses a private key to encrypt the
032: * communication with the client. The client must know the server's public key in order
033: * to be able to decrypt the communication; public keys are stored in X509 certificates.
034: * This X509 certificate is generated by the server and should be made available to
035: * clients (for example by distributing it). <br />
036: * The private and public key are normally stored in a server-side key store that can
037: * be created by using the JDK's keytool utility; here is a sample command that can
038: * be invoked to generate a keystore:
039: * <pre>
040: * keytool -genkey -v -keystore key.store -storepass storepwd -dname "CN=Anonymous Geek, OU=MX4J Development Team, O=The MX4J Project, L=New York City, S=NY, C=US"
041: * </pre>
042: * It creates a 'key.store' file that must be present in the classpath when running this example. <br />
043: * The next step is to export the X509 certificate for the clients, with the following command:
044: * <pre>
045: * keytool -export -v -storepass storepwd -keystore key.store -file myserver.cer
046: * </pre>
047: * It is also possible to generate a trust store containing the X509 certificate that
048: * can be used directly by the client with the following command:
049: * <pre>
050: * keytool -export -v -storepass storepwd -keystore key.store | keytool -import -v -storepass storepwd -keystore trust.store -noprompt
051: * </pre>
052: * Once you have exported the X509 certificate, follow the instructions on how to setup
053: * the client {@link Client here}.
054: *
055: * @version $Revision: 1.1 $
056: */
057: public class Server {
058: public static void main(String[] args) throws Exception {
059: MBeanServer server = MBeanServerFactory.createMBeanServer();
060:
061: // Register and start the rmiregistry MBean
062: ObjectName namingName = ObjectName
063: .getInstance("naming:type=rmiregistry");
064: server.createMBean("mx4j.tools.naming.NamingService",
065: namingName, null);
066: server.invoke(namingName, "start", null, null);
067: int namingPort = ((Integer) server.getAttribute(namingName,
068: "Port")).intValue();
069:
070: String jndiPath = "/ssljmxconnector";
071: JMXServiceURL url = new JMXServiceURL(
072: "service:jmx:rmi://localhost/jndi/rmi://localhost:"
073: + namingPort + jndiPath);
074:
075: // Create the rmi socket factories for SSL
076: Map environment = new HashMap();
077: SSLContext context = createSSLContext();
078: environment.put(
079: RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,
080: new SSLRMIClientSocketFactory());
081: environment.put(
082: RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
083: new SSLRMIServerSocketFactory(context));
084:
085: // Create and start the RMIConnectorServer
086: JMXConnectorServer connectorServer = JMXConnectorServerFactory
087: .newJMXConnectorServer(url, environment, null);
088: ObjectName connectorServerName = ObjectName
089: .getInstance("connectors:protocol=" + url.getProtocol());
090: server.registerMBean(connectorServer, connectorServerName);
091: connectorServer.start();
092:
093: System.out.println("Server up and running");
094: }
095:
096: /**
097: * Creates and returns an SSLContext by reading information from a keystore. <br>
098: * Change the hardcoded options to match your configuration and your environment.
099: */
100: private static SSLContext createSSLContext() throws Exception {
101: String keystoreName = "key.store";
102: String keystorePassword = "storepwd";
103:
104: KeyStore keystore = KeyStore.getInstance("JKS");
105: InputStream keystoreStream = Server.class.getClassLoader()
106: .getResourceAsStream(keystoreName);
107: // Must check for nullity, otherwise a new empty keystore is created by KeyStore.load
108: if (keystoreStream == null)
109: throw new IOException("Cannot find KeyStore "
110: + keystoreName + " in classpath");
111: keystore.load(keystoreStream, keystorePassword.toCharArray());
112:
113: KeyManagerFactory keyFactory = KeyManagerFactory
114: .getInstance("SunX509");
115: keyFactory.init(keystore, keystorePassword.toCharArray());
116:
117: SSLContext context = SSLContext.getInstance("TLS");
118: context.init(keyFactory.getKeyManagers(), null, null);
119:
120: return context;
121: }
122: }
|