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
26package sun.security.provider.certpath;
27
28import java.util.*;
29import java.io.IOException;
30
31import java.security.cert.Certificate;
32import java.security.cert.CertificateException;
33import java.security.cert.CertPathValidatorException;
34import java.security.cert.PKIXCertPathChecker;
35import java.security.cert.PKIXReason;
36import java.security.cert.PolicyNode;
37import java.security.cert.PolicyQualifierInfo;
38import java.security.cert.X509Certificate;
39
40import sun.security.util.Debug;
41import sun.security.x509.CertificatePoliciesExtension;
42import sun.security.x509.PolicyConstraintsExtension;
43import sun.security.x509.PolicyMappingsExtension;
44import sun.security.x509.CertificatePolicyMap;
45import sun.security.x509.PKIXExtensions;
46import sun.security.x509.PolicyInformation;
47import sun.security.x509.X509CertImpl;
48import 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 */
58class 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}