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+
26+package sun.security.provider.certpath;
27+
28+import java.io.*;
29+import java.net.URI;
30+import java.util.*;
31+import java.security.*;
32+import java.security.cert.*;
33+import javax.security.auth.x500.X500Principal;
34+
35+import sun.security.action.GetBooleanAction;
36+import sun.security.util.Debug;
37+import sun.security.util.DerOutputStream;
38+import 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+ */
53+class 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+}