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