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/ForwardBuilder.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/provider/certpath/ForwardBuilder.java+930−0
@@ -0,0 +1,930 @@
1/*
2 * Copyright (c) 2000, 2011, 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.io.IOException;
29import java.util.*;
30
31import java.security.GeneralSecurityException;
32import java.security.InvalidKeyException;
33import java.security.cert.Certificate;
34import java.security.cert.CertificateException;
35import java.security.cert.CertPathValidatorException;
36import java.security.cert.PKIXReason;
37import java.security.cert.CertStore;
38import java.security.cert.CertStoreException;
39import java.security.cert.PKIXBuilderParameters;
40import java.security.cert.PKIXCertPathChecker;
41import java.security.cert.TrustAnchor;
42import java.security.cert.X509Certificate;
43import java.security.cert.X509CertSelector;
44import javax.security.auth.x500.X500Principal;
45
46import sun.security.util.Debug;
47import sun.security.util.DerOutputStream;
48import sun.security.x509.AccessDescription;
49import sun.security.x509.AuthorityInfoAccessExtension;
50import sun.security.x509.PKIXExtensions;
51import sun.security.x509.PolicyMappingsExtension;
52import sun.security.x509.X500Name;
53import sun.security.x509.X509CertImpl;
54import sun.security.x509.X509CRLImpl;
55import sun.security.x509.AuthorityKeyIdentifierExtension;
56import sun.security.x509.KeyIdentifier;
57import sun.security.x509.SubjectKeyIdentifierExtension;
58import sun.security.x509.SerialNumber;
59import sun.security.x509.GeneralNames;
60import sun.security.x509.GeneralName;
61import sun.security.x509.GeneralNameInterface;
62import java.math.BigInteger;
63
64/**
65 * This class represents a forward builder, which is able to retrieve
66 * matching certificates from CertStores and verify a particular certificate
67 * against a ForwardState.
68 *
69 * @since 1.4
70 * @author Yassir Elley
71 * @author Sean Mullan
72 */
73class ForwardBuilder extends Builder {
74
75 private static final Debug debug = Debug.getInstance("certpath");
76 private final Set<X509Certificate> trustedCerts;
77 private final Set<X500Principal> trustedSubjectDNs;
78 private final Set<TrustAnchor> trustAnchors;
79 private X509CertSelector eeSelector;
80 private AdaptableX509CertSelector caSelector;
81 private X509CertSelector caTargetSelector;
82 TrustAnchor trustAnchor;
83 private Comparator<X509Certificate> comparator;
84 private boolean searchAllCertStores = true;
85 private boolean onlyEECert = false;
86
87 /**
88 * Initialize the builder with the input parameters.
89 *
90 * @param params the parameter set used to build a certification path
91 */
92 ForwardBuilder(PKIXBuilderParameters buildParams,
93 X500Principal targetSubjectDN, boolean searchAllCertStores,
94 boolean onlyEECert)
95 {
96 super(buildParams, targetSubjectDN);
97
98 // populate sets of trusted certificates and subject DNs
99 trustAnchors = buildParams.getTrustAnchors();
100 trustedCerts = new HashSet<X509Certificate>(trustAnchors.size());
101 trustedSubjectDNs = new HashSet<X500Principal>(trustAnchors.size());
102 for (TrustAnchor anchor : trustAnchors) {
103 X509Certificate trustedCert = anchor.getTrustedCert();
104 if (trustedCert != null) {
105 trustedCerts.add(trustedCert);
106 trustedSubjectDNs.add(trustedCert.getSubjectX500Principal());
107 } else {
108 trustedSubjectDNs.add(anchor.getCA());
109 }
110 }
111 comparator = new PKIXCertComparator(trustedSubjectDNs);
112 this.searchAllCertStores = searchAllCertStores;
113 this.onlyEECert = onlyEECert;
114 }
115
116 /**
117 * Retrieves all certs from the specified CertStores that satisfy the
118 * requirements specified in the parameters and the current
119 * PKIX state (name constraints, policy constraints, etc).
120 *
121 * @param currentState the current state.
122 * Must be an instance of <code>ForwardState</code>
123 * @param certStores list of CertStores
124 */
125 Collection<X509Certificate> getMatchingCerts
126 (State currentState, List<CertStore> certStores)
127 throws CertStoreException, CertificateException, IOException
128 {
129 if (debug != null) {
130 debug.println("ForwardBuilder.getMatchingCerts()...");
131 }
132
133 ForwardState currState = (ForwardState) currentState;
134
135 /*
136 * We store certs in a Set because we don't want duplicates.
137 * As each cert is added, it is sorted based on the PKIXCertComparator
138 * algorithm.
139 */
140 Set<X509Certificate> certs = new TreeSet<X509Certificate>(comparator);
141
142 /*
143 * Only look for EE certs if search has just started.
144 */
145 if (currState.isInitial()) {
146 getMatchingEECerts(currState, certStores, certs);
147 }
148 getMatchingCACerts(currState, certStores, certs);
149
150 return certs;
151 }
152
153 /*
154 * Retrieves all end-entity certificates which satisfy constraints
155 * and requirements specified in the parameters and PKIX state.
156 */
157 private void getMatchingEECerts(ForwardState currentState,
158 List<CertStore> certStores, Collection<X509Certificate> eeCerts)
159 throws IOException {
160
161 if (debug != null) {
162 debug.println("ForwardBuilder.getMatchingEECerts()...");
163 }
164 /*
165 * Compose a certificate matching rule to filter out
166 * certs which don't satisfy constraints
167 *
168 * First, retrieve clone of current target cert constraints,
169 * and then add more selection criteria based on current validation
170 * state. Since selector never changes, cache local copy & reuse.
171 */
172 if (eeSelector == null) {
173 eeSelector = (X509CertSelector) targetCertConstraints.clone();
174
175 /*
176 * Match on certificate validity date
177 */
178 eeSelector.setCertificateValid(date);
179
180 /*
181 * Policy processing optimizations
182 */
183 if (buildParams.isExplicitPolicyRequired()) {
184 eeSelector.setPolicy(getMatchingPolicies());
185 }
186 /*
187 * Require EE certs
188 */
189 eeSelector.setBasicConstraints(-2);
190 }
191
192 /* Retrieve matching EE certs from CertStores */
193 addMatchingCerts(eeSelector, certStores, eeCerts, searchAllCertStores);
194 }
195
196 /**
197 * Retrieves all CA certificates which satisfy constraints
198 * and requirements specified in the parameters and PKIX state.
199 */
200 private void getMatchingCACerts(ForwardState currentState,
201 List<CertStore> certStores, Collection<X509Certificate> caCerts)
202 throws IOException {
203
204 if (debug != null) {
205 debug.println("ForwardBuilder.getMatchingCACerts()...");
206 }
207 int initialSize = caCerts.size();
208
209 /*
210 * Compose a CertSelector to filter out
211 * certs which do not satisfy requirements.
212 */
213 X509CertSelector sel = null;
214
215 if (currentState.isInitial()) {
216 if (targetCertConstraints.getBasicConstraints() == -2) {
217 // no need to continue: this means we never can match a CA cert
218 return;
219 }
220
221 /* This means a CA is the target, so match on same stuff as
222 * getMatchingEECerts
223 */
224 if (debug != null) {
225 debug.println("ForwardBuilder.getMatchingCACerts(): ca is target");
226 }
227
228 if (caTargetSelector == null) {
229 caTargetSelector = (X509CertSelector)
230 targetCertConstraints.clone();
231
232 /*
233 * Since we don't check the validity period of trusted
234 * certificates, please don't set the certificate valid
235 * criterion unless the trusted certificate matching is
236 * completed.
237 */
238
239 /*
240 * Policy processing optimizations
241 */
242 if (buildParams.isExplicitPolicyRequired())
243 caTargetSelector.setPolicy(getMatchingPolicies());
244 }
245
246 sel = caTargetSelector;
247 } else {
248
249 if (caSelector == null) {
250 caSelector = new AdaptableX509CertSelector();
251
252 /*
253 * Since we don't check the validity period of trusted
254 * certificates, please don't set the certificate valid
255 * criterion unless the trusted certificate matching is
256 * completed.
257 */
258
259 /*
260 * Policy processing optimizations
261 */
262 if (buildParams.isExplicitPolicyRequired())
263 caSelector.setPolicy(getMatchingPolicies());
264 }
265
266 /*
267 * Match on subject (issuer of previous cert)
268 */
269 caSelector.setSubject(currentState.issuerDN);
270
271 /*
272 * Match on subjectNamesTraversed (both DNs and AltNames)
273 * (checks that current cert's name constraints permit it
274 * to certify all the DNs and AltNames that have been traversed)
275 */
276 CertPathHelper.setPathToNames
277 (caSelector, currentState.subjectNamesTraversed);
278
279 /*
280 * Facilitate certification path construction with authority
281 * key identifier and subject key identifier.
282 */
283 AuthorityKeyIdentifierExtension akidext =
284 currentState.cert.getAuthorityKeyIdentifierExtension();
285 caSelector.parseAuthorityKeyIdentifierExtension(akidext);
286
287 /*
288 * check the validity period
289 */
290 caSelector.setValidityPeriod(currentState.cert.getNotBefore(),
291 currentState.cert.getNotAfter());
292
293 sel = caSelector;
294 }
295
296 /*
297 * For compatibility, conservatively, we don't check the path
298 * length constraint of trusted anchors. Please don't set the
299 * basic constraints criterion unless the trusted certificate
300 * matching is completed.
301 */
302 sel.setBasicConstraints(-1);
303
304 for (X509Certificate trustedCert : trustedCerts) {
305 if (sel.match(trustedCert)) {
306 if (debug != null) {
307 debug.println("ForwardBuilder.getMatchingCACerts: "
308 + "found matching trust anchor");
309 }
310 if (caCerts.add(trustedCert) && !searchAllCertStores) {
311 return;
312 }
313 }
314 }
315
316 /*
317 * The trusted certificate matching is completed. We need to match
318 * on certificate validity date.
319 */
320 sel.setCertificateValid(date);
321
322 /*
323 * Require CA certs with a pathLenConstraint that allows
324 * at least as many CA certs that have already been traversed
325 */
326 sel.setBasicConstraints(currentState.traversedCACerts);
327
328 /*
329 * If we have already traversed as many CA certs as the maxPathLength
330 * will allow us to, then we don't bother looking through these
331 * certificate pairs. If maxPathLength has a value of -1, this
332 * means it is unconstrained, so we always look through the
333 * certificate pairs.
334 */
335 if (currentState.isInitial() ||
336 (buildParams.getMaxPathLength() == -1) ||
337 (buildParams.getMaxPathLength() > currentState.traversedCACerts))
338 {
339 if (addMatchingCerts(sel, certStores,
340 caCerts, searchAllCertStores) && !searchAllCertStores) {
341 return;
342 }
343 }
344
345 if (!currentState.isInitial() && Builder.USE_AIA) {
346 // check for AuthorityInformationAccess extension
347 AuthorityInfoAccessExtension aiaExt =
348 currentState.cert.getAuthorityInfoAccessExtension();
349 if (aiaExt != null) {
350 getCerts(aiaExt, caCerts);
351 }
352 }
353
354 if (debug != null) {
355 int numCerts = caCerts.size() - initialSize;
356 debug.println("ForwardBuilder.getMatchingCACerts: found " +
357 numCerts + " CA certs");
358 }
359 }
360
361 /**
362 * Download Certificates from the given AIA and add them to the
363 * specified Collection.
364 */
365 private boolean getCerts(AuthorityInfoAccessExtension aiaExt,
366 Collection<X509Certificate> certs) {
367 if (Builder.USE_AIA == false) {
368 return false;
369 }
370 List<AccessDescription> adList = aiaExt.getAccessDescriptions();
371 if (adList == null || adList.isEmpty()) {
372 return false;
373 }
374
375 boolean add = false;
376 for (AccessDescription ad : adList) {
377 CertStore cs = URICertStore.getInstance(ad);
378 try {
379 if (certs.addAll((Collection<X509Certificate>)
380 cs.getCertificates(caSelector))) {
381 add = true;
382 if (!searchAllCertStores) {
383 return true;
384 }
385 }
386 } catch (CertStoreException cse) {
387 if (debug != null) {
388 debug.println("exception getting certs from CertStore:");
389 cse.printStackTrace();
390 }
391 continue;
392 }
393 }
394 return add;
395 }
396
397 /**
398 * This inner class compares 2 PKIX certificates according to which
399 * should be tried first when building a path from the target.
400 * The preference order is as follows:
401 *
402 * Given trusted certificate(s):
403 * Subject:ou=D,ou=C,o=B,c=A
404 *
405 * Preference order for current cert:
406 *
407 * 1) Issuer matches a trusted subject
408 * Issuer: ou=D,ou=C,o=B,c=A
409 *
410 * 2) Issuer is a descendant of a trusted subject (in order of
411 * number of links to the trusted subject)
412 * a) Issuer: ou=E,ou=D,ou=C,o=B,c=A [links=1]
413 * b) Issuer: ou=F,ou=E,ou=D,ou=C,ou=B,c=A [links=2]
414 *
415 * 3) Issuer is an ancestor of a trusted subject (in order of number of
416 * links to the trusted subject)
417 * a) Issuer: ou=C,o=B,c=A [links=1]
418 * b) Issuer: o=B,c=A [links=2]
419 *
420 * 4) Issuer is in the same namespace as a trusted subject (in order of
421 * number of links to the trusted subject)
422 * a) Issuer: ou=G,ou=C,o=B,c=A [links=2]
423 * b) Issuer: ou=H,o=B,c=A [links=3]
424 *
425 * 5) Issuer is an ancestor of certificate subject (in order of number
426 * of links to the certificate subject)
427 * a) Issuer: ou=K,o=J,c=A
428 * Subject: ou=L,ou=K,o=J,c=A
429 * b) Issuer: o=J,c=A
430 * Subject: ou=L,ou=K,0=J,c=A
431 *
432 * 6) Any other certificates
433 */
434 static class PKIXCertComparator implements Comparator<X509Certificate> {
435
436 final static String METHOD_NME = "PKIXCertComparator.compare()";
437
438 private final Set<X500Principal> trustedSubjectDNs;
439
440 PKIXCertComparator(Set<X500Principal> trustedSubjectDNs) {
441 this.trustedSubjectDNs = trustedSubjectDNs;
442 }
443
444 /**
445 * @param oCert1 First X509Certificate to be compared
446 * @param oCert2 Second X509Certificate to be compared
447 * @return -1 if oCert1 is preferable to oCert2, or
448 * if oCert1 and oCert2 are equally preferable (in this
449 * case it doesn't matter which is preferable, but we don't
450 * return 0 because the comparator would behave strangely
451 * when used in a SortedSet).
452 * 1 if oCert2 is preferable to oCert1
453 * 0 if oCert1.equals(oCert2). We only return 0 if the
454 * certs are equal so that this comparator behaves
455 * correctly when used in a SortedSet.
456 * @throws ClassCastException if either argument is not of type
457 * X509Certificate
458 */
459 public int compare(X509Certificate oCert1, X509Certificate oCert2) {
460
461 // if certs are the same, return 0
462 if (oCert1.equals(oCert2)) return 0;
463
464 X500Principal cIssuer1 = oCert1.getIssuerX500Principal();
465 X500Principal cIssuer2 = oCert2.getIssuerX500Principal();
466 X500Name cIssuer1Name = X500Name.asX500Name(cIssuer1);
467 X500Name cIssuer2Name = X500Name.asX500Name(cIssuer2);
468
469 if (debug != null) {
470 debug.println(METHOD_NME + " o1 Issuer: " + cIssuer1);
471 debug.println(METHOD_NME + " o2 Issuer: " + cIssuer2);
472 }
473
474 /* If one cert's issuer matches a trusted subject, then it is
475 * preferable.
476 */
477 if (debug != null) {
478 debug.println(METHOD_NME + " MATCH TRUSTED SUBJECT TEST...");
479 }
480
481 boolean m1 = trustedSubjectDNs.contains(cIssuer1);
482 boolean m2 = trustedSubjectDNs.contains(cIssuer2);
483 if (debug != null) {
484 debug.println(METHOD_NME + " m1: " + m1);
485 debug.println(METHOD_NME + " m2: " + m2);
486 }
487 if (m1 && m2) {
488 return -1;
489 } else if (m1) {
490 return -1;
491 } else if (m2) {
492 return 1;
493 }
494
495 /* If one cert's issuer is a naming descendant of a trusted subject,
496 * then it is preferable, in order of increasing naming distance.
497 */
498 if (debug != null) {
499 debug.println(METHOD_NME + " NAMING DESCENDANT TEST...");
500 }
501 for (X500Principal tSubject : trustedSubjectDNs) {
502 X500Name tSubjectName = X500Name.asX500Name(tSubject);
503 int distanceTto1 =
504 Builder.distance(tSubjectName, cIssuer1Name, -1);
505 int distanceTto2 =
506 Builder.distance(tSubjectName, cIssuer2Name, -1);
507 if (debug != null) {
508 debug.println(METHOD_NME +" distanceTto1: " + distanceTto1);
509 debug.println(METHOD_NME +" distanceTto2: " + distanceTto2);
510 }
511 if (distanceTto1 > 0 || distanceTto2 > 0) {
512 if (distanceTto1 == distanceTto2) {
513 return -1;
514 } else if (distanceTto1 > 0 && distanceTto2 <= 0) {
515 return -1;
516 } else if (distanceTto1 <= 0 && distanceTto2 > 0) {
517 return 1;
518 } else if (distanceTto1 < distanceTto2) {
519 return -1;
520 } else { // distanceTto1 > distanceTto2
521 return 1;
522 }
523 }
524 }
525
526 /* If one cert's issuer is a naming ancestor of a trusted subject,
527 * then it is preferable, in order of increasing naming distance.
528 */
529 if (debug != null) {
530 debug.println(METHOD_NME + " NAMING ANCESTOR TEST...");
531 }
532 for (X500Principal tSubject : trustedSubjectDNs) {
533 X500Name tSubjectName = X500Name.asX500Name(tSubject);
534
535 int distanceTto1 = Builder.distance
536 (tSubjectName, cIssuer1Name, Integer.MAX_VALUE);
537 int distanceTto2 = Builder.distance
538 (tSubjectName, cIssuer2Name, Integer.MAX_VALUE);
539 if (debug != null) {
540 debug.println(METHOD_NME +" distanceTto1: " + distanceTto1);
541 debug.println(METHOD_NME +" distanceTto2: " + distanceTto2);
542 }
543 if (distanceTto1 < 0 || distanceTto2 < 0) {
544 if (distanceTto1 == distanceTto2) {
545 return -1;
546 } else if (distanceTto1 < 0 && distanceTto2 >= 0) {
547 return -1;
548 } else if (distanceTto1 >= 0 && distanceTto2 < 0) {
549 return 1;
550 } else if (distanceTto1 > distanceTto2) {
551 return -1;
552 } else {
553 return 1;
554 }
555 }
556 }
557
558 /* If one cert's issuer is in the same namespace as a trusted
559 * subject, then it is preferable, in order of increasing naming
560 * distance.
561 */
562 if (debug != null) {
563 debug.println(METHOD_NME +" SAME NAMESPACE AS TRUSTED TEST...");
564 }
565 for (X500Principal tSubject : trustedSubjectDNs) {
566 X500Name tSubjectName = X500Name.asX500Name(tSubject);
567 X500Name tAo1 = tSubjectName.commonAncestor(cIssuer1Name);
568 X500Name tAo2 = tSubjectName.commonAncestor(cIssuer2Name);
569 if (debug != null) {
570 debug.println(METHOD_NME +" tAo1: " + String.valueOf(tAo1));
571 debug.println(METHOD_NME +" tAo2: " + String.valueOf(tAo2));
572 }
573 if (tAo1 != null || tAo2 != null) {
574 if (tAo1 != null && tAo2 != null) {
575 int hopsTto1 = Builder.hops
576 (tSubjectName, cIssuer1Name, Integer.MAX_VALUE);
577 int hopsTto2 = Builder.hops
578 (tSubjectName, cIssuer2Name, Integer.MAX_VALUE);
579 if (debug != null) {
580 debug.println(METHOD_NME +" hopsTto1: " + hopsTto1);
581 debug.println(METHOD_NME +" hopsTto2: " + hopsTto2);
582 }
583 if (hopsTto1 == hopsTto2) {
584 } else if (hopsTto1 > hopsTto2) {
585 return 1;
586 } else { // hopsTto1 < hopsTto2
587 return -1;
588 }
589 } else if (tAo1 == null) {
590 return 1;
591 } else {
592 return -1;
593 }
594 }
595 }
596
597
598 /* If one cert's issuer is an ancestor of that cert's subject,
599 * then it is preferable, in order of increasing naming distance.
600 */
601 if (debug != null) {
602 debug.println(METHOD_NME+" CERT ISSUER/SUBJECT COMPARISON TEST...");
603 }
604 X500Principal cSubject1 = oCert1.getSubjectX500Principal();
605 X500Principal cSubject2 = oCert2.getSubjectX500Principal();
606 X500Name cSubject1Name = X500Name.asX500Name(cSubject1);
607 X500Name cSubject2Name = X500Name.asX500Name(cSubject2);
608
609 if (debug != null) {
610 debug.println(METHOD_NME + " o1 Subject: " + cSubject1);
611 debug.println(METHOD_NME + " o2 Subject: " + cSubject2);
612 }
613 int distanceStoI1 = Builder.distance
614 (cSubject1Name, cIssuer1Name, Integer.MAX_VALUE);
615 int distanceStoI2 = Builder.distance
616 (cSubject2Name, cIssuer2Name, Integer.MAX_VALUE);
617 if (debug != null) {
618 debug.println(METHOD_NME + " distanceStoI1: " + distanceStoI1);
619 debug.println(METHOD_NME + " distanceStoI2: " + distanceStoI2);
620 }
621 if (distanceStoI2 > distanceStoI1) {
622 return -1;
623 } else if (distanceStoI2 < distanceStoI1) {
624 return 1;
625 }
626
627 /* Otherwise, certs are equally preferable.
628 */
629 if (debug != null) {
630 debug.println(METHOD_NME + " no tests matched; RETURN 0");
631 }
632 return -1;
633 }
634 }
635
636 /**
637 * Verifies a matching certificate.
638 *
639 * This method executes the validation steps in the PKIX path
640 * validation algorithm <draft-ietf-pkix-new-part1-08.txt> which were
641 * not satisfied by the selection criteria used by getCertificates()
642 * to find the certs and only the steps that can be executed in a
643 * forward direction (target to trust anchor). Those steps that can
644 * only be executed in a reverse direction are deferred until the
645 * complete path has been built.
646 *
647 * Trust anchor certs are not validated, but are used to verify the
648 * signature and revocation status of the previous cert.
649 *
650 * If the last certificate is being verified (the one whose subject
651 * matches the target subject, then steps in 6.1.4 of the PKIX
652 * Certification Path Validation algorithm are NOT executed,
653 * regardless of whether or not the last cert is an end-entity
654 * cert or not. This allows callers to certify CA certs as
655 * well as EE certs.
656 *
657 * @param cert the certificate to be verified
658 * @param currentState the current state against which the cert is verified
659 * @param certPathList the certPathList generated thus far
660 */
661 void verifyCert(X509Certificate cert, State currentState,
662 List<X509Certificate> certPathList) throws GeneralSecurityException
663 {
664 if (debug != null) {
665 debug.println("ForwardBuilder.verifyCert(SN: "
666 + Debug.toHexString(cert.getSerialNumber())
667 + "\n Issuer: " + cert.getIssuerX500Principal() + ")"
668 + "\n Subject: " + cert.getSubjectX500Principal() + ")");
669 }
670
671 ForwardState currState = (ForwardState) currentState;
672
673 /*
674 * check for looping - abort a loop if
675 * ((we encounter the same certificate twice) AND
676 * ((policyMappingInhibited = true) OR (no policy mapping
677 * extensions can be found between the occurences of the same
678 * certificate)))
679 */
680 if (certPathList != null) {
681 boolean policyMappingFound = false;
682 for (X509Certificate cpListCert : certPathList) {
683 X509CertImpl cpListCertImpl = X509CertImpl.toImpl(cpListCert);
684 PolicyMappingsExtension policyMappingsExt
685 = cpListCertImpl.getPolicyMappingsExtension();
686 if (policyMappingsExt != null) {
687 policyMappingFound = true;
688 }
689 if (debug != null) {
690 debug.println("policyMappingFound = " + policyMappingFound);
691 }
692 if (cert.equals(cpListCert)) {
693 if ((buildParams.isPolicyMappingInhibited()) ||
694 (!policyMappingFound)) {
695 if (debug != null) {
696 debug.println("loop detected!!");
697 }
698 throw new CertPathValidatorException("loop detected");
699 }
700 }
701 }
702 }
703
704 /* check if trusted cert */
705 boolean isTrustedCert = trustedCerts.contains(cert);
706
707 /* we don't perform any validation of the trusted cert */
708 if (!isTrustedCert) {
709 /*
710 * Check CRITICAL private extensions for user checkers that
711 * support forward checking (forwardCheckers) and remove
712 * ones we know how to check.
713 */
714 Set<String> unresCritExts = cert.getCriticalExtensionOIDs();
715 if (unresCritExts == null) {
716 unresCritExts = Collections.<String>emptySet();
717 }
718 for (PKIXCertPathChecker checker : currState.forwardCheckers) {
719 checker.check(cert, unresCritExts);
720 }
721
722 /*
723 * Remove extensions from user checkers that don't support
724 * forward checking. After this step, we will have removed
725 * all extensions that all user checkers are capable of
726 * processing.
727 */
728 for (PKIXCertPathChecker checker : buildParams.getCertPathCheckers()) {
729 if (!checker.isForwardCheckingSupported()) {
730 Set<String> supportedExts = checker.getSupportedExtensions();
731 if (supportedExts != null) {
732 unresCritExts.removeAll(supportedExts);
733 }
734 }
735 }
736
737 /*
738 * Look at the remaining extensions and remove any ones we know how
739 * to check. If there are any left, throw an exception!
740 */
741 if (!unresCritExts.isEmpty()) {
742 unresCritExts.remove(
743 PKIXExtensions.BasicConstraints_Id.toString());
744 unresCritExts.remove(
745 PKIXExtensions.NameConstraints_Id.toString());
746 unresCritExts.remove(
747 PKIXExtensions.CertificatePolicies_Id.toString());
748 unresCritExts.remove(
749 PKIXExtensions.PolicyMappings_Id.toString());
750 unresCritExts.remove(
751 PKIXExtensions.PolicyConstraints_Id.toString());
752 unresCritExts.remove(
753 PKIXExtensions.InhibitAnyPolicy_Id.toString());
754 unresCritExts.remove(
755 PKIXExtensions.SubjectAlternativeName_Id.toString());
756 unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
757 unresCritExts.remove(
758 PKIXExtensions.ExtendedKeyUsage_Id.toString());
759
760 if (!unresCritExts.isEmpty())
761 throw new CertPathValidatorException
762 ("Unrecognized critical extension(s)", null, null, -1,
763 PKIXReason.UNRECOGNIZED_CRIT_EXT);
764 }
765 }
766
767 /*
768 * if this is the target certificate (init=true), then we are
769 * not able to do any more verification, so just return
770 */
771 if (currState.isInitial()) {
772 return;
773 }
774
775 /* we don't perform any validation of the trusted cert */
776 if (!isTrustedCert) {
777 /* Make sure this is a CA cert */
778 if (cert.getBasicConstraints() == -1) {
779 throw new CertificateException("cert is NOT a CA cert");
780 }
781
782 /*
783 * Check keyUsage extension
784 */
785 KeyChecker.verifyCAKeyUsage(cert);
786 }
787
788 /*
789 * the following checks are performed even when the cert
790 * is a trusted cert, since we are only extracting the
791 * subjectDN, and publicKey from the cert
792 * in order to verify a previous cert
793 */
794
795 /*
796 * Check revocation for the previous cert
797 */
798 if (buildParams.isRevocationEnabled()) {
799
800 // first off, see if this cert can authorize revocation...
801 if (CrlRevocationChecker.certCanSignCrl(cert)) {
802 // And then check to be sure no key requiring key parameters
803 // has been encountered
804 if (!currState.keyParamsNeeded())
805 // If all that checks out, we can check the
806 // revocation status of the cert. Otherwise,
807 // we'll just wait until the end.
808 currState.crlChecker.check(currState.cert,
809 cert.getPublicKey(),
810 true);
811 }
812 }
813
814 /*
815 * Check signature only if no key requiring key parameters has been
816 * encountered.
817 */
818 if (!currState.keyParamsNeeded()) {
819 (currState.cert).verify(cert.getPublicKey(),
820 buildParams.getSigProvider());
821 }
822 }
823
824 /**
825 * Verifies whether the input certificate completes the path.
826 * Checks the cert against each trust anchor that was specified, in order,
827 * and returns true as soon as it finds a valid anchor.
828 * Returns true if the cert matches a trust anchor specified as a
829 * certificate or if the cert verifies with a trust anchor that
830 * was specified as a trusted {pubkey, caname} pair. Returns false if none
831 * of the trust anchors are valid for this cert.
832 *
833 * @param cert the certificate to test
834 * @return a boolean value indicating whether the cert completes the path.
835 */
836 boolean isPathCompleted(X509Certificate cert) {
837 for (TrustAnchor anchor : trustAnchors) {
838 if (anchor.getTrustedCert() != null) {
839 if (cert.equals(anchor.getTrustedCert())) {
840 this.trustAnchor = anchor;
841 return true;
842 } else {
843 continue;
844 }
845 } else {
846 X500Principal principal = anchor.getCA();
847 java.security.PublicKey publicKey = anchor.getCAPublicKey();
848
849 if (principal != null && publicKey != null &&
850 principal.equals(cert.getSubjectX500Principal())) {
851 if (publicKey.equals(cert.getPublicKey())) {
852 // the cert itself is a trust anchor
853 this.trustAnchor = anchor;
854 return true;
855 }
856 // else, it is a self-issued certificate of the anchor
857 }
858
859 // Check subject/issuer name chaining
860 if (principal == null ||
861 !principal.equals(cert.getIssuerX500Principal())) {
862 continue;
863 }
864 }
865
866 /* Check revocation if it is enabled */
867 if (buildParams.isRevocationEnabled()) {
868 try {
869 CrlRevocationChecker crlChecker = new CrlRevocationChecker
870 (anchor, buildParams, null, onlyEECert);
871 crlChecker.check(cert, anchor.getCAPublicKey(), true);
872 } catch (CertPathValidatorException cpve) {
873 if (debug != null) {
874 debug.println("ForwardBuilder.isPathCompleted() cpve");
875 cpve.printStackTrace();
876 }
877 continue;
878 }
879 }
880
881 /*
882 * Check signature
883 */
884 try {
885 // NOTE: the DSA public key in the buildParams may lack
886 // parameters, yet there is no key to inherit the parameters
887 // from. This is probably such a rare case that it is not worth
888 // trying to detect the situation earlier.
889 cert.verify(anchor.getCAPublicKey(),
890 buildParams.getSigProvider());
891 } catch (InvalidKeyException ike) {
892 if (debug != null) {
893 debug.println("ForwardBuilder.isPathCompleted() invalid "
894 + "DSA key found");
895 }
896 continue;
897 } catch (Exception e){
898 if (debug != null) {
899 debug.println("ForwardBuilder.isPathCompleted() " +
900 "unexpected exception");
901 e.printStackTrace();
902 }
903 continue;
904 }
905
906 this.trustAnchor = anchor;
907 return true;
908 }
909
910 return false;
911 }
912
913 /** Adds the certificate to the certPathList
914 *
915 * @param cert the certificate to be added
916 * @param certPathList the certification path list
917 */
918 void addCertToPath(X509Certificate cert,
919 LinkedList<X509Certificate> certPathList) {
920 certPathList.addFirst(cert);
921 }
922
923 /** Removes final certificate from the certPathList
924 *
925 * @param certPathList the certification path list
926 */
927 void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
928 certPathList.removeFirst();
929 }
930}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t