| /* X509CRLSelector.java -- selects X.509 CRLs by criteria. |
| Copyright (C) 2004 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package java.security.cert; |
| |
| import gnu.classpath.SystemProperties; |
| import gnu.java.security.der.DERReader; |
| import gnu.java.security.der.DERValue; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.math.BigInteger; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import javax.security.auth.x500.X500Principal; |
| |
| /** |
| * A class for matching X.509 certificate revocation lists by criteria. |
| * |
| * <p>Use of this class requires extensive knowledge of the Internet |
| * Engineering Task Force's Public Key Infrastructure (X.509). The primary |
| * document describing this standard is <a |
| * href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509 |
| * Public Key Infrastructure Certificate and Certificate Revocation List |
| * (CRL) Profile</a>. |
| * |
| * <p>Note that this class is not thread-safe. If multiple threads will |
| * use or modify this class then they need to synchronize on the object. |
| * |
| * @author Casey Marshall (csm@gnu.org) |
| */ |
| public class X509CRLSelector implements CRLSelector, Cloneable |
| { |
| |
| // Fields. |
| // ------------------------------------------------------------------------- |
| |
| private static final String CRL_NUMBER_ID = "2.5.29.20"; |
| |
| private List issuerNames; |
| private BigInteger maxCrlNumber; |
| private BigInteger minCrlNumber; |
| private Date date; |
| private X509Certificate cert; |
| |
| // Constructor. |
| // ------------------------------------------------------------------------- |
| |
| /** |
| * Creates a new CRL selector with no criteria enabled; i.e., every CRL |
| * will be matched. |
| */ |
| public X509CRLSelector() |
| { |
| } |
| |
| // Instance methods. |
| // ------------------------------------------------------------------------- |
| |
| /** |
| * Add an issuer name to the set of issuer names criteria, as the DER |
| * encoded form. |
| * |
| * @param name The name to add, as DER bytes. |
| * @throws IOException If the argument is not a valid DER-encoding. |
| */ |
| public void addIssuerName(byte[] name) throws IOException |
| { |
| X500Principal p = null; |
| try |
| { |
| p = new X500Principal(name); |
| } |
| catch (IllegalArgumentException iae) |
| { |
| IOException ioe = new IOException("malformed name"); |
| ioe.initCause(iae); |
| throw ioe; |
| } |
| if (issuerNames == null) |
| issuerNames = new LinkedList(); |
| issuerNames.add(p); |
| } |
| |
| /** |
| * Add an issuer name to the set of issuer names criteria, as a |
| * String representation. |
| * |
| * @param name The name to add. |
| * @throws IOException If the argument is not a valid name. |
| */ |
| public void addIssuerName(String name) throws IOException |
| { |
| X500Principal p = null; |
| try |
| { |
| p = new X500Principal(name); |
| } |
| catch (IllegalArgumentException iae) |
| { |
| IOException ioe = new IOException("malformed name: " + name); |
| ioe.initCause(iae); |
| throw ioe; |
| } |
| if (issuerNames == null) |
| issuerNames = new LinkedList(); |
| issuerNames.add(p); |
| } |
| |
| /** |
| * Sets the issuer names criterion. Pass <code>null</code> to clear this |
| * value. CRLs matched by this selector must have an issuer name in this |
| * set. |
| * |
| * @param names The issuer names. |
| * @throws IOException If any of the elements in the collection is not |
| * a valid name. |
| */ |
| public void setIssuerNames(Collection names) throws IOException |
| { |
| if (names == null) |
| { |
| issuerNames = null; |
| return; |
| } |
| List l = new ArrayList(names.size()); |
| for (Iterator it = names.iterator(); it.hasNext(); ) |
| { |
| Object o = it.next(); |
| if (o instanceof X500Principal) |
| l.add(o); |
| else if (o instanceof String) |
| { |
| try |
| { |
| l.add(new X500Principal((String) o)); |
| } |
| catch (IllegalArgumentException iae) |
| { |
| IOException ioe = new IOException("malformed name: " + o); |
| ioe.initCause(iae); |
| throw ioe; |
| } |
| } |
| else if (o instanceof byte[]) |
| { |
| try |
| { |
| l.add(new X500Principal((byte[]) o)); |
| } |
| catch (IllegalArgumentException iae) |
| { |
| IOException ioe = new IOException("malformed name"); |
| ioe.initCause(iae); |
| throw ioe; |
| } |
| } |
| else if (o instanceof InputStream) |
| { |
| try |
| { |
| l.add(new X500Principal((InputStream) o)); |
| } |
| catch (IllegalArgumentException iae) |
| { |
| IOException ioe = new IOException("malformed name"); |
| ioe.initCause(iae); |
| throw ioe; |
| } |
| } |
| else |
| throw new IOException("not a valid name: " + |
| (o != null ? o.getClass().getName() : "null")); |
| |
| } |
| issuerNames = l; |
| } |
| |
| /** |
| * Returns the set of issuer names that are matched by this selector, |
| * or <code>null</code> if this criteria is not set. The returned |
| * collection is not modifiable. |
| * |
| * @return The set of issuer names. |
| */ |
| public Collection getIssuerNames() |
| { |
| if (issuerNames != null) |
| return Collections.unmodifiableList(issuerNames); |
| else |
| return null; |
| } |
| |
| /** |
| * Returns the maximum value of the CRLNumber extension present in |
| * CRLs matched by this selector, or <code>null</code> if this |
| * criteria is not set. |
| * |
| * @return The maximum CRL number. |
| */ |
| public BigInteger getMaxCRL() |
| { |
| return maxCrlNumber; |
| } |
| |
| /** |
| * Returns the minimum value of the CRLNumber extension present in |
| * CRLs matched by this selector, or <code>null</code> if this |
| * criteria is not set. |
| * |
| * @return The minimum CRL number. |
| */ |
| public BigInteger getMinCRL() |
| { |
| return minCrlNumber; |
| } |
| |
| /** |
| * Sets the maximum value of the CRLNumber extension present in CRLs |
| * matched by this selector. Specify <code>null</code> to clear this |
| * criterion. |
| * |
| * @param maxCrlNumber The maximum CRL number. |
| */ |
| public void setMaxCRLNumber(BigInteger maxCrlNumber) |
| { |
| this.maxCrlNumber = maxCrlNumber; |
| } |
| |
| /** |
| * Sets the minimum value of the CRLNumber extension present in CRLs |
| * matched by this selector. Specify <code>null</code> to clear this |
| * criterion. |
| * |
| * @param minCrlNumber The minimum CRL number. |
| */ |
| public void setMinCRLNumber(BigInteger minCrlNumber) |
| { |
| this.minCrlNumber = minCrlNumber; |
| } |
| |
| /** |
| * Returns the date when this CRL must be valid; that is, the date |
| * must be after the thisUpdate date, but before the nextUpdate date. |
| * Returns <code>null</code> if this criterion is not set. |
| * |
| * @return The date. |
| */ |
| public Date getDateAndTime() |
| { |
| return date != null ? (Date) date.clone() : null; |
| } |
| |
| /** |
| * Sets the date at which this CRL must be valid. Specify |
| * <code>null</code> to clear this criterion. |
| * |
| * @param date The date. |
| */ |
| public void setDateAndTime(Date date) |
| { |
| this.date = date != null ? (Date) date.clone() : null; |
| } |
| |
| /** |
| * Returns the certificate being checked, or <code>null</code> if this |
| * value is not set. |
| * |
| * @return The certificate. |
| */ |
| public X509Certificate getCertificateChecking() |
| { |
| return cert; |
| } |
| |
| /** |
| * Sets the certificate being checked. This is not a criterion, but |
| * info used by certificate store implementations to aid in searching. |
| * |
| * @param cert The certificate. |
| */ |
| public void setCertificateChecking(X509Certificate cert) |
| { |
| this.cert = cert; |
| } |
| |
| /** |
| * Returns a string representation of this selector. The string will |
| * only describe the enabled criteria, so if none are enabled this will |
| * return a string that contains little else besides the class name. |
| * |
| * @return The string. |
| */ |
| public String toString() |
| { |
| StringBuffer str = new StringBuffer(X509CRLSelector.class.getName()); |
| String nl = SystemProperties.getProperty("line.separator"); |
| String eol = ";" + nl; |
| |
| str.append(" {").append(nl); |
| if (issuerNames != null) |
| str.append(" issuer names = ").append(issuerNames).append(eol); |
| if (maxCrlNumber != null) |
| str.append(" max CRL = ").append(maxCrlNumber).append(eol); |
| if (minCrlNumber != null) |
| str.append(" min CRL = ").append(minCrlNumber).append(eol); |
| if (date != null) |
| str.append(" date = ").append(date).append(eol); |
| if (cert != null) |
| str.append(" certificate = ").append(cert).append(eol); |
| str.append("}").append(nl); |
| return str.toString(); |
| } |
| |
| /** |
| * Checks a CRL against the criteria of this selector, returning |
| * <code>true</code> if the given CRL matches all the criteria. |
| * |
| * @param _crl The CRL being checked. |
| * @return True if the CRL matches, false otherwise. |
| */ |
| public boolean match(CRL _crl) |
| { |
| if (!(_crl instanceof X509CRL)) |
| return false; |
| X509CRL crl = (X509CRL) _crl; |
| if (issuerNames != null) |
| { |
| if (!issuerNames.contains(crl.getIssuerX500Principal())) |
| return false; |
| } |
| BigInteger crlNumber = null; |
| if (maxCrlNumber != null) |
| { |
| byte[] b = crl.getExtensionValue(CRL_NUMBER_ID); |
| if (b == null) |
| return false; |
| try |
| { |
| DERValue val = DERReader.read(b); |
| if (!(val.getValue() instanceof BigInteger)) |
| return false; |
| crlNumber = (BigInteger) val.getValue(); |
| } |
| catch (IOException ioe) |
| { |
| return false; |
| } |
| if (maxCrlNumber.compareTo(crlNumber) < 0) |
| return false; |
| } |
| if (minCrlNumber != null) |
| { |
| if (crlNumber == null) |
| { |
| byte[] b = crl.getExtensionValue(CRL_NUMBER_ID); |
| if (b == null) |
| return false; |
| try |
| { |
| DERValue val = DERReader.read(b); |
| if (!(val.getValue() instanceof BigInteger)) |
| return false; |
| crlNumber = (BigInteger) val.getValue(); |
| } |
| catch (IOException ioe) |
| { |
| return false; |
| } |
| } |
| if (minCrlNumber.compareTo(crlNumber) > 0) |
| return false; |
| } |
| if (date != null) |
| { |
| if (date.compareTo(crl.getThisUpdate()) < 0 || |
| date.compareTo(crl.getNextUpdate()) > 0) |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Returns a copy of this object. |
| * |
| * @return The copy. |
| */ |
| public Object clone() |
| { |
| try |
| { |
| return super.clone(); |
| } |
| catch (CloneNotSupportedException shouldNotHappen) |
| { |
| throw new Error(shouldNotHappen); |
| } |
| } |
| } |