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