From 2882b91893c412e7fde40f2e059a511cb84df6f4 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 2 Oct 2009 18:49:46 +0800 Subject: [PATCH] 6868579: RFE: jarsigner to support reading password from environment variable Reviewed-by: xuelei, wetmore --- .../classes/sun/security/tools/JarSigner.java | 33 +++++--- .../classes/sun/security/tools/KeyTool.java | 77 +++++++++++++++++-- .../classes/sun/security/util/Resources.java | 4 + .../sun/security/tools/jarsigner/passtype.sh | 72 +++++++++++++++++ 4 files changed, 168 insertions(+), 18 deletions(-) create mode 100644 jdk/test/sun/security/tools/jarsigner/passtype.sh diff --git a/jdk/src/share/classes/sun/security/tools/JarSigner.java b/jdk/src/share/classes/sun/security/tools/JarSigner.java index c62018c99b0..3e1d0929104 100644 --- a/jdk/src/share/classes/sun/security/tools/JarSigner.java +++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java @@ -291,13 +291,21 @@ public class JarSigner { for (n=0; n < args.length; n++) { String flags = args[n]; + String modifier = null; + if (flags.charAt(0) == '-') { + int pos = flags.indexOf(':'); + if (pos > 0) { + modifier = flags.substring(pos+1); + flags = flags.substring(0, pos); + } + } if (collator.compare(flags, "-keystore") == 0) { if (++n == args.length) usageNoArg(); keystore = args[n]; } else if (collator.compare(flags, "-storepass") ==0) { if (++n == args.length) usageNoArg(); - storepass = args[n].toCharArray(); + storepass = getPass(modifier, args[n]); } else if (collator.compare(flags, "-storetype") ==0) { if (++n == args.length) usageNoArg(); storetype = args[n]; @@ -329,7 +337,7 @@ public class JarSigner { debug = true; } else if (collator.compare(flags, "-keypass") ==0) { if (++n == args.length) usageNoArg(); - keypass = args[n].toCharArray(); + keypass = getPass(modifier, args[n]); } else if (collator.compare(flags, "-sigfile") ==0) { if (++n == args.length) usageNoArg(); sigfile = args[n]; @@ -355,13 +363,7 @@ public class JarSigner { } else if (collator.compare(flags, "-verify") ==0) { verify = true; } else if (collator.compare(flags, "-verbose") ==0) { - verbose = "all"; - } else if (collator.compare(flags, "-verbose:all") ==0) { - verbose = "all"; - } else if (collator.compare(flags, "-verbose:summary") ==0) { - verbose = "summary"; - } else if (collator.compare(flags, "-verbose:grouped") ==0) { - verbose = "grouped"; + verbose = (modifier != null) ? modifier : "all"; } else if (collator.compare(flags, "-sigalg") ==0) { if (++n == args.length) usageNoArg(); sigalg = args[n]; @@ -465,18 +467,25 @@ public class JarSigner { } } - void usageNoArg() { + static char[] getPass(String modifier, String arg) { + char[] output = KeyTool.getPassWithModifier(modifier, arg); + if (output != null) return output; + usage(); + return null; // Useless, usage() already exit + } + + static void usageNoArg() { System.out.println(rb.getString("Option lacks argument")); usage(); } - void usage() { + static void usage() { System.out.println(); System.out.println(rb.getString("Please type jarsigner -help for usage")); System.exit(1); } - void fullusage() { + static void fullusage() { System.out.println(rb.getString ("Usage: jarsigner [options] jar-file alias")); System.out.println(rb.getString diff --git a/jdk/src/share/classes/sun/security/tools/KeyTool.java b/jdk/src/share/classes/sun/security/tools/KeyTool.java index df686a732c3..d34d0bcdc48 100644 --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java @@ -351,6 +351,15 @@ public final class KeyTool { } } + /* + * Check modifiers + */ + String modifier = null; + int pos = flags.indexOf(':'); + if (pos > 0) { + modifier = flags.substring(pos+1); + flags = flags.substring(0, pos); + } /* * command modes */ @@ -387,18 +396,18 @@ public final class KeyTool { ksfname = args[++i]; } else if (collator.compare(flags, "-storepass") == 0 || collator.compare(flags, "-deststorepass") == 0) { - storePass = args[++i].toCharArray(); + storePass = getPass(modifier, args[++i]); passwords.add(storePass); } else if (collator.compare(flags, "-storetype") == 0 || collator.compare(flags, "-deststoretype") == 0) { storetype = args[++i]; } else if (collator.compare(flags, "-srcstorepass") == 0) { - srcstorePass = args[++i].toCharArray(); + srcstorePass = getPass(modifier, args[++i]); passwords.add(srcstorePass); } else if (collator.compare(flags, "-srcstoretype") == 0) { srcstoretype = args[++i]; } else if (collator.compare(flags, "-srckeypass") == 0) { - srckeyPass = args[++i].toCharArray(); + srckeyPass = getPass(modifier, args[++i]); passwords.add(srckeyPass); } else if (collator.compare(flags, "-srcprovidername") == 0) { srcProviderName = args[++i]; @@ -408,13 +417,13 @@ public final class KeyTool { } else if (collator.compare(flags, "-providerpath") == 0) { pathlist = args[++i]; } else if (collator.compare(flags, "-keypass") == 0) { - keyPass = args[++i].toCharArray(); + keyPass = getPass(modifier, args[++i]); passwords.add(keyPass); } else if (collator.compare(flags, "-new") == 0) { - newPass = args[++i].toCharArray(); + newPass = getPass(modifier, args[++i]); passwords.add(newPass); } else if (collator.compare(flags, "-destkeypass") == 0) { - destKeyPass = args[++i].toCharArray(); + destKeyPass = getPass(modifier, args[++i]); passwords.add(destKeyPass); } else if (collator.compare(flags, "-alias") == 0 || collator.compare(flags, "-srcalias") == 0) { @@ -3842,6 +3851,61 @@ public final class KeyTool { rb.getString("Command option needs an argument.")).format(source)); tinyHelp(); } + + private char[] getPass(String modifier, String arg) { + char[] output = getPassWithModifier(modifier, arg); + if (output != null) return output; + tinyHelp(); + return null; // Useless, tinyHelp() already exits. + } + + // This method also used by JarSigner + public static char[] getPassWithModifier(String modifier, String arg) { + if (modifier == null) { + return arg.toCharArray(); + } else if (collator.compare(modifier, "env") == 0) { + String value = System.getenv(arg); + if (value == null) { + System.err.println(rb.getString( + "Cannot find environment variable: ") + arg); + return null; + } else { + return value.toCharArray(); + } + } else if (collator.compare(modifier, "file") == 0) { + try { + URL url = null; + try { + url = new URL(arg); + } catch (java.net.MalformedURLException mue) { + File f = new File(arg); + if (f.exists()) { + url = f.toURI().toURL(); + } else { + System.err.println(rb.getString( + "Cannot find file: ") + arg); + return null; + } + } + BufferedReader br = new BufferedReader(new InputStreamReader( + url.openStream())); + String value = br.readLine(); + br.close(); + if (value == null) { + return new char[0]; + } else { + return value.toCharArray(); + } + } catch (IOException ioe) { + System.err.println(ioe); + return null; + } + } else { + System.err.println(rb.getString("Unknown password type: ") + + modifier); + return null; + } + } } // This class is exactly the same as com.sun.tools.javac.util.Pair, @@ -3881,3 +3945,4 @@ class Pair { return new Pair(a,b); } } + diff --git a/jdk/src/share/classes/sun/security/util/Resources.java b/jdk/src/share/classes/sun/security/util/Resources.java index af49592e3d6..686e91469a8 100644 --- a/jdk/src/share/classes/sun/security/util/Resources.java +++ b/jdk/src/share/classes/sun/security/util/Resources.java @@ -178,6 +178,10 @@ public class Resources extends java.util.ListResourceBundle { {"keytool error: ", "keytool error: "}, {"Illegal option: ", "Illegal option: "}, {"Illegal value: ", "Illegal value: "}, + {"Unknown password type: ", "Unknown password type: "}, + {"Cannot find environment variable: ", + "Cannot find environment variable: "}, + {"Cannot find file: ", "Cannot find file: "}, {"Command option needs an argument.", "Command option {0} needs an argument."}, {"Warning: Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified value.", "Warning: Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified {0} value."}, diff --git a/jdk/test/sun/security/tools/jarsigner/passtype.sh b/jdk/test/sun/security/tools/jarsigner/passtype.sh new file mode 100644 index 00000000000..7e942350956 --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/passtype.sh @@ -0,0 +1,72 @@ +# +# Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 6868579 +# @summary RFE: jarsigner to support reading password from environment variable +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Windows_* ) + FS="\\" + ;; + * ) + FS="/" + ;; +esac + +KS=pt.jks +JFILE=pt.jar + +KT="$TESTJAVA${FS}bin${FS}keytool -keystore $KS -validity 300" +JAR=$TESTJAVA${FS}bin${FS}jar +JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner + +rm $KS $JFILE + +$KT -alias a -dname CN=a -keyalg rsa -genkey \ + -storepass test12 -keypass test12 || exit 1 +PASSENV=test12 $KT -alias b -dname CN=b -keyalg rsa -genkey \ + -storepass:env PASSENV -keypass:env PASSENV || exit 2 +echo test12 > passfile +$KT -alias c -dname CN=c -keyalg rsa -genkey \ + -storepass:file passfile -keypass:file passfile || exit 3 + +echo A > A +$JAR cvf $JFILE A + +$JARSIGNER -keystore $KS -storepass test12 $JFILE a || exit 4 +PASSENV=test12 $JARSIGNER -keystore $KS -storepass:env PASSENV $JFILE b || exit 5 +$JARSIGNER -keystore $KS -storepass:file passfile $JFILE b || exit 6 + +$JARSIGNER -keystore $KS -verify -debug -strict $JFILE || exit 7 + +exit 0 +