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