Home | History | Annotate | Download | only in cert
      1 /*
      2  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 package java.security.cert;
     27 
     28 import java.io.IOException;
     29 import java.math.BigInteger;
     30 import java.security.PublicKey;
     31 import java.util.*;
     32 import javax.security.auth.x500.X500Principal;
     33 
     34 import sun.misc.HexDumpEncoder;
     35 import sun.security.util.Debug;
     36 import sun.security.util.DerInputStream;
     37 import sun.security.util.DerValue;
     38 import sun.security.util.ObjectIdentifier;
     39 import sun.security.x509.*;
     40 
     41 /**
     42  * A {@code CertSelector} that selects {@code X509Certificates} that
     43  * match all specified criteria. This class is particularly useful when
     44  * selecting certificates from a {@code CertStore} to build a
     45  * PKIX-compliant certification path.
     46  * <p>
     47  * When first constructed, an {@code X509CertSelector} has no criteria
     48  * enabled and each of the {@code get} methods return a default value
     49  * ({@code null}, or {@code -1} for the {@link #getBasicConstraints
     50  * getBasicConstraints} method). Therefore, the {@link #match match}
     51  * method would return {@code true} for any {@code X509Certificate}.
     52  * Typically, several criteria are enabled (by calling
     53  * {@link #setIssuer setIssuer} or
     54  * {@link #setKeyUsage setKeyUsage}, for instance) and then the
     55  * {@code X509CertSelector} is passed to
     56  * {@link CertStore#getCertificates CertStore.getCertificates} or some similar
     57  * method.
     58  * <p>
     59  * Several criteria can be enabled (by calling {@link #setIssuer setIssuer}
     60  * and {@link #setSerialNumber setSerialNumber},
     61  * for example) such that the {@code match} method
     62  * usually uniquely matches a single {@code X509Certificate}. We say
     63  * usually, since it is possible for two issuing CAs to have the same
     64  * distinguished name and each issue a certificate with the same serial
     65  * number. Other unique combinations include the issuer, subject,
     66  * subjectKeyIdentifier and/or the subjectPublicKey criteria.
     67  * <p>
     68  * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
     69  * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a> for
     70  * definitions of the X.509 certificate extensions mentioned below.
     71  * <p>
     72  * <b>Concurrent Access</b>
     73  * <p>
     74  * Unless otherwise specified, the methods defined in this class are not
     75  * thread-safe. Multiple threads that need to access a single
     76  * object concurrently should synchronize amongst themselves and
     77  * provide the necessary locking. Multiple threads each manipulating
     78  * separate objects need not synchronize.
     79  *
     80  * @see CertSelector
     81  * @see X509Certificate
     82  *
     83  * @since       1.4
     84  * @author      Steve Hanna
     85  */
     86 public class X509CertSelector implements CertSelector {
     87 
     88     private static final Debug debug = Debug.getInstance("certpath");
     89 
     90     private final static ObjectIdentifier ANY_EXTENDED_KEY_USAGE =
     91         ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0});
     92 
     93     static {
     94         CertPathHelperImpl.initialize();
     95     }
     96 
     97     private BigInteger serialNumber;
     98     private X500Principal issuer;
     99     private X500Principal subject;
    100     private byte[] subjectKeyID;
    101     private byte[] authorityKeyID;
    102     private Date certificateValid;
    103     private Date privateKeyValid;
    104     private ObjectIdentifier subjectPublicKeyAlgID;
    105     private PublicKey subjectPublicKey;
    106     private byte[] subjectPublicKeyBytes;
    107     private boolean[] keyUsage;
    108     private Set<String> keyPurposeSet;
    109     private Set<ObjectIdentifier> keyPurposeOIDSet;
    110     private Set<List<?>> subjectAlternativeNames;
    111     private Set<GeneralNameInterface> subjectAlternativeGeneralNames;
    112     private CertificatePolicySet policy;
    113     private Set<String> policySet;
    114     private Set<List<?>> pathToNames;
    115     private Set<GeneralNameInterface> pathToGeneralNames;
    116     private NameConstraintsExtension nc;
    117     private byte[] ncBytes;
    118     private int basicConstraints = -1;
    119     private X509Certificate x509Cert;
    120     private boolean matchAllSubjectAltNames = true;
    121 
    122     private static final Boolean FALSE = Boolean.FALSE;
    123 
    124     private static final int PRIVATE_KEY_USAGE_ID = 0;
    125     private static final int SUBJECT_ALT_NAME_ID = 1;
    126     private static final int NAME_CONSTRAINTS_ID = 2;
    127     private static final int CERT_POLICIES_ID = 3;
    128     private static final int EXTENDED_KEY_USAGE_ID = 4;
    129     private static final int NUM_OF_EXTENSIONS = 5;
    130     private static final String[] EXTENSION_OIDS = new String[NUM_OF_EXTENSIONS];
    131 
    132     static {
    133         EXTENSION_OIDS[PRIVATE_KEY_USAGE_ID]  = "2.5.29.16";
    134         EXTENSION_OIDS[SUBJECT_ALT_NAME_ID]   = "2.5.29.17";
    135         EXTENSION_OIDS[NAME_CONSTRAINTS_ID]   = "2.5.29.30";
    136         EXTENSION_OIDS[CERT_POLICIES_ID]      = "2.5.29.32";
    137         EXTENSION_OIDS[EXTENDED_KEY_USAGE_ID] = "2.5.29.37";
    138     };
    139 
    140     /* Constants representing the GeneralName types */
    141     static final int NAME_ANY = 0;
    142     static final int NAME_RFC822 = 1;
    143     static final int NAME_DNS = 2;
    144     static final int NAME_X400 = 3;
    145     static final int NAME_DIRECTORY = 4;
    146     static final int NAME_EDI = 5;
    147     static final int NAME_URI = 6;
    148     static final int NAME_IP = 7;
    149     static final int NAME_OID = 8;
    150 
    151     /**
    152      * Creates an {@code X509CertSelector}. Initially, no criteria are set
    153      * so any {@code X509Certificate} will match.
    154      */
    155     public X509CertSelector() {
    156         // empty
    157     }
    158 
    159     /**
    160      * Sets the certificateEquals criterion. The specified
    161      * {@code X509Certificate} must be equal to the
    162      * {@code X509Certificate} passed to the {@code match} method.
    163      * If {@code null}, then this check is not applied.
    164      *
    165      * <p>This method is particularly useful when it is necessary to
    166      * match a single certificate. Although other criteria can be specified
    167      * in conjunction with the certificateEquals criterion, it is usually not
    168      * practical or necessary.
    169      *
    170      * @param cert the {@code X509Certificate} to match (or
    171      * {@code null})
    172      * @see #getCertificate
    173      */
    174     public void setCertificate(X509Certificate cert) {
    175         x509Cert = cert;
    176     }
    177 
    178     /**
    179      * Sets the serialNumber criterion. The specified serial number
    180      * must match the certificate serial number in the
    181      * {@code X509Certificate}. If {@code null}, any certificate
    182      * serial number will do.
    183      *
    184      * @param serial the certificate serial number to match
    185      *        (or {@code null})
    186      * @see #getSerialNumber
    187      */
    188     public void setSerialNumber(BigInteger serial) {
    189         serialNumber = serial;
    190     }
    191 
    192     /**
    193      * Sets the issuer criterion. The specified distinguished name
    194      * must match the issuer distinguished name in the
    195      * {@code X509Certificate}. If {@code null}, any issuer
    196      * distinguished name will do.
    197      *
    198      * @param issuer a distinguished name as X500Principal
    199      *                 (or {@code null})
    200      * @since 1.5
    201      */
    202     public void setIssuer(X500Principal issuer) {
    203         this.issuer = issuer;
    204     }
    205 
    206     /**
    207      * <strong>Denigrated</strong>, use {@linkplain #setIssuer(X500Principal)}
    208      * or {@linkplain #setIssuer(byte[])} instead. This method should not be
    209      * relied on as it can fail to match some certificates because of a loss of
    210      * encoding information in the
    211      * <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a> String form
    212      * of some distinguished names.
    213      * <p>
    214      * Sets the issuer criterion. The specified distinguished name
    215      * must match the issuer distinguished name in the
    216      * {@code X509Certificate}. If {@code null}, any issuer
    217      * distinguished name will do.
    218      * <p>
    219      * If {@code issuerDN} is not {@code null}, it should contain a
    220      * distinguished name, in RFC 2253 format.
    221      *
    222      * @param issuerDN a distinguished name in RFC 2253 format
    223      *                 (or {@code null})
    224      * @throws IOException if a parsing error occurs (incorrect form for DN)
    225      */
    226     public void setIssuer(String issuerDN) throws IOException {
    227         if (issuerDN == null) {
    228             issuer = null;
    229         } else {
    230             issuer = new X500Name(issuerDN).asX500Principal();
    231         }
    232     }
    233 
    234     /**
    235      * Sets the issuer criterion. The specified distinguished name
    236      * must match the issuer distinguished name in the
    237      * {@code X509Certificate}. If {@code null} is specified,
    238      * the issuer criterion is disabled and any issuer distinguished name will
    239      * do.
    240      * <p>
    241      * If {@code issuerDN} is not {@code null}, it should contain a
    242      * single DER encoded distinguished name, as defined in X.501. The ASN.1
    243      * notation for this structure is as follows.
    244      * <pre>{@code
    245      * Name ::= CHOICE {
    246      *   RDNSequence }
    247      *
    248      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
    249      *
    250      * RelativeDistinguishedName ::=
    251      *   SET SIZE (1 .. MAX) OF AttributeTypeAndValue
    252      *
    253      * AttributeTypeAndValue ::= SEQUENCE {
    254      *   type     AttributeType,
    255      *   value    AttributeValue }
    256      *
    257      * AttributeType ::= OBJECT IDENTIFIER
    258      *
    259      * AttributeValue ::= ANY DEFINED BY AttributeType
    260      * ....
    261      * DirectoryString ::= CHOICE {
    262      *       teletexString           TeletexString (SIZE (1..MAX)),
    263      *       printableString         PrintableString (SIZE (1..MAX)),
    264      *       universalString         UniversalString (SIZE (1..MAX)),
    265      *       utf8String              UTF8String (SIZE (1.. MAX)),
    266      *       bmpString               BMPString (SIZE (1..MAX)) }
    267      * }</pre>
    268      * <p>
    269      * Note that the byte array specified here is cloned to protect against
    270      * subsequent modifications.
    271      *
    272      * @param issuerDN a byte array containing the distinguished name
    273      *                 in ASN.1 DER encoded form (or {@code null})
    274      * @throws IOException if an encoding error occurs (incorrect form for DN)
    275      */
    276     public void setIssuer(byte[] issuerDN) throws IOException {
    277         try {
    278             issuer = (issuerDN == null ? null : new X500Principal(issuerDN));
    279         } catch (IllegalArgumentException e) {
    280             throw new IOException("Invalid name", e);
    281         }
    282     }
    283 
    284     /**
    285      * Sets the subject criterion. The specified distinguished name
    286      * must match the subject distinguished name in the
    287      * {@code X509Certificate}. If {@code null}, any subject
    288      * distinguished name will do.
    289      *
    290      * @param subject a distinguished name as X500Principal
    291      *                  (or {@code null})
    292      * @since 1.5
    293      */
    294     public void setSubject(X500Principal subject) {
    295         this.subject = subject;
    296     }
    297 
    298     /**
    299      * <strong>Denigrated</strong>, use {@linkplain #setSubject(X500Principal)}
    300      * or {@linkplain #setSubject(byte[])} instead. This method should not be
    301      * relied on as it can fail to match some certificates because of a loss of
    302      * encoding information in the RFC 2253 String form of some distinguished
    303      * names.
    304      * <p>
    305      * Sets the subject criterion. The specified distinguished name
    306      * must match the subject distinguished name in the
    307      * {@code X509Certificate}. If {@code null}, any subject
    308      * distinguished name will do.
    309      * <p>
    310      * If {@code subjectDN} is not {@code null}, it should contain a
    311      * distinguished name, in RFC 2253 format.
    312      *
    313      * @param subjectDN a distinguished name in RFC 2253 format
    314      *                  (or {@code null})
    315      * @throws IOException if a parsing error occurs (incorrect form for DN)
    316      */
    317     public void setSubject(String subjectDN) throws IOException {
    318         if (subjectDN == null) {
    319             subject = null;
    320         } else {
    321             subject = new X500Name(subjectDN).asX500Principal();
    322         }
    323     }
    324 
    325     /**
    326      * Sets the subject criterion. The specified distinguished name
    327      * must match the subject distinguished name in the
    328      * {@code X509Certificate}. If {@code null}, any subject
    329      * distinguished name will do.
    330      * <p>
    331      * If {@code subjectDN} is not {@code null}, it should contain a
    332      * single DER encoded distinguished name, as defined in X.501. For the ASN.1
    333      * notation for this structure, see
    334      * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
    335      *
    336      * @param subjectDN a byte array containing the distinguished name in
    337      *                  ASN.1 DER format (or {@code null})
    338      * @throws IOException if an encoding error occurs (incorrect form for DN)
    339      */
    340     public void setSubject(byte[] subjectDN) throws IOException {
    341         try {
    342             subject = (subjectDN == null ? null : new X500Principal(subjectDN));
    343         } catch (IllegalArgumentException e) {
    344             throw new IOException("Invalid name", e);
    345         }
    346     }
    347 
    348     /**
    349      * Sets the subjectKeyIdentifier criterion. The
    350      * {@code X509Certificate} must contain a SubjectKeyIdentifier
    351      * extension for which the contents of the extension
    352      * matches the specified criterion value.
    353      * If the criterion value is {@code null}, no
    354      * subjectKeyIdentifier check will be done.
    355      * <p>
    356      * If {@code subjectKeyID} is not {@code null}, it
    357      * should contain a single DER encoded value corresponding to the contents
    358      * of the extension value (not including the object identifier,
    359      * criticality setting, and encapsulating OCTET STRING)
    360      * for a SubjectKeyIdentifier extension.
    361      * The ASN.1 notation for this structure follows.
    362      *
    363      * <pre>{@code
    364      * SubjectKeyIdentifier ::= KeyIdentifier
    365      *
    366      * KeyIdentifier ::= OCTET STRING
    367      * }</pre>
    368      * <p>
    369      * Since the format of subject key identifiers is not mandated by
    370      * any standard, subject key identifiers are not parsed by the
    371      * {@code X509CertSelector}. Instead, the values are compared using
    372      * a byte-by-byte comparison.
    373      * <p>
    374      * Note that the byte array supplied here is cloned to protect against
    375      * subsequent modifications.
    376      *
    377      * @param subjectKeyID the subject key identifier (or {@code null})
    378      * @see #getSubjectKeyIdentifier
    379      */
    380     public void setSubjectKeyIdentifier(byte[] subjectKeyID) {
    381         if (subjectKeyID == null) {
    382             this.subjectKeyID = null;
    383         } else {
    384             this.subjectKeyID = subjectKeyID.clone();
    385         }
    386     }
    387 
    388     /**
    389      * Sets the authorityKeyIdentifier criterion. The
    390      * {@code X509Certificate} must contain an
    391      * AuthorityKeyIdentifier extension for which the contents of the
    392      * extension value matches the specified criterion value.
    393      * If the criterion value is {@code null}, no
    394      * authorityKeyIdentifier check will be done.
    395      * <p>
    396      * If {@code authorityKeyID} is not {@code null}, it
    397      * should contain a single DER encoded value corresponding to the contents
    398      * of the extension value (not including the object identifier,
    399      * criticality setting, and encapsulating OCTET STRING)
    400      * for an AuthorityKeyIdentifier extension.
    401      * The ASN.1 notation for this structure follows.
    402      *
    403      * <pre>{@code
    404      * AuthorityKeyIdentifier ::= SEQUENCE {
    405      *    keyIdentifier             [0] KeyIdentifier           OPTIONAL,
    406      *    authorityCertIssuer       [1] GeneralNames            OPTIONAL,
    407      *    authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
    408      *
    409      * KeyIdentifier ::= OCTET STRING
    410      * }</pre>
    411      * <p>
    412      * Authority key identifiers are not parsed by the
    413      * {@code X509CertSelector}.  Instead, the values are
    414      * compared using a byte-by-byte comparison.
    415      * <p>
    416      * When the {@code keyIdentifier} field of
    417      * {@code AuthorityKeyIdentifier} is populated, the value is
    418      * usually taken from the {@code SubjectKeyIdentifier} extension
    419      * in the issuer's certificate.  Note, however, that the result of
    420      * {@code X509Certificate.getExtensionValue(<SubjectKeyIdentifier Object
    421      * Identifier>)} on the issuer's certificate may NOT be used
    422      * directly as the input to {@code setAuthorityKeyIdentifier}.
    423      * This is because the SubjectKeyIdentifier contains
    424      * only a KeyIdentifier OCTET STRING, and not a SEQUENCE of
    425      * KeyIdentifier, GeneralNames, and CertificateSerialNumber.
    426      * In order to use the extension value of the issuer certificate's
    427      * {@code SubjectKeyIdentifier}
    428      * extension, it will be necessary to extract the value of the embedded
    429      * {@code KeyIdentifier} OCTET STRING, then DER encode this OCTET
    430      * STRING inside a SEQUENCE.
    431      * For more details on SubjectKeyIdentifier, see
    432      * {@link #setSubjectKeyIdentifier(byte[] subjectKeyID)}.
    433      * <p>
    434      * Note also that the byte array supplied here is cloned to protect against
    435      * subsequent modifications.
    436      *
    437      * @param authorityKeyID the authority key identifier
    438      *        (or {@code null})
    439      * @see #getAuthorityKeyIdentifier
    440      */
    441     public void setAuthorityKeyIdentifier(byte[] authorityKeyID) {
    442         if (authorityKeyID == null) {
    443             this.authorityKeyID = null;
    444         } else {
    445             this.authorityKeyID = authorityKeyID.clone();
    446         }
    447     }
    448 
    449     /**
    450      * Sets the certificateValid criterion. The specified date must fall
    451      * within the certificate validity period for the
    452      * {@code X509Certificate}. If {@code null}, no certificateValid
    453      * check will be done.
    454      * <p>
    455      * Note that the {@code Date} supplied here is cloned to protect
    456      * against subsequent modifications.
    457      *
    458      * @param certValid the {@code Date} to check (or {@code null})
    459      * @see #getCertificateValid
    460      */
    461     public void setCertificateValid(Date certValid) {
    462         if (certValid == null) {
    463             certificateValid = null;
    464         } else {
    465             certificateValid = (Date)certValid.clone();
    466         }
    467     }
    468 
    469     /**
    470      * Sets the privateKeyValid criterion. The specified date must fall
    471      * within the private key validity period for the
    472      * {@code X509Certificate}. If {@code null}, no privateKeyValid
    473      * check will be done.
    474      * <p>
    475      * Note that the {@code Date} supplied here is cloned to protect
    476      * against subsequent modifications.
    477      *
    478      * @param privateKeyValid the {@code Date} to check (or
    479      *                        {@code null})
    480      * @see #getPrivateKeyValid
    481      */
    482     public void setPrivateKeyValid(Date privateKeyValid) {
    483         if (privateKeyValid == null) {
    484             this.privateKeyValid = null;
    485         } else {
    486             this.privateKeyValid = (Date)privateKeyValid.clone();
    487         }
    488     }
    489 
    490     /**
    491      * Sets the subjectPublicKeyAlgID criterion. The
    492      * {@code X509Certificate} must contain a subject public key
    493      * with the specified algorithm. If {@code null}, no
    494      * subjectPublicKeyAlgID check will be done.
    495      *
    496      * @param oid The object identifier (OID) of the algorithm to check
    497      *            for (or {@code null}). An OID is represented by a
    498      *            set of nonnegative integers separated by periods.
    499      * @throws IOException if the OID is invalid, such as
    500      * the first component being not 0, 1 or 2 or the second component
    501      * being greater than 39.
    502      *
    503      * @see #getSubjectPublicKeyAlgID
    504      */
    505     public void setSubjectPublicKeyAlgID(String oid) throws IOException {
    506         if (oid == null) {
    507             subjectPublicKeyAlgID = null;
    508         } else {
    509             subjectPublicKeyAlgID = new ObjectIdentifier(oid);
    510         }
    511     }
    512 
    513     /**
    514      * Sets the subjectPublicKey criterion. The
    515      * {@code X509Certificate} must contain the specified subject public
    516      * key. If {@code null}, no subjectPublicKey check will be done.
    517      *
    518      * @param key the subject public key to check for (or {@code null})
    519      * @see #getSubjectPublicKey
    520      */
    521     public void setSubjectPublicKey(PublicKey key) {
    522         if (key == null) {
    523             subjectPublicKey = null;
    524             subjectPublicKeyBytes = null;
    525         } else {
    526             subjectPublicKey = key;
    527             subjectPublicKeyBytes = key.getEncoded();
    528         }
    529     }
    530 
    531     /**
    532      * Sets the subjectPublicKey criterion. The {@code X509Certificate}
    533      * must contain the specified subject public key. If {@code null},
    534      * no subjectPublicKey check will be done.
    535      * <p>
    536      * Because this method allows the public key to be specified as a byte
    537      * array, it may be used for unknown key types.
    538      * <p>
    539      * If {@code key} is not {@code null}, it should contain a
    540      * single DER encoded SubjectPublicKeyInfo structure, as defined in X.509.
    541      * The ASN.1 notation for this structure is as follows.
    542      * <pre>{@code
    543      * SubjectPublicKeyInfo  ::=  SEQUENCE  {
    544      *   algorithm            AlgorithmIdentifier,
    545      *   subjectPublicKey     BIT STRING  }
    546      *
    547      * AlgorithmIdentifier  ::=  SEQUENCE  {
    548      *   algorithm               OBJECT IDENTIFIER,
    549      *   parameters              ANY DEFINED BY algorithm OPTIONAL  }
    550      *                              -- contains a value of the type
    551      *                              -- registered for use with the
    552      *                              -- algorithm object identifier value
    553      * }</pre>
    554      * <p>
    555      * Note that the byte array supplied here is cloned to protect against
    556      * subsequent modifications.
    557      *
    558      * @param key a byte array containing the subject public key in ASN.1 DER
    559      *            form (or {@code null})
    560      * @throws IOException if an encoding error occurs (incorrect form for
    561      * subject public key)
    562      * @see #getSubjectPublicKey
    563      */
    564     public void setSubjectPublicKey(byte[] key) throws IOException {
    565         if (key == null) {
    566             subjectPublicKey = null;
    567             subjectPublicKeyBytes = null;
    568         } else {
    569             subjectPublicKeyBytes = key.clone();
    570             subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes));
    571         }
    572     }
    573 
    574     /**
    575      * Sets the keyUsage criterion. The {@code X509Certificate}
    576      * must allow the specified keyUsage values. If {@code null}, no
    577      * keyUsage check will be done. Note that an {@code X509Certificate}
    578      * that has no keyUsage extension implicitly allows all keyUsage values.
    579      * <p>
    580      * Note that the boolean array supplied here is cloned to protect against
    581      * subsequent modifications.
    582      *
    583      * @param keyUsage a boolean array in the same format as the boolean
    584      *                 array returned by
    585      * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
    586      *                 Or {@code null}.
    587      * @see #getKeyUsage
    588      */
    589     public void setKeyUsage(boolean[] keyUsage) {
    590         if (keyUsage == null) {
    591             this.keyUsage = null;
    592         } else {
    593             this.keyUsage = keyUsage.clone();
    594         }
    595     }
    596 
    597     /**
    598      * Sets the extendedKeyUsage criterion. The {@code X509Certificate}
    599      * must allow the specified key purposes in its extended key usage
    600      * extension. If {@code keyPurposeSet} is empty or {@code null},
    601      * no extendedKeyUsage check will be done. Note that an
    602      * {@code X509Certificate} that has no extendedKeyUsage extension
    603      * implicitly allows all key purposes.
    604      * <p>
    605      * Note that the {@code Set} is cloned to protect against
    606      * subsequent modifications.
    607      *
    608      * @param keyPurposeSet a {@code Set} of key purpose OIDs in string
    609      * format (or {@code null}). Each OID is represented by a set of
    610      * nonnegative integers separated by periods.
    611      * @throws IOException if the OID is invalid, such as
    612      * the first component being not 0, 1 or 2 or the second component
    613      * being greater than 39.
    614      * @see #getExtendedKeyUsage
    615      */
    616     public void setExtendedKeyUsage(Set<String> keyPurposeSet) throws IOException {
    617         if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
    618             this.keyPurposeSet = null;
    619             keyPurposeOIDSet = null;
    620         } else {
    621             this.keyPurposeSet =
    622                 Collections.unmodifiableSet(new HashSet<String>(keyPurposeSet));
    623             keyPurposeOIDSet = new HashSet<ObjectIdentifier>();
    624             for (String s : this.keyPurposeSet) {
    625                 keyPurposeOIDSet.add(new ObjectIdentifier(s));
    626             }
    627         }
    628     }
    629 
    630     /**
    631      * Enables/disables matching all of the subjectAlternativeNames
    632      * specified in the {@link #setSubjectAlternativeNames
    633      * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
    634      * addSubjectAlternativeName} methods. If enabled,
    635      * the {@code X509Certificate} must contain all of the
    636      * specified subject alternative names. If disabled, the
    637      * {@code X509Certificate} must contain at least one of the
    638      * specified subject alternative names.
    639      *
    640      * <p>The matchAllNames flag is {@code true} by default.
    641      *
    642      * @param matchAllNames if {@code true}, the flag is enabled;
    643      * if {@code false}, the flag is disabled.
    644      * @see #getMatchAllSubjectAltNames
    645      */
    646     public void setMatchAllSubjectAltNames(boolean matchAllNames) {
    647         this.matchAllSubjectAltNames = matchAllNames;
    648     }
    649 
    650     /**
    651      * Sets the subjectAlternativeNames criterion. The
    652      * {@code X509Certificate} must contain all or at least one of the
    653      * specified subjectAlternativeNames, depending on the value of
    654      * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
    655      * setMatchAllSubjectAltNames}).
    656      * <p>
    657      * This method allows the caller to specify, with a single method call,
    658      * the complete set of subject alternative names for the
    659      * subjectAlternativeNames criterion. The specified value replaces
    660      * the previous value for the subjectAlternativeNames criterion.
    661      * <p>
    662      * The {@code names} parameter (if not {@code null}) is a
    663      * {@code Collection} with one
    664      * entry for each name to be included in the subject alternative name
    665      * criterion. Each entry is a {@code List} whose first entry is an
    666      * {@code Integer} (the name type, 0-8) and whose second
    667      * entry is a {@code String} or a byte array (the name, in
    668      * string or ASN.1 DER encoded form, respectively).
    669      * There can be multiple names of the same type. If {@code null}
    670      * is supplied as the value for this argument, no
    671      * subjectAlternativeNames check will be performed.
    672      * <p>
    673      * Each subject alternative name in the {@code Collection}
    674      * may be specified either as a {@code String} or as an ASN.1 encoded
    675      * byte array. For more details about the formats used, see
    676      * {@link #addSubjectAlternativeName(int type, String name)
    677      * addSubjectAlternativeName(int type, String name)} and
    678      * {@link #addSubjectAlternativeName(int type, byte [] name)
    679      * addSubjectAlternativeName(int type, byte [] name)}.
    680      * <p>
    681      * <strong>Note:</strong> for distinguished names, specify the byte
    682      * array form instead of the String form. See the note in
    683      * {@link #addSubjectAlternativeName(int, String)} for more information.
    684      * <p>
    685      * Note that the {@code names} parameter can contain duplicate
    686      * names (same name and name type), but they may be removed from the
    687      * {@code Collection} of names returned by the
    688      * {@link #getSubjectAlternativeNames getSubjectAlternativeNames} method.
    689      * <p>
    690      * Note that a deep copy is performed on the {@code Collection} to
    691      * protect against subsequent modifications.
    692      *
    693      * @param names a {@code Collection} of names (or {@code null})
    694      * @throws IOException if a parsing error occurs
    695      * @see #getSubjectAlternativeNames
    696      */
    697     public void setSubjectAlternativeNames(Collection<List<?>> names)
    698             throws IOException {
    699         if (names == null) {
    700             subjectAlternativeNames = null;
    701             subjectAlternativeGeneralNames = null;
    702         } else {
    703             if (names.isEmpty()) {
    704                 subjectAlternativeNames = null;
    705                 subjectAlternativeGeneralNames = null;
    706                 return;
    707             }
    708             Set<List<?>> tempNames = cloneAndCheckNames(names);
    709             // Ensure that we either set both of these or neither
    710             subjectAlternativeGeneralNames = parseNames(tempNames);
    711             subjectAlternativeNames = tempNames;
    712         }
    713     }
    714 
    715     /**
    716      * Adds a name to the subjectAlternativeNames criterion. The
    717      * {@code X509Certificate} must contain all or at least one
    718      * of the specified subjectAlternativeNames, depending on the value of
    719      * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
    720      * setMatchAllSubjectAltNames}).
    721      * <p>
    722      * This method allows the caller to add a name to the set of subject
    723      * alternative names.
    724      * The specified name is added to any previous value for the
    725      * subjectAlternativeNames criterion. If the specified name is a
    726      * duplicate, it may be ignored.
    727      * <p>
    728      * The name is provided in string format.
    729      * <a href="http://www.ietf.org/rfc/rfc822.txt">RFC 822</a>, DNS, and URI
    730      * names use the well-established string formats for those types (subject to
    731      * the restrictions included in RFC 3280). IPv4 address names are
    732      * supplied using dotted quad notation. OID address names are represented
    733      * as a series of nonnegative integers separated by periods. And
    734      * directory names (distinguished names) are supplied in RFC 2253 format.
    735      * No standard string format is defined for otherNames, X.400 names,
    736      * EDI party names, IPv6 address names, or any other type of names. They
    737      * should be specified using the
    738      * {@link #addSubjectAlternativeName(int type, byte [] name)
    739      * addSubjectAlternativeName(int type, byte [] name)}
    740      * method.
    741      * <p>
    742      * <strong>Note:</strong> for distinguished names, use
    743      * {@linkplain #addSubjectAlternativeName(int, byte[])} instead.
    744      * This method should not be relied on as it can fail to match some
    745      * certificates because of a loss of encoding information in the RFC 2253
    746      * String form of some distinguished names.
    747      *
    748      * @param type the name type (0-8, as specified in
    749      *             RFC 3280, section 4.2.1.7)
    750      * @param name the name in string form (not {@code null})
    751      * @throws IOException if a parsing error occurs
    752      */
    753     public void addSubjectAlternativeName(int type, String name)
    754             throws IOException {
    755         addSubjectAlternativeNameInternal(type, name);
    756     }
    757 
    758     /**
    759      * Adds a name to the subjectAlternativeNames criterion. The
    760      * {@code X509Certificate} must contain all or at least one
    761      * of the specified subjectAlternativeNames, depending on the value of
    762      * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
    763      * setMatchAllSubjectAltNames}).
    764      * <p>
    765      * This method allows the caller to add a name to the set of subject
    766      * alternative names.
    767      * The specified name is added to any previous value for the
    768      * subjectAlternativeNames criterion. If the specified name is a
    769      * duplicate, it may be ignored.
    770      * <p>
    771      * The name is provided as a byte array. This byte array should contain
    772      * the DER encoded name, as it would appear in the GeneralName structure
    773      * defined in RFC 3280 and X.509. The encoded byte array should only contain
    774      * the encoded value of the name, and should not include the tag associated
    775      * with the name in the GeneralName structure. The ASN.1 definition of this
    776      * structure appears below.
    777      * <pre>{@code
    778      *  GeneralName ::= CHOICE {
    779      *       otherName                       [0]     OtherName,
    780      *       rfc822Name                      [1]     IA5String,
    781      *       dNSName                         [2]     IA5String,
    782      *       x400Address                     [3]     ORAddress,
    783      *       directoryName                   [4]     Name,
    784      *       ediPartyName                    [5]     EDIPartyName,
    785      *       uniformResourceIdentifier       [6]     IA5String,
    786      *       iPAddress                       [7]     OCTET STRING,
    787      *       registeredID                    [8]     OBJECT IDENTIFIER}
    788      * }</pre>
    789      * <p>
    790      * Note that the byte array supplied here is cloned to protect against
    791      * subsequent modifications.
    792      *
    793      * @param type the name type (0-8, as listed above)
    794      * @param name a byte array containing the name in ASN.1 DER encoded form
    795      * @throws IOException if a parsing error occurs
    796      */
    797     public void addSubjectAlternativeName(int type, byte[] name)
    798             throws IOException {
    799         // clone because byte arrays are modifiable
    800         addSubjectAlternativeNameInternal(type, name.clone());
    801     }
    802 
    803     /**
    804      * A private method that adds a name (String or byte array) to the
    805      * subjectAlternativeNames criterion. The {@code X509Certificate}
    806      * must contain the specified subjectAlternativeName.
    807      *
    808      * @param type the name type (0-8, as specified in
    809      *             RFC 3280, section 4.2.1.7)
    810      * @param name the name in string or byte array form
    811      * @throws IOException if a parsing error occurs
    812      */
    813     private void addSubjectAlternativeNameInternal(int type, Object name)
    814             throws IOException {
    815         // First, ensure that the name parses
    816         GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
    817         if (subjectAlternativeNames == null) {
    818             subjectAlternativeNames = new HashSet<List<?>>();
    819         }
    820         if (subjectAlternativeGeneralNames == null) {
    821             subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>();
    822         }
    823         List<Object> list = new ArrayList<Object>(2);
    824         list.add(Integer.valueOf(type));
    825         list.add(name);
    826         subjectAlternativeNames.add(list);
    827         subjectAlternativeGeneralNames.add(tempName);
    828     }
    829 
    830     /**
    831      * Parse an argument of the form passed to setSubjectAlternativeNames,
    832      * returning a {@code Collection} of
    833      * {@code GeneralNameInterface}s.
    834      * Throw an IllegalArgumentException or a ClassCastException
    835      * if the argument is malformed.
    836      *
    837      * @param names a Collection with one entry per name.
    838      *              Each entry is a {@code List} whose first entry
    839      *              is an Integer (the name type, 0-8) and whose second
    840      *              entry is a String or a byte array (the name, in
    841      *              string or ASN.1 DER encoded form, respectively).
    842      *              There can be multiple names of the same type. Null is
    843      *              not an acceptable value.
    844      * @return a Set of {@code GeneralNameInterface}s
    845      * @throws IOException if a parsing error occurs
    846      */
    847     private static Set<GeneralNameInterface> parseNames(Collection<List<?>> names) throws IOException {
    848         Set<GeneralNameInterface> genNames = new HashSet<GeneralNameInterface>();
    849         for (List<?> nameList : names) {
    850             if (nameList.size() != 2) {
    851                 throw new IOException("name list size not 2");
    852             }
    853             Object o =  nameList.get(0);
    854             if (!(o instanceof Integer)) {
    855                 throw new IOException("expected an Integer");
    856             }
    857             int nameType = ((Integer)o).intValue();
    858             o = nameList.get(1);
    859             genNames.add(makeGeneralNameInterface(nameType, o));
    860         }
    861 
    862         return genNames;
    863     }
    864 
    865     /**
    866      * Compare for equality two objects of the form passed to
    867      * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames).
    868      * Throw an {@code IllegalArgumentException} or a
    869      * {@code ClassCastException} if one of the objects is malformed.
    870      *
    871      * @param object1 a Collection containing the first object to compare
    872      * @param object2 a Collection containing the second object to compare
    873      * @return true if the objects are equal, false otherwise
    874      */
    875     static boolean equalNames(Collection<?> object1, Collection<?> object2) {
    876         if ((object1 == null) || (object2 == null)) {
    877             return object1 == object2;
    878         }
    879         return object1.equals(object2);
    880     }
    881 
    882     /**
    883      * Make a {@code GeneralNameInterface} out of a name type (0-8) and an
    884      * Object that may be a byte array holding the ASN.1 DER encoded
    885      * name or a String form of the name.  Except for X.509
    886      * Distinguished Names, the String form of the name must not be the
    887      * result from calling toString on an existing GeneralNameInterface
    888      * implementing class.  The output of toString is not compatible
    889      * with the String constructors for names other than Distinguished
    890      * Names.
    891      *
    892      * @param type name type (0-8)
    893      * @param name name as ASN.1 Der-encoded byte array or String
    894      * @return a GeneralNameInterface name
    895      * @throws IOException if a parsing error occurs
    896      */
    897     static GeneralNameInterface makeGeneralNameInterface(int type, Object name)
    898             throws IOException {
    899         GeneralNameInterface result;
    900         if (debug != null) {
    901             debug.println("X509CertSelector.makeGeneralNameInterface("
    902                 + type + ")...");
    903         }
    904 
    905         if (name instanceof String) {
    906             if (debug != null) {
    907                 debug.println("X509CertSelector.makeGeneralNameInterface() "
    908                     + "name is String: " + name);
    909             }
    910             switch (type) {
    911             case NAME_RFC822:
    912                 result = new RFC822Name((String)name);
    913                 break;
    914             case NAME_DNS:
    915                 result = new DNSName((String)name);
    916                 break;
    917             case NAME_DIRECTORY:
    918                 result = new X500Name((String)name);
    919                 break;
    920             case NAME_URI:
    921                 result = new URIName((String)name);
    922                 break;
    923             case NAME_IP:
    924                 result = new IPAddressName((String)name);
    925                 break;
    926             case NAME_OID:
    927                 result = new OIDName((String)name);
    928                 break;
    929             default:
    930                 throw new IOException("unable to parse String names of type "
    931                                       + type);
    932             }
    933             if (debug != null) {
    934                 debug.println("X509CertSelector.makeGeneralNameInterface() "
    935                     + "result: " + result.toString());
    936             }
    937         } else if (name instanceof byte[]) {
    938             DerValue val = new DerValue((byte[]) name);
    939             if (debug != null) {
    940                 debug.println
    941                     ("X509CertSelector.makeGeneralNameInterface() is byte[]");
    942             }
    943 
    944             switch (type) {
    945             case NAME_ANY:
    946                 result = new OtherName(val);
    947                 break;
    948             case NAME_RFC822:
    949                 result = new RFC822Name(val);
    950                 break;
    951             case NAME_DNS:
    952                 result = new DNSName(val);
    953                 break;
    954             case NAME_X400:
    955                 result = new X400Address(val);
    956                 break;
    957             case NAME_DIRECTORY:
    958                 result = new X500Name(val);
    959                 break;
    960             case NAME_EDI:
    961                 result = new EDIPartyName(val);
    962                 break;
    963             case NAME_URI:
    964                 result = new URIName(val);
    965                 break;
    966             case NAME_IP:
    967                 result = new IPAddressName(val);
    968                 break;
    969             case NAME_OID:
    970                 result = new OIDName(val);
    971                 break;
    972             default:
    973                 throw new IOException("unable to parse byte array names of "
    974                     + "type " + type);
    975             }
    976             if (debug != null) {
    977                 debug.println("X509CertSelector.makeGeneralNameInterface() result: "
    978                     + result.toString());
    979             }
    980         } else {
    981             if (debug != null) {
    982                 debug.println("X509CertSelector.makeGeneralName() input name "
    983                     + "not String or byte array");
    984             }
    985             throw new IOException("name not String or byte array");
    986         }
    987         return result;
    988     }
    989 
    990 
    991     /**
    992      * Sets the name constraints criterion. The {@code X509Certificate}
    993      * must have subject and subject alternative names that
    994      * meet the specified name constraints.
    995      * <p>
    996      * The name constraints are specified as a byte array. This byte array
    997      * should contain the DER encoded form of the name constraints, as they
    998      * would appear in the NameConstraints structure defined in RFC 3280
    999      * and X.509. The ASN.1 definition of this structure appears below.
   1000      *
   1001      * <pre>{@code
   1002      *  NameConstraints ::= SEQUENCE {
   1003      *       permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
   1004      *       excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
   1005      *
   1006      *  GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
   1007      *
   1008      *  GeneralSubtree ::= SEQUENCE {
   1009      *       base                    GeneralName,
   1010      *       minimum         [0]     BaseDistance DEFAULT 0,
   1011      *       maximum         [1]     BaseDistance OPTIONAL }
   1012      *
   1013      *  BaseDistance ::= INTEGER (0..MAX)
   1014      *
   1015      *  GeneralName ::= CHOICE {
   1016      *       otherName                       [0]     OtherName,
   1017      *       rfc822Name                      [1]     IA5String,
   1018      *       dNSName                         [2]     IA5String,
   1019      *       x400Address                     [3]     ORAddress,
   1020      *       directoryName                   [4]     Name,
   1021      *       ediPartyName                    [5]     EDIPartyName,
   1022      *       uniformResourceIdentifier       [6]     IA5String,
   1023      *       iPAddress                       [7]     OCTET STRING,
   1024      *       registeredID                    [8]     OBJECT IDENTIFIER}
   1025      * }</pre>
   1026      * <p>
   1027      * Note that the byte array supplied here is cloned to protect against
   1028      * subsequent modifications.
   1029      *
   1030      * @param bytes a byte array containing the ASN.1 DER encoding of
   1031      *              a NameConstraints extension to be used for checking
   1032      *              name constraints. Only the value of the extension is
   1033      *              included, not the OID or criticality flag. Can be
   1034      *              {@code null},
   1035      *              in which case no name constraints check will be performed.
   1036      * @throws IOException if a parsing error occurs
   1037      * @see #getNameConstraints
   1038      */
   1039     public void setNameConstraints(byte[] bytes) throws IOException {
   1040         if (bytes == null) {
   1041             ncBytes = null;
   1042             nc = null;
   1043         } else {
   1044             ncBytes = bytes.clone();
   1045             nc = new NameConstraintsExtension(FALSE, bytes);
   1046         }
   1047     }
   1048 
   1049     /**
   1050      * Sets the basic constraints constraint. If the value is greater than or
   1051      * equal to zero, {@code X509Certificates} must include a
   1052      * basicConstraints extension with
   1053      * a pathLen of at least this value. If the value is -2, only end-entity
   1054      * certificates are accepted. If the value is -1, no check is done.
   1055      * <p>
   1056      * This constraint is useful when building a certification path forward
   1057      * (from the target toward the trust anchor. If a partial path has been
   1058      * built, any candidate certificate must have a maxPathLen value greater
   1059      * than or equal to the number of certificates in the partial path.
   1060      *
   1061      * @param minMaxPathLen the value for the basic constraints constraint
   1062      * @throws IllegalArgumentException if the value is less than -2
   1063      * @see #getBasicConstraints
   1064      */
   1065     public void setBasicConstraints(int minMaxPathLen) {
   1066         if (minMaxPathLen < -2) {
   1067             throw new IllegalArgumentException("basic constraints less than -2");
   1068         }
   1069         basicConstraints = minMaxPathLen;
   1070     }
   1071 
   1072     /**
   1073      * Sets the policy constraint. The {@code X509Certificate} must
   1074      * include at least one of the specified policies in its certificate
   1075      * policies extension. If {@code certPolicySet} is empty, then the
   1076      * {@code X509Certificate} must include at least some specified policy
   1077      * in its certificate policies extension. If {@code certPolicySet} is
   1078      * {@code null}, no policy check will be performed.
   1079      * <p>
   1080      * Note that the {@code Set} is cloned to protect against
   1081      * subsequent modifications.
   1082      *
   1083      * @param certPolicySet a {@code Set} of certificate policy OIDs in
   1084      *                      string format (or {@code null}). Each OID is
   1085      *                      represented by a set of nonnegative integers
   1086      *                    separated by periods.
   1087      * @throws IOException if a parsing error occurs on the OID such as
   1088      * the first component is not 0, 1 or 2 or the second component is
   1089      * greater than 39.
   1090      * @see #getPolicy
   1091      */
   1092     public void setPolicy(Set<String> certPolicySet) throws IOException {
   1093         if (certPolicySet == null) {
   1094             policySet = null;
   1095             policy = null;
   1096         } else {
   1097             // Snapshot set and parse it
   1098             Set<String> tempSet = Collections.unmodifiableSet
   1099                                         (new HashSet<String>(certPolicySet));
   1100             /* Convert to Vector of ObjectIdentifiers */
   1101             Iterator<String> i = tempSet.iterator();
   1102             Vector<CertificatePolicyId> polIdVector = new Vector<CertificatePolicyId>();
   1103             while (i.hasNext()) {
   1104                 Object o = i.next();
   1105                 if (!(o instanceof String)) {
   1106                     throw new IOException("non String in certPolicySet");
   1107                 }
   1108                 polIdVector.add(new CertificatePolicyId(new ObjectIdentifier(
   1109                   (String)o)));
   1110             }
   1111             // If everything went OK, make the changes
   1112             policySet = tempSet;
   1113             policy = new CertificatePolicySet(polIdVector);
   1114         }
   1115     }
   1116 
   1117     /**
   1118      * Sets the pathToNames criterion. The {@code X509Certificate} must
   1119      * not include name constraints that would prohibit building a
   1120      * path to the specified names.
   1121      * <p>
   1122      * This method allows the caller to specify, with a single method call,
   1123      * the complete set of names which the {@code X509Certificates}'s
   1124      * name constraints must permit. The specified value replaces
   1125      * the previous value for the pathToNames criterion.
   1126      * <p>
   1127      * This constraint is useful when building a certification path forward
   1128      * (from the target toward the trust anchor. If a partial path has been
   1129      * built, any candidate certificate must not include name constraints that
   1130      * would prohibit building a path to any of the names in the partial path.
   1131      * <p>
   1132      * The {@code names} parameter (if not {@code null}) is a
   1133      * {@code Collection} with one
   1134      * entry for each name to be included in the pathToNames
   1135      * criterion. Each entry is a {@code List} whose first entry is an
   1136      * {@code Integer} (the name type, 0-8) and whose second
   1137      * entry is a {@code String} or a byte array (the name, in
   1138      * string or ASN.1 DER encoded form, respectively).
   1139      * There can be multiple names of the same type. If {@code null}
   1140      * is supplied as the value for this argument, no
   1141      * pathToNames check will be performed.
   1142      * <p>
   1143      * Each name in the {@code Collection}
   1144      * may be specified either as a {@code String} or as an ASN.1 encoded
   1145      * byte array. For more details about the formats used, see
   1146      * {@link #addPathToName(int type, String name)
   1147      * addPathToName(int type, String name)} and
   1148      * {@link #addPathToName(int type, byte [] name)
   1149      * addPathToName(int type, byte [] name)}.
   1150      * <p>
   1151      * <strong>Note:</strong> for distinguished names, specify the byte
   1152      * array form instead of the String form. See the note in
   1153      * {@link #addPathToName(int, String)} for more information.
   1154      * <p>
   1155      * Note that the {@code names} parameter can contain duplicate
   1156      * names (same name and name type), but they may be removed from the
   1157      * {@code Collection} of names returned by the
   1158      * {@link #getPathToNames getPathToNames} method.
   1159      * <p>
   1160      * Note that a deep copy is performed on the {@code Collection} to
   1161      * protect against subsequent modifications.
   1162      *
   1163      * @param names a {@code Collection} with one entry per name
   1164      *              (or {@code null})
   1165      * @throws IOException if a parsing error occurs
   1166      * @see #getPathToNames
   1167      */
   1168     public void setPathToNames(Collection<List<?>> names) throws IOException {
   1169         if ((names == null) || names.isEmpty()) {
   1170             pathToNames = null;
   1171             pathToGeneralNames = null;
   1172         } else {
   1173             Set<List<?>> tempNames = cloneAndCheckNames(names);
   1174             pathToGeneralNames = parseNames(tempNames);
   1175             // Ensure that we either set both of these or neither
   1176             pathToNames = tempNames;
   1177         }
   1178     }
   1179 
   1180     // called from CertPathHelper
   1181     void setPathToNamesInternal(Set<GeneralNameInterface> names) {
   1182         // set names to non-null dummy value
   1183         // this breaks getPathToNames()
   1184         pathToNames = Collections.<List<?>>emptySet();
   1185         pathToGeneralNames = names;
   1186     }
   1187 
   1188     /**
   1189      * Adds a name to the pathToNames criterion. The {@code X509Certificate}
   1190      * must not include name constraints that would prohibit building a
   1191      * path to the specified name.
   1192      * <p>
   1193      * This method allows the caller to add a name to the set of names which
   1194      * the {@code X509Certificates}'s name constraints must permit.
   1195      * The specified name is added to any previous value for the
   1196      * pathToNames criterion.  If the name is a duplicate, it may be ignored.
   1197      * <p>
   1198      * The name is provided in string format. RFC 822, DNS, and URI names
   1199      * use the well-established string formats for those types (subject to
   1200      * the restrictions included in RFC 3280). IPv4 address names are
   1201      * supplied using dotted quad notation. OID address names are represented
   1202      * as a series of nonnegative integers separated by periods. And
   1203      * directory names (distinguished names) are supplied in RFC 2253 format.
   1204      * No standard string format is defined for otherNames, X.400 names,
   1205      * EDI party names, IPv6 address names, or any other type of names. They
   1206      * should be specified using the
   1207      * {@link #addPathToName(int type, byte [] name)
   1208      * addPathToName(int type, byte [] name)} method.
   1209      * <p>
   1210      * <strong>Note:</strong> for distinguished names, use
   1211      * {@linkplain #addPathToName(int, byte[])} instead.
   1212      * This method should not be relied on as it can fail to match some
   1213      * certificates because of a loss of encoding information in the RFC 2253
   1214      * String form of some distinguished names.
   1215      *
   1216      * @param type the name type (0-8, as specified in
   1217      *             RFC 3280, section 4.2.1.7)
   1218      * @param name the name in string form
   1219      * @throws IOException if a parsing error occurs
   1220      */
   1221     public void addPathToName(int type, String name) throws IOException {
   1222         addPathToNameInternal(type, name);
   1223     }
   1224 
   1225     /**
   1226      * Adds a name to the pathToNames criterion. The {@code X509Certificate}
   1227      * must not include name constraints that would prohibit building a
   1228      * path to the specified name.
   1229      * <p>
   1230      * This method allows the caller to add a name to the set of names which
   1231      * the {@code X509Certificates}'s name constraints must permit.
   1232      * The specified name is added to any previous value for the
   1233      * pathToNames criterion. If the name is a duplicate, it may be ignored.
   1234      * <p>
   1235      * The name is provided as a byte array. This byte array should contain
   1236      * the DER encoded name, as it would appear in the GeneralName structure
   1237      * defined in RFC 3280 and X.509. The ASN.1 definition of this structure
   1238      * appears in the documentation for
   1239      * {@link #addSubjectAlternativeName(int type, byte [] name)
   1240      * addSubjectAlternativeName(int type, byte [] name)}.
   1241      * <p>
   1242      * Note that the byte array supplied here is cloned to protect against
   1243      * subsequent modifications.
   1244      *
   1245      * @param type the name type (0-8, as specified in
   1246      *             RFC 3280, section 4.2.1.7)
   1247      * @param name a byte array containing the name in ASN.1 DER encoded form
   1248      * @throws IOException if a parsing error occurs
   1249      */
   1250     public void addPathToName(int type, byte [] name) throws IOException {
   1251         // clone because byte arrays are modifiable
   1252         addPathToNameInternal(type, name.clone());
   1253     }
   1254 
   1255     /**
   1256      * A private method that adds a name (String or byte array) to the
   1257      * pathToNames criterion. The {@code X509Certificate} must contain
   1258      * the specified pathToName.
   1259      *
   1260      * @param type the name type (0-8, as specified in
   1261      *             RFC 3280, section 4.2.1.7)
   1262      * @param name the name in string or byte array form
   1263      * @throws IOException if an encoding error occurs (incorrect form for DN)
   1264      */
   1265     private void addPathToNameInternal(int type, Object name)
   1266             throws IOException {
   1267         // First, ensure that the name parses
   1268         GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
   1269         if (pathToGeneralNames == null) {
   1270             pathToNames = new HashSet<List<?>>();
   1271             pathToGeneralNames = new HashSet<GeneralNameInterface>();
   1272         }
   1273         List<Object> list = new ArrayList<Object>(2);
   1274         list.add(Integer.valueOf(type));
   1275         list.add(name);
   1276         pathToNames.add(list);
   1277         pathToGeneralNames.add(tempName);
   1278     }
   1279 
   1280     /**
   1281      * Returns the certificateEquals criterion. The specified
   1282      * {@code X509Certificate} must be equal to the
   1283      * {@code X509Certificate} passed to the {@code match} method.
   1284      * If {@code null}, this check is not applied.
   1285      *
   1286      * @return the {@code X509Certificate} to match (or {@code null})
   1287      * @see #setCertificate
   1288      */
   1289     public X509Certificate getCertificate() {
   1290         return x509Cert;
   1291     }
   1292 
   1293     /**
   1294      * Returns the serialNumber criterion. The specified serial number
   1295      * must match the certificate serial number in the
   1296      * {@code X509Certificate}. If {@code null}, any certificate
   1297      * serial number will do.
   1298      *
   1299      * @return the certificate serial number to match
   1300      *                (or {@code null})
   1301      * @see #setSerialNumber
   1302      */
   1303     public BigInteger getSerialNumber() {
   1304         return serialNumber;
   1305     }
   1306 
   1307     /**
   1308      * Returns the issuer criterion as an {@code X500Principal}. This
   1309      * distinguished name must match the issuer distinguished name in the
   1310      * {@code X509Certificate}. If {@code null}, the issuer criterion
   1311      * is disabled and any issuer distinguished name will do.
   1312      *
   1313      * @return the required issuer distinguished name as X500Principal
   1314      *         (or {@code null})
   1315      * @since 1.5
   1316      */
   1317     public X500Principal getIssuer() {
   1318         return issuer;
   1319     }
   1320 
   1321     /**
   1322      * <strong>Denigrated</strong>, use {@linkplain #getIssuer()} or
   1323      * {@linkplain #getIssuerAsBytes()} instead. This method should not be
   1324      * relied on as it can fail to match some certificates because of a loss of
   1325      * encoding information in the RFC 2253 String form of some distinguished
   1326      * names.
   1327      * <p>
   1328      * Returns the issuer criterion as a {@code String}. This
   1329      * distinguished name must match the issuer distinguished name in the
   1330      * {@code X509Certificate}. If {@code null}, the issuer criterion
   1331      * is disabled and any issuer distinguished name will do.
   1332      * <p>
   1333      * If the value returned is not {@code null}, it is a
   1334      * distinguished name, in RFC 2253 format.
   1335      *
   1336      * @return the required issuer distinguished name in RFC 2253 format
   1337      *         (or {@code null})
   1338      */
   1339     public String getIssuerAsString() {
   1340         return (issuer == null ? null : issuer.getName());
   1341     }
   1342 
   1343     /**
   1344      * Returns the issuer criterion as a byte array. This distinguished name
   1345      * must match the issuer distinguished name in the
   1346      * {@code X509Certificate}. If {@code null}, the issuer criterion
   1347      * is disabled and any issuer distinguished name will do.
   1348      * <p>
   1349      * If the value returned is not {@code null}, it is a byte
   1350      * array containing a single DER encoded distinguished name, as defined in
   1351      * X.501. The ASN.1 notation for this structure is supplied in the
   1352      * documentation for
   1353      * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
   1354      * <p>
   1355      * Note that the byte array returned is cloned to protect against
   1356      * subsequent modifications.
   1357      *
   1358      * @return a byte array containing the required issuer distinguished name
   1359      *         in ASN.1 DER format (or {@code null})
   1360      * @throws IOException if an encoding error occurs
   1361      */
   1362     public byte[] getIssuerAsBytes() throws IOException {
   1363         return (issuer == null ? null: issuer.getEncoded());
   1364     }
   1365 
   1366     /**
   1367      * Returns the subject criterion as an {@code X500Principal}. This
   1368      * distinguished name must match the subject distinguished name in the
   1369      * {@code X509Certificate}. If {@code null}, the subject criterion
   1370      * is disabled and any subject distinguished name will do.
   1371      *
   1372      * @return the required subject distinguished name as X500Principal
   1373      *         (or {@code null})
   1374      * @since 1.5
   1375      */
   1376     public X500Principal getSubject() {
   1377         return subject;
   1378     }
   1379 
   1380     /**
   1381      * <strong>Denigrated</strong>, use {@linkplain #getSubject()} or
   1382      * {@linkplain #getSubjectAsBytes()} instead. This method should not be
   1383      * relied on as it can fail to match some certificates because of a loss of
   1384      * encoding information in the RFC 2253 String form of some distinguished
   1385      * names.
   1386      * <p>
   1387      * Returns the subject criterion as a {@code String}. This
   1388      * distinguished name must match the subject distinguished name in the
   1389      * {@code X509Certificate}. If {@code null}, the subject criterion
   1390      * is disabled and any subject distinguished name will do.
   1391      * <p>
   1392      * If the value returned is not {@code null}, it is a
   1393      * distinguished name, in RFC 2253 format.
   1394      *
   1395      * @return the required subject distinguished name in RFC 2253 format
   1396      *         (or {@code null})
   1397      */
   1398     public String getSubjectAsString() {
   1399         return (subject == null ? null : subject.getName());
   1400     }
   1401 
   1402     /**
   1403      * Returns the subject criterion as a byte array. This distinguished name
   1404      * must match the subject distinguished name in the
   1405      * {@code X509Certificate}. If {@code null}, the subject criterion
   1406      * is disabled and any subject distinguished name will do.
   1407      * <p>
   1408      * If the value returned is not {@code null}, it is a byte
   1409      * array containing a single DER encoded distinguished name, as defined in
   1410      * X.501. The ASN.1 notation for this structure is supplied in the
   1411      * documentation for
   1412      * {@link #setSubject(byte [] subjectDN) setSubject(byte [] subjectDN)}.
   1413      * <p>
   1414      * Note that the byte array returned is cloned to protect against
   1415      * subsequent modifications.
   1416      *
   1417      * @return a byte array containing the required subject distinguished name
   1418      *         in ASN.1 DER format (or {@code null})
   1419      * @throws IOException if an encoding error occurs
   1420      */
   1421     public byte[] getSubjectAsBytes() throws IOException {
   1422         return (subject == null ? null : subject.getEncoded());
   1423     }
   1424 
   1425     /**
   1426      * Returns the subjectKeyIdentifier criterion. The
   1427      * {@code X509Certificate} must contain a SubjectKeyIdentifier
   1428      * extension with the specified value. If {@code null}, no
   1429      * subjectKeyIdentifier check will be done.
   1430      * <p>
   1431      * Note that the byte array returned is cloned to protect against
   1432      * subsequent modifications.
   1433      *
   1434      * @return the key identifier (or {@code null})
   1435      * @see #setSubjectKeyIdentifier
   1436      */
   1437     public byte[] getSubjectKeyIdentifier() {
   1438         if (subjectKeyID == null) {
   1439             return null;
   1440         }
   1441         return subjectKeyID.clone();
   1442     }
   1443 
   1444     /**
   1445      * Returns the authorityKeyIdentifier criterion. The
   1446      * {@code X509Certificate} must contain a AuthorityKeyIdentifier
   1447      * extension with the specified value. If {@code null}, no
   1448      * authorityKeyIdentifier check will be done.
   1449      * <p>
   1450      * Note that the byte array returned is cloned to protect against
   1451      * subsequent modifications.
   1452      *
   1453      * @return the key identifier (or {@code null})
   1454      * @see #setAuthorityKeyIdentifier
   1455      */
   1456     public byte[] getAuthorityKeyIdentifier() {
   1457         if (authorityKeyID == null) {
   1458           return null;
   1459         }
   1460         return authorityKeyID.clone();
   1461     }
   1462 
   1463     /**
   1464      * Returns the certificateValid criterion. The specified date must fall
   1465      * within the certificate validity period for the
   1466      * {@code X509Certificate}. If {@code null}, no certificateValid
   1467      * check will be done.
   1468      * <p>
   1469      * Note that the {@code Date} returned is cloned to protect against
   1470      * subsequent modifications.
   1471      *
   1472      * @return the {@code Date} to check (or {@code null})
   1473      * @see #setCertificateValid
   1474      */
   1475     public Date getCertificateValid() {
   1476         if (certificateValid == null) {
   1477             return null;
   1478         }
   1479         return (Date)certificateValid.clone();
   1480     }
   1481 
   1482     /**
   1483      * Returns the privateKeyValid criterion. The specified date must fall
   1484      * within the private key validity period for the
   1485      * {@code X509Certificate}. If {@code null}, no privateKeyValid
   1486      * check will be done.
   1487      * <p>
   1488      * Note that the {@code Date} returned is cloned to protect against
   1489      * subsequent modifications.
   1490      *
   1491      * @return the {@code Date} to check (or {@code null})
   1492      * @see #setPrivateKeyValid
   1493      */
   1494     public Date getPrivateKeyValid() {
   1495         if (privateKeyValid == null) {
   1496             return null;
   1497         }
   1498         return (Date)privateKeyValid.clone();
   1499     }
   1500 
   1501     /**
   1502      * Returns the subjectPublicKeyAlgID criterion. The
   1503      * {@code X509Certificate} must contain a subject public key
   1504      * with the specified algorithm. If {@code null}, no
   1505      * subjectPublicKeyAlgID check will be done.
   1506      *
   1507      * @return the object identifier (OID) of the signature algorithm to check
   1508      *         for (or {@code null}). An OID is represented by a set of
   1509      *         nonnegative integers separated by periods.
   1510      * @see #setSubjectPublicKeyAlgID
   1511      */
   1512     public String getSubjectPublicKeyAlgID() {
   1513         if (subjectPublicKeyAlgID == null) {
   1514             return null;
   1515         }
   1516         return subjectPublicKeyAlgID.toString();
   1517     }
   1518 
   1519     /**
   1520      * Returns the subjectPublicKey criterion. The
   1521      * {@code X509Certificate} must contain the specified subject
   1522      * public key. If {@code null}, no subjectPublicKey check will be done.
   1523      *
   1524      * @return the subject public key to check for (or {@code null})
   1525      * @see #setSubjectPublicKey
   1526      */
   1527     public PublicKey getSubjectPublicKey() {
   1528         return subjectPublicKey;
   1529     }
   1530 
   1531     /**
   1532      * Returns the keyUsage criterion. The {@code X509Certificate}
   1533      * must allow the specified keyUsage values. If null, no keyUsage
   1534      * check will be done.
   1535      * <p>
   1536      * Note that the boolean array returned is cloned to protect against
   1537      * subsequent modifications.
   1538      *
   1539      * @return a boolean array in the same format as the boolean
   1540      *                 array returned by
   1541      * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
   1542      *                 Or {@code null}.
   1543      * @see #setKeyUsage
   1544      */
   1545     public boolean[] getKeyUsage() {
   1546         if (keyUsage == null) {
   1547             return null;
   1548         }
   1549         return keyUsage.clone();
   1550     }
   1551 
   1552     /**
   1553      * Returns the extendedKeyUsage criterion. The {@code X509Certificate}
   1554      * must allow the specified key purposes in its extended key usage
   1555      * extension. If the {@code keyPurposeSet} returned is empty or
   1556      * {@code null}, no extendedKeyUsage check will be done. Note that an
   1557      * {@code X509Certificate} that has no extendedKeyUsage extension
   1558      * implicitly allows all key purposes.
   1559      *
   1560      * @return an immutable {@code Set} of key purpose OIDs in string
   1561      * format (or {@code null})
   1562      * @see #setExtendedKeyUsage
   1563      */
   1564     public Set<String> getExtendedKeyUsage() {
   1565         return keyPurposeSet;
   1566     }
   1567 
   1568     /**
   1569      * Indicates if the {@code X509Certificate} must contain all
   1570      * or at least one of the subjectAlternativeNames
   1571      * specified in the {@link #setSubjectAlternativeNames
   1572      * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
   1573      * addSubjectAlternativeName} methods. If {@code true},
   1574      * the {@code X509Certificate} must contain all of the
   1575      * specified subject alternative names. If {@code false}, the
   1576      * {@code X509Certificate} must contain at least one of the
   1577      * specified subject alternative names.
   1578      *
   1579      * @return {@code true} if the flag is enabled;
   1580      * {@code false} if the flag is disabled. The flag is
   1581      * {@code true} by default.
   1582      * @see #setMatchAllSubjectAltNames
   1583      */
   1584     public boolean getMatchAllSubjectAltNames() {
   1585         return matchAllSubjectAltNames;
   1586     }
   1587 
   1588     /**
   1589      * Returns a copy of the subjectAlternativeNames criterion.
   1590      * The {@code X509Certificate} must contain all or at least one
   1591      * of the specified subjectAlternativeNames, depending on the value
   1592      * of the matchAllNames flag (see {@link #getMatchAllSubjectAltNames
   1593      * getMatchAllSubjectAltNames}). If the value returned is
   1594      * {@code null}, no subjectAlternativeNames check will be performed.
   1595      * <p>
   1596      * If the value returned is not {@code null}, it is a
   1597      * {@code Collection} with
   1598      * one entry for each name to be included in the subject alternative name
   1599      * criterion. Each entry is a {@code List} whose first entry is an
   1600      * {@code Integer} (the name type, 0-8) and whose second
   1601      * entry is a {@code String} or a byte array (the name, in
   1602      * string or ASN.1 DER encoded form, respectively).
   1603      * There can be multiple names of the same type.  Note that the
   1604      * {@code Collection} returned may contain duplicate names (same name
   1605      * and name type).
   1606      * <p>
   1607      * Each subject alternative name in the {@code Collection}
   1608      * may be specified either as a {@code String} or as an ASN.1 encoded
   1609      * byte array. For more details about the formats used, see
   1610      * {@link #addSubjectAlternativeName(int type, String name)
   1611      * addSubjectAlternativeName(int type, String name)} and
   1612      * {@link #addSubjectAlternativeName(int type, byte [] name)
   1613      * addSubjectAlternativeName(int type, byte [] name)}.
   1614      * <p>
   1615      * Note that a deep copy is performed on the {@code Collection} to
   1616      * protect against subsequent modifications.
   1617      *
   1618      * @return a {@code Collection} of names (or {@code null})
   1619      * @see #setSubjectAlternativeNames
   1620      */
   1621     public Collection<List<?>> getSubjectAlternativeNames() {
   1622         if (subjectAlternativeNames == null) {
   1623             return null;
   1624         }
   1625         return cloneNames(subjectAlternativeNames);
   1626     }
   1627 
   1628     /**
   1629      * Clone an object of the form passed to
   1630      * setSubjectAlternativeNames and setPathToNames.
   1631      * Throw a {@code RuntimeException} if the argument is malformed.
   1632      * <p>
   1633      * This method wraps cloneAndCheckNames, changing any
   1634      * {@code IOException} into a {@code RuntimeException}. This
   1635      * method should be used when the object being
   1636      * cloned has already been checked, so there should never be any exceptions.
   1637      *
   1638      * @param names a {@code Collection} with one entry per name.
   1639      *              Each entry is a {@code List} whose first entry
   1640      *              is an Integer (the name type, 0-8) and whose second
   1641      *              entry is a String or a byte array (the name, in
   1642      *              string or ASN.1 DER encoded form, respectively).
   1643      *              There can be multiple names of the same type. Null
   1644      *              is not an acceptable value.
   1645      * @return a deep copy of the specified {@code Collection}
   1646      * @throws RuntimeException if a parsing error occurs
   1647      */
   1648     private static Set<List<?>> cloneNames(Collection<List<?>> names) {
   1649         try {
   1650             return cloneAndCheckNames(names);
   1651         } catch (IOException e) {
   1652             throw new RuntimeException("cloneNames encountered IOException: " +
   1653                                        e.getMessage());
   1654         }
   1655     }
   1656 
   1657     /**
   1658      * Clone and check an argument of the form passed to
   1659      * setSubjectAlternativeNames and setPathToNames.
   1660      * Throw an {@code IOException} if the argument is malformed.
   1661      *
   1662      * @param names a {@code Collection} with one entry per name.
   1663      *              Each entry is a {@code List} whose first entry
   1664      *              is an Integer (the name type, 0-8) and whose second
   1665      *              entry is a String or a byte array (the name, in
   1666      *              string or ASN.1 DER encoded form, respectively).
   1667      *              There can be multiple names of the same type.
   1668      *              {@code null} is not an acceptable value.
   1669      * @return a deep copy of the specified {@code Collection}
   1670      * @throws IOException if a parsing error occurs
   1671      */
   1672     private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException {
   1673         // Copy the Lists and Collection
   1674         Set<List<?>> namesCopy = new HashSet<List<?>>();
   1675         for (List<?> o : names)
   1676         {
   1677             namesCopy.add(new ArrayList<Object>(o));
   1678         }
   1679 
   1680         // Check the contents of the Lists and clone any byte arrays
   1681         for (List<?> list : namesCopy) {
   1682             @SuppressWarnings("unchecked") // See javadoc for parameter "names".
   1683             List<Object> nameList = (List<Object>)list;
   1684             if (nameList.size() != 2) {
   1685                 throw new IOException("name list size not 2");
   1686             }
   1687             Object o = nameList.get(0);
   1688             if (!(o instanceof Integer)) {
   1689                 throw new IOException("expected an Integer");
   1690             }
   1691             int nameType = ((Integer)o).intValue();
   1692             if ((nameType < 0) || (nameType > 8)) {
   1693                 throw new IOException("name type not 0-8");
   1694             }
   1695             Object nameObject = nameList.get(1);
   1696             if (!(nameObject instanceof byte[]) &&
   1697                 !(nameObject instanceof String)) {
   1698                 if (debug != null) {
   1699                     debug.println("X509CertSelector.cloneAndCheckNames() "
   1700                         + "name not byte array");
   1701                 }
   1702                 throw new IOException("name not byte array or String");
   1703             }
   1704             if (nameObject instanceof byte[]) {
   1705                 nameList.set(1, ((byte[]) nameObject).clone());
   1706             }
   1707         }
   1708         return namesCopy;
   1709     }
   1710 
   1711     /**
   1712      * Returns the name constraints criterion. The {@code X509Certificate}
   1713      * must have subject and subject alternative names that
   1714      * meet the specified name constraints.
   1715      * <p>
   1716      * The name constraints are returned as a byte array. This byte array
   1717      * contains the DER encoded form of the name constraints, as they
   1718      * would appear in the NameConstraints structure defined in RFC 3280
   1719      * and X.509. The ASN.1 notation for this structure is supplied in the
   1720      * documentation for
   1721      * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.
   1722      * <p>
   1723      * Note that the byte array returned is cloned to protect against
   1724      * subsequent modifications.
   1725      *
   1726      * @return a byte array containing the ASN.1 DER encoding of
   1727      *         a NameConstraints extension used for checking name constraints.
   1728      *         {@code null} if no name constraints check will be performed.
   1729      * @see #setNameConstraints
   1730      */
   1731     public byte[] getNameConstraints() {
   1732         if (ncBytes == null) {
   1733             return null;
   1734         } else {
   1735             return ncBytes.clone();
   1736         }
   1737     }
   1738 
   1739     /**
   1740      * Returns the basic constraints constraint. If the value is greater than
   1741      * or equal to zero, the {@code X509Certificates} must include a
   1742      * basicConstraints extension with a pathLen of at least this value.
   1743      * If the value is -2, only end-entity certificates are accepted. If
   1744      * the value is -1, no basicConstraints check is done.
   1745      *
   1746      * @return the value for the basic constraints constraint
   1747      * @see #setBasicConstraints
   1748      */
   1749     public int getBasicConstraints() {
   1750         return basicConstraints;
   1751     }
   1752 
   1753     /**
   1754      * Returns the policy criterion. The {@code X509Certificate} must
   1755      * include at least one of the specified policies in its certificate policies
   1756      * extension. If the {@code Set} returned is empty, then the
   1757      * {@code X509Certificate} must include at least some specified policy
   1758      * in its certificate policies extension. If the {@code Set} returned is
   1759      * {@code null}, no policy check will be performed.
   1760      *
   1761      * @return an immutable {@code Set} of certificate policy OIDs in
   1762      *         string format (or {@code null})
   1763      * @see #setPolicy
   1764      */
   1765     public Set<String> getPolicy() {
   1766         return policySet;
   1767     }
   1768 
   1769     /**
   1770      * Returns a copy of the pathToNames criterion. The
   1771      * {@code X509Certificate} must not include name constraints that would
   1772      * prohibit building a path to the specified names. If the value
   1773      * returned is {@code null}, no pathToNames check will be performed.
   1774      * <p>
   1775      * If the value returned is not {@code null}, it is a
   1776      * {@code Collection} with one
   1777      * entry for each name to be included in the pathToNames
   1778      * criterion. Each entry is a {@code List} whose first entry is an
   1779      * {@code Integer} (the name type, 0-8) and whose second
   1780      * entry is a {@code String} or a byte array (the name, in
   1781      * string or ASN.1 DER encoded form, respectively).
   1782      * There can be multiple names of the same type. Note that the
   1783      * {@code Collection} returned may contain duplicate names (same
   1784      * name and name type).
   1785      * <p>
   1786      * Each name in the {@code Collection}
   1787      * may be specified either as a {@code String} or as an ASN.1 encoded
   1788      * byte array. For more details about the formats used, see
   1789      * {@link #addPathToName(int type, String name)
   1790      * addPathToName(int type, String name)} and
   1791      * {@link #addPathToName(int type, byte [] name)
   1792      * addPathToName(int type, byte [] name)}.
   1793      * <p>
   1794      * Note that a deep copy is performed on the {@code Collection} to
   1795      * protect against subsequent modifications.
   1796      *
   1797      * @return a {@code Collection} of names (or {@code null})
   1798      * @see #setPathToNames
   1799      */
   1800     public Collection<List<?>> getPathToNames() {
   1801         if (pathToNames == null) {
   1802             return null;
   1803         }
   1804         return cloneNames(pathToNames);
   1805     }
   1806 
   1807     /**
   1808      * Return a printable representation of the {@code CertSelector}.
   1809      *
   1810      * @return a {@code String} describing the contents of the
   1811      *         {@code CertSelector}
   1812      */
   1813     public String toString() {
   1814         StringBuffer sb = new StringBuffer();
   1815         sb.append("X509CertSelector: [\n");
   1816         if (x509Cert != null) {
   1817             sb.append("  Certificate: " + x509Cert.toString() + "\n");
   1818         }
   1819         if (serialNumber != null) {
   1820             sb.append("  Serial Number: " + serialNumber.toString() + "\n");
   1821         }
   1822         if (issuer != null) {
   1823             sb.append("  Issuer: " + getIssuerAsString() + "\n");
   1824         }
   1825         if (subject != null) {
   1826             sb.append("  Subject: " + getSubjectAsString() + "\n");
   1827         }
   1828         sb.append("  matchAllSubjectAltNames flag: "
   1829                   + String.valueOf(matchAllSubjectAltNames) + "\n");
   1830         if (subjectAlternativeNames != null) {
   1831             sb.append("  SubjectAlternativeNames:\n");
   1832             Iterator<List<?>> i = subjectAlternativeNames.iterator();
   1833             while (i.hasNext()) {
   1834                 List<?> list = i.next();
   1835                 sb.append("    type " + list.get(0) +
   1836                           ", name " + list.get(1) + "\n");
   1837             }
   1838         }
   1839         if (subjectKeyID != null) {
   1840             HexDumpEncoder enc = new HexDumpEncoder();
   1841             sb.append("  Subject Key Identifier: " +
   1842                       enc.encodeBuffer(subjectKeyID) + "\n");
   1843         }
   1844         if (authorityKeyID != null) {
   1845             HexDumpEncoder enc = new HexDumpEncoder();
   1846             sb.append("  Authority Key Identifier: " +
   1847                       enc.encodeBuffer(authorityKeyID) + "\n");
   1848         }
   1849         if (certificateValid != null) {
   1850             sb.append("  Certificate Valid: " +
   1851                       certificateValid.toString() + "\n");
   1852         }
   1853         if (privateKeyValid != null) {
   1854             sb.append("  Private Key Valid: " +
   1855                       privateKeyValid.toString() + "\n");
   1856         }
   1857         if (subjectPublicKeyAlgID != null) {
   1858             sb.append("  Subject Public Key AlgID: " +
   1859                       subjectPublicKeyAlgID.toString() + "\n");
   1860         }
   1861         if (subjectPublicKey != null) {
   1862             sb.append("  Subject Public Key: " +
   1863                       subjectPublicKey.toString() + "\n");
   1864         }
   1865         if (keyUsage != null) {
   1866             sb.append("  Key Usage: " + keyUsageToString(keyUsage) + "\n");
   1867         }
   1868         if (keyPurposeSet != null) {
   1869             sb.append("  Extended Key Usage: " +
   1870                       keyPurposeSet.toString() + "\n");
   1871         }
   1872         if (policy != null) {
   1873             sb.append("  Policy: " + policy.toString() + "\n");
   1874         }
   1875         if (pathToGeneralNames != null) {
   1876             sb.append("  Path to names:\n");
   1877             Iterator<GeneralNameInterface> i = pathToGeneralNames.iterator();
   1878             while (i.hasNext()) {
   1879                 sb.append("    " + i.next() + "\n");
   1880             }
   1881         }
   1882         sb.append("]");
   1883         return sb.toString();
   1884     }
   1885 
   1886     // Copied from sun.security.x509.KeyUsageExtension
   1887     // (without calling the superclass)
   1888     /**
   1889      * Returns a printable representation of the KeyUsage.
   1890      */
   1891     private static String keyUsageToString(boolean[] k) {
   1892         String s = "KeyUsage [\n";
   1893         try {
   1894             if (k[0]) {
   1895                 s += "  DigitalSignature\n";
   1896             }
   1897             if (k[1]) {
   1898                 s += "  Non_repudiation\n";
   1899             }
   1900             if (k[2]) {
   1901                 s += "  Key_Encipherment\n";
   1902             }
   1903             if (k[3]) {
   1904                 s += "  Data_Encipherment\n";
   1905             }
   1906             if (k[4]) {
   1907                 s += "  Key_Agreement\n";
   1908             }
   1909             if (k[5]) {
   1910                 s += "  Key_CertSign\n";
   1911             }
   1912             if (k[6]) {
   1913                 s += "  Crl_Sign\n";
   1914             }
   1915             if (k[7]) {
   1916                 s += "  Encipher_Only\n";
   1917             }
   1918             if (k[8]) {
   1919                 s += "  Decipher_Only\n";
   1920             }
   1921         } catch (ArrayIndexOutOfBoundsException ex) {}
   1922 
   1923         s += "]\n";
   1924 
   1925         return (s);
   1926     }
   1927 
   1928     /**
   1929      * Returns an Extension object given any X509Certificate and extension oid.
   1930      * Throw an {@code IOException} if the extension byte value is
   1931      * malformed.
   1932      *
   1933      * @param cert a {@code X509Certificate}
   1934      * @param extId an {@code integer} which specifies the extension index.
   1935      * Currently, the supported extensions are as follows:
   1936      * index 0 - PrivateKeyUsageExtension
   1937      * index 1 - SubjectAlternativeNameExtension
   1938      * index 2 - NameConstraintsExtension
   1939      * index 3 - CertificatePoliciesExtension
   1940      * index 4 - ExtendedKeyUsageExtension
   1941      * @return an {@code Extension} object whose real type is as specified
   1942      * by the extension oid.
   1943      * @throws IOException if cannot construct the {@code Extension}
   1944      * object with the extension encoding retrieved from the passed in
   1945      * {@code X509Certificate}.
   1946      */
   1947     private static Extension getExtensionObject(X509Certificate cert, int extId)
   1948             throws IOException {
   1949         if (cert instanceof X509CertImpl) {
   1950             X509CertImpl impl = (X509CertImpl)cert;
   1951             switch (extId) {
   1952             case PRIVATE_KEY_USAGE_ID:
   1953                 return impl.getPrivateKeyUsageExtension();
   1954             case SUBJECT_ALT_NAME_ID:
   1955                 return impl.getSubjectAlternativeNameExtension();
   1956             case NAME_CONSTRAINTS_ID:
   1957                 return impl.getNameConstraintsExtension();
   1958             case CERT_POLICIES_ID:
   1959                 return impl.getCertificatePoliciesExtension();
   1960             case EXTENDED_KEY_USAGE_ID:
   1961                 return impl.getExtendedKeyUsageExtension();
   1962             default:
   1963                 return null;
   1964             }
   1965         }
   1966         byte[] rawExtVal = cert.getExtensionValue(EXTENSION_OIDS[extId]);
   1967         if (rawExtVal == null) {
   1968             return null;
   1969         }
   1970         DerInputStream in = new DerInputStream(rawExtVal);
   1971         byte[] encoded = in.getOctetString();
   1972         switch (extId) {
   1973         case PRIVATE_KEY_USAGE_ID:
   1974             try {
   1975                 return new PrivateKeyUsageExtension(FALSE, encoded);
   1976             } catch (CertificateException ex) {
   1977                 throw new IOException(ex.getMessage());
   1978             }
   1979         case SUBJECT_ALT_NAME_ID:
   1980             return new SubjectAlternativeNameExtension(FALSE, encoded);
   1981         case NAME_CONSTRAINTS_ID:
   1982             return new NameConstraintsExtension(FALSE, encoded);
   1983         case CERT_POLICIES_ID:
   1984             return new CertificatePoliciesExtension(FALSE, encoded);
   1985         case EXTENDED_KEY_USAGE_ID:
   1986             return new ExtendedKeyUsageExtension(FALSE, encoded);
   1987         default:
   1988             return null;
   1989         }
   1990     }
   1991 
   1992     /**
   1993      * Decides whether a {@code Certificate} should be selected.
   1994      *
   1995      * @param cert the {@code Certificate} to be checked
   1996      * @return {@code true} if the {@code Certificate} should be
   1997      *         selected, {@code false} otherwise
   1998      */
   1999     public boolean match(Certificate cert) {
   2000         if (!(cert instanceof X509Certificate)) {
   2001             return false;
   2002         }
   2003         X509Certificate xcert = (X509Certificate)cert;
   2004 
   2005         if (debug != null) {
   2006             debug.println("X509CertSelector.match(SN: "
   2007                 + (xcert.getSerialNumber()).toString(16) + "\n  Issuer: "
   2008                 + xcert.getIssuerDN() + "\n  Subject: " + xcert.getSubjectDN()
   2009                 + ")");
   2010         }
   2011 
   2012         /* match on X509Certificate */
   2013         if (x509Cert != null) {
   2014             if (!x509Cert.equals(xcert)) {
   2015                 if (debug != null) {
   2016                     debug.println("X509CertSelector.match: "
   2017                         + "certs don't match");
   2018                 }
   2019                 return false;
   2020             }
   2021         }
   2022 
   2023         /* match on serial number */
   2024         if (serialNumber != null) {
   2025             if (!serialNumber.equals(xcert.getSerialNumber())) {
   2026                 if (debug != null) {
   2027                     debug.println("X509CertSelector.match: "
   2028                         + "serial numbers don't match");
   2029                 }
   2030                 return false;
   2031             }
   2032         }
   2033 
   2034         /* match on issuer name */
   2035         if (issuer != null) {
   2036             if (!issuer.equals(xcert.getIssuerX500Principal())) {
   2037                 if (debug != null) {
   2038                     debug.println("X509CertSelector.match: "
   2039                         + "issuer DNs don't match");
   2040                 }
   2041                 return false;
   2042             }
   2043         }
   2044 
   2045         /* match on subject name */
   2046         if (subject != null) {
   2047             if (!subject.equals(xcert.getSubjectX500Principal())) {
   2048                 if (debug != null) {
   2049                     debug.println("X509CertSelector.match: "
   2050                         + "subject DNs don't match");
   2051                 }
   2052                 return false;
   2053             }
   2054         }
   2055 
   2056         /* match on certificate validity range */
   2057         if (certificateValid != null) {
   2058             try {
   2059                 xcert.checkValidity(certificateValid);
   2060             } catch (CertificateException e) {
   2061                 if (debug != null) {
   2062                     debug.println("X509CertSelector.match: "
   2063                         + "certificate not within validity period");
   2064                 }
   2065                 return false;
   2066             }
   2067         }
   2068 
   2069         /* match on subject public key */
   2070         if (subjectPublicKeyBytes != null) {
   2071             byte[] certKey = xcert.getPublicKey().getEncoded();
   2072             if (!Arrays.equals(subjectPublicKeyBytes, certKey)) {
   2073                 if (debug != null) {
   2074                     debug.println("X509CertSelector.match: "
   2075                         + "subject public keys don't match");
   2076                 }
   2077                 return false;
   2078             }
   2079         }
   2080 
   2081         boolean result = matchBasicConstraints(xcert)
   2082                       && matchKeyUsage(xcert)
   2083                       && matchExtendedKeyUsage(xcert)
   2084                       && matchSubjectKeyID(xcert)
   2085                       && matchAuthorityKeyID(xcert)
   2086                       && matchPrivateKeyValid(xcert)
   2087                       && matchSubjectPublicKeyAlgID(xcert)
   2088                       && matchPolicy(xcert)
   2089                       && matchSubjectAlternativeNames(xcert)
   2090                       && matchPathToNames(xcert)
   2091                       && matchNameConstraints(xcert);
   2092 
   2093         if (result && (debug != null)) {
   2094             debug.println("X509CertSelector.match returning: true");
   2095         }
   2096         return result;
   2097     }
   2098 
   2099     /* match on subject key identifier extension value */
   2100     private boolean matchSubjectKeyID(X509Certificate xcert) {
   2101         if (subjectKeyID == null) {
   2102             return true;
   2103         }
   2104         try {
   2105             byte[] extVal = xcert.getExtensionValue("2.5.29.14");
   2106             if (extVal == null) {
   2107                 if (debug != null) {
   2108                     debug.println("X509CertSelector.match: "
   2109                         + "no subject key ID extension");
   2110                 }
   2111                 return false;
   2112             }
   2113             DerInputStream in = new DerInputStream(extVal);
   2114             byte[] certSubjectKeyID = in.getOctetString();
   2115             if (certSubjectKeyID == null ||
   2116                     !Arrays.equals(subjectKeyID, certSubjectKeyID)) {
   2117                 if (debug != null) {
   2118                     debug.println("X509CertSelector.match: "
   2119                         + "subject key IDs don't match");
   2120                 }
   2121                 return false;
   2122             }
   2123         } catch (IOException ex) {
   2124             if (debug != null) {
   2125                 debug.println("X509CertSelector.match: "
   2126                     + "exception in subject key ID check");
   2127             }
   2128             return false;
   2129         }
   2130         return true;
   2131     }
   2132 
   2133     /* match on authority key identifier extension value */
   2134     private boolean matchAuthorityKeyID(X509Certificate xcert) {
   2135         if (authorityKeyID == null) {
   2136             return true;
   2137         }
   2138         try {
   2139             byte[] extVal = xcert.getExtensionValue("2.5.29.35");
   2140             if (extVal == null) {
   2141                 if (debug != null) {
   2142                     debug.println("X509CertSelector.match: "
   2143                         + "no authority key ID extension");
   2144                 }
   2145                 return false;
   2146             }
   2147             DerInputStream in = new DerInputStream(extVal);
   2148             byte[] certAuthKeyID = in.getOctetString();
   2149             if (certAuthKeyID == null ||
   2150                     !Arrays.equals(authorityKeyID, certAuthKeyID)) {
   2151                 if (debug != null) {
   2152                     debug.println("X509CertSelector.match: "
   2153                         + "authority key IDs don't match");
   2154                 }
   2155                 return false;
   2156             }
   2157         } catch (IOException ex) {
   2158             if (debug != null) {
   2159                 debug.println("X509CertSelector.match: "
   2160                     + "exception in authority key ID check");
   2161             }
   2162             return false;
   2163         }
   2164         return true;
   2165     }
   2166 
   2167     /* match on private key usage range */
   2168     private boolean matchPrivateKeyValid(X509Certificate xcert) {
   2169         if (privateKeyValid == null) {
   2170             return true;
   2171         }
   2172         PrivateKeyUsageExtension ext = null;
   2173         try {
   2174             ext = (PrivateKeyUsageExtension)
   2175                 getExtensionObject(xcert, PRIVATE_KEY_USAGE_ID);
   2176             if (ext != null) {
   2177                 ext.valid(privateKeyValid);
   2178             }
   2179         } catch (CertificateExpiredException e1) {
   2180             if (debug != null) {
   2181                 String time = "n/a";
   2182                 try {
   2183                     Date notAfter = ext.get(PrivateKeyUsageExtension.NOT_AFTER);
   2184                     time = notAfter.toString();
   2185                 } catch (CertificateException ex) {
   2186                     // not able to retrieve notAfter value
   2187                 }
   2188                 debug.println("X509CertSelector.match: private key usage not "
   2189                     + "within validity date; ext.NOT_After: "
   2190                     + time + "; X509CertSelector: "
   2191                     + this.toString());
   2192                 e1.printStackTrace();
   2193             }
   2194             return false;
   2195         } catch (CertificateNotYetValidException e2) {
   2196             if (debug != null) {
   2197                 String time = "n/a";
   2198                 try {
   2199                     Date notBefore = ext.get(PrivateKeyUsageExtension.NOT_BEFORE);
   2200                     time = notBefore.toString();
   2201                 } catch (CertificateException ex) {
   2202                     // not able to retrieve notBefore value
   2203                 }
   2204                 debug.println("X509CertSelector.match: private key usage not "
   2205                     + "within validity date; ext.NOT_BEFORE: "
   2206                     + time + "; X509CertSelector: "
   2207                     + this.toString());
   2208                 e2.printStackTrace();
   2209             }
   2210             return false;
   2211         } catch (IOException e4) {
   2212             if (debug != null) {
   2213                 debug.println("X509CertSelector.match: IOException in "
   2214                     + "private key usage check; X509CertSelector: "
   2215                     + this.toString());
   2216                 e4.printStackTrace();
   2217             }
   2218             return false;
   2219         }
   2220         return true;
   2221     }
   2222 
   2223     /* match on subject public key algorithm OID */
   2224     private boolean matchSubjectPublicKeyAlgID(X509Certificate xcert) {
   2225         if (subjectPublicKeyAlgID == null) {
   2226             return true;
   2227         }
   2228         try {
   2229             byte[] encodedKey = xcert.getPublicKey().getEncoded();
   2230             DerValue val = new DerValue(encodedKey);
   2231             if (val.tag != DerValue.tag_Sequence) {
   2232                 throw new IOException("invalid key format");
   2233             }
   2234 
   2235             AlgorithmId algID = AlgorithmId.parse(val.data.getDerValue());
   2236             if (debug != null) {
   2237                 debug.println("X509CertSelector.match: subjectPublicKeyAlgID = "
   2238                     + subjectPublicKeyAlgID + ", xcert subjectPublicKeyAlgID = "
   2239                     + algID.getOID());
   2240             }
   2241             if (!subjectPublicKeyAlgID.equals((Object)algID.getOID())) {
   2242                 if (debug != null) {
   2243                     debug.println("X509CertSelector.match: "
   2244                         + "subject public key alg IDs don't match");
   2245                 }
   2246                 return false;
   2247             }
   2248         } catch (IOException e5) {
   2249             if (debug != null) {
   2250                 debug.println("X509CertSelector.match: IOException in subject "
   2251                     + "public key algorithm OID check");
   2252             }
   2253             return false;
   2254         }
   2255         return true;
   2256     }
   2257 
   2258     /* match on key usage extension value */
   2259     private boolean matchKeyUsage(X509Certificate xcert) {
   2260         if (keyUsage == null) {
   2261             return true;
   2262         }
   2263         boolean[] certKeyUsage = xcert.getKeyUsage();
   2264         if (certKeyUsage != null) {
   2265             for (int keyBit = 0; keyBit < keyUsage.length; keyBit++) {
   2266                 if (keyUsage[keyBit] &&
   2267                     ((keyBit >= certKeyUsage.length) || !certKeyUsage[keyBit])) {
   2268                     if (debug != null) {
   2269                         debug.println("X509CertSelector.match: "
   2270                             + "key usage bits don't match");
   2271                     }
   2272                     return false;
   2273                 }
   2274             }
   2275         }
   2276         return true;
   2277     }
   2278 
   2279     /* match on extended key usage purpose OIDs */
   2280     private boolean matchExtendedKeyUsage(X509Certificate xcert) {
   2281         if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
   2282             return true;
   2283         }
   2284         try {
   2285             ExtendedKeyUsageExtension ext =
   2286                 (ExtendedKeyUsageExtension)getExtensionObject(xcert,
   2287                                                 EXTENDED_KEY_USAGE_ID);
   2288             if (ext != null) {
   2289                 Vector<ObjectIdentifier> certKeyPurposeVector =
   2290                     ext.get(ExtendedKeyUsageExtension.USAGES);
   2291                 if (!certKeyPurposeVector.contains(ANY_EXTENDED_KEY_USAGE)
   2292                         && !certKeyPurposeVector.containsAll(keyPurposeOIDSet)) {
   2293                     if (debug != null) {
   2294                         debug.println("X509CertSelector.match: cert failed "
   2295                             + "extendedKeyUsage criterion");
   2296                     }
   2297                     return false;
   2298                 }
   2299             }
   2300         } catch (IOException ex) {
   2301             if (debug != null) {
   2302                 debug.println("X509CertSelector.match: "
   2303                     + "IOException in extended key usage check");
   2304             }
   2305             return false;
   2306         }
   2307         return true;
   2308     }
   2309 
   2310     /* match on subject alternative name extension names */
   2311     private boolean matchSubjectAlternativeNames(X509Certificate xcert) {
   2312         if ((subjectAlternativeNames == null) || subjectAlternativeNames.isEmpty()) {
   2313             return true;
   2314         }
   2315         try {
   2316             SubjectAlternativeNameExtension sanExt =
   2317                 (SubjectAlternativeNameExtension) getExtensionObject(xcert,
   2318                                                       SUBJECT_ALT_NAME_ID);
   2319             if (sanExt == null) {
   2320                 if (debug != null) {
   2321                   debug.println("X509CertSelector.match: "
   2322                       + "no subject alternative name extension");
   2323                 }
   2324                 return false;
   2325             }
   2326             GeneralNames certNames =
   2327                     sanExt.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
   2328             Iterator<GeneralNameInterface> i =
   2329                                 subjectAlternativeGeneralNames.iterator();
   2330             while (i.hasNext()) {
   2331                 GeneralNameInterface matchName = i.next();
   2332                 boolean found = false;
   2333                 for (Iterator<GeneralName> t = certNames.iterator();
   2334                                                 t.hasNext() && !found; ) {
   2335                     GeneralNameInterface certName = (t.next()).getName();
   2336                     found = certName.equals(matchName);
   2337                 }
   2338                 if (!found && (matchAllSubjectAltNames || !i.hasNext())) {
   2339                     if (debug != null) {
   2340                       debug.println("X509CertSelector.match: subject alternative "
   2341                           + "name " + matchName + " not found");
   2342                     }
   2343                     return false;
   2344                 } else if (found && !matchAllSubjectAltNames) {
   2345                     break;
   2346                 }
   2347             }
   2348         } catch (IOException ex) {
   2349             if (debug != null)
   2350                 debug.println("X509CertSelector.match: IOException in subject "
   2351                     + "alternative name check");
   2352             return false;
   2353         }
   2354         return true;
   2355     }
   2356 
   2357     /* match on name constraints */
   2358     private boolean matchNameConstraints(X509Certificate xcert) {
   2359         if (nc == null) {
   2360             return true;
   2361         }
   2362         try {
   2363             if (!nc.verify(xcert)) {
   2364                 if (debug != null) {
   2365                     debug.println("X509CertSelector.match: "
   2366                         + "name constraints not satisfied");
   2367                 }
   2368                 return false;
   2369             }
   2370         } catch (IOException e) {
   2371             if (debug != null) {
   2372                 debug.println("X509CertSelector.match: "
   2373                     + "IOException in name constraints check");
   2374             }
   2375             return false;
   2376         }
   2377         return true;
   2378     }
   2379 
   2380     /* match on policy OIDs */
   2381     private boolean matchPolicy(X509Certificate xcert) {
   2382         if (policy == null) {
   2383             return true;
   2384         }
   2385         try {
   2386             CertificatePoliciesExtension ext = (CertificatePoliciesExtension)
   2387                 getExtensionObject(xcert, CERT_POLICIES_ID);
   2388             if (ext == null) {
   2389                 if (debug != null) {
   2390                   debug.println("X509CertSelector.match: "
   2391                       + "no certificate policy extension");
   2392                 }
   2393                 return false;
   2394             }
   2395             List<PolicyInformation> policies = ext.get(CertificatePoliciesExtension.POLICIES);
   2396             /*
   2397              * Convert the Vector of PolicyInformation to a Vector
   2398              * of CertificatePolicyIds for easier comparison.
   2399              */
   2400             List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(policies.size());
   2401             for (PolicyInformation info : policies) {
   2402                 policyIDs.add(info.getPolicyIdentifier());
   2403             }
   2404             if (policy != null) {
   2405                 boolean foundOne = false;
   2406                 /*
   2407                  * if the user passes in an empty policy Set, then
   2408                  * we just want to make sure that the candidate certificate
   2409                  * has some policy OID in its CertPoliciesExtension
   2410                  */
   2411                 if (policy.getCertPolicyIds().isEmpty()) {
   2412                     if (policyIDs.isEmpty()) {
   2413                         if (debug != null) {
   2414                             debug.println("X509CertSelector.match: "
   2415                                 + "cert failed policyAny criterion");
   2416                         }
   2417                         return false;
   2418                     }
   2419                 } else {
   2420                     for (CertificatePolicyId id : policy.getCertPolicyIds()) {
   2421                         if (policyIDs.contains(id)) {
   2422                             foundOne = true;
   2423                             break;
   2424                         }
   2425                     }
   2426                     if (!foundOne) {
   2427                         if (debug != null) {
   2428                             debug.println("X509CertSelector.match: "
   2429                                 + "cert failed policyAny criterion");
   2430                         }
   2431                         return false;
   2432                     }
   2433                 }
   2434             }
   2435         } catch (IOException ex) {
   2436             if (debug != null) {
   2437                 debug.println("X509CertSelector.match: "
   2438                     + "IOException in certificate policy ID check");
   2439             }
   2440             return false;
   2441         }
   2442         return true;
   2443     }
   2444 
   2445     /* match on pathToNames */
   2446     private boolean matchPathToNames(X509Certificate xcert) {
   2447         if (pathToGeneralNames == null) {
   2448             return true;
   2449         }
   2450         try {
   2451             NameConstraintsExtension ext = (NameConstraintsExtension)
   2452                 getExtensionObject(xcert, NAME_CONSTRAINTS_ID);
   2453             if (ext == null) {
   2454                 return true;
   2455             }
   2456             if ((debug != null) && Debug.isOn("certpath")) {
   2457                 debug.println("X509CertSelector.match pathToNames:\n");
   2458                 Iterator<GeneralNameInterface> i =
   2459                                         pathToGeneralNames.iterator();
   2460                 while (i.hasNext()) {
   2461                     debug.println("    " + i.next() + "\n");
   2462                 }
   2463             }
   2464 
   2465             GeneralSubtrees permitted =
   2466                     ext.get(NameConstraintsExtension.PERMITTED_SUBTREES);
   2467             GeneralSubtrees excluded =
   2468                     ext.get(NameConstraintsExtension.EXCLUDED_SUBTREES);
   2469             if (excluded != null) {
   2470                 if (matchExcluded(excluded) == false) {
   2471                     return false;
   2472                 }
   2473             }
   2474             if (permitted != null) {
   2475                 if (matchPermitted(permitted) == false) {
   2476                     return false;
   2477                 }
   2478             }
   2479         } catch (IOException ex) {
   2480             if (debug != null) {
   2481                 debug.println("X509CertSelector.match: "
   2482                     + "IOException in name constraints check");
   2483             }
   2484             return false;
   2485         }
   2486         return true;
   2487     }
   2488 
   2489     private boolean matchExcluded(GeneralSubtrees excluded) {
   2490         /*
   2491          * Enumerate through excluded and compare each entry
   2492          * to all pathToNames. If any pathToName is within any of the
   2493          * subtrees listed in excluded, return false.
   2494          */
   2495         for (Iterator<GeneralSubtree> t = excluded.iterator(); t.hasNext(); ) {
   2496             GeneralSubtree tree = t.next();
   2497             GeneralNameInterface excludedName = tree.getName().getName();
   2498             Iterator<GeneralNameInterface> i = pathToGeneralNames.iterator();
   2499             while (i.hasNext()) {
   2500                 GeneralNameInterface pathToName = i.next();
   2501                 if (excludedName.getType() == pathToName.getType()) {
   2502                     switch (pathToName.constrains(excludedName)) {
   2503                     case GeneralNameInterface.NAME_WIDENS:
   2504                     case GeneralNameInterface.NAME_MATCH:
   2505                         if (debug != null) {
   2506                             debug.println("X509CertSelector.match: name constraints "
   2507                                 + "inhibit path to specified name");
   2508                             debug.println("X509CertSelector.match: excluded name: " +
   2509                                 pathToName);
   2510                         }
   2511                         return false;
   2512                     default:
   2513                     }
   2514                 }
   2515             }
   2516         }
   2517         return true;
   2518     }
   2519 
   2520     private boolean matchPermitted(GeneralSubtrees permitted) {
   2521         /*
   2522          * Enumerate through pathToNames, checking that each pathToName
   2523          * is in at least one of the subtrees listed in permitted.
   2524          * If not, return false. However, if no subtrees of a given type
   2525          * are listed, all names of that type are permitted.
   2526          */
   2527         Iterator<GeneralNameInterface> i = pathToGeneralNames.iterator();
   2528         while (i.hasNext()) {
   2529             GeneralNameInterface pathToName = i.next();
   2530             Iterator<GeneralSubtree> t = permitted.iterator();
   2531             boolean permittedNameFound = false;
   2532             boolean nameTypeFound = false;
   2533             String names = "";
   2534             while (t.hasNext() && !permittedNameFound) {
   2535                 GeneralSubtree tree = t.next();
   2536                 GeneralNameInterface permittedName = tree.getName().getName();
   2537                 if (permittedName.getType() == pathToName.getType()) {
   2538                     nameTypeFound = true;
   2539                     names = names + "  " + permittedName;
   2540                     switch (pathToName.constrains(permittedName)) {
   2541                     case GeneralNameInterface.NAME_WIDENS:
   2542                     case GeneralNameInterface.NAME_MATCH:
   2543                         permittedNameFound = true;
   2544                         break;
   2545                     default:
   2546                     }
   2547                 }
   2548             }
   2549             if (!permittedNameFound && nameTypeFound) {
   2550                 if (debug != null)
   2551                   debug.println("X509CertSelector.match: " +
   2552                             "name constraints inhibit path to specified name; " +
   2553                             "permitted names of type " + pathToName.getType() +
   2554                             ": " + names);
   2555                 return false;
   2556             }
   2557         }
   2558         return true;
   2559     }
   2560 
   2561     /* match on basic constraints */
   2562     private boolean matchBasicConstraints(X509Certificate xcert) {
   2563         if (basicConstraints == -1) {
   2564             return true;
   2565         }
   2566         int maxPathLen = xcert.getBasicConstraints();
   2567         if (basicConstraints == -2) {
   2568             if (maxPathLen != -1) {
   2569                 if (debug != null) {
   2570                     debug.println("X509CertSelector.match: not an EE cert");
   2571                 }
   2572                 return false;
   2573             }
   2574         } else {
   2575             if (maxPathLen < basicConstraints) {
   2576                 if (debug != null) {
   2577                     debug.println("X509CertSelector.match: cert's maxPathLen " +
   2578                             "is less than the min maxPathLen set by " +
   2579                             "basicConstraints. " +
   2580                             "(" + maxPathLen + " < " + basicConstraints + ")");
   2581                 }
   2582                 return false;
   2583             }
   2584         }
   2585         return true;
   2586     }
   2587 
   2588     @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
   2589     private static <T> Set<T> cloneSet(Set<T> set) {
   2590         if (set instanceof HashSet) {
   2591             Object clone = ((HashSet<T>)set).clone();
   2592             return (Set<T>)clone;
   2593         } else {
   2594             return new HashSet<T>(set);
   2595         }
   2596     }
   2597 
   2598     /**
   2599      * Returns a copy of this object.
   2600      *
   2601      * @return the copy
   2602      */
   2603     public Object clone() {
   2604         try {
   2605             X509CertSelector copy = (X509CertSelector)super.clone();
   2606             // Must clone these because addPathToName et al. modify them
   2607             if (subjectAlternativeNames != null) {
   2608                 copy.subjectAlternativeNames =
   2609                         cloneSet(subjectAlternativeNames);
   2610                 copy.subjectAlternativeGeneralNames =
   2611                         cloneSet(subjectAlternativeGeneralNames);
   2612             }
   2613             if (pathToGeneralNames != null) {
   2614                 copy.pathToNames = cloneSet(pathToNames);
   2615                 copy.pathToGeneralNames = cloneSet(pathToGeneralNames);
   2616             }
   2617             return copy;
   2618         } catch (CloneNotSupportedException e) {
   2619             /* Cannot happen */
   2620             throw new InternalError(e.toString(), e);
   2621         }
   2622     }
   2623 }
   2624