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