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