/*
* 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.
*/
/**
* PolicyChecker is a <code>PKIXCertPathChecker</code> that checks policy
* information on a PKIX certificate, namely certificate policies, policy
* mappings, policy constraints and policy qualifiers.
*
* @since 1.4
* @author Yassir Elley
*/
private final int certPathLen;
private final boolean expPolicyRequired;
private final boolean polMappingInhibited;
private final boolean anyPolicyInhibited;
private final boolean rejectPolicyQualifiers;
private int explicitPolicy;
private int policyMapping;
private int inhibitAnyPolicy;
private int certIndex;
/**
* Constructs a Policy Checker.
*
* @param initialPolicies Set of initial policies
* @param certPathLen length of the certification path to be checked
* @param expPolicyRequired true if explicit policy is required
* @param polMappingInhibited true if policy mapping is inhibited
* @param anyPolicyInhibited true if the ANY_POLICY OID should be inhibited
* @param rejectPolicyQualifiers true if pol qualifiers are to be rejected
* @param rootNode the initial root node of the valid policy tree
*/
boolean expPolicyRequired, boolean polMappingInhibited,
boolean anyPolicyInhibited, boolean rejectPolicyQualifiers,
{
if (initialPolicies.isEmpty()) {
// if no initialPolicies are specified by user, set
// initPolicies to be anyPolicy by default
} else {
}
this.certPathLen = certPathLen;
this.expPolicyRequired = expPolicyRequired;
this.anyPolicyInhibited = anyPolicyInhibited;
init(false);
}
/**
* Initializes the internal state of the checker from parameters
* specified in the constructor
*
* @param forward a boolean indicating whether this checker should
* be initialized capable of building in the forward direction
* @exception CertPathValidatorException Exception thrown if user
* wants to enable forward checking and forward checking is not supported.
*/
if (forward) {
throw new CertPathValidatorException
("forward checking not supported");
}
certIndex = 1;
}
/**
* Checks if forward checking is supported. Forward checking refers
* to the ability of the PKIXCertPathChecker to perform its checks
* when presented with certificates in the forward direction (from
* target to anchor).
*
* @return true if forward checking is supported, false otherwise
*/
public boolean isForwardCheckingSupported() {
return false;
}
/**
* Gets an immutable Set of the OID strings for the extensions that
* the PKIXCertPathChecker supports (i.e. recognizes, is able to
* process), or null if no extensions are
* supported. All OID strings that a PKIXCertPathChecker might
* possibly be able to process should be included.
*
* @return the Set of extensions supported by this PKIXCertPathChecker,
* or null if no extensions are supported
*/
if (supportedExts == null) {
}
return supportedExts;
}
/**
* Performs the policy processing checks on the certificate using its
* internal state.
*
* @param cert the Certificate to be processed
* @param unresCritExts the unresolved critical extensions
* @exception CertPathValidatorException Exception thrown if
* the certificate does not verify.
*/
throws CertPathValidatorException
{
// now do the policy checks
}
}
/**
* Internal method to run through all the checks.
*
* @param currCert the certificate to be processed
* @exception CertPathValidatorException Exception thrown if
* the certificate does not verify
*/
throws CertPathValidatorException
{
+ "...");
+ certIndex);
+ "explicitPolicy = " + explicitPolicy);
+ "policyMapping = " + policyMapping);
+ "inhibitAnyPolicy = " + inhibitAnyPolicy);
+ "policyTree = " + rootNode);
}
try {
} catch (CertificateException ce) {
throw new CertPathValidatorException(ce);
}
if (!finalCert) {
}
certIndex++;
+ "explicitPolicy = " + explicitPolicy);
+ "policyMapping = " + policyMapping);
+ "inhibitAnyPolicy = " + inhibitAnyPolicy);
+ "policyTree = " + rootNode);
}
}
/**
* Merges the specified explicitPolicy value with the
* requireExplicitPolicy field of the <code>PolicyConstraints</code>
* extension obtained from the certificate. An explicitPolicy
* value of -1 implies no constraint.
*
* @param explicitPolicy an integer which indicates if a non-null
* valid policy tree is required
* @param currCert the Certificate to be processed
* @param finalCert a boolean indicating whether currCert is
* the final cert in the cert path
* @return returns the new explicitPolicy value
* @exception CertPathValidatorException Exception thrown if an error
* occurs
*/
boolean finalCert) throws CertPathValidatorException
{
}
try {
if (polConstExt == null)
return explicitPolicy;
+ "require Index from cert = " + require);
}
if (!finalCert) {
if (require != -1) {
}
}
} else {
if (require == 0)
}
} catch (Exception e) {
+ "unexpected exception");
e.printStackTrace();
}
throw new CertPathValidatorException(e);
}
return explicitPolicy;
}
/**
* Merges the specified policyMapping value with the
* inhibitPolicyMapping field of the <code>PolicyConstraints</code>
* extension obtained from the certificate. A policyMapping
* value of -1 implies no constraint.
*
* @param policyMapping an integer which indicates if policy mapping
* is inhibited
* @param currCert the Certificate to be processed
* @return returns the new policyMapping value
* @exception CertPathValidatorException Exception thrown if an error
* occurs
*/
throws CertPathValidatorException
{
}
try {
if (polConstExt == null)
return policyMapping;
+ "inhibit Index from cert = " + inhibit);
if (inhibit != -1) {
}
}
} catch (Exception e) {
+ "unexpected exception");
e.printStackTrace();
}
throw new CertPathValidatorException(e);
}
return policyMapping;
}
/**
* Merges the specified inhibitAnyPolicy value with the
* SkipCerts value of the InhibitAnyPolicy
* extension obtained from the certificate.
*
* @param inhibitAnyPolicy an integer which indicates whether
* "any-policy" is considered a match
* @param currCert the Certificate to be processed
* @return returns the new inhibitAnyPolicy value
* @exception CertPathValidatorException Exception thrown if an error
* occurs
*/
{
}
try {
if (inhAnyPolExt == null)
return inhibitAnyPolicy;
+ "skipCerts Index from cert = " + skipCerts);
if (skipCerts != -1) {
if (skipCerts < inhibitAnyPolicy) {
}
}
} catch (Exception e) {
+ "unexpected exception");
e.printStackTrace();
}
throw new CertPathValidatorException(e);
}
return inhibitAnyPolicy;
}
/**
* Processes certificate policies in the certificate.
*
* @param certIndex the index of the certificate
* @param initPolicies the initial policies required by the user
* @param explicitPolicy an integer which indicates if a non-null
* valid policy tree is required
* @param policyMapping an integer which indicates if policy
* mapping is inhibited
* @param inhibitAnyPolicy an integer which indicates whether
* "any-policy" is considered a match
* @param rejectPolicyQualifiers a boolean indicating whether the
* user wants to reject policies that have qualifiers
* @param origRootNode the root node of the valid policy tree
* @param currCert the Certificate to be processed
* @param finalCert a boolean indicating whether currCert is the final
* cert in the cert path
* @return the root node of the valid policy tree after modification
* @exception CertPathValidatorException Exception thrown if an
* error occurs while processing policies.
*/
throws CertPathValidatorException
{
boolean policiesCritical = false;
if (origRootNode == null)
else
// retrieve policyOIDs from currCert
// PKIX: Section 6.1.3: Step (d)
+ "policiesCritical = " + policiesCritical);
try {
} catch (IOException ioe) {
throw new CertPathValidatorException("Exception while "
+ "retrieving policyOIDs", ioe);
}
+ "rejectPolicyQualifiers = " + rejectPolicyQualifiers);
boolean foundAnyPolicy = false;
// process each policy in cert
foundAnyPolicy = true;
} else {
// PKIX: Section 6.1.3: Step (d)(1)
+ "processing policy: " + curPolicy);
// retrieve policy qualifiers from cert
// reject cert if we find critical policy qualifiers and
// the policyQualifiersRejected flag is set in the params
throw new CertPathValidatorException(
"critical policy qualifiers present in certificate",
}
// PKIX: Section 6.1.3: Step (d)(1)(i)
if (!foundMatch) {
// PKIX: Section 6.1.3: Step (d)(1)(ii)
pQuals, true);
}
}
}
// PKIX: Section 6.1.3: Step (d)(2)
if (foundAnyPolicy) {
if ((inhibitAnyPolicy > 0) ||
+ "processing policy: " + ANY_POLICY);
}
true);
}
}
// PKIX: Section 6.1.3: Step (d)(3)
}
} else if (currCertPolicies == null) {
+ "no policies present in cert");
// PKIX: Section 6.1.3: Step (e)
}
// We delay PKIX: Section 6.1.3: Step (f) to the end
// because the code that follows may delete some nodes
// resulting in a null tree
if (!finalCert) {
// PKIX: Section 6.1.4: Steps (a)-(b)
}
}
// At this point, we optimize the PKIX algorithm by
// removing those nodes which would later have
// been removed by PKIX: Section 6.1.5: Step (g)(iii)
&& (currCertPolicies != null)) {
// PKIX: Section 6.1.5: Step (g)(iii)
// rewrite anyPolicy leaf nodes (see method comments)
}
}
if (finalCert) {
// PKIX: Section 6.1.5: Steps (a) and (b)
}
// PKIX: Section 6.1.3: Step (f)
// verify that either explicit policy is greater than 0 or
// the valid_policy_tree is not equal to NULL
throw new CertPathValidatorException
("non-null policy tree required and policy tree is null",
}
return rootNode;
}
/**
* Rewrite leaf nodes at the end of validation as described in RFC 3280
* section 6.1.5: Step (g)(iii). Leaf nodes with anyPolicy are replaced
* by nodes explicitly representing initial policies not already
* represented by leaf nodes.
*
* This method should only be called when processing the final cert
* and if the policy tree is not null and initial policies is not
* anyPolicy.
*
* @param certIndex the depth of the tree
* @param initPolicies Set of user specified initial policies
* @param rootNode the root of the policy tree
*/
return rootNode;
}
// see if there are any initialPolicies not represented by leaf nodes
}
// we deleted the anyPolicy node and have nothing to re-add,
// so we need to prune the tree
}
} else {
}
}
return rootNode;
}
/**
* Finds the policy nodes of depth (certIndex-1) where curPolicy
* is in the expected policy set and creates a new child node
* appropriately. If matchAny is true, then a value of ANY_POLICY
* in the expected policy set will match any curPolicy. If matchAny
* is false, then the expected policy set must exactly contain the
* curPolicy to be considered a match. This method returns a boolean
* value indicating whether a match was found.
*
* @param certIndex the index of the certificate whose policy is
* being processed
* @param policiesCritical a boolean indicating whether the certificate
* policies extension is critical
* @param rejectPolicyQualifiers a boolean indicating whether the
* user wants to reject policies that have qualifiers
* @param rootNode the root node of the valid policy tree
* @param curPolicy a String representing the policy being processed
* @param pQuals the policy qualifiers of the policy being processed or an
* empty Set if there are no qualifiers
* @param matchAny a boolean indicating whether a value of ANY_POLICY
* in the expected policy set will be considered a match
* @return a boolean indicating whether a match was found
* @exception CertPathValidatorException Exception thrown if error occurs.
*/
boolean policiesCritical, boolean rejectPolicyQualifiers,
boolean matchAny) throws CertPathValidatorException
{
boolean foundMatch = false;
+ matchAny);
// find matching parents
// for each matching parent, extend policy tree
foundMatch = true;
// do step 2
+ "expected policy set already appears in "
+ "child node");
continue parentExplicitPolicies;
}
}
curNode = new PolicyNodeImpl
policiesCritical, expPols, false);
}
} else {
curNode = new PolicyNodeImpl
policiesCritical, curExpPols, false);
}
}
return foundMatch;
}
/**
* Processes policy mappings in the certificate.
*
* @param currCert the Certificate to be processed
* @param certIndex the index of the current certificate
* @param policyMapping an integer which indicates if policy
* mapping is inhibited
* @param rootNode the root node of the valid policy tree
* @param policiesCritical a boolean indicating if the certificate policies
* extension is critical
* @param anyQuals the qualifiers associated with ANY-POLICY, or an empty
* Set if there are no qualifiers associated with ANY-POLICY
* @return the root node of the valid policy tree after modification
* @exception CertPathValidatorException exception thrown if an error
* occurs while processing policy mappings
*/
throws CertPathValidatorException
{
if (polMappingsExt == null)
return rootNode;
+ "inside policyMapping check");
try {
} catch (IOException e) {
+ "mapping exception");
e.printStackTrace();
}
throw new CertPathValidatorException("Exception while checking "
+ "mapping", e);
}
boolean childDeleted = false;
+ "issuerDomain = " + issuerDomain);
+ "subjectDomain = " + subjectDomain);
}
throw new CertPathValidatorException
("encountered an issuerDomainPolicy of ANY_POLICY",
}
throw new CertPathValidatorException
("encountered a subjectDomainPolicy of ANY_POLICY",
}
if (!validNodes.isEmpty()) {
} else if (policyMapping == 0) {
+ "() before deleting: policy tree = "
+ rootNode);
childDeleted = true;
+ "() after deleting: policy tree = "
+ rootNode);
}
}
} else { // no node of depth i has a valid policy
policiesCritical, expPols, true);
}
}
}
}
if (childDeleted) {
}
}
return rootNode;
}
/**
* Removes those nodes which do not intersect with the initial policies
* specified by the user.
*
* @param rootNode the root node of the valid policy tree
* @param certIndex the index of the certificate being processed
* @param initPolicies the Set of policies required by the user
* @param currCertPolicies the CertificatePoliciesExtension of the
* certificate being processed
* @returns the root node of the valid policy tree after modification
* @exception CertPathValidatorException Exception thrown if error occurs.
*/
throws CertPathValidatorException
{
try {
} catch (IOException ioe) {
throw new CertPathValidatorException("Exception while "
+ "retrieving policyOIDs", ioe);
}
boolean childDeleted = false;
+ "processing policy second time: " + curPolicy);
+ "before deleting: policy tree = " + rootNode);
childDeleted = true;
+ "after deleting: policy tree = " + rootNode);
}
}
}
}
if (childDeleted) {
}
}
return rootNode;
}
/**
* Gets the root node of the valid policy tree, or null if the
* valid policy tree is null. Marks each node of the returned tree
* immutable and thread-safe.
*
* @returns the root node of the valid policy tree, or null if
* the valid policy tree is null
*/
return null;
else {
return policyTree;
}
}
}