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