8168882: keytool doesn't print certificate info if disabled algorithm was used for signing a jar
Reviewed-by: weijun, mullan
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Tue Nov 08 14:29:14 2016 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Tue Nov 08 15:55:11 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -84,8 +84,10 @@
import sun.security.x509.*;
import static java.security.KeyStore.*;
+import java.security.Security;
import static sun.security.tools.keytool.Main.Command.*;
import static sun.security.tools.keytool.Main.Option.*;
+import sun.security.util.DisabledAlgorithmConstraints;
/**
* This tool manages keystores.
@@ -2428,6 +2430,10 @@
private void doPrintCert(final PrintStream out) throws Exception {
if (jarfile != null) {
+ // reset "jdk.certpath.disabledAlgorithms" security property
+ // to be able to read jars which were signed with weak algorithms
+ Security.setProperty(DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS, "");
+
JarFile jf = new JarFile(jarfile, true);
Enumeration<JarEntry> entries = jf.entries();
Set<CodeSigner> ss = new HashSet<>();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/security/SecurityTools.java Tue Nov 08 15:55:11 2016 -0800
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import jdk.testlibrary.JDKToolLauncher;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class SecurityTools {
+
+ public static final String NO_ALIAS = null;
+
+ // keytool
+
+ public static OutputAnalyzer keytool(List<String> options)
+ throws Throwable {
+
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("keytool")
+ .addVMArg("-Duser.language=en")
+ .addVMArg("-Duser.country=US");
+ for (String option : options) {
+ if (option.startsWith("-J")) {
+ launcher.addVMArg(option.substring(2));
+ } else {
+ launcher.addToolArg(option);
+ }
+ }
+ return ProcessTools.executeCommand(launcher.getCommand());
+ }
+
+ public static OutputAnalyzer keytool(String options) throws Throwable {
+ return keytool(options.split("\\s+"));
+ }
+
+ public static OutputAnalyzer keytool(String... options) throws Throwable {
+ return keytool(List.of(options));
+ }
+
+ // jarsigner
+
+ public static OutputAnalyzer jarsigner(String jar, String alias,
+ List<String> options) throws Throwable {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner")
+ .addVMArg("-Duser.language=en")
+ .addVMArg("-Duser.country=US");
+ for (String option : options) {
+ if (option.startsWith("-J")) {
+ launcher.addVMArg(option.substring(2));
+ } else {
+ launcher.addToolArg(option);
+ }
+ }
+ launcher.addToolArg(jar);
+ if (alias != null) {
+ launcher.addToolArg(alias);
+ }
+ return ProcessTools.executeCommand(launcher.getCommand());
+ }
+
+ public static OutputAnalyzer jarsigner(String jar, String alias,
+ String options) throws Throwable {
+
+ return jarsigner(jar, alias, options.split("\\s+"));
+ }
+
+ public static OutputAnalyzer jarsigner(String jar, String alias,
+ String... options) throws Throwable {
+
+ return jarsigner(jar, alias, List.of(options));
+ }
+
+ public static OutputAnalyzer sign(String jar, String alias, String... options)
+ throws Throwable {
+
+ return jarsigner(jar, alias,
+ mergeOptions("-J-Djava.security.egd=file:/dev/./urandom", options));
+ }
+
+ public static OutputAnalyzer verify(String jar, String... options)
+ throws Throwable {
+
+ return jarsigner(jar, NO_ALIAS, mergeOptions("-verify", options));
+ }
+
+ // helper methods
+
+ private static List<String> mergeOptions(
+ String firstOption, String... secondPart) {
+
+ return mergeOptions(List.of(firstOption), secondPart);
+ }
+
+ private static List<String> mergeOptions(
+ List<String> firstPart, String... secondPart) {
+
+ List<String> options = new ArrayList<>(firstPart);
+ Collections.addAll(options, secondPart);
+ return options;
+ }
+}
--- a/jdk/test/sun/security/tools/keytool/KeyToolTest.java Tue Nov 08 14:29:14 2016 -0800
+++ b/jdk/test/sun/security/tools/keytool/KeyToolTest.java Tue Nov 08 15:55:11 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -1211,18 +1211,26 @@
void sqePrintcertTest() throws Exception {
remove("x.jks");
remove("mykey.cert");
+ remove("myweakkey.cert");
testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
"-keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
"-export -file mykey.cert -alias mykey");
+ testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
+ "-keypass changeit -genkeypair -dname CN=weak -keyalg rsa " +
+ "-keysize 512 -sigalg MD5withRSA -alias myweakkey");
+ testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
+ "-export -file myweakkey.cert -alias myweakkey");
testFail("", "-printcert -file badkeystore");
testFail("", "-printcert -file a/b/c/d");
testOK("", "-printcert -file mykey.cert");
+ testOK("", "-printcert -file myweakkey.cert");
FileInputStream fin = new FileInputStream("mykey.cert");
testOK(fin, "-printcert");
fin.close();
remove("x.jks");
remove("mykey.cert");
+ remove("myweakkey.cert");
}
// 8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness
--- a/jdk/test/sun/security/tools/keytool/PrintSSL.java Tue Nov 08 14:29:14 2016 -0800
+++ b/jdk/test/sun/security/tools/keytool/PrintSSL.java Tue Nov 08 15:55:11 2016 -0800
@@ -24,20 +24,32 @@
/*
* @test
* @bug 6480981 8160624
- * @modules java.base/sun.security.tools.keytool
* @summary keytool should be able to import certificates from remote SSL server
+ * @library /lib/security
+ * @library /lib/testlibrary
* @run main/othervm PrintSSL
*/
-import java.io.IOException;
import java.net.ServerSocket;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.concurrent.CountDownLatch;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
+import jdk.testlibrary.OutputAnalyzer;
public class PrintSSL {
- public static void main(String[] args) throws Exception {
+ public static void main(String[] args) throws Throwable {
+ Files.deleteIfExists(Paths.get("keystore"));
+
+ // make sure that "-printcert" works with weak algorithms
+ OutputAnalyzer out = SecurityTools.keytool("-genkeypair "
+ + "-keystore keystore -storepass passphrase "
+ + "-keypass passphrase -keyalg rsa -keysize 512 "
+ + "-sigalg MD5withRSA -alias rsa_alias -dname CN=Server");
+ System.out.println(out.getOutput());
+ out.shouldHaveExitValue(0);
int port = new Server().start();
if(port == -1) {
@@ -47,7 +59,10 @@
String cmd = String.format(
"-debug %s -printcert -sslserver localhost:%s",
((vmOpt == null) ? "" : vmOpt ), port);
- sun.security.tools.keytool.Main.main(cmd.split("\\s+"));
+
+ out = SecurityTools.keytool(cmd);
+ System.out.println(out.getOutput());
+ out.shouldHaveExitValue(0);
}
private static class Server implements Runnable {
@@ -68,9 +83,7 @@
public void run() {
System.setProperty("javax.net.ssl.keyStorePassword", "passphrase");
- System.setProperty("javax.net.ssl.keyStore",
- System.getProperty("test.src", "./")
- + "/../../../../javax/net/ssl/etc/keystore");
+ System.setProperty("javax.net.ssl.keyStore", "keystore");
SSLServerSocketFactory sslssf =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
try (ServerSocket server = sslssf.createServerSocket(0)) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/keytool/ReadJar.java Tue Nov 08 15:55:11 2016 -0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016, 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 6890872 8168882
+ * @summary keytool -printcert to recognize signed jar files
+ * @library /lib/security
+ * @library /lib/testlibrary
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import jdk.testlibrary.JarUtils;
+import jdk.testlibrary.OutputAnalyzer;
+
+public class ReadJar {
+
+ public static void main(String[] args) throws Throwable {
+ testWithMD5();
+ }
+
+ // make sure that -printcert option works
+ // if a weak algorithm was used for signing a jar
+ private static void testWithMD5() throws Throwable {
+ // create jar files
+ JarUtils.createJar("test_md5.jar", "test");
+ JarUtils.createJar("test_rsa.jar", "test");
+
+ // create a keystore and generate keys for jar signing
+ Files.deleteIfExists(Paths.get("keystore"));
+
+ OutputAnalyzer out = SecurityTools.keytool("-genkeypair "
+ + "-keystore keystore -storepass password "
+ + "-keypass password -keyalg rsa -alias rsa_alias -dname CN=A");
+ System.out.println(out.getOutput());
+ out.shouldHaveExitValue(0);
+
+ out = SecurityTools.jarsigner("test_rsa.jar", "rsa_alias",
+ "-keystore keystore -storepass password ");
+ System.out.println(out.getOutput());
+ out.shouldHaveExitValue(0);
+
+ printCert("test_rsa.jar");
+
+ out = SecurityTools.jarsigner("test_md5.jar", "rsa_alias",
+ "-keystore keystore -storepass password "
+ + "-sigalg MD5withRSA -digestalg MD5");
+ System.out.println(out.getOutput());
+ out.shouldHaveExitValue(0);
+
+ printCert("test_md5.jar");
+ }
+
+ private static void printCert(String jar) throws Throwable {
+ OutputAnalyzer out = SecurityTools.keytool("-printcert -jarfile " + jar);
+ System.out.println(out.getOutput());
+ out.shouldHaveExitValue(0);
+ out.shouldNotContain("Not a signed jar file");
+
+ out = SecurityTools.keytool("-printcert -rfc -jarfile " + jar);
+ System.out.println(out.getOutput());
+ out.shouldHaveExitValue(0);
+ out.shouldNotContain("Not a signed jar file");
+ }
+}
--- a/jdk/test/sun/security/tools/keytool/readjar.sh Tue Nov 08 14:29:14 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-#
-# Copyright (c) 2009, 2013, 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 6890872
-# @summary keytool -printcert to recognize signed jar files
-#
-
-if [ "${TESTJAVA}" = "" ] ; then
- JAVAC_CMD=`which javac`
- TESTJAVA=`dirname $JAVAC_CMD`/..
- COMPILEJAVA=${TESTJAVA}
-fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
- Windows_* )
- FS="\\"
- ;;
- * )
- FS="/"
- ;;
-esac
-
-KS=readjar.jks
-rm $KS
-$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS \
- -keyalg rsa -alias x -dname CN=X -genkeypair
-$COMPILEJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS} cvf readjar.jar $KS
-$COMPILEJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -storepass changeit -keystore $KS readjar.jar x
-
-$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -printcert -jarfile readjar.jar || exit 1
-$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -printcert -jarfile readjar.jar -rfc || exit 1
-
-exit 0
-