1 /*
   2  * Copyright (c) 2013, 2018, 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.test.lib.Platform;
  27 
  28 import java.io.BufferedWriter;
  29 import java.io.IOException;
  30 import java.nio.charset.Charset;
  31 import java.nio.file.FileSystem;
  32 import java.nio.file.FileSystems;
  33 import java.nio.file.Files;
  34 import java.nio.file.Path;
  35 import java.nio.file.attribute.PosixFilePermission;
  36 import java.util.ArrayList;
  37 import java.util.Arrays;
  38 import java.util.HashSet;
  39 import java.util.List;
  40 import java.util.Set;
  41 
  42 /**
  43  * Change file permission for out-of-the-box management an do test used by
  44  * PasswordFilePermissionTest and SSLConfigFilePermissionTest tests
  45  *
  46  * @author Taras Ledkov
  47  */
  48 public abstract class AbstractFilePermissionTest {
  49     private final String TEST_CLASS_PATH = System.getProperty("test.class.path");
  50     protected final String TEST_CLASSES = System.getProperty("test.classes");
  51     protected final FileSystem FS = FileSystems.getDefault();
  52     private int MAX_GET_FREE_PORT_TRIES = 10;
  53 
  54     protected final Path libDir = FS.getPath(TEST_CLASSES, "lib");
  55     protected final Path mgmt = libDir.resolve("management.properties");
  56     private final String mp = "-Dcom.sun.management.config.file=" + mgmt.toFile().getAbsolutePath();
  57     private final String className = "Dummy";
  58     private int failures = 0;
  59 
  60     protected final Path file2PermissionTest;
  61 
  62     protected AbstractFilePermissionTest(String fileName2PermissionTest) {
  63         this.file2PermissionTest = libDir.resolve(fileName2PermissionTest);
  64 
  65         try {
  66             MAX_GET_FREE_PORT_TRIES = Integer.parseInt(System.getProperty("test.getfreeport.max.tries", "10"));
  67         } catch (NumberFormatException ex) {
  68             ex.printStackTrace();
  69         }
  70     }
  71 
  72 
  73     public static void createFile(Path path, String... content) throws IOException {
  74         if (Files.exists(path) && Files.isRegularFile(path)) {
  75             try {
  76                 Files.delete(path);
  77             } catch (Exception ex) {
  78                 System.out.println("WARNING: " + path.toFile().getAbsolutePath() + " already exists - unable to remove old copy");
  79                 ex.printStackTrace();
  80             }
  81         }
  82 
  83         try (BufferedWriter bw = Files.newBufferedWriter(path, Charset.defaultCharset())) {
  84             for (String str : content) {
  85                 bw.write(str, 0, str.length());
  86                 bw.newLine();
  87             }
  88         }
  89     }
  90 
  91     public boolean skipTest() {
  92         if ((TEST_CLASSES == null) || ("".equals(TEST_CLASSES))) {
  93             System.out.println("Test is designed to be run from jtreg only");
  94             return true;
  95         }
  96 
  97         if (!Platform.isLinux() && !Platform.isSolaris()) {
  98             System.out.println("Test not designed to run on this operating system, skipping...");
  99             return true;
 100         }
 101         return false;
 102     }
 103 
 104     protected abstract void testSetup() throws IOException;
 105 
 106     public void runTest(String[] args) throws Exception {
 107 
 108         if (skipTest()) {
 109             return;
 110         }
 111 
 112         Files.deleteIfExists(mgmt);
 113         Files.deleteIfExists(file2PermissionTest);
 114         libDir.toFile().mkdir();
 115 
 116         testSetup();
 117 
 118         try {
 119             test1();
 120             test2();
 121 
 122             if (failures == 0) {
 123                 System.out.println("All test(s) passed");
 124             } else {
 125                 throw new Error(String.format("%d test(s) failed", failures));
 126             }
 127         } finally {
 128             resetPasswordFilePermission();
 129         }
 130     }
 131 
 132     /**
 133      * Test 1 - SSL config file is secure - VM should start
 134      */
 135     private void test1() throws Exception {
 136         final Set<PosixFilePermission> perms_0700 = new HashSet<>();
 137         perms_0700.add(PosixFilePermission.OWNER_WRITE);
 138         perms_0700.add(PosixFilePermission.OWNER_READ);
 139         perms_0700.add(PosixFilePermission.OWNER_EXECUTE);
 140         Files.setPosixFilePermissions(file2PermissionTest, perms_0700);
 141 
 142         if (doTest() != 0) {
 143             ++failures;
 144         }
 145     }
 146 
 147     /**
 148      * Test 1 - SSL config file is secure - VM should start
 149      */
 150     private void test2() throws Exception {
 151         final Set<PosixFilePermission> perms = Files.getPosixFilePermissions(file2PermissionTest);
 152         perms.add(PosixFilePermission.OTHERS_READ);
 153         perms.add(PosixFilePermission.OTHERS_EXECUTE);
 154         Files.setPosixFilePermissions(file2PermissionTest, perms);
 155 
 156         if (doTest() == 0) {
 157             ++failures;
 158         }
 159     }
 160 
 161     private int doTest() throws Exception {
 162 
 163         for (int i = 0; i < MAX_GET_FREE_PORT_TRIES; ++i) {
 164             final String pp = "-Dcom.sun.management.jmxremote.port=" + jdk.test.lib.Utils.getFreePort();
 165 
 166             List<String> command = new ArrayList<>();
 167             command.addAll(jdk.test.lib.Utils.getVmOptions());
 168             command.add(mp);
 169             command.add(pp);
 170             command.add("-cp");
 171             command.add(TEST_CLASSES);
 172             command.add(className);
 173 
 174 
 175             ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
 176                     command.toArray(new String[command.size()]));
 177 
 178             System.out.println("test cmdline: " + Arrays.toString(processBuilder.command().toArray()).replace(",", ""));
 179             OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
 180 
 181             System.out.println("test output:");
 182             System.out.println(output.getOutput());
 183 
 184             if ((output.getExitValue() == 0)  ||
 185                 !output.getOutput().contains("Exception thrown by the agent : " +
 186                         "java.rmi.server.ExportException: Port already in use")) {
 187                 return output.getExitValue();
 188             }
 189         }
 190 
 191         return -1;
 192     }
 193 
 194     private void resetPasswordFilePermission() throws Exception {
 195         final Set<PosixFilePermission> perms_0777 = new HashSet<>();
 196         Arrays.asList(PosixFilePermission.values()).stream().forEach(p -> {
 197             perms_0777.add(p);
 198         });
 199         Files.setPosixFilePermissions(file2PermissionTest, perms_0777);
 200     }
 201 }