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