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