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