8183509: keytool should not allow multiple commands
authorweijun
Sat, 08 Jul 2017 14:09:01 +0800
changeset 45839 6df5e24443fc
parent 45838 c6223c3b4594
child 45840 7eb973f73ce1
8183509: keytool should not allow multiple commands Reviewed-by: mullan, vinnie
jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java
jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java
jdk/test/sun/security/tools/keytool/DupCommands.java
jdk/test/sun/security/tools/keytool/WeakAlg.java
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Fri Jul 07 12:19:00 2017 +0530
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Sat Jul 08 14:09:01 2017 +0800
@@ -302,6 +302,8 @@
         Command.IMPORTPASS.setAltName("-importpassword");
     }
 
+    // If an option is allowed multiple times, remember to record it
+    // in the optionsSet.contains() block in parseArgs().
     enum Option {
         ALIAS("alias", "<alias>", "alias.name.of.the.entry.to.process"),
         DESTALIAS("destalias", "<alias>", "destination.alias"),
@@ -423,9 +425,31 @@
 
         String confFile = null;
 
+        // Records all commands and options set. Used to check dups.
+        Set<String> optionsSet = new HashSet<>();
+
         for (i=0; i < args.length; i++) {
             String flags = args[i];
             if (flags.startsWith("-")) {
+                String lowerFlags = flags.toLowerCase(Locale.ROOT);
+                if (optionsSet.contains(lowerFlags)) {
+                    switch (lowerFlags) {
+                        case "-ext":
+                        case "-id":
+                        case "-provider":
+                        case "-addprovider":
+                        case "-providerclass":
+                        case "-providerarg":
+                            // These options are allowed multiple times
+                            break;
+                        default:
+                            weakWarnings.add(String.format(
+                                    rb.getString("option.1.set.twice"),
+                                    lowerFlags));
+                    }
+                } else {
+                    optionsSet.add(lowerFlags);
+                }
                 if (collator.compare(flags, "-conf") == 0) {
                     if (i == args.length - 1) {
                         errorNeedArgument(flags);
@@ -433,7 +457,15 @@
                     confFile = args[++i];
                 } else {
                     Command c = Command.getCommand(flags);
-                    if (c != null) command = c;
+                    if (c != null) {
+                        if (command == null) {
+                            command = c;
+                        } else {
+                            throw new Exception(String.format(
+                                    rb.getString("multiple.commands.1.2"),
+                                    command.name, c.name));
+                        }
+                    }
                 }
             }
         }
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java	Fri Jul 07 12:19:00 2017 +0530
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java	Sat Jul 08 14:09:01 2017 +0800
@@ -42,6 +42,8 @@
         // keytool: Help part
         {".OPTION.", " [OPTION]..."},
         {"Options.", "Options:"},
+        {"option.1.set.twice", "The %s option is specified multiple times. All except the last one will be ignored."},
+        {"multiple.commands.1.2", "Only one command is allowed: both %1$s and %2$s were specified."},
         {"Use.keytool.help.for.all.available.commands",
                  "Use \"keytool -help\" for all available commands"},
         {"Key.and.Certificate.Management.Tool",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/keytool/DupCommands.java	Sat Jul 08 14:09:01 2017 +0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8183509
+ * @summary keytool should not allow multiple commands
+ * @library /test/lib
+ * @build jdk.test.lib.SecurityTools
+ *        jdk.test.lib.Utils
+ *        jdk.test.lib.Asserts
+ *        jdk.test.lib.JDKToolFinder
+ *        jdk.test.lib.JDKToolLauncher
+ *        jdk.test.lib.Platform
+ *        jdk.test.lib.process.*
+ * @run main/othervm DupCommands
+ */
+
+import jdk.test.lib.SecurityTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class DupCommands {
+
+    public static void main(String[] args) throws Throwable {
+
+        kt("-list -printcert")
+                .shouldHaveExitValue(1)
+                .shouldContain("Only one command is allowed");
+
+        kt("-import -importcert") // command with different names
+                .shouldHaveExitValue(1)
+                .shouldContain("Only one command is allowed");
+
+        kt("-help -v -v")
+                .shouldHaveExitValue(0)
+                .shouldContain("The -v option is specified multiple times.");
+
+        kt("-help -id 1 -id 2") // some options are allowed multiple times
+                .shouldHaveExitValue(0)
+                .shouldNotContain("specified multiple times.");
+    }
+
+    static OutputAnalyzer kt(String arg) throws Exception {
+        return SecurityTools.keytool(arg);
+    }
+}
--- a/jdk/test/sun/security/tools/keytool/WeakAlg.java	Fri Jul 07 12:19:00 2017 +0530
+++ b/jdk/test/sun/security/tools/keytool/WeakAlg.java	Sat Jul 08 14:09:01 2017 +0800
@@ -571,7 +571,7 @@
 
     static OutputAnalyzer genkeypair(String alias, String options) {
         return kt("-genkeypair -alias " + alias + " -dname CN=" + alias
-                + " -keyalg RSA -storetype JKS " + options);
+                + " -storetype JKS " + options);
     }
 
     static OutputAnalyzer certreq(String alias, String options) {