--- a/jdk/src/java.base/share/classes/module-info.java Tue Jan 17 11:34:47 2017 -0800
+++ b/jdk/src/java.base/share/classes/module-info.java Wed Jan 18 08:02:53 2017 +0800
@@ -290,6 +290,8 @@
jdk.crypto.token,
jdk.jartool,
jdk.security.auth;
+ exports sun.security.validator to
+ jdk.jartool;
exports sun.text.resources to
jdk.localedata;
exports sun.util.cldr to
--- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Tue Jan 17 11:34:47 2017 -0800
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Wed Jan 18 08:02:53 2017 +0800
@@ -26,6 +26,8 @@
package sun.security.tools.jarsigner;
import java.io.*;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.PKIXBuilderParameters;
import java.util.*;
import java.util.zip.*;
import java.util.jar.*;
@@ -40,11 +42,9 @@
import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.cert.CertPath;
-import java.security.cert.CertPathValidator;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.util.Map.Entry;
@@ -54,6 +54,8 @@
import sun.security.pkcs.SignerInfo;
import sun.security.timestamp.TimestampToken;
import sun.security.tools.KeyStoreUtil;
+import sun.security.validator.Validator;
+import sun.security.validator.ValidatorException;
import sun.security.x509.*;
import sun.security.util.*;
@@ -177,9 +179,7 @@
private boolean seeWeak = false;
- CertificateFactory certificateFactory;
- CertPathValidator validator;
- PKIXParameters pkixParameters;
+ PKIXBuilderParameters pkixParameters;
public void run(String args[]) {
try {
@@ -1623,19 +1623,10 @@
try {
validateCertChain(certs);
} catch (Exception e) {
- if (debug) {
- e.printStackTrace();
- }
- if (e.getCause() != null &&
- (e.getCause() instanceof CertificateExpiredException ||
- e.getCause() instanceof CertificateNotYetValidException)) {
- // 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
- }
+ 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))) {
@@ -1654,9 +1645,6 @@
}
try {
-
- certificateFactory = CertificateFactory.getInstance("X.509");
- validator = CertPathValidator.getInstance("PKIX");
Set<TrustAnchor> tas = new HashSet<>();
try {
KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
@@ -1732,7 +1720,7 @@
}
} finally {
try {
- pkixParameters = new PKIXParameters(tas);
+ pkixParameters = new PKIXBuilderParameters(tas, null);
pkixParameters.setRevocationEnabled(false);
} catch (InvalidAlgorithmParameterException ex) {
// Only if tas is empty
@@ -1899,17 +1887,8 @@
try {
validateCertChain(Arrays.asList(certChain));
} catch (Exception e) {
- if (debug) {
- e.printStackTrace();
- }
- if (e.getCause() != null &&
- (e.getCause() instanceof CertificateExpiredException ||
- e.getCause() instanceof CertificateNotYetValidException)) {
- // No more warning, we already have hasExpiredCert or notYetValidCert
- } else {
- chainNotValidated = true;
- chainNotValidatedReason = e;
- }
+ chainNotValidated = true;
+ chainNotValidatedReason = e;
}
if (KeyStoreUtil.isSelfSigned(certChain[0])) {
@@ -1966,18 +1945,40 @@
}
void validateCertChain(List<? extends Certificate> certs) throws Exception {
- int cpLen = 0;
- out: for (; cpLen<certs.size(); cpLen++) {
- for (TrustAnchor ta: pkixParameters.getTrustAnchors()) {
- if (ta.getTrustedCert().equals(certs.get(cpLen))) {
- break out;
+ try {
+ Validator.getInstance(Validator.TYPE_PKIX,
+ Validator.VAR_CODE_SIGNING,
+ pkixParameters)
+ .validate(certs.toArray(new X509Certificate[certs.size()]));
+ } catch (Exception e) {
+ if (debug) {
+ e.printStackTrace();
+ }
+ if (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 &&
+ hasExpiredCert) ||
+ (t instanceof CertificateNotYetValidException &&
+ notYetValidCert)) {
+ // we already have hasExpiredCert and notYetValidCert
+ return;
+ }
+ }
+ if (e instanceof ValidatorException) {
+ ValidatorException ve = (ValidatorException)e;
+ if (ve.getErrorType() == ValidatorException.T_EE_EXTENSIONS &&
+ (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType)) {
+ // We already have badKeyUsage, badExtendedKeyUsage
+ // and badNetscapeCertType
+ return;
+ }
}
}
- }
- if (cpLen > 0) {
- CertPath cp = certificateFactory.generateCertPath(
- (cpLen == certs.size())? certs: certs.subList(0, cpLen));
- validator.validate(cp, pkixParameters);
+ throw e;
}
}
--- a/jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh Tue Jan 17 11:34:47 2017 -0800
+++ b/jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh Wed Jan 18 08:02:53 2017 +0800
@@ -22,7 +22,7 @@
#
# @test
-# @bug 6802846
+# @bug 6802846 8172529
# @summary jarsigner needs enhanced cert validation(options)
#
# @run shell/timeout=240 concise_jarsigner.sh
@@ -52,7 +52,7 @@
KS=js.ks
KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS -keyalg rsa -keysize 1024"
JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}"
-JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}"
+JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -debug"
JAVAC="$TESTJAVA${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}"
rm $KS
@@ -138,7 +138,7 @@
[ $LINES = 4 ] || exit $LINENO
# ==========================================================
-# Second part: exit code 2, 4, 8
+# Second part: exit code 2, 4, 8.
# 16 and 32 already covered in the first part
# ==========================================================
@@ -174,11 +174,14 @@
$JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodeku
[ $? = 0 ] || exit $LINENO
-# badchain signed by ca, but ca is removed later
+# badchain signed by ca1, but ca1 is removed later
$KT -genkeypair -alias badchain -dname CN=badchain -validity 365
-$KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \
+$KT -genkeypair -alias ca1 -dname CN=ca1 -ext bc -validity 365
+$KT -certreq -alias badchain | $KT -gencert -alias ca1 -validity 365 | \
$KT -importcert -alias badchain
-$KT -delete -alias ca
+# save ca1.cert for easy replay
+$KT -exportcert -file ca1.cert -alias ca1
+$KT -delete -alias ca1
$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badchain
[ $? = 4 ] || exit $LINENO
@@ -204,13 +207,41 @@
$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
[ $? = 0 ] || exit $LINENO
-# but if ca2 is removed, -certchain does not work
+# if ca2 is removed, -certchain still work because altchain is a self-signed entry and
+# it is trusted by jarsigner
+# save ca2.cert for easy replay
+$KT -exportcert -file ca2.cert -alias ca2
$KT -delete -alias ca2
$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
+[ $? = 0 ] || exit $LINENO
+
+# if cert is imported, -certchain won't work because this certificate entry is not trusted
+$KT -importcert -file certchain -alias altchain -noprompt
+$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
[ $? = 4 ] || exit $LINENO
$JARSIGNER -verify a.jar
[ $? = 0 ] || exit $LINENO
+# ==========================================================
+# 8172529
+# ==========================================================
+
+$KT -genkeypair -alias ee -dname CN=ee
+$KT -genkeypair -alias caone -dname CN=caone
+$KT -genkeypair -alias catwo -dname CN=catwo
+
+$KT -certreq -alias ee | $KT -gencert -alias catwo -rfc > ee.cert
+$KT -certreq -alias catwo | $KT -gencert -alias caone -sigalg MD5withRSA -rfc > catwo.cert
+
+# This certchain contains a cross-signed weak catwo.cert
+cat ee.cert catwo.cert | $KT -importcert -alias ee
+
+$JAR cvf a.jar A1.class
+$JARSIGNER -strict -keystore $KS -storepass changeit a.jar ee
+[ $? = 0 ] || exit $LINENO
+$JARSIGNER -strict -keystore $KS -storepass changeit -verify a.jar
+[ $? = 0 ] || exit $LINENO
+
echo OK
exit 0