--- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Wed Dec 02 16:44:54 2015 +0800
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Wed Dec 02 16:44:57 2015 +0800
@@ -150,6 +150,7 @@
private Date expireDate = new Date(0L); // used in noTimestamp warning
// Severe warnings
+ private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg
private boolean hasExpiredCert = false;
private boolean notYetValidCert = false;
private boolean chainNotValidated = false;
@@ -159,6 +160,9 @@
private boolean badKeyUsage = false;
private boolean badExtendedKeyUsage = false;
private boolean badNetscapeCertType = false;
+ private boolean signerSelfSigned = false;
+
+ private Throwable chainNotValidatedReason = null;
CertificateFactory certificateFactory;
CertPathValidator validator;
@@ -243,7 +247,7 @@
if (strict) {
int exitCode = 0;
- if (chainNotValidated || hasExpiredCert || notYetValidCert) {
+ if (weakAlg != 0 || chainNotValidated || hasExpiredCert || notYetValidCert || signerSelfSigned) {
exitCode |= 4;
}
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
@@ -780,6 +784,12 @@
if (man == null)
System.out.println(rb.getString("no.manifest."));
+ // If signer is a trusted cert or private entry in user's own
+ // keystore, it can be self-signed.
+ if (!aliasNotInStore) {
+ signerSelfSigned = false;
+ }
+
if (!anySigned) {
System.out.println(rb.getString(
"jar.is.unsigned.signatures.missing.or.not.parsable."));
@@ -788,7 +798,7 @@
boolean errorAppeared = false;
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
notYetValidCert || chainNotValidated || hasExpiredCert ||
- hasUnsignedEntry ||
+ hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) ||
aliasNotInStore || notSignedByAlias) {
if (strict) {
@@ -803,6 +813,12 @@
warningAppeared = true;
}
+ if (weakAlg != 0) {
+ // In fact, jarsigner verification did not catch this
+ // since it has not read the JarFile content itself.
+ // Everything is done with JarFile API.
+ }
+
if (badKeyUsage) {
System.out.println(
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
@@ -832,8 +848,9 @@
}
if (chainNotValidated) {
- System.out.println(
- rb.getString("This.jar.contains.entries.whose.certificate.chain.is.not.validated."));
+ System.out.println(String.format(
+ rb.getString("This.jar.contains.entries.whose.certificate.chain.is.not.validated.reason.1"),
+ chainNotValidatedReason.getLocalizedMessage()));
}
if (notSignedByAlias) {
@@ -844,6 +861,11 @@
if (aliasNotInStore) {
System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
}
+
+ if (signerSelfSigned) {
+ System.out.println(rb.getString(
+ "This.jar.contains.entries.whose.signer.certificate.is.self.signed."));
+ }
} else {
System.out.println(rb.getString("jar.verified."));
}
@@ -1074,7 +1096,25 @@
}
void signJar(String jarName, String alias)
- throws Exception {
+ throws Exception {
+
+ DisabledAlgorithmConstraints dac =
+ new DisabledAlgorithmConstraints(
+ DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
+
+ if (digestalg != null && !dac.permits(
+ Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), digestalg, null)) {
+ weakAlg |= 1;
+ }
+ if (tSADigestAlg != null && !dac.permits(
+ Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), tSADigestAlg, null)) {
+ weakAlg |= 4;
+ }
+ if (sigalg != null && !dac.permits(
+ Collections.singleton(CryptoPrimitive.SIGNATURE), sigalg, null)) {
+ weakAlg |= 2;
+ }
+
boolean aliasUsed = false;
X509Certificate tsaCert = null;
@@ -1255,8 +1295,8 @@
}
boolean warningAppeared = false;
- if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
- notYetValidCert || chainNotValidated || hasExpiredCert) {
+ if (weakAlg != 0 || badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
+ notYetValidCert || chainNotValidated || hasExpiredCert || signerSelfSigned) {
if (strict) {
System.out.println(rb.getString("jar.signed.with.signer.errors."));
System.out.println();
@@ -1292,8 +1332,31 @@
}
if (chainNotValidated) {
+ System.out.println(String.format(
+ rb.getString("The.signer.s.certificate.chain.is.not.validated.reason.1"),
+ chainNotValidatedReason.getLocalizedMessage()));
+ }
+
+ if (signerSelfSigned) {
System.out.println(
- rb.getString("The.signer.s.certificate.chain.is.not.validated."));
+ rb.getString("The.signer.s.certificate.is.self.signed."));
+ }
+
+ if ((weakAlg & 1) == 1) {
+ System.out.println(String.format(
+ rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
+ digestalg, "-digestalg"));
+ }
+
+ if ((weakAlg & 2) == 2) {
+ System.out.println(String.format(
+ rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
+ sigalg, "-sigalg"));
+ }
+ if ((weakAlg & 4) == 4) {
+ System.out.println(String.format(
+ rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
+ tSADigestAlg, "-tsadigestalg"));
}
} else {
System.out.println(rb.getString("jar.signed."));
@@ -1377,10 +1440,15 @@
// No more warning, we alreay have hasExpiredCert or notYetValidCert
} else {
chainNotValidated = true;
+ chainNotValidatedReason = e;
sb.append(tab).append(rb.getString(".CertPath.not.validated."))
.append(e.getLocalizedMessage()).append("]\n"); // TODO
}
}
+ if (certs.size() == 1
+ && KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
+ signerSelfSigned = true;
+ }
String result = sb.toString();
cacheForSignerInfo.put(signer, result);
return result;
@@ -1645,12 +1713,17 @@
if (e.getCause() != null &&
(e.getCause() instanceof CertificateExpiredException ||
e.getCause() instanceof CertificateNotYetValidException)) {
- // No more warning, we alreay have hasExpiredCert or notYetValidCert
+ // No more warning, we already have hasExpiredCert or notYetValidCert
} else {
chainNotValidated = true;
+ chainNotValidatedReason = e;
}
}
+ if (KeyStoreUtil.isSelfSigned(certChain[0])) {
+ signerSelfSigned = true;
+ }
+
try {
if (!token && keypass == null)
key = store.getKey(alias, storepass);