1 /*
2  * Copyright (c) 2000, 2015, 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 java.security.cert;
27 
28 import java.io.IOException;
29 import java.math.BigInteger;
30 import java.util.*;
31 
32 import javax.security.auth.x500.X500Principal;
33 
34 import sun.security.util.Debug;
35 import sun.security.util.DerInputStream;
36 import sun.security.x509.CRLNumberExtension;
37 import sun.security.x509.X500Name;
38 
39 /**
40  * A {@code CRLSelector} that selects {@code X509CRLs} that
41  * match all specified criteria. This class is particularly useful when
42  * selecting CRLs from a {@code CertStore} to check revocation status
43  * of a particular certificate.
44  * <p>
45  * When first constructed, an {@code X509CRLSelector} has no criteria
46  * enabled and each of the {@code get} methods return a default
47  * value ({@code null}). Therefore, the {@link #match match} method
48  * would return {@code true} for any {@code X509CRL}. Typically,
49  * several criteria are enabled (by calling {@link #setIssuers setIssuers}
50  * or {@link #setDateAndTime setDateAndTime}, for instance) and then the
51  * {@code X509CRLSelector} is passed to
52  * {@link CertStore#getCRLs CertStore.getCRLs} or some similar
53  * method.
54  * <p>
55  * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
56  * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a>
57  * for definitions of the X.509 CRL fields and extensions mentioned below.
58  * <p>
59  * <b>Concurrent Access</b>
60  * <p>
61  * Unless otherwise specified, the methods defined in this class are not
62  * thread-safe. Multiple threads that need to access a single
63  * object concurrently should synchronize amongst themselves and
64  * provide the necessary locking. Multiple threads each manipulating
65  * separate objects need not synchronize.
66  *
67  * @see CRLSelector
68  * @see X509CRL
69  *
70  * @since       1.4
71  * @author      Steve Hanna
72  */
73 public class X509CRLSelector implements CRLSelector {
74 
75     static {
CertPathHelperImpl.initialize()76         CertPathHelperImpl.initialize();
77     }
78 
79     private static final Debug debug = Debug.getInstance("certpath");
80     private HashSet<Object> issuerNames;
81     private HashSet<X500Principal> issuerX500Principals;
82     private BigInteger minCRL;
83     private BigInteger maxCRL;
84     private Date dateAndTime;
85     private X509Certificate certChecking;
86     private long skew = 0;
87 
88     /**
89      * Creates an {@code X509CRLSelector}. Initially, no criteria are set
90      * so any {@code X509CRL} will match.
91      */
X509CRLSelector()92     public X509CRLSelector() {}
93 
94     /**
95      * Sets the issuerNames criterion. The issuer distinguished name in the
96      * {@code X509CRL} must match at least one of the specified
97      * distinguished names. If {@code null}, any issuer distinguished name
98      * will do.
99      * <p>
100      * This method allows the caller to specify, with a single method call,
101      * the complete set of issuer names which {@code X509CRLs} may contain.
102      * The specified value replaces the previous value for the issuerNames
103      * criterion.
104      * <p>
105      * The {@code names} parameter (if not {@code null}) is a
106      * {@code Collection} of {@code X500Principal}s.
107      * <p>
108      * Note that the {@code names} parameter can contain duplicate
109      * distinguished names, but they may be removed from the
110      * {@code Collection} of names returned by the
111      * {@link #getIssuers getIssuers} method.
112      * <p>
113      * Note that a copy is performed on the {@code Collection} to
114      * protect against subsequent modifications.
115      *
116      * @param issuers a {@code Collection} of X500Principals
117      *   (or {@code null})
118      * @see #getIssuers
119      * @since 1.5
120      */
setIssuers(Collection<X500Principal> issuers)121     public void setIssuers(Collection<X500Principal> issuers) {
122         if ((issuers == null) || issuers.isEmpty()) {
123             issuerNames = null;
124             issuerX500Principals = null;
125         } else {
126             // clone
127             issuerX500Principals = new HashSet<X500Principal>(issuers);
128             issuerNames = new HashSet<Object>();
129             for (X500Principal p : issuerX500Principals) {
130                 issuerNames.add(p.getEncoded());
131             }
132         }
133     }
134 
135     /**
136      * <strong>Note:</strong> use {@linkplain #setIssuers(Collection)} instead
137      * or only specify the byte array form of distinguished names when using
138      * this method. See {@link #addIssuerName(String)} for more information.
139      * <p>
140      * Sets the issuerNames criterion. The issuer distinguished name in the
141      * {@code X509CRL} must match at least one of the specified
142      * distinguished names. If {@code null}, any issuer distinguished name
143      * will do.
144      * <p>
145      * This method allows the caller to specify, with a single method call,
146      * the complete set of issuer names which {@code X509CRLs} may contain.
147      * The specified value replaces the previous value for the issuerNames
148      * criterion.
149      * <p>
150      * The {@code names} parameter (if not {@code null}) is a
151      * {@code Collection} of names. Each name is a {@code String}
152      * or a byte array representing a distinguished name (in
153      * <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a> or
154      * ASN.1 DER encoded form, respectively). If {@code null} is supplied
155      * as the value for this argument, no issuerNames check will be performed.
156      * <p>
157      * Note that the {@code names} parameter can contain duplicate
158      * distinguished names, but they may be removed from the
159      * {@code Collection} of names returned by the
160      * {@link #getIssuerNames getIssuerNames} method.
161      * <p>
162      * If a name is specified as a byte array, it should contain a single DER
163      * encoded distinguished name, as defined in X.501. The ASN.1 notation for
164      * this structure is as follows.
165      * <pre>{@code
166      * Name ::= CHOICE {
167      *   RDNSequence }
168      *
169      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
170      *
171      * RelativeDistinguishedName ::=
172      *   SET SIZE (1 .. MAX) OF AttributeTypeAndValue
173      *
174      * AttributeTypeAndValue ::= SEQUENCE {
175      *   type     AttributeType,
176      *   value    AttributeValue }
177      *
178      * AttributeType ::= OBJECT IDENTIFIER
179      *
180      * AttributeValue ::= ANY DEFINED BY AttributeType
181      * ....
182      * DirectoryString ::= CHOICE {
183      *       teletexString           TeletexString (SIZE (1..MAX)),
184      *       printableString         PrintableString (SIZE (1..MAX)),
185      *       universalString         UniversalString (SIZE (1..MAX)),
186      *       utf8String              UTF8String (SIZE (1.. MAX)),
187      *       bmpString               BMPString (SIZE (1..MAX)) }
188      * }</pre>
189      * <p>
190      * Note that a deep copy is performed on the {@code Collection} to
191      * protect against subsequent modifications.
192      *
193      * @param names a {@code Collection} of names (or {@code null})
194      * @throws IOException if a parsing error occurs
195      * @see #getIssuerNames
196      */
setIssuerNames(Collection<?> names)197     public void setIssuerNames(Collection<?> names) throws IOException {
198         if (names == null || names.size() == 0) {
199             issuerNames = null;
200             issuerX500Principals = null;
201         } else {
202             HashSet<Object> tempNames = cloneAndCheckIssuerNames(names);
203             // Ensure that we either set both of these or neither
204             issuerX500Principals = parseIssuerNames(tempNames);
205             issuerNames = tempNames;
206         }
207     }
208 
209     /**
210      * Adds a name to the issuerNames criterion. The issuer distinguished
211      * name in the {@code X509CRL} must match at least one of the specified
212      * distinguished names.
213      * <p>
214      * This method allows the caller to add a name to the set of issuer names
215      * which {@code X509CRLs} may contain. The specified name is added to
216      * any previous value for the issuerNames criterion.
217      * If the specified name is a duplicate, it may be ignored.
218      *
219      * @param issuer the issuer as X500Principal
220      * @since 1.5
221      */
addIssuer(X500Principal issuer)222     public void addIssuer(X500Principal issuer) {
223         addIssuerNameInternal(issuer.getEncoded(), issuer);
224     }
225 
226     /**
227      * <strong>Denigrated</strong>, use
228      * {@linkplain #addIssuer(X500Principal)} or
229      * {@linkplain #addIssuerName(byte[])} instead. This method should not be
230      * relied on as it can fail to match some CRLs because of a loss of
231      * encoding information in the RFC 2253 String form of some distinguished
232      * names.
233      * <p>
234      * Adds a name to the issuerNames criterion. The issuer distinguished
235      * name in the {@code X509CRL} must match at least one of the specified
236      * distinguished names.
237      * <p>
238      * This method allows the caller to add a name to the set of issuer names
239      * which {@code X509CRLs} may contain. The specified name is added to
240      * any previous value for the issuerNames criterion.
241      * If the specified name is a duplicate, it may be ignored.
242      *
243      * @param name the name in RFC 2253 form
244      * @throws IOException if a parsing error occurs
245      */
addIssuerName(String name)246     public void addIssuerName(String name) throws IOException {
247         addIssuerNameInternal(name, new X500Name(name).asX500Principal());
248     }
249 
250     /**
251      * Adds a name to the issuerNames criterion. The issuer distinguished
252      * name in the {@code X509CRL} must match at least one of the specified
253      * distinguished names.
254      * <p>
255      * This method allows the caller to add a name to the set of issuer names
256      * which {@code X509CRLs} may contain. The specified name is added to
257      * any previous value for the issuerNames criterion. If the specified name
258      * is a duplicate, it may be ignored.
259      * If a name is specified as a byte array, it should contain a single DER
260      * encoded distinguished name, as defined in X.501. The ASN.1 notation for
261      * this structure is as follows.
262      * <p>
263      * The name is provided as a byte array. This byte array should contain
264      * a single DER encoded distinguished name, as defined in X.501. The ASN.1
265      * notation for this structure appears in the documentation for
266      * {@link #setIssuerNames setIssuerNames(Collection names)}.
267      * <p>
268      * Note that the byte array supplied here is cloned to protect against
269      * subsequent modifications.
270      *
271      * @param name a byte array containing the name in ASN.1 DER encoded form
272      * @throws IOException if a parsing error occurs
273      */
addIssuerName(byte[] name)274     public void addIssuerName(byte[] name) throws IOException {
275         // clone because byte arrays are modifiable
276         addIssuerNameInternal(name.clone(), new X500Name(name).asX500Principal());
277     }
278 
279     /**
280      * A private method that adds a name (String or byte array) to the
281      * issuerNames criterion. The issuer distinguished
282      * name in the {@code X509CRL} must match at least one of the specified
283      * distinguished names.
284      *
285      * @param name the name in string or byte array form
286      * @param principal the name in X500Principal form
287      * @throws IOException if a parsing error occurs
288      */
addIssuerNameInternal(Object name, X500Principal principal)289     private void addIssuerNameInternal(Object name, X500Principal principal) {
290         if (issuerNames == null) {
291             issuerNames = new HashSet<Object>();
292         }
293         if (issuerX500Principals == null) {
294             issuerX500Principals = new HashSet<X500Principal>();
295         }
296         issuerNames.add(name);
297         issuerX500Principals.add(principal);
298     }
299 
300     /**
301      * Clone and check an argument of the form passed to
302      * setIssuerNames. Throw an IOException if the argument is malformed.
303      *
304      * @param names a {@code Collection} of names. Each entry is a
305      *              String or a byte array (the name, in string or ASN.1
306      *              DER encoded form, respectively). {@code null} is
307      *              not an acceptable value.
308      * @return a deep copy of the specified {@code Collection}
309      * @throws IOException if a parsing error occurs
310      */
cloneAndCheckIssuerNames(Collection<?> names)311     private static HashSet<Object> cloneAndCheckIssuerNames(Collection<?> names)
312         throws IOException
313     {
314         HashSet<Object> namesCopy = new HashSet<Object>();
315         Iterator<?> i = names.iterator();
316         while (i.hasNext()) {
317             Object nameObject = i.next();
318             if (!(nameObject instanceof byte []) &&
319                 !(nameObject instanceof String))
320                 throw new IOException("name not byte array or String");
321             if (nameObject instanceof byte [])
322                 namesCopy.add(((byte []) nameObject).clone());
323             else
324                 namesCopy.add(nameObject);
325         }
326         return(namesCopy);
327     }
328 
329     /**
330      * Clone an argument of the form passed to setIssuerNames.
331      * Throw a RuntimeException if the argument is malformed.
332      * <p>
333      * This method wraps cloneAndCheckIssuerNames, changing any IOException
334      * into a RuntimeException. This method should be used when the object being
335      * cloned has already been checked, so there should never be any exceptions.
336      *
337      * @param names a {@code Collection} of names. Each entry is a
338      *              String or a byte array (the name, in string or ASN.1
339      *              DER encoded form, respectively). {@code null} is
340      *              not an acceptable value.
341      * @return a deep copy of the specified {@code Collection}
342      * @throws RuntimeException if a parsing error occurs
343      */
cloneIssuerNames(Collection<Object> names)344     private static HashSet<Object> cloneIssuerNames(Collection<Object> names) {
345         try {
346             return cloneAndCheckIssuerNames(names);
347         } catch (IOException ioe) {
348             throw new RuntimeException(ioe);
349         }
350     }
351 
352     /**
353      * Parse an argument of the form passed to setIssuerNames,
354      * returning a Collection of issuerX500Principals.
355      * Throw an IOException if the argument is malformed.
356      *
357      * @param names a {@code Collection} of names. Each entry is a
358      *              String or a byte array (the name, in string or ASN.1
359      *              DER encoded form, respectively). <Code>Null</Code> is
360      *              not an acceptable value.
361      * @return a HashSet of issuerX500Principals
362      * @throws IOException if a parsing error occurs
363      */
parseIssuerNames(Collection<Object> names)364     private static HashSet<X500Principal> parseIssuerNames(Collection<Object> names)
365     throws IOException {
366         HashSet<X500Principal> x500Principals = new HashSet<X500Principal>();
367         for (Iterator<Object> t = names.iterator(); t.hasNext(); ) {
368             Object nameObject = t.next();
369             if (nameObject instanceof String) {
370                 x500Principals.add(new X500Name((String)nameObject).asX500Principal());
371             } else {
372                 try {
373                     x500Principals.add(new X500Principal((byte[])nameObject));
374                 } catch (IllegalArgumentException e) {
375                     throw (IOException)new IOException("Invalid name").initCause(e);
376                 }
377             }
378         }
379         return x500Principals;
380     }
381 
382     /**
383      * Sets the minCRLNumber criterion. The {@code X509CRL} must have a
384      * CRL number extension whose value is greater than or equal to the
385      * specified value. If {@code null}, no minCRLNumber check will be
386      * done.
387      *
388      * @param minCRL the minimum CRL number accepted (or {@code null})
389      */
setMinCRLNumber(BigInteger minCRL)390     public void setMinCRLNumber(BigInteger minCRL) {
391         this.minCRL = minCRL;
392     }
393 
394     /**
395      * Sets the maxCRLNumber criterion. The {@code X509CRL} must have a
396      * CRL number extension whose value is less than or equal to the
397      * specified value. If {@code null}, no maxCRLNumber check will be
398      * done.
399      *
400      * @param maxCRL the maximum CRL number accepted (or {@code null})
401      */
setMaxCRLNumber(BigInteger maxCRL)402     public void setMaxCRLNumber(BigInteger maxCRL) {
403         this.maxCRL = maxCRL;
404     }
405 
406     /**
407      * Sets the dateAndTime criterion. The specified date must be
408      * equal to or later than the value of the thisUpdate component
409      * of the {@code X509CRL} and earlier than the value of the
410      * nextUpdate component. There is no match if the {@code X509CRL}
411      * does not contain a nextUpdate component.
412      * If {@code null}, no dateAndTime check will be done.
413      * <p>
414      * Note that the {@code Date} supplied here is cloned to protect
415      * against subsequent modifications.
416      *
417      * @param dateAndTime the {@code Date} to match against
418      *                    (or {@code null})
419      * @see #getDateAndTime
420      */
setDateAndTime(Date dateAndTime)421     public void setDateAndTime(Date dateAndTime) {
422         if (dateAndTime == null)
423             this.dateAndTime = null;
424         else
425             this.dateAndTime = new Date(dateAndTime.getTime());
426         this.skew = 0;
427     }
428 
429     /**
430      * Sets the dateAndTime criterion and allows for the specified clock skew
431      * (in milliseconds) when checking against the validity period of the CRL.
432      */
setDateAndTime(Date dateAndTime, long skew)433     void setDateAndTime(Date dateAndTime, long skew) {
434         this.dateAndTime =
435             (dateAndTime == null ? null : new Date(dateAndTime.getTime()));
436         this.skew = skew;
437     }
438 
439     /**
440      * Sets the certificate being checked. This is not a criterion. Rather,
441      * it is optional information that may help a {@code CertStore}
442      * find CRLs that would be relevant when checking revocation for the
443      * specified certificate. If {@code null} is specified, then no
444      * such optional information is provided.
445      *
446      * @param cert the {@code X509Certificate} being checked
447      *             (or {@code null})
448      * @see #getCertificateChecking
449      */
setCertificateChecking(X509Certificate cert)450     public void setCertificateChecking(X509Certificate cert) {
451         certChecking = cert;
452     }
453 
454     /**
455      * Returns the issuerNames criterion. The issuer distinguished
456      * name in the {@code X509CRL} must match at least one of the specified
457      * distinguished names. If the value returned is {@code null}, any
458      * issuer distinguished name will do.
459      * <p>
460      * If the value returned is not {@code null}, it is a
461      * unmodifiable {@code Collection} of {@code X500Principal}s.
462      *
463      * @return an unmodifiable {@code Collection} of names
464      *   (or {@code null})
465      * @see #setIssuers
466      * @since 1.5
467      */
getIssuers()468     public Collection<X500Principal> getIssuers() {
469         if (issuerX500Principals == null) {
470             return null;
471         }
472         return Collections.unmodifiableCollection(issuerX500Principals);
473     }
474 
475     /**
476      * Returns a copy of the issuerNames criterion. The issuer distinguished
477      * name in the {@code X509CRL} must match at least one of the specified
478      * distinguished names. If the value returned is {@code null}, any
479      * issuer distinguished name will do.
480      * <p>
481      * If the value returned is not {@code null}, it is a
482      * {@code Collection} of names. Each name is a {@code String}
483      * or a byte array representing a distinguished name (in RFC 2253 or
484      * ASN.1 DER encoded form, respectively).  Note that the
485      * {@code Collection} returned may contain duplicate names.
486      * <p>
487      * If a name is specified as a byte array, it should contain a single DER
488      * encoded distinguished name, as defined in X.501. The ASN.1 notation for
489      * this structure is given in the documentation for
490      * {@link #setIssuerNames setIssuerNames(Collection names)}.
491      * <p>
492      * Note that a deep copy is performed on the {@code Collection} to
493      * protect against subsequent modifications.
494      *
495      * @return a {@code Collection} of names (or {@code null})
496      * @see #setIssuerNames
497      */
getIssuerNames()498     public Collection<Object> getIssuerNames() {
499         if (issuerNames == null) {
500             return null;
501         }
502         return cloneIssuerNames(issuerNames);
503     }
504 
505     /**
506      * Returns the minCRLNumber criterion. The {@code X509CRL} must have a
507      * CRL number extension whose value is greater than or equal to the
508      * specified value. If {@code null}, no minCRLNumber check will be done.
509      *
510      * @return the minimum CRL number accepted (or {@code null})
511      */
getMinCRL()512     public BigInteger getMinCRL() {
513         return minCRL;
514     }
515 
516     /**
517      * Returns the maxCRLNumber criterion. The {@code X509CRL} must have a
518      * CRL number extension whose value is less than or equal to the
519      * specified value. If {@code null}, no maxCRLNumber check will be
520      * done.
521      *
522      * @return the maximum CRL number accepted (or {@code null})
523      */
getMaxCRL()524     public BigInteger getMaxCRL() {
525         return maxCRL;
526     }
527 
528     /**
529      * Returns the dateAndTime criterion. The specified date must be
530      * equal to or later than the value of the thisUpdate component
531      * of the {@code X509CRL} and earlier than the value of the
532      * nextUpdate component. There is no match if the
533      * {@code X509CRL} does not contain a nextUpdate component.
534      * If {@code null}, no dateAndTime check will be done.
535      * <p>
536      * Note that the {@code Date} returned is cloned to protect against
537      * subsequent modifications.
538      *
539      * @return the {@code Date} to match against (or {@code null})
540      * @see #setDateAndTime
541      */
getDateAndTime()542     public Date getDateAndTime() {
543         if (dateAndTime == null)
544             return null;
545         return (Date) dateAndTime.clone();
546     }
547 
548     /**
549      * Returns the certificate being checked. This is not a criterion. Rather,
550      * it is optional information that may help a {@code CertStore}
551      * find CRLs that would be relevant when checking revocation for the
552      * specified certificate. If the value returned is {@code null}, then
553      * no such optional information is provided.
554      *
555      * @return the certificate being checked (or {@code null})
556      * @see #setCertificateChecking
557      */
getCertificateChecking()558     public X509Certificate getCertificateChecking() {
559         return certChecking;
560     }
561 
562     /**
563      * Returns a printable representation of the {@code X509CRLSelector}.
564      *
565      * @return a {@code String} describing the contents of the
566      *         {@code X509CRLSelector}.
567      */
toString()568     public String toString() {
569         StringBuffer sb = new StringBuffer();
570         sb.append("X509CRLSelector: [\n");
571         if (issuerNames != null) {
572             sb.append("  IssuerNames:\n");
573             Iterator<Object> i = issuerNames.iterator();
574             while (i.hasNext())
575                 sb.append("    " + i.next() + "\n");
576         }
577         if (minCRL != null)
578             sb.append("  minCRLNumber: " + minCRL + "\n");
579         if (maxCRL != null)
580             sb.append("  maxCRLNumber: " + maxCRL + "\n");
581         if (dateAndTime != null)
582             sb.append("  dateAndTime: " + dateAndTime + "\n");
583         if (certChecking != null)
584             sb.append("  Certificate being checked: " + certChecking + "\n");
585         sb.append("]");
586         return sb.toString();
587     }
588 
589     /**
590      * Decides whether a {@code CRL} should be selected.
591      *
592      * @param crl the {@code CRL} to be checked
593      * @return {@code true} if the {@code CRL} should be selected,
594      *         {@code false} otherwise
595      */
match(CRL crl)596     public boolean match(CRL crl) {
597         if (!(crl instanceof X509CRL)) {
598             return false;
599         }
600         X509CRL xcrl = (X509CRL)crl;
601 
602         /* match on issuer name */
603         if (issuerNames != null) {
604             X500Principal issuer = xcrl.getIssuerX500Principal();
605             Iterator<X500Principal> i = issuerX500Principals.iterator();
606             boolean found = false;
607             while (!found && i.hasNext()) {
608                 if (i.next().equals(issuer)) {
609                     found = true;
610                 }
611             }
612             if (!found) {
613                 if (debug != null) {
614                     debug.println("X509CRLSelector.match: issuer DNs "
615                         + "don't match");
616                 }
617                 return false;
618             }
619         }
620 
621         if ((minCRL != null) || (maxCRL != null)) {
622             /* Get CRL number extension from CRL */
623             byte[] crlNumExtVal = xcrl.getExtensionValue("2.5.29.20");
624             if (crlNumExtVal == null) {
625                 if (debug != null) {
626                     debug.println("X509CRLSelector.match: no CRLNumber");
627                 }
628             }
629             BigInteger crlNum;
630             try {
631                 DerInputStream in = new DerInputStream(crlNumExtVal);
632                 byte[] encoded = in.getOctetString();
633                 CRLNumberExtension crlNumExt =
634                     new CRLNumberExtension(Boolean.FALSE, encoded);
635                 crlNum = crlNumExt.get(CRLNumberExtension.NUMBER);
636             } catch (IOException ex) {
637                 if (debug != null) {
638                     debug.println("X509CRLSelector.match: exception in "
639                         + "decoding CRL number");
640                 }
641                 return false;
642             }
643 
644             /* match on minCRLNumber */
645             if (minCRL != null) {
646                 if (crlNum.compareTo(minCRL) < 0) {
647                     if (debug != null) {
648                         debug.println("X509CRLSelector.match: CRLNumber too small");
649                     }
650                     return false;
651                 }
652             }
653 
654             /* match on maxCRLNumber */
655             if (maxCRL != null) {
656                 if (crlNum.compareTo(maxCRL) > 0) {
657                     if (debug != null) {
658                         debug.println("X509CRLSelector.match: CRLNumber too large");
659                     }
660                     return false;
661                 }
662             }
663         }
664 
665 
666         /* match on dateAndTime */
667         if (dateAndTime != null) {
668             Date crlThisUpdate = xcrl.getThisUpdate();
669             Date nextUpdate = xcrl.getNextUpdate();
670             if (nextUpdate == null) {
671                 if (debug != null) {
672                     debug.println("X509CRLSelector.match: nextUpdate null");
673                 }
674                 return false;
675             }
676             Date nowPlusSkew = dateAndTime;
677             Date nowMinusSkew = dateAndTime;
678             if (skew > 0) {
679                 nowPlusSkew = new Date(dateAndTime.getTime() + skew);
680                 nowMinusSkew = new Date(dateAndTime.getTime() - skew);
681             }
682 
683             // Check that the test date is within the validity interval:
684             //   [ thisUpdate - MAX_CLOCK_SKEW,
685             //     nextUpdate + MAX_CLOCK_SKEW ]
686             if (nowMinusSkew.after(nextUpdate)
687                 || nowPlusSkew.before(crlThisUpdate)) {
688                 if (debug != null) {
689                     debug.println("X509CRLSelector.match: update out-of-range");
690                 }
691                 return false;
692             }
693         }
694 
695         return true;
696     }
697 
698     /**
699      * Returns a copy of this object.
700      *
701      * @return the copy
702      */
clone()703     public Object clone() {
704         try {
705             X509CRLSelector copy = (X509CRLSelector)super.clone();
706             if (issuerNames != null) {
707                 copy.issuerNames =
708                         new HashSet<Object>(issuerNames);
709                 copy.issuerX500Principals =
710                         new HashSet<X500Principal>(issuerX500Principals);
711             }
712             return copy;
713         } catch (CloneNotSupportedException e) {
714             /* Cannot happen */
715             throw new InternalError(e.toString(), e);
716         }
717     }
718 }
719