History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/provider/certpath/PolicyChecker.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/provider/certpath/PolicyChecker.java+926−0
@@ -0,0 +1,926 @@
1+/*
2+ * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.security.provider.certpath;
27+
28+import java.util.*;
29+import java.io.IOException;
30+
31+import java.security.cert.Certificate;
32+import java.security.cert.CertificateException;
33+import java.security.cert.CertPathValidatorException;
34+import java.security.cert.PKIXCertPathChecker;
35+import java.security.cert.PKIXReason;
36+import java.security.cert.PolicyNode;
37+import java.security.cert.PolicyQualifierInfo;
38+import java.security.cert.X509Certificate;
39+
40+import sun.security.util.Debug;
41+import sun.security.x509.CertificatePoliciesExtension;
42+import sun.security.x509.PolicyConstraintsExtension;
43+import sun.security.x509.PolicyMappingsExtension;
44+import sun.security.x509.CertificatePolicyMap;
45+import sun.security.x509.PKIXExtensions;
46+import sun.security.x509.PolicyInformation;
47+import sun.security.x509.X509CertImpl;
48+import sun.security.x509.InhibitAnyPolicyExtension;
49+
50+/**
51+ * PolicyChecker is a <code>PKIXCertPathChecker</code> that checks policy
52+ * information on a PKIX certificate, namely certificate policies, policy
53+ * mappings, policy constraints and policy qualifiers.
54+ *
55+ * @since 1.4
56+ * @author Yassir Elley
57+ */
58+class PolicyChecker extends PKIXCertPathChecker {
59+
60+ private final Set<String> initPolicies;
61+ private final int certPathLen;
62+ private final boolean expPolicyRequired;
63+ private final boolean polMappingInhibited;
64+ private final boolean anyPolicyInhibited;
65+ private final boolean rejectPolicyQualifiers;
66+ private PolicyNodeImpl rootNode;
67+ private int explicitPolicy;
68+ private int policyMapping;
69+ private int inhibitAnyPolicy;
70+ private int certIndex;
71+
72+ private Set<String> supportedExts;
73+
74+ private static final Debug debug = Debug.getInstance("certpath");
75+ static final String ANY_POLICY = "2.5.29.32.0";
76+
77+ /**
78+ * Constructs a Policy Checker.
79+ *
80+ * @param initialPolicies Set of initial policies
81+ * @param certPathLen length of the certification path to be checked
82+ * @param expPolicyRequired true if explicit policy is required
83+ * @param polMappingInhibited true if policy mapping is inhibited
84+ * @param anyPolicyInhibited true if the ANY_POLICY OID should be inhibited
85+ * @param rejectPolicyQualifiers true if pol qualifiers are to be rejected
86+ * @param rootNode the initial root node of the valid policy tree
87+ */
88+ PolicyChecker(Set<String> initialPolicies, int certPathLen,
89+ boolean expPolicyRequired, boolean polMappingInhibited,
90+ boolean anyPolicyInhibited, boolean rejectPolicyQualifiers,
91+ PolicyNodeImpl rootNode) throws CertPathValidatorException
92+ {
93+ if (initialPolicies.isEmpty()) {
94+ // if no initialPolicies are specified by user, set
95+ // initPolicies to be anyPolicy by default
96+ this.initPolicies = new HashSet<String>(1);
97+ this.initPolicies.add(ANY_POLICY);
98+ } else {
99+ this.initPolicies = new HashSet<String>(initialPolicies);
100+ }
101+ this.certPathLen = certPathLen;
102+ this.expPolicyRequired = expPolicyRequired;
103+ this.polMappingInhibited = polMappingInhibited;
104+ this.anyPolicyInhibited = anyPolicyInhibited;
105+ this.rejectPolicyQualifiers = rejectPolicyQualifiers;
106+ this.rootNode = rootNode;
107+ init(false);
108+ }
109+
110+ /**
111+ * Initializes the internal state of the checker from parameters
112+ * specified in the constructor
113+ *
114+ * @param forward a boolean indicating whether this checker should
115+ * be initialized capable of building in the forward direction
116+ * @exception CertPathValidatorException Exception thrown if user
117+ * wants to enable forward checking and forward checking is not supported.
118+ */
119+ public void init(boolean forward) throws CertPathValidatorException {
120+ if (forward) {
121+ throw new CertPathValidatorException
122+ ("forward checking not supported");
123+ }
124+
125+ certIndex = 1;
126+ explicitPolicy = (expPolicyRequired ? 0 : certPathLen + 1);
127+ policyMapping = (polMappingInhibited ? 0 : certPathLen + 1);
128+ inhibitAnyPolicy = (anyPolicyInhibited ? 0 : certPathLen + 1);
129+ }
130+
131+ /**
132+ * Checks if forward checking is supported. Forward checking refers
133+ * to the ability of the PKIXCertPathChecker to perform its checks
134+ * when presented with certificates in the forward direction (from
135+ * target to anchor).
136+ *
137+ * @return true if forward checking is supported, false otherwise
138+ */
139+ public boolean isForwardCheckingSupported() {
140+ return false;
141+ }
142+
143+ /**
144+ * Gets an immutable Set of the OID strings for the extensions that
145+ * the PKIXCertPathChecker supports (i.e. recognizes, is able to
146+ * process), or null if no extensions are
147+ * supported. All OID strings that a PKIXCertPathChecker might
148+ * possibly be able to process should be included.
149+ *
150+ * @return the Set of extensions supported by this PKIXCertPathChecker,
151+ * or null if no extensions are supported
152+ */
153+ public Set<String> getSupportedExtensions() {
154+ if (supportedExts == null) {
155+ supportedExts = new HashSet<String>();
156+ supportedExts.add(PKIXExtensions.CertificatePolicies_Id.toString());
157+ supportedExts.add(PKIXExtensions.PolicyMappings_Id.toString());
158+ supportedExts.add(PKIXExtensions.PolicyConstraints_Id.toString());
159+ supportedExts.add(PKIXExtensions.InhibitAnyPolicy_Id.toString());
160+ supportedExts = Collections.unmodifiableSet(supportedExts);
161+ }
162+ return supportedExts;
163+ }
164+
165+ /**
166+ * Performs the policy processing checks on the certificate using its
167+ * internal state.
168+ *
169+ * @param cert the Certificate to be processed
170+ * @param unresCritExts the unresolved critical extensions
171+ * @exception CertPathValidatorException Exception thrown if
172+ * the certificate does not verify.
173+ */
174+ public void check(Certificate cert, Collection<String> unresCritExts)
175+ throws CertPathValidatorException
176+ {
177+ // now do the policy checks
178+ checkPolicy((X509Certificate) cert);
179+
180+ if (unresCritExts != null && !unresCritExts.isEmpty()) {
181+ unresCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString());
182+ unresCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString());
183+ unresCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString());
184+ unresCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString());
185+ }
186+ }
187+
188+ /**
189+ * Internal method to run through all the checks.
190+ *
191+ * @param currCert the certificate to be processed
192+ * @exception CertPathValidatorException Exception thrown if
193+ * the certificate does not verify
194+ */
195+ private void checkPolicy(X509Certificate currCert)
196+ throws CertPathValidatorException
197+ {
198+ String msg = "certificate policies";
199+ if (debug != null) {
200+ debug.println("PolicyChecker.checkPolicy() ---checking " + msg
201+ + "...");
202+ debug.println("PolicyChecker.checkPolicy() certIndex = "
203+ + certIndex);
204+ debug.println("PolicyChecker.checkPolicy() BEFORE PROCESSING: "
205+ + "explicitPolicy = " + explicitPolicy);
206+ debug.println("PolicyChecker.checkPolicy() BEFORE PROCESSING: "
207+ + "policyMapping = " + policyMapping);
208+ debug.println("PolicyChecker.checkPolicy() BEFORE PROCESSING: "
209+ + "inhibitAnyPolicy = " + inhibitAnyPolicy);
210+ debug.println("PolicyChecker.checkPolicy() BEFORE PROCESSING: "
211+ + "policyTree = " + rootNode);
212+ }
213+
214+ X509CertImpl currCertImpl = null;
215+ try {
216+ currCertImpl = X509CertImpl.toImpl(currCert);
217+ } catch (CertificateException ce) {
218+ throw new CertPathValidatorException(ce);
219+ }
220+
221+ boolean finalCert = (certIndex == certPathLen);
222+
223+ rootNode = processPolicies(certIndex, initPolicies, explicitPolicy,
224+ policyMapping, inhibitAnyPolicy, rejectPolicyQualifiers, rootNode,
225+ currCertImpl, finalCert);
226+
227+ if (!finalCert) {
228+ explicitPolicy = mergeExplicitPolicy(explicitPolicy, currCertImpl,
229+ finalCert);
230+ policyMapping = mergePolicyMapping(policyMapping, currCertImpl);
231+ inhibitAnyPolicy = mergeInhibitAnyPolicy(inhibitAnyPolicy,
232+ currCertImpl);
233+ }
234+
235+ certIndex++;
236+
237+ if (debug != null) {
238+ debug.println("PolicyChecker.checkPolicy() AFTER PROCESSING: "
239+ + "explicitPolicy = " + explicitPolicy);
240+ debug.println("PolicyChecker.checkPolicy() AFTER PROCESSING: "
241+ + "policyMapping = " + policyMapping);
242+ debug.println("PolicyChecker.checkPolicy() AFTER PROCESSING: "
243+ + "inhibitAnyPolicy = " + inhibitAnyPolicy);
244+ debug.println("PolicyChecker.checkPolicy() AFTER PROCESSING: "
245+ + "policyTree = " + rootNode);
246+ debug.println("PolicyChecker.checkPolicy() " + msg + " verified");
247+ }
248+ }
249+
250+ /**
251+ * Merges the specified explicitPolicy value with the
252+ * requireExplicitPolicy field of the <code>PolicyConstraints</code>
253+ * extension obtained from the certificate. An explicitPolicy
254+ * value of -1 implies no constraint.
255+ *
256+ * @param explicitPolicy an integer which indicates if a non-null
257+ * valid policy tree is required
258+ * @param currCert the Certificate to be processed
259+ * @param finalCert a boolean indicating whether currCert is
260+ * the final cert in the cert path
261+ * @return returns the new explicitPolicy value
262+ * @exception CertPathValidatorException Exception thrown if an error
263+ * occurs
264+ */
265+ static int mergeExplicitPolicy(int explicitPolicy, X509CertImpl currCert,
266+ boolean finalCert) throws CertPathValidatorException
267+ {
268+ if ((explicitPolicy > 0) && !X509CertImpl.isSelfIssued(currCert)) {
269+ explicitPolicy--;
270+ }
271+
272+ try {
273+ PolicyConstraintsExtension polConstExt
274+ = currCert.getPolicyConstraintsExtension();
275+ if (polConstExt == null)
276+ return explicitPolicy;
277+ int require = ((Integer)
278+ polConstExt.get(PolicyConstraintsExtension.REQUIRE)).intValue();
279+ if (debug != null) {
280+ debug.println("PolicyChecker.mergeExplicitPolicy() "
281+ + "require Index from cert = " + require);
282+ }
283+ if (!finalCert) {
284+ if (require != -1) {
285+ if ((explicitPolicy == -1) || (require < explicitPolicy)) {
286+ explicitPolicy = require;
287+ }
288+ }
289+ } else {
290+ if (require == 0)
291+ explicitPolicy = require;
292+ }
293+ } catch (Exception e) {
294+ if (debug != null) {
295+ debug.println("PolicyChecker.mergeExplicitPolicy "
296+ + "unexpected exception");
297+ e.printStackTrace();
298+ }
299+ throw new CertPathValidatorException(e);
300+ }
301+
302+ return explicitPolicy;
303+ }
304+
305+ /**
306+ * Merges the specified policyMapping value with the
307+ * inhibitPolicyMapping field of the <code>PolicyConstraints</code>
308+ * extension obtained from the certificate. A policyMapping
309+ * value of -1 implies no constraint.
310+ *
311+ * @param policyMapping an integer which indicates if policy mapping
312+ * is inhibited
313+ * @param currCert the Certificate to be processed
314+ * @return returns the new policyMapping value
315+ * @exception CertPathValidatorException Exception thrown if an error
316+ * occurs
317+ */
318+ static int mergePolicyMapping(int policyMapping, X509CertImpl currCert)
319+ throws CertPathValidatorException
320+ {
321+ if ((policyMapping > 0) && !X509CertImpl.isSelfIssued(currCert)) {
322+ policyMapping--;
323+ }
324+
325+ try {
326+ PolicyConstraintsExtension polConstExt
327+ = currCert.getPolicyConstraintsExtension();
328+ if (polConstExt == null)
329+ return policyMapping;
330+
331+ int inhibit = ((Integer)
332+ polConstExt.get(PolicyConstraintsExtension.INHIBIT)).intValue();
333+ if (debug != null)
334+ debug.println("PolicyChecker.mergePolicyMapping() "
335+ + "inhibit Index from cert = " + inhibit);
336+
337+ if (inhibit != -1) {
338+ if ((policyMapping == -1) || (inhibit < policyMapping)) {
339+ policyMapping = inhibit;
340+ }
341+ }
342+ } catch (Exception e) {
343+ if (debug != null) {
344+ debug.println("PolicyChecker.mergePolicyMapping "
345+ + "unexpected exception");
346+ e.printStackTrace();
347+ }
348+ throw new CertPathValidatorException(e);
349+ }
350+
351+ return policyMapping;
352+ }
353+
354+ /**
355+ * Merges the specified inhibitAnyPolicy value with the
356+ * SkipCerts value of the InhibitAnyPolicy
357+ * extension obtained from the certificate.
358+ *
359+ * @param inhibitAnyPolicy an integer which indicates whether
360+ * "any-policy" is considered a match
361+ * @param currCert the Certificate to be processed
362+ * @return returns the new inhibitAnyPolicy value
363+ * @exception CertPathValidatorException Exception thrown if an error
364+ * occurs
365+ */
366+ static int mergeInhibitAnyPolicy(int inhibitAnyPolicy,
367+ X509CertImpl currCert) throws CertPathValidatorException
368+ {
369+ if ((inhibitAnyPolicy > 0) && !X509CertImpl.isSelfIssued(currCert)) {
370+ inhibitAnyPolicy--;
371+ }
372+
373+ try {
374+ InhibitAnyPolicyExtension inhAnyPolExt = (InhibitAnyPolicyExtension)
375+ currCert.getExtension(PKIXExtensions.InhibitAnyPolicy_Id);
376+ if (inhAnyPolExt == null)
377+ return inhibitAnyPolicy;
378+
379+ int skipCerts = ((Integer)
380+ inhAnyPolExt.get(InhibitAnyPolicyExtension.SKIP_CERTS)).intValue();
381+ if (debug != null)
382+ debug.println("PolicyChecker.mergeInhibitAnyPolicy() "
383+ + "skipCerts Index from cert = " + skipCerts);
384+
385+ if (skipCerts != -1) {
386+ if (skipCerts < inhibitAnyPolicy) {
387+ inhibitAnyPolicy = skipCerts;
388+ }
389+ }
390+ } catch (Exception e) {
391+ if (debug != null) {
392+ debug.println("PolicyChecker.mergeInhibitAnyPolicy "
393+ + "unexpected exception");
394+ e.printStackTrace();
395+ }
396+ throw new CertPathValidatorException(e);
397+ }
398+
399+ return inhibitAnyPolicy;
400+ }
401+
402+ /**
403+ * Processes certificate policies in the certificate.
404+ *
405+ * @param certIndex the index of the certificate
406+ * @param initPolicies the initial policies required by the user
407+ * @param explicitPolicy an integer which indicates if a non-null
408+ * valid policy tree is required
409+ * @param policyMapping an integer which indicates if policy
410+ * mapping is inhibited
411+ * @param inhibitAnyPolicy an integer which indicates whether
412+ * "any-policy" is considered a match
413+ * @param rejectPolicyQualifiers a boolean indicating whether the
414+ * user wants to reject policies that have qualifiers
415+ * @param origRootNode the root node of the valid policy tree
416+ * @param currCert the Certificate to be processed
417+ * @param finalCert a boolean indicating whether currCert is the final
418+ * cert in the cert path
419+ * @return the root node of the valid policy tree after modification
420+ * @exception CertPathValidatorException Exception thrown if an
421+ * error occurs while processing policies.
422+ */
423+ static PolicyNodeImpl processPolicies(int certIndex, Set<String> initPolicies,
424+ int explicitPolicy, int policyMapping, int inhibitAnyPolicy,
425+ boolean rejectPolicyQualifiers, PolicyNodeImpl origRootNode,
426+ X509CertImpl currCert, boolean finalCert)
427+ throws CertPathValidatorException
428+ {
429+ boolean policiesCritical = false;
430+ List<PolicyInformation> policyInfo;
431+ PolicyNodeImpl rootNode = null;
432+ Set<PolicyQualifierInfo> anyQuals = new HashSet<PolicyQualifierInfo>();
433+
434+ if (origRootNode == null)
435+ rootNode = null;
436+ else
437+ rootNode = origRootNode.copyTree();
438+
439+ // retrieve policyOIDs from currCert
440+ CertificatePoliciesExtension currCertPolicies
441+ = currCert.getCertificatePoliciesExtension();
442+
443+ // PKIX: Section 6.1.3: Step (d)
444+ if ((currCertPolicies != null) && (rootNode != null)) {
445+ policiesCritical = currCertPolicies.isCritical();
446+ if (debug != null)
447+ debug.println("PolicyChecker.processPolicies() "
448+ + "policiesCritical = " + policiesCritical);
449+
450+ try {
451+ policyInfo = (List<PolicyInformation>)
452+ currCertPolicies.get(CertificatePoliciesExtension.POLICIES);
453+ } catch (IOException ioe) {
454+ throw new CertPathValidatorException("Exception while "
455+ + "retrieving policyOIDs", ioe);
456+ }
457+
458+ if (debug != null)
459+ debug.println("PolicyChecker.processPolicies() "
460+ + "rejectPolicyQualifiers = " + rejectPolicyQualifiers);
461+
462+ boolean foundAnyPolicy = false;
463+
464+ // process each policy in cert
465+ for (PolicyInformation curPolInfo : policyInfo) {
466+ String curPolicy =
467+ curPolInfo.getPolicyIdentifier().getIdentifier().toString();
468+
469+ if (curPolicy.equals(ANY_POLICY)) {
470+ foundAnyPolicy = true;
471+ anyQuals = curPolInfo.getPolicyQualifiers();
472+ } else {
473+ // PKIX: Section 6.1.3: Step (d)(1)
474+ if (debug != null)
475+ debug.println("PolicyChecker.processPolicies() "
476+ + "processing policy: " + curPolicy);
477+
478+ // retrieve policy qualifiers from cert
479+ Set<PolicyQualifierInfo> pQuals =
480+ curPolInfo.getPolicyQualifiers();
481+
482+ // reject cert if we find critical policy qualifiers and
483+ // the policyQualifiersRejected flag is set in the params
484+ if (!pQuals.isEmpty() && rejectPolicyQualifiers &&
485+ policiesCritical) {
486+ throw new CertPathValidatorException(
487+ "critical policy qualifiers present in certificate",
488+ null, null, -1, PKIXReason.INVALID_POLICY);
489+ }
490+
491+ // PKIX: Section 6.1.3: Step (d)(1)(i)
492+ boolean foundMatch = processParents(certIndex,
493+ policiesCritical, rejectPolicyQualifiers, rootNode,
494+ curPolicy, pQuals, false);
495+
496+ if (!foundMatch) {
497+ // PKIX: Section 6.1.3: Step (d)(1)(ii)
498+ processParents(certIndex, policiesCritical,
499+ rejectPolicyQualifiers, rootNode, curPolicy,
500+ pQuals, true);
501+ }
502+ }
503+ }
504+
505+ // PKIX: Section 6.1.3: Step (d)(2)
506+ if (foundAnyPolicy) {
507+ if ((inhibitAnyPolicy > 0) ||
508+ (!finalCert && X509CertImpl.isSelfIssued(currCert))) {
509+ if (debug != null) {
510+ debug.println("PolicyChecker.processPolicies() "
511+ + "processing policy: " + ANY_POLICY);
512+ }
513+ processParents(certIndex, policiesCritical,
514+ rejectPolicyQualifiers, rootNode, ANY_POLICY, anyQuals,
515+ true);
516+ }
517+ }
518+
519+ // PKIX: Section 6.1.3: Step (d)(3)
520+ rootNode.prune(certIndex);
521+ if (!rootNode.getChildren().hasNext()) {
522+ rootNode = null;
523+ }
524+ } else if (currCertPolicies == null) {
525+ if (debug != null)
526+ debug.println("PolicyChecker.processPolicies() "
527+ + "no policies present in cert");
528+ // PKIX: Section 6.1.3: Step (e)
529+ rootNode = null;
530+ }
531+
532+ // We delay PKIX: Section 6.1.3: Step (f) to the end
533+ // because the code that follows may delete some nodes
534+ // resulting in a null tree
535+ if (rootNode != null) {
536+ if (!finalCert) {
537+ // PKIX: Section 6.1.4: Steps (a)-(b)
538+ rootNode = processPolicyMappings(currCert, certIndex,
539+ policyMapping, rootNode, policiesCritical, anyQuals);
540+ }
541+ }
542+
543+ // At this point, we optimize the PKIX algorithm by
544+ // removing those nodes which would later have
545+ // been removed by PKIX: Section 6.1.5: Step (g)(iii)
546+
547+ if ((rootNode != null) && (!initPolicies.contains(ANY_POLICY))
548+ && (currCertPolicies != null)) {
549+ rootNode = removeInvalidNodes(rootNode, certIndex,
550+ initPolicies, currCertPolicies);
551+
552+ // PKIX: Section 6.1.5: Step (g)(iii)
553+ if ((rootNode != null) && finalCert) {
554+ // rewrite anyPolicy leaf nodes (see method comments)
555+ rootNode = rewriteLeafNodes(certIndex, initPolicies, rootNode);
556+ }
557+ }
558+
559+
560+ if (finalCert) {
561+ // PKIX: Section 6.1.5: Steps (a) and (b)
562+ explicitPolicy = mergeExplicitPolicy(explicitPolicy, currCert,
563+ finalCert);
564+ }
565+
566+ // PKIX: Section 6.1.3: Step (f)
567+ // verify that either explicit policy is greater than 0 or
568+ // the valid_policy_tree is not equal to NULL
569+
570+ if ((explicitPolicy == 0) && (rootNode == null)) {
571+ throw new CertPathValidatorException
572+ ("non-null policy tree required and policy tree is null",
573+ null, null, -1, PKIXReason.INVALID_POLICY);
574+ }
575+
576+ return rootNode;
577+ }
578+
579+ /**
580+ * Rewrite leaf nodes at the end of validation as described in RFC 3280
581+ * section 6.1.5: Step (g)(iii). Leaf nodes with anyPolicy are replaced
582+ * by nodes explicitly representing initial policies not already
583+ * represented by leaf nodes.
584+ *
585+ * This method should only be called when processing the final cert
586+ * and if the policy tree is not null and initial policies is not
587+ * anyPolicy.
588+ *
589+ * @param certIndex the depth of the tree
590+ * @param initPolicies Set of user specified initial policies
591+ * @param rootNode the root of the policy tree
592+ */
593+ private static PolicyNodeImpl rewriteLeafNodes(int certIndex,
594+ Set<String> initPolicies, PolicyNodeImpl rootNode) {
595+ Set<PolicyNodeImpl> anyNodes =
596+ rootNode.getPolicyNodesValid(certIndex, ANY_POLICY);
597+ if (anyNodes.isEmpty()) {
598+ return rootNode;
599+ }
600+ PolicyNodeImpl anyNode = anyNodes.iterator().next();
601+ PolicyNodeImpl parentNode = (PolicyNodeImpl)anyNode.getParent();
602+ parentNode.deleteChild(anyNode);
603+ // see if there are any initialPolicies not represented by leaf nodes
604+ Set<String> initial = new HashSet<String>(initPolicies);
605+ for (PolicyNodeImpl node : rootNode.getPolicyNodes(certIndex)) {
606+ initial.remove(node.getValidPolicy());
607+ }
608+ if (initial.isEmpty()) {
609+ // we deleted the anyPolicy node and have nothing to re-add,
610+ // so we need to prune the tree
611+ rootNode.prune(certIndex);
612+ if (rootNode.getChildren().hasNext() == false) {
613+ rootNode = null;
614+ }
615+ } else {
616+ boolean anyCritical = anyNode.isCritical();
617+ Set<PolicyQualifierInfo> anyQualifiers =
618+ anyNode.getPolicyQualifiers();
619+ for (String policy : initial) {
620+ Set<String> expectedPolicies = Collections.singleton(policy);
621+ PolicyNodeImpl node = new PolicyNodeImpl(parentNode, policy,
622+ anyQualifiers, anyCritical, expectedPolicies, false);
623+ }
624+ }
625+ return rootNode;
626+ }
627+
628+ /**
629+ * Finds the policy nodes of depth (certIndex-1) where curPolicy
630+ * is in the expected policy set and creates a new child node
631+ * appropriately. If matchAny is true, then a value of ANY_POLICY
632+ * in the expected policy set will match any curPolicy. If matchAny
633+ * is false, then the expected policy set must exactly contain the
634+ * curPolicy to be considered a match. This method returns a boolean
635+ * value indicating whether a match was found.
636+ *
637+ * @param certIndex the index of the certificate whose policy is
638+ * being processed
639+ * @param policiesCritical a boolean indicating whether the certificate
640+ * policies extension is critical
641+ * @param rejectPolicyQualifiers a boolean indicating whether the
642+ * user wants to reject policies that have qualifiers
643+ * @param rootNode the root node of the valid policy tree
644+ * @param curPolicy a String representing the policy being processed
645+ * @param pQuals the policy qualifiers of the policy being processed or an
646+ * empty Set if there are no qualifiers
647+ * @param matchAny a boolean indicating whether a value of ANY_POLICY
648+ * in the expected policy set will be considered a match
649+ * @return a boolean indicating whether a match was found
650+ * @exception CertPathValidatorException Exception thrown if error occurs.
651+ */
652+ private static boolean processParents(int certIndex,
653+ boolean policiesCritical, boolean rejectPolicyQualifiers,
654+ PolicyNodeImpl rootNode, String curPolicy,
655+ Set<PolicyQualifierInfo> pQuals,
656+ boolean matchAny) throws CertPathValidatorException
657+ {
658+ boolean foundMatch = false;
659+
660+ if (debug != null)
661+ debug.println("PolicyChecker.processParents(): matchAny = "
662+ + matchAny);
663+
664+ // find matching parents
665+ Set<PolicyNodeImpl> parentNodes =
666+ rootNode.getPolicyNodesExpected(certIndex - 1,
667+ curPolicy, matchAny);
668+
669+ // for each matching parent, extend policy tree
670+ for (PolicyNodeImpl curParent : parentNodes) {
671+ if (debug != null)
672+ debug.println("PolicyChecker.processParents() "
673+ + "found parent:\n" + curParent.asString());
674+
675+ foundMatch = true;
676+ String curParPolicy = curParent.getValidPolicy();
677+
678+ PolicyNodeImpl curNode = null;
679+ Set<String> curExpPols = null;
680+
681+ if (curPolicy.equals(ANY_POLICY)) {
682+ // do step 2
683+ Set<String> parExpPols = curParent.getExpectedPolicies();
684+ parentExplicitPolicies:
685+ for (String curParExpPol : parExpPols) {
686+
687+ Iterator<PolicyNodeImpl> childIter =
688+ curParent.getChildren();
689+ while (childIter.hasNext()) {
690+ PolicyNodeImpl childNode = childIter.next();
691+ String childPolicy = childNode.getValidPolicy();
692+ if (curParExpPol.equals(childPolicy)) {
693+ if (debug != null)
694+ debug.println(childPolicy + " in parent's "
695+ + "expected policy set already appears in "
696+ + "child node");
697+ continue parentExplicitPolicies;
698+ }
699+ }
700+
701+ Set<String> expPols = new HashSet<String>();
702+ expPols.add(curParExpPol);
703+
704+ curNode = new PolicyNodeImpl
705+ (curParent, curParExpPol, pQuals,
706+ policiesCritical, expPols, false);
707+ }
708+ } else {
709+ curExpPols = new HashSet<String>();
710+ curExpPols.add(curPolicy);
711+
712+ curNode = new PolicyNodeImpl
713+ (curParent, curPolicy, pQuals,
714+ policiesCritical, curExpPols, false);
715+ }
716+ }
717+
718+ return foundMatch;
719+ }
720+
721+ /**
722+ * Processes policy mappings in the certificate.
723+ *
724+ * @param currCert the Certificate to be processed
725+ * @param certIndex the index of the current certificate
726+ * @param policyMapping an integer which indicates if policy
727+ * mapping is inhibited
728+ * @param rootNode the root node of the valid policy tree
729+ * @param policiesCritical a boolean indicating if the certificate policies
730+ * extension is critical
731+ * @param anyQuals the qualifiers associated with ANY-POLICY, or an empty
732+ * Set if there are no qualifiers associated with ANY-POLICY
733+ * @return the root node of the valid policy tree after modification
734+ * @exception CertPathValidatorException exception thrown if an error
735+ * occurs while processing policy mappings
736+ */
737+ private static PolicyNodeImpl processPolicyMappings(X509CertImpl currCert,
738+ int certIndex, int policyMapping, PolicyNodeImpl rootNode,
739+ boolean policiesCritical, Set<PolicyQualifierInfo> anyQuals)
740+ throws CertPathValidatorException
741+ {
742+ PolicyMappingsExtension polMappingsExt
743+ = currCert.getPolicyMappingsExtension();
744+
745+ if (polMappingsExt == null)
746+ return rootNode;
747+
748+ if (debug != null)
749+ debug.println("PolicyChecker.processPolicyMappings() "
750+ + "inside policyMapping check");
751+
752+ List<CertificatePolicyMap> maps = null;
753+ try {
754+ maps = (List<CertificatePolicyMap>)polMappingsExt.get
755+ (PolicyMappingsExtension.MAP);
756+ } catch (IOException e) {
757+ if (debug != null) {
758+ debug.println("PolicyChecker.processPolicyMappings() "
759+ + "mapping exception");
760+ e.printStackTrace();
761+ }
762+ throw new CertPathValidatorException("Exception while checking "
763+ + "mapping", e);
764+ }
765+
766+ boolean childDeleted = false;
767+ for (int j = 0; j < maps.size(); j++) {
768+ CertificatePolicyMap polMap = maps.get(j);
769+ String issuerDomain
770+ = polMap.getIssuerIdentifier().getIdentifier().toString();
771+ String subjectDomain
772+ = polMap.getSubjectIdentifier().getIdentifier().toString();
773+ if (debug != null) {
774+ debug.println("PolicyChecker.processPolicyMappings() "
775+ + "issuerDomain = " + issuerDomain);
776+ debug.println("PolicyChecker.processPolicyMappings() "
777+ + "subjectDomain = " + subjectDomain);
778+ }
779+
780+ if (issuerDomain.equals(ANY_POLICY)) {
781+ throw new CertPathValidatorException
782+ ("encountered an issuerDomainPolicy of ANY_POLICY",
783+ null, null, -1, PKIXReason.INVALID_POLICY);
784+ }
785+
786+ if (subjectDomain.equals(ANY_POLICY)) {
787+ throw new CertPathValidatorException
788+ ("encountered a subjectDomainPolicy of ANY_POLICY",
789+ null, null, -1, PKIXReason.INVALID_POLICY);
790+ }
791+
792+ Set<PolicyNodeImpl> validNodes =
793+ rootNode.getPolicyNodesValid(certIndex, issuerDomain);
794+ if (!validNodes.isEmpty()) {
795+ for (PolicyNodeImpl curNode : validNodes) {
796+ if ((policyMapping > 0) || (policyMapping == -1)) {
797+ curNode.addExpectedPolicy(subjectDomain);
798+ } else if (policyMapping == 0) {
799+ PolicyNodeImpl parentNode =
800+ (PolicyNodeImpl) curNode.getParent();
801+ if (debug != null)
802+ debug.println("PolicyChecker.processPolicyMappings"
803+ + "() before deleting: policy tree = "
804+ + rootNode);
805+ parentNode.deleteChild(curNode);
806+ childDeleted = true;
807+ if (debug != null)
808+ debug.println("PolicyChecker.processPolicyMappings"
809+ + "() after deleting: policy tree = "
810+ + rootNode);
811+ }
812+ }
813+ } else { // no node of depth i has a valid policy
814+ if ((policyMapping > 0) || (policyMapping == -1)) {
815+ Set<PolicyNodeImpl> validAnyNodes =
816+ rootNode.getPolicyNodesValid(certIndex, ANY_POLICY);
817+ for (PolicyNodeImpl curAnyNode : validAnyNodes) {
818+ PolicyNodeImpl curAnyNodeParent =
819+ (PolicyNodeImpl) curAnyNode.getParent();
820+
821+ Set<String> expPols = new HashSet<String>();
822+ expPols.add(subjectDomain);
823+
824+ PolicyNodeImpl curNode = new PolicyNodeImpl
825+ (curAnyNodeParent, issuerDomain, anyQuals,
826+ policiesCritical, expPols, true);
827+ }
828+ }
829+ }
830+ }
831+
832+ if (childDeleted) {
833+ rootNode.prune(certIndex);
834+ if (!rootNode.getChildren().hasNext()) {
835+ if (debug != null)
836+ debug.println("setting rootNode to null");
837+ rootNode = null;
838+ }
839+ }
840+
841+ return rootNode;
842+ }
843+
844+ /**
845+ * Removes those nodes which do not intersect with the initial policies
846+ * specified by the user.
847+ *
848+ * @param rootNode the root node of the valid policy tree
849+ * @param certIndex the index of the certificate being processed
850+ * @param initPolicies the Set of policies required by the user
851+ * @param currCertPolicies the CertificatePoliciesExtension of the
852+ * certificate being processed
853+ * @returns the root node of the valid policy tree after modification
854+ * @exception CertPathValidatorException Exception thrown if error occurs.
855+ */
856+ private static PolicyNodeImpl removeInvalidNodes(PolicyNodeImpl rootNode,
857+ int certIndex, Set<String> initPolicies,
858+ CertificatePoliciesExtension currCertPolicies)
859+ throws CertPathValidatorException
860+ {
861+ List<PolicyInformation> policyInfo = null;
862+ try {
863+ policyInfo = (List<PolicyInformation>)
864+ currCertPolicies.get(CertificatePoliciesExtension.POLICIES);
865+ } catch (IOException ioe) {
866+ throw new CertPathValidatorException("Exception while "
867+ + "retrieving policyOIDs", ioe);
868+ }
869+
870+ boolean childDeleted = false;
871+ for (PolicyInformation curPolInfo : policyInfo) {
872+ String curPolicy =
873+ curPolInfo.getPolicyIdentifier().getIdentifier().toString();
874+
875+ if (debug != null)
876+ debug.println("PolicyChecker.processPolicies() "
877+ + "processing policy second time: " + curPolicy);
878+
879+ Set<PolicyNodeImpl> validNodes =
880+ rootNode.getPolicyNodesValid(certIndex, curPolicy);
881+ for (PolicyNodeImpl curNode : validNodes) {
882+ PolicyNodeImpl parentNode = (PolicyNodeImpl)curNode.getParent();
883+ if (parentNode.getValidPolicy().equals(ANY_POLICY)) {
884+ if ((!initPolicies.contains(curPolicy)) &&
885+ (!curPolicy.equals(ANY_POLICY))) {
886+ if (debug != null)
887+ debug.println("PolicyChecker.processPolicies() "
888+ + "before deleting: policy tree = " + rootNode);
889+ parentNode.deleteChild(curNode);
890+ childDeleted = true;
891+ if (debug != null)
892+ debug.println("PolicyChecker.processPolicies() "
893+ + "after deleting: policy tree = " + rootNode);
894+ }
895+ }
896+ }
897+ }
898+
899+ if (childDeleted) {
900+ rootNode.prune(certIndex);
901+ if (!rootNode.getChildren().hasNext()) {
902+ rootNode = null;
903+ }
904+ }
905+
906+ return rootNode;
907+ }
908+
909+ /**
910+ * Gets the root node of the valid policy tree, or null if the
911+ * valid policy tree is null. Marks each node of the returned tree
912+ * immutable and thread-safe.
913+ *
914+ * @returns the root node of the valid policy tree, or null if
915+ * the valid policy tree is null
916+ */
917+ PolicyNode getPolicyTree() {
918+ if (rootNode == null)
919+ return null;
920+ else {
921+ PolicyNodeImpl policyTree = rootNode.copyTree();
922+ policyTree.setImmutable();
923+ return policyTree;
924+ }
925+ }
926+}