diff options
Diffstat (limited to 'libraries/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CRLSelector.java')
-rw-r--r-- | libraries/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CRLSelector.java | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/libraries/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CRLSelector.java b/libraries/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CRLSelector.java new file mode 100644 index 000000000..6ddd43356 --- /dev/null +++ b/libraries/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CRLSelector.java @@ -0,0 +1,717 @@ +package org.spongycastle.jce.cert; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CRL; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Object; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.asn1.x509.X509Name; +import org.spongycastle.jce.PrincipalUtil; + +/** + * A <code>CRLSelector</code> that selects <code>X509CRLs</code> that match + * all specified criteria. This class is particularly useful when selecting CRLs + * from a <code>CertStore</code> to check revocation status of a particular + * certificate.<br /> + * <br /> + * When first constructed, an <code>X509CRLSelector</code> has no criteria + * enabled and each of the <code>get</code> methods return a default value (<code>null</code>). + * Therefore, the {@link #match match} method would return <code>true</code> + * for any <code>X509CRL</code>. Typically, several criteria are enabled (by + * calling {@link #setIssuerNames setIssuerNames} or + * {@link #setDateAndTime setDateAndTime}, for instance) and then the + * <code>X509CRLSelector</code> is passed to + * {@link CertStore#getCRLs CertStore.getCRLs} or some similar method.<br /> + * <br /> + * Please refer to RFC 2459 for definitions of the X.509 CRL fields and + * extensions mentioned below.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * Unless otherwise specified, the methods defined in this class are not + * thread-safe. Multiple threads that need to access a single object + * concurrently should synchronize amongst themselves and provide the necessary + * locking. Multiple threads each manipulating separate objects need not + * synchronize.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}, + * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier}, + * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object}, + * {@link org.spongycastle.asn1.x509.X509Name X509Name} + * + * @see CRLSelector + * @see X509CRL + */ +public class X509CRLSelector implements CRLSelector +{ + private Set issuerNames = null; + + private Set issuerNamesX509 = null; + + private BigInteger minCRL = null; + + private BigInteger maxCRL = null; + + private Date dateAndTime = null; + + private X509Certificate certChecking = null; + + /** + * Creates an <code>X509CRLSelector</code>. Initially, no criteria are + * set so any <code>X509CRL</code> will match. + */ + public X509CRLSelector() + { + } + + /** + * Sets the issuerNames criterion. The issuer distinguished name in the + * <code>X509CRL</code> must match at least one of the specified + * distinguished names. If <code>null</code>, any issuer distinguished + * name will do.<br /> + * <br /> + * This method allows the caller to specify, with a single method call, the + * complete set of issuer names which <code>X509CRLs</code> may contain. + * The specified value replaces the previous value for the issuerNames + * criterion.<br /> + * <br /> + * The <code>names</code> parameter (if not <code>null</code>) is a + * <code>Collection</code> of names. Each name is a <code>String</code> + * or a byte array representing a distinguished name (in RFC 2253 or ASN.1 + * DER encoded form, respectively). If <code>null</code> is supplied as + * the value for this argument, no issuerNames check will be performed.<br /> + * <br /> + * Note that the <code>names</code> parameter can contain duplicate + * distinguished names, but they may be removed from the + * <code>Collection</code> of names returned by the + * {@link #getIssuerNames getIssuerNames} method.<br /> + * <br /> + * If a name is specified as a byte array, it should contain a single DER + * encoded distinguished name, as defined in X.501. The ASN.1 notation for + * this structure is as follows. + * + * <pre><code> + * Name ::= CHOICE { + * RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RDN + * + * RDN ::= + * SET SIZE (1 .. MAX) OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * .... + * DirectoryString ::= CHOICE { + * teletexString TeletexString (SIZE (1..MAX)), + * printableString PrintableString (SIZE (1..MAX)), + * universalString UniversalString (SIZE (1..MAX)), + * utf8String UTF8String (SIZE (1.. MAX)), + * bmpString BMPString (SIZE (1..MAX)) } + * </code></pre> + * + * <br /> + * <br /> + * Note that a deep copy is performed on the <code>Collection</code> to + * protect against subsequent modifications. + * + * @param names + * a <code>Collection</code> of names (or <code>null</code>) + * + * @exception IOException + * if a parsing error occurs + * + * @see #getIssuerNames + */ + public void setIssuerNames(Collection names) throws IOException + { + if (names == null || names.isEmpty()) + { + issuerNames = null; + issuerNamesX509 = null; + } + else + { + Object item; + Iterator iter = names.iterator(); + while (iter.hasNext()) + { + item = iter.next(); + if (item instanceof String) + { + addIssuerName((String)item); + } + else if (item instanceof byte[]) + { + addIssuerName((byte[])item); + } + else + { + throw new IOException("name not byte[]or String: " + + item.toString()); + } + } + } + } + + /** + * Adds a name to the issuerNames criterion. The issuer distinguished name + * in the <code>X509CRL</code> must match at least one of the specified + * distinguished names.<br /> + * <br /> + * This method allows the caller to add a name to the set of issuer names + * which <code>X509CRLs</code> may contain. The specified name is added to + * any previous value for the issuerNames criterion. If the specified name + * is a duplicate, it may be ignored.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the + * name + * + * @param name + * the name in RFC 2253 form + * + * @exception IOException + * if a parsing error occurs + */ + public void addIssuerName(String name) throws IOException + { + if (issuerNames == null) + { + issuerNames = new HashSet(); + issuerNamesX509 = new HashSet(); + } + X509Name nameX509; + try + { + nameX509 = new X509Name(name); + } + catch (IllegalArgumentException ex) + { + throw new IOException(ex.getMessage()); + } + issuerNamesX509.add(nameX509); + issuerNames.add(name); + } + + /** + * Adds a name to the issuerNames criterion. The issuer distinguished name + * in the <code>X509CRL</code> must match at least one of the specified + * distinguished names.<br /> + * <br /> + * This method allows the caller to add a name to the set of issuer names + * which <code>X509CRLs</code> may contain. The specified name is added to + * any previous value for the issuerNames criterion. If the specified name + * is a duplicate, it may be ignored. If a name is specified as a byte + * array, it should contain a single DER encoded distinguished name, as + * defined in X.501. The ASN.1 notation for this structure is as follows.<br /> + * <br /> + * The name is provided as a byte array. This byte array should contain a + * single DER encoded distinguished name, as defined in X.501. The ASN.1 + * notation for this structure appears in the documentation for + * {@link #setIssuerNames setIssuerNames(Collection names)}.<br /> + * <br /> + * Note that the byte array supplied here is cloned to protect against + * subsequent modifications.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the + * name, {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object} and + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence} + * + * @param name + * a byte array containing the name in ASN.1 DER encoded form + * + * @exception IOException + * if a parsing error occurs + */ + public void addIssuerName(byte[] name) throws IOException + { + if (issuerNames == null) + { + issuerNames = new HashSet(); + issuerNamesX509 = new HashSet(); + } + + ByteArrayInputStream inStream = new ByteArrayInputStream(name); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object obj = derInStream.readObject(); + if (obj instanceof ASN1Sequence) + { + issuerNamesX509.add(new X509Name((ASN1Sequence)obj)); + } + else + { + throw new IOException("parsing error"); + } + issuerNames.add(name.clone()); + } + + /** + * Sets the minCRLNumber criterion. The <code>X509CRL</code> must have a + * CRL number extension whose value is greater than or equal to the + * specified value. If <code>null</code>, no minCRLNumber check will be + * done. + * + * @param minCRL + * the minimum CRL number accepted (or <code>null</code>) + */ + public void setMinCRLNumber(BigInteger minCRL) + { + this.minCRL = minCRL; + } + + /** + * Sets the maxCRLNumber criterion. The <code>X509CRL</code> must have a + * CRL number extension whose value is less than or equal to the specified + * value. If <code>null</code>, no maxCRLNumber check will be done. + * + * @param maxCRL + * the maximum CRL number accepted (or <code>null</code>) + */ + public void setMaxCRLNumber(BigInteger maxCRL) + { + this.maxCRL = maxCRL; + } + + /** + * Sets the dateAndTime criterion. The specified date must be equal to or + * later than the value of the thisUpdate component of the + * <code>X509CRL</code> and earlier than the value of the nextUpdate + * component. There is no match if the <code>X509CRL</code> does not + * contain a nextUpdate component. If <code>null</code>, no dateAndTime + * check will be done.<br /> + * <br /> + * Note that the <code>Date</code> supplied here is cloned to protect + * against subsequent modifications. + * + * @param dateAndTime + * the <code>Date</code> to match against (or <code>null</code>) + * + * @see #getDateAndTime + */ + public void setDateAndTime(Date dateAndTime) + { + if (dateAndTime == null) + { + this.dateAndTime = null; + } + else + { + this.dateAndTime = new Date(dateAndTime.getTime()); + } + } + + /** + * Sets the certificate being checked. This is not a criterion. Rather, it + * is optional information that may help a <code>CertStore</code> find + * CRLs that would be relevant when checking revocation for the specified + * certificate. If <code>null</code> is specified, then no such optional + * information is provided. + * + * @param cert + * the <code>X509Certificate</code> being checked (or + * <code>null</code>) + * + * @see #getCertificateChecking + */ + public void setCertificateChecking(X509Certificate cert) + { + certChecking = cert; + } + + /** + * Returns a copy of the issuerNames criterion. The issuer distinguished + * name in the <code>X509CRL</code> must match at least one of the + * specified distinguished names. If the value returned is <code>null</code>, + * any issuer distinguished name will do.<br /> + * <br /> + * If the value returned is not <code>null</code>, it is a + * <code>Collection</code> of names. Each name is a <code>String</code> + * or a byte array representing a distinguished name (in RFC 2253 or ASN.1 + * DER encoded form, respectively). Note that the <code>Collection</code> + * returned may contain duplicate names.<br /> + * <br /> + * If a name is specified as a byte array, it should contain a single DER + * encoded distinguished name, as defined in X.501. The ASN.1 notation for + * this structure is given in the documentation for + * {@link #setIssuerNames setIssuerNames(Collection names)}.<br /> + * <br /> + * Note that a deep copy is performed on the <code>Collection</code> to + * protect against subsequent modifications. + * + * @return a <code>Collection</code> of names (or <code>null</code>) + * @see #setIssuerNames + */ + public Collection getIssuerNames() + { + if (issuerNames == null) + { + return null; + } + + Collection set = new HashSet(); + Iterator iter = issuerNames.iterator(); + Object item; + while (iter.hasNext()) + { + item = iter.next(); + if (item instanceof String) + { + set.add(new String((String)item)); + } + else if (item instanceof byte[]) + { + set.add(((byte[])item).clone()); + } + } + return set; + } + + /** + * Returns the minCRLNumber criterion. The <code>X509CRL</code> must have + * a CRL number extension whose value is greater than or equal to the + * specified value. If <code>null</code>, no minCRLNumber check will be + * done. + * + * @return the minimum CRL number accepted (or <code>null</code>) + */ + public BigInteger getMinCRL() + { + return minCRL; + } + + /** + * Returns the maxCRLNumber criterion. The <code>X509CRL</code> must have + * a CRL number extension whose value is less than or equal to the specified + * value. If <code>null</code>, no maxCRLNumber check will be done. + * + * @return the maximum CRL number accepted (or <code>null</code>) + */ + public BigInteger getMaxCRL() + { + return maxCRL; + } + + /** + * Returns the dateAndTime criterion. The specified date must be equal to or + * later than the value of the thisUpdate component of the + * <code>X509CRL</code> and earlier than the value of the nextUpdate + * component. There is no match if the <code>X509CRL</code> does not + * contain a nextUpdate component. If <code>null</code>, no dateAndTime + * check will be done.<br /> + * <br /> + * Note that the <code>Date</code> returned is cloned to protect against + * subsequent modifications. + * + * @return the <code>Date</code> to match against (or <code>null</code>) + * + * @see #setDateAndTime + */ + public Date getDateAndTime() + { + if (dateAndTime == null) + { + return null; + } + + return new Date(dateAndTime.getTime()); + } + + /** + * Returns the certificate being checked. This is not a criterion. Rather, + * it is optional information that may help a <code>CertStore</code> find + * CRLs that would be relevant when checking revocation for the specified + * certificate. If the value returned is <code>null</code>, then no such + * optional information is provided. + * + * @return the certificate being checked (or <code>null</code>) + * + * @see #setCertificateChecking + */ + public X509Certificate getCertificateChecking() + { + return certChecking; + } + + /** + * Returns a printable representation of the <code>X509CRLSelector</code>.<br /> + * <br /> + * Uses + * {@link org.spongycastle.asn1.x509.X509Name#toString X509Name.toString} to + * format the output + * + * @return a <code>String</code> describing the contents of the + * <code>X509CRLSelector</code>. + */ + public String toString() + { + StringBuffer s = new StringBuffer(); + s.append("X509CRLSelector: [\n"); + if (issuerNamesX509 != null) + { + s.append(" IssuerNames:\n"); + Iterator iter = issuerNamesX509.iterator(); + while (iter.hasNext()) + { + s.append(" ").append(iter.next()).append('\n'); + } + } + if (minCRL != null) + { + s.append(" minCRLNumber: ").append(minCRL).append('\n'); + } + if (maxCRL != null) + { + s.append(" maxCRLNumber: ").append(maxCRL).append('\n'); + } + if (dateAndTime != null) + { + s.append(" dateAndTime: ").append(dateAndTime).append('\n'); + } + if (certChecking != null) + { + s.append(" Certificate being checked: ").append(certChecking).append('\n'); + } + s.append(']'); + return s.toString(); + } + + /** + * Decides whether a <code>CRL</code> should be selected.<br /> + * <br /> + * Uses + * {@link org.spongycastle.asn1.x509.X509Name#toString X509Name.toString} to + * parse and to compare the crl parameter issuer and + * {@link org.spongycastle.asn1.x509.X509Extensions#CRLNumber CRLNumber} to + * access the CRL number extension. + * + * @param crl + * the <code>CRL</code> to be checked + * + * @return <code>true</code> if the <code>CRL</code> should be selected, + * <code>false</code> otherwise + */ + public boolean match(CRL crl) + { + if (!(crl instanceof X509CRL)) + { + return false; + } + + X509CRL crlX509 = (X509CRL)crl; + boolean test; + + if (issuerNamesX509 != null) + { + Iterator iter = issuerNamesX509.iterator(); + test = false; + X509Name crlIssuer = null; + try + { + crlIssuer = PrincipalUtil.getIssuerX509Principal(crlX509); + } + catch (Exception ex) + { + + return false; + } + + while (iter.hasNext()) + { + if (crlIssuer.equals(iter.next(), true)) + { + test = true; + break; + } + } + if (!test) + { + return false; + } + } + + byte[] data = crlX509.getExtensionValue(X509Extensions.CRLNumber + .getId()); + if (data != null) + { + try + { + ByteArrayInputStream inStream = new ByteArrayInputStream(data); + ASN1InputStream derInputStream = new ASN1InputStream(inStream); + inStream = new ByteArrayInputStream( + ((ASN1OctetString)derInputStream.readObject()) + .getOctets()); + derInputStream = new ASN1InputStream(inStream); + BigInteger crlNumber = ((DERInteger)derInputStream.readObject()) + .getPositiveValue(); + if (minCRL != null && minCRL.compareTo(crlNumber) > 0) + { + return false; + } + if (maxCRL != null && maxCRL.compareTo(crlNumber) < 0) + { + return false; + } + } + catch (IOException ex) + { + return false; + } + } + else if (minCRL != null || maxCRL != null) + { + return false; + } + + if (dateAndTime != null) + { + Date check = crlX509.getThisUpdate(); + if (check == null) + { + return false; + } + else if (dateAndTime.before(check)) + { + return false; + } + + check = crlX509.getNextUpdate(); + if (check == null) + { + return false; + } + else if (!dateAndTime.before(check)) + { + return false; + } + } + + return true; + } + + /** + * Returns a copy of this object. + * + * @return the copy + */ + public Object clone() + { + try + { + X509CRLSelector copy = (X509CRLSelector)super.clone(); + if (issuerNames != null) + { + copy.issuerNames = new HashSet(); + Iterator iter = issuerNames.iterator(); + Object obj; + while (iter.hasNext()) + { + obj = iter.next(); + if (obj instanceof byte[]) + { + copy.issuerNames.add(((byte[])obj).clone()); + } + else + { + copy.issuerNames.add(obj); + } + } + copy.issuerNamesX509 = new HashSet(issuerNamesX509); + } + return copy; + } + catch (CloneNotSupportedException e) + { + /* Cannot happen */ + throw new InternalError(e.toString()); + } + } + + /** + * Decides whether a <code>CRL</code> should be selected. + * + * @param crl + * the <code>CRL</code> to be checked + * + * @return <code>true</code> if the <code>CRL</code> should be selected, + * <code>false</code> otherwise + */ + public boolean equals(Object obj) + { + if (!(obj instanceof X509CRLSelector)) + { + return false; + } + + X509CRLSelector equalsCRL = (X509CRLSelector)obj; + + if (!equals(dateAndTime, equalsCRL.dateAndTime)) + { + return false; + } + + if (!equals(minCRL, equalsCRL.minCRL)) + { + return false; + } + + if (!equals(maxCRL, equalsCRL.maxCRL)) + { + return false; + } + + if (!equals(issuerNamesX509, equalsCRL.issuerNamesX509)) + { + return false; + } + + if (!equals(certChecking, equalsCRL.certChecking)) + { + return false; + } + + return true; + } + + /** + * Return <code>true</code> if two Objects are unequal. + * This means that one is <code>null</code> and the other is + * not or <code>obj1.equals(obj2)</code> returns + * <code>false</code>. + **/ + private boolean equals(Object obj1, Object obj2) + { + if (obj1 == null) + { + if (obj2 != null) + { + return true; + } + } + else if (!obj1.equals(obj2)) + { + return true; + } + return false; + } +}
\ No newline at end of file |