1 /*
  2  * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 5016500
 27  * @summary Test SslRmi[Client|Server]SocketFactory SSL socket parameters.
 28  * @run main/othervm SSLSocketParametersTest 1
 29  * @run main/othervm SSLSocketParametersTest 2
 30  * @run main/othervm SSLSocketParametersTest 3
 31  * @run main/othervm SSLSocketParametersTest 4
 32  * @run main/othervm SSLSocketParametersTest 5
 33  * @run main/othervm SSLSocketParametersTest 6
 34  * @run main/othervm SSLSocketParametersTest 7
 35  */
 36 import java.io.IOException;
 37 import java.io.File;
 38 import java.io.Serializable;
 39 import java.net.ServerSocket;
 40 import java.net.Socket;
 41 import java.rmi.Remote;
 42 import java.rmi.RemoteException;
 43 import java.rmi.server.RMIClientSocketFactory;
 44 import java.rmi.server.RMIServerSocketFactory;
 45 import java.rmi.server.UnicastRemoteObject;
 46 import javax.net.ssl.SSLContext;
 47 import javax.rmi.ssl.SslRMIClientSocketFactory;
 48 import javax.rmi.ssl.SslRMIServerSocketFactory;
 49 
 50 public class SSLSocketParametersTest implements Serializable {
 51 
 52     public interface Hello extends Remote {
 53         public String sayHello() throws RemoteException;
 54     }
 55 
 56     public class HelloImpl extends UnicastRemoteObject implements Hello {
 57 
 58         public HelloImpl(int port,
 59                          RMIClientSocketFactory csf,
 60                          RMIServerSocketFactory ssf)
 61             throws RemoteException {
 62             super(port, csf, ssf);
 63         }
 64 
 65         public String sayHello() {
 66             return "Hello World!";
 67         }
 68 
 69         public Remote runServer() throws IOException {
 70             System.out.println("Inside HelloImpl::runServer");
 71             // Get a remote stub for this RMI object
 72             //
 73             Remote stub = toStub(this);
 74             System.out.println("Stub = " + stub);
 75             return stub;
 76         }
 77     }
 78 
 79     public class HelloClient {
 80 
 81         public void runClient(Remote stub) throws IOException {
 82             System.out.println("Inside HelloClient::runClient");
 83             // "obj" is the identifier that we'll use to refer
 84             // to the remote object that implements the "Hello"
 85             // interface
 86             Hello obj = (Hello) stub;
 87             String message = obj.sayHello();
 88             System.out.println(message);
 89         }
 90     }
 91 
 92     public static class ClientFactory extends SslRMIClientSocketFactory {
 93 
 94         public ClientFactory() {
 95             super();
 96         }
 97 
 98         public Socket createSocket(String host, int port) throws IOException {
 99             System.out.println("ClientFactory::Calling createSocket(" +
100                                host + "," + port + ")");
101             return super.createSocket(host, port);
102         }
103     }
104 
105     public static class ServerFactory extends SslRMIServerSocketFactory {
106 
107         public ServerFactory() {
108             super();
109         }
110 
111         public ServerFactory(String[] ciphers,
112                              String[] protocols,
113                              boolean need) {
114             super(ciphers, protocols, need);
115         }
116 
117         public ServerFactory(SSLContext context,
118                              String[] ciphers,
119                              String[] protocols,
120                              boolean need) {
121             super(context, ciphers, protocols, need);
122         }
123 
124         public ServerSocket createServerSocket(int port) throws IOException {
125             System.out.println("ServerFactory::Calling createServerSocket(" +
126                                port + ")");
127             return super.createServerSocket(port);
128         }
129     }
130 
131     public void testRmiCommunication(RMIServerSocketFactory serverFactory, boolean expectException) {
132 
133         HelloImpl server = null;
134         try {
135             server = new HelloImpl(0,
136                                     new ClientFactory(),
137                                     serverFactory);
138             Remote stub = server.runServer();
139             HelloClient client = new HelloClient();
140             client.runClient(stub);
141             if (expectException) {
142                 throw new RuntimeException("Test completed without throwing an expected exception.");
143             }
144 
145         } catch (IOException exc) {
146             if (!expectException) {
147                 throw new RuntimeException("An error occurred during test execution", exc);
148             } else {
149                 System.out.println("Caught expected exception: " + exc);
150             }
151 
152         }
153     }
154 
155     private static void testServerFactory(String[] cipherSuites, String[] protocol, String expectedMessage) throws Exception {
156         try {
157             new ServerFactory(SSLContext.getDefault(),
158                     cipherSuites, protocol, false);
159             throw new RuntimeException(
160                     "The expected exception for "+ expectedMessage + " was not thrown.");
161         } catch (IllegalArgumentException exc) {
162             // expecting an exception with a specific message
163             // anything else is an error
164             if (!exc.getMessage().toLowerCase().contains(expectedMessage)) {
165                 throw exc;
166             }
167         }
168     }
169 
170     public void runTest(int testNumber) throws Exception {
171         System.out.println("Running test " + testNumber);
172 
173         switch (testNumber) {
174             /* default constructor - default config */
175             case 1 -> testRmiCommunication(new ServerFactory(), false);
176 
177             /* non-default constructor - default config */
178             case 2 -> testRmiCommunication(new ServerFactory(null, null, false), false);
179 
180             /* needClientAuth=true */
181             case 3 -> testRmiCommunication(new ServerFactory(null, null, null, true), false);
182 
183             /* server side dummy_ciphersuite */
184             case 4 ->
185                 testServerFactory(new String[]{"dummy_ciphersuite"}, null, "unsupported ciphersuite");
186 
187             /* server side dummy_protocol */
188             case 5 ->
189                 testServerFactory(null, new String[]{"dummy_protocol"}, "unsupported protocol");
190 
191             /* client side dummy_ciphersuite */
192             case 6 -> {
193                 System.setProperty("javax.rmi.ssl.client.enabledCipherSuites",
194                         "dummy_ciphersuite");
195                 testRmiCommunication(new ServerFactory(), true);
196             }
197 
198             /* client side dummy_protocol */
199             case 7 -> {
200                 System.setProperty("javax.rmi.ssl.client.enabledProtocols",
201                         "dummy_protocol");
202                 testRmiCommunication(new ServerFactory(), true);
203             }
204 
205             default ->
206                     throw new RuntimeException("Unknown test number: " + testNumber);
207         }
208     }
209 
210     public static void main(String[] args) throws Exception {
211         // Set keystore properties (server-side)
212         //
213         final String keystore = System.getProperty("test.src") +
214                 File.separator + "keystore";
215         System.out.println("KeyStore = " + keystore);
216         System.setProperty("javax.net.ssl.keyStore", keystore);
217         System.setProperty("javax.net.ssl.keyStorePassword", "password");
218 
219         // Set truststore properties (client-side)
220         //
221         final String truststore = System.getProperty("test.src") +
222                 File.separator + "truststore";
223         System.out.println("TrustStore = " + truststore);
224         System.setProperty("javax.net.ssl.trustStore", truststore);
225         System.setProperty("javax.net.ssl.trustStorePassword", "trustword");
226 
227         SSLSocketParametersTest test = new SSLSocketParametersTest();
228         test.runTest(Integer.parseInt(args[0]));
229     }
230 }