提交 53c39c77 编写于 作者: I igerasim

8172529: Use PKIXValidator in jarsigner

Reviewed-by: xuelei, mullan, alanb
上级 b19fcdd3
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
package sun.security.tools.jarsigner; package sun.security.tools.jarsigner;
import java.io.*; import java.io.*;
import java.security.cert.CertPathValidatorException;
import java.security.cert.PKIXBuilderParameters;
import java.util.*; import java.util.*;
import java.util.zip.*; import java.util.zip.*;
import java.util.jar.*; import java.util.jar.*;
...@@ -46,11 +48,9 @@ import java.net.SocketTimeoutException; ...@@ -46,11 +48,9 @@ import java.net.SocketTimeoutException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.security.cert.CertPath; import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor; import java.security.cert.TrustAnchor;
import java.util.Map.Entry; import java.util.Map.Entry;
import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS7;
...@@ -58,6 +58,8 @@ import sun.security.pkcs.SignerInfo; ...@@ -58,6 +58,8 @@ import sun.security.pkcs.SignerInfo;
import sun.security.timestamp.TimestampToken; import sun.security.timestamp.TimestampToken;
import sun.security.tools.KeyStoreUtil; import sun.security.tools.KeyStoreUtil;
import sun.security.tools.PathList; import sun.security.tools.PathList;
import sun.security.validator.Validator;
import sun.security.validator.ValidatorException;
import sun.security.x509.*; import sun.security.x509.*;
import sun.security.util.*; import sun.security.util.*;
import java.util.Base64; import java.util.Base64;
...@@ -190,9 +192,7 @@ public class Main { ...@@ -190,9 +192,7 @@ public class Main {
private boolean seeWeak = false; private boolean seeWeak = false;
CertificateFactory certificateFactory; PKIXBuilderParameters pkixParameters;
CertPathValidator validator;
PKIXParameters pkixParameters;
public void run(String args[]) { public void run(String args[]) {
try { try {
...@@ -1791,19 +1791,10 @@ public class Main { ...@@ -1791,19 +1791,10 @@ public class Main {
try { try {
validateCertChain(certs); validateCertChain(certs);
} catch (Exception e) { } catch (Exception e) {
if (debug) { chainNotValidated = true;
e.printStackTrace(); chainNotValidatedReason = e;
} s.append(tab).append(rb.getString(".CertPath.not.validated."))
if (e.getCause() != null && .append(e.getLocalizedMessage()).append("]\n"); // TODO
(e.getCause() instanceof CertificateExpiredException ||
e.getCause() instanceof CertificateNotYetValidException)) {
// No more warning, we alreay have hasExpiredCert or notYetValidCert
} else {
chainNotValidated = true;
chainNotValidatedReason = e;
s.append(tab + rb.getString(".CertPath.not.validated.") +
e.getLocalizedMessage() + "]\n"); // TODO
}
} }
if (certs.size() == 1 if (certs.size() == 1
&& KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) { && KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
...@@ -1861,9 +1852,6 @@ public class Main { ...@@ -1861,9 +1852,6 @@ public class Main {
} }
try { try {
certificateFactory = CertificateFactory.getInstance("X.509");
validator = CertPathValidator.getInstance("PKIX");
Set<TrustAnchor> tas = new HashSet<>(); Set<TrustAnchor> tas = new HashSet<>();
try { try {
KeyStore caks = KeyStoreUtil.getCacertsKeyStore(); KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
...@@ -1939,7 +1927,7 @@ public class Main { ...@@ -1939,7 +1927,7 @@ public class Main {
} }
} finally { } finally {
try { try {
pkixParameters = new PKIXParameters(tas); pkixParameters = new PKIXBuilderParameters(tas, null);
pkixParameters.setRevocationEnabled(false); pkixParameters.setRevocationEnabled(false);
} catch (InvalidAlgorithmParameterException ex) { } catch (InvalidAlgorithmParameterException ex) {
// Only if tas is empty // Only if tas is empty
...@@ -2106,17 +2094,8 @@ public class Main { ...@@ -2106,17 +2094,8 @@ public class Main {
try { try {
validateCertChain(Arrays.asList(certChain)); validateCertChain(Arrays.asList(certChain));
} catch (Exception e) { } catch (Exception e) {
if (debug) { chainNotValidated = true;
e.printStackTrace(); chainNotValidatedReason = e;
}
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;
}
} }
if (KeyStoreUtil.isSelfSigned(certChain[0])) { if (KeyStoreUtil.isSelfSigned(certChain[0])) {
...@@ -2175,18 +2154,40 @@ public class Main { ...@@ -2175,18 +2154,40 @@ public class Main {
} }
void validateCertChain(List<? extends Certificate> certs) throws Exception { void validateCertChain(List<? extends Certificate> certs) throws Exception {
int cpLen = 0; try {
out: for (; cpLen<certs.size(); cpLen++) { Validator.getInstance(Validator.TYPE_PKIX,
for (TrustAnchor ta: pkixParameters.getTrustAnchors()) { Validator.VAR_CODE_SIGNING,
if (ta.getTrustedCert().equals(certs.get(cpLen))) { pkixParameters)
break out; .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;
}
} }
} }
} throw e;
if (cpLen > 0) {
CertPath cp = certificateFactory.generateCertPath(
(cpLen == certs.size())? certs: certs.subList(0, cpLen));
validator.validate(cp, pkixParameters);
} }
} }
......
# #
# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
# #
# @test # @test
# @bug 6802846 # @bug 6802846 8172529
# @summary jarsigner needs enhanced cert validation(options) # @summary jarsigner needs enhanced cert validation(options)
# #
# @run shell/timeout=240 concise_jarsigner.sh # @run shell/timeout=240 concise_jarsigner.sh
...@@ -47,12 +47,15 @@ esac ...@@ -47,12 +47,15 @@ esac
# Choose 1024-bit RSA to make sure it runs fine and fast on all platforms. In # Choose 1024-bit RSA to make sure it runs fine and fast on all platforms. In
# fact, every keyalg/keysize combination is OK for this test. # fact, every keyalg/keysize combination is OK for this test.
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore js.jks -keyalg rsa -keysize 1024" TESTTOOLVMOPTS="$TESTTOOLVMOPTS -J-Duser.language=en -J-Duser.country=US"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
JAVAC=$TESTJAVA${FS}bin${FS}javac
rm js.jks 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} -debug"
JAVAC="$TESTJAVA${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}"
rm $KS
echo class A1 {} > A1.java echo class A1 {} > A1.java
echo class A2 {} > A2.java echo class A2 {} > A2.java
...@@ -73,9 +76,9 @@ $KT -genkeypair -alias a2 -dname CN=a2 -validity 366 ...@@ -73,9 +76,9 @@ $KT -genkeypair -alias a2 -dname CN=a2 -validity 366
# a.jar includes 8 unsigned, 2 signed by a1 and a2, 2 signed by a3 # a.jar includes 8 unsigned, 2 signed by a1 and a2, 2 signed by a3
$JAR cvf a.jar A1.class A2.class $JAR cvf a.jar A1.class A2.class
$JARSIGNER -keystore js.jks -storepass changeit a.jar a1 $JARSIGNER -keystore $KS -storepass changeit a.jar a1
$JAR uvf a.jar A3.class A4.class $JAR uvf a.jar A3.class A4.class
$JARSIGNER -keystore js.jks -storepass changeit a.jar a2 $JARSIGNER -keystore $KS -storepass changeit a.jar a2
$JAR uvf a.jar A5.class A6.class $JAR uvf a.jar A5.class A6.class
# Verify OK # Verify OK
...@@ -87,15 +90,15 @@ $JARSIGNER -verify a.jar -strict ...@@ -87,15 +90,15 @@ $JARSIGNER -verify a.jar -strict
[ $? = 20 ] || exit $LINENO [ $? = 20 ] || exit $LINENO
# 16(hasUnsignedEntry) # 16(hasUnsignedEntry)
$JARSIGNER -verify a.jar -strict -keystore js.jks $JARSIGNER -verify a.jar -strict -keystore $KS -storepass changeit
[ $? = 16 ] || exit $LINENO [ $? = 16 ] || exit $LINENO
# 16(hasUnsignedEntry)+32(notSignedByAlias) # 16(hasUnsignedEntry)+32(notSignedByAlias)
$JARSIGNER -verify a.jar a1 -strict -keystore js.jks $JARSIGNER -verify a.jar a1 -strict -keystore $KS -storepass changeit
[ $? = 48 ] || exit $LINENO [ $? = 48 ] || exit $LINENO
# 16(hasUnsignedEntry) # 16(hasUnsignedEntry)
$JARSIGNER -verify a.jar a1 a2 -strict -keystore js.jks $JARSIGNER -verify a.jar a1 a2 -strict -keystore $KS -storepass changeit
[ $? = 16 ] || exit $LINENO [ $? = 16 ] || exit $LINENO
# 12 entries all together # 12 entries all together
...@@ -135,7 +138,7 @@ LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l` ...@@ -135,7 +138,7 @@ LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l`
[ $LINES = 4 ] || exit $LINENO [ $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 # 16 and 32 already covered in the first part
# ========================================================== # ==========================================================
...@@ -153,31 +156,34 @@ $KT -certreq -alias goodku | $KT -gencert -alias ca -ext KU=dig -validity 365 | ...@@ -153,31 +156,34 @@ $KT -certreq -alias goodku | $KT -gencert -alias ca -ext KU=dig -validity 365 |
$KT -genkeypair -alias goodeku -dname CN=goodeku $KT -genkeypair -alias goodeku -dname CN=goodeku
$KT -certreq -alias goodeku | $KT -gencert -alias ca -ext EKU=codesign -validity 365 | $KT -import -alias goodeku $KT -certreq -alias goodeku | $KT -gencert -alias ca -ext EKU=codesign -validity 365 | $KT -import -alias goodeku
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expired $JARSIGNER -strict -keystore $KS -storepass changeit a.jar expired
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar notyetvalid $JARSIGNER -strict -keystore $KS -storepass changeit a.jar notyetvalid
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badku $JARSIGNER -strict -keystore $KS -storepass changeit a.jar badku
[ $? = 8 ] || exit $LINENO [ $? = 8 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badeku $JARSIGNER -strict -keystore $KS -storepass changeit a.jar badeku
[ $? = 8 ] || exit $LINENO [ $? = 8 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodku $JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodku
[ $? = 0 ] || exit $LINENO [ $? = 0 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodeku $JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodeku
[ $? = 0 ] || exit $LINENO [ $? = 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 -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 -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 js.jks -storepass changeit a.jar badchain $JARSIGNER -strict -keystore $KS -storepass changeit a.jar badchain
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
$JARSIGNER -verify a.jar $JARSIGNER -verify a.jar
...@@ -194,20 +200,48 @@ $KT -certreq -alias altchain | $KT -gencert -alias ca2 -validity 365 -rfc > cert ...@@ -194,20 +200,48 @@ $KT -certreq -alias altchain | $KT -gencert -alias ca2 -validity 365 -rfc > cert
$KT -exportcert -alias ca2 -rfc >> certchain $KT -exportcert -alias ca2 -rfc >> certchain
# Self-signed cert does not work # Self-signed cert does not work
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar altchain $JARSIGNER -strict -keystore $KS -storepass changeit a.jar altchain
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
# -certchain works # -certchain works
$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain $JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
[ $? = 0 ] || exit $LINENO [ $? = 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 $KT -delete -alias ca2
$JARSIGNER -strict -keystore js.jks -storepass changeit -certchain certchain a.jar altchain $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 [ $? = 4 ] || exit $LINENO
$JARSIGNER -verify a.jar $JARSIGNER -verify a.jar
[ $? = 0 ] || exit $LINENO [ $? = 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 echo OK
exit 0 exit 0
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册