1 /*
  2  * Copyright (c) 2021, 2024, 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 /*
 25  * @test
 26  * @bug 8266459 8268349 8269543 8270380
 27  * @summary check various warnings
 28  * @library /test/lib
 29  */
 30 
 31 import jdk.test.lib.process.OutputAnalyzer;
 32 import jdk.test.lib.process.ProcessTools;
 33 import jdk.test.lib.util.JarUtils;
 34 
 35 import java.io.ByteArrayOutputStream;
 36 import java.io.File;
 37 import java.io.PrintStream;
 38 import java.nio.file.Files;
 39 import java.nio.file.Path;
 40 
 41 public class SecurityManagerWarnings {
 42 
 43     public static void main(String args[]) throws Exception {
 44         if (args.length == 0) {
 45             Files.writeString(Path.of("policy"), """
 46                     grant {
 47                         permission java.lang.RuntimePermission "setIO";
 48                         permission java.lang.RuntimePermission "createSecurityManager";
 49                         permission java.lang.RuntimePermission "setSecurityManager";
 50                     };
 51                     """);
 52 
 53             System.setProperty("test.noclasspath", "true");
 54             String testClasses = System.getProperty("test.classes");
 55 
 56             disallowTest(null, testClasses);
 57             allowTest("allow", testClasses);
 58             disallowTest("disallow", testClasses);
 59             enableTest("", testClasses);
 60             enableTest("default", testClasses);
 61             enableTest("java.lang.SecurityManager", testClasses);
 62 
 63             JarUtils.createJarFile(Path.of("a.jar"),
 64                     Path.of(testClasses),
 65                     Path.of("SecurityManagerWarnings.class"),
 66                     Path.of("A.class"),
 67                     Path.of("B.class"));
 68 
 69             disallowTest(null, "a.jar");
 70         } else {
 71             System.out.println("SM is enabled: " + (System.getSecurityManager() != null));
 72             PrintStream oldErr = System.err;
 73             // Modify System.err, thus make sure warnings are always printed
 74             // to the original System.err and will not be swallowed.
 75             System.setErr(new PrintStream(new ByteArrayOutputStream()));
 76             try {
 77                 // Run A.run() twice will show only one warning
 78                 // (setSecurityManager(null) to ensure the next set is permitted)
 79                 // Run B.run() and a new warning will appear
 80                 A.run();    // System.setSecurityManager(null);
 81                 A.run();    // System.setSecurityManager(null);
 82                 B.run();    // System.setSecurityManager(new SecurityManager());
 83             } catch (Exception e) {
 84                 // Exception messages must show in original stderr
 85                 e.printStackTrace(oldErr);
 86                 throw e;
 87             }
 88         }
 89     }
 90 
 91     // When SM is allowed, no startup warning, has setSM warning
 92     static void allowTest(String prop, String cp) throws Exception {
 93         checkInstallMessage(run(prop, cp), cp)
 94                 .shouldHaveExitValue(0)
 95                 .stdoutShouldContain("SM is enabled: false")
 96                 .shouldNotContain("A command line option");
 97     }
 98 
 99     // When SM is disallowed, no startup warning, setSM fails
100     static void disallowTest(String prop, String cp) throws Exception {
101         run(prop, cp)
102                 .shouldNotHaveExitValue(0)
103                 .stdoutShouldContain("SM is enabled: false")
104                 .shouldNotContain("A command line option")
105                 .shouldNotContain("A terminally deprecated method")
106                 .stderrShouldContain("UnsupportedOperationException: The Security Manager is deprecated and will be removed in a future release");
107     }
108 
109     // When SM is allowed, has startup warning, has setSM warning
110     static void enableTest(String prop, String cp) throws Exception {
111         checkInstallMessage(run(prop, cp), cp)
112                 .shouldHaveExitValue(0)
113                 .stdoutShouldContain("SM is enabled: true")
114                 .stderrShouldContain("WARNING: A command line option has enabled the Security Manager")
115                 .stderrShouldContain("WARNING: The Security Manager is deprecated and will be removed in a future release");
116     }
117 
118     // Check the setSM warning
119     static OutputAnalyzer checkInstallMessage(OutputAnalyzer oa, String cp) {
120         String uri = new File(cp).toURI().toString();
121         return oa
122                 .stderrShouldContain("WARNING: A terminally deprecated method in java.lang.System has been called")
123                 .stderrShouldContain("WARNING: System::setSecurityManager has been called by A (" + uri + ")")
124                 .stderrShouldContain("WARNING: System::setSecurityManager has been called by B (" + uri + ")")
125                 .stderrShouldContain("WARNING: Please consider reporting this to the maintainers of A")
126                 .stderrShouldContain("WARNING: Please consider reporting this to the maintainers of B")
127                 .stderrShouldContain("WARNING: System::setSecurityManager will be removed in a future release")
128                 .stderrShouldNotMatch("(?s)by A.*by A");    // "by A" appears only once
129     }
130 
131     static OutputAnalyzer run(String prop, String cp) throws Exception {
132         ProcessBuilder pb;
133         if (prop == null) {
134             pb = ProcessTools.createTestJavaProcessBuilder(
135                     "-cp", cp,
136                     "SecurityManagerWarnings", "run");
137         } else {
138             pb = ProcessTools.createTestJavaProcessBuilder(
139                     "-cp", cp,
140                     "-Djava.security.manager=" + prop,
141                     "-Djava.security.policy=policy",
142                     "SecurityManagerWarnings", "run");
143         }
144         return ProcessTools.executeProcess(pb)
145                 .stderrShouldNotContain("AccessControlException");
146     }
147 }
148 
149 class A {
150     static void run() {
151         System.setSecurityManager(null);
152     }
153 }
154 
155 class B {
156     static void run() {
157         System.setSecurityManager(new SecurityManager());
158     }
159 }