8074018: Named extension not recognized in keytool -ext honored after 8073182
authorweijun
Sat, 28 Feb 2015 10:47:07 +0800
changeset 29225 fb5b4b9d12f5
parent 29224 8433f5f46142
child 29226 b675016fabfd
8074018: Named extension not recognized in keytool -ext honored after 8073182 Reviewed-by: mullan
jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java
jdk/test/sun/security/tools/keytool/KeyToolTest.java
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Fri Feb 27 14:36:03 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Sat Feb 28 10:47:07 2015 +0800
@@ -3790,6 +3790,17 @@
             PublicKey pkey,
             PublicKey akey) throws Exception {
 
+        // By design, inside a CertificateExtensions object, all known
+        // extensions uses name (say, "BasicConstraints") as key and
+        // a child Extension type (say, "BasicConstraintsExtension")
+        // as value, unknown extensions uses OID as key and bare
+        // Extension object as value. This works fine inside JDK.
+        //
+        // However, in keytool, there is no way to prevent people
+        // using OID in -ext, either as a new extension, or in a
+        // honored value. Thus here we (ab)use CertificateExtensions
+        // by always using OID as key and value can be of any type.
+
         if (existingEx != null && requestedEx != null) {
             // This should not happen
             throw new Exception("One of request and original should be null.");
@@ -3805,13 +3816,19 @@
             // name{:critical}{=value}
             // Honoring requested extensions
             if (requestedEx != null) {
+                // The existing requestedEx might use names as keys,
+                // translate to all-OID first.
+                CertificateExtensions request2 = new CertificateExtensions();
+                for (sun.security.x509.Extension ex: requestedEx.getAllExtensions()) {
+                    request2.set(ex.getId(), ex);
+                }
                 for(String extstr: extstrs) {
                     if (extstr.toLowerCase(Locale.ENGLISH).startsWith("honored=")) {
                         List<String> list = Arrays.asList(
                                 extstr.toLowerCase(Locale.ENGLISH).substring(8).split(","));
                         // First check existence of "all"
                         if (list.contains("all")) {
-                            for (Extension ex: requestedEx.getAllExtensions()) {
+                            for (Extension ex: request2.getAllExtensions()) {
                                 setExt(result, ex);
                             }
                         }
@@ -3844,7 +3861,7 @@
                             }
                             String n = findOidForExtName(type).toString();
                             if (add) {
-                                Extension e = requestedEx.get(n);
+                                Extension e = request2.get(n);
                                 if (!e.isCritical() && action == 0
                                         || e.isCritical() && action == 1) {
                                     e = Extension.newExtension(
--- a/jdk/test/sun/security/tools/keytool/KeyToolTest.java	Fri Feb 27 14:36:03 2015 -0800
+++ b/jdk/test/sun/security/tools/keytool/KeyToolTest.java	Sat Feb 28 10:47:07 2015 +0800
@@ -1612,7 +1612,7 @@
 
         // 8073181: keytool -ext honored not working correctly
         testOK("", simple+"-gencert -alias ca -infile test.req -ext " +
-                "honored=1.2.3,1.2.4:critical " +
+                "honored=1.2.3,KU,1.2.4:critical " +
                 "-debug -rfc -outfile test2.cert");
         testOK("", simple+"-importcert -file test2.cert -alias b");
         ks = loadStore("x.jks", "changeit", "JKS");