summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/security/cert/X509CertSelector.java
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/java/security/cert/X509CertSelector.java
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/java/security/cert/X509CertSelector.java')
-rw-r--r--libjava/classpath/java/security/cert/X509CertSelector.java1319
1 files changed, 1319 insertions, 0 deletions
diff --git a/libjava/classpath/java/security/cert/X509CertSelector.java b/libjava/classpath/java/security/cert/X509CertSelector.java
new file mode 100644
index 000000000..8c1230afb
--- /dev/null
+++ b/libjava/classpath/java/security/cert/X509CertSelector.java
@@ -0,0 +1,1319 @@
+/* X509CertSelector.java -- selects X.509 certificates by criteria.
+ Copyright (C) 2004, 2005, 2006 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.lang.CPStringBuilder;
+import gnu.java.security.OID;
+import gnu.java.security.x509.GnuPKIExtension;
+import gnu.java.security.x509.ext.CertificatePolicies;
+import gnu.java.security.x509.ext.Extension;
+import gnu.java.security.x509.ext.GeneralName;
+import gnu.java.security.x509.ext.GeneralSubtree;
+import gnu.java.security.x509.ext.NameConstraints;
+import gnu.java.security.x509.ext.GeneralName.Kind;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.InetAddress;
+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;
+
+/**
+ * A concrete implementation of {@link 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.
+ *
+ * <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)
+ * @since 1.4
+ */
+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 static boolean checkOid(int[] oid)
+ {
+ return (oid != null && oid.length > 2 &&
+ (oid[0] >= 0 && oid[0] <= 2) && (oid[1] >= 0 && oid[1] <= 39));
+ }
+
+ private static GeneralName makeName(int id, String name) throws IOException
+ {
+ byte[] nameBytes = null;
+ GeneralName.Kind kind = GeneralName.Kind.forTag(id);
+ switch (Kind.forTag(id))
+ {
+ case dNSName:
+ case rfc822Name:
+ case uniformResourceIdentifier:
+ nameBytes = name.getBytes("ASCII");
+ break;
+
+ case iPAddress:
+ InetAddress addr = InetAddress.getByName(name);
+ nameBytes = addr.getAddress();
+ break;
+
+ case registeredId:
+ OID oid = new OID(name);
+ nameBytes = oid.getDER();
+ break;
+
+ case directoryName:
+ X500Principal xname = new X500Principal(name);
+ nameBytes = xname.getEncoded();
+ break;
+
+ case ediPartyName:
+ case x400Address:
+ case otherName:
+ throw new IOException("cannot decode string representation of "
+ + kind);
+ }
+ return new GeneralName(kind, nameBytes);
+ }
+
+ 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<String> keyPurposeSet;
+ private List<GeneralName> altNames;
+ private boolean matchAllNames;
+ private byte[] nameConstraints;
+ private Set<OID> policy;
+ private List<GeneralName> pathToNames;
+
+ /**
+ * Creates a new X.509 certificate selector. The new selector will be
+ * empty, and will accept any certificate (provided that it is an
+ * {@link X509Certificate}).
+ */
+ public X509CertSelector()
+ {
+ basicConstraints = -1;
+ }
+
+ /**
+ * Add a name to match in the NameConstraints extension. The argument is
+ * the DER-encoded bytes of a GeneralName structure.
+ *
+ * See the method {@link #addSubjectAlternativeName(int, byte[])} for the
+ * format of the GeneralName structure.
+ *
+ * @param id The name identifier. Must be between 0 and 8.
+ * @param name The DER-encoded bytes of the name to match.
+ * @throws IOException If the name DER is malformed.
+ */
+ public void addPathToName(int id, byte[] name) throws IOException
+ {
+ GeneralName generalName = new GeneralName(GeneralName.Kind.forTag(id), name);
+ if (pathToNames == null)
+ pathToNames = new LinkedList<GeneralName>();
+ pathToNames.add(generalName);
+ }
+
+ /**
+ * Add a name to match in the NameConstraints extension. This method will
+ * only recognize certain types of name that have convenient string
+ * encodings. For robustness, you should use the {@link
+ * #addPathToName(int, byte[])} method whenever possible.
+ *
+ * @param id The name identifier. Must be between 0 and 8.
+ * @param name The name.
+ * @throws IOException If the name cannot be decoded.
+ */
+ public void addPathToName(int id, String name) throws IOException
+ {
+ GeneralName generalName = makeName(id, name);
+ if (pathToNames == null)
+ pathToNames = new LinkedList<GeneralName>();
+ pathToNames.add(generalName);
+ }
+
+ /**
+ * Add a name, as DER-encoded bytes, to the subject alternative names
+ * criterion.
+ *
+ * The name is a GeneralName structure, which has the ASN.1 format:
+ *
+ * <pre>
+ GeneralName ::= CHOICE {
+ otherName [0] OtherName,
+ rfc822Name [1] IA5String,
+ dNSName [2] IA5String,
+ x400Address [3] ORAddress,
+ directoryName [4] Name,
+ ediPartyName [5] EDIPartyName,
+ uniformResourceIdentifier [6] IA5String,
+ iPAddress [7] OCTET STRING,
+ registeredID [8] OBJECT IDENTIFIER }
+</pre>
+ *
+ * @param id The type of name this is.
+ * @param name The DER-encoded name.
+ * @throws IOException If the name is not a valid DER sequence.
+ */
+ public void addSubjectAlternativeName(int id, byte[] name)
+ throws IOException
+ {
+ GeneralName generalName = new GeneralName(GeneralName.Kind.forTag(id), name);
+ if (altNames == null)
+ altNames = new LinkedList<GeneralName>();
+ altNames.add(generalName);
+ }
+
+ /**
+ * Add a name to the subject alternative names criterion. This method will
+ * only recognize certain types of name that have convenient string
+ * encodings. For robustness, you should use the {@link
+ * #addSubjectAlternativeName(int, byte[])} method whenever possible.
+ *
+ * This method can only decode certain name kinds of names as strings.
+ *
+ * @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
+ {
+ GeneralName generalName = makeName(id, name);
+ if (altNames == null)
+ altNames = new LinkedList<GeneralName>();
+ altNames.add(generalName);
+ }
+
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen);
+ }
+ }
+
+ /**
+ * Returns the authority key identifier criterion, or <code>null</code> 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;
+ }
+
+ /**
+ * Returns the basic constraints criterion, or -1 if this value is not set.
+ *
+ * @return The basic constraints.
+ */
+ public int getBasicConstraints()
+ {
+ return basicConstraints;
+ }
+
+ /**
+ * Returns the certificate criterion, or <code>null</code> if this value
+ * was not set.
+ *
+ * @return The certificate.
+ */
+ public X509Certificate getCertificate()
+ {
+ return cert;
+ }
+
+ /**
+ * Returns the date at which certificates must be valid, or <code>null</code>
+ * 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;
+ }
+
+ /**
+ * Returns the set of extended key purpose IDs, as an unmodifiable set
+ * of OID strings. Returns <code>null</code> if this criterion is not
+ * set.
+ *
+ * @return The set of key purpose OIDs (strings).
+ */
+ public Set<String> getExtendedKeyUsage()
+ {
+ if (keyPurposeSet != null)
+ return Collections.unmodifiableSet(keyPurposeSet);
+ else
+ return null;
+ }
+
+ /**
+ * Returns the issuer criterion as a sequence of DER bytes, or
+ * <code>null</code> if this value was not set.
+ *
+ * @return The issuer.
+ */
+ public byte[] getIssuerAsBytes() throws IOException
+ {
+ if (issuer != null)
+ return issuer.getEncoded();
+ else
+ return null;
+ }
+
+ /**
+ * Returns the issuer criterion as a string, or <code>null</code> if this
+ * value was not set.
+ *
+ * @return The issuer.
+ */
+ public String getIssuerAsString()
+ {
+ if (issuer != null)
+ return issuer.getName();
+ else
+ return null;
+ }
+
+ /**
+ * Returns the public key usage criterion, or <code>null</code> 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;
+ }
+
+ /**
+ * Returns whether or not all specified alternative names must match.
+ * If false, a certificate is considered a match if <em>one</em> of the
+ * specified alternative names matches.
+ *
+ * @return true if all names must match.
+ */
+ public boolean getMatchAllSubjectAltNames()
+ {
+ return matchAllNames;
+ }
+
+ /**
+ * Returns the name constraints criterion, or <code>null</code> 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;
+ }
+
+ public Collection<List<?>> getPathToNames()
+ {
+ if (pathToNames != null)
+ {
+ List<List<?>> names = new ArrayList<List<?>>(pathToNames.size());
+ for (GeneralName name : pathToNames)
+ {
+ List<Object> n = new ArrayList<Object>(2);
+ n.add(name.kind().tag());
+ n.add(name.name());
+ names.add(n);
+ }
+
+ return names;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the certificate policy extension that will be matched by this
+ * selector, or null if the certificate policy will not be matched.
+ *
+ * @return The policy to be matched, or null.
+ */
+ public Set<String> getPolicy()
+ {
+ Set<OID> p = this.policy;
+ if (p != null)
+ {
+ Set<String> strings = new HashSet<String>(p.size());
+ for (OID o : p)
+ {
+ strings.add(o.toString());
+ }
+ return strings;
+ }
+ return null;
+ }
+
+ /**
+ * This method, and its related X.509 certificate extension &mdash; the
+ * private key usage period &mdash; is not supported under the Internet
+ * PKI for X.509 certificates (PKIX), described in RFC 3280. As such, this
+ * method is not supported either.
+ *
+ * <p>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 <code>null</code>.
+ *
+ * @return Null.
+ */
+ public Date getPrivateKeyValid()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the serial number criterion, or <code>null</code> if this
+ * value was not set.
+ *
+ * @return The serial number.
+ */
+ public BigInteger getSerialNumber()
+ {
+ return serialNo;
+ }
+
+ /**
+ * Get the subject alternative names criterion. The collection returned
+ * is a collection of pairs: the first element is an {@link Integer}
+ * containing the name type, and the second is a byte array containing
+ * the DER-encoded name bytes.
+ *
+ * @return The subject alternative names criterion. Returns null if this
+ * criterion is not set.
+ */
+ public Collection<List<?>> getSubjectAlternativeNames()
+ {
+ if (altNames != null)
+ {
+ List<List<?>> names = new ArrayList<List<?>>(altNames.size());
+ for (GeneralName name : altNames)
+ {
+ List<Object> n = new ArrayList<Object>(2);
+ n.add(name.kind().tag());
+ n.add(name.name());
+ names.add(n);
+ }
+ return names;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the subject criterion as a sequence of DER bytes, or
+ * <code>null</code> if this value is not set.
+ *
+ * @return The subject.
+ */
+ public byte[] getSubjectAsBytes() throws IOException
+ {
+ if (subject != null)
+ return subject.getEncoded();
+ else
+ return null;
+ }
+
+ /**
+ * Returns the subject criterion as a string, of <code>null</code> if
+ * this value was not set.
+ *
+ * @return The subject.
+ */
+ public String getSubjectAsString()
+ {
+ if (subject != null)
+ return subject.getName();
+ else
+ return null;
+ }
+
+ /**
+ * Returns the subject key identifier criterion, or <code>null</code> 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;
+ }
+
+ /**
+ * Returns the subject public key criterion, or <code>null</code> if this
+ * value is not set.
+ *
+ * @return The subject public key.
+ */
+ public PublicKey getSubjectPublicKey()
+ {
+ return subjectKey;
+ }
+
+ /**
+ * Returns the public key algorithm ID that matching certificates must have,
+ * or <code>null</code> if this criterion was not set.
+ *
+ * @return The public key algorithm ID.
+ */
+ public String getSubjectPublicKeyAlgID()
+ {
+ return String.valueOf(sigId);
+ }
+
+ /**
+ * Match a certificate. This method will check the given certificate
+ * against all the enabled criteria of this selector, and will return
+ * <code>true</code> 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.toString().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<List<?>> an = null;
+ try
+ {
+ an = cert.getSubjectAlternativeNames();
+ }
+ catch (CertificateParsingException cpe)
+ {
+ return false;
+ }
+ if (an == null)
+ return false;
+ int match = 0;
+ for (GeneralName name : altNames)
+ {
+ for (List<?> list : an)
+ {
+ try
+ {
+ Integer id = (Integer) list.get(0);
+ Object val = list.get(1);
+ GeneralName n = null;
+ if (val instanceof String)
+ n = makeName(id, (String) val);
+ else if (val instanceof byte[])
+ {
+ n = new GeneralName(GeneralName.Kind.forTag(id),
+ (byte[]) val);
+ }
+ else
+ continue;
+ if (name.equals(n))
+ match++;
+ }
+ catch (Exception e)
+ {
+ continue;
+ }
+ }
+ 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;
+ }
+
+ if (policy != null)
+ {
+ CertificatePolicies policies = null;
+ if (cert instanceof GnuPKIExtension)
+ {
+ policies = (CertificatePolicies)
+ ((GnuPKIExtension) cert).getExtension(CertificatePolicies.ID).getValue();
+ }
+ else
+ {
+ byte[] policiesDer =
+ cert.getExtensionValue(CertificatePolicies.ID.toString());
+ try
+ {
+ policies = new CertificatePolicies(policiesDer);
+ }
+ catch (IOException ioe)
+ {
+ // ignored
+ }
+ }
+
+ if (policies == null)
+ return false;
+ if (!policies.getPolicies().containsAll(policy))
+ return false;
+ }
+
+ if (pathToNames != null)
+ {
+ NameConstraints nc = null;
+ if (cert instanceof GnuPKIExtension)
+ {
+ Extension e =
+ ((GnuPKIExtension) cert).getExtension(NameConstraints.ID);
+ if (e != null)
+ nc = (NameConstraints) e.getValue();
+ }
+ else
+ {
+ byte[] b = cert.getExtensionValue(NameConstraints.ID.toString());
+ if (b != null)
+ {
+ try
+ {
+ nc = new NameConstraints(b);
+ }
+ catch (IOException ioe)
+ {
+ }
+ }
+ }
+
+ if (nc == null)
+ return false;
+
+ int match = 0;
+ for (GeneralName name : pathToNames)
+ {
+ for (GeneralSubtree subtree : nc.permittedSubtrees())
+ {
+ if (name.equals(subtree.base()))
+ match++;
+ }
+ }
+ if (match == 0 || (matchAllNames && match < pathToNames.size()))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the authority key identifier criterion, or <code>null</code> to clear
+ * this criterion. Note that the byte array is cloned to prevent modification.
+ *
+ * @param authKeyId The authority key identifier.
+ */
+ public void setAuthorityKeyIdentifier(byte[] authKeyId)
+ {
+ this.authKeyId = authKeyId != null ? (byte[]) authKeyId.clone() : null;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Sets the date at which certificates must be valid. Specify
+ * <code>null</code> to clear this criterion.
+ *
+ * @param certValid The certificate validity date.
+ */
+ public void setCertificateValid(Date certValid)
+ {
+ this.certValid = certValid != null ? (Date) certValid.clone() : null;
+ }
+
+ /**
+ * Sets the extended key usage criterion, as a set of OID strings. Specify
+ * <code>null</code> 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<String> keyPurposeSet) throws IOException
+ {
+ if (keyPurposeSet == null)
+ {
+ this.keyPurposeSet = null;
+ return;
+ }
+ Set<String> s = new HashSet<String>();
+ 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;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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 public key usage criterion. Specify <code>null</code> to clear
+ * this value.
+ *
+ * @param keyUsage The public key usage.
+ */
+ public void setKeyUsage(boolean[] keyUsage)
+ {
+ this.keyUsage = keyUsage != null ? (boolean[]) keyUsage.clone() : null;
+ }
+
+ /**
+ * 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 name constraints criterion; specify <code>null</code> 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
+ {
+ // Check if the input is well-formed...
+ new NameConstraints(nameConstraints);
+
+ // But we just compare raw byte arrays.
+ this.nameConstraints = nameConstraints != null
+ ? (byte[]) nameConstraints.clone() : null;
+ }
+
+ /**
+ * Sets the pathToNames criterion. The argument is a collection of
+ * pairs, the first element of which is an {@link Integer} giving
+ * the ID of the name, and the second element is either a {@link String}
+ * or a byte array.
+ *
+ * See {@link #addPathToName(int, byte[])} and {@link #addPathToName(int, String)}
+ * for how these arguments are handled.
+ *
+ * @param names The names.
+ * @throws IOException If any argument is malformed.
+ */
+ public void setPathToNames(Collection<List<?>> names) throws IOException
+ {
+ if (names == null || names.size() == 0)
+ {
+ pathToNames = null;
+ }
+ else
+ {
+ pathToNames = new ArrayList<GeneralName>(names.size());
+ for (List<?> name : names)
+ {
+ Integer id = (Integer) name.get(0);
+ Object name2 = name.get(1);
+ if (name2 instanceof String)
+ addPathToName(id, (String) name2);
+ else if (name2 instanceof byte[])
+ addPathToName(id, (byte[]) name2);
+ else
+ throw new IOException("invalid name type: "
+ + name2.getClass().getName());
+ }
+ }
+ }
+
+ /**
+ * Sets the certificate policy to match, or null if this criterion should
+ * not be checked. Each element if the set must be a dotted-decimal form
+ * of certificate policy object identifier.
+ *
+ * @param policy The policy to match.
+ * @throws IOException If some element of the policy is not a valid
+ * policy extenison OID.
+ */
+ public void setPolicy(Set<String> policy) throws IOException
+ {
+ if (policy != null)
+ {
+ HashSet<OID> p = new HashSet<OID>(policy.size());
+ for (String s : policy)
+ {
+ try
+ {
+ OID oid = new OID(s);
+ int[] i = oid.getIDs();
+ if (!checkOid(i))
+ throw new IOException("invalid OID");
+ p.add(oid);
+ }
+ catch (IOException ioe)
+ {
+ throw ioe;
+ }
+ catch (Exception x)
+ {
+ IOException ioe = new IOException("invalid OID");
+ ioe.initCause(x);
+ throw ioe;
+ }
+ }
+ this.policy = p;
+ }
+ else
+ this.policy = null;
+ }
+
+ /**
+ * This method, and its related X.509 certificate extension &mdash; the
+ * private key usage period &mdash; is not supported under the Internet
+ * PKI for X.509 certificates (PKIX), described in RFC 3280. As such, this
+ * method is not supported either.
+ *
+ * <p>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)
+ {
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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 alternative names critertion. Each element of the
+ * argument must be a {@link java.util.List} that contains exactly two
+ * elements: the first an {@link Integer}, representing the type of
+ * name, and the second either a {@link 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<List<?>> altNames)
+ throws IOException
+ {
+ if (altNames == null || altNames.isEmpty())
+ {
+ this.altNames = null;
+ return;
+ }
+ List<GeneralName> l = new ArrayList<GeneralName>(altNames.size());
+ for (List<?> list : altNames)
+ {
+ Integer id = (Integer) list.get(0);
+ Object value = list.get(1);
+ GeneralName name = null;
+ if (value instanceof String)
+ name = makeName(id, (String) value);
+ else if (value instanceof byte[])
+ name = new GeneralName(GeneralName.Kind.forTag(id), (byte[]) value);
+ else
+ throw new IOException("invalid name type: " + value.getClass().getName());
+ l.add(name);
+ }
+ this.altNames = l;
+ }
+
+ /**
+ * Sets the subject key identifier criterion, or <code>null</code> 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;
+ }
+
+ /**
+ * Sets the subject public key criterion as a DER-encoded key. Specify
+ * <code>null</code> 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;
+ }
+ }
+
+ /**
+ * Sets the subject public key criterion as an opaque representation.
+ * Specify <code>null</code> 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 public key algorithm ID that matching certificates must have.
+ * Specify <code>null</code> 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;
+ }
+
+ public String toString()
+ {
+ CPStringBuilder str = new CPStringBuilder(X509CertSelector.class.getName());
+ String nl = SystemProperties.getProperty("line.separator");
+ 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 = <blob of data>").append(eol);
+ if (policy != null)
+ str.append(" policy = ").append(policy).append(eol);
+ if (pathToNames != null)
+ str.append(" pathToNames = ").append(pathToNames).append(eol);
+ str.append("}").append(nl);
+ return str.toString();
+ }
+}