diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/java/security/cert/X509CertSelector.java | |
download | cbb-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.java | 1319 |
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 — 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. + * + * <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 — 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. + * + * <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(); + } +} |