Frames | No Frames |
1: /* X509CRLSelector.java -- selects X.509 CRLs by criteria. 2: Copyright (C) 2004 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.security.cert; 40: 41: import gnu.classpath.SystemProperties; 42: import gnu.java.lang.CPStringBuilder; 43: import gnu.java.security.der.DERReader; 44: import gnu.java.security.der.DERValue; 45: 46: import java.io.IOException; 47: import java.io.InputStream; 48: import java.math.BigInteger; 49: import java.util.ArrayList; 50: import java.util.Collection; 51: import java.util.Collections; 52: import java.util.Date; 53: import java.util.Iterator; 54: import java.util.LinkedList; 55: import java.util.List; 56: 57: import javax.security.auth.x500.X500Principal; 58: 59: /** 60: * A class for matching X.509 certificate revocation lists by criteria. 61: * 62: * <p>Use of this class requires extensive knowledge of the Internet 63: * Engineering Task Force's Public Key Infrastructure (X.509). The primary 64: * document describing this standard is <a 65: * href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509 66: * Public Key Infrastructure Certificate and Certificate Revocation List 67: * (CRL) Profile</a>. 68: * 69: * <p>Note that this class is not thread-safe. If multiple threads will 70: * use or modify this class then they need to synchronize on the object. 71: * 72: * @author Casey Marshall (csm@gnu.org) 73: * @since 1.4 74: */ 75: public class X509CRLSelector implements CRLSelector, Cloneable 76: { 77: 78: // Fields. 79: // ------------------------------------------------------------------------- 80: 81: private static final String CRL_NUMBER_ID = "2.5.29.20"; 82: 83: private List issuerNames; 84: private BigInteger maxCrlNumber; 85: private BigInteger minCrlNumber; 86: private Date date; 87: private X509Certificate cert; 88: 89: // Constructor. 90: // ------------------------------------------------------------------------- 91: 92: /** 93: * Creates a new CRL selector with no criteria enabled; i.e., every CRL 94: * will be matched. 95: */ 96: public X509CRLSelector() 97: { 98: } 99: 100: // Instance methods. 101: // ------------------------------------------------------------------------- 102: 103: /** 104: * Add an issuer name to the set of issuer names criteria, as the DER 105: * encoded form. 106: * 107: * @param name The name to add, as DER bytes. 108: * @throws IOException If the argument is not a valid DER-encoding. 109: */ 110: public void addIssuerName(byte[] name) throws IOException 111: { 112: X500Principal p = null; 113: try 114: { 115: p = new X500Principal(name); 116: } 117: catch (IllegalArgumentException iae) 118: { 119: IOException ioe = new IOException("malformed name"); 120: ioe.initCause(iae); 121: throw ioe; 122: } 123: if (issuerNames == null) 124: issuerNames = new LinkedList(); 125: issuerNames.add(p); 126: } 127: 128: /** 129: * Add an issuer name to the set of issuer names criteria, as a 130: * String representation. 131: * 132: * @param name The name to add. 133: * @throws IOException If the argument is not a valid name. 134: */ 135: public void addIssuerName(String name) throws IOException 136: { 137: X500Principal p = null; 138: try 139: { 140: p = new X500Principal(name); 141: } 142: catch (IllegalArgumentException iae) 143: { 144: IOException ioe = new IOException("malformed name: " + name); 145: ioe.initCause(iae); 146: throw ioe; 147: } 148: if (issuerNames == null) 149: issuerNames = new LinkedList(); 150: issuerNames.add(p); 151: } 152: 153: /** 154: * Sets the issuer names criterion. Pass <code>null</code> to clear this 155: * value. CRLs matched by this selector must have an issuer name in this 156: * set. 157: * 158: * @param names The issuer names. 159: * @throws IOException If any of the elements in the collection is not 160: * a valid name. 161: */ 162: public void setIssuerNames(Collection<?> names) throws IOException 163: { 164: if (names == null) 165: { 166: issuerNames = null; 167: return; 168: } 169: List l = new ArrayList(names.size()); 170: for (Iterator it = names.iterator(); it.hasNext(); ) 171: { 172: Object o = it.next(); 173: if (o instanceof X500Principal) 174: l.add(o); 175: else if (o instanceof String) 176: { 177: try 178: { 179: l.add(new X500Principal((String) o)); 180: } 181: catch (IllegalArgumentException iae) 182: { 183: IOException ioe = new IOException("malformed name: " + o); 184: ioe.initCause(iae); 185: throw ioe; 186: } 187: } 188: else if (o instanceof byte[]) 189: { 190: try 191: { 192: l.add(new X500Principal((byte[]) o)); 193: } 194: catch (IllegalArgumentException iae) 195: { 196: IOException ioe = new IOException("malformed name"); 197: ioe.initCause(iae); 198: throw ioe; 199: } 200: } 201: else if (o instanceof InputStream) 202: { 203: try 204: { 205: l.add(new X500Principal((InputStream) o)); 206: } 207: catch (IllegalArgumentException iae) 208: { 209: IOException ioe = new IOException("malformed name"); 210: ioe.initCause(iae); 211: throw ioe; 212: } 213: } 214: else 215: throw new IOException("not a valid name: " + 216: (o != null ? o.getClass().getName() : "null")); 217: 218: } 219: issuerNames = l; 220: } 221: 222: /** 223: * Returns the set of issuer names that are matched by this selector, 224: * or <code>null</code> if this criteria is not set. The returned 225: * collection is not modifiable. 226: * 227: * @return The set of issuer names. 228: */ 229: public Collection<Object> getIssuerNames() 230: { 231: if (issuerNames != null) 232: return Collections.unmodifiableList(issuerNames); 233: else 234: return null; 235: } 236: 237: /** 238: * Returns the maximum value of the CRLNumber extension present in 239: * CRLs matched by this selector, or <code>null</code> if this 240: * criteria is not set. 241: * 242: * @return The maximum CRL number. 243: */ 244: public BigInteger getMaxCRL() 245: { 246: return maxCrlNumber; 247: } 248: 249: /** 250: * Returns the minimum value of the CRLNumber extension present in 251: * CRLs matched by this selector, or <code>null</code> if this 252: * criteria is not set. 253: * 254: * @return The minimum CRL number. 255: */ 256: public BigInteger getMinCRL() 257: { 258: return minCrlNumber; 259: } 260: 261: /** 262: * Sets the maximum value of the CRLNumber extension present in CRLs 263: * matched by this selector. Specify <code>null</code> to clear this 264: * criterion. 265: * 266: * @param maxCrlNumber The maximum CRL number. 267: */ 268: public void setMaxCRLNumber(BigInteger maxCrlNumber) 269: { 270: this.maxCrlNumber = maxCrlNumber; 271: } 272: 273: /** 274: * Sets the minimum value of the CRLNumber extension present in CRLs 275: * matched by this selector. Specify <code>null</code> to clear this 276: * criterion. 277: * 278: * @param minCrlNumber The minimum CRL number. 279: */ 280: public void setMinCRLNumber(BigInteger minCrlNumber) 281: { 282: this.minCrlNumber = minCrlNumber; 283: } 284: 285: /** 286: * Returns the date when this CRL must be valid; that is, the date 287: * must be after the thisUpdate date, but before the nextUpdate date. 288: * Returns <code>null</code> if this criterion is not set. 289: * 290: * @return The date. 291: */ 292: public Date getDateAndTime() 293: { 294: return date != null ? (Date) date.clone() : null; 295: } 296: 297: /** 298: * Sets the date at which this CRL must be valid. Specify 299: * <code>null</code> to clear this criterion. 300: * 301: * @param date The date. 302: */ 303: public void setDateAndTime(Date date) 304: { 305: this.date = date != null ? (Date) date.clone() : null; 306: } 307: 308: /** 309: * Returns the certificate being checked, or <code>null</code> if this 310: * value is not set. 311: * 312: * @return The certificate. 313: */ 314: public X509Certificate getCertificateChecking() 315: { 316: return cert; 317: } 318: 319: /** 320: * Sets the certificate being checked. This is not a criterion, but 321: * info used by certificate store implementations to aid in searching. 322: * 323: * @param cert The certificate. 324: */ 325: public void setCertificateChecking(X509Certificate cert) 326: { 327: this.cert = cert; 328: } 329: 330: /** 331: * Returns a string representation of this selector. The string will 332: * only describe the enabled criteria, so if none are enabled this will 333: * return a string that contains little else besides the class name. 334: * 335: * @return The string. 336: */ 337: public String toString() 338: { 339: CPStringBuilder str = new CPStringBuilder(X509CRLSelector.class.getName()); 340: String nl = SystemProperties.getProperty("line.separator"); 341: String eol = ";" + nl; 342: 343: str.append(" {").append(nl); 344: if (issuerNames != null) 345: str.append(" issuer names = ").append(issuerNames).append(eol); 346: if (maxCrlNumber != null) 347: str.append(" max CRL = ").append(maxCrlNumber).append(eol); 348: if (minCrlNumber != null) 349: str.append(" min CRL = ").append(minCrlNumber).append(eol); 350: if (date != null) 351: str.append(" date = ").append(date).append(eol); 352: if (cert != null) 353: str.append(" certificate = ").append(cert).append(eol); 354: str.append("}").append(nl); 355: return str.toString(); 356: } 357: 358: /** 359: * Checks a CRL against the criteria of this selector, returning 360: * <code>true</code> if the given CRL matches all the criteria. 361: * 362: * @param _crl The CRL being checked. 363: * @return True if the CRL matches, false otherwise. 364: */ 365: public boolean match(CRL _crl) 366: { 367: if (!(_crl instanceof X509CRL)) 368: return false; 369: X509CRL crl = (X509CRL) _crl; 370: if (issuerNames != null) 371: { 372: if (!issuerNames.contains(crl.getIssuerX500Principal())) 373: return false; 374: } 375: BigInteger crlNumber = null; 376: if (maxCrlNumber != null) 377: { 378: byte[] b = crl.getExtensionValue(CRL_NUMBER_ID); 379: if (b == null) 380: return false; 381: try 382: { 383: DERValue val = DERReader.read(b); 384: if (!(val.getValue() instanceof BigInteger)) 385: return false; 386: crlNumber = (BigInteger) val.getValue(); 387: } 388: catch (IOException ioe) 389: { 390: return false; 391: } 392: if (maxCrlNumber.compareTo(crlNumber) < 0) 393: return false; 394: } 395: if (minCrlNumber != null) 396: { 397: if (crlNumber == null) 398: { 399: byte[] b = crl.getExtensionValue(CRL_NUMBER_ID); 400: if (b == null) 401: return false; 402: try 403: { 404: DERValue val = DERReader.read(b); 405: if (!(val.getValue() instanceof BigInteger)) 406: return false; 407: crlNumber = (BigInteger) val.getValue(); 408: } 409: catch (IOException ioe) 410: { 411: return false; 412: } 413: } 414: if (minCrlNumber.compareTo(crlNumber) > 0) 415: return false; 416: } 417: if (date != null) 418: { 419: if (date.compareTo(crl.getThisUpdate()) < 0 || 420: date.compareTo(crl.getNextUpdate()) > 0) 421: return false; 422: } 423: return true; 424: } 425: 426: /** 427: * Returns a copy of this object. 428: * 429: * @return The copy. 430: */ 431: public Object clone() 432: { 433: try 434: { 435: return super.clone(); 436: } 437: catch (CloneNotSupportedException shouldNotHappen) 438: { 439: throw new Error(shouldNotHappen); 440: } 441: } 442: }