From 2e77de17ec18eac98bfa659bcbc8b81d9842ce63 Mon Sep 17 00:00:00 2001 From: weijun Date: Fri, 16 Apr 2010 10:06:07 +0800 Subject: [PATCH] 6937978: let keytool -gencert generate the chain Reviewed-by: mullan --- .../classes/sun/security/tools/KeyTool.java | 107 ++++++++++-------- test/sun/security/tools/keytool/selfissued.sh | 28 ++--- 2 files changed, 72 insertions(+), 63 deletions(-) diff --git a/src/share/classes/sun/security/tools/KeyTool.java b/src/share/classes/sun/security/tools/KeyTool.java index 3f6eca932..bd03c696e 100644 --- a/src/share/classes/sun/security/tools/KeyTool.java +++ b/src/share/classes/sun/security/tools/KeyTool.java @@ -1211,6 +1211,14 @@ public final class KeyTool { X509CertImpl cert = new X509CertImpl(info); cert.sign(privateKey, sigAlgName); dumpCert(cert, out); + for (Certificate ca: keyStore.getCertificateChain(alias)) { + if (ca instanceof X509Certificate) { + X509Certificate xca = (X509Certificate)ca; + if (!isSelfSigned(xca)) { + dumpCert(xca, out); + } + } + } } /** @@ -2640,19 +2648,33 @@ public final class KeyTool { } /** - * Returns true if the given certificate is trusted, false otherwise. + * Locates a signer for a given certificate from a given keystore and + * returns the signer's certificate. + * @param cert the certificate whose signer is searched, not null + * @param ks the keystore to search with, not null + * @return cert itself if it's already inside ks, + * or a certificate inside ks who signs cert, + * or null otherwise. */ - private boolean isTrusted(Certificate cert) - throws Exception - { - if (keyStore.getCertificateAlias(cert) != null) { - return true; // found in own keystore + private static Certificate getTrustedSigner(Certificate cert, KeyStore ks) + throws Exception { + if (ks.getCertificateAlias(cert) != null) { + return cert; } - if (trustcacerts && (caks != null) && - (caks.getCertificateAlias(cert) != null)) { - return true; // found in CA keystore + for (Enumeration aliases = ks.aliases(); + aliases.hasMoreElements(); ) { + String name = aliases.nextElement(); + Certificate trustedCert = ks.getCertificate(name); + if (trustedCert != null) { + try { + cert.verify(trustedCert.getPublicKey()); + return trustedCert; + } catch (Exception e) { + // Not verified, skip to the next one + } + } } - return false; + return null; } /** @@ -2985,48 +3007,33 @@ public final class KeyTool { return replyCerts; } - // do we trust the (root) cert at the top? + // do we trust the cert at the top? Certificate topCert = replyCerts[replyCerts.length-1]; - if (!isTrusted(topCert)) { - boolean verified = false; - Certificate rootCert = null; - if (trustcacerts && (caks!= null)) { - for (Enumeration aliases = caks.aliases(); - aliases.hasMoreElements(); ) { - String name = aliases.nextElement(); - rootCert = caks.getCertificate(name); - if (rootCert != null) { - try { - topCert.verify(rootCert.getPublicKey()); - verified = true; - break; - } catch (Exception e) { - } - } - } + Certificate root = getTrustedSigner(topCert, keyStore); + if (root == null && trustcacerts && caks != null) { + root = getTrustedSigner(topCert, caks); + } + if (root == null) { + System.err.println(); + System.err.println + (rb.getString("Top-level certificate in reply:\n")); + printX509Cert((X509Certificate)topCert, System.out); + System.err.println(); + System.err.print(rb.getString("... is not trusted. ")); + String reply = getYesNoReply + (rb.getString("Install reply anyway? [no]: ")); + if ("NO".equals(reply)) { + return null; } - if (!verified) { - System.err.println(); - System.err.println - (rb.getString("Top-level certificate in reply:\n")); - printX509Cert((X509Certificate)topCert, System.out); - System.err.println(); - System.err.print(rb.getString("... is not trusted. ")); - String reply = getYesNoReply - (rb.getString("Install reply anyway? [no]: ")); - if ("NO".equals(reply)) { - return null; - } - } else { - if (!isSelfSigned((X509Certificate)topCert)) { - // append the (self-signed) root CA cert to the chain - Certificate[] tmpCerts = - new Certificate[replyCerts.length+1]; - System.arraycopy(replyCerts, 0, tmpCerts, 0, - replyCerts.length); - tmpCerts[tmpCerts.length-1] = rootCert; - replyCerts = tmpCerts; - } + } else { + if (root != topCert) { + // append the root CA cert to the chain + Certificate[] tmpCerts = + new Certificate[replyCerts.length+1]; + System.arraycopy(replyCerts, 0, tmpCerts, 0, + replyCerts.length); + tmpCerts[tmpCerts.length-1] = root; + replyCerts = tmpCerts; } } diff --git a/test/sun/security/tools/keytool/selfissued.sh b/test/sun/security/tools/keytool/selfissued.sh index e6e06c040..ec27a98a6 100644 --- a/test/sun/security/tools/keytool/selfissued.sh +++ b/test/sun/security/tools/keytool/selfissued.sh @@ -1,5 +1,5 @@ # -# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2009-2010 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 @@ -22,8 +22,8 @@ # # @test -# @bug 6825352 -# @summary support self-issued certificate in keytool +# @bug 6825352 6937978 +# @summary support self-issued certificate in keytool and let -gencert generate the chain # # @run shell selfissued.sh # @@ -50,20 +50,22 @@ KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystor rm $KS $KT -alias ca -dname CN=CA -genkeypair -$KT -alias me -dname CN=CA -genkeypair +$KT -alias ca1 -dname CN=CA -genkeypair +$KT -alias ca2 -dname CN=CA -genkeypair $KT -alias e1 -dname CN=E1 -genkeypair -$KT -alias e2 -dname CN=E2 -genkeypair -# me signed by ca, self-issued -$KT -alias me -certreq | $KT -alias ca -gencert | $KT -alias me -importcert +# ca signs ca1, ca1 signs ca2, all self-issued +$KT -alias ca1 -certreq | $KT -alias ca -gencert -ext san=dns:ca1 \ + | $KT -alias ca1 -importcert +$KT -alias ca2 -certreq | $KT -alias ca1 -gencert -ext san=dns:ca2 \ + | $KT -alias ca2 -importcert -# Import e1 signed by me, should add me and ca -$KT -alias e1 -certreq | $KT -alias me -gencert | $KT -alias e1 -importcert +# Import e1 signed by ca2, should add ca2 and ca1, at least 3 certs in the chain +$KT -alias e1 -certreq | $KT -alias ca2 -gencert > e1.cert +$KT -alias ca1 -delete +$KT -alias ca2 -delete +cat e1.cert | $KT -alias e1 -importcert $KT -alias e1 -list -v | grep '\[3\]' || { echo Bad E1; exit 1; } -# Import (e2 signed by me,ca,me), should reorder to (e2,me,ca) -( $KT -alias e2 -certreq | $KT -alias me -gencert; $KT -exportcert -alias ca; $KT -exportcert -alias me ) | $KT -alias e2 -importcert -$KT -alias e2 -list -v | grep '\[3\]' || { echo Bad E2; exit 1; } - echo Good -- GitLab