Index: java/security/cert/X509CRLSelector.java =================================================================== RCS file: java/security/cert/X509CRLSelector.java diff -N java/security/cert/X509CRLSelector.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ java/security/cert/X509CRLSelector.java 21 Aug 2004 06:53:04 -0000 @@ -0,0 +1,459 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 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 java.io.IOException; +import java.io.InputStream; + +import java.math.BigInteger; + +import java.security.AccessController; + +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; + +import gnu.java.security.action.GetPropertyAction; +import gnu.java.security.der.DERReader; +import gnu.java.security.der.DERValue; + +/** + * A class for matching X.509 certificate revocation lists by criteria. + * + *
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 RFC 3280: Internet X.509 + * Public Key Infrastructure Certificate and Certificate Revocation List + * (CRL) Profile. + * + *
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 (address@hidden)
+ */
+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 null
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 null
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 null
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 null
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 null
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 null
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 null
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
+ * null
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 null
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());
+ GetPropertyAction getProp = new GetPropertyAction("line.separator");
+ String nl = (String) AccessController.doPrivileged(getProp);
+ 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
+ * true
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)
+ {
+ try
+ {
+ 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;
+ }
+ catch (CertificateParsingException cpe)
+ {
+ return false;
+ }
+ }
+ if (minCrlNumber != null)
+ {
+ try
+ {
+ 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;
+ }
+ catch (CertificateParsingException cpe)
+ {
+ 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);
+ }
+ }
+}
Index: java/security/cert/X509CertSelector.java
===================================================================
RCS file: java/security/cert/X509CertSelector.java
diff -N java/security/cert/X509CertSelector.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ java/security/cert/X509CertSelector.java 21 Aug 2004 06:53:04 -0000
@@ -0,0 +1,1111 @@
+/* X509CertSelector.java -- selects X.509 certificates 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., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 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 java.io.IOException;
+
+import java.math.BigInteger;
+
+import java.security.AccessController;
+import java.security.KeyFactory;
+import java.security.PublicKey;
+import java.security.spec.X509EncodedKeySpec;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+import gnu.java.security.OID;
+import gnu.java.security.action.GetPropertyAction;
+
+/**
+ * A concrete implementation of address@hidden CertSelector} for X.509 certificates,
+ * which allows a number of criteria to be set when accepting certificates,
+ * from validity dates, to issuer and subject distinguished names, to some
+ * of the various X.509 extensions.
+ *
+ *
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 RFC 3280: Internet X.509 + * Public Key Infrastructure Certificate and Certificate Revocation List + * (CRL) Profile. + * + *
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 (address@hidden)
+ */
+public class X509CertSelector implements CertSelector, Cloneable
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ private static final String AUTH_KEY_ID = "2.5.29.35";
+ private static final String SUBJECT_KEY_ID = "2.5.29.14";
+ private static final String NAME_CONSTRAINTS_ID = "2.5.29.30";
+
+ private int basicConstraints;
+ private X509Certificate cert;
+ private BigInteger serialNo;
+ private X500Principal issuer;
+ private X500Principal subject;
+ private byte[] subjectKeyId;
+ private byte[] authKeyId;
+ private boolean[] keyUsage;
+ private Date certValid;
+ private OID sigId;
+ private PublicKey subjectKey;
+ private X509EncodedKeySpec subjectKeySpec;
+ private Set keyPurposeSet;
+ private List altNames;
+ private boolean matchAllNames;
+ private byte[] nameConstraints;
+ private Set policy;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new X.509 certificate selector. The new selector will be
+ * empty, and will accept any certificate (provided that it is an
+ * address@hidden X509Certificate}).
+ */
+ public X509CertSelector()
+ {
+ basicConstraints = -1;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the certificate criterion, or null
if this value
+ * was not set.
+ *
+ * @return The certificate.
+ */
+ public X509Certificate getCertificate()
+ {
+ return cert;
+ }
+
+ /**
+ * Sets the certificate criterion. If set, only certificates that are
+ * equal to the certificate passed here will be accepted.
+ *
+ * @param cert The certificate.
+ */
+ public void setCertificate(X509Certificate cert)
+ {
+ this.cert = cert;
+ }
+
+ /**
+ * Returns the serial number criterion, or null
if this
+ * value was not set.
+ *
+ * @return The serial number.
+ */
+ public BigInteger getSerialNumber()
+ {
+ return serialNo;
+ }
+
+ /**
+ * Sets the serial number of the desired certificate. Only certificates that
+ * contain this serial number are accepted.
+ *
+ * @param serialNo The serial number.
+ */
+ public void setSerialNumber(BigInteger serialNo)
+ {
+ this.serialNo = serialNo;
+ }
+
+ /**
+ * Returns the issuer criterion as a string, or null
if this
+ * value was not set.
+ *
+ * @return The issuer.
+ */
+ public String getIssuerAsString()
+ {
+ if (issuer != null)
+ return issuer.getName();
+ else
+ return null;
+ }
+
+ /**
+ * Returns the issuer criterion as a sequence of DER bytes, or
+ * null
if this value was not set.
+ *
+ * @return The issuer.
+ */
+ public byte[] getIssuerAsBytes() throws IOException
+ {
+ if (issuer != null)
+ return issuer.getEncoded();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the issuer, specified as a string representation of the issuer's
+ * distinguished name. Only certificates issued by this issuer will
+ * be accepted.
+ *
+ * @param name The string representation of the issuer's distinguished name.
+ * @throws IOException If the given name is incorrectly formatted.
+ */
+ public void setIssuer(String name) throws IOException
+ {
+ if (name != null)
+ {
+ try
+ {
+ issuer = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new IOException(iae.getMessage());
+ }
+ }
+ else
+ issuer = null;
+ }
+
+ /**
+ * Sets the issuer, specified as the DER encoding of the issuer's
+ * distinguished name. Only certificates issued by this issuer will
+ * be accepted.
+ *
+ * @param name The DER encoding of the issuer's distinguished name.
+ * @throws IOException If the given name is incorrectly formatted.
+ */
+ public void setIssuer(byte[] name) throws IOException
+ {
+ if (name != null)
+ {
+ try
+ {
+ issuer = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new IOException(iae.getMessage());
+ }
+ }
+ else
+ issuer = null;
+ }
+
+ /**
+ * Returns the subject criterion as a string, of null
if
+ * this value was not set.
+ *
+ * @return The subject.
+ */
+ public String getSubjectAsString()
+ {
+ if (subject != null)
+ return subject.getName();
+ else
+ return null;
+ }
+
+ /**
+ * Returns the subject criterion as a sequence of DER bytes, or
+ * null
if this value is not set.
+ *
+ * @return The subject.
+ */
+ public byte[] getSubjectAsBytes() throws IOException
+ {
+ if (subject != null)
+ return subject.getEncoded();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the subject, specified as a string representation of the
+ * subject's distinguished name. Only certificates with the given
+ * subject will be accepted.
+ *
+ * @param name The string representation of the subject's distinguished name.
+ * @throws IOException If the given name is incorrectly formatted.
+ */
+ public void setSubject(String name) throws IOException
+ {
+ if (name != null)
+ {
+ try
+ {
+ subject = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new IOException(iae.getMessage());
+ }
+ }
+ else
+ subject = null;
+ }
+
+ /**
+ * Sets the subject, specified as the DER encoding of the subject's
+ * distinguished name. Only certificates with the given subject will
+ * be accepted.
+ *
+ * @param name The DER encoding of the subject's distinguished name.
+ * @throws IOException If the given name is incorrectly formatted.
+ */
+ public void setSubject(byte[] name) throws IOException
+ {
+ if (name != null)
+ {
+ try
+ {
+ subject = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new IOException(iae.getMessage());
+ }
+ }
+ else
+ subject = null;
+ }
+
+ /**
+ * Returns the subject key identifier criterion, or null
if
+ * this value was not set. Note that the byte array is cloned to prevent
+ * modification.
+ *
+ * @return The subject key identifier.
+ */
+ public byte[] getSubjectKeyIdentifier()
+ {
+ if (subjectKeyId != null)
+ return (byte[]) subjectKeyId.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the subject key identifier criterion, or null
to clear
+ * this criterion. Note that the byte array is cloned to prevent modification.
+ *
+ * @param subjectKeyId The subject key identifier.
+ */
+ public void setSubjectKeyIdentifier(byte[] subjectKeyId)
+ {
+ this.subjectKeyId = subjectKeyId != null ? (byte[]) subjectKeyId.clone() :
+ null;
+ }
+
+ /**
+ * Returns the authority key identifier criterion, or null
if
+ * this value was not set. Note that the byte array is cloned to prevent
+ * modification.
+ *
+ * @return The authority key identifier.
+ */
+ public byte[] getAuthorityKeyIdentifier()
+ {
+ if (authKeyId != null)
+ return (byte[]) authKeyId.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the authority key identifier criterion, or null
to clear
+ * this criterion. Note that the byte array is cloned to prevent modification.
+ *
+ * @param subjectKeyId The subject key identifier.
+ */
+ public void setAuthorityKeyIdentifier(byte[] authKeyId)
+ {
+ this.authKeyId = authKeyId != null ? (byte[]) authKeyId.clone() : null;
+ }
+
+ /**
+ * Returns the date at which certificates must be valid, or null
+ * if this criterion was not set.
+ *
+ * @return The target certificate valitity date.
+ */
+ public Date getCertificateValid()
+ {
+ if (certValid != null)
+ return (Date) certValid.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the date at which certificates must be valid. Specify
+ * null
to clear this criterion.
+ *
+ * @param certValid The certificate validity date.
+ */
+ public void setCertificateValid(Date certValid)
+ {
+ this.certValid = certValid != null ? (Date) certValid.clone() : null;
+ }
+
+ /**
+ * This method, and its related X.509 certificate extension — the
+ * private key usage period — is not supported under the Internet
+ * PKI for X.509 certificates (PKIX), described in RFC 3280. As such, this
+ * method is not supported either.
+ *
+ *
Do not use this method. It is not deprecated, as it is not deprecated
+ * in the Java standard, but it is basically a no-operation and simply
+ * returns null
.
+ *
+ * @return Null.
+ */
+ public Date getPrivateKeyValid()
+ {
+ return null;
+ }
+
+ /**
+ * This method, and its related X.509 certificate extension — the
+ * private key usage period — is not supported under the Internet
+ * PKI for X.509 certificates (PKIX), described in RFC 3280. As such, this
+ * method is not supported either.
+ *
+ *
Do not use this method. It is not deprecated, as it is not deprecated
+ * in the Java standard, but it is basically a no-operation.
+ *
+ * @param UNUSED Is silently ignored.
+ */
+ public void setPrivateKeyValid(Date UNUSED)
+ {
+ }
+
+ /**
+ * Returns the public key algorithm ID that matching certificates must have,
+ * or null
if this criterion was not set.
+ *
+ * @return The public key algorithm ID.
+ */
+ public String getSubjectPublicKeyAlgID()
+ {
+ return String.valueOf(sigId);
+ }
+
+ /**
+ * Sets the public key algorithm ID that matching certificates must have.
+ * Specify null
to clear this criterion.
+ *
+ * @param sigId The public key ID.
+ * @throws IOException If the specified ID is not a valid object identifier.
+ */
+ public void setSubjectPublicKeyAlgID(String sigId) throws IOException
+ {
+ if (sigId != null)
+ {
+ try
+ {
+ OID oid = new OID(sigId);
+ int[] comp = oid.getIDs();
+ if (!checkOid(comp))
+ throw new IOException("malformed OID: " + sigId);
+ this.sigId = oid;
+ }
+ catch (IllegalArgumentException iae)
+ {
+ IOException ioe = new IOException("malformed OID: " + sigId);
+ ioe.initCause(iae);
+ throw ioe;
+ }
+ }
+ else
+ this.sigId = null;
+ }
+
+ /**
+ * Returns the subject public key criterion, or null
if this
+ * value is not set.
+ *
+ * @return The subject public key.
+ */
+ public PublicKey getSubjectPublicKey()
+ {
+ return subjectKey;
+ }
+
+ /**
+ * Sets the subject public key criterion as an opaque representation.
+ * Specify null
to clear this criterion.
+ *
+ * @param key The public key.
+ */
+ public void setSubjectPublicKey(PublicKey key)
+ {
+ this.subjectKey = key;
+ if (key == null)
+ {
+ subjectKeySpec = null;
+ return;
+ }
+ try
+ {
+ KeyFactory enc = KeyFactory.getInstance("X.509");
+ subjectKeySpec = (X509EncodedKeySpec)
+ enc.getKeySpec(key, X509EncodedKeySpec.class);
+ }
+ catch (Exception x)
+ {
+ subjectKey = null;
+ subjectKeySpec = null;
+ }
+ }
+
+ /**
+ * Sets the subject public key criterion as a DER-encoded key. Specify
+ * null
to clear this value.
+ *
+ * @param key The DER-encoded key bytes.
+ * @throws IOException If the argument is not a valid DER-encoded key.
+ */
+ public void setSubjectPublicKey(byte[] key) throws IOException
+ {
+ if (key == null)
+ {
+ subjectKey = null;
+ subjectKeySpec = null;
+ return;
+ }
+ try
+ {
+ subjectKeySpec = new X509EncodedKeySpec(key);
+ KeyFactory enc = KeyFactory.getInstance("X.509");
+ subjectKey = enc.generatePublic(subjectKeySpec);
+ }
+ catch (Exception x)
+ {
+ subjectKey = null;
+ subjectKeySpec = null;
+ IOException ioe = new IOException(x.getMessage());
+ ioe.initCause(x);
+ throw ioe;
+ }
+ }
+
+ /**
+ * Returns the public key usage criterion, or null
if this
+ * value is not set. Note that the array is cloned to prevent modification.
+ *
+ * @return The public key usage.
+ */
+ public boolean[] getKeyUsage()
+ {
+ if (keyUsage != null)
+ return (boolean[]) keyUsage.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the public key usage criterion. Specify null
to clear
+ * this value.
+ *
+ * @param keyUsage The public key usage.
+ */
+ public void setKeyUsage(boolean[] keyUsage)
+ {
+ this.keyUsage = keyUsage != null ? (boolean[]) keyUsage.clone() : null;
+ }
+
+ /**
+ * Returns the set of extended key purpose IDs, as an unmodifiable set
+ * of OID strings. Returns null
if this criterion is not
+ * set.
+ *
+ * @return The set of key purpose OIDs (strings).
+ */
+ public Set getExtendedKeyUsage()
+ {
+ if (keyPurposeSet != null)
+ return Collections.unmodifiableSet(keyPurposeSet);
+ else
+ return null;
+ }
+
+ /**
+ * Sets the extended key usage criterion, as a set of OID strings. Specify
+ * null
to clear this value.
+ *
+ * @param keyPurposeSet The set of key purpose OIDs.
+ * @throws IOException If any element of the set is not a valid OID string.
+ */
+ public void setExtendedKeyUsage(Set keyPurposeSet) throws IOException
+ {
+ if (keyPurposeSet == null)
+ {
+ this.keyPurposeSet = null;
+ return;
+ }
+ Set s = new HashSet();
+ for (Iterator it = keyPurposeSet.iterator(); it.hasNext(); )
+ {
+ Object o = it.next();
+ if (!(o instanceof String))
+ throw new IOException("not a string: " + o);
+ try
+ {
+ OID oid = new OID((String) o);
+ int[] comp = oid.getIDs();
+ if (!checkOid(comp))
+ throw new IOException("malformed OID: " + o);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ IOException ioe = new IOException("malformed OID: " + o);
+ ioe.initCause(iae);
+ throw ioe;
+ }
+ }
+ this.keyPurposeSet = s;
+ }
+
+ /**
+ * Returns whether or not all specified alternative names must match.
+ * If false, a certificate is considered a match if one of the
+ * specified alternative names matches.
+ *
+ * @return true if all names must match.
+ */
+ public boolean getMatchAllSubjectAltNames()
+ {
+ return matchAllNames;
+ }
+
+ /**
+ * Sets whether or not all subject alternative names must be matched.
+ * If false, then a certificate will be considered a match if one
+ * alternative name matches.
+ *
+ * @param matchAllNames Whether or not all alternative names must be
+ * matched.
+ */
+ public void setMatchAllSubjectAltNames(boolean matchAllNames)
+ {
+ this.matchAllNames = matchAllNames;
+ }
+
+ /**
+ * Sets the subject alternative names critertion. Each element of the
+ * argument must be a address@hidden java.util.List} that contains exactly two
+ * elements: the first an address@hidden Integer}, representing the type of
+ * name, and the second either a address@hidden String} or a byte array,
+ * representing the name itself.
+ *
+ * @param altNames The alternative names.
+ * @throws IOException If any element of the argument is invalid.
+ */
+ public void setSubjectAlternativeNames(Collection altNames)
+ throws IOException
+ {
+ if (altNames == null)
+ {
+ this.altNames = null;
+ return;
+ }
+ List l = new ArrayList(altNames.size());
+ for (Iterator it = altNames.iterator(); it.hasNext(); )
+ {
+ Object o = it.next();
+ if (!(o instanceof List) || ((List) o).size() != 2 ||
+ !(((List) o).get(0) instanceof Integer) ||
+ !(((List) o).get(1) instanceof String) ||
+ !(((List) o).get(1) instanceof byte[]))
+ throw new IOException("illegal alternative name: " + o);
+ Integer i = (Integer) ((List) o).get(0);
+ if (i.intValue() < 0 || i.intValue() > 8)
+ throw new IOException("illegal alternative name: " + o +
+ ", bad id: " + i);
+ l.add(new ArrayList((List) o));
+ }
+ this.altNames = l;
+ }
+
+ /**
+ * Add a name to the subject alternative names criterion.
+ *
+ * @param id The type of name this is. Must be in the range [0,8].
+ * @param name The name.
+ * @throws IOException If the id is out of range, or if the name
+ * is null.
+ */
+ public void addSubjectAlternativeName(int id, String name)
+ throws IOException
+ {
+ if (id < 0 || id > 8 || name == null)
+ throw new IOException("illegal alternative name");
+ if (altNames == null)
+ altNames = new LinkedList();
+ ArrayList l = new ArrayList(2);
+ l.add(new Integer(id));
+ l.add(name);
+ altNames.add(l);
+ }
+
+ /**
+ * Add a name, as DER-encoded bytes, to the subject alternative names
+ * criterion.
+ *
+ * @param id The type of name this is.
+ */
+ public void addSubjectAlternativeName(int id, byte[] name)
+ throws IOException
+ {
+ if (id < 0 || id > 8 || name == null)
+ throw new IOException("illegal alternative name");
+ if (altNames == null)
+ altNames = new LinkedList();
+ ArrayList l = new ArrayList(2);
+ l.add(new Integer(id));
+ l.add(name);
+ altNames.add(l);
+ }
+
+ /**
+ * Returns the name constraints criterion, or null
if this
+ * value is not set. Note that the byte array is cloned to prevent
+ * modification.
+ *
+ * @return The name constraints.
+ */
+ public byte[] getNameConstraints()
+ {
+ if (nameConstraints != null)
+ return (byte[]) nameConstraints.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the name constraints criterion; specify null
to
+ * clear this criterion. Note that if non-null, the argument will be
+ * cloned to prevent modification.
+ *
+ * @param nameConstraints The new name constraints.
+ * @throws IOException If the argument is not a valid DER-encoded
+ * name constraints.
+ */
+ public void setNameConstraints(byte[] nameConstraints)
+ throws IOException
+ {
+ // FIXME check if the argument is valid.
+ this.nameConstraints = nameConstraints != null
+ ? (byte[]) nameConstraints.clone() : null;
+ }
+
+ /**
+ * Returns the basic constraints criterion, or -1 if this value is not set.
+ *
+ * @return The basic constraints.
+ */
+ public int getBasicConstraints()
+ {
+ return basicConstraints;
+ }
+
+ /**
+ * Sets the basic constraints criterion. Specify -1 to clear this parameter.
+ *
+ * @param basicConstraints The new basic constraints value.
+ */
+ public void setBasicConstraints(int basicConstraints)
+ {
+ if (basicConstraints < -1)
+ basicConstraints = -1;
+ this.basicConstraints = basicConstraints;
+ }
+
+ // The last two criteria not yet implemented are certificate policies
+ // and path-to-names. Both of these are somewhat advanced extensions
+ // (you could probably count the applications that actually use them
+ // on one hand), and they both have no support in the X509Certificate
+ // class.
+ //
+ // Not having support in X509Certificate is not always a problem; for
+ // example, we can compare DER-encoded values as byte arrays for some
+ // extensions. We can't, however, compare them if they are specified
+ // in a set (as policies are). We need to parse the actual value in the
+ // certificate, and check it against the specified set.
+
+ // FIXME
+// public void setPolicy(Set policy) throws IOException
+// {
+// if (policy != null)
+// {
+// for (Iterator it = policy.iterator(); it.hasNext(); )
+// try
+// {
+// OID oid = new OID((String) it.next());
+// int[] i = oid.getIDs();
+// if (!checkOid(i))
+// throw new IOException("invalid OID");
+// }
+// catch (Exception x)
+// {
+// throw new IOException("invalid OID");
+// }
+// }
+// this.policy = policy != null ? new HashSet(policy) : null;
+// }
+
+ // FIXME
+// public void setPathToNames(Collection names) throws IOException
+// {
+// if (names == null)
+// {
+// this.names = null;
+// return;
+// }
+// for (Iterator it = names.iterator(); it.hasNext(); )
+// {
+// try
+// {
+// List l = (List) it.next();
+// if (l.get(1) instanceof String)
+// addPathToName(((Integer)l.get(0)).intValue(), (String)l.get(1));
+// else
+// addPathToName(((Integer)l.get(0)).intValue(), (byte[])l.get(1));
+// }
+// catch (Exception x)
+// {
+// this.names = null;
+// throw new IOException("invalid names");
+// }
+// }
+// }
+
+ // FIXME
+// public void addPathToName(int id, String name) throws IOException
+// {
+// }
+
+ // FIXME
+// public void addPathToName(int id, byte[] name) throws IOException
+// {
+// }
+
+ // FIXME
+// public Collection getSubjectAlternativeNames()
+// {
+// return null;
+// }
+
+ // FIXME
+// public Set getPolicy()
+// {
+// return null;
+// }
+
+ // FIXME
+// public Collection getPathToNames()
+// {
+// return null;
+// }
+
+ /**
+ * Match a certificate. This method will check the given certificate
+ * against all the enabled criteria of this selector, and will return
+ * true
if the given certificate matches.
+ *
+ * @param certificate The certificate to check.
+ * @return true if the certificate matches all criteria.
+ */
+ public boolean match(Certificate certificate)
+ {
+ if (!(certificate instanceof X509Certificate))
+ return false;
+ X509Certificate cert = (X509Certificate) certificate;
+ if (this.cert != null)
+ {
+ try
+ {
+ byte[] e1 = this.cert.getEncoded();
+ byte[] e2 = cert.getEncoded();
+ if (!Arrays.equals(e1, e2))
+ return false;
+ }
+ catch (CertificateEncodingException cee)
+ {
+ return false;
+ }
+ }
+ if (serialNo != null)
+ {
+ if (!serialNo.equals(cert.getSerialNumber()))
+ return false;
+ }
+ if (certValid != null)
+ {
+ try
+ {
+ cert.checkValidity(certValid);
+ }
+ catch (CertificateException ce)
+ {
+ return false;
+ }
+ }
+ if (issuer != null)
+ {
+ if (!issuer.equals(cert.getIssuerX500Principal()))
+ return false;
+ }
+ if (subject != null)
+ {
+ if (!subject.equals(cert.getSubjectX500Principal()))
+ return false;
+ }
+ if (sigId != null)
+ {
+ if (!sigId.equals(cert.getSigAlgOID()))
+ return false;
+ }
+ if (subjectKeyId != null)
+ {
+ byte[] b = cert.getExtensionValue(SUBJECT_KEY_ID);
+ if (!Arrays.equals(b, subjectKeyId))
+ return false;
+ }
+ if (authKeyId != null)
+ {
+ byte[] b = cert.getExtensionValue(AUTH_KEY_ID);
+ if (!Arrays.equals(b, authKeyId))
+ return false;
+ }
+ if (keyUsage != null)
+ {
+ boolean[] b = cert.getKeyUsage();
+ if (!Arrays.equals(b, keyUsage))
+ return false;
+ }
+ if (basicConstraints >= 0)
+ {
+ if (cert.getBasicConstraints() != basicConstraints)
+ return false;
+ }
+ if (keyPurposeSet != null)
+ {
+ List kp = null;
+ try
+ {
+ kp = cert.getExtendedKeyUsage();
+ }
+ catch (CertificateParsingException cpe)
+ {
+ return false;
+ }
+ if (kp == null)
+ return false;
+ for (Iterator it = keyPurposeSet.iterator(); it.hasNext(); )
+ {
+ if (!kp.contains(it.next()))
+ return false;
+ }
+ }
+ if (altNames != null)
+ {
+ Collection an = null;
+ try
+ {
+ an = cert.getSubjectAlternativeNames();
+ }
+ catch (CertificateParsingException cpe)
+ {
+ return false;
+ }
+ if (an == null)
+ return false;
+ int match = 0;
+ for (Iterator it = altNames.iterator(); it.hasNext(); )
+ {
+ List l = (List) it.next();
+ Integer id = (Integer) l.get(0);
+ String s = null;
+ byte[] b = null;
+ if (l.get(1) instanceof String)
+ s = (String) l.get(1);
+ else if (l.get(1) instanceof byte[])
+ b = (byte[]) l.get(1);
+ else
+ return false;
+ for (Iterator it2 = an.iterator(); it2.hasNext(); )
+ {
+ Object o = it2.next();
+ if (!(o instanceof List))
+ continue;
+ List l2 = (List) o;
+ if (l2.size() != 2)
+ continue;
+ if (!id.equals(l2.get(0)))
+ continue;
+ if (s != null && (l2.get(1) instanceof String) &&
+ s.equals(l2.get(1)))
+ match++;
+ else if (b != null && (l2.get(1) instanceof byte[]) &&
+ Arrays.equals(b, (byte[]) l2.get(1)))
+ match++;
+ }
+ if (match == 0 || (matchAllNames && match != altNames.size()))
+ return false;
+ }
+ }
+ if (nameConstraints != null)
+ {
+ byte[] nc = cert.getExtensionValue(NAME_CONSTRAINTS_ID);
+ if (!Arrays.equals(nameConstraints, nc))
+ return false;
+ }
+
+ // FIXME check policies.
+ // FIXME check path-to-names.
+
+ return true;
+ }
+
+ public String toString()
+ {
+ StringBuffer str = new StringBuffer(X509CertSelector.class.getName());
+ GetPropertyAction getProp = new GetPropertyAction("line.separator");
+ String nl = (String) AccessController.doPrivileged(getProp);
+ String eol = ";" + nl;
+ str.append(" {").append(nl);
+ if (cert != null)
+ str.append(" certificate = ").append(cert).append(eol);
+ if (basicConstraints >= 0)
+ str.append(" basic constraints = ").append(basicConstraints).append(eol);
+ if (serialNo != null)
+ str.append(" serial number = ").append(serialNo).append(eol);
+ if (certValid != null)
+ str.append(" valid date = ").append(certValid).append(eol);
+ if (issuer != null)
+ str.append(" issuer = ").append(issuer).append(eol);
+ if (subject != null)
+ str.append(" subject = ").append(subject).append(eol);
+ if (sigId != null)
+ str.append(" signature OID = ").append(sigId).append(eol);
+ if (subjectKey != null)
+ str.append(" subject public key = ").append(subjectKey).append(eol);
+ if (subjectKeyId != null)
+ {
+ str.append(" subject key ID = ");
+ for (int i = 0; i < subjectKeyId.length; i++)
+ {
+ str.append(Character.forDigit((subjectKeyId[i] & 0xF0) >>> 8, 16));
+ str.append(Character.forDigit((subjectKeyId[i] & 0x0F), 16));
+ if (i < subjectKeyId.length - 1)
+ str.append(':');
+ }
+ str.append(eol);
+ }
+ if (authKeyId != null)
+ {
+ str.append(" authority key ID = ");
+ for (int i = 0; i < authKeyId.length; i++)
+ {
+ str.append(Character.forDigit((authKeyId[i] & 0xF0) >>> 8, 16));
+ str.append(Character.forDigit((authKeyId[i] & 0x0F), 16));
+ if (i < authKeyId.length - 1)
+ str.append(':');
+ }
+ str.append(eol);
+ }
+ if (keyUsage != null)
+ {
+ str.append(" key usage = ");
+ for (int i = 0; i < keyUsage.length; i++)
+ str.append(keyUsage[i] ? '1' : '0');
+ str.append(eol);
+ }
+ if (keyPurposeSet != null)
+ str.append(" key purpose = ").append(keyPurposeSet).append(eol);
+ if (altNames != null)
+ str.append(" alternative names = ").append(altNames).append(eol);
+ if (nameConstraints != null)
+ str.append(" name constraints =