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