1 /*
   2  * Copyright (c) 2015, 2017, 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.testlibrary.JDKToolLauncher;
  25 import jdk.test.lib.util.JarUtils;
  26 import jdk.testlibrary.OutputAnalyzer;
  27 import jdk.testlibrary.ProcessTools;
  28 
  29 import java.nio.file.Files;
  30 import java.nio.file.Paths;
  31 import java.util.Arrays;
  32 
  33 /**
  34  * @test
  35  * @bug 8024302 8026037 8130132
  36  * @summary warnings, errors and -strict
  37  * @library /lib/testlibrary /test/lib
  38  */
  39 public 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