1 /*
   2  * Copyright (c) 2000, 2013, 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 {
  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      */
  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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 568     public String toString() {
 569         StringBuilder sb = new StringBuilder();
 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      */
 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             if (nowMinusSkew.after(nextUpdate)
 683                 || nowPlusSkew.before(crlThisUpdate)) {
 684                 if (debug != null) {
 685                     debug.println("X509CRLSelector.match: update out of range");
 686                 }
 687                 return false;
 688             }
 689         }
 690 
 691         return true;
 692     }
 693 
 694     /**
 695      * Returns a copy of this object.
 696      *
 697      * @return the copy
 698      */
 699     public Object clone() {
 700         try {
 701             X509CRLSelector copy = (X509CRLSelector)super.clone();
 702             if (issuerNames != null) {
 703                 copy.issuerNames =
 704                         new HashSet<Object>(issuerNames);
 705                 copy.issuerX500Principals =
 706                         new HashSet<X500Principal>(issuerX500Principals);
 707             }
 708             return copy;
 709         } catch (CloneNotSupportedException e) {
 710             /* Cannot happen */
 711             throw new InternalError(e.toString(), e);
 712         }
 713     }
 714 }