KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > cert > X509CertSelector


1 /*
2  * @(#)X509CertSelector.java 1.20 04/06/08
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.security.cert;
9
10 import java.io.IOException JavaDoc;
11 import java.math.BigInteger JavaDoc;
12 import java.security.PublicKey JavaDoc;
13 import java.util.*;
14 import javax.security.auth.x500.X500Principal JavaDoc;
15
16 import sun.misc.HexDumpEncoder;
17 import sun.security.util.Debug;
18 import sun.security.util.DerInputStream;
19 import sun.security.util.DerValue;
20 import sun.security.util.ObjectIdentifier;
21 import sun.security.x509.*;
22
23 /**
24  * A <code>CertSelector</code> that selects <code>X509Certificates</code> that
25  * match all specified criteria. This class is particularly useful when
26  * selecting certificates from a <code>CertStore</code> to build a
27  * PKIX-compliant certification path.
28  * <p>
29  * When first constructed, an <code>X509CertSelector</code> has no criteria
30  * enabled and each of the <code>get</code> methods return a default value
31  * (<code>null</code>, or <code>-1</code> for the {@link #getBasicConstraints
32  * getBasicConstraints} method). Therefore, the {@link #match match}
33  * method would return <code>true</code> for any <code>X509Certificate</code>.
34  * Typically, several criteria are enabled (by calling
35  * {@link #setIssuer setIssuer} or
36  * {@link #setKeyUsage setKeyUsage}, for instance) and then the
37  * <code>X509CertSelector</code> is passed to
38  * {@link CertStore#getCertificates CertStore.getCertificates} or some similar
39  * method.
40  * <p>
41  * Several criteria can be enabled (by calling {@link #setIssuer setIssuer}
42  * and {@link #setSerialNumber setSerialNumber},
43  * for example) such that the <code>match</code> method
44  * usually uniquely matches a single <code>X509Certificate</code>. We say
45  * usually, since it is possible for two issuing CAs to have the same
46  * distinguished name and each issue a certificate with the same serial
47  * number. Other unique combinations include the issuer, subject,
48  * subjectKeyIdentifier and/or the subjectPublicKey criteria.
49  * <p>
50  * Please refer to RFC 2459 for definitions of the X.509 certificate
51  * extensions mentioned below.
52  * <p>
53  * <b>Concurrent Access</b>
54  * <p>
55  * Unless otherwise specified, the methods defined in this class are not
56  * thread-safe. Multiple threads that need to access a single
57  * object concurrently should synchronize amongst themselves and
58  * provide the necessary locking. Multiple threads each manipulating
59  * separate objects need not synchronize.
60  *
61  * @see CertSelector
62  * @see X509Certificate
63  *
64  * @version 1.20, 06/08/04
65  * @since 1.4
66  * @author Steve Hanna
67  */

68 public class X509CertSelector implements CertSelector JavaDoc {
69
70     private static final Debug debug = Debug.getInstance("certpath");
71     
72     private final static ObjectIdentifier ANY_EXTENDED_KEY_USAGE =
73     ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0});
74     
75     static {
76     CertPathHelperImpl.initialize();
77     }
78   
79     private BigInteger JavaDoc serialNumber;
80     private X500Principal JavaDoc issuer;
81     private X500Principal JavaDoc subject;
82     private byte[] subjectKeyID;
83     private byte[] authorityKeyID;
84     private Date certificateValid;
85     private Date privateKeyValid;
86     private ObjectIdentifier subjectPublicKeyAlgID;
87     private PublicKey JavaDoc subjectPublicKey;
88     private byte[] subjectPublicKeyBytes;
89     private boolean[] keyUsage;
90     private Set<String JavaDoc> keyPurposeSet;
91     private Set<ObjectIdentifier> keyPurposeOIDSet;
92     private Set<List<?>> subjectAlternativeNames;
93     private Set<GeneralNameInterface> subjectAlternativeGeneralNames;
94     private CertificatePolicySet policy;
95     private Set<String JavaDoc> policySet;
96     private Set<List<?>> pathToNames;
97     private Set<GeneralNameInterface> pathToGeneralNames;
98     private NameConstraintsExtension nc;
99     private byte[] ncBytes;
100     private int basicConstraints = -1;
101     private X509Certificate JavaDoc x509Cert;
102     private boolean matchAllSubjectAltNames = true;
103
104     private static final Boolean JavaDoc FALSE = Boolean.FALSE;
105
106     private static final int PRIVATE_KEY_USAGE_ID = 0;
107     private static final int SUBJECT_ALT_NAME_ID = 1;
108     private static final int NAME_CONSTRAINTS_ID = 2;
109     private static final int CERT_POLICIES_ID = 3;
110     private static final int EXTENDED_KEY_USAGE_ID = 4;
111     private static final int NUM_OF_EXTENSIONS = 5;
112     private static final String JavaDoc[] EXTENSION_OIDS = new String JavaDoc[NUM_OF_EXTENSIONS];
113     
114     static {
115     EXTENSION_OIDS[PRIVATE_KEY_USAGE_ID] = "2.5.29.16";
116     EXTENSION_OIDS[SUBJECT_ALT_NAME_ID] = "2.5.29.17";
117     EXTENSION_OIDS[NAME_CONSTRAINTS_ID] = "2.5.29.30";
118     EXTENSION_OIDS[CERT_POLICIES_ID] = "2.5.29.32";
119     EXTENSION_OIDS[EXTENDED_KEY_USAGE_ID] = "2.5.29.37";
120     };
121     
122     /* Constants representing the GeneralName types */
123     static final int NAME_ANY = 0;
124     static final int NAME_RFC822 = 1;
125     static final int NAME_DNS = 2;
126     static final int NAME_X400 = 3;
127     static final int NAME_DIRECTORY = 4;
128     static final int NAME_EDI = 5;
129     static final int NAME_URI = 6;
130     static final int NAME_IP = 7;
131     static final int NAME_OID = 8;
132
133     /**
134      * Creates an <code>X509CertSelector</code>. Initially, no criteria are set
135      * so any <code>X509Certificate</code> will match.
136      */

137     public X509CertSelector() {
138     // empty
139
}
140  
141     /**
142      * Sets the certificateEquals criterion. The specified
143      * <code>X509Certificate</code> must be equal to the
144      * <code>X509Certificate</code> passed to the <code>match</code> method.
145      * If <code>null</code>, then this check is not applied.
146      *
147      * <p>This method is particularly useful when it is necessary to
148      * match a single certificate. Although other criteria can be specified
149      * in conjunction with the certificateEquals criterion, it is usually not
150      * practical or necessary.
151      *
152      * @param cert the <code>X509Certificate</code> to match (or
153      * <code>null</code>)
154      * @see #getCertificate
155      */

156     public void setCertificate(X509Certificate JavaDoc cert) {
157     x509Cert = cert;
158     }
159
160     /**
161      * Sets the serialNumber criterion. The specified serial number
162      * must match the certificate serial number in the
163      * <code>X509Certificate</code>. If <code>null</code>, any certificate
164      * serial number will do.
165      *
166      * @param serial the certificate serial number to match
167      * (or <code>null</code>)
168      * @see #getSerialNumber
169      */

170     public void setSerialNumber(BigInteger JavaDoc serial) {
171     serialNumber = serial;
172     }
173   
174     /**
175      * Sets the issuer criterion. The specified distinguished name
176      * must match the issuer distinguished name in the
177      * <code>X509Certificate</code>. If <code>null</code>, any issuer
178      * distinguished name will do.
179      *
180      * @param issuer a distinguished name as X500Principal
181      * (or <code>null</code>)
182      * @since 1.5
183      */

184     public void setIssuer(X500Principal JavaDoc issuer) {
185     this.issuer = issuer;
186     }
187
188     /**
189      * <strong>Denigrated</strong>, use {@linkplain #setIssuer(X500Principal)}
190      * or {@linkplain #setIssuer(byte[])} instead. This method should not be
191      * relied on as it can fail to match some certificates because of a loss of
192      * encoding information in the RFC 2253 String form of some distinguished
193      * names.
194      * <p>
195      * Sets the issuer criterion. The specified distinguished name
196      * must match the issuer distinguished name in the
197      * <code>X509Certificate</code>. If <code>null</code>, any issuer
198      * distinguished name will do.
199      * <p>
200      * If <code>issuerDN</code> is not <code>null</code>, it should contain a
201      * distinguished name, in RFC 2253 format.
202      *
203      * @param issuerDN a distinguished name in RFC 2253 format
204      * (or <code>null</code>)
205      * @throws IOException if a parsing error occurs (incorrect form for DN)
206      */

207     public void setIssuer(String JavaDoc issuerDN) throws IOException JavaDoc {
208     if (issuerDN == null) {
209         issuer = null;
210     } else {
211         issuer = new X500Name(issuerDN).asX500Principal();
212     }
213     }
214
215     /**
216      * Sets the issuer criterion. The specified distinguished name
217      * must match the issuer distinguished name in the
218      * <code>X509Certificate</code>. If <code>null</code> is specified,
219      * the issuer criterion is disabled and any issuer distinguished name will
220      * do.
221      * <p>
222      * If <code>issuerDN</code> is not <code>null</code>, it should contain a
223      * single DER encoded distinguished name, as defined in X.501. The ASN.1
224      * notation for this structure is as follows.
225      * <pre><code>
226      * Name ::= CHOICE {
227      * RDNSequence }
228      *
229      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
230      *
231      * RelativeDistinguishedName ::=
232      * SET SIZE (1 .. MAX) OF AttributeTypeAndValue
233      *
234      * AttributeTypeAndValue ::= SEQUENCE {
235      * type AttributeType,
236      * value AttributeValue }
237      *
238      * AttributeType ::= OBJECT IDENTIFIER
239      *
240      * AttributeValue ::= ANY DEFINED BY AttributeType
241      * ....
242      * DirectoryString ::= CHOICE {
243      * teletexString TeletexString (SIZE (1..MAX)),
244      * printableString PrintableString (SIZE (1..MAX)),
245      * universalString UniversalString (SIZE (1..MAX)),
246      * utf8String UTF8String (SIZE (1.. MAX)),
247      * bmpString BMPString (SIZE (1..MAX)) }
248      * </code></pre>
249      * <p>
250      * Note that the byte array specified here is cloned to protect against
251      * subsequent modifications.
252      *
253      * @param issuerDN a byte array containing the distinguished name
254      * in ASN.1 DER encoded form (or <code>null</code>)
255      * @throws IOException if an encoding error occurs (incorrect form for DN)
256      */

257     public void setIssuer(byte[] issuerDN) throws IOException JavaDoc {
258     try {
259         issuer = (issuerDN == null ? null : new X500Principal JavaDoc(issuerDN));
260     } catch (IllegalArgumentException JavaDoc e) {
261         throw (IOException JavaDoc)new IOException JavaDoc("Invalid name").initCause(e);
262     }
263     }
264   
265     /**
266      * Sets the subject criterion. The specified distinguished name
267      * must match the subject distinguished name in the
268      * <code>X509Certificate</code>. If <code>null</code>, any subject
269      * distinguished name will do.
270      *
271      * @param subject a distinguished name as X500Principal
272      * (or <code>null</code>)
273      * @since 1.5
274      */

275     public void setSubject(X500Principal JavaDoc subject) {
276     this.subject = subject;
277     }
278
279     /**
280      * <strong>Denigrated</strong>, use {@linkplain #setSubject(X500Principal)}
281      * or {@linkplain #setSubject(byte[])} instead. This method should not be
282      * relied on as it can fail to match some certificates because of a loss of
283      * encoding information in the RFC 2253 String form of some distinguished
284      * names.
285      * <p>
286      * Sets the subject criterion. The specified distinguished name
287      * must match the subject distinguished name in the
288      * <code>X509Certificate</code>. If <code>null</code>, any subject
289      * distinguished name will do.
290      * <p>
291      * If <code>subjectDN</code> is not <code>null</code>, it should contain a
292      * distinguished name, in RFC 2253 format.
293      *
294      * @param subjectDN a distinguished name in RFC 2253 format
295      * (or <code>null</code>)
296      * @throws IOException if a parsing error occurs (incorrect form for DN)
297      */

298     public void setSubject(String JavaDoc subjectDN) throws IOException JavaDoc {
299     if (subjectDN == null) {
300         subject = null;
301     } else {
302         subject = new X500Name(subjectDN).asX500Principal();
303     }
304     }
305
306     /**
307      * Sets the subject criterion. The specified distinguished name
308      * must match the subject distinguished name in the
309      * <code>X509Certificate</code>. If <code>null</code>, any subject
310      * distinguished name will do.
311      * <p>
312      * If <code>subjectDN</code> is not <code>null</code>, it should contain a
313      * single DER encoded distinguished name, as defined in X.501. For the ASN.1
314      * notation for this structure, see
315      * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
316      *
317      * @param subjectDN a byte array containing the distinguished name in
318      * ASN.1 DER format (or <code>null</code>)
319      * @throws IOException if an encoding error occurs (incorrect form for DN)
320      */

321     public void setSubject(byte[] subjectDN) throws IOException JavaDoc {
322     try {
323         subject = (subjectDN == null ? null : new X500Principal JavaDoc(subjectDN));
324     } catch (IllegalArgumentException JavaDoc e) {
325         throw (IOException JavaDoc)new IOException JavaDoc("Invalid name").initCause(e);
326     }
327     }
328
329     /**
330      * Sets the subjectKeyIdentifier criterion. The
331      * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
332      * extension for which the contents of the extension
333      * matches the specified criterion value.
334      * If the criterion value is <code>null</code>, no
335      * subjectKeyIdentifier check will be done.
336      * <p>
337      * If <code>subjectKeyID</code> is not <code>null</code>, it
338      * should contain a single DER encoded value corresponding to the contents
339      * of the extension value (not including the object identifier,
340      * criticality setting, and encapsulating OCTET STRING)
341      * for a SubjectKeyIdentifier extension.
342      * The ASN.1 notation for this structure follows.
343      * <p>
344      * <pre><code>
345      * SubjectKeyIdentifier ::= KeyIdentifier
346      *
347      * KeyIdentifier ::= OCTET STRING
348      * </code></pre>
349      * <p>
350      * Since the format of subject key identifiers is not mandated by
351      * any standard, subject key identifiers are not parsed by the
352      * <code>X509CertSelector</code>. Instead, the values are compared using
353      * a byte-by-byte comparison.
354      * <p>
355      * Note that the byte array supplied here is cloned to protect against
356      * subsequent modifications.
357      *
358      * @param subjectKeyID the subject key identifier (or <code>null</code>)
359      * @see #getSubjectKeyIdentifier
360      */

361     public void setSubjectKeyIdentifier(byte[] subjectKeyID) {
362     if (subjectKeyID == null) {
363         this.subjectKeyID = null;
364     } else {
365         this.subjectKeyID = (byte[])subjectKeyID.clone();
366     }
367     }
368
369     /**
370      * Sets the authorityKeyIdentifier criterion. The
371      * <code>X509Certificate</code> must contain an
372      * AuthorityKeyIdentifier extension for which the contents of the
373      * extension value matches the specified criterion value.
374      * If the criterion value is <code>null</code>, no
375      * authorityKeyIdentifier check will be done.
376      * <p>
377      * If <code>authorityKeyID</code> is not <code>null</code>, it
378      * should contain a single DER encoded value corresponding to the contents
379      * of the extension value (not including the object identifier,
380      * criticality setting, and encapsulating OCTET STRING)
381      * for an AuthorityKeyIdentifier extension.
382      * The ASN.1 notation for this structure follows.
383      * <p>
384      * <pre><code>
385      * AuthorityKeyIdentifier ::= SEQUENCE {
386      * keyIdentifier [0] KeyIdentifier OPTIONAL,
387      * authorityCertIssuer [1] GeneralNames OPTIONAL,
388      * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
389      *
390      * KeyIdentifier ::= OCTET STRING
391      * </code></pre>
392      * <p>
393      * Authority key identifiers are not parsed by the
394      * <code>X509CertSelector</code>. Instead, the values are
395      * compared using a byte-by-byte comparison.
396      * <p>
397      * When the <code>keyIdentifier</code> field of
398      * <code>AuthorityKeyIdentifier</code> is populated, the value is
399      * usually taken from the <code>SubjectKeyIdentifier</code> extension
400      * in the issuer's certificate. Note, however, that the result of
401      * <code>X509Certificate.getExtensionValue(&lt;SubjectKeyIdentifier Object
402      * Identifier&gt;)</code> on the issuer's certificate may NOT be used
403      * directly as the input to <code>setAuthorityKeyIdentifier</code>.
404      * This is because the SubjectKeyIdentifier contains
405      * only a KeyIdentifier OCTET STRING, and not a SEQUENCE of
406      * KeyIdentifier, GeneralNames, and CertificateSerialNumber.
407      * In order to use the extension value of the issuer certificate's
408      * <code>SubjectKeyIdentifier</code>
409      * extension, it will be necessary to extract the value of the embedded
410      * <code>KeyIdentifier</code> OCTET STRING, then DER encode this OCTET
411      * STRING inside a SEQUENCE.
412      * For more details on SubjectKeyIdentifier, see
413      * {@link #setSubjectKeyIdentifier(byte[] subjectKeyID)}.
414      * <p>
415      * Note also that the byte array supplied here is cloned to protect against
416      * subsequent modifications.
417      *
418      * @param authorityKeyID the authority key identifier
419      * (or <code>null</code>)
420      * @see #getAuthorityKeyIdentifier
421      */

422     public void setAuthorityKeyIdentifier(byte[] authorityKeyID) {
423     if (authorityKeyID == null) {
424         this.authorityKeyID = null;
425     } else {
426         this.authorityKeyID = (byte[])authorityKeyID.clone();
427     }
428     }
429
430     /**
431      * Sets the certificateValid criterion. The specified date must fall
432      * within the certificate validity period for the
433      * <code>X509Certificate</code>. If <code>null</code>, no certificateValid
434      * check will be done.
435      * <p>
436      * Note that the <code>Date</code> supplied here is cloned to protect
437      * against subsequent modifications.
438      *
439      * @param certValid the <code>Date</code> to check (or <code>null</code>)
440      * @see #getCertificateValid
441      */

442     public void setCertificateValid(Date certValid) {
443     if (certValid == null) {
444         certificateValid = null;
445     } else {
446         certificateValid = (Date)certValid.clone();
447     }
448     }
449
450     /**
451      * Sets the privateKeyValid criterion. The specified date must fall
452      * within the private key validity period for the
453      * <code>X509Certificate</code>. If <code>null</code>, no privateKeyValid
454      * check will be done.
455      * <p>
456      * Note that the <code>Date</code> supplied here is cloned to protect
457      * against subsequent modifications.
458      *
459      * @param privateKeyValid the <code>Date</code> to check (or
460      * <code>null</code>)
461      * @see #getPrivateKeyValid
462      */

463     public void setPrivateKeyValid(Date privateKeyValid) {
464     if (privateKeyValid == null) {
465         this.privateKeyValid = null;
466     } else {
467         this.privateKeyValid = (Date)privateKeyValid.clone();
468     }
469     }
470
471     /**
472      * Sets the subjectPublicKeyAlgID criterion. The
473      * <code>X509Certificate</code> must contain a subject public key
474      * with the specified algorithm. If <code>null</code>, no
475      * subjectPublicKeyAlgID check will be done.
476      *
477      * @param oid The object identifier (OID) of the algorithm to check
478      * for (or <code>null</code>). An OID is represented by a
479      * set of nonnegative integers separated by periods.
480      * @throws IOException if the OID is invalid, such as
481      * the first component being not 0, 1 or 2 or the second component
482      * being greater than 39.
483      *
484      * @see #getSubjectPublicKeyAlgID
485      */

486     public void setSubjectPublicKeyAlgID(String JavaDoc oid) throws IOException JavaDoc {
487     if (oid == null) {
488         subjectPublicKeyAlgID = null;
489     } else {
490         subjectPublicKeyAlgID = new ObjectIdentifier(oid);
491     }
492     }
493     
494     /**
495      * Sets the subjectPublicKey criterion. The
496      * <code>X509Certificate</code> must contain the specified subject public
497      * key. If <code>null</code>, no subjectPublicKey check will be done.
498      *
499      * @param key the subject public key to check for (or <code>null</code>)
500      * @see #getSubjectPublicKey
501      */

502     public void setSubjectPublicKey(PublicKey JavaDoc key) {
503     if (key == null) {
504         subjectPublicKey = null;
505         subjectPublicKeyBytes = null;
506     } else {
507         subjectPublicKey = key;
508         subjectPublicKeyBytes = key.getEncoded();
509     }
510     }
511
512     /**
513      * Sets the subjectPublicKey criterion. The <code>X509Certificate</code>
514      * must contain the specified subject public key. If <code>null</code>,
515      * no subjectPublicKey check will be done.
516      * <p>
517      * Because this method allows the public key to be specified as a byte
518      * array, it may be used for unknown key types.
519      * <p>
520      * If <code>key</code> is not <code>null</code>, it should contain a
521      * single DER encoded SubjectPublicKeyInfo structure, as defined in X.509.
522      * The ASN.1 notation for this structure is as follows.
523      * <pre><code>
524      * SubjectPublicKeyInfo ::= SEQUENCE {
525      * algorithm AlgorithmIdentifier,
526      * subjectPublicKey BIT STRING }
527      *
528      * AlgorithmIdentifier ::= SEQUENCE {
529      * algorithm OBJECT IDENTIFIER,
530      * parameters ANY DEFINED BY algorithm OPTIONAL }
531      * -- contains a value of the type
532      * -- registered for use with the
533      * -- algorithm object identifier value
534      * </code></pre>
535      * <p>
536      * Note that the byte array supplied here is cloned to protect against
537      * subsequent modifications.
538      *
539      * @param key a byte array containing the subject public key in ASN.1 DER
540      * form (or <code>null</code>)
541      * @throws IOException if an encoding error occurs (incorrect form for
542      * subject public key)
543      * @see #getSubjectPublicKey
544      */

545     public void setSubjectPublicKey(byte[] key) throws IOException JavaDoc {
546     if (key == null) {
547         subjectPublicKey = null;
548         subjectPublicKeyBytes = null;
549     } else {
550         subjectPublicKeyBytes = (byte[])key.clone();
551         subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes));
552     }
553     }
554
555     /**
556      * Sets the keyUsage criterion. The <code>X509Certificate</code>
557      * must allow the specified keyUsage values. If <code>null</code>, no
558      * keyUsage check will be done. Note that an <code>X509Certificate</code>
559      * that has no keyUsage extension implicitly allows all keyUsage values.
560      * <p>
561      * Note that the boolean array supplied here is cloned to protect against
562      * subsequent modifications.
563      *
564      * @param keyUsage a boolean array in the same format as the boolean
565      * array returned by
566      * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
567      * Or <code>null</code>.
568      * @see #getKeyUsage
569      */

570     public void setKeyUsage(boolean[] keyUsage) {
571     if (keyUsage == null) {
572         this.keyUsage = null;
573     } else {
574         this.keyUsage = (boolean[])keyUsage.clone();
575     }
576     }
577
578     /**
579      * Sets the extendedKeyUsage criterion. The <code>X509Certificate</code>
580      * must allow the specified key purposes in its extended key usage
581      * extension. If <code>keyPurposeSet</code> is empty or <code>null</code>,
582      * no extendedKeyUsage check will be done. Note that an
583      * <code>X509Certificate</code> that has no extendedKeyUsage extension
584      * implicitly allows all key purposes.
585      * <p>
586      * Note that the <code>Set</code> is cloned to protect against
587      * subsequent modifications.
588      *
589      * @param keyPurposeSet a <code>Set</code> of key purpose OIDs in string
590      * format (or <code>null</code>). Each OID is represented by a set of
591      * nonnegative integers separated by periods.
592      * @throws IOException if the OID is invalid, such as
593      * the first component being not 0, 1 or 2 or the second component
594      * being greater than 39.
595      * @see #getExtendedKeyUsage
596      */

597     public void setExtendedKeyUsage(Set<String JavaDoc> keyPurposeSet) throws IOException JavaDoc {
598     if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
599         this.keyPurposeSet = null;
600         keyPurposeOIDSet = null;
601     } else {
602         this.keyPurposeSet =
603         Collections.unmodifiableSet(new HashSet<String JavaDoc>(keyPurposeSet));
604         keyPurposeOIDSet = new HashSet<ObjectIdentifier>();
605         for (String JavaDoc s : this.keyPurposeSet) {
606         keyPurposeOIDSet.add(new ObjectIdentifier(s));
607         }
608     }
609     }
610
611     /**
612      * Enables/disables matching all of the subjectAlternativeNames
613      * specified in the {@link #setSubjectAlternativeNames
614      * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
615      * addSubjectAlternativeName} methods. If enabled,
616      * the <code>X509Certificate</code> must contain all of the
617      * specified subject alternative names. If disabled, the
618      * <code>X509Certificate</code> must contain at least one of the
619      * specified subject alternative names.
620      *
621      * <p>The matchAllNames flag is <code>true</code> by default.
622      *
623      * @param matchAllNames if <code>true</code>, the flag is enabled;
624      * if <code>false</code>, the flag is disabled.
625      * @see #getMatchAllSubjectAltNames
626      */

627     public void setMatchAllSubjectAltNames(boolean matchAllNames) {
628     this.matchAllSubjectAltNames = matchAllNames;
629     }
630
631     /**
632      * Sets the subjectAlternativeNames criterion. The
633      * <code>X509Certificate</code> must contain all or at least one of the
634      * specified subjectAlternativeNames, depending on the value of
635      * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
636      * setMatchAllSubjectAltNames}).
637      * <p>
638      * This method allows the caller to specify, with a single method call,
639      * the complete set of subject alternative names for the
640      * subjectAlternativeNames criterion. The specified value replaces
641      * the previous value for the subjectAlternativeNames criterion.
642      * <p>
643      * The <code>names</code> parameter (if not <code>null</code>) is a
644      * <code>Collection</code> with one
645      * entry for each name to be included in the subject alternative name
646      * criterion. Each entry is a <code>List</code> whose first entry is an
647      * <code>Integer</code> (the name type, 0-8) and whose second
648      * entry is a <code>String</code> or a byte array (the name, in
649      * string or ASN.1 DER encoded form, respectively).
650      * There can be multiple names of the same type. If <code>null</code>
651      * is supplied as the value for this argument, no
652      * subjectAlternativeNames check will be performed.
653      * <p>
654      * Each subject alternative name in the <code>Collection</code>
655      * may be specified either as a <code>String</code> or as an ASN.1 encoded
656      * byte array. For more details about the formats used, see
657      * {@link #addSubjectAlternativeName(int type, String name)
658      * addSubjectAlternativeName(int type, String name)} and
659      * {@link #addSubjectAlternativeName(int type, byte [] name)
660      * addSubjectAlternativeName(int type, byte [] name)}.
661      * <p>
662      * <strong>Note:</strong> for distinguished names, specify the byte
663      * array form instead of the String form. See the note in
664      * {@link #addSubjectAlternativeName(int, String)} for more information.
665      * <p>
666      * Note that the <code>names</code> parameter can contain duplicate
667      * names (same name and name type), but they may be removed from the
668      * <code>Collection</code> of names returned by the
669      * {@link #getSubjectAlternativeNames getSubjectAlternativeNames} method.
670      * <p>
671      * Note that a deep copy is performed on the <code>Collection</code> to
672      * protect against subsequent modifications.
673      *
674      * @param names a <code>Collection</code> of names (or <code>null</code>)
675      * @throws IOException if a parsing error occurs
676      * @see #getSubjectAlternativeNames
677      */

678     public void setSubjectAlternativeNames(Collection<List<?>> names)
679         throws IOException JavaDoc {
680     if (names == null) {
681         subjectAlternativeNames = null;
682         subjectAlternativeGeneralNames = null;
683     } else {
684         if (names.isEmpty()) {
685         subjectAlternativeNames = null;
686         subjectAlternativeGeneralNames = null;
687         return;
688         }
689         Set<List<?>> tempNames = cloneAndCheckNames(names);
690         // Ensure that we either set both of these or neither
691
subjectAlternativeGeneralNames = parseNames(tempNames);
692         subjectAlternativeNames = tempNames;
693     }
694     }
695
696     /**
697      * Adds a name to the subjectAlternativeNames criterion. The
698      * <code>X509Certificate</code> must contain all or at least one
699      * of the specified subjectAlternativeNames, depending on the value of
700      * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
701      * setMatchAllSubjectAltNames}).
702      * <p>
703      * This method allows the caller to add a name to the set of subject
704      * alternative names.
705      * The specified name is added to any previous value for the
706      * subjectAlternativeNames criterion. If the specified name is a
707      * duplicate, it may be ignored.
708      * <p>
709      * The name is provided in string format. RFC 822, DNS, and URI names
710      * use the well-established string formats for those types (subject to
711      * the restrictions included in RFC 2459). IPv4 address names are
712      * supplied using dotted quad notation. OID address names are represented
713      * as a series of nonnegative integers separated by periods. And
714      * directory names (distinguished names) are supplied in RFC 2253 format.
715      * No standard string format is defined for otherNames, X.400 names,
716      * EDI party names, IPv6 address names, or any other type of names. They
717      * should be specified using the
718      * {@link #addSubjectAlternativeName(int type, byte [] name)
719      * addSubjectAlternativeName(int type, byte [] name)}
720      * method.
721      * <p>
722      * <strong>Note:</strong> for distinguished names, use
723      * {@linkplain #addSubjectAlternativeName(int, byte[])} instead.
724      * This method should not be relied on as it can fail to match some
725      * certificates because of a loss of encoding information in the RFC 2253
726      * String form of some distinguished names.
727      *
728      * @param type the name type (0-8, as specified in
729      * RFC 2459, section 4.2.1.7)
730      * @param name the name in string form (not <code>null</code>)
731      * @throws IOException if a parsing error occurs
732      */

733     public void addSubjectAlternativeName(int type, String JavaDoc name)
734         throws IOException JavaDoc {
735     addSubjectAlternativeNameInternal(type, name);
736     }
737
738     /**
739      * Adds a name to the subjectAlternativeNames criterion. The
740      * <code>X509Certificate</code> must contain all or at least one
741      * of the specified subjectAlternativeNames, depending on the value of
742      * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
743      * setMatchAllSubjectAltNames}).
744      * <p>
745      * This method allows the caller to add a name to the set of subject
746      * alternative names.
747      * The specified name is added to any previous value for the
748      * subjectAlternativeNames criterion. If the specified name is a
749      * duplicate, it may be ignored.
750      * <p>
751      * The name is provided as a byte array. This byte array should contain
752      * the DER encoded name, as it would appear in the GeneralName structure
753      * defined in RFC 2459 and X.509. The encoded byte array should only contain
754      * the encoded value of the name, and should not include the tag associated
755      * with the name in the GeneralName structure. The ASN.1 definition of this
756      * structure appears below.
757      * <pre><code>
758      * GeneralName ::= CHOICE {
759      * otherName [0] OtherName,
760      * rfc822Name [1] IA5String,
761      * dNSName [2] IA5String,
762      * x400Address [3] ORAddress,
763      * directoryName [4] Name,
764      * ediPartyName [5] EDIPartyName,
765      * uniformResourceIdentifier [6] IA5String,
766      * iPAddress [7] OCTET STRING,
767      * registeredID [8] OBJECT IDENTIFIER}
768      * </code></pre>
769      * <p>
770      * Note that the byte array supplied here is cloned to protect against
771      * subsequent modifications.
772      *
773      * @param type the name type (0-8, as listed above)
774      * @param name a byte array containing the name in ASN.1 DER encoded form
775      * @throws IOException if a parsing error occurs
776      */

777     public void addSubjectAlternativeName(int type, byte[] name)
778         throws IOException JavaDoc {
779     // clone because byte arrays are modifiable
780
addSubjectAlternativeNameInternal(type, name.clone());
781     }
782
783     /**
784      * A private method that adds a name (String or byte array) to the
785      * subjectAlternativeNames criterion. The <code>X509Certificate</code>
786      * must contain the specified subjectAlternativeName.
787      *
788      * @param type the name type (0-8, as specified in
789      * RFC 2459, section 4.2.1.7)
790      * @param name the name in string or byte array form
791      * @throws IOException if a parsing error occurs
792      */

793     private void addSubjectAlternativeNameInternal(int type, Object JavaDoc name)
794         throws IOException JavaDoc {
795     // First, ensure that the name parses
796
GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
797     if (subjectAlternativeNames == null) {
798         subjectAlternativeNames = new HashSet<List<?>>();
799     }
800     if (subjectAlternativeGeneralNames == null) {
801         subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>();
802     }
803     List<Object JavaDoc> list = new ArrayList<Object JavaDoc>(2);
804     list.add(Integer.valueOf(type));
805     list.add(name);
806     subjectAlternativeNames.add(list);
807     subjectAlternativeGeneralNames.add(tempName);
808     }
809
810     /**
811      * Parse an argument of the form passed to setSubjectAlternativeNames,
812      * returning a <code>Collection</code> of
813      * <code>GeneralNameInterface</code>s.
814      * Throw an IllegalArgumentException or a ClassCastException
815      * if the argument is malformed.
816      *
817      * @param names a Collection with one entry per name.
818      * Each entry is a <code>List</code> whose first entry
819      * is an Integer (the name type, 0-8) and whose second
820      * entry is a String or a byte array (the name, in
821      * string or ASN.1 DER encoded form, respectively).
822      * There can be multiple names of the same type. Null is
823      * not an acceptable value.
824      * @return a Set of <code>GeneralNameInterface</code>s
825      * @throws IOException if a parsing error occurs
826      */

827     private static Set<GeneralNameInterface> parseNames(Collection<List<?>> names) throws IOException JavaDoc {
828     Set<GeneralNameInterface> genNames = new HashSet<GeneralNameInterface>();
829     Iterator<List<?>> i = names.iterator();
830     while (i.hasNext()) {
831         Object JavaDoc o = i.next();
832         if (!(o instanceof List)) {
833         throw new IOException JavaDoc("expected List");
834         }
835         List<Object JavaDoc> nameList = (List<Object JavaDoc>)o;
836         if (nameList.size() != 2) {
837         throw new IOException JavaDoc("name list size not 2");
838         }
839         o = nameList.get(0);
840         if (!(o instanceof Integer JavaDoc)) {
841         throw new IOException JavaDoc("expected an Integer");
842         }
843         int nameType = ((Integer JavaDoc)o).intValue();
844         o = nameList.get(1);
845         genNames.add(makeGeneralNameInterface(nameType, o));
846     }
847     return genNames;
848     }
849   
850     /**
851      * Compare for equality two objects of the form passed to
852      * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames).
853      * Throw an <code>IllegalArgumentException</code> or a
854      * <code>ClassCastException</code> if one of the objects is malformed.
855      *
856      * @param object1 a Collection containing the first object to compare
857      * @param object2 a Collection containing the second object to compare
858      * @return true if the objects are equal, false otherwise
859      */

860     static boolean equalNames(Collection object1, Collection object2) {
861     if ((object1 == null) || (object2 == null)) {
862         return object1 == object2;
863     }
864     return object1.equals(object2);
865     }
866
867     /**
868      * Make a <code>GeneralNameInterface</code> out of a name type (0-8) and an
869      * Object that may be a byte array holding the ASN.1 DER encoded
870      * name or a String form of the name. Except for X.509
871      * Distinguished Names, the String form of the name must not be the
872      * result from calling toString on an existing GeneralNameInterface
873      * implementing class. The output of toString is not compatible
874      * with the String constructors for names other than Distinguished
875      * Names.
876      *
877      * @param type name type (0-8)
878      * @param name name as ASN.1 Der-encoded byte array or String
879      * @return a GeneralNameInterface name
880      * @throws IOException if a parsing error occurs
881      */

882     static GeneralNameInterface makeGeneralNameInterface(int type, Object JavaDoc name)
883         throws IOException JavaDoc {
884     GeneralNameInterface result;
885     if (debug != null) {
886         debug.println("X509CertSelector.makeGeneralNameInterface("
887             + type + ")...");
888     }
889   
890     if (name instanceof String JavaDoc) {
891         if (debug != null) {
892         debug.println("X509CertSelector.makeGeneralNameInterface() "
893             + "name is String: " + name);
894         }
895         switch (type) {
896         case NAME_RFC822:
897         result = new RFC822Name((String JavaDoc)name);
898         break;
899         case NAME_DNS:
900         result = new DNSName((String JavaDoc)name);
901         break;
902         case NAME_DIRECTORY:
903         result = new X500Name((String JavaDoc)name);
904         break;
905         case NAME_URI:
906         result = new URIName((String JavaDoc)name);
907         break;
908         case NAME_IP:
909         result = new IPAddressName((String JavaDoc)name);
910         break;
911         case NAME_OID:
912         result = new OIDName((String JavaDoc)name);
913         break;
914         default:
915         throw new IOException JavaDoc("unable to parse String names of type "
916                       + type);
917         }
918         if (debug != null) {
919         debug.println("X509CertSelector.makeGeneralNameInterface() "
920             + "result: " + result.toString());
921         }
922     } else if (name instanceof byte[]) {
923         DerValue val = new DerValue((byte[]) name);
924         if (debug != null) {
925         debug.println
926             ("X509CertSelector.makeGeneralNameInterface() is byte[]");
927         }
928     
929         switch (type) {
930         case NAME_ANY:
931         result = new OtherName(val);
932         break;
933         case NAME_RFC822:
934         result = new RFC822Name(val);
935         break;
936         case NAME_DNS:
937         result = new DNSName(val);
938         break;
939         case NAME_X400:
940         result = new X400Address(val);
941         break;
942         case NAME_DIRECTORY:
943         result = new X500Name(val);
944         break;
945         case NAME_EDI:
946         result = new EDIPartyName(val);
947         break;
948         case NAME_URI:
949         result = new URIName(val);
950         break;
951         case NAME_IP:
952         result = new IPAddressName(val);
953         break;
954         case NAME_OID:
955         result = new OIDName(val);
956         break;
957         default:
958         throw new IOException JavaDoc("unable to parse byte array names of "
959             + "type " + type);
960         }
961         if (debug != null) {
962         debug.println("X509CertSelector.makeGeneralNameInterface() result: "
963             + result.toString());
964         }
965     } else {
966         if (debug != null) {
967         debug.println("X509CertSelector.makeGeneralName() input name "
968             + "not String or byte array");
969         }
970         throw new IOException JavaDoc("name not String or byte array");
971     }
972     return result;
973     }
974
975
976     /**
977      * Sets the name constraints criterion. The <code>X509Certificate</code>
978      * must have subject and subject alternative names that
979      * meet the specified name constraints.
980      * <p>
981      * The name constraints are specified as a byte array. This byte array
982      * should contain the DER encoded form of the name constraints, as they
983      * would appear in the NameConstraints structure defined in RFC 2459
984      * and X.509. The ASN.1 definition of this structure appears below.
985      *
986      * <pre><code>
987      * NameConstraints ::= SEQUENCE {
988      * permittedSubtrees [0] GeneralSubtrees OPTIONAL,
989      * excludedSubtrees [1] GeneralSubtrees OPTIONAL }
990      *
991      * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
992      *
993      * GeneralSubtree ::= SEQUENCE {
994      * base GeneralName,
995      * minimum [0] BaseDistance DEFAULT 0,
996      * maximum [1] BaseDistance OPTIONAL }
997      *
998      * BaseDistance ::= INTEGER (0..MAX)
999      *
1000     * GeneralName ::= CHOICE {
1001     * otherName [0] OtherName,
1002     * rfc822Name [1] IA5String,
1003     * dNSName [2] IA5String,
1004     * x400Address [3] ORAddress,
1005     * directoryName [4] Name,
1006     * ediPartyName [5] EDIPartyName,
1007     * uniformResourceIdentifier [6] IA5String,
1008     * iPAddress [7] OCTET STRING,
1009     * registeredID [8] OBJECT IDENTIFIER}
1010     * </code></pre>
1011     * <p>
1012     * Note that the byte array supplied here is cloned to protect against
1013     * subsequent modifications.
1014     *
1015     * @param bytes a byte array containing the ASN.1 DER encoding of
1016     * a NameConstraints extension to be used for checking
1017     * name constraints. Only the value of the extension is
1018     * included, not the OID or criticality flag. Can be
1019     * <code>null</code>,
1020     * in which case no name constraints check will be performed.
1021     * @throws IOException if a parsing error occurs
1022     * @see #getNameConstraints
1023     */

1024    public void setNameConstraints(byte[] bytes) throws IOException JavaDoc {
1025    if (bytes == null) {
1026        ncBytes = null;
1027        nc = null;
1028    } else {
1029        ncBytes = (byte[])bytes.clone();
1030        nc = new NameConstraintsExtension(FALSE, bytes);
1031    }
1032    }
1033
1034    /**
1035     * Sets the basic constraints constraint. If the value is greater than or
1036     * equal to zero, <code>X509Certificates</code> must include a
1037     * basicConstraints extension with
1038     * a pathLen of at least this value. If the value is -2, only end-entity
1039     * certificates are accepted. If the value is -1, no check is done.
1040     * <p>
1041     * This constraint is useful when building a certification path forward
1042     * (from the target toward the trust anchor. If a partial path has been
1043     * built, any candidate certificate must have a maxPathLen value greater
1044     * than or equal to the number of certificates in the partial path.
1045     *
1046     * @param minMaxPathLen the value for the basic constraints constraint
1047     * @throws IllegalArgumentException if the value is less than -2
1048     * @see #getBasicConstraints
1049     */

1050    public void setBasicConstraints(int minMaxPathLen) {
1051    if (minMaxPathLen < -2) {
1052        throw new IllegalArgumentException JavaDoc("basic constraints less than -2");
1053    }
1054    basicConstraints = minMaxPathLen;
1055    }
1056
1057    /**
1058     * Sets the policy constraint. The <code>X509Certificate</code> must
1059     * include at least one of the specified policies in its certificate
1060     * policies extension. If <code>certPolicySet</code> is empty, then the
1061     * <code>X509Certificate</code> must include at least some specified policy
1062     * in its certificate policies extension. If <code>certPolicySet</code> is
1063     * <code>null</code>, no policy check will be performed.
1064     * <p>
1065     * Note that the <code>Set</code> is cloned to protect against
1066     * subsequent modifications.
1067     *
1068     * @param certPolicySet a <code>Set</code> of certificate policy OIDs in
1069     * string format (or <code>null</code>). Each OID is
1070     * represented by a set of nonnegative integers
1071     * separated by periods.
1072     * @throws IOException if a parsing error occurs on the OID such as
1073     * the first component is not 0, 1 or 2 or the second component is
1074     * greater than 39.
1075     * @see #getPolicy
1076     */

1077    public void setPolicy(Set<String JavaDoc> certPolicySet) throws IOException JavaDoc {
1078    if (certPolicySet == null) {
1079        policySet = null;
1080        policy = null;
1081    } else {
1082        // Snapshot set and parse it
1083
Set<String JavaDoc> tempSet = Collections.unmodifiableSet
1084                        (new HashSet<String JavaDoc>(certPolicySet));
1085        /* Convert to Vector of ObjectIdentifiers */
1086        Iterator i = tempSet.iterator();
1087        Vector<CertificatePolicyId> polIdVector = new Vector<CertificatePolicyId>();
1088        while (i.hasNext()) {
1089        Object JavaDoc o = i.next();
1090        if (!(o instanceof String JavaDoc)) {
1091            throw new IOException JavaDoc("non String in certPolicySet");
1092        }
1093        polIdVector.add(new CertificatePolicyId(new ObjectIdentifier(
1094          (String JavaDoc)o)));
1095        }
1096        // If everything went OK, make the changes
1097
policySet = tempSet;
1098        policy = new CertificatePolicySet(polIdVector);
1099    }
1100    }
1101
1102    /**
1103     * Sets the pathToNames criterion. The <code>X509Certificate</code> must
1104     * not include name constraints that would prohibit building a
1105     * path to the specified names.
1106     * <p>
1107     * This method allows the caller to specify, with a single method call,
1108     * the complete set of names which the <code>X509Certificates</code>'s
1109     * name constraints must permit. The specified value replaces
1110     * the previous value for the pathToNames criterion.
1111     * <p>
1112     * This constraint is useful when building a certification path forward
1113     * (from the target toward the trust anchor. If a partial path has been
1114     * built, any candidate certificate must not include name constraints that
1115     * would prohibit building a path to any of the names in the partial path.
1116     * <p>
1117     * The <code>names</code> parameter (if not <code>null</code>) is a
1118     * <code>Collection</code> with one
1119     * entry for each name to be included in the pathToNames
1120     * criterion. Each entry is a <code>List</code> whose first entry is an
1121     * <code>Integer</code> (the name type, 0-8) and whose second
1122     * entry is a <code>String</code> or a byte array (the name, in
1123     * string or ASN.1 DER encoded form, respectively).
1124     * There can be multiple names of the same type. If <code>null</code>
1125     * is supplied as the value for this argument, no
1126     * pathToNames check will be performed.
1127     * <p>
1128     * Each name in the <code>Collection</code>
1129     * may be specified either as a <code>String</code> or as an ASN.1 encoded
1130     * byte array. For more details about the formats used, see
1131     * {@link #addPathToName(int type, String name)
1132     * addPathToName(int type, String name)} and
1133     * {@link #addPathToName(int type, byte [] name)
1134     * addPathToName(int type, byte [] name)}.
1135     * <p>
1136     * <strong>Note:</strong> for distinguished names, specify the byte
1137     * array form instead of the String form. See the note in
1138     * {@link #addPathToName(int, String)} for more information.
1139     * <p>
1140     * Note that the <code>names</code> parameter can contain duplicate
1141     * names (same name and name type), but they may be removed from the
1142     * <code>Collection</code> of names returned by the
1143     * {@link #getPathToNames getPathToNames} method.
1144     * <p>
1145     * Note that a deep copy is performed on the <code>Collection</code> to
1146     * protect against subsequent modifications.
1147     *
1148     * @param names a <code>Collection</code> with one entry per name
1149     * (or <code>null</code>)
1150     * @throws IOException if a parsing error occurs
1151     * @see #getPathToNames
1152     */

1153    public void setPathToNames(Collection<List<?>> names) throws IOException JavaDoc {
1154    if ((names == null) || names.isEmpty()) {
1155        pathToNames = null;
1156        pathToGeneralNames = null;
1157    } else {
1158        Set<List<?>> tempNames = cloneAndCheckNames(names);
1159        pathToGeneralNames = parseNames(tempNames);
1160        // Ensure that we either set both of these or neither
1161
pathToNames = tempNames;
1162    }
1163    }
1164  
1165    // called from CertPathHelper
1166
void setPathToNamesInternal(Set<GeneralNameInterface> names) {
1167    // set names to non-null dummy value
1168
// this breaks getPathToNames()
1169
pathToNames = Collections.<List<?>>emptySet();
1170    pathToGeneralNames = names;
1171    }
1172
1173    /**
1174     * Adds a name to the pathToNames criterion. The <code>X509Certificate</code>
1175     * must not include name constraints that would prohibit building a
1176     * path to the specified name.
1177     * <p>
1178     * This method allows the caller to add a name to the set of names which
1179     * the <code>X509Certificates</code>'s name constraints must permit.
1180     * The specified name is added to any previous value for the
1181     * pathToNames criterion. If the name is a duplicate, it may be ignored.
1182     * <p>
1183     * The name is provided in string format. RFC 822, DNS, and URI names
1184     * use the well-established string formats for those types (subject to
1185     * the restrictions included in RFC 2459). IPv4 address names are
1186     * supplied using dotted quad notation. OID address names are represented
1187     * as a series of nonnegative integers separated by periods. And
1188     * directory names (distinguished names) are supplied in RFC 2253 format.
1189     * No standard string format is defined for otherNames, X.400 names,
1190     * EDI party names, IPv6 address names, or any other type of names. They
1191     * should be specified using the
1192     * {@link #addPathToName(int type, byte [] name)
1193     * addPathToName(int type, byte [] name)} method.
1194     * <p>
1195     * <strong>Note:</strong> for distinguished names, use
1196     * {@linkplain #addPathToName(int, byte[])} instead.
1197     * This method should not be relied on as it can fail to match some
1198     * certificates because of a loss of encoding information in the RFC 2253
1199     * String form of some distinguished names.
1200     *
1201     * @param type the name type (0-8, as specified in
1202     * RFC 2459, section 4.2.1.7)
1203     * @param name the name in string form
1204     * @throws IOException if a parsing error occurs
1205     */

1206    public void addPathToName(int type, String JavaDoc name) throws IOException JavaDoc {
1207    addPathToNameInternal(type, name);
1208    }
1209
1210    /**
1211     * Adds a name to the pathToNames criterion. The <code>X509Certificate</code>
1212     * must not include name constraints that would prohibit building a
1213     * path to the specified name.
1214     * <p>
1215     * This method allows the caller to add a name to the set of names which
1216     * the <code>X509Certificates</code>'s name constraints must permit.
1217     * The specified name is added to any previous value for the
1218     * pathToNames criterion. If the name is a duplicate, it may be ignored.
1219     * <p>
1220     * The name is provided as a byte array. This byte array should contain
1221     * the DER encoded name, as it would appear in the GeneralName structure
1222     * defined in RFC 2459 and X.509. The ASN.1 definition of this structure
1223     * appears in the documentation for
1224     * {@link #addSubjectAlternativeName(int type, byte [] name)
1225     * addSubjectAlternativeName(int type, byte [] name)}.
1226     * <p>
1227     * Note that the byte array supplied here is cloned to protect against
1228     * subsequent modifications.
1229     *
1230     * @param type the name type (0-8, as specified in
1231     * RFC 2459, section 4.2.1.7)
1232     * @param name a byte array containing the name in ASN.1 DER encoded form
1233     * @throws IOException if a parsing error occurs
1234     */

1235    public void addPathToName(int type, byte [] name) throws IOException JavaDoc {
1236    // clone because byte arrays are modifiable
1237
addPathToNameInternal(type, name.clone());
1238    }
1239
1240    /**
1241     * A private method that adds a name (String or byte array) to the
1242     * pathToNames criterion. The <code>X509Certificate</code> must contain
1243     * the specified pathToName.
1244     *
1245     * @param type the name type (0-8, as specified in
1246     * RFC 2459, section 4.2.1.7)
1247     * @param name the name in string or byte array form
1248     * @throws IOException if an encoding error occurs (incorrect form for DN)
1249     */

1250    private void addPathToNameInternal(int type, Object JavaDoc name)
1251        throws IOException JavaDoc {
1252    // First, ensure that the name parses
1253
GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
1254    if (pathToGeneralNames == null) {
1255        pathToNames = new HashSet<List<?>>();
1256        pathToGeneralNames = new HashSet<GeneralNameInterface>();
1257    }
1258    List<Object JavaDoc> list = new ArrayList<Object JavaDoc>(2);
1259    list.add(Integer.valueOf(type));
1260    list.add(name);
1261    pathToNames.add(list);
1262    pathToGeneralNames.add(tempName);
1263    }
1264
1265    /**
1266     * Returns the certificateEquals criterion. The specified
1267     * <code>X509Certificate</code> must be equal to the
1268     * <code>X509Certificate</code> passed to the <code>match</code> method.
1269     * If <code>null</code>, this check is not applied.
1270     *
1271     * @return the <code>X509Certificate</code> to match (or <code>null</code>)
1272     * @see #setCertificate
1273     */

1274    public X509Certificate JavaDoc getCertificate() {
1275    return x509Cert;
1276    }
1277
1278    /**
1279     * Returns the serialNumber criterion. The specified serial number
1280     * must match the certificate serial number in the
1281     * <code>X509Certificate</code>. If <code>null</code>, any certificate
1282     * serial number will do.
1283     *
1284     * @return the certificate serial number to match
1285     * (or <code>null</code>)
1286     * @see #setSerialNumber
1287     */

1288    public BigInteger JavaDoc getSerialNumber() {
1289    return serialNumber;
1290    }
1291  
1292    /**
1293     * Returns the issuer criterion as an <code>X500Principal</code>. This
1294     * distinguished name must match the issuer distinguished name in the
1295     * <code>X509Certificate</code>. If <code>null</code>, the issuer criterion
1296     * is disabled and any issuer distinguished name will do.
1297     *
1298     * @return the required issuer distinguished name as X500Principal
1299     * (or <code>null</code>)
1300     * @since 1.5
1301     */

1302    public X500Principal JavaDoc getIssuer() {
1303    return issuer;
1304    }
1305
1306    /**
1307     * <strong>Denigrated</strong>, use {@linkplain #getIssuer()} or
1308     * {@linkplain #getIssuerAsBytes()} instead. This method should not be
1309     * relied on as it can fail to match some certificates because of a loss of
1310     * encoding information in the RFC 2253 String form of some distinguished
1311     * names.
1312     * <p>
1313     * Returns the issuer criterion as a <code>String</code>. This
1314     * distinguished name must match the issuer distinguished name in the
1315     * <code>X509Certificate</code>. If <code>null</code>, the issuer criterion
1316     * is disabled and any issuer distinguished name will do.
1317     * <p>
1318     * If the value returned is not <code>null</code>, it is a
1319     * distinguished name, in RFC 2253 format.
1320     *
1321     * @return the required issuer distinguished name in RFC 2253 format
1322     * (or <code>null</code>)
1323     */

1324    public String JavaDoc getIssuerAsString() {
1325    return (issuer == null ? null : issuer.getName());
1326    }
1327
1328    /**
1329     * Returns the issuer criterion as a byte array. This distinguished name
1330     * must match the issuer distinguished name in the
1331     * <code>X509Certificate</code>. If <code>null</code>, the issuer criterion
1332     * is disabled and any issuer distinguished name will do.
1333     * <p>
1334     * If the value returned is not <code>null</code>, it is a byte
1335     * array containing a single DER encoded distinguished name, as defined in
1336     * X.501. The ASN.1 notation for this structure is supplied in the
1337     * documentation for
1338     * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
1339     * <p>
1340     * Note that the byte array returned is cloned to protect against
1341     * subsequent modifications.
1342     *
1343     * @return a byte array containing the required issuer distinguished name
1344     * in ASN.1 DER format (or <code>null</code>)
1345     * @throws IOException if an encoding error occurs
1346     */

1347    public byte[] getIssuerAsBytes() throws IOException JavaDoc {
1348    return (issuer == null ? null: issuer.getEncoded());
1349    }
1350  
1351    /**
1352     * Returns the subject criterion as an <code>X500Principal</code>. This
1353     * distinguished name must match the subject distinguished name in the
1354     * <code>X509Certificate</code>. If <code>null</code>, the subject criterion
1355     * is disabled and any subject distinguished name will do.
1356     *
1357     * @return the required subject distinguished name as X500Principal
1358     * (or <code>null</code>)
1359     * @since 1.5
1360     */

1361    public X500Principal JavaDoc getSubject() {
1362    return subject;
1363    }
1364
1365    /**
1366     * <strong>Denigrated</strong>, use {@linkplain #getSubject()} or
1367     * {@linkplain #getSubjectAsBytes()} instead. This method should not be
1368     * relied on as it can fail to match some certificates because of a loss of
1369     * encoding information in the RFC 2253 String form of some distinguished
1370     * names.
1371     * <p>
1372     * Returns the subject criterion as a <code>String</code>. This
1373     * distinguished name must match the subject distinguished name in the
1374     * <code>X509Certificate</code>. If <code>null</code>, the subject criterion
1375     * is disabled and any subject distinguished name will do.
1376     * <p>
1377     * If the value returned is not <code>null</code>, it is a
1378     * distinguished name, in RFC 2253 format.
1379     *
1380     * @return the required subject distinguished name in RFC 2253 format
1381     * (or <code>null</code>)
1382     */

1383    public String JavaDoc getSubjectAsString() {
1384    return (subject == null ? null : subject.getName());
1385    }
1386
1387    /**
1388     * Returns the subject criterion as a byte array. This distinguished name
1389     * must match the subject distinguished name in the
1390     * <code>X509Certificate</code>. If <code>null</code>, the subject criterion
1391     * is disabled and any subject distinguished name will do.
1392     * <p>
1393     * If the value returned is not <code>null</code>, it is a byte
1394     * array containing a single DER encoded distinguished name, as defined in
1395     * X.501. The ASN.1 notation for this structure is supplied in the
1396     * documentation for
1397     * {@link #setSubject(byte [] subjectDN) setSubject(byte [] subjectDN)}.
1398     * <p>
1399     * Note that the byte array returned is cloned to protect against
1400     * subsequent modifications.
1401     *
1402     * @return a byte array containing the required subject distinguished name
1403     * in ASN.1 DER format (or <code>null</code>)
1404     * @throws IOException if an encoding error occurs
1405     */

1406    public byte[] getSubjectAsBytes() throws IOException JavaDoc {
1407    return (subject == null ? null : subject.getEncoded());
1408    }
1409
1410    /**
1411     * Returns the subjectKeyIdentifier criterion. The
1412     * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
1413     * extension with the specified value. If <code>null</code>, no
1414     * subjectKeyIdentifier check will be done.
1415     * <p>
1416     * Note that the byte array returned is cloned to protect against
1417     * subsequent modifications.
1418     *
1419     * @return the key identifier (or <code>null</code>)
1420     * @see #setSubjectKeyIdentifier
1421     */

1422    public byte[] getSubjectKeyIdentifier() {
1423    if (subjectKeyID == null) {
1424        return null;
1425    }
1426    return (byte[])subjectKeyID.clone();
1427    }
1428
1429    /**
1430     * Returns the authorityKeyIdentifier criterion. The
1431     * <code>X509Certificate</code> must contain a AuthorityKeyIdentifier
1432     * extension with the specified value. If <code>null</code>, no
1433     * authorityKeyIdentifier check will be done.
1434     * <p>
1435     * Note that the byte array returned is cloned to protect against
1436     * subsequent modifications.
1437     *
1438     * @return the key identifier (or <code>null</code>)
1439     * @see #setAuthorityKeyIdentifier
1440     */

1441    public byte[] getAuthorityKeyIdentifier() {
1442    if (authorityKeyID == null) {
1443      return null;
1444    }
1445    return (byte[])authorityKeyID.clone();
1446    }
1447
1448    /**
1449     * Returns the certificateValid criterion. The specified date must fall
1450     * within the certificate validity period for the
1451     * <code>X509Certificate</code>. If <code>null</code>, no certificateValid
1452     * check will be done.
1453     * <p>
1454     * Note that the <code>Date</code> returned is cloned to protect against
1455     * subsequent modifications.
1456     *
1457     * @return the <code>Date</code> to check (or <code>null</code>)
1458     * @see #setCertificateValid
1459     */

1460    public Date getCertificateValid() {
1461    if (certificateValid == null) {
1462        return null;
1463    }
1464    return (Date)certificateValid.clone();
1465    }
1466
1467    /**
1468     * Returns the privateKeyValid criterion. The specified date must fall
1469     * within the private key validity period for the
1470     * <code>X509Certificate</code>. If <code>null</code>, no privateKeyValid
1471     * check will be done.
1472     * <p>
1473     * Note that the <code>Date</code> returned is cloned to protect against
1474     * subsequent modifications.
1475     *
1476     * @return the <code>Date</code> to check (or <code>null</code>)
1477     * @see #setPrivateKeyValid
1478     */

1479    public Date getPrivateKeyValid() {
1480    if (privateKeyValid == null) {
1481        return null;
1482    }
1483    return (Date)privateKeyValid.clone();
1484    }
1485
1486    /**
1487     * Returns the subjectPublicKeyAlgID criterion. The
1488     * <code>X509Certificate</code> must contain a subject public key
1489     * with the specified algorithm. If <code>null</code>, no
1490     * subjectPublicKeyAlgID check will be done.
1491     *
1492     * @return the object identifier (OID) of the signature algorithm to check
1493     * for (or <code>null</code>). An OID is represented by a set of
1494     * nonnegative integers separated by periods.
1495     * @see #setSubjectPublicKeyAlgID
1496     */

1497    public String JavaDoc getSubjectPublicKeyAlgID() {
1498    if (subjectPublicKeyAlgID == null) {
1499        return null;
1500    }
1501    return subjectPublicKeyAlgID.toString();
1502    }
1503
1504    /**
1505     * Returns the subjectPublicKey criterion. The
1506     * <code>X509Certificate</code> must contain the specified subject
1507     * public key. If <code>null</code>, no subjectPublicKey check will be done.
1508     *
1509     * @return the subject public key to check for (or <code>null</code>)
1510     * @see #setSubjectPublicKey
1511     */

1512    public PublicKey JavaDoc getSubjectPublicKey() {
1513    return subjectPublicKey;
1514    }
1515
1516    /**
1517     * Returns the keyUsage criterion. The <code>X509Certificate</code>
1518     * must allow the specified keyUsage values. If null, no keyUsage
1519     * check will be done.
1520     * <p>
1521     * Note that the boolean array returned is cloned to protect against
1522     * subsequent modifications.
1523     *
1524     * @return a boolean array in the same format as the boolean
1525     * array returned by
1526     * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
1527     * Or <code>null</code>.
1528     * @see #setKeyUsage
1529     */

1530    public boolean[] getKeyUsage() {
1531    if (keyUsage == null) {
1532        return null;
1533    }
1534    return (boolean[])keyUsage.clone();
1535    }
1536
1537    /**
1538     * Returns the extendedKeyUsage criterion. The <code>X509Certificate</code>
1539     * must allow the specified key purposes in its extended key usage
1540     * extension. If the <code>keyPurposeSet</code> returned is empty or
1541     * <code>null</code>, no extendedKeyUsage check will be done. Note that an
1542     * <code>X509Certificate</code> that has no extendedKeyUsage extension
1543     * implicitly allows all key purposes.
1544     *
1545     * @return an immutable <code>Set</code> of key purpose OIDs in string
1546     * format (or <code>null</code>)
1547     * @see #setExtendedKeyUsage
1548     */

1549    public Set<String JavaDoc> getExtendedKeyUsage() {
1550    return keyPurposeSet;
1551    }
1552
1553    /**
1554     * Indicates if the <code>X509Certificate</code> must contain all
1555     * or at least one of the subjectAlternativeNames
1556     * specified in the {@link #setSubjectAlternativeNames
1557     * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
1558     * addSubjectAlternativeName} methods. If <code>true</code>,
1559     * the <code>X509Certificate</code> must contain all of the
1560     * specified subject alternative names. If <code>false</code>, the
1561     * <code>X509Certificate</code> must contain at least one of the
1562     * specified subject alternative names.
1563     *
1564     * @return <code>true</code> if the flag is enabled;
1565     * <code>false</code> if the flag is disabled. The flag is
1566     * <code>true</code> by default.
1567     * @see #setMatchAllSubjectAltNames
1568     */

1569    public boolean getMatchAllSubjectAltNames() {
1570    return matchAllSubjectAltNames;
1571    }
1572
1573    /**
1574     * Returns a copy of the subjectAlternativeNames criterion.
1575     * The <code>X509Certificate</code> must contain all or at least one
1576     * of the specified subjectAlternativeNames, depending on the value
1577     * of the matchAllNames flag (see {@link #getMatchAllSubjectAltNames
1578     * getMatchAllSubjectAltNames}). If the value returned is
1579     * <code>null</code>, no subjectAlternativeNames check will be performed.
1580     * <p>
1581     * If the value returned is not <code>null</code>, it is a
1582     * <code>Collection</code> with
1583     * one entry for each name to be included in the subject alternative name
1584     * criterion. Each entry is a <code>List</code> whose first entry is an
1585     * <code>Integer</code> (the name type, 0-8) and whose second
1586     * entry is a <code>String</code> or a byte array (the name, in
1587     * string or ASN.1 DER encoded form, respectively).
1588     * There can be multiple names of the same type. Note that the
1589     * <code>Collection</code> returned may contain duplicate names (same name
1590     * and name type).
1591     * <p>
1592     * Each subject alternative name in the <code>Collection</code>
1593     * may be specified either as a <code>String</code> or as an ASN.1 encoded
1594     * byte array. For more details about the formats used, see
1595     * {@link #addSubjectAlternativeName(int type, String name)
1596     * addSubjectAlternativeName(int type, String name)} and
1597     * {@link #addSubjectAlternativeName(int type, byte [] name)
1598     * addSubjectAlternativeName(int type, byte [] name)}.
1599     * <p>
1600     * Note that a deep copy is performed on the <code>Collection</code> to
1601     * protect against subsequent modifications.
1602     *
1603     * @return a <code>Collection</code> of names (or <code>null</code>)
1604     * @see #setSubjectAlternativeNames
1605     */

1606    public Collection<List<?>> getSubjectAlternativeNames() {
1607    if (subjectAlternativeNames == null) {
1608        return null;
1609    }
1610    return cloneNames(subjectAlternativeNames);
1611    }
1612
1613    /**
1614     * Clone an object of the form passed to
1615     * setSubjectAlternativeNames and setPathToNames.
1616     * Throw a <code>RuntimeException</code> if the argument is malformed.
1617     * <p>
1618     * This method wraps cloneAndCheckNames, changing any
1619     * <code>IOException</code> into a <code>RuntimeException</code>. This
1620     * method should be used when the object being
1621     * cloned has already been checked, so there should never be any exceptions.
1622     *
1623     * @param names a <code>Collection</code> with one entry per name.
1624     * Each entry is a <code>List</code> whose first entry
1625     * is an Integer (the name type, 0-8) and whose second
1626     * entry is a String or a byte array (the name, in
1627     * string or ASN.1 DER encoded form, respectively).
1628     * There can be multiple names of the same type. Null
1629     * is not an acceptable value.
1630     * @return a deep copy of the specified <code>Collection</code>
1631     * @throws RuntimeException if a parsing error occurs
1632     */

1633    private static Set<List<?>> cloneNames(Collection<List<?>> names) {
1634    try {
1635        return cloneAndCheckNames(names);
1636    } catch (IOException JavaDoc e) {
1637        throw new RuntimeException JavaDoc("cloneNames encountered IOException: " +
1638                       e.getMessage());
1639    }
1640    }
1641
1642    /**
1643     * Clone and check an argument of the form passed to
1644     * setSubjectAlternativeNames and setPathToNames.
1645     * Throw an <code>IOException</code> if the argument is malformed.
1646     *
1647     * @param names a <code>Collection</code> with one entry per name.
1648     * Each entry is a <code>List</code> whose first entry
1649     * is an Integer (the name type, 0-8) and whose second
1650     * entry is a String or a byte array (the name, in
1651     * string or ASN.1 DER encoded form, respectively).
1652     * There can be multiple names of the same type.
1653     * <code>null</code> is not an acceptable value.
1654     * @return a deep copy of the specified <code>Collection</code>
1655     * @throws IOException if a parsing error occurs
1656     */

1657    private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException JavaDoc {
1658    // Copy the Lists and Collection
1659
Set<List<?>> namesCopy = new HashSet<List<?>>();
1660    Iterator<List<?>> i = names.iterator();
1661    while (i.hasNext()) {
1662        Object JavaDoc o = i.next();
1663        if (!(o instanceof List)) {
1664        throw new IOException JavaDoc("expected a List");
1665        }
1666        namesCopy.add(new ArrayList<Object JavaDoc>((List<?>)o));
1667    }
1668    
1669    // Check the contents of the Lists and clone any byte arrays
1670
i = namesCopy.iterator();
1671    while (i.hasNext()) {
1672        List<Object JavaDoc> nameList = (List<Object JavaDoc>)i.next();
1673        if (nameList.size() != 2) {
1674        throw new IOException JavaDoc("name list size not 2");
1675        }
1676        Object JavaDoc o = nameList.get(0);
1677        if (!(o instanceof Integer JavaDoc)) {
1678        throw new IOException JavaDoc("expected an Integer");
1679        }
1680        int nameType = ((Integer JavaDoc) o).intValue();
1681        if ((nameType < 0) || (nameType > 8)) {
1682        throw new IOException JavaDoc("name type not 0-8");
1683        }
1684        Object JavaDoc nameObject = nameList.get(1);
1685        if (!(nameObject instanceof byte[]) &&
1686        !(nameObject instanceof String JavaDoc)) {
1687        if (debug != null) {
1688            debug.println("X509CertSelector.cloneAndCheckNames() "
1689                + "name not byte array");
1690        }
1691        throw new IOException JavaDoc("name not byte array or String");
1692        }
1693        if (nameObject instanceof byte[]) {
1694        nameList.set(1, ((byte[]) nameObject).clone());
1695        }
1696    }
1697    return namesCopy;
1698    }
1699
1700    /**
1701     * Returns the name constraints criterion. The <code>X509Certificate</code>
1702     * must have subject and subject alternative names that
1703     * meet the specified name constraints.
1704     * <p>
1705     * The name constraints are returned as a byte array. This byte array
1706     * contains the DER encoded form of the name constraints, as they
1707     * would appear in the NameConstraints structure defined in RFC 2459
1708     * and X.509. The ASN.1 notation for this structure is supplied in the
1709     * documentation for
1710     * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.
1711     * <p>
1712     * Note that the byte array returned is cloned to protect against
1713     * subsequent modifications.
1714     *
1715     * @return a byte array containing the ASN.1 DER encoding of
1716     * a NameConstraints extension used for checking name constraints.
1717     * <code>null</code> if no name constraints check will be performed.
1718     * @see #setNameConstraints
1719     */

1720    public byte[] getNameConstraints() {
1721    if (ncBytes == null) {
1722        return null;
1723    } else {
1724        return (byte[]) ncBytes.clone();
1725    }
1726    }
1727
1728    /**
1729     * Returns the basic constraints constraint. If the value is greater than
1730     * or equal to zero, the <code>X509Certificates</code> must include a
1731     * basicConstraints extension with a pathLen of at least this value.
1732     * If the value is -2, only end-entity certificates are accepted. If
1733     * the value is -1, no basicConstraints check is done.
1734     *
1735     * @return the value for the basic constraints constraint
1736     * @see #setBasicConstraints
1737     */

1738    public int getBasicConstraints() {
1739    return basicConstraints;
1740    }
1741
1742    /**
1743     * Returns the policy criterion. The <code>X509Certificate</code> must
1744     * include at least one of the specified policies in its certificate policies
1745     * extension. If the <code>Set</code> returned is empty, then the
1746     * <code>X509Certificate</code> must include at least some specified policy
1747     * in its certificate policies extension. If the <code>Set</code> returned is
1748     * <code>null</code>, no policy check will be performed.
1749     *
1750     * @return an immutable <code>Set</code> of certificate policy OIDs in
1751     * string format (or <code>null</code>)
1752     * @see #setPolicy
1753     */

1754    public Set<String JavaDoc> getPolicy() {
1755    return policySet;
1756    }
1757
1758    /**
1759     * Returns a copy of the pathToNames criterion. The
1760     * <code>X509Certificate</code> must not include name constraints that would
1761     * prohibit building a path to the specified names. If the value
1762     * returned is <code>null</code>, no pathToNames check will be performed.
1763     * <p>
1764     * If the value returned is not <code>null</code>, it is a
1765     * <code>Collection</code> with one
1766     * entry for each name to be included in the pathToNames
1767     * criterion. Each entry is a <code>List</code> whose first entry is an
1768     * <code>Integer</code> (the name type, 0-8) and whose second
1769     * entry is a <code>String</code> or a byte array (the name, in
1770     * string or ASN.1 DER encoded form, respectively).
1771     * There can be multiple names of the same type. Note that the
1772     * <code>Collection</code> returned may contain duplicate names (same
1773     * name and name type).
1774     * <p>
1775     * Each name in the <code>Collection</code>
1776     * may be specified either as a <code>String</code> or as an ASN.1 encoded
1777     * byte array. For more details about the formats used, see
1778     * {@link #addPathToName(int type, String name)
1779     * addPathToName(int type, String name)} and
1780     * {@link #addPathToName(int type, byte [] name)
1781     * addPathToName(int type, byte [] name)}.
1782     * <p>
1783     * Note that a deep copy is performed on the <code>Collection</code> to
1784     * protect against subsequent modifications.
1785     *
1786     * @return a <code>Collection</code> of names (or <code>null</code>)
1787     * @see #setPathToNames
1788     */

1789    public Collection<List<?>> getPathToNames() {
1790    if (pathToNames == null) {
1791        return null;
1792    }
1793    return cloneNames(pathToNames);
1794    }
1795
1796    /**
1797     * Return a printable representation of the <code>CertSelector</code>.
1798     *
1799     * @return a <code>String</code> describing the contents of the
1800     * <code>CertSelector</code>
1801     */

1802    public String JavaDoc toString() {
1803    StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1804    sb.append("X509CertSelector: [\n");
1805    if (x509Cert != null) {
1806        sb.append(" Certificate: " + x509Cert.toString() + "\n");
1807    }
1808    if (serialNumber != null) {
1809        sb.append(" Serial Number: " + serialNumber.toString() + "\n");
1810    }
1811    if (issuer != null) {
1812        sb.append(" Issuer: " + getIssuerAsString() + "\n");
1813    }
1814    if (subject != null) {
1815        sb.append(" Subject: " + getSubjectAsString() + "\n");
1816    }
1817    sb.append(" matchAllSubjectAltNames flag: "
1818          + String.valueOf(matchAllSubjectAltNames) + "\n");
1819    if (subjectAlternativeNames != null) {
1820        sb.append(" SubjectAlternativeNames:\n");
1821        Iterator i = subjectAlternativeNames.iterator();
1822        while (i.hasNext()) {
1823        List list = (List) i.next();
1824        sb.append(" type " + list.get(0) +
1825              ", name " + list.get(1) + "\n");
1826        }
1827    }
1828    if (subjectKeyID != null) {
1829        HexDumpEncoder enc = new HexDumpEncoder();
1830        sb.append(" Subject Key Identifier: " +
1831              enc.encodeBuffer(subjectKeyID) + "\n");
1832    }
1833    if (authorityKeyID != null) {
1834        HexDumpEncoder enc = new HexDumpEncoder();
1835        sb.append(" Authority Key Identifier: " +
1836              enc.encodeBuffer(authorityKeyID) + "\n");
1837    }
1838    if (certificateValid != null) {
1839        sb.append(" Certificate Valid: " +
1840              certificateValid.toString() + "\n");
1841    }
1842    if (privateKeyValid != null) {
1843        sb.append(" Private Key Valid: " +
1844              privateKeyValid.toString() + "\n");
1845    }
1846    if (subjectPublicKeyAlgID != null) {
1847        sb.append(" Subject Public Key AlgID: " +
1848              subjectPublicKeyAlgID.toString() + "\n");
1849    }
1850    if (subjectPublicKey != null) {
1851        sb.append(" Subject Public Key: " +
1852              subjectPublicKey.toString() + "\n");
1853    }
1854    if (keyUsage != null) {
1855        sb.append(" Key Usage: " + keyUsageToString(keyUsage) + "\n");
1856    }
1857    if (keyPurposeSet != null) {
1858        sb.append(" Extended Key Usage: " +
1859              keyPurposeSet.toString() + "\n");
1860    }
1861    if (policy != null) {
1862        sb.append(" Policy: " + policy.toString() + "\n");
1863    }
1864    if (pathToGeneralNames != null) {
1865        sb.append(" Path to names:\n");
1866        Iterator i = pathToGeneralNames.iterator();
1867        while (i.hasNext()) {
1868        sb.append(" " + i.next() + "\n");
1869        }
1870    }
1871    sb.append("]");
1872    return sb.toString();
1873    }
1874
1875    // Copied from sun.security.x509.KeyUsageExtension
1876
// (without calling the superclass)
1877
/**
1878     * Returns a printable representation of the KeyUsage.
1879     */

1880    private static String JavaDoc keyUsageToString(boolean[] k) {
1881    String JavaDoc s = "KeyUsage [\n";
1882    try {
1883        if (k[0]) {
1884        s += " DigitalSignature\n";
1885        }
1886        if (k[1]) {
1887        s += " Non_repudiation\n";
1888        }
1889        if (k[2]) {
1890        s += " Key_Encipherment\n";
1891        }
1892        if (k[3]) {
1893        s += " Data_Encipherment\n";
1894        }
1895        if (k[4]) {
1896        s += " Key_Agreement\n";
1897        }
1898        if (k[5]) {
1899        s += " Key_CertSign\n";
1900        }
1901        if (k[6]) {
1902        s += " Crl_Sign\n";
1903        }
1904        if (k[7]) {
1905        s += " Encipher_Only\n";
1906        }
1907        if (k[8]) {
1908        s += " Decipher_Only\n";
1909        }
1910    } catch (ArrayIndexOutOfBoundsException JavaDoc ex) {}
1911    
1912    s += "]\n";
1913    
1914    return (s);
1915    }
1916
1917    /**
1918     * Returns an Extension object given any X509Certificate and extension oid.
1919     * Throw an <code>IOException</code> if the extension byte value is
1920     * malformed.
1921     *
1922     * @param cert a <code>X509Certificate</code>
1923     * @param extId an <code>integer</code> which specifies the extension index.
1924     * Currently, the supported extensions are as follows:
1925     * index 0 - PrivateKeyUsageExtension
1926     * index 1 - SubjectAlternativeNameExtension
1927     * index 2 - NameConstraintsExtension
1928     * index 3 - CertificatePoliciesExtension
1929     * index 4 - ExtendedKeyUsageExtension
1930     * @return an <code>Extension</code> object whose real type is as specified
1931     * by the extension oid.
1932     * @throws IOException if cannot construct the <code>Extension</code>
1933     * object with the extension encoding retrieved from the passed in
1934     * <code>X509Certificate</code>.
1935     */

1936    private static Extension getExtensionObject(X509Certificate JavaDoc cert, int extId)
1937        throws IOException JavaDoc {
1938    if (cert instanceof X509CertImpl) {
1939        X509CertImpl impl = (X509CertImpl)cert;
1940        switch (extId) {
1941        case PRIVATE_KEY_USAGE_ID:
1942        return impl.getPrivateKeyUsageExtension();
1943        case SUBJECT_ALT_NAME_ID:
1944        return impl.getSubjectAlternativeNameExtension();
1945        case NAME_CONSTRAINTS_ID:
1946        return impl.getNameConstraintsExtension();
1947        case CERT_POLICIES_ID:
1948        return impl.getCertificatePoliciesExtension();
1949        case EXTENDED_KEY_USAGE_ID:
1950        return impl.getExtendedKeyUsageExtension();
1951        default:
1952        return null;
1953        }
1954    }
1955    byte[] rawExtVal = cert.getExtensionValue(EXTENSION_OIDS[extId]);
1956    if (rawExtVal == null) {
1957        return null;
1958    }
1959    DerInputStream in = new DerInputStream(rawExtVal);
1960    byte[] encoded = in.getOctetString();
1961    switch (extId) {
1962    case PRIVATE_KEY_USAGE_ID:
1963        try {
1964        return new PrivateKeyUsageExtension(FALSE, encoded);
1965        } catch (CertificateException JavaDoc ex) {
1966        throw new IOException JavaDoc(ex.getMessage());
1967        }
1968    case SUBJECT_ALT_NAME_ID:
1969        return new SubjectAlternativeNameExtension(FALSE, encoded);
1970    case NAME_CONSTRAINTS_ID:
1971        return new NameConstraintsExtension(FALSE, encoded);
1972    case CERT_POLICIES_ID:
1973        return new CertificatePoliciesExtension(FALSE, encoded);
1974    case EXTENDED_KEY_USAGE_ID:
1975        return new ExtendedKeyUsageExtension(FALSE, encoded);
1976    default:
1977        return null;
1978    }
1979    }
1980
1981    /**
1982     * Decides whether a <code>Certificate</code> should be selected.
1983     *
1984     * @param cert the <code>Certificate</code> to be checked
1985     * @return <code>true</code> if the <code>Certificate</code> should be
1986     * selected, <code>false</code> otherwise
1987     */

1988    public boolean match(Certificate JavaDoc cert) {
1989    if (!(cert instanceof X509Certificate JavaDoc)) {
1990        return false;
1991    }
1992    X509Certificate JavaDoc xcert = (X509Certificate JavaDoc)cert;
1993    
1994    if (debug != null) {
1995        debug.println("X509CertSelector.match(SN: "
1996        + (xcert.getSerialNumber()).toString(16) + "\n Issuer: "
1997        + xcert.getIssuerDN() + "\n Subject: " + xcert.getSubjectDN()
1998        + ")");
1999    }
2000    
2001    /* match on X509Certificate */
2002    if (x509Cert != null) {
2003        if (!x509Cert.equals(xcert)) {
2004        if (debug != null) {
2005            debug.println("X509CertSelector.match: "
2006                + "certs don't match");
2007        }
2008        return false;
2009        }
2010    }
2011    
2012    /* match on serial number */
2013    if (serialNumber != null) {
2014        if (!serialNumber.equals(xcert.getSerialNumber())) {
2015        if (debug != null) {
2016            debug.println("X509CertSelector.match: "
2017                + "serial numbers don't match");
2018        }
2019        return false;
2020        }
2021    }
2022    
2023    /* match on issuer name */
2024    if (issuer != null) {
2025        if (!issuer.equals(xcert.getIssuerX500Principal())) {
2026        if (debug != null) {
2027            debug.println("X509CertSelector.match: "
2028                + "issuer DNs don't match");
2029        }
2030        return false;
2031        }
2032    }
2033    
2034    /* match on subject name */
2035    if (subject != null) {
2036        if (!subject.equals(xcert.getSubjectX500Principal())) {
2037        if (debug != null) {
2038            debug.println("X509CertSelector.match: "
2039                + "subject DNs don't match");
2040        }
2041        return false;
2042        }
2043    }
2044    
2045    /* match on certificate validity range */
2046    if (certificateValid != null) {
2047        try {
2048        xcert.checkValidity(certificateValid);
2049        } catch (CertificateException JavaDoc e) {
2050        if (debug != null) {
2051            debug.println("X509CertSelector.match: "
2052                + "certificate not within validity period");
2053        }
2054        return false;
2055        }
2056    }
2057    
2058    /* match on subject public key */
2059    if (subjectPublicKeyBytes != null) {
2060        byte[] certKey = xcert.getPublicKey().getEncoded();
2061        if (!Arrays.equals(subjectPublicKeyBytes, certKey)) {
2062        if (debug != null) {
2063            debug.println("X509CertSelector.match: "
2064                + "subject public keys don't match");
2065        }
2066        return false;
2067        }
2068    }
2069    
2070    boolean result = matchBasicConstraints(xcert)
2071              && matchKeyUsage(xcert)
2072              && matchExtendedKeyUsage(xcert)
2073              && matchSubjectKeyID(xcert)
2074              && matchAuthorityKeyID(xcert)
2075              && matchPrivateKeyValid(xcert)
2076              && matchSubjectPublicKeyAlgID(xcert)
2077              && matchPolicy(xcert)
2078              && matchSubjectAlternativeNames(xcert)
2079              && matchPathToNames(xcert)
2080              && matchNameConstraints(xcert);
2081    
2082    if (result && (debug != null)) {
2083        debug.println("X509CertSelector.match returning: true");
2084    }
2085    return result;
2086    }
2087
2088    /* match on subject key identifier extension value */
2089    private boolean matchSubjectKeyID(X509Certificate JavaDoc xcert) {
2090    if (subjectKeyID == null) {
2091        return true;
2092    }
2093    try {
2094        byte[] extVal = xcert.getExtensionValue("2.5.29.14");
2095        if (extVal == null) {
2096        if (debug != null) {
2097            debug.println("X509CertSelector.match: "
2098                + "no subject key ID extension");
2099        }
2100        return false;
2101        }
2102        DerInputStream in = new DerInputStream(extVal);
2103        byte[] certSubjectKeyID = in.getOctetString();
2104        if (certSubjectKeyID == null ||
2105                !Arrays.equals(subjectKeyID, certSubjectKeyID)) {
2106        if (debug != null) {
2107            debug.println("X509CertSelector.match: "
2108                + "subject key IDs don't match");
2109        }
2110        return false;
2111        }
2112    } catch (IOException JavaDoc ex) {
2113        if (debug != null) {
2114        debug.println("X509CertSelector.match: "
2115            + "exception in subject key ID check");
2116        }
2117        return false;
2118    }
2119    return true;
2120    }
2121
2122    /* match on authority key identifier extension value */
2123    private boolean matchAuthorityKeyID(X509Certificate JavaDoc xcert) {
2124    if (authorityKeyID == null) {
2125        return true;
2126    }
2127    try {
2128        byte[] extVal = xcert.getExtensionValue("2.5.29.35");
2129        if (extVal == null) {
2130        if (debug != null) {
2131            debug.println("X509CertSelector.match: "
2132                + "no authority key ID extension");
2133        }
2134        return false;
2135        }
2136        DerInputStream in = new DerInputStream(extVal);
2137        byte[] certAuthKeyID = in.getOctetString();
2138        if (certAuthKeyID == null ||
2139                !Arrays.equals(authorityKeyID, certAuthKeyID)) {
2140        if (debug != null) {
2141            debug.println("X509CertSelector.match: "
2142                + "authority key IDs don't match");
2143        }
2144        return false;
2145        }
2146    } catch (IOException JavaDoc ex) {
2147        if (debug != null) {
2148        debug.println("X509CertSelector.match: "
2149            + "exception in authority key ID check");
2150        }
2151        return false;
2152    }
2153    return true;
2154    }
2155
2156    /* match on private key usage range */
2157    private boolean matchPrivateKeyValid(X509Certificate JavaDoc xcert) {
2158    if (privateKeyValid == null) {
2159        return true;
2160    }
2161    PrivateKeyUsageExtension ext = null;
2162    try {
2163        ext = (PrivateKeyUsageExtension)
2164        getExtensionObject(xcert, PRIVATE_KEY_USAGE_ID);
2165        if (ext != null) {
2166            ext.valid(privateKeyValid);
2167        }
2168    } catch (CertificateExpiredException JavaDoc e1) {
2169        if (debug != null) {
2170            String JavaDoc time = "n/a";
2171        try {
2172            Date notAfter =
2173                (Date)ext.get(PrivateKeyUsageExtension.NOT_AFTER);
2174            time = notAfter.toString();
2175        } catch (CertificateException JavaDoc ex) {
2176            // not able to retrieve notAfter value
2177
}
2178        debug.println("X509CertSelector.match: private key usage not "
2179            + "within validity date; ext.NOT_After: "
2180            + time + "; X509CertSelector: "
2181            + this.toString());
2182        e1.printStackTrace();
2183        }
2184        return false;
2185    } catch (CertificateNotYetValidException JavaDoc e2) {
2186        if (debug != null) {
2187        String JavaDoc time = "n/a";
2188        try {
2189            Date notBefore = (Date)
2190            ext.get(PrivateKeyUsageExtension.NOT_BEFORE);
2191            time = notBefore.toString();
2192        } catch (CertificateException JavaDoc ex) {
2193            // not able to retrieve notBefore value
2194
}
2195        debug.println("X509CertSelector.match: private key usage not "
2196            + "within validity date; ext.NOT_BEFORE: "
2197            + time + "; X509CertSelector: "
2198            + this.toString());
2199        e2.printStackTrace();
2200        }
2201        return false;
2202    } catch (CertificateException JavaDoc e3) {
2203        if (debug != null) {
2204            debug.println("X509CertSelector.match: CertificateException "
2205            + "in private key usage check; X509CertSelector: "
2206            + this.toString());
2207            e3.printStackTrace();
2208        }
2209        return false;
2210    } catch (IOException JavaDoc e4) {
2211        if (debug != null) {
2212            debug.println("X509CertSelector.match: IOException in "
2213            + "private key usage check; X509CertSelector: "
2214            + this.toString());
2215            e4.printStackTrace();
2216        }
2217        return false;
2218    }
2219    return true;
2220    }
2221
2222    /* match on subject public key algorithm OID */
2223    private boolean matchSubjectPublicKeyAlgID(X509Certificate JavaDoc xcert) {
2224    if (subjectPublicKeyAlgID == null) {
2225        return true;
2226    }
2227    try {
2228        byte[] encodedKey = xcert.getPublicKey().getEncoded();
2229        DerValue val = new DerValue(encodedKey);
2230        if (val.tag != DerValue.tag_Sequence) {
2231        throw new IOException JavaDoc("invalid key format");
2232        }
2233  
2234        AlgorithmId algID = AlgorithmId.parse(val.data.getDerValue());
2235        if (debug != null) {
2236        debug.println("X509CertSelector.match: subjectPublicKeyAlgID = "
2237            + subjectPublicKeyAlgID + ", xcert subjectPublicKeyAlgID = "
2238            + algID.getOID());
2239        }
2240        if (!subjectPublicKeyAlgID.equals(algID.getOID())) {
2241        if (debug != null) {
2242            debug.println("X509CertSelector.match: "
2243                + "subject public key alg IDs don't match");
2244        }
2245        return false;
2246        }
2247    } catch (IOException JavaDoc e5) {
2248        if (debug != null) {
2249        debug.println("X509CertSelector.match: IOException in subject "
2250            + "public key algorithm OID check");
2251        }
2252        return false;
2253    }
2254    return true;
2255    }
2256    
2257    /* match on key usage extension value */
2258    private boolean matchKeyUsage(X509Certificate JavaDoc xcert) {
2259    if (keyUsage == null) {
2260        return true;
2261    }
2262    boolean[] certKeyUsage = xcert.getKeyUsage();
2263    if (certKeyUsage != null) {
2264        for (int keyBit = 0; keyBit < keyUsage.length; keyBit++) {
2265        if (keyUsage[keyBit] &&
2266            ((keyBit >= certKeyUsage.length) || !certKeyUsage[keyBit])) {
2267            if (debug != null) {
2268            debug.println("X509CertSelector.match: "
2269                + "key usage bits don't match");
2270            }
2271            return false;
2272        }
2273        }
2274    }
2275    return true;
2276    }
2277    
2278    /* match on extended key usage purpose OIDs */
2279    private boolean matchExtendedKeyUsage(X509Certificate JavaDoc xcert) {
2280    if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
2281        return true;
2282    }
2283    try {
2284        ExtendedKeyUsageExtension ext =
2285        (ExtendedKeyUsageExtension)getExtensionObject(xcert,
2286                        EXTENDED_KEY_USAGE_ID);
2287        if (ext != null) {
2288        Vector<ObjectIdentifier> certKeyPurposeVector =
2289            (Vector<ObjectIdentifier>)ext.get(ExtendedKeyUsageExtension.USAGES);
2290        if (!certKeyPurposeVector.contains(ANY_EXTENDED_KEY_USAGE)
2291                && !certKeyPurposeVector.containsAll(keyPurposeOIDSet)) {
2292            if (debug != null) {
2293            debug.println("X509CertSelector.match: cert failed "
2294                + "extendedKeyUsage criterion");
2295            }
2296            return false;
2297        }
2298        }
2299    } catch (IOException JavaDoc ex) {
2300        if (debug != null) {
2301        debug.println("X509CertSelector.match: "
2302            + "IOException in extended key usage check");
2303        }
2304        return false;
2305    }
2306    return true;
2307    }
2308    
2309    /* match on subject alternative name extension names */
2310    private boolean matchSubjectAlternativeNames(X509Certificate JavaDoc xcert) {
2311    if ((subjectAlternativeNames == null) || subjectAlternativeNames.isEmpty()) {
2312        return true;
2313    }
2314    try {
2315        SubjectAlternativeNameExtension sanExt =
2316        (SubjectAlternativeNameExtension) getExtensionObject(xcert,
2317                              SUBJECT_ALT_NAME_ID);
2318        if (sanExt == null) {
2319        if (debug != null) {
2320          debug.println("X509CertSelector.match: "
2321              + "no subject alternative name extension");
2322        }
2323        return false;
2324        }
2325        GeneralNames certNames = (GeneralNames)
2326        sanExt.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
2327        Iterator i = subjectAlternativeGeneralNames.iterator();
2328        while (i.hasNext()) {
2329        GeneralNameInterface matchName = (GeneralNameInterface) i.next();
2330        boolean found = false;
2331        for (Iterator t = certNames.iterator(); t.hasNext() && !found; ) {
2332            GeneralNameInterface certName =
2333            ((GeneralName)t.next()).getName();
2334            found = certName.equals(matchName);
2335        }
2336        if (!found && (matchAllSubjectAltNames || !i.hasNext())) {
2337            if (debug != null) {
2338              debug.println("X509CertSelector.match: subject alternative "
2339              + "name " + matchName + " not found");
2340            }
2341            return false;
2342        } else if (found && !matchAllSubjectAltNames) {
2343            break;
2344        }
2345        }
2346    } catch (IOException JavaDoc ex) {
2347        if (debug != null)
2348        debug.println("X509CertSelector.match: IOException in subject "
2349            + "alternative name check");
2350        return false;
2351    }
2352    return true;
2353    }
2354    
2355    /* match on name constraints */
2356    private boolean matchNameConstraints(X509Certificate JavaDoc xcert) {
2357    if (nc == null) {
2358        return true;
2359    }
2360    try {
2361        if (!nc.verify(xcert)) {
2362        if (debug != null) {
2363            debug.println("X509CertSelector.match: "
2364                + "name constraints not satisfied");
2365        }
2366        return false;
2367        }
2368    } catch (IOException JavaDoc e) {
2369        if (debug != null) {
2370        debug.println("X509CertSelector.match: "
2371            + "IOException in name constraints check");
2372        }
2373        return false;
2374    }
2375    return true;
2376    }
2377    
2378    /* match on policy OIDs */
2379    private boolean matchPolicy(X509Certificate JavaDoc xcert) {
2380    if (policy == null) {
2381        return true;
2382    }
2383    try {
2384        CertificatePoliciesExtension ext = (CertificatePoliciesExtension)
2385            getExtensionObject(xcert, CERT_POLICIES_ID);
2386        if (ext == null) {
2387        if (debug != null) {
2388          debug.println("X509CertSelector.match: "
2389              + "no certificate policy extension");
2390        }
2391        return false;
2392        }
2393        List<PolicyInformation> policies = (List<PolicyInformation>)ext.get(CertificatePoliciesExtension.POLICIES);
2394        /*
2395         * Convert the Vector of PolicyInformation to a Vector
2396         * of CertificatePolicyIds for easier comparison.
2397         */

2398        List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(policies.size());
2399        for (PolicyInformation info : policies) {
2400        policyIDs.add(info.getPolicyIdentifier());
2401        }
2402        if (policy != null) {
2403        boolean foundOne = false;
2404        /*
2405         * if the user passes in an empty policy Set, then
2406         * we just want to make sure that the candidate certificate
2407         * has some policy OID in its CertPoliciesExtension
2408         */

2409        if (policy.getCertPolicyIds().isEmpty()) {
2410            if (policyIDs.isEmpty()) {
2411            if (debug != null) {
2412                debug.println("X509CertSelector.match: "
2413                    + "cert failed policyAny criterion");
2414            }
2415            return false;
2416            }
2417        } else {
2418            for (CertificatePolicyId id : policy.getCertPolicyIds()) {
2419            if (policyIDs.contains(id)) {
2420                foundOne = true;
2421                break;
2422            }
2423            }
2424            if (!foundOne) {
2425            if (debug != null) {
2426                debug.println("X509CertSelector.match: "
2427                    + "cert failed policyAny criterion");
2428            }
2429            return false;
2430            }
2431        }
2432        }
2433    } catch (IOException JavaDoc ex) {
2434        if (debug != null) {
2435            debug.println("X509CertSelector.match: "
2436            + "IOException in certificate policy ID check");
2437        }
2438        return false;
2439    }
2440    return true;
2441    }
2442    
2443    /* match on pathToNames */
2444    private boolean matchPathToNames(X509Certificate JavaDoc xcert) {
2445    if (pathToGeneralNames == null) {
2446        return true;
2447    }
2448    try {
2449        NameConstraintsExtension ext = (NameConstraintsExtension)
2450            getExtensionObject(xcert, NAME_CONSTRAINTS_ID);
2451        if (ext == null) {
2452        return true;
2453        }
2454        if ((debug != null) && debug.isOn("certpath")) {
2455        debug.println("X509CertSelector.match pathToNames:\n");
2456        Iterator i = pathToGeneralNames.iterator();
2457        while (i.hasNext()) {
2458            debug.println(" " + i.next() + "\n");
2459        }
2460        }
2461    
2462        GeneralSubtrees permitted = (GeneralSubtrees)
2463        ext.get(NameConstraintsExtension.PERMITTED_SUBTREES);
2464        GeneralSubtrees excluded = (GeneralSubtrees)
2465        ext.get(NameConstraintsExtension.EXCLUDED_SUBTREES);
2466        if (excluded != null) {
2467        if (matchExcluded(excluded) == false) {
2468            return false;
2469        }
2470        }
2471        if (permitted != null) {
2472        if (matchPermitted(permitted) == false) {
2473            return false;
2474        }
2475        }
2476    } catch (IOException JavaDoc ex) {
2477        if (debug != null) {
2478        debug.println("X509CertSelector.match: "
2479            + "IOException in name constraints check");
2480        }
2481        return false;
2482    }
2483    return true;
2484    }
2485   
2486    private boolean matchExcluded(GeneralSubtrees excluded) {
2487    /*
2488     * Enumerate through excluded and compare each entry
2489     * to all pathToNames. If any pathToName is within any of the
2490     * subtrees listed in excluded, return false.
2491     */

2492    for (Iterator t = excluded.iterator(); t.hasNext(); ) {
2493        GeneralSubtree tree = (GeneralSubtree)t.next();
2494        GeneralNameInterface excludedName = tree.getName().getName();
2495        Iterator i = pathToGeneralNames.iterator();
2496        while (i.hasNext()) {
2497        GeneralNameInterface pathToName = (GeneralNameInterface) i.next();
2498        if (excludedName.getType() == pathToName.getType()) {
2499            switch (pathToName.constrains(excludedName)) {
2500            case GeneralNameInterface.NAME_WIDENS:
2501            case GeneralNameInterface.NAME_MATCH:
2502            if (debug != null) {
2503                debug.println("X509CertSelector.match: name constraints "
2504                + "inhibit path to specified name");
2505                debug.println("X509CertSelector.match: excluded name: " +
2506                pathToName);
2507            }
2508            return false;
2509            default:
2510            }
2511        }
2512        }
2513    }
2514    return true;
2515    }
2516    
2517    private boolean matchPermitted(GeneralSubtrees permitted) {
2518    /*
2519     * Enumerate through pathToNames, checking that each pathToName
2520     * is in at least one of the subtrees listed in permitted.
2521     * If not, return false. However, if no subtrees of a given type
2522     * are listed, all names of that type are permitted.
2523     */

2524    Iterator i = pathToGeneralNames.iterator();
2525    while (i.hasNext()) {
2526        GeneralNameInterface pathToName = (GeneralNameInterface)i.next();
2527        Iterator t = permitted.iterator();
2528        boolean permittedNameFound = false;
2529        boolean nameTypeFound = false;
2530        String JavaDoc names = "";
2531        while (t.hasNext() && !permittedNameFound) {
2532        GeneralSubtree tree = (GeneralSubtree)t.next();
2533        GeneralNameInterface permittedName = tree.getName().getName();
2534        if (permittedName.getType() == pathToName.getType()) {
2535            nameTypeFound = true;
2536            names = names + " " + permittedName;
2537            switch (pathToName.constrains(permittedName)) {
2538            case GeneralNameInterface.NAME_WIDENS:
2539            case GeneralNameInterface.NAME_MATCH:
2540            permittedNameFound = true;
2541            break;
2542            default:
2543            }
2544        }
2545        }
2546        if (!permittedNameFound && nameTypeFound) {
2547        if (debug != null)
2548          debug.println("X509CertSelector.match: " +
2549                "name constraints inhibit path to specified name; " +
2550                "permitted names of type " + pathToName.getType() +
2551                ": " + names);
2552        return false;
2553        }
2554    }
2555    return true;
2556    }
2557    
2558    /* match on basic constraints */
2559    private boolean matchBasicConstraints(X509Certificate JavaDoc xcert) {
2560    if (basicConstraints == -1) {
2561        return true;
2562    }
2563    int maxPathLen = xcert.getBasicConstraints();
2564    if (basicConstraints == -2) {
2565        if (maxPathLen != -1) {
2566        if (debug != null) {
2567            debug.println("X509CertSelector.match: not an EE cert");
2568        }
2569        return false;
2570        }
2571    } else {
2572        if (maxPathLen < basicConstraints) {
2573        if (debug != null) {
2574            debug.println("X509CertSelector.match: maxPathLen too small ("
2575            + maxPathLen + " < " + basicConstraints + ")");
2576        }
2577        return false;
2578        }
2579    }
2580    return true;
2581    }
2582  
2583    private static Set<?> cloneSet(Set<?> set) {
2584    if (set instanceof HashSet) {
2585        Object JavaDoc clone = ((HashSet<?>)set).clone();
2586        return (Set<?>)clone;
2587    } else {
2588        return new HashSet<Object JavaDoc>(set);
2589    }
2590    }
2591
2592    /**
2593     * Returns a copy of this object.
2594     *
2595     * @return the copy
2596     */

2597    public Object JavaDoc clone() {
2598    try {
2599        X509CertSelector JavaDoc copy = (X509CertSelector JavaDoc)super.clone();
2600        // Must clone these because addPathToName et al. modify them
2601
if (subjectAlternativeNames != null) {
2602        copy.subjectAlternativeNames =
2603            (Set<List<?>>)cloneSet(subjectAlternativeNames);
2604        copy.subjectAlternativeGeneralNames =
2605            (Set<GeneralNameInterface>)cloneSet
2606                (subjectAlternativeGeneralNames);
2607        }
2608        if (pathToGeneralNames != null) {
2609        copy.pathToNames =
2610            (Set<List<?>>)cloneSet(pathToNames);
2611        copy.pathToGeneralNames =
2612            (Set<GeneralNameInterface>)cloneSet
2613                (pathToGeneralNames);
2614        }
2615        return copy;
2616    } catch (CloneNotSupportedException JavaDoc e) {
2617        /* Cannot happen */
2618        throw new InternalError JavaDoc(e.toString());
2619    }
2620    }
2621}
2622
Popular Tags