/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* This class represents a forward builder, which is able to retrieve
* matching certificates from CertStores and verify a particular certificate
* against a ForwardState.
*
* @since 1.4
* @author Yassir Elley
* @author Sean Mullan
*/
private boolean searchAllCertStores = true;
private boolean onlyEECert = false;
/**
* Initialize the builder with the input parameters.
*
* @param params the parameter set used to build a certification path
*/
boolean onlyEECert)
{
super(buildParams, targetSubjectDN);
// populate sets of trusted certificates and subject DNs
if (trustedCert != null) {
} else {
}
}
this.onlyEECert = onlyEECert;
}
/**
* Retrieves all certs from the specified CertStores that satisfy the
* requirements specified in the parameters and the current
* PKIX state (name constraints, policy constraints, etc).
*
* @param currentState the current state.
* Must be an instance of <code>ForwardState</code>
* @param certStores list of CertStores
*/
{
}
/*
* We store certs in a Set because we don't want duplicates.
* As each cert is added, it is sorted based on the PKIXCertComparator
* algorithm.
*/
/*
* Only look for EE certs if search has just started.
*/
}
return certs;
}
/*
* Retrieves all end-entity certificates which satisfy constraints
* and requirements specified in the parameters and PKIX state.
*/
throws IOException {
}
/*
* Compose a certificate matching rule to filter out
* certs which don't satisfy constraints
*
* First, retrieve clone of current target cert constraints,
* and then add more selection criteria based on current validation
* state. Since selector never changes, cache local copy & reuse.
*/
if (eeSelector == null) {
/*
* Match on certificate validity date
*/
/*
* Policy processing optimizations
*/
if (buildParams.isExplicitPolicyRequired()) {
}
/*
* Require EE certs
*/
}
/* Retrieve matching EE certs from CertStores */
}
/**
* Retrieves all CA certificates which satisfy constraints
* and requirements specified in the parameters and PKIX state.
*/
throws IOException {
}
/*
* Compose a CertSelector to filter out
* certs which do not satisfy requirements.
*/
if (currentState.isInitial()) {
// no need to continue: this means we never can match a CA cert
return;
}
/* This means a CA is the target, so match on same stuff as
* getMatchingEECerts
*/
}
if (caTargetSelector == null) {
/*
* Since we don't check the validity period of trusted
* certificates, please don't set the certificate valid
* criterion unless the trusted certificate matching is
* completed.
*/
/*
* Policy processing optimizations
*/
}
} else {
if (caSelector == null) {
caSelector = new AdaptableX509CertSelector();
/*
* Since we don't check the validity period of trusted
* certificates, please don't set the certificate valid
* criterion unless the trusted certificate matching is
* completed.
*/
/*
* Policy processing optimizations
*/
}
/*
* Match on subject (issuer of previous cert)
*/
/*
* Match on subjectNamesTraversed (both DNs and AltNames)
* (checks that current cert's name constraints permit it
* to certify all the DNs and AltNames that have been traversed)
*/
/*
* Facilitate certification path construction with authority
* key identifier and subject key identifier.
*/
/*
* check the validity period
*/
sel = caSelector;
}
/*
* For compatibility, conservatively, we don't check the path
* length constraint of trusted anchors. Please don't set the
* basic constraints criterion unless the trusted certificate
* matching is completed.
*/
+ "found matching trust anchor");
}
return;
}
}
}
/*
* The trusted certificate matching is completed. We need to match
* on certificate validity date.
*/
/*
* Require CA certs with a pathLenConstraint that allows
* at least as many CA certs that have already been traversed
*/
/*
* If we have already traversed as many CA certs as the maxPathLength
* will allow us to, then we don't bother looking through these
* certificate pairs. If maxPathLength has a value of -1, this
* means it is unconstrained, so we always look through the
* certificate pairs.
*/
if (currentState.isInitial() ||
{
return;
}
}
// check for AuthorityInformationAccess extension
}
}
numCerts + " CA certs");
}
}
/**
* Download Certificates from the given AIA and add them to the
* specified Collection.
*/
return false;
}
return false;
}
boolean add = false;
try {
add = true;
if (!searchAllCertStores) {
return true;
}
}
} catch (CertStoreException cse) {
}
continue;
}
}
return add;
}
/**
* This inner class compares 2 PKIX certificates according to which
* should be tried first when building a path from the target.
* The preference order is as follows:
*
* Given trusted certificate(s):
* Subject:ou=D,ou=C,o=B,c=A
*
* Preference order for current cert:
*
* 1) Issuer matches a trusted subject
* Issuer: ou=D,ou=C,o=B,c=A
*
* 2) Issuer is a descendant of a trusted subject (in order of
* number of links to the trusted subject)
* a) Issuer: ou=E,ou=D,ou=C,o=B,c=A [links=1]
* b) Issuer: ou=F,ou=E,ou=D,ou=C,ou=B,c=A [links=2]
*
* 3) Issuer is an ancestor of a trusted subject (in order of number of
* links to the trusted subject)
* a) Issuer: ou=C,o=B,c=A [links=1]
* b) Issuer: o=B,c=A [links=2]
*
* 4) Issuer is in the same namespace as a trusted subject (in order of
* number of links to the trusted subject)
* a) Issuer: ou=G,ou=C,o=B,c=A [links=2]
* b) Issuer: ou=H,o=B,c=A [links=3]
*
* 5) Issuer is an ancestor of certificate subject (in order of number
* of links to the certificate subject)
* a) Issuer: ou=K,o=J,c=A
* Subject: ou=L,ou=K,o=J,c=A
* b) Issuer: o=J,c=A
* Subject: ou=L,ou=K,0=J,c=A
*
* 6) Any other certificates
*/
this.trustedSubjectDNs = trustedSubjectDNs;
}
/**
* @param oCert1 First X509Certificate to be compared
* @param oCert2 Second X509Certificate to be compared
* @return -1 if oCert1 is preferable to oCert2, or
* if oCert1 and oCert2 are equally preferable (in this
* case it doesn't matter which is preferable, but we don't
* return 0 because the comparator would behave strangely
* when used in a SortedSet).
* 1 if oCert2 is preferable to oCert1
* 0 if oCert1.equals(oCert2). We only return 0 if the
* certs are equal so that this comparator behaves
* correctly when used in a SortedSet.
* @throws ClassCastException if either argument is not of type
* X509Certificate
*/
// if certs are the same, return 0
}
/* If one cert's issuer matches a trusted subject, then it is
* preferable.
*/
}
}
return -1;
} else if (m1) {
return -1;
} else if (m2) {
return 1;
}
/* If one cert's issuer is a naming descendant of a trusted subject,
* then it is preferable, in order of increasing naming distance.
*/
}
int distanceTto1 =
int distanceTto2 =
}
if (distanceTto1 == distanceTto2) {
return -1;
return -1;
return 1;
} else if (distanceTto1 < distanceTto2) {
return -1;
} else { // distanceTto1 > distanceTto2
return 1;
}
}
}
/* If one cert's issuer is a naming ancestor of a trusted subject,
* then it is preferable, in order of increasing naming distance.
*/
}
}
if (distanceTto1 == distanceTto2) {
return -1;
return -1;
return 1;
} else if (distanceTto1 > distanceTto2) {
return -1;
} else {
return 1;
}
}
}
/* If one cert's issuer is in the same namespace as a trusted
* subject, then it is preferable, in order of increasing naming
* distance.
*/
}
}
}
return 1;
} else { // hopsTto1 < hopsTto2
return -1;
}
return 1;
} else {
return -1;
}
}
}
/* If one cert's issuer is an ancestor of that cert's subject,
* then it is preferable, in order of increasing naming distance.
*/
}
}
}
if (distanceStoI2 > distanceStoI1) {
return -1;
} else if (distanceStoI2 < distanceStoI1) {
return 1;
}
/* Otherwise, certs are equally preferable.
*/
}
return -1;
}
}
/**
* Verifies a matching certificate.
*
* This method executes the validation steps in the PKIX path
* validation algorithm <draft-ietf-pkix-new-part1-08.txt> which were
* not satisfied by the selection criteria used by getCertificates()
* to find the certs and only the steps that can be executed in a
* forward direction (target to trust anchor). Those steps that can
* only be executed in a reverse direction are deferred until the
* complete path has been built.
*
* Trust anchor certs are not validated, but are used to verify the
* signature and revocation status of the previous cert.
*
* If the last certificate is being verified (the one whose subject
* matches the target subject, then steps in 6.1.4 of the PKIX
* Certification Path Validation algorithm are NOT executed,
* regardless of whether or not the last cert is an end-entity
* cert or not. This allows callers to certify CA certs as
* well as EE certs.
*
* @param cert the certificate to be verified
* @param currentState the current state against which the cert is verified
* @param certPathList the certPathList generated thus far
*/
{
}
// Don't bother to verify untrusted certificate more.
/*
* check for looping - abort a loop if
* ((we encounter the same certificate twice) AND
* ((policyMappingInhibited = true) OR (no policy mapping
* extensions can be found between the occurences of the same
* certificate)))
*/
if (certPathList != null) {
boolean policyMappingFound = false;
if (policyMappingsExt != null) {
policyMappingFound = true;
}
}
if ((buildParams.isPolicyMappingInhibited()) ||
(!policyMappingFound)) {
}
throw new CertPathValidatorException("loop detected");
}
}
}
}
/* check if trusted cert */
/* we don't perform any validation of the trusted cert */
if (!isTrustedCert) {
/*
* Check CRITICAL private extensions for user checkers that
* support forward checking (forwardCheckers) and remove
* ones we know how to check.
*/
if (unresCritExts == null) {
}
}
/*
* Remove extensions from user checkers that don't support
* forward checking. After this step, we will have removed
* all extensions that all user checkers are capable of
* processing.
*/
if (!checker.isForwardCheckingSupported()) {
if (supportedExts != null) {
}
}
}
/*
* Look at the remaining extensions and remove any ones we know how
* to check. If there are any left, throw an exception!
*/
if (!unresCritExts.isEmpty()) {
if (!unresCritExts.isEmpty())
throw new CertPathValidatorException
}
}
/*
* if this is the target certificate (init=true), then we are
* not able to do any more verification, so just return
*/
return;
}
/* we don't perform any validation of the trusted cert */
if (!isTrustedCert) {
/* Make sure this is a CA cert */
throw new CertificateException("cert is NOT a CA cert");
}
/*
* Check keyUsage extension
*/
}
/*
* the following checks are performed even when the cert
* is a trusted cert, since we are only extracting the
* subjectDN, and publicKey from the cert
* in order to verify a previous cert
*/
/*
* Check revocation for the previous cert
*/
if (buildParams.isRevocationEnabled()) {
// first off, see if this cert can authorize revocation...
// And then check to be sure no key requiring key parameters
// has been encountered
if (!currState.keyParamsNeeded())
// If all that checks out, we can check the
// revocation status of the cert. Otherwise,
// we'll just wait until the end.
cert.getPublicKey(),
true);
}
}
/*
* Check signature only if no key requiring key parameters has been
* encountered.
*/
if (!currState.keyParamsNeeded()) {
}
}
/**
* Verifies whether the input certificate completes the path.
* Checks the cert against each trust anchor that was specified, in order,
* and returns true as soon as it finds a valid anchor.
* Returns true if the cert matches a trust anchor specified as a
* certificate or if the cert verifies with a trust anchor that
* was specified as a trusted {pubkey, caname} pair. Returns false if none
* of the trust anchors are valid for this cert.
*
* @param cert the certificate to test
* @return a boolean value indicating whether the cert completes the path.
*/
this.trustAnchor = anchor;
return true;
} else {
continue;
}
} else {
// the cert itself is a trust anchor
this.trustAnchor = anchor;
return true;
}
// else, it is a self-issued certificate of the anchor
}
continue;
}
}
/* Check revocation if it is enabled */
if (buildParams.isRevocationEnabled()) {
try {
} catch (CertPathValidatorException cpve) {
}
continue;
}
}
/*
* Check signature
*/
try {
// NOTE: the DSA public key in the buildParams may lack
// parameters, yet there is no key to inherit the parameters
// from. This is probably such a rare case that it is not worth
// trying to detect the situation earlier.
} catch (InvalidKeyException ike) {
+ "DSA key found");
}
continue;
} catch (Exception e){
"unexpected exception");
e.printStackTrace();
}
continue;
}
this.trustAnchor = anchor;
return true;
}
return false;
}
/** Adds the certificate to the certPathList
*
* @param cert the certificate to be added
* @param certPathList the certification path list
*/
}
/** Removes final certificate from the certPathList
*
* @param certPathList the certification path list
*/
}
}