--- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Tue Feb 13 15:32:41 2018 -0800
+++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Wed Feb 14 16:58:49 2018 +0800
@@ -30,6 +30,7 @@
import java.security.cert.CertPathValidatorException;
import java.security.cert.PKIXBuilderParameters;
import java.util.*;
+import java.util.stream.Collectors;
import java.util.zip.*;
import java.util.jar.*;
import java.net.URI;
@@ -92,6 +93,7 @@
private static final String P11KEYSTORE = "PKCS11";
private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
+ private static final long ONE_YEAR = 366*24*60*60*1000L;
private static final DisabledAlgorithmConstraints DISABLED_CHECK =
new DisabledAlgorithmConstraints(
@@ -102,6 +104,13 @@
private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
+ static final String VERSION = "1.0";
+
+ static final int IN_KEYSTORE = 0x01; // signer is in keystore
+ static final int NOT_ALIAS = 0x04; // alias list is NOT empty and
+ // signer is not in alias list
+ static final int SIGNED_BY_ALIAS = 0x08; // signer is in alias list
+
// Attention:
// This is the entry that get launched by the security tool jarsigner.
public static void main(String args[]) throws Exception {
@@ -109,13 +118,6 @@
js.run(args);
}
- static final String VERSION = "1.0";
-
- static final int IN_KEYSTORE = 0x01; // signer is in keystore
- static final int NOT_ALIAS = 0x04; // alias list is NOT empty and
- // signer is not in alias list
- static final int SIGNED_BY_ALIAS = 0x08; // signer is in alias list
-
X509Certificate[] certChain; // signer's cert chain (when composing)
PrivateKey privateKey; // private key
KeyStore store; // the keystore specified by -keystore
@@ -160,8 +162,16 @@
// Informational warnings
private boolean hasExpiringCert = false;
- private boolean noTimestamp = false;
- private Date expireDate = new Date(0L); // used in noTimestamp warning
+ private boolean hasExpiringTsaCert = false;
+ private boolean noTimestamp = true;
+
+ // Expiration date. The value could be null if signed by a trusted cert.
+ private Date expireDate = null;
+ private Date tsaExpireDate = null;
+
+ // If there is a time stamp block inside the PKCS7 block file
+ boolean hasTimestampBlock = false;
+
// Severe warnings.
@@ -174,6 +184,7 @@
private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg
private boolean hasExpiredCert = false;
+ private boolean hasExpiredTsaCert = false;
private boolean notYetValidCert = false;
private boolean chainNotValidated = false;
private boolean tsaChainNotValidated = false;
@@ -191,6 +202,7 @@
private boolean seeWeak = false;
PKIXBuilderParameters pkixParameters;
+ Set<X509Certificate> trustedCerts = new HashSet<>();
public void run(String args[]) {
try {
@@ -277,8 +289,8 @@
if (strict) {
int exitCode = 0;
- if (weakAlg != 0 || chainNotValidated
- || hasExpiredCert || notYetValidCert || signerSelfSigned) {
+ if (weakAlg != 0 || chainNotValidated || hasExpiredCert
+ || hasExpiredTsaCert || notYetValidCert || signerSelfSigned) {
exitCode |= 4;
}
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
@@ -879,14 +891,12 @@
}
// If signer is a trusted cert or private entry in user's own
- // keystore, it can be self-signed.
- if (!aliasNotInStore) {
+ // keystore, it can be self-signed. Please note aliasNotInStore
+ // is always false when ~/.keystore is used.
+ if (!aliasNotInStore && keystore != null) {
signerSelfSigned = false;
}
- // If there is a time stamp block inside the PKCS7 block file
- boolean hasTimestampBlock = false;
-
// Even if the verbose option is not specified, all out strings
// must be generated so seeWeak can be updated.
if (!digestMap.isEmpty()
@@ -986,118 +996,7 @@
System.out.println(rb.getString("jar.is.unsigned"));
}
} else {
- boolean warningAppeared = false;
- boolean errorAppeared = false;
- if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
- notYetValidCert || chainNotValidated || hasExpiredCert ||
- hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) ||
- aliasNotInStore || notSignedByAlias || tsaChainNotValidated) {
-
- 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 (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. The signing
- // history (digestMap etc) will show these info and
- // print out proper warnings.
- }
-
- if (badKeyUsage) {
- System.out.println(
- rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
- }
-
- if (badExtendedKeyUsage) {
- System.out.println(
- rb.getString("This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
- }
-
- if (badNetscapeCertType) {
- System.out.println(
- rb.getString("This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
- }
-
- if (hasUnsignedEntry) {
- System.out.println(rb.getString(
- "This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
- }
- if (hasExpiredCert) {
- System.out.println(rb.getString(
- "This.jar.contains.entries.whose.signer.certificate.has.expired."));
- }
- if (notYetValidCert) {
- System.out.println(rb.getString(
- "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
- }
-
- if (chainNotValidated) {
- System.out.println(String.format(
- rb.getString("This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1"),
- chainNotValidatedReason.getLocalizedMessage()));
- }
-
- if (tsaChainNotValidated) {
- System.out.println(String.format(
- rb.getString("This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1"),
- tsaChainNotValidatedReason.getLocalizedMessage()));
- }
-
- if (notSignedByAlias) {
- System.out.println(
- rb.getString("This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es."));
- }
-
- 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."));
- }
- 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) {
- if (hasTimestampBlock) {
- // JarSigner API has not seen the timestamp,
- // might have ignored it due to weak alg, etc.
- System.out.println(
- String.format(rb.getString("bad.timestamp.verifying"), expireDate));
- } else {
- 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."));
- }
- }
+ displayMessagesAndResult(false);
}
return;
} catch (Exception e) {
@@ -1114,6 +1013,230 @@
System.exit(1);
}
+ private void displayMessagesAndResult(boolean isSigning) {
+ String result;
+ List<String> errors = new ArrayList<>();
+ List<String> warnings = new ArrayList<>();
+ List<String> info = new ArrayList<>();
+
+ boolean signerNotExpired = expireDate == null
+ || expireDate.after(new Date());
+
+ if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
+ notYetValidCert || chainNotValidated || hasExpiredCert ||
+ hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) ||
+ aliasNotInStore || notSignedByAlias ||
+ tsaChainNotValidated ||
+ (hasExpiredTsaCert && !signerNotExpired)) {
+
+ if (strict) {
+ result = rb.getString(isSigning
+ ? "jar.signed.with.signer.errors."
+ : "jar.verified.with.signer.errors.");
+ } else {
+ result = rb.getString(isSigning
+ ? "jar.signed."
+ : "jar.verified.");
+ }
+
+ if (badKeyUsage) {
+ errors.add(rb.getString(isSigning
+ ? "The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."
+ : "This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
+ }
+
+ if (badExtendedKeyUsage) {
+ errors.add(rb.getString(isSigning
+ ? "The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."
+ : "This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
+ }
+
+ if (badNetscapeCertType) {
+ errors.add(rb.getString(isSigning
+ ? "The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."
+ : "This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
+ }
+
+ // only in verifying
+ if (hasUnsignedEntry) {
+ errors.add(rb.getString(
+ "This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
+ }
+ if (hasExpiredCert) {
+ errors.add(rb.getString(isSigning
+ ? "The.signer.certificate.has.expired."
+ : "This.jar.contains.entries.whose.signer.certificate.has.expired."));
+ }
+ if (notYetValidCert) {
+ errors.add(rb.getString(isSigning
+ ? "The.signer.certificate.is.not.yet.valid."
+ : "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
+ }
+
+ if (chainNotValidated) {
+ errors.add(String.format(rb.getString(isSigning
+ ? "The.signer.s.certificate.chain.is.invalid.reason.1"
+ : "This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1"),
+ chainNotValidatedReason.getLocalizedMessage()));
+ }
+
+ if (hasExpiredTsaCert) {
+ errors.add(rb.getString("The.timestamp.has.expired."));
+ }
+ if (tsaChainNotValidated) {
+ errors.add(String.format(rb.getString(isSigning
+ ? "The.tsa.certificate.chain.is.invalid.reason.1"
+ : "This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1"),
+ tsaChainNotValidatedReason.getLocalizedMessage()));
+ }
+
+ // only in verifying
+ if (notSignedByAlias) {
+ errors.add(
+ rb.getString("This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es."));
+ }
+
+ // only in verifying
+ if (aliasNotInStore) {
+ errors.add(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
+ }
+
+ if (signerSelfSigned) {
+ errors.add(rb.getString(isSigning
+ ? "The.signer.s.certificate.is.self.signed."
+ : "This.jar.contains.entries.whose.signer.certificate.is.self.signed."));
+ }
+
+ // weakAlg only detected in signing. The jar file is
+ // now simply treated unsigned in verifying.
+ if ((weakAlg & 1) == 1) {
+ errors.add(String.format(
+ rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
+ digestalg, "-digestalg"));
+ }
+
+ if ((weakAlg & 2) == 2) {
+ errors.add(String.format(
+ rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
+ sigalg, "-sigalg"));
+ }
+ if ((weakAlg & 4) == 4) {
+ errors.add(String.format(
+ rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
+ tSADigestAlg, "-tsadigestalg"));
+ }
+ if ((weakAlg & 8) == 8) {
+ errors.add(String.format(
+ rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk."),
+ privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey)));
+ }
+ } else {
+ result = rb.getString(isSigning ? "jar.signed." : "jar.verified.");
+ }
+
+ if (hasExpiredTsaCert) {
+ // No need to warn about expiring if already expired
+ hasExpiringTsaCert = false;
+ }
+
+ if (hasExpiringCert ||
+ (hasExpiringTsaCert && expireDate != null) ||
+ (noTimestamp && expireDate != null) ||
+ (hasExpiredTsaCert && signerNotExpired)) {
+
+ if (hasExpiredTsaCert && signerNotExpired) {
+ if (expireDate != null) {
+ warnings.add(String.format(
+ rb.getString("The.timestamp.expired.1.but.usable.2"),
+ tsaExpireDate,
+ expireDate));
+ }
+ // Reset the flag so exit code is 0
+ hasExpiredTsaCert = false;
+ }
+ if (hasExpiringCert) {
+ warnings.add(rb.getString(isSigning
+ ? "The.signer.certificate.will.expire.within.six.months."
+ : "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
+ }
+ if (hasExpiringTsaCert && expireDate != null) {
+ if (expireDate.after(tsaExpireDate)) {
+ warnings.add(String.format(rb.getString(
+ "The.timestamp.will.expire.within.one.year.on.1.but.2"), tsaExpireDate, expireDate));
+ } else {
+ warnings.add(String.format(rb.getString(
+ "The.timestamp.will.expire.within.one.year.on.1"), tsaExpireDate));
+ }
+ }
+ if (noTimestamp && expireDate != null) {
+ if (hasTimestampBlock) {
+ warnings.add(String.format(rb.getString(isSigning
+ ? "invalid.timestamp.signing"
+ : "bad.timestamp.verifying"), expireDate));
+ } else {
+ warnings.add(String.format(rb.getString(isSigning
+ ? "no.timestamp.signing"
+ : "no.timestamp.verifying"), expireDate));
+ }
+ }
+ }
+
+ System.out.println(result);
+ if (strict) {
+ if (!errors.isEmpty()) {
+ System.out.println();
+ System.out.println(rb.getString("Error."));
+ errors.forEach(System.out::println);
+ }
+ if (!warnings.isEmpty()) {
+ System.out.println();
+ System.out.println(rb.getString("Warning."));
+ warnings.forEach(System.out::println);
+ }
+ } else {
+ if (!errors.isEmpty() || !warnings.isEmpty()) {
+ System.out.println();
+ System.out.println(rb.getString("Warning."));
+ errors.forEach(System.out::println);
+ warnings.forEach(System.out::println);
+ }
+ }
+ if (!isSigning && (!errors.isEmpty() || !warnings.isEmpty())) {
+ if (! (verbose != null && showcerts)) {
+ System.out.println();
+ System.out.println(rb.getString(
+ "Re.run.with.the.verbose.and.certs.options.for.more.details."));
+ }
+ }
+
+ if (isSigning || verbose != null) {
+ // Always print out expireDate, unless expired or expiring.
+ if (!hasExpiringCert && !hasExpiredCert
+ && expireDate != null && signerNotExpired) {
+ info.add(String.format(rb.getString(
+ "The.signer.certificate.will.expire.on.1."), expireDate));
+ }
+ if (!noTimestamp) {
+ if (!hasExpiringTsaCert && !hasExpiredTsaCert && tsaExpireDate != null) {
+ if (signerNotExpired) {
+ info.add(String.format(rb.getString(
+ "The.timestamp.will.expire.on.1."), tsaExpireDate));
+ } else {
+ info.add(String.format(rb.getString(
+ "signer.cert.expired.1.but.timestamp.good.2."),
+ expireDate,
+ tsaExpireDate));
+ }
+ }
+ }
+ }
+
+ if (!info.isEmpty()) {
+ System.out.println();
+ info.forEach(System.out::println);
+ }
+ }
+
private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
return alg;
@@ -1152,8 +1275,9 @@
*
* Note: no newline character at the end.
*
- * When isTsCert is true, this method sets global flags like hasExpiredCert,
- * notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType.
+ * This method sets global flags like hasExpiringCert, hasExpiredCert,
+ * notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType,
+ * hasExpiringTsaCert, hasExpiredTsaCert.
*
* @param isTsCert true if c is in the TSA cert chain, false otherwise.
* @param checkUsage true to check code signer keyUsage
@@ -1182,55 +1306,75 @@
if (x509Cert != null) {
certStr.append("\n").append(tab).append("[");
- Date notAfter = x509Cert.getNotAfter();
- try {
- boolean printValidity = true;
- if (timestamp == null) {
- if (expireDate.getTime() == 0 || expireDate.after(notAfter)) {
- expireDate = notAfter;
+
+ if (trustedCerts.contains(x509Cert)) {
+ certStr.append(rb.getString("trusted.certificate"));
+ } else {
+ Date notAfter = x509Cert.getNotAfter();
+ try {
+ boolean printValidity = true;
+ if (isTsCert) {
+ if (tsaExpireDate == null || tsaExpireDate.after(notAfter)) {
+ tsaExpireDate = notAfter;
+ }
+ } else {
+ if (expireDate == null || expireDate.after(notAfter)) {
+ expireDate = notAfter;
+ }
}
- x509Cert.checkValidity();
- // test if cert will expire within six months
- if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
- if (!isTsCert) hasExpiringCert = true;
- if (expiringTimeForm == null) {
- expiringTimeForm = new MessageFormat(
- rb.getString("certificate.will.expire.on"));
+ if (timestamp == null) {
+ x509Cert.checkValidity();
+ // test if cert will expire within six months (or one year for tsa)
+ long age = isTsCert ? ONE_YEAR : SIX_MONTHS;
+ if (notAfter.getTime() < System.currentTimeMillis() + age) {
+ if (isTsCert) {
+ hasExpiringTsaCert = true;
+ } else {
+ hasExpiringCert = true;
+ }
+ if (expiringTimeForm == null) {
+ expiringTimeForm = new MessageFormat(
+ rb.getString("certificate.will.expire.on"));
+ }
+ Object[] source = {notAfter};
+ certStr.append(expiringTimeForm.format(source));
+ printValidity = false;
+ }
+ } else {
+ x509Cert.checkValidity(timestamp);
+ }
+ if (printValidity) {
+ if (validityTimeForm == null) {
+ validityTimeForm = new MessageFormat(
+ rb.getString("certificate.is.valid.from"));
}
- Object[] source = { notAfter };
- certStr.append(expiringTimeForm.format(source));
- printValidity = false;
+ Object[] source = {x509Cert.getNotBefore(), notAfter};
+ certStr.append(validityTimeForm.format(source));
+ }
+ } catch (CertificateExpiredException cee) {
+ if (isTsCert) {
+ hasExpiredTsaCert = true;
+ } else {
+ hasExpiredCert = true;
}
- } else {
- x509Cert.checkValidity(timestamp);
+
+ if (expiredTimeForm == null) {
+ expiredTimeForm = new MessageFormat(
+ rb.getString("certificate.expired.on"));
+ }
+ Object[] source = {notAfter};
+ certStr.append(expiredTimeForm.format(source));
+
+ } catch (CertificateNotYetValidException cnyve) {
+ if (!isTsCert) notYetValidCert = true;
+
+ if (notYetTimeForm == null) {
+ notYetTimeForm = new MessageFormat(
+ rb.getString("certificate.is.not.valid.until"));
+ }
+ Object[] source = {x509Cert.getNotBefore()};
+ certStr.append(notYetTimeForm.format(source));
}
- if (printValidity) {
- if (validityTimeForm == null) {
- validityTimeForm = new MessageFormat(
- rb.getString("certificate.is.valid.from"));
- }
- Object[] source = { x509Cert.getNotBefore(), notAfter };
- certStr.append(validityTimeForm.format(source));
- }
- } catch (CertificateExpiredException cee) {
- if (!isTsCert) hasExpiredCert = true;
-
- if (expiredTimeForm == null) {
- expiredTimeForm = new MessageFormat(
- rb.getString("certificate.expired.on"));
- }
- Object[] source = { notAfter };
- certStr.append(expiredTimeForm.format(source));
-
- } catch (CertificateNotYetValidException cnyve) {
- if (!isTsCert) notYetValidCert = true;
-
- if (notYetTimeForm == null) {
- notYetTimeForm = new MessageFormat(
- rb.getString("certificate.is.not.valid.until"));
- }
- Object[] source = { x509Cert.getNotBefore() };
- certStr.append(notYetTimeForm.format(source));
}
certStr.append("]");
@@ -1446,8 +1590,6 @@
if (tSAPolicyID != null) {
builder.setProperty("tsaPolicyId", tSAPolicyID);
}
- } else {
- noTimestamp = true;
}
if (altSignerClass != null) {
@@ -1519,160 +1661,64 @@
error(failedMessage, failedCause);
}
+ if (verbose != null) {
+ System.out.println();
+ }
+
// The JarSigner API always accepts the timestamp received.
// We need to extract the certs from the signed jar to
// validate it.
- if (!noTimestamp) {
- try (JarFile check = new JarFile(signedJarFile)) {
- PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
- "META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
+ try (JarFile check = new JarFile(signedJarFile)) {
+ PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
+ "META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
+ Timestamp ts = null;
+ try {
SignerInfo si = p7.getSignerInfos()[0];
- PKCS7 tsToken = si.getTsToken();
- SignerInfo tsSi = tsToken.getSignerInfos()[0];
- try {
- validateCertChain(Validator.VAR_TSA_SERVER,
- tsSi.getCertificateChain(tsToken), null);
- } catch (Exception e) {
- tsaChainNotValidated = true;
- tsaChainNotValidatedReason = e;
+ if (si.getTsToken() != null) {
+ hasTimestampBlock = true;
}
+ ts = si.getTimestamp();
} catch (Exception e) {
- if (debug) {
- e.printStackTrace();
+ tsaChainNotValidated = true;
+ tsaChainNotValidatedReason = e;
+ }
+ // Spaces before the ">>> Signer" and other lines are different
+ String result = certsAndTSInfo("", " ", Arrays.asList(certChain), ts);
+ if (verbose != null) {
+ System.out.println(result);
+ }
+ } catch (Exception e) {
+ if (debug) {
+ e.printStackTrace();
+ }
+ }
+
+ if (signedjar == null) {
+ // attempt an atomic rename. If that fails,
+ // rename the original jar file, then the signed
+ // one, then delete the original.
+ if (!signedJarFile.renameTo(jarFile)) {
+ File origJar = new File(jarName+".orig");
+
+ if (jarFile.renameTo(origJar)) {
+ if (signedJarFile.renameTo(jarFile)) {
+ origJar.delete();
+ } else {
+ MessageFormat form = new MessageFormat(rb.getString
+ ("attempt.to.rename.signedJarFile.to.jarFile.failed"));
+ Object[] source = {signedJarFile, jarFile};
+ error(form.format(source));
+ }
+ } else {
+ MessageFormat form = new MessageFormat(rb.getString
+ ("attempt.to.rename.jarFile.to.origJar.failed"));
+ Object[] source = {jarFile, origJar};
+ error(form.format(source));
}
}
}
- // no IOException thrown in the follow try clause, so disable
- // the try clause.
- // try {
- if (signedjar == null) {
- // attempt an atomic rename. If that fails,
- // rename the original jar file, then the signed
- // one, then delete the original.
- if (!signedJarFile.renameTo(jarFile)) {
- File origJar = new File(jarName+".orig");
-
- if (jarFile.renameTo(origJar)) {
- if (signedJarFile.renameTo(jarFile)) {
- origJar.delete();
- } else {
- MessageFormat form = new MessageFormat(rb.getString
- ("attempt.to.rename.signedJarFile.to.jarFile.failed"));
- Object[] source = {signedJarFile, jarFile};
- error(form.format(source));
- }
- } else {
- MessageFormat form = new MessageFormat(rb.getString
- ("attempt.to.rename.jarFile.to.origJar.failed"));
- Object[] source = {jarFile, origJar};
- error(form.format(source));
- }
- }
- }
-
- boolean warningAppeared = false;
- if (weakAlg != 0 || badKeyUsage || badExtendedKeyUsage
- || badNetscapeCertType || notYetValidCert
- || chainNotValidated || tsaChainNotValidated
- || hasExpiredCert || signerSelfSigned) {
- 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;
- }
-
- if (badKeyUsage) {
- System.out.println(
- rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
- }
-
- if (badExtendedKeyUsage) {
- System.out.println(
- rb.getString("The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
- }
-
- if (badNetscapeCertType) {
- System.out.println(
- rb.getString("The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
- }
-
- if (hasExpiredCert) {
- System.out.println(
- rb.getString("The.signer.certificate.has.expired."));
- } else if (notYetValidCert) {
- System.out.println(
- rb.getString("The.signer.certificate.is.not.yet.valid."));
- }
-
- if (chainNotValidated) {
- System.out.println(String.format(
- rb.getString("The.signer.s.certificate.chain.is.invalid.reason.1"),
- chainNotValidatedReason.getLocalizedMessage()));
- }
-
- if (tsaChainNotValidated) {
- System.out.println(String.format(
- rb.getString("The.tsa.certificate.chain.is.invalid.reason.1"),
- tsaChainNotValidatedReason.getLocalizedMessage()));
- }
-
- if (signerSelfSigned) {
- System.out.println(
- 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"));
- }
- if ((weakAlg & 8) == 8) {
- System.out.println(String.format(
- rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk."),
- privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey)));
- }
- } 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
- // the catch clause.
- // } catch(IOException ioe) {
- // error(rb.getString("unable.to.sign.jar.")+ioe, ioe);
- // }
+ displayMessagesAndResult(true);
}
/**
@@ -1691,31 +1737,57 @@
Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
/**
- * Returns a string of singer info, with a newline at the end
+ * Returns a string of signer info, with a newline at the end.
+ * Called by verifyJar().
*/
private String signerInfo(CodeSigner signer, String tab) throws Exception {
if (cacheForSignerInfo.containsKey(signer)) {
return cacheForSignerInfo.get(signer);
}
- StringBuilder sb = new StringBuilder();
List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
- // display the signature timestamp, if present
- Date timestamp;
+ // signing time is only displayed on verification
Timestamp ts = signer.getTimestamp();
+ String tsLine = "";
if (ts != null) {
- sb.append(printTimestamp(tab, ts));
- sb.append('\n');
+ tsLine = printTimestamp(tab, ts) + "\n";
+ }
+ // Spaces before the ">>> Signer" and other lines are the same.
+
+ String result = certsAndTSInfo(tab, tab, certs, ts);
+ cacheForSignerInfo.put(signer, tsLine + result);
+ return result;
+ }
+
+ /**
+ * Fills info on certs and timestamp into a StringBuilder, sets
+ * warning flags (through printCert) and validates cert chains.
+ *
+ * @param tab1 spaces before the ">>> Signer" line
+ * @param tab2 spaces before the other lines
+ * @param certs the signer cert
+ * @param ts the timestamp, can be null
+ * @return the info as a string
+ */
+ private String certsAndTSInfo(
+ String tab1,
+ String tab2,
+ List<? extends Certificate> certs, Timestamp ts)
+ throws Exception {
+
+ Date timestamp;
+ if (ts != null) {
timestamp = ts.getTimestamp();
+ noTimestamp = false;
} else {
timestamp = null;
- noTimestamp = true;
}
// display the certificate(sb). The first one is end-entity cert and
// its KeyUsage should be checked.
boolean first = true;
- sb.append(tab).append(rb.getString("...Signer")).append('\n');
+ StringBuilder sb = new StringBuilder();
+ sb.append(tab1).append(rb.getString("...Signer")).append('\n');
for (Certificate c : certs) {
- sb.append(printCert(false, tab, c, timestamp, first));
+ sb.append(printCert(false, tab2, c, timestamp, first));
sb.append('\n');
first = false;
}
@@ -1724,13 +1796,13 @@
} catch (Exception e) {
chainNotValidated = true;
chainNotValidatedReason = e;
- sb.append(tab).append(rb.getString(".Invalid.certificate.chain."))
+ sb.append(tab2).append(rb.getString(".Invalid.certificate.chain."))
.append(e.getLocalizedMessage()).append("]\n");
}
if (ts != null) {
- sb.append(tab).append(rb.getString("...TSA")).append('\n');
+ sb.append(tab1).append(rb.getString("...TSA")).append('\n');
for (Certificate c : ts.getSignerCertPath().getCertificates()) {
- sb.append(printCert(true, tab, c, timestamp, false));
+ sb.append(printCert(true, tab2, c, null, false));
sb.append('\n');
}
try {
@@ -1739,7 +1811,7 @@
} catch (Exception e) {
tsaChainNotValidated = true;
tsaChainNotValidatedReason = e;
- sb.append(tab).append(rb.getString(".Invalid.TSA.certificate.chain."))
+ sb.append(tab2).append(rb.getString(".Invalid.TSA.certificate.chain."))
.append(e.getLocalizedMessage()).append("]\n");
}
}
@@ -1747,9 +1819,8 @@
&& KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
signerSelfSigned = true;
}
- String result = sb.toString();
- cacheForSignerInfo.put(signer, result);
- return result;
+
+ return sb.toString();
}
void loadKeyStore(String keyStoreName, boolean prompt) {
@@ -1760,7 +1831,6 @@
}
try {
- Set<TrustAnchor> tas = new HashSet<>();
try {
KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
if (caks != null) {
@@ -1768,7 +1838,7 @@
while (aliases.hasMoreElements()) {
String a = aliases.nextElement();
try {
- tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null));
+ trustedCerts.add((X509Certificate)caks.getCertificate(a));
} catch (Exception e2) {
// ignore, when a SecretkeyEntry does not include a cert
}
@@ -1827,7 +1897,7 @@
// PrivateKeyEntry
if (store.isCertificateEntry(a) ||
c.getSubjectDN().equals(c.getIssuerDN())) {
- tas.add(new TrustAnchor(c, null));
+ trustedCerts.add(c);
}
} catch (Exception e2) {
// ignore, when a SecretkeyEntry does not include a cert
@@ -1835,7 +1905,11 @@
}
} finally {
try {
- pkixParameters = new PKIXBuilderParameters(tas, null);
+ pkixParameters = new PKIXBuilderParameters(
+ trustedCerts.stream()
+ .map(c -> new TrustAnchor(c, null))
+ .collect(Collectors.toSet()),
+ null);
pkixParameters.setRevocationEnabled(false);
} catch (InvalidAlgorithmParameterException ex) {
// Only if tas is empty
@@ -1951,6 +2025,7 @@
}
}
+ // Called by signJar().
void getAliasInfo(String alias) throws Exception {
Key key = null;
@@ -1995,22 +2070,6 @@
certChain[i] = (X509Certificate)cs[i];
}
- // We don't meant to print anything, the next call
- // checks validity and keyUsage etc
- printCert(false, "", certChain[0], null, true);
-
- try {
- validateCertChain(Validator.VAR_CODE_SIGNING,
- Arrays.asList(certChain), null);
- } catch (Exception e) {
- chainNotValidated = true;
- chainNotValidatedReason = e;
- }
-
- if (KeyStoreUtil.isSelfSigned(certChain[0])) {
- signerSelfSigned = true;
- }
-
try {
if (!token && keypass == null)
key = store.getKey(alias, storepass);
@@ -2066,7 +2125,7 @@
* @param parameter this might be a timestamp
*/
void validateCertChain(String variant, List<? extends Certificate> certs,
- Object parameter)
+ Timestamp parameter)
throws Exception {
try {
Validator.getInstance(Validator.TYPE_PKIX,
@@ -2080,8 +2139,22 @@
}
// Exception might be dismissed if another warning flag
- // is already set by printCert. This is only done for
- // code signing certs.
+ // is already set by printCert.
+
+ if (variant.equals(Validator.VAR_TSA_SERVER) &&
+ e instanceof ValidatorException) {
+ // Throw cause if it's CertPathValidatorException,
+ if (e.getCause() != null &&
+ e.getCause() instanceof CertPathValidatorException) {
+ e = (Exception) e.getCause();
+ Throwable t = e.getCause();
+ if ((t instanceof CertificateExpiredException &&
+ hasExpiredTsaCert)) {
+ // we already have hasExpiredTsaCert
+ return;
+ }
+ }
+ }
if (variant.equals(Validator.VAR_CODE_SIGNING) &&
e instanceof ValidatorException) {
--- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java Tue Feb 13 15:32:41 2018 -0800
+++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java Wed Feb 14 16:58:49 2018 +0800
@@ -229,6 +229,7 @@
{"Error.", "Error: "},
{"...Signer", ">>> Signer"},
{"...TSA", ">>> TSA"},
+ {"trusted.certificate", "trusted certificate"},
{"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.",
@@ -245,8 +246,16 @@
"Re-run with the -verbose and -certs options for more details."},
{"The.signer.certificate.has.expired.",
"The signer certificate has expired."},
+ {"The.timestamp.expired.1.but.usable.2",
+ "The timestamp expired on %1$tY-%1$tm-%1$td. However, the JAR will be valid until the signer certificate expires on %2$tY-%2$tm-%2$td."},
+ {"The.timestamp.has.expired.",
+ "The timestamp has expired."},
{"The.signer.certificate.will.expire.within.six.months.",
"The signer certificate will expire within six months."},
+ {"The.timestamp.will.expire.within.one.year.on.1",
+ "The timestamp will expire within one year on %1$tY-%1$tm-%1$td."},
+ {"The.timestamp.will.expire.within.one.year.on.1.but.2",
+ "The timestamp will expire within one year on %1$tY-%1$tm-%1$td. However, the JAR will be valid until the signer certificate expires on %2$tY-%2$tm-%2$td."},
{"The.signer.certificate.is.not.yet.valid.",
"The signer certificate is not yet valid."},
{"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
@@ -279,10 +288,18 @@
"This jar contains entries whose TSA certificate chain is invalid. Reason: %s"},
{"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)."},
+ {"invalid.timestamp.signing",
+ "The timestamp is invalid. Without a valid timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td)."},
{"no.timestamp.verifying",
"This jar contains signatures that do not include a timestamp. Without a timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as %1$tY-%1$tm-%1$td)."},
{"bad.timestamp.verifying",
"This jar contains signatures that include an invalid timestamp. Without a valid timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as %1$tY-%1$tm-%1$td).\nRerun jarsigner with -J-Djava.security.debug=jar for more information."},
+ {"The.signer.certificate.will.expire.on.1.",
+ "The signer certificate will expire on %1$tY-%1$tm-%1$td."},
+ {"The.timestamp.will.expire.on.1.",
+ "The timestamp will expire on %1$tY-%1$tm-%1$td."},
+ {"signer.cert.expired.1.but.timestamp.good.2.",
+ "The signer certificate expired on %1$tY-%1$tm-%1$td. However, the JAR will be valid until the timestamp expires on %2$tY-%2$tm-%2$td."},
{"Unknown.password.type.", "Unknown password type: "},
{"Cannot.find.environment.variable.",
"Cannot find environment variable: "},
--- a/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. 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
@@ -79,6 +79,7 @@
* jdk.test.lib.JDKToolLauncher
* jdk.test.lib.Platform
* jdk.test.lib.process.*
+ * @compile -XDignore.symbol.file TimestampCheck.java
* @run main/timeout=600 TimestampCheck
*/
public class TimestampCheck {
@@ -126,12 +127,12 @@
byte[] sign(byte[] input, String path) throws Exception {
DerValue value = new DerValue(input);
- System.out.println("\nIncoming Request\n===================");
- System.out.println("Version: " + value.data.getInteger());
+ System.out.println("#\n# Incoming Request\n===================");
+ System.out.println("# Version: " + value.data.getInteger());
DerValue messageImprint = value.data.getDerValue();
AlgorithmId aid = AlgorithmId.parse(
messageImprint.data.getDerValue());
- System.out.println("AlgorithmId: " + aid);
+ System.out.println("# AlgorithmId: " + aid);
ObjectIdentifier policyId = new ObjectIdentifier(defaultPolicyId);
BigInteger nonce = null;
@@ -139,16 +140,16 @@
DerValue v = value.data.getDerValue();
if (v.tag == DerValue.tag_Integer) {
nonce = v.getBigInteger();
- System.out.println("nonce: " + nonce);
+ System.out.println("# nonce: " + nonce);
} else if (v.tag == DerValue.tag_Boolean) {
- System.out.println("certReq: " + v.getBoolean());
+ System.out.println("# certReq: " + v.getBoolean());
} else if (v.tag == DerValue.tag_ObjectId) {
policyId = v.getOID();
- System.out.println("PolicyID: " + policyId);
+ System.out.println("# PolicyID: " + policyId);
}
}
- System.out.println("\nResponse\n===================");
+ System.out.println("#\n# Response\n===================");
KeyStore ks = KeyStore.getInstance(
new File(keystore), "changeit".toCharArray());
@@ -232,10 +233,10 @@
"1.2.840.113549.1.9.16.1.4"),
new DerValue(tstInfo2.toByteArray()));
- System.out.println("Signing...");
- System.out.println(new X500Name(signer
+ System.out.println("# Signing...");
+ System.out.println("# " + new X500Name(signer
.getIssuerX500Principal().getName()));
- System.out.println(signer.getSerialNumber());
+ System.out.println("# " + signer.getSerialNumber());
SignerInfo signerInfo = new SignerInfo(
new X500Name(signer.getIssuerX500Principal().getName()),
@@ -306,8 +307,6 @@
public static void main(String[] args) throws Throwable {
- prepare();
-
try (Handler tsa = Handler.init(0, "ks");) {
tsa.start();
int port = tsa.getPort();
@@ -315,62 +314,99 @@
if (args.length == 0) { // Run this test
+ prepare();
+
sign("normal")
.shouldNotContain("Warning")
+ .shouldContain("The signer certificate will expire on")
+ .shouldContain("The timestamp will expire on")
.shouldHaveExitValue(0);
verify("normal.jar")
.shouldNotContain("Warning")
.shouldHaveExitValue(0);
+ verify("normal.jar", "-verbose")
+ .shouldNotContain("Warning")
+ .shouldContain("The signer certificate will expire on")
+ .shouldContain("The timestamp will expire on")
+ .shouldHaveExitValue(0);
+
// Simulate signing at a previous date:
// 1. tsold will create a timestamp of 20 days ago.
// 2. oldsigner expired 10 days ago.
- // jarsigner will show a warning at signing.
signVerbose("tsold", "unsigned.jar", "tsold.jar", "oldsigner")
- .shouldHaveExitValue(4);
+ .shouldNotContain("Warning")
+ .shouldMatch("signer certificate expired on .*. "
+ + "However, the JAR will be valid")
+ .shouldHaveExitValue(0);
// It verifies perfectly.
verify("tsold.jar", "-verbose", "-certs")
.shouldNotContain("Warning")
+ .shouldMatch("signer certificate expired on .*. "
+ + "However, the JAR will be valid")
.shouldHaveExitValue(0);
+ // No timestamp
signVerbose(null, "unsigned.jar", "none.jar", "signer")
.shouldContain("is not timestamped")
+ .shouldContain("The signer certificate will expire on")
.shouldHaveExitValue(0);
+ verify("none.jar", "-verbose")
+ .shouldContain("do not include a timestamp")
+ .shouldContain("The signer certificate will expire on")
+ .shouldHaveExitValue(0);
+
+ // Error cases
+
signVerbose(null, "unsigned.jar", "badku.jar", "badku")
+ .shouldContain("KeyUsage extension doesn't allow code signing")
.shouldHaveExitValue(8);
checkBadKU("badku.jar");
// 8180289: unvalidated TSA cert chain
sign("tsnoca")
- .shouldContain("TSA certificate chain is invalid")
+ .shouldContain("The TSA certificate chain is invalid. "
+ + "Reason: Path does not chain with any of the trust anchors")
.shouldHaveExitValue(64);
verify("tsnoca.jar", "-verbose", "-certs")
.shouldHaveExitValue(64)
.shouldContain("jar verified")
- .shouldContain("Invalid TSA certificate chain")
- .shouldContain("TSA certificate chain is invalid");
+ .shouldContain("Invalid TSA certificate chain: "
+ + "Path does not chain with any of the trust anchors")
+ .shouldContain("TSA certificate chain is invalid."
+ + " Reason: Path does not chain with any of the trust anchors");
sign("nononce")
+ .shouldContain("Nonce missing in timestamp token")
.shouldHaveExitValue(1);
sign("diffnonce")
+ .shouldContain("Nonce changed in timestamp token")
.shouldHaveExitValue(1);
sign("baddigest")
+ .shouldContain("Digest octets changed in timestamp token")
.shouldHaveExitValue(1);
sign("diffalg")
+ .shouldContain("Digest algorithm not")
.shouldHaveExitValue(1);
+
sign("fullchain")
.shouldHaveExitValue(0); // Success, 6543440 solved.
+
sign("tsbad1")
+ .shouldContain("Certificate is not valid for timestamping")
.shouldHaveExitValue(1);
sign("tsbad2")
+ .shouldContain("Certificate is not valid for timestamping")
.shouldHaveExitValue(1);
sign("tsbad3")
+ .shouldContain("Certificate is not valid for timestamping")
.shouldHaveExitValue(1);
sign("nocert")
+ .shouldContain("Certificate not included in timestamp token")
.shouldHaveExitValue(1);
sign("policy", "-tsapolicyid", "1.2.3")
@@ -378,6 +414,7 @@
checkTimestamp("policy.jar", "1.2.3", "SHA-256");
sign("diffpolicy", "-tsapolicyid", "1.2.3")
+ .shouldContain("TSAPolicyID changed in timestamp token")
.shouldHaveExitValue(1);
sign("sha1alg", "-tsadigestalg", "SHA")
@@ -387,6 +424,7 @@
sign("tsweak", "-digestalg", "MD5",
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
.shouldHaveExitValue(68)
+ .shouldContain("The timestamp is invalid. Without a valid timestamp")
.shouldMatch("MD5.*-digestalg.*risk")
.shouldMatch("MD5.*-tsadigestalg.*risk")
.shouldMatch("MD5withRSA.*-sigalg.*risk");
@@ -394,6 +432,7 @@
signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer")
.shouldHaveExitValue(64)
+ .shouldContain("The timestamp is invalid. Without a valid timestamp")
.shouldContain("TSA certificate chain is invalid");
// Weak timestamp is an error and jar treated unsigned
@@ -402,19 +441,26 @@
.shouldContain("treated as unsigned")
.shouldMatch("Timestamp.*512.*weak");
+ // Algorithm used in signing is weak
signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer",
"-digestalg", "MD5")
+ .shouldContain("-digestalg option is considered a security risk")
.shouldHaveExitValue(4);
checkHalfWeak("halfWeak.jar");
// sign with DSA key
signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey")
.shouldHaveExitValue(0);
+
// sign with RSAkeysize < 1024
signVerbose("normal", "sign1.jar", "sign2.jar", "weakkeysize")
+ .shouldContain("Algorithm constraints check failed on keysize")
.shouldHaveExitValue(4);
checkMultiple("sign2.jar");
+ // 8191438: jarsigner should print when a timestamp will expire
+ checkExpiration();
+
// When .SF or .RSA is missing or invalid
checkMissingOrInvalidFiles("normal.jar");
@@ -422,12 +468,118 @@
checkInvalidTsaCertKeyUsage();
}
} else { // Run as a standalone server
- System.out.println("Press Enter to quit server");
+ System.out.println("TSA started at " + host
+ + ". Press Enter to quit server");
System.in.read();
}
}
}
+ private static void checkExpiration() throws Exception {
+
+ // Warning when expired or expiring
+ signVerbose(null, "unsigned.jar", "expired.jar", "expired")
+ .shouldContain("signer certificate has expired")
+ .shouldHaveExitValue(4);
+ verify("expired.jar")
+ .shouldContain("signer certificate has expired")
+ .shouldHaveExitValue(4);
+ signVerbose(null, "unsigned.jar", "expiring.jar", "expiring")
+ .shouldContain("signer certificate will expire within")
+ .shouldHaveExitValue(0);
+ verify("expiring.jar")
+ .shouldContain("signer certificate will expire within")
+ .shouldHaveExitValue(0);
+ // Info for long
+ signVerbose(null, "unsigned.jar", "long.jar", "long")
+ .shouldNotContain("signer certificate has expired")
+ .shouldNotContain("signer certificate will expire within")
+ .shouldContain("signer certificate will expire on")
+ .shouldHaveExitValue(0);
+ verify("long.jar")
+ .shouldNotContain("signer certificate has expired")
+ .shouldNotContain("signer certificate will expire within")
+ .shouldNotContain("The signer certificate will expire")
+ .shouldHaveExitValue(0);
+ verify("long.jar", "-verbose")
+ .shouldContain("The signer certificate will expire")
+ .shouldHaveExitValue(0);
+
+ // Both expired
+ signVerbose("tsexpired", "unsigned.jar",
+ "tsexpired-expired.jar", "expired")
+ .shouldContain("The signer certificate has expired.")
+ .shouldContain("The timestamp has expired.")
+ .shouldHaveExitValue(4);
+ verify("tsexpired-expired.jar")
+ .shouldContain("signer certificate has expired")
+ .shouldContain("timestamp has expired.")
+ .shouldHaveExitValue(4);
+
+ // TS expired but signer still good
+ signVerbose("tsexpired", "unsigned.jar",
+ "tsexpired-long.jar", "long")
+ .shouldContain("The timestamp expired on")
+ .shouldHaveExitValue(0);
+ verify("tsexpired-long.jar")
+ .shouldMatch("timestamp expired on.*However, the JAR will be valid")
+ .shouldNotContain("Error")
+ .shouldHaveExitValue(0);
+
+ signVerbose("tsexpired", "unsigned.jar",
+ "tsexpired-ca.jar", "ca")
+ .shouldContain("The timestamp has expired.")
+ .shouldHaveExitValue(4);
+ verify("tsexpired-ca.jar")
+ .shouldNotContain("timestamp has expired")
+ .shouldNotContain("Error")
+ .shouldHaveExitValue(0);
+
+ // Warning when expiring
+ sign("tsexpiring")
+ .shouldContain("timestamp will expire within")
+ .shouldHaveExitValue(0);
+ verify("tsexpiring.jar")
+ .shouldContain("timestamp will expire within")
+ .shouldNotContain("still valid")
+ .shouldHaveExitValue(0);
+
+ signVerbose("tsexpiring", "unsigned.jar",
+ "tsexpiring-ca.jar", "ca")
+ .shouldContain("self-signed")
+ .stderrShouldNotMatch("The.*expir")
+ .shouldHaveExitValue(4); // self-signed
+ verify("tsexpiring-ca.jar")
+ .stderrShouldNotMatch("The.*expir")
+ .shouldHaveExitValue(0);
+
+ signVerbose("tsexpiringsoon", "unsigned.jar",
+ "tsexpiringsoon-long.jar", "long")
+ .shouldContain("The timestamp will expire")
+ .shouldHaveExitValue(0);
+ verify("tsexpiringsoon-long.jar")
+ .shouldMatch("timestamp will expire.*However, the JAR will be valid until")
+ .shouldHaveExitValue(0);
+
+ // Info for long
+ sign("tslong")
+ .shouldNotContain("timestamp has expired")
+ .shouldNotContain("timestamp will expire within")
+ .shouldContain("timestamp will expire on")
+ .shouldContain("signer certificate will expire on")
+ .shouldHaveExitValue(0);
+ verify("tslong.jar")
+ .shouldNotContain("timestamp has expired")
+ .shouldNotContain("timestamp will expire within")
+ .shouldNotContain("timestamp will expire on")
+ .shouldNotContain("signer certificate will expire on")
+ .shouldHaveExitValue(0);
+ verify("tslong.jar", "-verbose")
+ .shouldContain("timestamp will expire on")
+ .shouldContain("signer certificate will expire on")
+ .shouldHaveExitValue(0);
+ }
+
private static void checkInvalidTsaCertKeyUsage() throws Exception {
// Hack: Rewrite the TSA cert inside normal.jar into ts2.jar.
@@ -680,6 +832,14 @@
keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3");
keytool("-alias tsnoca -genkeypair -dname CN=tsnoca");
+ keytool("-alias expired -genkeypair -dname CN=expired");
+ keytool("-alias expiring -genkeypair -dname CN=expiring");
+ keytool("-alias long -genkeypair -dname CN=long");
+ keytool("-alias tsexpired -genkeypair -dname CN=tsexpired");
+ keytool("-alias tsexpiring -genkeypair -dname CN=tsexpiring");
+ keytool("-alias tsexpiringsoon -genkeypair -dname CN=tsexpiringsoon");
+ keytool("-alias tslong -genkeypair -dname CN=tslong");
+
// tsnoca's issuer will be removed from keystore later
keytool("-alias ca -genkeypair -ext bc -dname CN=CA");
gencert("tsnoca", "-ext eku:critical=ts");
@@ -691,7 +851,15 @@
gencert("dsakey");
gencert("weakkeysize");
gencert("badku", "-ext ku:critical=keyAgreement");
- gencert("ts", "-ext eku:critical=ts");
+ gencert("ts", "-ext eku:critical=ts -validity 500");
+
+ gencert("expired", "-validity 10 -startdate -12d");
+ gencert("expiring", "-validity 178");
+ gencert("long", "-validity 182");
+ gencert("tsexpired", "-ext eku:critical=ts -validity 10 -startdate -12d");
+ gencert("tsexpiring", "-ext eku:critical=ts -validity 364");
+ gencert("tsexpiringsoon", "-ext eku:critical=ts -validity 170"); // earlier than expiring
+ gencert("tslong", "-ext eku:critical=ts -validity 367");
for (int i = 0; i < 5; i++) {
@@ -711,7 +879,7 @@
}
}
- gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 45");
+ gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 500");
gencert("tsweak", "-ext eku:critical=ts");
gencert("tsbad1");
--- a/test/jdk/sun/security/tools/jarsigner/warnings/AliasNotInStoreTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/AliasNotInStoreTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -51,32 +51,12 @@
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
// create first key pair for signing
- keytool(
- "-genkey",
- "-alias", FIRST_KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", BOTH_KEYS_KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=First",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
-
- // create second key pair for signing
- keytool(
- "-genkey",
- "-alias", SECOND_KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", BOTH_KEYS_KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Second",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+ createAlias(FIRST_KEY_ALIAS);
+ createAlias(SECOND_KEY_ALIAS);
// sign jar with first key
OutputAnalyzer analyzer = jarsigner(
- "-keystore", BOTH_KEYS_KEYSTORE,
+ "-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
"-signedjar", SIGNED_JARFILE,
@@ -93,7 +73,7 @@
// sign jar with second key
analyzer = jarsigner(
- "-keystore", BOTH_KEYS_KEYSTORE,
+ "-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
UPDATED_SIGNED_JARFILE,
@@ -104,7 +84,7 @@
// create keystore that contains only first key
keytool(
"-importkeystore",
- "-srckeystore", BOTH_KEYS_KEYSTORE,
+ "-srckeystore", KEYSTORE,
"-srcalias", FIRST_KEY_ALIAS,
"-srcstorepass", PASSWORD,
"-srckeypass", PASSWORD,
@@ -113,7 +93,7 @@
"-deststorepass", PASSWORD,
"-destkeypass", PASSWORD).shouldHaveExitValue(0);
- // verify jar with keystore that contains only first key in strict mode,
+ // verify jar with keystore that contains only first key,
// so there is signed entry (FirstClass.class) that is not signed
// by any alias in the keystore
analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -52,17 +52,14 @@
// create a certificate whose signer certificate's
// ExtendedKeyUsage extension doesn't allow code signing
- keytool(
- "-genkey",
- "-alias", KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Test",
+ // create key pair for jar signing
+ createAlias(CA_KEY_ALIAS);
+ createAlias(KEY_ALIAS);
+
+ issueCert(
+ KEY_ALIAS,
"-ext", "ExtendedkeyUsage=serverAuth",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+ "-validity", Integer.toString(VALIDITY));
// sign jar
OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -53,17 +53,13 @@
// create a certificate whose signer certificate's KeyUsage extension
// doesn't allow code signing
- keytool(
- "-genkey",
- "-alias", KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Test",
+ createAlias(CA_KEY_ALIAS);
+ createAlias(KEY_ALIAS);
+
+ issueCert(
+ KEY_ALIAS,
"-ext", "KeyUsage=keyAgreement",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+ "-validity", Integer.toString(VALIDITY));
// sign jar
OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -24,10 +24,6 @@
import jdk.testlibrary.OutputAnalyzer;
import jdk.test.lib.util.JarUtils;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.Base64;
-
/**
* @test
* @bug 8024302 8026037
@@ -38,25 +34,14 @@
*/
public class BadNetscapeCertTypeTest extends Test {
- private static final String NETSCAPE_KEYSTORE_BASE64 = TEST_SOURCES + FS
- + "bad_netscape_cert_type.jks.base64";
-
- private static final String NETSCAPE_KEYSTORE
- = "bad_netscape_cert_type.jks";
-
/**
* The test signs and verifies a jar that contains entries
* whose signer certificate's NetscapeCertType extension
* doesn't allow code signing (badNetscapeCertType).
* Warning message is expected.
- * Run bad_netscape_cert_type.sh script to create bad_netscape_cert_type.jks
*/
public static void main(String[] args) throws Throwable {
- Files.write(Paths.get(NETSCAPE_KEYSTORE),
- Base64.getMimeDecoder().decode(
- Files.readAllBytes(Paths.get(NETSCAPE_KEYSTORE_BASE64))));
-
BadNetscapeCertTypeTest test = new BadNetscapeCertTypeTest();
test.start();
}
@@ -66,10 +51,22 @@
Utils.createFiles(FIRST_FILE);
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+ // create a certificate whose signer certificate's
+ // NetscapeCertType extension doesn't allow code signing
+ // create key pair for jar signing
+ createAlias(CA_KEY_ALIAS);
+ createAlias(KEY_ALIAS);
+
+ issueCert(
+ KEY_ALIAS,
+ // NetscapeCertType [ SSL client ]
+ "-ext", "2.16.840.1.113730.1.1=03020780",
+ "-validity", Integer.toString(VALIDITY));
+
// sign jar
OutputAnalyzer analyzer = jarsigner(
"-verbose",
- "-keystore", NETSCAPE_KEYSTORE,
+ "-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
"-signedjar", SIGNED_JARFILE,
@@ -82,7 +79,7 @@
analyzer = jarsigner(
"-verify",
"-verbose",
- "-keystore", NETSCAPE_KEYSTORE,
+ "-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
SIGNED_JARFILE);
@@ -94,7 +91,7 @@
"-verify",
"-verbose",
"-strict",
- "-keystore", NETSCAPE_KEYSTORE,
+ "-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
SIGNED_JARFILE);
--- a/test/jdk/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -21,118 +21,52 @@
* questions.
*/
-import java.io.File;
import jdk.testlibrary.OutputAnalyzer;
-import jdk.testlibrary.ProcessTools;
import jdk.test.lib.util.JarUtils;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
/**
* @test
* @bug 8024302 8026037
* @summary Test for chainNotValidated warning
* @library /lib/testlibrary /test/lib ../
* @build jdk.test.lib.util.JarUtils
- * @run main ChainNotValidatedTest
+ * @run main ChainNotValidatedTest ca2yes
+ * @run main ChainNotValidatedTest ca2no
*/
public class ChainNotValidatedTest extends Test {
- private static final String CHAIN = "chain";
-
- /**
- * The test signs and verifies a jar that contains entries
- * whose cert chain can't be correctly validated (chainNotValidated).
- * Warning message is expected.
- */
public static void main(String[] args) throws Throwable {
ChainNotValidatedTest test = new ChainNotValidatedTest();
- test.start();
+ test.start(args[0].equals("ca2yes"));
}
- private void start() throws Throwable {
+ private void start(boolean ca2yes) throws Throwable {
// create a jar file that contains one class file
Utils.createFiles(FIRST_FILE);
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
- // create self-signed certificate whose BasicConstraints extension
- // is set to false, so the certificate may not be used
- // as a parent certificate (certpath validation should fail)
- keytool(
- "-genkeypair",
- "-alias", CA_KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=CA",
- "-ext", "BasicConstraints:critical=ca:false",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
-
- // create a certificate that is signed by self-signed certificate
- // despite of it may not be used as a parent certificate
- // (certpath validation should fail)
- keytool(
- "-genkeypair",
- "-alias", KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Test",
- "-ext", "BasicConstraints:critical=ca:false",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
-
- keytool(
- "-certreq",
- "-alias", KEY_ALIAS,
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-file", CERT_REQUEST_FILENAME).shouldHaveExitValue(0);
+ // We have 2 @run. Need cleanup.
+ Files.deleteIfExists(Paths.get(KEYSTORE));
- keytool(
- "-gencert",
- "-alias", CA_KEY_ALIAS,
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-infile", CERT_REQUEST_FILENAME,
- "-validity", Integer.toString(VALIDITY),
- "-outfile", CERT_FILENAME).shouldHaveExitValue(0);
-
- keytool(
- "-importcert",
- "-alias", KEY_ALIAS,
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-file", CERT_FILENAME).shouldHaveExitValue(0);
+ // Root CA is not checked at all. If the intermediate CA has
+ // BasicConstraints extension set to true, it will be valid.
+ // Otherwise, chain validation will fail.
+ createAlias(CA_KEY_ALIAS);
+ createAlias(CA2_KEY_ALIAS);
+ issueCert(CA2_KEY_ALIAS,
+ "-ext",
+ "bc=ca:" + ca2yes);
- ProcessBuilder pb = new ProcessBuilder(KEYTOOL,
- "-export",
- "-rfc",
- "-alias", KEY_ALIAS,
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD);
- pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
- ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
+ createAlias(KEY_ALIAS);
+ issueCert(KEY_ALIAS, "-alias", CA2_KEY_ALIAS);
- pb = new ProcessBuilder(KEYTOOL,
- "-export",
- "-rfc",
- "-alias", CA_KEY_ALIAS,
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD);
- pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
- ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
-
- // remove CA certificate
+ // remove CA2 certificate so it's not trusted
keytool(
"-delete",
- "-alias", CA_KEY_ALIAS,
+ "-alias", CA2_KEY_ALIAS,
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD).shouldHaveExitValue(0);
@@ -142,12 +76,15 @@
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
- "-certchain", CHAIN,
"-signedjar", SIGNED_JARFILE,
UNSIGNED_JARFILE,
KEY_ALIAS);
- checkSigning(analyzer, CHAIN_NOT_VALIDATED_SIGNING_WARNING);
+ if (ca2yes) {
+ checkSigning(analyzer, "!" + CHAIN_NOT_VALIDATED_SIGNING_WARNING);
+ } else {
+ checkSigning(analyzer, CHAIN_NOT_VALIDATED_SIGNING_WARNING);
+ }
// verify signed jar
analyzer = jarsigner(
@@ -156,10 +93,13 @@
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
- "-certchain", CHAIN,
SIGNED_JARFILE);
- checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+ if (ca2yes) {
+ checkVerifying(analyzer, 0, "!" + CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+ } else {
+ checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+ }
// verify signed jar in strict mode
analyzer = jarsigner(
@@ -169,11 +109,15 @@
"-keystore", KEYSTORE,
"-storepass", PASSWORD,
"-keypass", PASSWORD,
- "-certchain", CHAIN,
SIGNED_JARFILE);
- checkVerifying(analyzer, CHAIN_NOT_VALIDATED_EXIT_CODE,
- CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+ if (ca2yes) {
+ checkVerifying(analyzer, 0,
+ "!" + CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+ } else {
+ checkVerifying(analyzer, CHAIN_NOT_VALIDATED_EXIT_CODE,
+ CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+ }
System.out.println("Test passed");
}
--- a/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiredCertTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiredCertTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -52,18 +52,13 @@
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
// create key pair for jar signing
- keytool(
- "-genkey",
- "-alias", KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Test",
+ createAlias(CA_KEY_ALIAS);
+ createAlias(KEY_ALIAS);
+
+ issueCert(
+ KEY_ALIAS,
"-startdate", "-" + SHORT_VALIDITY * 2 + "d",
- "-validity", Integer.toString(SHORT_VALIDITY))
- .shouldHaveExitValue(0);
+ "-validity", Integer.toString(SHORT_VALIDITY));
// sign jar
OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -52,17 +52,12 @@
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
// create key pair for jar signing
- keytool(
- "-genkey",
- "-alias", KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Test",
- "-validity", Integer.toString(SHORT_VALIDITY))
- .shouldHaveExitValue(0);
+ createAlias(CA_KEY_ALIAS);
+ createAlias(KEY_ALIAS);
+
+ issueCert(
+ KEY_ALIAS,
+ "-validity", Integer.toString(SHORT_VALIDITY));
// sign jar
OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -51,16 +51,11 @@
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
// create key pair for signing
- keytool(
- "-genkey",
- "-alias", KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Test",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+ createAlias(CA_KEY_ALIAS);
+ createAlias(KEY_ALIAS);
+ issueCert(
+ KEY_ALIAS,
+ "-validity", Integer.toString(VALIDITY));
// sign jar
OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/MultipleWarningsTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/MultipleWarningsTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -54,35 +54,25 @@
// create a jar file that contains one class file
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+ createAlias(CA_KEY_ALIAS);
+
// create first expired certificate
// whose ExtendedKeyUsage extension does not allow code signing
- keytool(
- "-genkey",
- "-alias", FIRST_KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=First",
+ createAlias(FIRST_KEY_ALIAS);
+ issueCert(
+ FIRST_KEY_ALIAS,
"-ext", "ExtendedkeyUsage=serverAuth",
"-startdate", "-" + VALIDITY * 2 + "d",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+ "-validity", Integer.toString(VALIDITY));
// create second expired certificate
// whose KeyUsage extension does not allow code signing
- keytool(
- "-genkey",
- "-alias", SECOND_KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Second",
+ createAlias(SECOND_KEY_ALIAS);
+ issueCert(
+ SECOND_KEY_ALIAS,
"-ext", "ExtendedkeyUsage=serverAuth",
"-startdate", "-" + VALIDITY * 2 + "d",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+ "-validity", Integer.toString(VALIDITY));
// sign jar with first key
OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -57,15 +57,9 @@
* 24 * 60 * 60 * 1000L);
// create key pair
- keytool(
- "-genkey",
- "-alias", KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Test",
+ createAlias(CA_KEY_ALIAS);
+ createAlias(KEY_ALIAS);
+ issueCert(KEY_ALIAS,
"-validity", Integer.toString(VALIDITY));
// sign jar file
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -49,29 +49,19 @@
Utils.createFiles(FIRST_FILE);
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
- // create first key pair for signing
- keytool(
- "-genkey",
- "-alias", FIRST_KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=First",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+ createAlias(CA_KEY_ALIAS);
// create first key pair for signing
- keytool(
- "-genkey",
- "-alias", SECOND_KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Second",
- "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+ createAlias(FIRST_KEY_ALIAS);
+ issueCert(
+ FIRST_KEY_ALIAS,
+ "-validity", Integer.toString(VALIDITY));
+
+ // create first key pair for signing
+ createAlias(SECOND_KEY_ALIAS);
+ issueCert(
+ SECOND_KEY_ALIAS,
+ "-validity", Integer.toString(VALIDITY));
// sign jar with first key
OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NotYetValidCertTest.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NotYetValidCertTest.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -50,15 +50,11 @@
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
// create certificate that will be valid only tomorrow
- keytool(
- "-genkey",
- "-alias", KEY_ALIAS,
- "-keyalg", KEY_ALG,
- "-keysize", Integer.toString(KEY_SIZE),
- "-keystore", KEYSTORE,
- "-storepass", PASSWORD,
- "-keypass", PASSWORD,
- "-dname", "CN=Test",
+ createAlias(CA_KEY_ALIAS);
+ createAlias(KEY_ALIAS);
+
+ issueCert(
+ KEY_ALIAS,
"-startdate", "+1d",
"-validity", Integer.toString(VALIDITY));
--- a/test/jdk/sun/security/tools/jarsigner/warnings/Test.java Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/Test.java Wed Feb 14 16:58:49 2018 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@@ -45,7 +45,6 @@
static final String FIRST_FILE = "first.txt";
static final String SECOND_FILE = "second.txt";
static final String PASSWORD = "password";
- static final String BOTH_KEYS_KEYSTORE = "both_keys.jks";
static final String FIRST_KEY_KEYSTORE = "first_key.jks";
static final String KEYSTORE = "keystore.jks";
static final String FIRST_KEY_ALIAS = "first";
@@ -55,11 +54,13 @@
static final String CERT_REQUEST_FILENAME = "test.req";
static final String CERT_FILENAME = "test.crt";
static final String CA_KEY_ALIAS = "ca";
+ static final String CA2_KEY_ALIAS = "ca2";
static final int KEY_SIZE = 2048;
static final int TIMEOUT = 6 * 60 * 1000; // in millis
static final int VALIDITY = 365;
static final String WARNING = "Warning:";
+ static final String WARNING_OR_ERROR = "(Warning|Error):";
static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING
= "This jar contains entries "
@@ -154,14 +155,72 @@
static final int ALIAS_NOT_IN_STORE_EXIT_CODE = 32;
static final int NOT_SIGNED_BY_ALIAS_EXIT_CODE = 32;
+ protected void createAlias(String alias, String ... options)
+ throws Throwable {
+ List<String> cmd = new ArrayList<>();
+ cmd.addAll(List.of(
+ "-genkeypair",
+ "-alias", alias,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=" + alias));
+ cmd.addAll(Arrays.asList(options));
+
+ keytool(cmd.toArray(new String[cmd.size()]))
+ .shouldHaveExitValue(0);
+ }
+
+ protected void issueCert(String alias, String ... options)
+ throws Throwable {
+ keytool("-certreq",
+ "-alias", alias,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-file", alias + ".req")
+ .shouldHaveExitValue(0);
+
+ List<String> cmd = new ArrayList<>();
+ cmd.addAll(List.of(
+ "-gencert",
+ "-alias", CA_KEY_ALIAS,
+ "-infile", alias + ".req",
+ "-outfile", alias + ".cert",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-file", alias + ".req"));
+ cmd.addAll(Arrays.asList(options));
+
+ keytool(cmd.toArray(new String[cmd.size()]))
+ .shouldHaveExitValue(0);
+
+ keytool("-importcert",
+ "-alias", alias,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-file", alias + ".cert")
+ .shouldHaveExitValue(0);
+ }
+
protected void checkVerifying(OutputAnalyzer analyzer, int expectedExitCode,
String... warnings) {
analyzer.shouldHaveExitValue(expectedExitCode);
+ int count = 0;
for (String warning : warnings) {
- analyzer.shouldContain(warning);
+ if (warning.startsWith("!")) {
+ analyzer.shouldNotContain(warning.substring(1));
+ } else {
+ count++;
+ analyzer.shouldContain(warning);
+ }
}
- if (warnings.length > 0) {
- analyzer.shouldContain(WARNING);
+ if (count > 0) {
+ analyzer.shouldMatch(WARNING_OR_ERROR);
}
if (expectedExitCode == 0) {
analyzer.shouldContain(JAR_VERIFIED);
@@ -172,11 +231,17 @@
protected void checkSigning(OutputAnalyzer analyzer, String... warnings) {
analyzer.shouldHaveExitValue(0);
+ int count = 0;
for (String warning : warnings) {
- analyzer.shouldContain(warning);
+ if (warning.startsWith("!")) {
+ analyzer.shouldNotContain(warning.substring(1));
+ } else {
+ count++;
+ analyzer.shouldContain(warning);
+ }
}
- if (warnings.length > 0) {
- analyzer.shouldContain(WARNING);
+ if (count > 0) {
+ analyzer.shouldMatch(WARNING_OR_ERROR);
}
analyzer.shouldContain(JAR_SIGNED);
}
--- a/test/jdk/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.jks.base64 Tue Feb 13 15:32:41 2018 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/u3+7QAAAAIAAAABAAAAAQAFYWxpYXMAAAFBpkwW0gAAAr0wggK5MA4GCisGAQQB
-KgIRAQEFAASCAqWkGJ3PPjYmWNKrV23Y1u413RMAkrRZ+1OLWYRcQt4jtxtIyEH5
-Ho5b9dy9XN9FBKlTOD4c2Pc1T43BLKXeuLu3uLLeIxgXFt0z9CLyGwdYZZ751kXr
-DQ99qY6aNQUO6SeE4Wdty0KPAqid6ZJ8bF7T6wsTZSvNhaBRzyFydEfG7bbUYjOl
-mWC44nlsu6VEU3o9RQpcm1gIMwradOaIVT/HoB2bKmAv8gHqI6kreiEZwTdZkSAI
-IRi2vt1RPllXt5hgjDxUfZe8XOYYweR4Vt2/jVuKLJ80DNTu/9SeUD88zQAz53k4
-r3nRhv6TRcPm6tV/Fh92XLHiskL+TAzTfm+bUAudPCCVxN+yRtxvAgA+UhdV/SuM
-Zn5F6nrmP+YJG1hmprgCJIJJaCEXa9RXYC+vIVpO0WVNRuGlGm+/1afnOuQC8Wss
-ShXwjkaqTwAhqBFq7eYmmP8BK3gflYrt2zDLXvhl4ndVvMhMthFJ3ZvLh2LWpqLI
-/n8EMCf8US3lIEFk9DTHBZjffiHkqK2e7+FXEpG3xrgE6ZYLMdbd5Pb3YjZfhQx+
-ZTtiEFzYSaEGhacek/m7dRq1qmwgFsytng2OdWZe2ln8LJY0odr1dGUfJHfgafvi
-tlfbkg/rgjONtwliChDggbkUwnerrj/D/zrdEufUvfyltSshhHXRNDD3fH6spmEk
-hHKgxEc4yvxqJxzdMGtuib355aSfNegyl+GsnsKzXQCVEK2h3BLTQObzaD+8NZ12
-LQHvbrCiaS34vxJ3rEC+a+SW7itZp0aCdXMWdMJNkRKqyLBD3vG3zN05sN3XrhEM
-8BRT020TWY00tbVFbbBFheYLQRgTjrQtr0Yt6UHWBZc4N20crDLcSH5gqcCOVpla
-1Y2uqFEn8yqrGRwn/kgfNgAAAAEABVguNTA5AAABtTCCAbEwggEaoAMCAQICCQDH
-cEuVvzCuqzANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDDARUZXN0MB4XDTEzMTAx
-MTA2NTUwNloXDTIzMTAwOTA2NTUwNlowDzENMAsGA1UEAwwEVGVzdDCBnzANBgkq
-hkiG9w0BAQEFAAOBjQAwgYkCgYEA8hOfp2Dcnvt//ZZQAja9TRiwKqXVS+TiYE3S
-gngCBjIi+YYdo0DsUeO5MBfE6uvCWOr5lwAR/u1iaJOhIoGJDiGoPasZlt+yIgtR
-LzA7j2q+1q6kcwiVxfikI3aUgHV/QsybTriT4Bf7TQNKtJG23MQa4sD7+PjtCWD7
-p3cHTfkCAwEAAaMVMBMwEQYJYIZIAYb4QgEBBAQDAgeAMA0GCSqGSIb3DQEBBQUA
-A4GBAKoDlTJ8wLRA7G8XdGm4gv733n1cSQzlkcsjfOO6/mA5Jvu8tyFNq9HTf9AT
-VXbrbGcUYJjhzSSY3w5apXK1kXyqTB1LUNEJ45WnmciqSSecVTpJz9TuegyoX0Zf
-HScSgqfDmjqoiiFiNCgn3ZEJ85ykGvoFYGH+php+BVi3S0bj5E/jRpyV3vNnii/S
-wJDSAXF6bYU=
--- a/test/jdk/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.sh Tue Feb 13 15:32:41 2018 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 2013, 2015, Oracle and/or its affiliates. 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-#!/bin/sh
-
-# This script creates JKS keystore with a certificate
-# that contains Netscape Certificate Type extension
-# that does not allow code signing
-# The keystore is used by BadNetscapeCertTypeTest.java test
-
-rm -rf keystore.jks
-echo "nsCertType = client" > ext.cfg
-
-openssl req -new -out cert.req -keyout key.pem -days 3650 \
- -passin pass:password -passout pass:password -subj "/CN=Test"
-openssl x509 -in cert.req -out cert.pem -req -signkey key.pem -days 3650 \
- -passin pass:password -extfile ext.cfg
-openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 \
- -passin pass:password -passout pass:password -name alias
-
-${JAVA_HOME}/bin/keytool -importkeystore \
- -srckeystore keystore.p12 -srcstoretype pkcs12 \
- -srcstorepass password -alias alias \
- -destkeystore bad_netscape_cert_type.jks -deststoretype jks \
- -deststorepass password -destalias alias \
-
-openssl base64 < bad_netscape_cert_type.jks > bad_netscape_cert_type.jks.base64
-rm -rf cert.req key.pem cert.pem keystore.p12 ext.cfg bad_netscape_cert_type.jks