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

Unified · Split

java/pkg/sun/security/provider/certpath/DistributionPointFetcher.java+736−0
@@ -0,0 +1,736 @@
1/*
2 * Copyright (c) 2002, 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.*;
29import java.net.URI;
30import java.util.*;
31import java.security.*;
32import java.security.cert.*;
33import javax.security.auth.x500.X500Principal;
34
35import sun.security.action.GetBooleanAction;
36import sun.security.util.Debug;
37import sun.security.util.DerOutputStream;
38import sun.security.x509.*;
39
40/**
41 * Class to obtain CRLs via the CRLDistributionPoints extension.
42 * Note that the functionality of this class must be explicitly enabled
43 * via a system property, see the USE_CRLDP variable below.
44 *
45 * This class uses the URICertStore class to fetch CRLs. The URICertStore
46 * class also implements CRL caching: see the class description for more
47 * information.
48 *
49 * @author Andreas Sterbenz
50 * @author Sean Mullan
51 * @since 1.4.2
52 */
53class DistributionPointFetcher {
54
55 private static final Debug debug = Debug.getInstance("certpath");
56
57 private static final boolean[] ALL_REASONS =
58 {true, true, true, true, true, true, true, true, true};
59
60 /**
61 * Flag indicating whether support for the CRL distribution point
62 * extension shall be enabled. Currently disabled by default for
63 * compatibility and legal reasons.
64 */
65 private final static boolean USE_CRLDP = AccessController.doPrivileged
66 (new GetBooleanAction("com.sun.security.enableCRLDP"));
67
68 // singleton instance
69 private static final DistributionPointFetcher INSTANCE =
70 new DistributionPointFetcher();
71
72 /**
73 * Private instantiation only.
74 */
75 private DistributionPointFetcher() {}
76
77 /**
78 * Return a DistributionPointFetcher instance.
79 */
80 static DistributionPointFetcher getInstance() {
81 return INSTANCE;
82 }
83
84 /**
85 * Return the X509CRLs matching this selector. The selector must be
86 * an X509CRLSelector with certificateChecking set.
87 *
88 * If CRLDP support is disabled, this method always returns an
89 * empty set.
90 */
91 Collection<X509CRL> getCRLs(X509CRLSelector selector, boolean signFlag,
92 PublicKey prevKey, String provider, List<CertStore> certStores,
93 boolean[] reasonsMask, Set<TrustAnchor> trustAnchors,
94 Date validity) throws CertStoreException {
95
96 if (USE_CRLDP == false) {
97 return Collections.emptySet();
98 }
99 X509Certificate cert = selector.getCertificateChecking();
100 if (cert == null) {
101 return Collections.emptySet();
102 }
103 try {
104 X509CertImpl certImpl = X509CertImpl.toImpl(cert);
105 if (debug != null) {
106 debug.println("DistributionPointFetcher.getCRLs: Checking "
107 + "CRLDPs for " + certImpl.getSubjectX500Principal());
108 }
109 CRLDistributionPointsExtension ext =
110 certImpl.getCRLDistributionPointsExtension();
111 if (ext == null) {
112 if (debug != null) {
113 debug.println("No CRLDP ext");
114 }
115 return Collections.emptySet();
116 }
117 List<DistributionPoint> points = (List<DistributionPoint>)ext.get(
118 CRLDistributionPointsExtension.POINTS);
119 Set<X509CRL> results = new HashSet<X509CRL>();
120 for (Iterator<DistributionPoint> t = points.iterator();
121 t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
122 DistributionPoint point = t.next();
123 Collection<X509CRL> crls = getCRLs(selector, certImpl,
124 point, reasonsMask, signFlag, prevKey, provider,
125 certStores, trustAnchors, validity);
126 results.addAll(crls);
127 }
128 if (debug != null) {
129 debug.println("Returning " + results.size() + " CRLs");
130 }
131 return results;
132 } catch (CertificateException e) {
133 return Collections.emptySet();
134 } catch (IOException e) {
135 return Collections.emptySet();
136 }
137 }
138
139 /**
140 * Download CRLs from the given distribution point, verify and return them.
141 * See the top of the class for current limitations.
142 */
143 private Collection<X509CRL> getCRLs(X509CRLSelector selector,
144 X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
145 boolean signFlag, PublicKey prevKey, String provider,
146 List<CertStore> certStores, Set<TrustAnchor> trustAnchors,
147 Date validity) {
148
149 // check for full name
150 GeneralNames fullName = point.getFullName();
151 if (fullName == null) {
152 // check for relative name
153 RDN relativeName = point.getRelativeName();
154 if (relativeName == null) {
155 return Collections.emptySet();
156 }
157 try {
158 GeneralNames crlIssuers = point.getCRLIssuer();
159 if (crlIssuers == null) {
160 fullName = getFullNames
161 ((X500Name) certImpl.getIssuerDN(), relativeName);
162 } else {
163 // should only be one CRL Issuer
164 if (crlIssuers.size() != 1) {
165 return Collections.emptySet();
166 } else {
167 fullName = getFullNames
168 ((X500Name) crlIssuers.get(0).getName(), relativeName);
169 }
170 }
171 } catch (IOException ioe) {
172 return Collections.emptySet();
173 }
174 }
175 Collection<X509CRL> possibleCRLs = new ArrayList<X509CRL>();
176 Collection<X509CRL> crls = new ArrayList<X509CRL>(2);
177 for (Iterator<GeneralName> t = fullName.iterator(); t.hasNext(); ) {
178 GeneralName name = t.next();
179 if (name.getType() == GeneralNameInterface.NAME_DIRECTORY) {
180 X500Name x500Name = (X500Name) name.getName();
181 possibleCRLs.addAll(
182 getCRLs(x500Name, certImpl.getIssuerX500Principal(),
183 certStores));
184 } else if (name.getType() == GeneralNameInterface.NAME_URI) {
185 URIName uriName = (URIName)name.getName();
186 X509CRL crl = getCRL(uriName);
187 if (crl != null) {
188 possibleCRLs.add(crl);
189 }
190 }
191 }
192
193 for (X509CRL crl : possibleCRLs) {
194 try {
195 // make sure issuer is not set
196 // we check the issuer in verifyCRLs method
197 selector.setIssuerNames(null);
198 if (selector.match(crl) && verifyCRL(certImpl, point, crl,
199 reasonsMask, signFlag, prevKey, provider, trustAnchors,
200 certStores, validity)) {
201 crls.add(crl);
202 }
203 } catch (Exception e) {
204 // don't add the CRL
205 if (debug != null) {
206 debug.println("Exception verifying CRL: " + e.getMessage());
207 e.printStackTrace();
208 }
209 }
210 }
211 return crls;
212 }
213
214 /**
215 * Download CRL from given URI.
216 */
217 private X509CRL getCRL(URIName name) {
218 URI uri = name.getURI();
219 if (debug != null) {
220 debug.println("Trying to fetch CRL from DP " + uri);
221 }
222 try {
223 CertStore ucs = URICertStore.getInstance
224 (new URICertStore.URICertStoreParameters(uri));
225 Collection<? extends CRL> crls = ucs.getCRLs(null);
226 if (crls.isEmpty()) {
227 return null;
228 } else {
229 return (X509CRL) crls.iterator().next();
230 }
231 } catch (Exception e) {
232 if (debug != null) {
233 debug.println("Exception getting CRL from CertStore: " + e);
234 e.printStackTrace();
235 }
236 }
237 return null;
238 }
239
240 /**
241 * Fetch CRLs from certStores.
242 */
243 private Collection<X509CRL> getCRLs(X500Name name,
244 X500Principal certIssuer, List<CertStore> certStores)
245 {
246 if (debug != null) {
247 debug.println("Trying to fetch CRL from DP " + name);
248 }
249 X509CRLSelector xcs = new X509CRLSelector();
250 xcs.addIssuer(name.asX500Principal());
251 xcs.addIssuer(certIssuer);
252 Collection<X509CRL> crls = new ArrayList<X509CRL>();
253 for (CertStore store : certStores) {
254 try {
255 for (CRL crl : store.getCRLs(xcs)) {
256 crls.add((X509CRL)crl);
257 }
258 } catch (CertStoreException cse) {
259 // don't add the CRL
260 if (debug != null) {
261 debug.println("Non-fatal exception while retrieving " +
262 "CRLs: " + cse);
263 cse.printStackTrace();
264 }
265 }
266 }
267 return crls;
268 }
269
270 /**
271 * Verifies a CRL for the given certificate's Distribution Point to
272 * ensure it is appropriate for checking the revocation status.
273 *
274 * @param certImpl the certificate whose revocation status is being checked
275 * @param point one of the distribution points of the certificate
276 * @param crl the CRL
277 * @param reasonsMask the interim reasons mask
278 * @param signFlag true if prevKey can be used to verify the CRL
279 * @param prevKey the public key that verifies the certificate's signature
280 * @param provider the Signature provider to use
281 * @param trustAnchors a {@code Set} of {@code TrustAnchor}s
282 * @param certStores a {@code List} of {@code CertStore}s to be used in
283 * finding certificates and CRLs
284 * @param validity the time for which the validity of the CRL issuer's
285 * certification path should be determined
286 * @return true if ok, false if not
287 */
288 boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,
289 X509CRL crl, boolean[] reasonsMask, boolean signFlag,
290 PublicKey prevKey, String provider,
291 Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
292 Date validity) throws CRLException, IOException {
293
294 boolean indirectCRL = false;
295 X509CRLImpl crlImpl = X509CRLImpl.toImpl(crl);
296 IssuingDistributionPointExtension idpExt =
297 crlImpl.getIssuingDistributionPointExtension();
298 X500Name certIssuer = (X500Name) certImpl.getIssuerDN();
299 X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();
300
301 // if crlIssuer is set, verify that it matches the issuer of the
302 // CRL and the CRL contains an IDP extension with the indirectCRL
303 // boolean asserted. Otherwise, verify that the CRL issuer matches the
304 // certificate issuer.
305 GeneralNames pointCrlIssuers = point.getCRLIssuer();
306 X500Name pointCrlIssuer = null;
307 if (pointCrlIssuers != null) {
308 if (idpExt == null ||
309 ((Boolean) idpExt.get
310 (IssuingDistributionPointExtension.INDIRECT_CRL)).equals
311 (Boolean.FALSE)) {
312 return false;
313 }
314 boolean match = false;
315 for (Iterator<GeneralName> t = pointCrlIssuers.iterator();
316 !match && t.hasNext(); ) {
317 GeneralNameInterface name = t.next().getName();
318 if (crlIssuer.equals(name) == true) {
319 pointCrlIssuer = (X500Name) name;
320 match = true;
321 }
322 }
323 if (match == false) {
324 return false;
325 }
326
327 // we accept the case that a CRL issuer provide status
328 // information for itself.
329 if (issues(certImpl, crlImpl, provider)) {
330 // reset the public key used to verify the CRL's signature
331 prevKey = certImpl.getPublicKey();
332 } else {
333 indirectCRL = true;
334 }
335 } else if (crlIssuer.equals(certIssuer) == false) {
336 if (debug != null) {
337 debug.println("crl issuer does not equal cert issuer");
338 }
339 return false;
340 } else {
341 // in case of self-issued indirect CRL issuer.
342 byte[] certAKID = certImpl.getExtensionValue(
343 PKIXExtensions.AuthorityKey_Id.toString());
344 byte[] crlAKID = crlImpl.getExtensionValue(
345 PKIXExtensions.AuthorityKey_Id.toString());
346
347 if (certAKID == null || crlAKID == null) {
348 // cannot recognize indirect CRL without AKID
349
350 // we accept the case that a CRL issuer provide status
351 // information for itself.
352 if (issues(certImpl, crlImpl, provider)) {
353 // reset the public key used to verify the CRL's signature
354 prevKey = certImpl.getPublicKey();
355 }
356 } else if (!Arrays.equals(certAKID, crlAKID)) {
357 // we accept the case that a CRL issuer provide status
358 // information for itself.
359 if (issues(certImpl, crlImpl, provider)) {
360 // reset the public key used to verify the CRL's signature
361 prevKey = certImpl.getPublicKey();
362 } else {
363 indirectCRL = true;
364 }
365 }
366 }
367
368 if (!indirectCRL && !signFlag) {
369 // cert's key cannot be used to verify the CRL
370 return false;
371 }
372
373 if (idpExt != null) {
374 DistributionPointName idpPoint = (DistributionPointName)
375 idpExt.get(IssuingDistributionPointExtension.POINT);
376 if (idpPoint != null) {
377 GeneralNames idpNames = idpPoint.getFullName();
378 if (idpNames == null) {
379 RDN relativeName = idpPoint.getRelativeName();
380 if (relativeName == null) {
381 if (debug != null) {
382 debug.println("IDP must be relative or full DN");
383 }
384 return false;
385 }
386 if (debug != null) {
387 debug.println("IDP relativeName:" + relativeName);
388 }
389 idpNames = getFullNames(crlIssuer, relativeName);
390 }
391 // if the DP name is present in the IDP CRL extension and the
392 // DP field is present in the DP, then verify that one of the
393 // names in the IDP matches one of the names in the DP
394 if (point.getFullName() != null ||
395 point.getRelativeName() != null) {
396 GeneralNames pointNames = point.getFullName();
397 if (pointNames == null) {
398 RDN relativeName = point.getRelativeName();
399 if (relativeName == null) {
400 if (debug != null) {
401 debug.println("DP must be relative or full DN");
402 }
403 return false;
404 }
405 if (debug != null) {
406 debug.println("DP relativeName:" + relativeName);
407 }
408 if (indirectCRL) {
409 if (pointCrlIssuers.size() != 1) {
410 // RFC 3280: there must be only 1 CRL issuer
411 // name when relativeName is present
412 if (debug != null) {
413 debug.println("must only be one CRL " +
414 "issuer when relative name present");
415 }
416 return false;
417 }
418 pointNames = getFullNames
419 (pointCrlIssuer, relativeName);
420 } else {
421 pointNames = getFullNames(certIssuer, relativeName);
422 }
423 }
424 boolean match = false;
425 for (Iterator<GeneralName> i = idpNames.iterator();
426 !match && i.hasNext(); ) {
427 GeneralNameInterface idpName = i.next().getName();
428 if (debug != null) {
429 debug.println("idpName: " + idpName);
430 }
431 for (Iterator<GeneralName> p = pointNames.iterator();
432 !match && p.hasNext(); ) {
433 GeneralNameInterface pointName = p.next().getName();
434 if (debug != null) {
435 debug.println("pointName: " + pointName);
436 }
437 match = idpName.equals(pointName);
438 }
439 }
440 if (!match) {
441 if (debug != null) {
442 debug.println("IDP name does not match DP name");
443 }
444 return false;
445 }
446 // if the DP name is present in the IDP CRL extension and the
447 // DP field is absent from the DP, then verify that one of the
448 // names in the IDP matches one of the names in the crlIssuer
449 // field of the DP
450 } else {
451 // verify that one of the names in the IDP matches one of
452 // the names in the cRLIssuer of the cert's DP
453 boolean match = false;
454 for (Iterator<GeneralName> t = pointCrlIssuers.iterator();
455 !match && t.hasNext(); ) {
456 GeneralNameInterface crlIssuerName = t.next().getName();
457 for (Iterator<GeneralName> i = idpNames.iterator();
458 !match && i.hasNext(); ) {
459 GeneralNameInterface idpName = i.next().getName();
460 match = crlIssuerName.equals(idpName);
461 }
462 }
463 if (!match) {
464 return false;
465 }
466 }
467 }
468
469 // if the onlyContainsUserCerts boolean is asserted, verify that the
470 // cert is not a CA cert
471 Boolean b = (Boolean)
472 idpExt.get(IssuingDistributionPointExtension.ONLY_USER_CERTS);
473 if (b.equals(Boolean.TRUE) && certImpl.getBasicConstraints() != -1) {
474 if (debug != null) {
475 debug.println("cert must be a EE cert");
476 }
477 return false;
478 }
479
480 // if the onlyContainsCACerts boolean is asserted, verify that the
481 // cert is a CA cert
482 b = (Boolean)
483 idpExt.get(IssuingDistributionPointExtension.ONLY_CA_CERTS);
484 if (b.equals(Boolean.TRUE) && certImpl.getBasicConstraints() == -1) {
485 if (debug != null) {
486 debug.println("cert must be a CA cert");
487 }
488 return false;
489 }
490
491 // verify that the onlyContainsAttributeCerts boolean is not
492 // asserted
493 b = (Boolean) idpExt.get
494 (IssuingDistributionPointExtension.ONLY_ATTRIBUTE_CERTS);
495 if (b.equals(Boolean.TRUE)) {
496 if (debug != null) {
497 debug.println("cert must not be an AA cert");
498 }
499 return false;
500 }
501 }
502
503 // compute interim reasons mask
504 boolean[] interimReasonsMask = new boolean[9];
505 ReasonFlags reasons = null;
506 if (idpExt != null) {
507 reasons = (ReasonFlags)
508 idpExt.get(IssuingDistributionPointExtension.REASONS);
509 }
510
511 boolean[] pointReasonFlags = point.getReasonFlags();
512 if (reasons != null) {
513 if (pointReasonFlags != null) {
514 // set interim reasons mask to the intersection of
515 // reasons in the DP and onlySomeReasons in the IDP
516 boolean[] idpReasonFlags = reasons.getFlags();
517 for (int i = 0; i < idpReasonFlags.length; i++) {
518 if (idpReasonFlags[i] && pointReasonFlags[i]) {
519 interimReasonsMask[i] = true;
520 }
521 }
522 } else {
523 // set interim reasons mask to the value of
524 // onlySomeReasons in the IDP (and clone it since we may
525 // modify it)
526 interimReasonsMask = reasons.getFlags().clone();
527 }
528 } else if (idpExt == null || reasons == null) {
529 if (pointReasonFlags != null) {
530 // set interim reasons mask to the value of DP reasons
531 interimReasonsMask = pointReasonFlags.clone();
532 } else {
533 // set interim reasons mask to the special value all-reasons
534 interimReasonsMask = new boolean[9];
535 Arrays.fill(interimReasonsMask, true);
536 }
537 }
538
539 // verify that interim reasons mask includes one or more reasons
540 // not included in the reasons mask
541 boolean oneOrMore = false;
542 for (int i=0; i < interimReasonsMask.length && !oneOrMore; i++) {
543 if (!reasonsMask[i] && interimReasonsMask[i]) {
544 oneOrMore = true;
545 }
546 }
547 if (!oneOrMore) {
548 return false;
549 }
550
551 // Obtain and validate the certification path for the complete
552 // CRL issuer (if indirect CRL). If a key usage extension is present
553 // in the CRL issuer's certificate, verify that the cRLSign bit is set.
554 if (indirectCRL) {
555 X509CertSelector certSel = new X509CertSelector();
556 certSel.setSubject(crlIssuer.asX500Principal());
557 boolean[] crlSign = {false,false,false,false,false,false,true};
558 certSel.setKeyUsage(crlSign);
559
560 // Currently by default, forward builder does not enable
561 // subject/authority key identifier identifying for target
562 // certificate, instead, it only compares the CRL issuer and
563 // the target certificate subject. If the certificate of the
564 // delegated CRL issuer is a self-issued certificate, the
565 // builder is unable to find the proper CRL issuer by issuer
566 // name only, there is a potential dead loop on finding the
567 // proper issuer. It is of great help to narrow the target
568 // scope down to aware of authority key identifiers in the
569 // selector, for the purposes of breaking the dead loop.
570 AuthorityKeyIdentifierExtension akidext =
571 crlImpl.getAuthKeyIdExtension();
572 if (akidext != null) {
573 KeyIdentifier akid = (KeyIdentifier)akidext.get(akidext.KEY_ID);
574 if (akid != null) {
575 DerOutputStream derout = new DerOutputStream();
576 derout.putOctetString(akid.getIdentifier());
577 certSel.setSubjectKeyIdentifier(derout.toByteArray());
578 }
579
580 SerialNumber asn =
581 (SerialNumber)akidext.get(akidext.SERIAL_NUMBER);
582 if (asn != null) {
583 certSel.setSerialNumber(asn.getNumber());
584 }
585 // the subject criterion will be set by builder automatically.
586 }
587
588 // by far, we have validated the previous certificate, we can
589 // trust it during validating the CRL issuer.
590 // Except the performance improvement, another benefit is to break
591 // the dead loop while looking for the issuer back and forth
592 // between the delegated self-issued certificate and its issuer.
593 Set<TrustAnchor> newTrustAnchors = new HashSet<>(trustAnchors);
594
595 if (prevKey != null) {
596 // Add the previous certificate as a trust anchor.
597 X500Principal principal = certImpl.getIssuerX500Principal();
598 TrustAnchor temporary =
599 new TrustAnchor(principal, prevKey, null);
600 newTrustAnchors.add(temporary);
601 }
602
603 PKIXBuilderParameters params = null;
604 try {
605 params = new PKIXBuilderParameters(newTrustAnchors, certSel);
606 } catch (InvalidAlgorithmParameterException iape) {
607 throw new CRLException(iape);
608 }
609 params.setCertStores(certStores);
610 params.setSigProvider(provider);
611 params.setDate(validity);
612 try {
613 CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
614 PKIXCertPathBuilderResult result =
615 (PKIXCertPathBuilderResult) builder.build(params);
616 prevKey = result.getPublicKey();
617 } catch (Exception e) {
618 throw new CRLException(e);
619 }
620 }
621
622 // check the crl signature algorithm
623 try {
624 AlgorithmChecker.check(prevKey, crl);
625 } catch (CertPathValidatorException cpve) {
626 if (debug != null) {
627 debug.println("CRL signature algorithm check failed: " + cpve);
628 }
629 return false;
630 }
631
632 // validate the signature on the CRL
633 try {
634 crl.verify(prevKey, provider);
635 } catch (Exception e) {
636 if (debug != null) {
637 debug.println("CRL signature failed to verify");
638 }
639 return false;
640 }
641
642 // reject CRL if any unresolved critical extensions remain in the CRL.
643 Set<String> unresCritExts = crl.getCriticalExtensionOIDs();
644 // remove any that we have processed
645 if (unresCritExts != null) {
646 unresCritExts.remove
647 (PKIXExtensions.IssuingDistributionPoint_Id.toString());
648 if (!unresCritExts.isEmpty()) {
649 if (debug != null) {
650 debug.println("Unrecognized critical extension(s) in CRL: "
651 + unresCritExts);
652 Iterator<String> i = unresCritExts.iterator();
653 while (i.hasNext())
654 debug.println(i.next());
655 }
656 return false;
657 }
658 }
659
660 // update reasonsMask
661 for (int i=0; i < interimReasonsMask.length; i++) {
662 if (!reasonsMask[i] && interimReasonsMask[i]) {
663 reasonsMask[i] = true;
664 }
665 }
666 return true;
667 }
668
669 /**
670 * Append relative name to the issuer name and return a new
671 * GeneralNames object.
672 */
673 private GeneralNames getFullNames(X500Name issuer, RDN rdn)
674 throws IOException {
675 List<RDN> rdns = new ArrayList<RDN>(issuer.rdns());
676 rdns.add(rdn);
677 X500Name fullName = new X500Name(rdns.toArray(new RDN[0]));
678 GeneralNames fullNames = new GeneralNames();
679 fullNames.add(new GeneralName(fullName));
680 return fullNames;
681 }
682
683 /** Verifies whether a CRL is issued by a certain certificate
684 *
685 * @param cert the certificate
686 * @param crl the CRL to be verified
687 * @param provider the name of the signature provider
688 */
689 private static boolean issues(X509CertImpl cert, X509CRLImpl crl,
690 String provider) throws IOException {
691
692 boolean matched = false;
693
694 AdaptableX509CertSelector issuerSelector =
695 new AdaptableX509CertSelector();
696
697 // check certificate's key usage
698 boolean[] usages = cert.getKeyUsage();
699 if (usages != null) {
700 usages[6] = true; // cRLSign
701 issuerSelector.setKeyUsage(usages);
702 }
703
704 // check certificate's subject
705 X500Principal crlIssuer = crl.getIssuerX500Principal();
706 issuerSelector.setSubject(crlIssuer);
707
708 /*
709 * Facilitate certification path construction with authority
710 * key identifier and subject key identifier.
711 *
712 * In practice, conforming CAs MUST use the key identifier method,
713 * and MUST include authority key identifier extension in all CRLs
714 * issued. [section 5.2.1, RFC 2459]
715 */
716 AuthorityKeyIdentifierExtension crlAKID = crl.getAuthKeyIdExtension();
717 if (crlAKID != null) {
718 issuerSelector.parseAuthorityKeyIdentifierExtension(crlAKID);
719 }
720
721 matched = issuerSelector.match(cert);
722
723 // if AKID is unreliable, verify the CRL signature with the cert
724 if (matched && (crlAKID == null ||
725 cert.getAuthorityKeyIdentifierExtension() == null)) {
726 try {
727 crl.verify(cert.getPublicKey(), provider);
728 matched = true;
729 } catch (Exception e) {
730 matched = false;
731 }
732 }
733
734 return matched;
735 }
736}