--- a/jdk/src/share/classes/sun/security/tools/KeyTool.java Thu Apr 15 17:00:55 2010 -0700
+++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java Fri Apr 16 10:06:07 2010 +0800
@@ -1211,6 +1211,14 @@
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 @@
}
/**
- * 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 <code>cert</code> itself if it's already inside <code>ks</code>,
+ * or a certificate inside <code>ks</code> who signs <code>cert</code>,
+ * 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<String> 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 @@
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<String> 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;
}
}
--- a/jdk/test/sun/security/tools/keytool/selfissued.sh Thu Apr 15 17:00:55 2010 -0700
+++ b/jdk/test/sun/security/tools/keytool/selfissued.sh Fri Apr 16 10:06:07 2010 +0800
@@ -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 @@
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
-# Import e1 signed by me, should add me and ca
-$KT -alias e1 -certreq | $KT -alias me -gencert | $KT -alias e1 -importcert
-$KT -alias e1 -list -v | grep '\[3\]' || { echo Bad E1; exit 1; }
+# 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 (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; }
+# 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; }
echo Good