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