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 jdk.testlibrary.JDKToolLauncher;
25import jdk.testlibrary.JarUtils;
26import jdk.testlibrary.OutputAnalyzer;
27import jdk.testlibrary.ProcessTools;
28
29import java.nio.file.Files;
30import java.nio.file.Paths;
31import java.util.Arrays;
32
33/**
34 * @test
35 * @bug 8024302 8026037 8130132
36 * @summary warnings, errors and -strict
37 * @library /lib/testlibrary
38 */
39public class Warning {
40
41    public static void main(String[] args) throws Throwable {
42
43        Files.deleteIfExists(Paths.get("ks"));
44
45        newCert("ca", "-validity 365000");
46
47        recreateJar();
48
49        newCert("a");
50        run("jarsigner", "a.jar a")
51                .shouldContain("is self-signed");
52        run("jarsigner", "a.jar a -strict")
53                .shouldContain("is self-signed")
54                .shouldHaveExitValue(4);
55        // Trusted entry can be self-signed without a warning
56        run("jarsigner", "-verify a.jar")
57                .shouldNotContain("is self-signed")
58                .shouldNotContain("not signed by alias in this keystore");
59        run("keytool", "-delete -alias a");
60        // otherwise a warning will be shown
61        run("jarsigner", "-verify a.jar")
62                .shouldContain("is self-signed")
63                .shouldContain("not signed by alias in this keystore");
64
65        recreateJar();
66
67        newCert("b");
68        issueCert("b");
69        run("jarsigner", "a.jar b")
70                .shouldNotContain("is self-signed");
71        run("jarsigner", "-verify a.jar")
72                .shouldNotContain("is self-signed");
73
74        run("jarsigner", "a.jar b -digestalg MD5")
75                .shouldContain("-digestalg option is considered a security risk.");
76        run("jarsigner", "a.jar b -digestalg MD5 -strict")
77                .shouldHaveExitValue(4)
78                .shouldContain("-digestalg option is considered a security risk.");
79        run("jarsigner", "a.jar b -sigalg MD5withRSA")
80                .shouldContain("-sigalg option is considered a security risk");
81
82        issueCert("b", "-sigalg MD5withRSA");
83        run("jarsigner", "a.jar b")
84                .shouldMatch("chain is not validated. Reason:.*MD5withRSA");
85
86        recreateJar();
87
88        newCert("c", "-keysize 512");
89        issueCert("c");
90        run("jarsigner", "a.jar c")
91                .shouldContain("chain is not validated. " +
92                        "Reason: Algorithm constraints check failed");
93
94        recreateJar();
95
96        newCert("s1"); issueCert("s1", "-startdate 2000/01/01 -validity 36525");
97        run("jarsigner", "a.jar s1")
98                .shouldHaveExitValue(0)
99                .shouldContain("Warning:")
100                .shouldNotContain("Error:")
101                .shouldContain("timestamp").shouldContain("2100-01-01")
102                .shouldNotContain("with signer errors");
103        run("jarsigner", "a.jar s1 -strict")
104                .shouldHaveExitValue(0)
105                .shouldContain("Warning:")
106                .shouldNotContain("Error:")
107                .shouldContain("timestamp").shouldContain("2100-01-01")
108                .shouldNotContain("with signer errors");
109        run("jarsigner", "a.jar s1 -verify")
110                .shouldHaveExitValue(0)
111                .shouldContain("Warning:")
112                .shouldNotContain("Error:")
113                .shouldContain("timestamp").shouldContain("2100-01-01")
114                .shouldNotContain("with signer errors");
115        run("jarsigner", "a.jar s1 -verify -strict")
116                .shouldHaveExitValue(0)
117                .shouldContain("Warning:")
118                .shouldNotContain("Error:")
119                .shouldContain("timestamp").shouldContain("2100-01-01")
120                .shouldNotContain("with signer errors");
121
122        recreateJar();
123
124        newCert("s2"); issueCert("s2", "-validity 100");
125        run("jarsigner", "a.jar s2")
126                .shouldHaveExitValue(0)
127                .shouldContain("Warning:")
128                .shouldNotContain("Error:")
129                .shouldContain("timestamp")
130                .shouldContain("will expire")
131                .shouldNotContain("with signer errors");
132        run("jarsigner", "a.jar s2 -strict")
133                .shouldHaveExitValue(0)
134                .shouldContain("Warning:")
135                .shouldNotContain("Error:")
136                .shouldContain("timestamp")
137                .shouldContain("will expire")
138                .shouldNotContain("with signer errors");
139        run("jarsigner", "a.jar s2 -verify")
140                .shouldHaveExitValue(0)
141                .shouldContain("Warning:")
142                .shouldNotContain("Error:")
143                .shouldContain("timestamp")
144                .shouldContain("will expire")
145                .shouldNotContain("with signer errors");
146        run("jarsigner", "a.jar s2 -verify -strict")
147                .shouldHaveExitValue(0)
148                .shouldContain("Warning:")
149                .shouldNotContain("Error:")
150                .shouldContain("timestamp")
151                .shouldContain("will expire")
152                .shouldNotContain("with signer errors");
153
154        recreateJar();
155
156        newCert("s3"); issueCert("s3", "-startdate -200d -validity 100");
157        run("jarsigner", "a.jar s3")
158                .shouldHaveExitValue(0)
159                .shouldContain("Warning:")
160                .shouldContain("has expired")
161                .shouldNotContain("with signer errors")
162                .shouldNotContain("Error:");
163        run("jarsigner", "a.jar s3 -strict")
164                .shouldHaveExitValue(4)
165                .shouldContain("with signer errors")
166                .shouldMatch("(?s).*Error:.*has expired.*Warning:.*");
167        run("jarsigner", "a.jar s3 -verify")
168                .shouldHaveExitValue(0)
169                .shouldContain("Warning:")
170                .shouldNotContain("with signer errors")
171                .shouldNotContain("Error:");
172        run("jarsigner", "a.jar s3 -verify -strict")
173                .shouldHaveExitValue(4)
174                .shouldContain("with signer errors")
175                .shouldMatch("(?s).*Error:.*has expired.*Warning:.*");
176    }
177
178    // Creates a new jar without signature
179    static void recreateJar() throws Exception {
180        JarUtils.createJar("a.jar", "ks");
181    }
182
183    // Creates a self-signed cert for alias with zero or more -genkey options
184    static void newCert(String alias, String... more) throws Exception {
185        String args = "-genkeypair -alias " + alias + " -dname CN=" + alias;
186        for (String s: more) {
187            args += " " + s;
188        }
189        run("keytool", args).shouldHaveExitValue(0);
190    }
191
192    // Asks ca to issue a cert to alias with zero or more -gencert options
193    static void issueCert(String alias, String...more) throws Exception {
194        String req = run("keytool", "-certreq -alias " + alias)
195                .shouldHaveExitValue(0).getStdout();
196        String args = "-gencert -alias ca -rfc";
197        for (String s: more) {
198            args += " " + s;
199        }
200        String cert = run("keytool", args, req)
201                .shouldHaveExitValue(0).getStdout();
202        run("keytool", "-import -alias " + alias, cert).shouldHaveExitValue(0);
203    }
204
205    // Runs a java tool with command line arguments
206    static OutputAnalyzer run(String command, String args)
207            throws Exception {
208        return run(command, args, null);
209    }
210
211    // Runs a java tool with command line arguments and an optional input block
212    static OutputAnalyzer run(String command, String args, String input)
213            throws Exception {
214        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(command);
215        launcher.addVMArg("-Duser.language=en").addVMArg("-Duser.country=US");
216        switch (command) {
217            case "keytool":
218                for (String s: new String[] {
219                        "-keystore", "ks", "-storepass", "changeit",
220                        "-storetype", "jks",
221                        "-keypass", "changeit", "-keyalg", "rsa", "-debug"}) {
222                    launcher.addToolArg(s);
223                }
224                break;
225            case "jarsigner":
226                for (String s: new String[] {
227                        "-keystore", "ks", "-storepass", "changeit",
228                        "-storetype", "jks"}) {
229                    launcher.addToolArg(s);
230                }
231                break;
232        }
233        for (String arg: args.split(" ")) {
234            launcher.addToolArg(arg);
235        }
236        String[] cmd = launcher.getCommand();
237        ProcessBuilder pb = new ProcessBuilder(cmd);
238        OutputAnalyzer out = ProcessTools.executeProcess(pb, input);
239        System.out.println("======================");
240        System.out.println(Arrays.toString(cmd));
241        String msg = " stdout: [" + out.getStdout() + "];\n"
242                + " stderr: [" + out.getStderr() + "]\n"
243                + " exitValue = " + out.getExitValue() + "\n";
244        System.out.println(msg);
245        return out;
246    }
247}
248
249