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