1/*
2 * Copyright (c) 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
24import java.io.File;
25import java.nio.file.Files;
26import java.nio.file.Paths;
27import java.security.AccessControlException;
28import java.security.AccessController;
29import java.security.Permission;
30import java.security.PrivilegedAction;
31import jdk.testlibrary.ProcessTools;
32
33/**
34 * @test
35 * @bug 8048360
36 * @summary test policy entry with signedBy alias
37 * @library /lib/testlibrary
38 * @run main/othervm SignedJarTest
39 */
40public class SignedJarTest {
41
42    private static final String FS = File.separator;
43    private static final String JAVA_HOME = System.getProperty("test.jdk");
44    private static final String TESTCLASSES = System.getProperty("test.classes", "");
45    private static final String TESTSRC = System.getProperty("test.src", "");
46    private static final String KEYTOOL = JAVA_HOME + FS + "bin" + FS + "keytool";
47    private static final String JAR = JAVA_HOME + FS + "bin" + FS + "jar";
48    private static final String JARSIGNER = JAVA_HOME + FS + "bin" + FS + "jarsigner";
49    private static final String PASSWORD = "password";
50    private static final String PWDFILE = "keypass";
51    private static final String POLICY1 = "SignedJarTest_1.policy";
52    private static final String POLICY2 = "SignedJarTest_2.policy";
53    private static final String KEYSTORE1 = "both.jks";
54    private static final String KEYSTORE2 = "first.jks";
55
56    public static void main(String args[]) throws Throwable {
57        //copy PrivilegeTest.class, policy files and keystore password file into current direcotry
58        Files.copy(Paths.get(TESTCLASSES, "PrivilegeTest.class"), Paths.get("PrivilegeTest.class"));
59        Files.copy(Paths.get(TESTSRC, POLICY1), Paths.get(POLICY1));
60        Files.copy(Paths.get(TESTSRC, POLICY2), Paths.get(POLICY2));
61        Files.copy(Paths.get(TESTSRC, PWDFILE), Paths.get(PWDFILE));
62
63        //create Jar file
64        ProcessTools.executeCommand(JAR, "-cvf", "test.jar", "PrivilegeTest.class");
65
66        //Creating first key , keystore both.jks
67        ProcessTools.executeCommand(KEYTOOL,
68                "-genkey",
69                "-alias", "first",
70                "-keystore", KEYSTORE1,
71                "-keypass", PASSWORD,
72                "-dname", "cn=First",
73                "-storepass", PASSWORD
74        ).shouldHaveExitValue(0);
75
76        //Creating Second key, keystore both.jks
77        ProcessTools.executeCommand(KEYTOOL,
78                "-genkey",
79                // "-storetype","JKS",
80                "-alias", "second",
81                "-keystore", KEYSTORE1,
82                "-keypass", PASSWORD,
83                "-dname", "cn=Second",
84                "-storepass", PASSWORD
85        ).shouldHaveExitValue(0);
86
87        //copy both.jks to first.jks, remove second Keypair from first.jks
88        Files.copy(Paths.get(KEYSTORE1), Paths.get(KEYSTORE2));
89        ProcessTools.executeCommand(KEYTOOL,
90                "-delete",
91                "-keystore", KEYSTORE2,
92                "-alias", "second",
93                "-storepass", PASSWORD
94        ).shouldHaveExitValue(0);
95
96        //sign jar with first key, first.jar is only signed by first signer
97        ProcessTools.executeCommand(JARSIGNER,
98                "-keystore", KEYSTORE1,
99                "-storepass", PASSWORD,
100                "-keypass", PASSWORD,
101                "-signedjar", "first.jar", "test.jar",
102                "first").shouldHaveExitValue(0);
103
104        //sign jar with second key, both.jar is signed by first and second signer
105        ProcessTools.executeCommand(JARSIGNER,
106                "-keystore", KEYSTORE1,
107                "-storepass", PASSWORD,
108                "-keypass", PASSWORD,
109                "-signedjar", "both.jar", "first.jar",
110                "second").shouldHaveExitValue(0);
111
112        //test case 1
113        //setIO permission granted to code that was signed by first signer
114        //setFactory permission granted to code that was signed by second signer
115        //Keystore that contains both first and second  keypairs
116        //code was singed by first signer
117        //Expect AccessControlException for setFactory permission
118        System.out.println("Test Case 1");
119        //copy policy file into current directory
120        String[] cmd = constructCMD("first.jar", POLICY1, "false", "true");
121        ProcessTools.executeTestJvm(cmd).shouldHaveExitValue(0);
122
123        //test case 2, test with both.jar
124        //setIO permission granted to code that was signed by first signer
125        //setFactory permission granted to code that was signed by second signer
126        //Keystore that contains both first and second  keypairs
127        //code was singed by first signer and second signer
128        //Expect no AccessControlException
129        System.out.println("Test Case 2");
130        cmd = constructCMD("both.jar", POLICY1, "false", "false");
131        ProcessTools.executeTestJvm(cmd).shouldHaveExitValue(0);
132
133        //test case 3
134        //setIO permission granted to code that was signed by first signer
135        //setFactory permission granted to code that was signed by second signer
136        //Keystore that contains only first keypairs
137        //code was singed by first signer and second signer
138        //Expect AccessControlException for setFactory permission
139        System.out.println("Test Case 3");
140        cmd = constructCMD("both.jar", POLICY2, "false", "true");
141        ProcessTools.executeTestJvm(cmd).shouldHaveExitValue(0);
142
143    }
144
145    private static String[] constructCMD(String classpath, String policy, String arg1, String arg2) {
146        String[] cmd = {
147            "-classpath", classpath,
148            "-Djava.security.manager",
149            "-Djava.security.policy=" + policy,
150            "PrivilegeTest",
151            arg1, arg2};
152        return cmd;
153    }
154}
155
156class PrivilegeTest {
157
158    private static final Permission PERM1 = new RuntimePermission("setIO");
159    private static final Permission PERM2 = new RuntimePermission("setFactory");
160
161    public static void main(String args[]) {
162        boolean expectException1 = Boolean.parseBoolean(args[0]);
163        boolean expectException2 = Boolean.parseBoolean(args[1]);
164        test(PERM1, expectException1);
165        test(PERM2, expectException2);
166    }
167
168    public static void test(Permission perm, boolean expectException) {
169        boolean getException = (Boolean) AccessController.doPrivileged((PrivilegedAction) () -> {
170            try {
171                AccessController.checkPermission(perm);
172                return (Boolean) false;
173            } catch (AccessControlException ex) {
174                return (Boolean) true;
175            }
176        });
177
178        if (expectException ^ getException) {
179            String message = "Check Permission :" + perm + "\n ExpectException = "
180                    + expectException + "\n getException = " + getException;
181            throw new RuntimeException(message);
182        }
183
184    }
185
186}
187