1 /*
   2  * Copyright (c) 2013, 2015, 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 import jdk.testlibrary.OutputAnalyzer;
  25 import jdk.testlibrary.ProcessTools;
  26 import jdk.testlibrary.Utils;
  27 
  28 import java.io.BufferedReader;
  29 import java.io.BufferedWriter;
  30 import java.io.IOException;
  31 import java.net.BindException;
  32 import java.nio.charset.Charset;
  33 import java.nio.file.FileSystem;
  34 import java.nio.file.FileSystems;
  35 import java.nio.file.Files;
  36 import java.nio.file.Path;
  37 import java.util.*;
  38 import java.util.regex.Pattern;
  39 
  40 /**
  41  * @test
  42  * @library /lib/testlibrary
  43  * @bug 6228231
  44  * @summary Test that RMI registry uses SSL.
  45  * @modules jdk.management.agent
  46  * @build jdk.testlibrary.* RmiRegistrySslTestApp
  47  * @run main/timeout=300 RmiRegistrySslTest
  48  * @author Luis-Miguel Alventosa, Taras Ledkov
  49  */
  50 public class RmiRegistrySslTest {
  51     private final String TEST_CLASS_PATH = System.getProperty("test.class.path");
  52     private final String TEST_CLASSES = System.getProperty("test.classes");
  53     private final String TEST_SRC = System.getProperty("test.src");
  54     private final FileSystem FS = FileSystems.getDefault();
  55 
  56     private final Path libDir = FS.getPath(TEST_CLASSES, "lib");
  57     private final Path rmiRegistryTemplate = FS.getPath(TEST_SRC, "rmiregistry.properties");
  58     private final Path rmiRegistrySslTemplate = FS.getPath(TEST_SRC, "rmiregistryssl.properties");
  59     private final Path rmiRegistryFile = libDir.resolve("rmiregistry.properties");
  60     private final Path rmiRegistrySslFile = libDir.resolve("rmiregistryssl.properties");
  61     private final String className = "RmiRegistrySslTestApp";
  62     private int failures = 0;
  63     private int port = 4444;
  64     private static int MAX_GET_FREE_PORT_TRIES = 10;
  65     private Map<String, Object> model = new HashMap<>();
  66 
  67     private RmiRegistrySslTest() {
  68         try {
  69             MAX_GET_FREE_PORT_TRIES = Integer.parseInt(System.getProperty("test.getfreeport.max.tries", "10"));
  70         } catch (NumberFormatException ex) {
  71         }
  72     }
  73 
  74     private void initPort() {
  75         try {
  76             port = Utils.getFreePort();
  77         } catch (Exception e) {
  78         }
  79         model.put("${getFreePort}", new Integer(port));
  80     }
  81 
  82     private void initTestEnvironment() throws IOException {
  83         initPort();
  84 
  85         Files.deleteIfExists(rmiRegistryFile);
  86         Files.deleteIfExists(rmiRegistrySslFile);
  87         libDir.toFile().mkdir();
  88         createFileByTemplate(rmiRegistryTemplate, rmiRegistryFile, model);
  89         createFileByTemplate(rmiRegistrySslTemplate, rmiRegistrySslFile, model);
  90     }
  91 
  92     public static void createFileByTemplate(Path template, Path out, Map<String, Object> model) throws IOException {
  93         if (Files.exists(out) && Files.isRegularFile(out)) {
  94             try {
  95                 Files.delete(out);
  96             } catch (Exception ex) {
  97                 System.out.println("WARNING: " + out.toFile().getAbsolutePath() + " already exists - unable to remove old copy");
  98                 ex.printStackTrace();
  99             }
 100         }
 101 
 102         try (BufferedReader br = Files.newBufferedReader(template, Charset.defaultCharset());
 103              BufferedWriter bw = Files.newBufferedWriter(out, Charset.defaultCharset())) {
 104             String line;
 105             while ((line = br.readLine()) != null) {
 106                 if (model != null) {
 107                     for (Map.Entry<String, Object> macro : model.entrySet()) {
 108                         line = line.replaceAll(Pattern.quote(macro.getKey()), macro.getValue().toString());
 109                     }
 110                 }
 111 
 112                 bw.write(line, 0, line.length());
 113                 bw.newLine();
 114             }
 115         }
 116     }
 117 
 118     public void runTest(String[] args) throws Exception {
 119 
 120         test1();
 121         test2();
 122         test3();
 123 
 124         if (failures == 0) {
 125             System.out.println("All test(s) passed");
 126         } else {
 127             throw new Error(String.format("%d test(s) failed", failures));
 128         }
 129     }
 130 
 131     private void test1() throws Exception {
 132         System.out.println("-------------------------------------------------------------");
 133         System.out.println(getClass().getName() + " : Non SSL RMIRegistry - Non SSL Lookup");
 134         System.out.println("-------------------------------------------------------------");
 135 
 136         int res = doTest("-DtestID=Test1",
 137                 "-Dcom.sun.management.config.file=" + rmiRegistryFile.toFile().getAbsolutePath());
 138 
 139         if (res != 0) {
 140             ++failures;
 141         }
 142     }
 143 
 144     private void test2() throws Exception {
 145         System.out.println("-------------------------------------------------------------");
 146         System.out.println(getClass().getName() + " : SSL RMIRegistry - Non SSL Lookup");
 147         System.out.println("-------------------------------------------------------------");
 148 
 149         int res = doTest("-DtestID=Test2",
 150                 "-Dcom.sun.management.config.file=" + rmiRegistrySslFile.toFile().getAbsolutePath());
 151 
 152         if (res != 0) {
 153             ++failures;
 154         }
 155     }
 156 
 157     private void test3() throws Exception {
 158 
 159         System.out.println("-------------------------------------------------------------");
 160         System.out.println(getClass().getName() + " : SSL RMIRegistry - SSL Lookup");
 161         System.out.println("-------------------------------------------------------------");
 162 
 163         int res = doTest("-DtestID=Test3",
 164                 "-Djavax.net.ssl.keyStore=" + FS.getPath(TEST_SRC, "ssl", "keystore").toFile().getAbsolutePath(),
 165                 "-Djavax.net.ssl.keyStorePassword=password",
 166                 "-Djavax.net.ssl.trustStore=" + FS.getPath(TEST_SRC, "ssl", "truststore").toFile().getAbsolutePath(),
 167                 "-Djavax.net.ssl.trustStorePassword=trustword",
 168                 "-Dcom.sun.management.config.file=" + rmiRegistrySslFile.toFile().getAbsolutePath());
 169 
 170         if (res != 0) {
 171             ++failures;
 172         }
 173     }
 174 
 175     private int doTest(String... args) throws Exception {
 176 
 177         for (int i = 0; i < MAX_GET_FREE_PORT_TRIES; ++i) {
 178 
 179             initTestEnvironment();
 180 
 181             List<String> command = new ArrayList<>();
 182             command.addAll(Utils.getVmOptions());
 183             command.add("-Dtest.src=" + TEST_SRC);
 184             command.add("-Dtest.rmi.port=" + port);
 185             command.addAll(Arrays.asList(args));
 186             command.add("-cp");
 187             command.add(TEST_CLASS_PATH);
 188             command.add(className);
 189 
 190             ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(command.toArray(new String[command.size()]));
 191 
 192             OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
 193 
 194             System.out.println("test output:");
 195             System.out.println(output.getOutput());
 196 
 197             if (!output.getOutput().contains("Exception thrown by the agent : " +
 198                     "java.rmi.server.ExportException: Port already in use")) {
 199                 return output.getExitValue();
 200             }
 201         }
 202         throw new Error("Cannot find free port");
 203     }
 204 
 205     public static void main(String[] args) throws Exception {
 206         RmiRegistrySslTest test = new RmiRegistrySslTest();
 207 
 208         test.runTest(args);
 209     }
 210 }