8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,373 @@
/*
* Copyright (c) 2002, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.validator;
import java.util.*;
import java.security.cert.*;
import sun.security.x509.NetscapeCertTypeExtension;
/**
* Class to check if an end entity cert is suitable for use in some
* context.<p>
*
* This class is used internally by the validator. Currently, seven variants
* are supported defined as VAR_XXX constants in the Validator class:
* <ul>
* <li>Generic. No additional requirements, all certificates are ok.
*
* <li>TLS server. Requires that a String parameter is passed to
* validate that specifies the name of the TLS key exchange algorithm
* in use. See the JSSE X509TrustManager spec for details.
*
* <li>TLS client.
*
* <li>Code signing.
*
* <li>JCE code signing. Some early JCE code signing certs issued to
* providers had incorrect extensions. In this mode the checks
* are relaxed compared to standard code signing checks in order to
* allow these certificates to pass.
*
* <li>Plugin code signing. WebStart and Plugin require their own variant
* which is equivalent to VAR_CODE_SIGNING with additional checks for
* compatibility/special cases. See also PKIXValidator.
*
* <li>TSA Server (see RFC 3161, section 2.3).
*
* </ul>
*
* @author Andreas Sterbenz
*/
class EndEntityChecker {
// extended key usage OIDs for TLS server, TLS client, code signing
// and any usage
private static final String OID_EXTENDED_KEY_USAGE =
SimpleValidator.OID_EXTENDED_KEY_USAGE;
private static final String OID_EKU_TLS_SERVER = "1.3.6.1.5.5.7.3.1";
private static final String OID_EKU_TLS_CLIENT = "1.3.6.1.5.5.7.3.2";
private static final String OID_EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3";
private static final String OID_EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8";
private static final String OID_EKU_ANY_USAGE = "2.5.29.37.0";
// the Netscape Server-Gated-Cryptography EKU extension OID
private static final String OID_EKU_NS_SGC = "2.16.840.1.113730.4.1";
// the Microsoft Server-Gated-Cryptography EKU extension OID
private static final String OID_EKU_MS_SGC = "1.3.6.1.4.1.311.10.3.3";
// the recognized extension OIDs
private static final String OID_SUBJECT_ALT_NAME = "2.5.29.17";
private static final String NSCT_SSL_CLIENT =
NetscapeCertTypeExtension.SSL_CLIENT;
private static final String NSCT_SSL_SERVER =
NetscapeCertTypeExtension.SSL_SERVER;
private static final String NSCT_CODE_SIGNING =
NetscapeCertTypeExtension.OBJECT_SIGNING;
// bit numbers in the key usage extension
private static final int KU_SIGNATURE = 0;
private static final int KU_KEY_ENCIPHERMENT = 2;
private static final int KU_KEY_AGREEMENT = 4;
// TLS key exchange algorithms requiring digitalSignature key usage
private static final Collection<String> KU_SERVER_SIGNATURE =
Arrays.asList("DHE_DSS", "DHE_RSA", "ECDHE_ECDSA", "ECDHE_RSA",
"RSA_EXPORT", "UNKNOWN");
// TLS key exchange algorithms requiring keyEncipherment key usage
private static final Collection<String> KU_SERVER_ENCRYPTION =
Arrays.asList("RSA");
// TLS key exchange algorithms requiring keyAgreement key usage
private static final Collection<String> KU_SERVER_KEY_AGREEMENT =
Arrays.asList("DH_DSS", "DH_RSA", "ECDH_ECDSA", "ECDH_RSA");
// variant of this end entity cert checker
private final String variant;
// type of the validator this checker belongs to
private final String type;
private EndEntityChecker(String type, String variant) {
this.type = type;
this.variant = variant;
}
static EndEntityChecker getInstance(String type, String variant) {
return new EndEntityChecker(type, variant);
}
void check(X509Certificate cert, Object parameter,
boolean checkUnresolvedCritExts) throws CertificateException {
if (variant.equals(Validator.VAR_GENERIC)) {
return; // no checks
}
Set<String> exts = getCriticalExtensions(cert);
if (variant.equals(Validator.VAR_TLS_SERVER)) {
checkTLSServer(cert, (String)parameter, exts);
} else if (variant.equals(Validator.VAR_TLS_CLIENT)) {
checkTLSClient(cert, exts);
} else if (variant.equals(Validator.VAR_CODE_SIGNING)) {
checkCodeSigning(cert, exts);
} else if (variant.equals(Validator.VAR_JCE_SIGNING)) {
checkCodeSigning(cert, exts);
} else if (variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING)) {
checkCodeSigning(cert, exts);
} else if (variant.equals(Validator.VAR_TSA_SERVER)) {
checkTSAServer(cert, exts);
} else {
throw new CertificateException("Unknown variant: " + variant);
}
// if neither VAR_GENERIC variant nor unknown variant
if (checkUnresolvedCritExts) {
checkRemainingExtensions(exts);
}
}
/**
* Utility method returning the Set of critical extensions for
* certificate cert (never null).
*/
private Set<String> getCriticalExtensions(X509Certificate cert) {
Set<String> exts = cert.getCriticalExtensionOIDs();
if (exts == null) {
exts = Collections.emptySet();
}
return exts;
}
/**
* Utility method checking if there are any unresolved critical extensions.
* @throws CertificateException if so.
*/
private void checkRemainingExtensions(Set<String> exts)
throws CertificateException {
// basic constraints irrelevant in EE certs
exts.remove(SimpleValidator.OID_BASIC_CONSTRAINTS);
// If the subject field contains an empty sequence, the subjectAltName
// extension MUST be marked critical.
// We do not check the validity of the critical extension, just mark
// it recognizable here.
exts.remove(OID_SUBJECT_ALT_NAME);
if (!exts.isEmpty()) {
throw new CertificateException("Certificate contains unsupported "
+ "critical extensions: " + exts);
}
}
/**
* Utility method checking if the extended key usage extension in
* certificate cert allows use for expectedEKU.
*/
private boolean checkEKU(X509Certificate cert, Set<String> exts,
String expectedEKU) throws CertificateException {
List<String> eku = cert.getExtendedKeyUsage();
if (eku == null) {
return true;
}
return eku.contains(expectedEKU) || eku.contains(OID_EKU_ANY_USAGE);
}
/**
* Utility method checking if bit 'bit' is set in this certificates
* key usage extension.
* @throws CertificateException if not
*/
private boolean checkKeyUsage(X509Certificate cert, int bit)
throws CertificateException {
boolean[] keyUsage = cert.getKeyUsage();
if (keyUsage == null) {
return true;
}
return (keyUsage.length > bit) && keyUsage[bit];
}
/**
* Check whether this certificate can be used for TLS client
* authentication.
* @throws CertificateException if not.
*/
private void checkTLSClient(X509Certificate cert, Set<String> exts)
throws CertificateException {
if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
throw new ValidatorException
("KeyUsage does not allow digital signatures",
ValidatorException.T_EE_EXTENSIONS, cert);
}
if (checkEKU(cert, exts, OID_EKU_TLS_CLIENT) == false) {
throw new ValidatorException("Extended key usage does not "
+ "permit use for TLS client authentication",
ValidatorException.T_EE_EXTENSIONS, cert);
}
if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_CLIENT)) {
throw new ValidatorException
("Netscape cert type does not permit use for SSL client",
ValidatorException.T_EE_EXTENSIONS, cert);
}
// remove extensions we checked
exts.remove(SimpleValidator.OID_KEY_USAGE);
exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
}
/**
* Check whether this certificate can be used for TLS server authentication
* using the specified authentication type parameter. See X509TrustManager
* specification for details.
* @throws CertificateException if not.
*/
private void checkTLSServer(X509Certificate cert, String parameter,
Set<String> exts) throws CertificateException {
if (KU_SERVER_ENCRYPTION.contains(parameter)) {
if (checkKeyUsage(cert, KU_KEY_ENCIPHERMENT) == false) {
throw new ValidatorException
("KeyUsage does not allow key encipherment",
ValidatorException.T_EE_EXTENSIONS, cert);
}
} else if (KU_SERVER_SIGNATURE.contains(parameter)) {
if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
throw new ValidatorException
("KeyUsage does not allow digital signatures",
ValidatorException.T_EE_EXTENSIONS, cert);
}
} else if (KU_SERVER_KEY_AGREEMENT.contains(parameter)) {
if (checkKeyUsage(cert, KU_KEY_AGREEMENT) == false) {
throw new ValidatorException
("KeyUsage does not allow key agreement",
ValidatorException.T_EE_EXTENSIONS, cert);
}
} else {
throw new CertificateException("Unknown authType: " + parameter);
}
if (checkEKU(cert, exts, OID_EKU_TLS_SERVER) == false) {
// check for equivalent but now obsolete Server-Gated-Cryptography
// (aka Step-Up, 128 bit) EKU OIDs
if ((checkEKU(cert, exts, OID_EKU_MS_SGC) == false) &&
(checkEKU(cert, exts, OID_EKU_NS_SGC) == false)) {
throw new ValidatorException
("Extended key usage does not permit use for TLS "
+ "server authentication",
ValidatorException.T_EE_EXTENSIONS, cert);
}
}
if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_SERVER)) {
throw new ValidatorException
("Netscape cert type does not permit use for SSL server",
ValidatorException.T_EE_EXTENSIONS, cert);
}
// remove extensions we checked
exts.remove(SimpleValidator.OID_KEY_USAGE);
exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
}
/**
* Check whether this certificate can be used for code signing.
* @throws CertificateException if not.
*/
private void checkCodeSigning(X509Certificate cert, Set<String> exts)
throws CertificateException {
if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
throw new ValidatorException
("KeyUsage does not allow digital signatures",
ValidatorException.T_EE_EXTENSIONS, cert);
}
if (checkEKU(cert, exts, OID_EKU_CODE_SIGNING) == false) {
throw new ValidatorException
("Extended key usage does not permit use for code signing",
ValidatorException.T_EE_EXTENSIONS, cert);
}
// do not check Netscape cert type for JCE code signing checks
// (some certs were issued with incorrect extensions)
if (variant.equals(Validator.VAR_JCE_SIGNING) == false) {
if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_CODE_SIGNING)) {
throw new ValidatorException
("Netscape cert type does not permit use for code signing",
ValidatorException.T_EE_EXTENSIONS, cert);
}
exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
}
// remove extensions we checked
exts.remove(SimpleValidator.OID_KEY_USAGE);
exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
}
/**
* Check whether this certificate can be used by a time stamping authority
* server (see RFC 3161, section 2.3).
* @throws CertificateException if not.
*/
private void checkTSAServer(X509Certificate cert, Set<String> exts)
throws CertificateException {
if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
throw new ValidatorException
("KeyUsage does not allow digital signatures",
ValidatorException.T_EE_EXTENSIONS, cert);
}
if (cert.getExtendedKeyUsage() == null) {
throw new ValidatorException
("Certificate does not contain an extended key usage " +
"extension required for a TSA server",
ValidatorException.T_EE_EXTENSIONS, cert);
}
if (checkEKU(cert, exts, OID_EKU_TIME_STAMPING) == false) {
throw new ValidatorException
("Extended key usage does not permit use for TSA server",
ValidatorException.T_EE_EXTENSIONS, cert);
}
// remove extensions we checked
exts.remove(SimpleValidator.OID_KEY_USAGE);
exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
}
}

View file

@ -0,0 +1,454 @@
/*
* Copyright (c) 2002, 2017, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.validator;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import javax.security.auth.x500.X500Principal;
import sun.security.action.GetBooleanAction;
import sun.security.provider.certpath.AlgorithmChecker;
import sun.security.provider.certpath.PKIXExtendedParameters;
/**
* Validator implementation built on the PKIX CertPath API. This
* implementation will be emphasized going forward.
* <p>
* Note that the validate() implementation tries to use a PKIX validator
* if that appears possible and a PKIX builder otherwise. This increases
* performance and currently also leads to better exception messages
* in case of failures.
* <p>
* {@code PKIXValidator} objects are immutable once they have been created.
* Please DO NOT add methods that can change the state of an instance once
* it has been created.
*
* @author Andreas Sterbenz
*/
public final class PKIXValidator extends Validator {
/**
* Flag indicating whether to enable revocation check for the PKIX trust
* manager. Typically, this will only work if the PKIX implementation
* supports CRL distribution points as we do not manually setup CertStores.
*/
private static final boolean checkTLSRevocation =
AccessController.doPrivileged
(new GetBooleanAction("com.sun.net.ssl.checkRevocation"));
private final Set<X509Certificate> trustedCerts;
private final PKIXBuilderParameters parameterTemplate;
private int certPathLength = -1;
// needed only for the validator
private final Map<X500Principal, List<PublicKey>> trustedSubjects;
private final CertificateFactory factory;
private final boolean plugin;
PKIXValidator(String variant, Collection<X509Certificate> trustedCerts) {
super(TYPE_PKIX, variant);
this.trustedCerts = (trustedCerts instanceof Set) ?
(Set<X509Certificate>)trustedCerts :
new HashSet<X509Certificate>(trustedCerts);
Set<TrustAnchor> trustAnchors = new HashSet<>();
for (X509Certificate cert : trustedCerts) {
trustAnchors.add(new TrustAnchor(cert, null));
}
try {
parameterTemplate = new PKIXBuilderParameters(trustAnchors, null);
factory = CertificateFactory.getInstance("X.509");
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException("Unexpected error: " + e.toString(), e);
} catch (CertificateException e) {
throw new RuntimeException("Internal error", e);
}
setDefaultParameters(variant);
plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
trustedSubjects = setTrustedSubjects();
}
PKIXValidator(String variant, PKIXBuilderParameters params) {
super(TYPE_PKIX, variant);
trustedCerts = new HashSet<X509Certificate>();
for (TrustAnchor anchor : params.getTrustAnchors()) {
X509Certificate cert = anchor.getTrustedCert();
if (cert != null) {
trustedCerts.add(cert);
}
}
parameterTemplate = params;
try {
factory = CertificateFactory.getInstance("X.509");
} catch (CertificateException e) {
throw new RuntimeException("Internal error", e);
}
plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
trustedSubjects = setTrustedSubjects();
}
/**
* Populate the trustedSubjects Map using the DN and public keys from
* the list of trusted certificates
*
* @return Map containing each subject DN and one or more public keys
* tied to those DNs.
*/
private Map<X500Principal, List<PublicKey>> setTrustedSubjects() {
Map<X500Principal, List<PublicKey>> subjectMap = new HashMap<>();
for (X509Certificate cert : trustedCerts) {
X500Principal dn = cert.getSubjectX500Principal();
List<PublicKey> keys;
if (subjectMap.containsKey(dn)) {
keys = subjectMap.get(dn);
} else {
keys = new ArrayList<PublicKey>();
subjectMap.put(dn, keys);
}
keys.add(cert.getPublicKey());
}
return subjectMap;
}
public Collection<X509Certificate> getTrustedCertificates() {
return trustedCerts;
}
/**
* Returns the length of the last certification path that is validated by
* CertPathValidator. This is intended primarily as a callback mechanism
* for PKIXCertPathCheckers to determine the length of the certification
* path that is being validated. It is necessary since engineValidate()
* may modify the length of the path.
*
* @return the length of the last certification path passed to
* CertPathValidator.validate, or -1 if it has not been invoked yet
*/
public int getCertPathLength() { // mutable, should be private
return certPathLength;
}
/**
* Set J2SE global default PKIX parameters. Currently, hardcoded to disable
* revocation checking. In the future, this should be configurable.
*/
private void setDefaultParameters(String variant) {
if ((variant == Validator.VAR_TLS_SERVER) ||
(variant == Validator.VAR_TLS_CLIENT)) {
parameterTemplate.setRevocationEnabled(checkTLSRevocation);
} else {
parameterTemplate.setRevocationEnabled(false);
}
}
/**
* Return the PKIX parameters used by this instance. An application may
* modify the parameters but must make sure not to perform any concurrent
* validations.
*/
public PKIXBuilderParameters getParameters() { // mutable, should be private
return parameterTemplate;
}
@Override
X509Certificate[] engineValidate(X509Certificate[] chain,
Collection<X509Certificate> otherCerts,
List<byte[]> responseList,
AlgorithmConstraints constraints,
Object parameter) throws CertificateException {
if ((chain == null) || (chain.length == 0)) {
throw new CertificateException
("null or zero-length certificate chain");
}
// Use PKIXExtendedParameters for timestamp and variant additions
PKIXBuilderParameters pkixParameters = null;
try {
pkixParameters = new PKIXExtendedParameters(
(PKIXBuilderParameters) parameterTemplate.clone(),
(parameter instanceof Timestamp) ?
(Timestamp) parameter : null,
variant);
} catch (InvalidAlgorithmParameterException e) {
// ignore exception
}
// add new algorithm constraints checker
if (constraints != null) {
pkixParameters.addCertPathChecker(
new AlgorithmChecker(constraints, null, variant));
}
// attach it to the PKIXBuilderParameters.
if (!responseList.isEmpty()) {
addResponses(pkixParameters, chain, responseList);
}
// check that chain is in correct order and check if chain contains
// trust anchor
X500Principal prevIssuer = null;
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
X500Principal dn = cert.getSubjectX500Principal();
if (i != 0 && !dn.equals(prevIssuer)) {
// chain is not ordered correctly, call builder instead
return doBuild(chain, otherCerts, pkixParameters);
}
// Check if chain[i] is already trusted. It may be inside
// trustedCerts, or has the same dn and public key as a cert
// inside trustedCerts. The latter happens when a CA has
// updated its cert with a stronger signature algorithm in JRE
// but the weak one is still in circulation.
if (trustedCerts.contains(cert) || // trusted cert
(trustedSubjects.containsKey(dn) && // replacing ...
trustedSubjects.get(dn).contains( // ... weak cert
cert.getPublicKey()))) {
if (i == 0) {
return new X509Certificate[] {chain[0]};
}
// Remove and call validator on partial chain [0 .. i-1]
X509Certificate[] newChain = new X509Certificate[i];
System.arraycopy(chain, 0, newChain, 0, i);
return doValidate(newChain, pkixParameters);
}
prevIssuer = cert.getIssuerX500Principal();
}
// apparently issued by trust anchor?
X509Certificate last = chain[chain.length - 1];
X500Principal issuer = last.getIssuerX500Principal();
X500Principal subject = last.getSubjectX500Principal();
if (trustedSubjects.containsKey(issuer) &&
isSignatureValid(trustedSubjects.get(issuer), last)) {
return doValidate(chain, pkixParameters);
}
// don't fallback to builder if called from plugin/webstart
if (plugin) {
// Validate chain even if no trust anchor is found. This
// allows plugin/webstart to make sure the chain is
// otherwise valid
if (chain.length > 1) {
X509Certificate[] newChain =
new X509Certificate[chain.length-1];
System.arraycopy(chain, 0, newChain, 0, newChain.length);
// temporarily set last cert as sole trust anchor
try {
pkixParameters.setTrustAnchors
(Collections.singleton(new TrustAnchor
(chain[chain.length-1], null)));
} catch (InvalidAlgorithmParameterException iape) {
// should never occur, but ...
throw new CertificateException(iape);
}
doValidate(newChain, pkixParameters);
}
// if the rest of the chain is valid, throw exception
// indicating no trust anchor was found
throw new ValidatorException
(ValidatorException.T_NO_TRUST_ANCHOR);
}
// otherwise, fall back to builder
return doBuild(chain, otherCerts, pkixParameters);
}
private boolean isSignatureValid(List<PublicKey> keys,
X509Certificate sub) {
if (plugin) {
for (PublicKey key: keys) {
try {
sub.verify(key);
return true;
} catch (Exception ex) {
continue;
}
}
return false;
}
return true; // only check if PLUGIN is set
}
private static X509Certificate[] toArray(CertPath path, TrustAnchor anchor)
throws CertificateException {
List<? extends java.security.cert.Certificate> list =
path.getCertificates();
X509Certificate[] chain = new X509Certificate[list.size() + 1];
list.toArray(chain);
X509Certificate trustedCert = anchor.getTrustedCert();
if (trustedCert == null) {
throw new ValidatorException
("TrustAnchor must be specified as certificate");
}
chain[chain.length - 1] = trustedCert;
return chain;
}
/**
* Set the check date (for debugging).
*/
private void setDate(PKIXBuilderParameters params) {
@SuppressWarnings("deprecation")
Date date = validationDate;
if (date != null) {
params.setDate(date);
}
}
private X509Certificate[] doValidate(X509Certificate[] chain,
PKIXBuilderParameters params) throws CertificateException {
try {
setDate(params);
// do the validation
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
CertPath path = factory.generateCertPath(Arrays.asList(chain));
certPathLength = chain.length;
PKIXCertPathValidatorResult result =
(PKIXCertPathValidatorResult)validator.validate(path, params);
return toArray(path, result.getTrustAnchor());
} catch (GeneralSecurityException e) {
throw new ValidatorException
("PKIX path validation failed: " + e.toString(), e);
}
}
private X509Certificate[] doBuild(X509Certificate[] chain,
Collection<X509Certificate> otherCerts,
PKIXBuilderParameters params) throws CertificateException {
try {
setDate(params);
// setup target constraints
X509CertSelector selector = new X509CertSelector();
selector.setCertificate(chain[0]);
params.setTargetCertConstraints(selector);
// setup CertStores
Collection<X509Certificate> certs =
new ArrayList<X509Certificate>();
certs.addAll(Arrays.asList(chain));
if (otherCerts != null) {
certs.addAll(otherCerts);
}
CertStore store = CertStore.getInstance("Collection",
new CollectionCertStoreParameters(certs));
params.addCertStore(store);
// do the build
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
PKIXCertPathBuilderResult result =
(PKIXCertPathBuilderResult)builder.build(params);
return toArray(result.getCertPath(), result.getTrustAnchor());
} catch (GeneralSecurityException e) {
throw new ValidatorException
("PKIX path building failed: " + e.toString(), e);
}
}
/**
* For OCSP Stapling, add responses that came in during the handshake
* into a {@code PKIXRevocationChecker} so we can evaluate them.
*
* @param pkixParams the pkixParameters object that will be used in
* path validation.
* @param chain the chain of certificates to verify
* @param responseList a {@code List} of zero or more byte arrays, each
* one being a DER-encoded OCSP response (per RFC 6960). Entries
* in the List must match the order of the certificates in the
* chain parameter.
*/
private static void addResponses(PKIXBuilderParameters pkixParams,
X509Certificate[] chain, List<byte[]> responseList) {
if (pkixParams.isRevocationEnabled()) {
try {
// Make a modifiable copy of the CertPathChecker list
PKIXRevocationChecker revChecker = null;
List<PKIXCertPathChecker> checkerList =
new ArrayList<>(pkixParams.getCertPathCheckers());
// Find the first PKIXRevocationChecker in the list
for (PKIXCertPathChecker checker : checkerList) {
if (checker instanceof PKIXRevocationChecker) {
revChecker = (PKIXRevocationChecker)checker;
break;
}
}
// If we still haven't found one, make one
if (revChecker == null) {
revChecker = (PKIXRevocationChecker)CertPathValidator.
getInstance("PKIX").getRevocationChecker();
checkerList.add(revChecker);
}
// Each response in the list should be in parallel with
// the certificate list. If there is a zero-length response
// treat it as being absent. If the user has provided their
// own PKIXRevocationChecker with pre-populated responses, do
// not overwrite them with the ones from the handshake.
Map<X509Certificate, byte[]> responseMap =
revChecker.getOcspResponses();
int limit = Integer.min(chain.length, responseList.size());
for (int idx = 0; idx < limit; idx++) {
byte[] respBytes = responseList.get(idx);
if (respBytes != null && respBytes.length > 0 &&
!responseMap.containsKey(chain[idx])) {
responseMap.put(chain[idx], respBytes);
}
}
// Add the responses and push it all back into the
// PKIXBuilderParameters
revChecker.setOcspResponses(responseMap);
pkixParams.setCertPathCheckers(checkerList);
} catch (NoSuchAlgorithmException exc) {
// This should not occur, but if it does happen then
// stapled OCSP responses won't be part of revocation checking.
// Clients can still fall back to other means of revocation
// checking.
}
}
}
}

View file

@ -0,0 +1,447 @@
/*
* Copyright (c) 2002, 2017, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.validator;
import java.io.IOException;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import javax.security.auth.x500.X500Principal;
import sun.security.x509.X509CertImpl;
import sun.security.x509.KeyIdentifier;
import sun.security.x509.NetscapeCertTypeExtension;
import sun.security.util.DerValue;
import sun.security.util.DerInputStream;
import sun.security.util.ObjectIdentifier;
import sun.security.provider.certpath.AlgorithmChecker;
import sun.security.provider.certpath.UntrustedChecker;
/**
* A simple validator implementation. It is based on code from the JSSE
* X509TrustManagerImpl. This implementation is designed for compatibility with
* deployed certificates and previous J2SE versions. It will never support
* more advanced features and will be deemphasized in favor of the PKIX
* validator going forward.
* <p>
* {@code SimpleValidator} objects are immutable once they have been created.
* Please DO NOT add methods that can change the state of an instance once
* it has been created.
*
* @author Andreas Sterbenz
*/
public final class SimpleValidator extends Validator {
// Constants for the OIDs we need
static final String OID_BASIC_CONSTRAINTS = "2.5.29.19";
static final String OID_NETSCAPE_CERT_TYPE = "2.16.840.1.113730.1.1";
static final String OID_KEY_USAGE = "2.5.29.15";
static final String OID_EXTENDED_KEY_USAGE = "2.5.29.37";
static final String OID_EKU_ANY_USAGE = "2.5.29.37.0";
static final ObjectIdentifier OBJID_NETSCAPE_CERT_TYPE =
NetscapeCertTypeExtension.NetscapeCertType_Id;
private static final String NSCT_SSL_CA =
NetscapeCertTypeExtension.SSL_CA;
private static final String NSCT_CODE_SIGNING_CA =
NetscapeCertTypeExtension.OBJECT_SIGNING_CA;
/**
* The trusted certificates as:
* Map (X500Principal)subject of trusted cert -> List of X509Certificate
* The list is used because there may be multiple certificates
* with an identical subject DN.
*/
private final Map<X500Principal, List<X509Certificate>>
trustedX500Principals;
/**
* Set of the trusted certificates. Present only for
* getTrustedCertificates().
*/
private final Collection<X509Certificate> trustedCerts;
SimpleValidator(String variant, Collection<X509Certificate> trustedCerts) {
super(TYPE_SIMPLE, variant);
this.trustedCerts = trustedCerts;
trustedX500Principals =
new HashMap<X500Principal, List<X509Certificate>>();
for (X509Certificate cert : trustedCerts) {
X500Principal principal = cert.getSubjectX500Principal();
List<X509Certificate> list = trustedX500Principals.get(principal);
if (list == null) {
// this actually should be a set, but duplicate entries
// are not a problem and we can avoid the Set overhead
list = new ArrayList<X509Certificate>(2);
trustedX500Principals.put(principal, list);
}
list.add(cert);
}
}
public Collection<X509Certificate> getTrustedCertificates() {
return trustedCerts;
}
/**
* Perform simple validation of chain. The arguments otherCerts and
* parameter are ignored.
*/
@Override
X509Certificate[] engineValidate(X509Certificate[] chain,
Collection<X509Certificate> otherCerts,
List<byte[]> responseList,
AlgorithmConstraints constraints,
Object parameter) throws CertificateException {
if ((chain == null) || (chain.length == 0)) {
throw new CertificateException
("null or zero-length certificate chain");
}
// make sure chain includes a trusted cert
chain = buildTrustedChain(chain);
@SuppressWarnings("deprecation")
Date date = validationDate;
if (date == null) {
date = new Date();
}
// create distrusted certificates checker
UntrustedChecker untrustedChecker = new UntrustedChecker();
// check if anchor is untrusted
X509Certificate anchorCert = chain[chain.length - 1];
try {
untrustedChecker.check(anchorCert);
} catch (CertPathValidatorException cpve) {
throw new ValidatorException(
"Untrusted certificate: "+ anchorCert.getSubjectX500Principal(),
ValidatorException.T_UNTRUSTED_CERT, anchorCert, cpve);
}
// create default algorithm constraints checker
TrustAnchor anchor = new TrustAnchor(anchorCert, null);
AlgorithmChecker defaultAlgChecker =
new AlgorithmChecker(anchor, variant);
// create application level algorithm constraints checker
AlgorithmChecker appAlgChecker = null;
if (constraints != null) {
appAlgChecker = new AlgorithmChecker(anchor, constraints, null,
null, variant);
}
// verify top down, starting at the certificate issued by
// the trust anchor
int maxPathLength = chain.length - 1;
for (int i = chain.length - 2; i >= 0; i--) {
X509Certificate issuerCert = chain[i + 1];
X509Certificate cert = chain[i];
// check untrusted certificate
try {
// Untrusted checker does not care about the unresolved
// critical extensions.
untrustedChecker.check(cert, Collections.<String>emptySet());
} catch (CertPathValidatorException cpve) {
throw new ValidatorException(
"Untrusted certificate: " + cert.getSubjectX500Principal(),
ValidatorException.T_UNTRUSTED_CERT, cert, cpve);
}
// check certificate algorithm
try {
// Algorithm checker does not care about the unresolved
// critical extensions.
defaultAlgChecker.check(cert, Collections.<String>emptySet());
if (appAlgChecker != null) {
appAlgChecker.check(cert, Collections.<String>emptySet());
}
} catch (CertPathValidatorException cpve) {
throw new ValidatorException
(ValidatorException.T_ALGORITHM_DISABLED, cert, cpve);
}
// no validity check for code signing certs
if ((variant.equals(VAR_CODE_SIGNING) == false)
&& (variant.equals(VAR_JCE_SIGNING) == false)) {
cert.checkValidity(date);
}
// check name chaining
if (cert.getIssuerX500Principal().equals(
issuerCert.getSubjectX500Principal()) == false) {
throw new ValidatorException
(ValidatorException.T_NAME_CHAINING, cert);
}
// check signature
try {
cert.verify(issuerCert.getPublicKey());
} catch (GeneralSecurityException e) {
throw new ValidatorException
(ValidatorException.T_SIGNATURE_ERROR, cert, e);
}
// check extensions for CA certs
if (i != 0) {
maxPathLength = checkExtensions(cert, maxPathLength);
}
}
return chain;
}
private int checkExtensions(X509Certificate cert, int maxPathLen)
throws CertificateException {
Set<String> critSet = cert.getCriticalExtensionOIDs();
if (critSet == null) {
critSet = Collections.<String>emptySet();
}
// Check the basic constraints extension
int pathLenConstraint =
checkBasicConstraints(cert, critSet, maxPathLen);
// Check the key usage and extended key usage extensions
checkKeyUsage(cert, critSet);
// check Netscape certificate type extension
checkNetscapeCertType(cert, critSet);
if (!critSet.isEmpty()) {
throw new ValidatorException
("Certificate contains unknown critical extensions: " + critSet,
ValidatorException.T_CA_EXTENSIONS, cert);
}
return pathLenConstraint;
}
private void checkNetscapeCertType(X509Certificate cert,
Set<String> critSet) throws CertificateException {
if (variant.equals(VAR_GENERIC)) {
// nothing
} else if (variant.equals(VAR_TLS_CLIENT)
|| variant.equals(VAR_TLS_SERVER)) {
if (getNetscapeCertTypeBit(cert, NSCT_SSL_CA) == false) {
throw new ValidatorException
("Invalid Netscape CertType extension for SSL CA "
+ "certificate",
ValidatorException.T_CA_EXTENSIONS, cert);
}
critSet.remove(OID_NETSCAPE_CERT_TYPE);
} else if (variant.equals(VAR_CODE_SIGNING)
|| variant.equals(VAR_JCE_SIGNING)) {
if (getNetscapeCertTypeBit(cert, NSCT_CODE_SIGNING_CA) == false) {
throw new ValidatorException
("Invalid Netscape CertType extension for code "
+ "signing CA certificate",
ValidatorException.T_CA_EXTENSIONS, cert);
}
critSet.remove(OID_NETSCAPE_CERT_TYPE);
} else {
throw new CertificateException("Unknown variant " + variant);
}
}
/**
* Get the value of the specified bit in the Netscape certificate type
* extension. If the extension is not present at all, we return true.
*/
static boolean getNetscapeCertTypeBit(X509Certificate cert, String type) {
try {
NetscapeCertTypeExtension ext;
if (cert instanceof X509CertImpl) {
X509CertImpl certImpl = (X509CertImpl)cert;
ObjectIdentifier oid = OBJID_NETSCAPE_CERT_TYPE;
ext = (NetscapeCertTypeExtension)certImpl.getExtension(oid);
if (ext == null) {
return true;
}
} else {
byte[] extVal = cert.getExtensionValue(OID_NETSCAPE_CERT_TYPE);
if (extVal == null) {
return true;
}
DerInputStream in = new DerInputStream(extVal);
byte[] encoded = in.getOctetString();
encoded = new DerValue(encoded).getUnalignedBitString()
.toByteArray();
ext = new NetscapeCertTypeExtension(encoded);
}
Boolean val = ext.get(type);
return val.booleanValue();
} catch (IOException e) {
return false;
}
}
private int checkBasicConstraints(X509Certificate cert,
Set<String> critSet, int maxPathLen) throws CertificateException {
critSet.remove(OID_BASIC_CONSTRAINTS);
int constraints = cert.getBasicConstraints();
// reject, if extension missing or not a CA (constraints == -1)
if (constraints < 0) {
throw new ValidatorException("End user tried to act as a CA",
ValidatorException.T_CA_EXTENSIONS, cert);
}
// if the certificate is self-issued, ignore the pathLenConstraint
// checking.
if (!X509CertImpl.isSelfIssued(cert)) {
if (maxPathLen <= 0) {
throw new ValidatorException("Violated path length constraints",
ValidatorException.T_CA_EXTENSIONS, cert);
}
maxPathLen--;
}
if (maxPathLen > constraints) {
maxPathLen = constraints;
}
return maxPathLen;
}
/*
* Verify the key usage and extended key usage for intermediate
* certificates.
*/
private void checkKeyUsage(X509Certificate cert, Set<String> critSet)
throws CertificateException {
critSet.remove(OID_KEY_USAGE);
// EKU irrelevant in CA certificates
critSet.remove(OID_EXTENDED_KEY_USAGE);
// check key usage extension
boolean[] keyUsageInfo = cert.getKeyUsage();
if (keyUsageInfo != null) {
// keyUsageInfo[5] is for keyCertSign.
if ((keyUsageInfo.length < 6) || (keyUsageInfo[5] == false)) {
throw new ValidatorException
("Wrong key usage: expected keyCertSign",
ValidatorException.T_CA_EXTENSIONS, cert);
}
}
}
/**
* Build a trusted certificate chain. This method always returns a chain
* with a trust anchor as the final cert in the chain. If no trust anchor
* could be found, a CertificateException is thrown.
*/
private X509Certificate[] buildTrustedChain(X509Certificate[] chain)
throws CertificateException {
List<X509Certificate> c = new ArrayList<X509Certificate>(chain.length);
// scan chain starting at EE cert
// if a trusted certificate is found, append it and return
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
X509Certificate trustedCert = getTrustedCertificate(cert);
if (trustedCert != null) {
c.add(trustedCert);
return c.toArray(CHAIN0);
}
c.add(cert);
}
// check if we can append a trusted cert
X509Certificate cert = chain[chain.length - 1];
X500Principal subject = cert.getSubjectX500Principal();
X500Principal issuer = cert.getIssuerX500Principal();
List<X509Certificate> list = trustedX500Principals.get(issuer);
if (list != null) {
X509Certificate matchedCert = list.get(0);
X509CertImpl certImpl = X509CertImpl.toImpl(cert);
KeyIdentifier akid = certImpl.getAuthKeyId();
if (akid != null) {
for (X509Certificate sup : list) {
// Look for a best match issuer.
X509CertImpl supCert = X509CertImpl.toImpl(sup);
if (akid.equals(supCert.getSubjectKeyId())) {
matchedCert = sup;
break;
}
}
}
c.add(matchedCert);
return c.toArray(CHAIN0);
}
// no trusted cert found, error
throw new ValidatorException(ValidatorException.T_NO_TRUST_ANCHOR);
}
/**
* Return a trusted certificate that matches the input certificate,
* or null if no such certificate can be found. This method also handles
* cases where a CA re-issues a trust anchor with the same public key and
* same subject and issuer names but a new validity period, etc.
*/
private X509Certificate getTrustedCertificate(X509Certificate cert) {
Principal certSubjectName = cert.getSubjectX500Principal();
List<X509Certificate> list = trustedX500Principals.get(certSubjectName);
if (list == null) {
return null;
}
Principal certIssuerName = cert.getIssuerX500Principal();
PublicKey certPublicKey = cert.getPublicKey();
for (X509Certificate mycert : list) {
if (mycert.equals(cert)) {
return cert;
}
if (!mycert.getIssuerX500Principal().equals(certIssuerName)) {
continue;
}
if (!mycert.getPublicKey().equals(certPublicKey)) {
continue;
}
// All tests pass, this must be the one to use...
return mycert;
}
return null;
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2002, 2016, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.validator;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.Enumeration;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.X509Certificate;
import java.security.cert.Certificate;
/**
* Collection of static utility methods related to trust anchor KeyStores.
*
* @author Andreas Sterbenz
*/
public final class TrustStoreUtil {
private TrustStoreUtil() {
// empty
}
/**
* Return an unmodifiable Set with all trusted X509Certificates contained
* in the specified KeyStore.
*/
public static Set<X509Certificate> getTrustedCerts(KeyStore ks) {
Set<X509Certificate> set = new HashSet<>();
try {
for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
String alias = e.nextElement();
if (ks.isCertificateEntry(alias)) {
Certificate cert = ks.getCertificate(alias);
if (cert instanceof X509Certificate) {
set.add((X509Certificate)cert);
}
} else if (ks.isKeyEntry(alias)) {
Certificate[] certs = ks.getCertificateChain(alias);
if ((certs != null) && (certs.length > 0) &&
(certs[0] instanceof X509Certificate)) {
set.add((X509Certificate)certs[0]);
}
}
}
} catch (KeyStoreException e) {
// ignore
//
// This should be rare, but better to log this in the future.
}
return Collections.unmodifiableSet(set);
}
}

View file

@ -0,0 +1,308 @@
/*
* Copyright (c) 2002, 2016, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.validator;
import java.util.*;
import java.security.AlgorithmConstraints;
import java.security.KeyStore;
import java.security.cert.*;
/**
* Validator abstract base class. Concrete classes are instantiated by calling
* one of the getInstance() methods. All methods defined in this class
* must be safe for concurrent use by multiple threads.<p>
*
* The model is that a Validator instance is created specifying validation
* settings, such as trust anchors or PKIX parameters. Then one or more
* paths are validated using those parameters. In some cases, additional
* information can be provided per path validation. This is independent of
* the validation parameters and currently only used for TLS server validation.
* <p>
* Path validation is performed by calling one of the validate() methods. It
* specifies a suggested path to be used for validation if available, or only
* the end entity certificate otherwise. Optionally additional certificates can
* be specified that the caller believes could be helpful. Implementations are
* free to make use of this information or validate the path using other means.
* validate() also checks that the end entity certificate is suitable for the
* intended purpose as described below.
*
* <p>There are two orthogonal parameters to select the Validator
* implementation: type and variant. Type selects the validation algorithm.
* Currently supported are TYPE_SIMPLE and TYPE_PKIX. See SimpleValidator and
* PKIXValidator for details.
* <p>
* Variant controls additional extension checks. Currently supported are
* five variants:
* <ul>
* <li>VAR_GENERIC (no additional checks),
* <li>VAR_TLS_CLIENT (TLS client specific checks)
* <li>VAR_TLS_SERVER (TLS server specific checks), and
* <li>VAR_CODE_SIGNING (code signing specific checks).
* <li>VAR_JCE_SIGNING (JCE code signing specific checks).
* <li>VAR_TSA_SERVER (TSA server specific checks).
* <li>VAR_PLUGIN_CODE_SIGNING (Plugin/WebStart code signing specific checks).
* </ul>
* See EndEntityChecker for more information.
* <p>
* Examples:
* <pre>
* // instantiate validator specifying type, variant, and trust anchors
* Validator validator = Validator.getInstance(Validator.TYPE_PKIX,
* Validator.VAR_TLS_CLIENT,
* trustedCerts);
* // validate one or more chains using the validator
* validator.validate(chain); // throws CertificateException if failed
* </pre>
*
* @see SimpleValidator
* @see PKIXValidator
* @see EndEntityChecker
*
* @author Andreas Sterbenz
*/
public abstract class Validator {
static final X509Certificate[] CHAIN0 = {};
/**
* Constant for a validator of type Simple.
* @see #getInstance
*/
public static final String TYPE_SIMPLE = "Simple";
/**
* Constant for a validator of type PKIX.
* @see #getInstance
*/
public static final String TYPE_PKIX = "PKIX";
/**
* Constant for a Generic variant of a validator.
* @see #getInstance
*/
public static final String VAR_GENERIC = "generic";
/**
* Constant for a Code Signing variant of a validator.
* @see #getInstance
*/
public static final String VAR_CODE_SIGNING = "code signing";
/**
* Constant for a JCE Code Signing variant of a validator.
* @see #getInstance
*/
public static final String VAR_JCE_SIGNING = "jce signing";
/**
* Constant for a TLS Client variant of a validator.
* @see #getInstance
*/
public static final String VAR_TLS_CLIENT = "tls client";
/**
* Constant for a TLS Server variant of a validator.
* @see #getInstance
*/
public static final String VAR_TLS_SERVER = "tls server";
/**
* Constant for a TSA Server variant of a validator.
* @see #getInstance
*/
public static final String VAR_TSA_SERVER = "tsa server";
/**
* Constant for a Code Signing variant of a validator for use by
* the J2SE Plugin/WebStart code.
* @see #getInstance
*/
public static final String VAR_PLUGIN_CODE_SIGNING = "plugin code signing";
private final String type;
final EndEntityChecker endEntityChecker;
final String variant;
/**
* @deprecated
* @see #setValidationDate
*/
@Deprecated
volatile Date validationDate;
Validator(String type, String variant) {
this.type = type;
this.variant = variant;
endEntityChecker = EndEntityChecker.getInstance(type, variant);
}
/**
* Get a new Validator instance using the trusted certificates from the
* specified KeyStore as trust anchors.
*/
public static Validator getInstance(String type, String variant,
KeyStore ks) {
return getInstance(type, variant, TrustStoreUtil.getTrustedCerts(ks));
}
/**
* Get a new Validator instance using the Set of X509Certificates as trust
* anchors.
*/
public static Validator getInstance(String type, String variant,
Collection<X509Certificate> trustedCerts) {
if (type.equals(TYPE_SIMPLE)) {
return new SimpleValidator(variant, trustedCerts);
} else if (type.equals(TYPE_PKIX)) {
return new PKIXValidator(variant, trustedCerts);
} else {
throw new IllegalArgumentException
("Unknown validator type: " + type);
}
}
/**
* Get a new Validator instance using the provided PKIXBuilderParameters.
* This method can only be used with the PKIX validator.
*/
public static Validator getInstance(String type, String variant,
PKIXBuilderParameters params) {
if (type.equals(TYPE_PKIX) == false) {
throw new IllegalArgumentException
("getInstance(PKIXBuilderParameters) can only be used "
+ "with PKIX validator");
}
return new PKIXValidator(variant, params);
}
/**
* Validate the given certificate chain.
*/
public final X509Certificate[] validate(X509Certificate[] chain)
throws CertificateException {
return validate(chain, null, null);
}
/**
* Validate the given certificate chain. If otherCerts is non-null, it is
* a Collection of additional X509Certificates that could be helpful for
* path building.
*/
public final X509Certificate[] validate(X509Certificate[] chain,
Collection<X509Certificate> otherCerts) throws CertificateException {
return validate(chain, otherCerts, null);
}
/**
* Validate the given certificate chain. If otherCerts is non-null, it is
* a Collection of additional X509Certificates that could be helpful for
* path building.
*
* @return a non-empty chain that was used to validate the path. The
* end entity cert is at index 0, the trust anchor at index n-1.
*/
public final X509Certificate[] validate(X509Certificate[] chain,
Collection<X509Certificate> otherCerts, Object parameter)
throws CertificateException {
return validate(chain, otherCerts, Collections.emptyList(), null,
parameter);
}
/**
* Validate the given certificate chain.
*
* @param chain the target certificate chain
* @param otherCerts a Collection of additional X509Certificates that
* could be helpful for path building (or null)
* @param responseList a List of zero or more byte arrays, each
* one being a DER-encoded OCSP response (per RFC 6960). Entries
* in the List must match the order of the certificates in the
* chain parameter. It is possible that fewer responses may be
* in the list than are elements in {@code chain} and a missing
* response for a matching element in {@code chain} can be
* represented with a zero-length byte array.
* @param constraints algorithm constraints for certification path
* processing
* @param parameter an additional parameter object to pass specific data.
* This parameter object maybe one of the two below:
* 1) TLS_SERVER variant validators, where it must be non null and
* the name of the TLS key exchange algorithm being used
* (see JSSE X509TrustManager specification).
* 2) {@code Timestamp} object from a signed JAR file.
* @return a non-empty chain that was used to validate the path. The
* end entity cert is at index 0, the trust anchor at index n-1.
*/
public final X509Certificate[] validate(X509Certificate[] chain,
Collection<X509Certificate> otherCerts,
List<byte[]> responseList,
AlgorithmConstraints constraints,
Object parameter) throws CertificateException {
chain = engineValidate(chain, otherCerts, responseList, constraints,
parameter);
// omit EE extension check if EE cert is also trust anchor
if (chain.length > 1) {
// EndEntityChecker does not need to check unresolved critical
// extensions when validating with a TYPE_PKIX Validator.
// A TYPE_PKIX Validator will already have run checks on all
// certs' extensions, including checks by any PKIXCertPathCheckers
// included in the PKIXParameters, so the extra checks would be
// redundant.
boolean checkUnresolvedCritExts =
(type == TYPE_PKIX) ? false : true;
endEntityChecker.check(chain[0], parameter,
checkUnresolvedCritExts);
}
return chain;
}
abstract X509Certificate[] engineValidate(X509Certificate[] chain,
Collection<X509Certificate> otherCerts,
List<byte[]> responseList,
AlgorithmConstraints constraints,
Object parameter) throws CertificateException;
/**
* Returns an immutable Collection of the X509Certificates this instance
* uses as trust anchors.
*/
public abstract Collection<X509Certificate> getTrustedCertificates();
/**
* Set the date to be used for subsequent validations. NOTE that
* this is not a supported API, it is provided to simplify
* writing tests only.
*
* @deprecated
*/
@Deprecated
public void setValidationDate(Date validationDate) {
this.validationDate = validationDate;
}
}

View file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2002, 2012, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.validator;
import java.security.cert.*;
/**
* ValidatorException thrown by the Validator. It has optional fields that
* allow better error diagnostics.
*
* @author Andreas Sterbenz
*/
public class ValidatorException extends CertificateException {
private static final long serialVersionUID = -2836879718282292155L;
public static final Object T_NO_TRUST_ANCHOR =
"No trusted certificate found";
public static final Object T_EE_EXTENSIONS =
"End entity certificate extension check failed";
public static final Object T_CA_EXTENSIONS =
"CA certificate extension check failed";
public static final Object T_CERT_EXPIRED =
"Certificate expired";
public static final Object T_SIGNATURE_ERROR =
"Certificate signature validation failed";
public static final Object T_NAME_CHAINING =
"Certificate chaining error";
public static final Object T_ALGORITHM_DISABLED =
"Certificate signature algorithm disabled";
public static final Object T_UNTRUSTED_CERT =
"Untrusted certificate";
private Object type;
private X509Certificate cert;
public ValidatorException(String msg) {
super(msg);
}
public ValidatorException(String msg, Throwable cause) {
super(msg);
initCause(cause);
}
public ValidatorException(Object type) {
this(type, null);
}
public ValidatorException(Object type, X509Certificate cert) {
super((String)type);
this.type = type;
this.cert = cert;
}
public ValidatorException(Object type, X509Certificate cert,
Throwable cause) {
this(type, cert);
initCause(cause);
}
public ValidatorException(String msg, Object type, X509Certificate cert) {
super(msg);
this.type = type;
this.cert = cert;
}
public ValidatorException(String msg, Object type, X509Certificate cert,
Throwable cause) {
this(msg, type, cert);
initCause(cause);
}
/**
* Get the type of the failure (one of the T_XXX constants), if
* available. This may be helpful when designing a user interface.
*/
public Object getErrorType() {
return type;
}
/**
* Get the certificate causing the exception, if available.
*/
public X509Certificate getErrorCertificate() {
return cert;
}
}