changeset 6408:d53388381f50

8024302: Clarify jar verifications 8023338: Update jarsigner to encourage timestamping Reviewed-by: mullan, ahgross
author weijun
date Thu, 19 Sep 2013 10:40:16 +0800
parents 5f85d1b98239
children 47e0b80c2703
files src/share/classes/sun/security/tools/JarSigner.java src/share/classes/sun/security/tools/JarSignerResources.java
diffstat 2 files changed, 91 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/tools/JarSigner.java	Tue Mar 06 10:25:45 2012 +0800
+++ b/src/share/classes/sun/security/tools/JarSigner.java	Thu Sep 19 10:40:16 2013 +0800
@@ -155,8 +155,13 @@
     private String altSignerClasspath = null;
     private ZipFile zipFile = null;
 
+    // Informational warnings
+    private boolean hasExpiringCert = false;
+    private boolean noTimestamp = false;
+    private Date expireDate = new Date(0L);     // used in noTimestamp warning
+
+    // Severe warnings
     private boolean hasExpiredCert = false;
-    private boolean hasExpiringCert = false;
     private boolean notYetValidCert = false;
     private boolean chainNotValidated = false;
     private boolean notSignedByAlias = false;
@@ -255,9 +260,6 @@
 
         if (strict) {
             int exitCode = 0;
-            if (hasExpiringCert) {
-                exitCode |= 2;
-            }
             if (chainNotValidated || hasExpiredCert || notYetValidCert) {
                 exitCode |= 4;
             }
@@ -746,14 +748,25 @@
                 System.out.println(rb.getString(
                       "jar.is.unsigned.signatures.missing.or.not.parsable."));
             } else {
-                System.out.println(rb.getString("jar.verified."));
-                if (hasUnsignedEntry || hasExpiredCert || hasExpiringCert ||
-                    badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
-                    notYetValidCert || chainNotValidated ||
-                    aliasNotInStore || notSignedByAlias) {
+                boolean warningAppeared = false;
+                boolean errorAppeared = false;
+                if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
+                        notYetValidCert || chainNotValidated || hasExpiredCert ||
+                        hasUnsignedEntry ||
+                        aliasNotInStore || notSignedByAlias) {
 
-                    System.out.println();
-                    System.out.println(rb.getString("Warning."));
+                    if (strict) {
+                        System.out.println(rb.getString("jar.verified.with.signer.errors."));
+                        System.out.println();
+                        System.out.println(rb.getString("Error."));
+                        errorAppeared = true;
+                    } else {
+                        System.out.println(rb.getString("jar.verified."));
+                        System.out.println();
+                        System.out.println(rb.getString("Warning."));
+                        warningAppeared = true;
+                    }
+
                     if (badKeyUsage) {
                         System.out.println(
                             rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
@@ -777,10 +790,6 @@
                         System.out.println(rb.getString(
                             "This.jar.contains.entries.whose.signer.certificate.has.expired."));
                     }
-                    if (hasExpiringCert) {
-                        System.out.println(rb.getString(
-                            "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
-                    }
                     if (notYetValidCert) {
                         System.out.println(rb.getString(
                             "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
@@ -799,10 +808,29 @@
                     if (aliasNotInStore) {
                         System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
                     }
+                } else {
+                    System.out.println(rb.getString("jar.verified."));
+                }
+                if (hasExpiringCert || noTimestamp) {
+                    if (!warningAppeared) {
+                        System.out.println();
+                        System.out.println(rb.getString("Warning."));
+                        warningAppeared = true;
+                    }
+                    if (hasExpiringCert) {
+                        System.out.println(rb.getString(
+                                "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
+                    }
+                    if (noTimestamp) {
+                        System.out.println(
+                                String.format(rb.getString("no.timestamp.verifying"), expireDate));
+                    }
+                }
+                if (warningAppeared || errorAppeared) {
                     if (! (verbose != null && showcerts)) {
                         System.out.println();
                         System.out.println(rb.getString(
-                            "Re.run.with.the.verbose.and.certs.options.for.more.details."));
+                                "Re.run.with.the.verbose.and.certs.options.for.more.details."));
                     }
                 }
             }
@@ -862,6 +890,9 @@
             try {
                 boolean printValidity = true;
                 if (timestamp == null) {
+                    if (expireDate.getTime() == 0 || expireDate.after(notAfter)) {
+                        expireDate = notAfter;
+                    }
                     x509Cert.checkValidity();
                     // test if cert will expire within six months
                     if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
@@ -1227,6 +1258,10 @@
                 tsaCert = getTsaCert(tsaAlias);
             }
 
+            if (tsaUrl == null && tsaCert == null) {
+                noTimestamp = true;
+            }
+
             SignatureFile.Block block = null;
 
             try {
@@ -1375,12 +1410,20 @@
                 }
             }
 
-            if (hasExpiredCert || hasExpiringCert || notYetValidCert
-                    || badKeyUsage || badExtendedKeyUsage
-                    || badNetscapeCertType || chainNotValidated) {
-                System.out.println();
+            boolean warningAppeared = false;
+            if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
+                    notYetValidCert || chainNotValidated || hasExpiredCert) {
+                if (strict) {
+                    System.out.println(rb.getString("jar.signed.with.signer.errors."));
+                    System.out.println();
+                    System.out.println(rb.getString("Error."));
+                } else {
+                    System.out.println(rb.getString("jar.signed."));
+                    System.out.println();
+                    System.out.println(rb.getString("Warning."));
+                    warningAppeared = true;
+                }
 
-                System.out.println(rb.getString("Warning."));
                 if (badKeyUsage) {
                     System.out.println(
                         rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
@@ -1399,9 +1442,6 @@
                 if (hasExpiredCert) {
                     System.out.println(
                         rb.getString("The.signer.certificate.has.expired."));
-                } else if (hasExpiringCert) {
-                    System.out.println(
-                        rb.getString("The.signer.certificate.will.expire.within.six.months."));
                 } else if (notYetValidCert) {
                     System.out.println(
                         rb.getString("The.signer.certificate.is.not.yet.valid."));
@@ -1411,6 +1451,24 @@
                     System.out.println(
                             rb.getString("The.signer.s.certificate.chain.is.not.validated."));
                 }
+            } else {
+                System.out.println(rb.getString("jar.signed."));
+            }
+            if (hasExpiringCert || noTimestamp) {
+                if (!warningAppeared) {
+                    System.out.println();
+                    System.out.println(rb.getString("Warning."));
+                }
+
+                if (hasExpiringCert) {
+                    System.out.println(
+                            rb.getString("The.signer.certificate.will.expire.within.six.months."));
+                }
+
+                if (noTimestamp) {
+                    System.out.println(
+                            String.format(rb.getString("no.timestamp.signing"), expireDate));
+                }
             }
 
         // no IOException thrown in the above try clause, so disable
@@ -1496,6 +1554,7 @@
             timestamp = ts.getTimestamp();
         } else {
             timestamp = null;
+            noTimestamp = true;
         }
         // display the certificate(s). The first one is end-entity cert and
         // its KeyUsage should be checked.
--- a/src/share/classes/sun/security/tools/JarSignerResources.java	Tue Mar 06 10:25:45 2012 +0800
+++ b/src/share/classes/sun/security/tools/JarSignerResources.java	Thu Sep 19 10:40:16 2013 +0800
@@ -133,7 +133,10 @@
         {".Unsigned.entries.", "(Unsigned entries)"},
         {"jar.is.unsigned.signatures.missing.or.not.parsable.",
                 "jar is unsigned. (signatures missing or not parsable)"},
+        {"jar.signed.", "jar signed."},
+        {"jar.signed.with.signer.errors.", "jar signed, with signer errors."},
         {"jar.verified.", "jar verified."},
+        {"jar.verified.with.signer.errors.", "jar verified, with signer errors."},
         {"jarsigner.", "jarsigner: "},
         {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
                 "signature filename must consist of the following characters: A-Z, 0-9, _ or -"},
@@ -191,6 +194,7 @@
                 "using an alternative signing mechanism"},
         {"entry.was.signed.on", "entry was signed on {0}"},
         {"Warning.", "Warning: "},
+        {"Error.", "Error: "},
         {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
                 "This jar contains unsigned entries which have not been integrity-checked. "},
         {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
@@ -227,6 +231,10 @@
                 "The signer's certificate chain is not validated."},
         {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.",
                  "This jar contains entries whose certificate chain is not validated."},
+        {"no.timestamp.signing",
+                "No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
+        {"no.timestamp.verifying",
+                "This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
     };
 
     /**