< prev index next >

src/share/classes/sun/security/tools/keytool/Main.java

Print this page

        

@@ -75,13 +75,15 @@
 import sun.security.util.KeyUtil;
 import sun.security.util.NamedCurve;
 import sun.security.util.ObjectIdentifier;
 import sun.security.pkcs10.PKCS10;
 import sun.security.pkcs10.PKCS10Attribute;
+import sun.security.pkcs12.PKCS12KeyStore;
 import sun.security.provider.X509Factory;
 import sun.security.provider.certpath.CertStoreHelper;
 import sun.security.util.Password;
+import sun.security.util.SecurityProperties;
 import sun.security.util.SecurityProviderConstants;
 import sun.security.util.SignatureUtil;
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;

@@ -188,10 +190,11 @@
             new DisabledAlgorithmConstraints(
                     DisabledAlgorithmConstraints.PROPERTY_SECURITY_LEGACY_ALGS);
 
     private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
             .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
+    private boolean isPasswordlessKeyStore = false;
 
     enum Command {
         CERTREQ("Generates.a.certificate.request",
             ALIAS, SIGALG, FILEOUT, KEYPASS, KEYSTORE, DNAME,
             STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,

@@ -792,20 +795,44 @@
             alias = getAlias(null);
             if ("".equals(alias)) {
                 throw new Exception(rb.getString("Must.specify.alias"));
             }
         }
-
         // Create new keystore
+    // Probe for keystore type when filename is available
+    if (ksfile != null && ksStream != null && providerName == null &&
+            storetype == null && !inplaceImport) {
+        String realType = keyStoreType(ksfile);
+        // If the magic number does not conform to JKS
+        // then it must be PKCS12
+        if (!"JKS".equalsIgnoreCase(realType)) {
+            storetype = P12KEYSTORE;
+            isPasswordlessKeyStore = PKCS12KeyStore.isPasswordless(ksfile);
+        } else {
+            storetype = KeyStore.getDefaultType();;
+        }
+        keyStore = KeyStore.getInstance(storetype);
+        keyStore.load(ksStream, storePass);
+        ksStream.close();
+    } else {
         if (storetype == null) {
             storetype = KeyStore.getDefaultType();
         }
         if (providerName == null) {
             keyStore = KeyStore.getInstance(storetype);
         } else {
             keyStore = KeyStore.getInstance(storetype, providerName);
         }
+        // When creating a new pkcs12 file, Do not prompt for storepass
+        // if certProtectionAlgorithm and macAlgorithm are both NONE.
+        if (storetype.equalsIgnoreCase("pkcs12") && !isPasswordlessKeyStore) {
+            isPasswordlessKeyStore =
+                    "NONE".equals(SecurityProperties.privilegedGetOverridable(
+                            "keystore.pkcs12.certProtectionAlgorithm"))
+                            && "NONE".equals(SecurityProperties.privilegedGetOverridable(
+                            "keystore.pkcs12.macAlgorithm"));
+        }
 
         /*
          * Load the keystore data.
          *
          * At this point, it's OK if no keystore password has been provided.

@@ -833,11 +860,11 @@
             }
             if (ksStream != null) {
                 ksStream.close();
             }
         }
-
+    }
         if (P12KEYSTORE.equalsIgnoreCase(storetype) && command == KEYPASSWD) {
             throw new UnsupportedOperationException(rb.getString
                     (".keypasswd.commands.not.supported.if.storetype.is.PKCS12"));
         }
 

@@ -852,15 +879,14 @@
             if (ksStream == null && storePass.length < 6) {
                 throw new Exception(rb.getString
                         ("Keystore.password.must.be.at.least.6.characters"));
             }
         } else if (storePass == null) {
-
-            // only prompt if (protectedPath == false)
-
-            if (!protectedPath && !KeyStoreUtil.isWindowsKeyStore(storetype) &&
-                (command == CERTREQ ||
+            if (!protectedPath && !KeyStoreUtil.isWindowsKeyStore(storetype)
+                    && isKeyStoreRelated(command)
+                    && !isPasswordlessKeyStore) {
+                if (command == CERTREQ ||
                         command == DELETE ||
                         command == GENKEYPAIR ||
                         command == GENSECKEY ||
                         command == IMPORTCERT ||
                         command == IMPORTPASS ||

@@ -868,11 +894,11 @@
                         command == KEYCLONE ||
                         command == CHANGEALIAS ||
                         command == SELFCERT ||
                         command == STOREPASSWD ||
                         command == KEYPASSWD ||
-                        command == IDENTITYDB)) {
+                        command == IDENTITYDB) {
                 int count = 0;
                 do {
                     if (command == IMPORTKEYSTORE) {
                         System.err.print
                                 (rb.getString("Enter.destination.keystore.password."));

@@ -912,21 +938,20 @@
                 if (storePass == null) {
                     System.err.println
                         (rb.getString("Too.many.failures.try.later"));
                     return;
                 }
-            } else if (!protectedPath
-                    && !KeyStoreUtil.isWindowsKeyStore(storetype)
-                    && isKeyStoreRelated(command)) {
+                } else {
                 // here we have EXPORTCERT and LIST (info valid until STOREPASSWD)
                 if (command != PRINTCRL) {
                     System.err.print(rb.getString("Enter.keystore.password."));
                     System.err.flush();
                     storePass = Password.readPassword(System.in);
                     passwords.add(storePass);
                 }
             }
+            }
 
             // Now load a nullStream-based keystore,
             // or verify the integrity of an input stream-based keystore
             if (nullStream) {
                 keyStore.load(null, storePass);

@@ -1113,11 +1138,12 @@
             keyPassNew = newPass;
             doChangeKeyPasswd(alias);
             kssave = true;
         } else if (command == LIST) {
             if (storePass == null
-                    && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
+                && !KeyStoreUtil.isWindowsKeyStore(storetype)
+                && !isPasswordlessKeyStore) {
                 printNoIntegrityWarning();
             }
 
             if (alias != null) {
                 doPrintEntry(rb.getString("the.certificate"), alias, out);

@@ -1494,11 +1520,12 @@
      */
     private void doExportCert(String alias, PrintStream out)
         throws Exception
     {
         if (storePass == null
-                && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
+                && !KeyStoreUtil.isWindowsKeyStore(storetype)
+                && !isPasswordlessKeyStore) {
             printNoIntegrityWarning();
         }
         if (alias == null) {
             alias = keyAlias;
         }

@@ -1525,35 +1552,38 @@
      * @param alias the entry we will set password for
      * @param orig the original entry of doing a dup, null if generate new
      * @param origPass the password to copy from if user press ENTER
      */
     private char[] promptForKeyPass(String alias, String orig, char[] origPass) throws Exception{
-        if (P12KEYSTORE.equalsIgnoreCase(storetype)) {
+        if (origPass != null && P12KEYSTORE.equalsIgnoreCase(storetype)) {
             return origPass;
         } else if (!token && !protectedPath) {
             // Prompt for key password
             int count;
             for (count = 0; count < 3; count++) {
                 MessageFormat form = new MessageFormat(rb.getString
                         ("Enter.key.password.for.alias."));
                 Object[] source = {alias};
-                System.err.println(form.format(source));
+                System.err.print(form.format(source));
+                if (origPass != null) {
+                    System.err.println();
                 if (orig == null) {
                     System.err.print(rb.getString
                             (".RETURN.if.same.as.keystore.password."));
                 } else {
                     form = new MessageFormat(rb.getString
                             (".RETURN.if.same.as.for.otherAlias."));
                     Object[] src = {orig};
                     System.err.print(form.format(src));
                 }
+                }
                 System.err.flush();
                 char[] entered = Password.readPassword(System.in);
                 passwords.add(entered);
-                if (entered == null) {
+                if (entered == null && origPass != null) {
                     return origPass;
-                } else if (entered.length >= 6) {
+                } else if (entered != null && entered.length >= 6) {
                     System.err.print(rb.getString("Re.enter.new.password."));
                     char[] passAgain = Password.readPassword(System.in);
                     passwords.add(passAgain);
                     if (!Arrays.equals(entered, passAgain)) {
                         System.err.println

@@ -1942,10 +1972,13 @@
                     out.println
                         (rb.getString("Certificate.fingerprint.SHA.256.") +
                         getCertFingerPrint("SHA-256", chain[0]));
                     checkWeak(label, chain[0]);
                 }
+            } else {
+                out.println(rb.getString
+                        ("Certificate.chain.length.") + 0);
             }
         } else if (keyStore.entryInstanceOf(alias,
                 KeyStore.TrustedCertificateEntry.class)) {
             // We have a trusted certificate entry
             Certificate cert = keyStore.getCertificate(alias);

@@ -2006,11 +2039,11 @@
      */
     KeyStore loadSourceKeyStore() throws Exception {
 
         InputStream is = null;
         File srcksfile = null;
-
+        boolean srcIsPasswordless = false;
         if (P11KEYSTORE.equalsIgnoreCase(srcstoretype) ||
                 KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
             if (!NONE.equals(srcksfname)) {
                 System.err.println(MessageFormat.format(rb.getString
                     (".keystore.must.be.NONE.if.storetype.is.{0}"), srcstoretype));

@@ -2023,21 +2056,29 @@
         }
 
         KeyStore store;
         try {
             if (srcstoretype == null) {
+                String realType = keyStoreType(srcksfile);
+                if (srcksfile != null && is != null && srcProviderName == null &&
+                        !"JKS".equalsIgnoreCase(realType)) {
+                    srcstoretype = P12KEYSTORE;
+                    srcIsPasswordless = PKCS12KeyStore.isPasswordless(srcksfile);
+                } else {
                 srcstoretype = KeyStore.getDefaultType();
             }
+            }
             if (srcProviderName == null) {
                 store = KeyStore.getInstance(srcstoretype);
             } else {
                 store = KeyStore.getInstance(srcstoretype, srcProviderName);
             }
 
             if (srcstorePass == null
                     && !srcprotectedPath
-                    && !KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
+                    && !KeyStoreUtil.isWindowsKeyStore(srcstoretype)
+                    && !srcIsPasswordless) {
                 System.err.print(rb.getString("Enter.source.keystore.password."));
                 System.err.flush();
                 srcstorePass = Password.readPassword(System.in);
                 passwords.add(srcstorePass);
             }

@@ -2060,10 +2101,11 @@
                 is.close();
             }
         }
 
         if (srcstorePass == null
+                && !srcIsPasswordless
                 && !KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
             // anti refactoring, copied from printNoIntegrityWarning(),
             // but change 2 lines
             System.err.println();
             System.err.println(rb.getString

@@ -3374,30 +3416,30 @@
             throw new Exception(form.format(source));
         }
 
         if (keyPass == null) {
             // Try to recover the key using the keystore password
+            if (storePass != null) {
             try {
                 key = keyStore.getKey(alias, storePass);
-
-                keyPass = storePass;
-                passwords.add(keyPass);
+                    passwords.add(storePass);
+                    return Pair.of(key, storePass);
             } catch (UnrecoverableKeyException e) {
-                // Did not work out, so prompt user for key password
-                if (!token) {
-                    keyPass = getKeyPasswd(alias, null, null);
-                    key = keyStore.getKey(alias, keyPass);
-                } else {
+                    if (token) {
                     throw e;
                 }
             }
+            }
+            // prompt user for key password
+            keyPass = getKeyPasswd(alias, null, null);
+            key = keyStore.getKey(alias, keyPass);
+            return Pair.of(key, keyPass);
         } else {
             key = keyStore.getKey(alias, keyPass);
-        }
-
         return Pair.of(key, keyPass);
     }
+    }
 
     /**
      * Recovers entry associated with given alias.
      *
      * @return an array of objects, where the 1st element in the array is the

@@ -3406,73 +3448,62 @@
      */
     private Pair<Entry,char[]> recoverEntry(KeyStore ks,
                             String alias,
                             char[] pstore,
                             char[] pkey) throws Exception {
-
-        if (ks.containsAlias(alias) == false) {
-            MessageFormat form = new MessageFormat
-                (rb.getString("Alias.alias.does.not.exist"));
+        if (!ks.containsAlias(alias)) {
+            MessageFormat form = new MessageFormat(
+                    rb.getString("Alias.alias.does.not.exist"));
             Object[] source = {alias};
             throw new Exception(form.format(source));
         }
 
-        PasswordProtection pp = null;
-        Entry entry;
-
+        // Step 1: First attempt to access entry without key password
+        // (PKCS11 entry or trusted certificate entry, for example).
+        // If fail, go next.
         try {
-            // First attempt to access entry without key password
-            // (PKCS11 entry or trusted certificate entry, for example)
-
-            entry = ks.getEntry(alias, pp);
-            pkey = null;
+            Entry entry = ks.getEntry(alias, null);
+            return Pair.of(entry, null);
         } catch (UnrecoverableEntryException une) {
-
             if(P11KEYSTORE.equalsIgnoreCase(ks.getType()) ||
                 KeyStoreUtil.isWindowsKeyStore(ks.getType())) {
                 // should not happen, but a possibility
                 throw une;
             }
+        }
 
             // entry is protected
-
+        // Step 2: try pkey if not null. If fail, fail.
             if (pkey != null) {
+            PasswordProtection pp = new PasswordProtection(pkey);
+            Entry entry = ks.getEntry(alias, pp);
+            return Pair.of(entry, pkey);
+        }
 
-                // try provided key password
-
-                pp = new PasswordProtection(pkey);
-                entry = ks.getEntry(alias, pp);
-
-            } else {
-
-                // try store pass
-
+        // Step 3: try pstore if not null. If fail, go next.
+        if (pstore != null) {
                 try {
-                    pp = new PasswordProtection(pstore);
-                    entry = ks.getEntry(alias, pp);
-                    pkey = pstore;
-                } catch (UnrecoverableEntryException une2) {
+                PasswordProtection pp = new PasswordProtection(pstore);
+                Entry entry = ks.getEntry(alias, pp);
+                return Pair.of(entry, pstore);
+            } catch (UnrecoverableEntryException une) {
                     if (P12KEYSTORE.equalsIgnoreCase(ks.getType())) {
-
                         // P12 keystore currently does not support separate
-                        // store and entry passwords
-
-                        throw une2;
-                    } else {
-
-                        // prompt for entry password
-
-                        pkey = getKeyPasswd(alias, null, null);
-                        pp = new PasswordProtection(pkey);
-                        entry = ks.getEntry(alias, pp);
-                    }
+                    // store and entry passwords. We will not prompt for
+                    // entry password.
+                    throw une;
                 }
             }
         }
 
+        // Step 4: prompt for entry password
+        pkey = getKeyPasswd(alias, null, null);
+        PasswordProtection pp = new PasswordProtection(pkey);
+        Entry entry = ks.getEntry(alias, pp);
         return Pair.of(entry, pkey);
     }
+
     /**
      * Gets the requested finger print of the certificate.
      */
     private String getCertFingerPrint(String mdAlg, Certificate cert)
         throws Exception
< prev index next >