mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue