1 /*
2 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
260 * ....
261 * DirectoryString ::= CHOICE {
262 * teletexString TeletexString (SIZE (1..MAX)),
263 * printableString PrintableString (SIZE (1..MAX)),
264 * universalString UniversalString (SIZE (1..MAX)),
265 * utf8String UTF8String (SIZE (1.. MAX)),
266 * bmpString BMPString (SIZE (1..MAX)) }
267 * </code></pre>
268 * <p>
269 * Note that the byte array specified here is cloned to protect against
270 * subsequent modifications.
271 *
272 * @param issuerDN a byte array containing the distinguished name
273 * in ASN.1 DER encoded form (or <code>null</code>)
274 * @throws IOException if an encoding error occurs (incorrect form for DN)
275 */
276 public void setIssuer(byte[] issuerDN) throws IOException {
277 try {
278 issuer = (issuerDN == null ? null : new X500Principal(issuerDN));
279 } catch (IllegalArgumentException e) {
280 throw (IOException)new IOException("Invalid name").initCause(e);
281 }
282 }
283
284 /**
285 * Sets the subject criterion. The specified distinguished name
286 * must match the subject distinguished name in the
287 * <code>X509Certificate</code>. If <code>null</code>, any subject
288 * distinguished name will do.
289 *
290 * @param subject a distinguished name as X500Principal
291 * (or <code>null</code>)
292 * @since 1.5
293 */
294 public void setSubject(X500Principal subject) {
295 this.subject = subject;
296 }
297
298 /**
299 * <strong>Denigrated</strong>, use {@linkplain #setSubject(X500Principal)}
300 * or {@linkplain #setSubject(byte[])} instead. This method should not be
324
325 /**
326 * Sets the subject criterion. The specified distinguished name
327 * must match the subject distinguished name in the
328 * <code>X509Certificate</code>. If <code>null</code>, any subject
329 * distinguished name will do.
330 * <p>
331 * If <code>subjectDN</code> is not <code>null</code>, it should contain a
332 * single DER encoded distinguished name, as defined in X.501. For the ASN.1
333 * notation for this structure, see
334 * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
335 *
336 * @param subjectDN a byte array containing the distinguished name in
337 * ASN.1 DER format (or <code>null</code>)
338 * @throws IOException if an encoding error occurs (incorrect form for DN)
339 */
340 public void setSubject(byte[] subjectDN) throws IOException {
341 try {
342 subject = (subjectDN == null ? null : new X500Principal(subjectDN));
343 } catch (IllegalArgumentException e) {
344 throw (IOException)new IOException("Invalid name").initCause(e);
345 }
346 }
347
348 /**
349 * Sets the subjectKeyIdentifier criterion. The
350 * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
351 * extension for which the contents of the extension
352 * matches the specified criterion value.
353 * If the criterion value is <code>null</code>, no
354 * subjectKeyIdentifier check will be done.
355 * <p>
356 * If <code>subjectKeyID</code> is not <code>null</code>, it
357 * should contain a single DER encoded value corresponding to the contents
358 * of the extension value (not including the object identifier,
359 * criticality setting, and encapsulating OCTET STRING)
360 * for a SubjectKeyIdentifier extension.
361 * The ASN.1 notation for this structure follows.
362 * <p>
363 * <pre><code>
364 * SubjectKeyIdentifier ::= KeyIdentifier
365 *
366 * KeyIdentifier ::= OCTET STRING
367 * </code></pre>
368 * <p>
369 * Since the format of subject key identifiers is not mandated by
370 * any standard, subject key identifiers are not parsed by the
371 * <code>X509CertSelector</code>. Instead, the values are compared using
372 * a byte-by-byte comparison.
373 * <p>
374 * Note that the byte array supplied here is cloned to protect against
375 * subsequent modifications.
376 *
377 * @param subjectKeyID the subject key identifier (or <code>null</code>)
378 * @see #getSubjectKeyIdentifier
379 */
380 public void setSubjectKeyIdentifier(byte[] subjectKeyID) {
381 if (subjectKeyID == null) {
382 this.subjectKeyID = null;
383 } else {
384 this.subjectKeyID = (byte[])subjectKeyID.clone();
385 }
386 }
387
388 /**
389 * Sets the authorityKeyIdentifier criterion. The
390 * <code>X509Certificate</code> must contain an
391 * AuthorityKeyIdentifier extension for which the contents of the
392 * extension value matches the specified criterion value.
393 * If the criterion value is <code>null</code>, no
394 * authorityKeyIdentifier check will be done.
395 * <p>
396 * If <code>authorityKeyID</code> is not <code>null</code>, it
397 * should contain a single DER encoded value corresponding to the contents
398 * of the extension value (not including the object identifier,
399 * criticality setting, and encapsulating OCTET STRING)
400 * for an AuthorityKeyIdentifier extension.
401 * The ASN.1 notation for this structure follows.
402 * <p>
403 * <pre><code>
404 * AuthorityKeyIdentifier ::= SEQUENCE {
425 * KeyIdentifier, GeneralNames, and CertificateSerialNumber.
426 * In order to use the extension value of the issuer certificate's
427 * <code>SubjectKeyIdentifier</code>
428 * extension, it will be necessary to extract the value of the embedded
429 * <code>KeyIdentifier</code> OCTET STRING, then DER encode this OCTET
430 * STRING inside a SEQUENCE.
431 * For more details on SubjectKeyIdentifier, see
432 * {@link #setSubjectKeyIdentifier(byte[] subjectKeyID)}.
433 * <p>
434 * Note also that the byte array supplied here is cloned to protect against
435 * subsequent modifications.
436 *
437 * @param authorityKeyID the authority key identifier
438 * (or <code>null</code>)
439 * @see #getAuthorityKeyIdentifier
440 */
441 public void setAuthorityKeyIdentifier(byte[] authorityKeyID) {
442 if (authorityKeyID == null) {
443 this.authorityKeyID = null;
444 } else {
445 this.authorityKeyID = (byte[])authorityKeyID.clone();
446 }
447 }
448
449 /**
450 * Sets the certificateValid criterion. The specified date must fall
451 * within the certificate validity period for the
452 * <code>X509Certificate</code>. If <code>null</code>, no certificateValid
453 * check will be done.
454 * <p>
455 * Note that the <code>Date</code> supplied here is cloned to protect
456 * against subsequent modifications.
457 *
458 * @param certValid the <code>Date</code> to check (or <code>null</code>)
459 * @see #getCertificateValid
460 */
461 public void setCertificateValid(Date certValid) {
462 if (certValid == null) {
463 certificateValid = null;
464 } else {
465 certificateValid = (Date)certValid.clone();
549 * parameters ANY DEFINED BY algorithm OPTIONAL }
550 * -- contains a value of the type
551 * -- registered for use with the
552 * -- algorithm object identifier value
553 * </code></pre>
554 * <p>
555 * Note that the byte array supplied here is cloned to protect against
556 * subsequent modifications.
557 *
558 * @param key a byte array containing the subject public key in ASN.1 DER
559 * form (or <code>null</code>)
560 * @throws IOException if an encoding error occurs (incorrect form for
561 * subject public key)
562 * @see #getSubjectPublicKey
563 */
564 public void setSubjectPublicKey(byte[] key) throws IOException {
565 if (key == null) {
566 subjectPublicKey = null;
567 subjectPublicKeyBytes = null;
568 } else {
569 subjectPublicKeyBytes = (byte[])key.clone();
570 subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes));
571 }
572 }
573
574 /**
575 * Sets the keyUsage criterion. The <code>X509Certificate</code>
576 * must allow the specified keyUsage values. If <code>null</code>, no
577 * keyUsage check will be done. Note that an <code>X509Certificate</code>
578 * that has no keyUsage extension implicitly allows all keyUsage values.
579 * <p>
580 * Note that the boolean array supplied here is cloned to protect against
581 * subsequent modifications.
582 *
583 * @param keyUsage a boolean array in the same format as the boolean
584 * array returned by
585 * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
586 * Or <code>null</code>.
587 * @see #getKeyUsage
588 */
589 public void setKeyUsage(boolean[] keyUsage) {
590 if (keyUsage == null) {
591 this.keyUsage = null;
592 } else {
593 this.keyUsage = (boolean[])keyUsage.clone();
594 }
595 }
596
597 /**
598 * Sets the extendedKeyUsage criterion. The <code>X509Certificate</code>
599 * must allow the specified key purposes in its extended key usage
600 * extension. If <code>keyPurposeSet</code> is empty or <code>null</code>,
601 * no extendedKeyUsage check will be done. Note that an
602 * <code>X509Certificate</code> that has no extendedKeyUsage extension
603 * implicitly allows all key purposes.
604 * <p>
605 * Note that the <code>Set</code> is cloned to protect against
606 * subsequent modifications.
607 *
608 * @param keyPurposeSet a <code>Set</code> of key purpose OIDs in string
609 * format (or <code>null</code>). Each OID is represented by a set of
610 * nonnegative integers separated by periods.
611 * @throws IOException if the OID is invalid, such as
612 * the first component being not 0, 1 or 2 or the second component
613 * being greater than 39.
855 throw new IOException("expected an Integer");
856 }
857 int nameType = ((Integer)o).intValue();
858 o = nameList.get(1);
859 genNames.add(makeGeneralNameInterface(nameType, o));
860 }
861
862 return genNames;
863 }
864
865 /**
866 * Compare for equality two objects of the form passed to
867 * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames).
868 * Throw an <code>IllegalArgumentException</code> or a
869 * <code>ClassCastException</code> if one of the objects is malformed.
870 *
871 * @param object1 a Collection containing the first object to compare
872 * @param object2 a Collection containing the second object to compare
873 * @return true if the objects are equal, false otherwise
874 */
875 static boolean equalNames(Collection object1, Collection object2) {
876 if ((object1 == null) || (object2 == null)) {
877 return object1 == object2;
878 }
879 return object1.equals(object2);
880 }
881
882 /**
883 * Make a <code>GeneralNameInterface</code> out of a name type (0-8) and an
884 * Object that may be a byte array holding the ASN.1 DER encoded
885 * name or a String form of the name. Except for X.509
886 * Distinguished Names, the String form of the name must not be the
887 * result from calling toString on an existing GeneralNameInterface
888 * implementing class. The output of toString is not compatible
889 * with the String constructors for names other than Distinguished
890 * Names.
891 *
892 * @param type name type (0-8)
893 * @param name name as ASN.1 Der-encoded byte array or String
894 * @return a GeneralNameInterface name
895 * @throws IOException if a parsing error occurs
1024 * registeredID [8] OBJECT IDENTIFIER}
1025 * </code></pre>
1026 * <p>
1027 * Note that the byte array supplied here is cloned to protect against
1028 * subsequent modifications.
1029 *
1030 * @param bytes a byte array containing the ASN.1 DER encoding of
1031 * a NameConstraints extension to be used for checking
1032 * name constraints. Only the value of the extension is
1033 * included, not the OID or criticality flag. Can be
1034 * <code>null</code>,
1035 * in which case no name constraints check will be performed.
1036 * @throws IOException if a parsing error occurs
1037 * @see #getNameConstraints
1038 */
1039 public void setNameConstraints(byte[] bytes) throws IOException {
1040 if (bytes == null) {
1041 ncBytes = null;
1042 nc = null;
1043 } else {
1044 ncBytes = (byte[])bytes.clone();
1045 nc = new NameConstraintsExtension(FALSE, bytes);
1046 }
1047 }
1048
1049 /**
1050 * Sets the basic constraints constraint. If the value is greater than or
1051 * equal to zero, <code>X509Certificates</code> must include a
1052 * basicConstraints extension with
1053 * a pathLen of at least this value. If the value is -2, only end-entity
1054 * certificates are accepted. If the value is -1, no check is done.
1055 * <p>
1056 * This constraint is useful when building a certification path forward
1057 * (from the target toward the trust anchor. If a partial path has been
1058 * built, any candidate certificate must have a maxPathLen value greater
1059 * than or equal to the number of certificates in the partial path.
1060 *
1061 * @param minMaxPathLen the value for the basic constraints constraint
1062 * @throws IllegalArgumentException if the value is less than -2
1063 * @see #getBasicConstraints
1064 */
1421 public byte[] getSubjectAsBytes() throws IOException {
1422 return (subject == null ? null : subject.getEncoded());
1423 }
1424
1425 /**
1426 * Returns the subjectKeyIdentifier criterion. The
1427 * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
1428 * extension with the specified value. If <code>null</code>, no
1429 * subjectKeyIdentifier check will be done.
1430 * <p>
1431 * Note that the byte array returned is cloned to protect against
1432 * subsequent modifications.
1433 *
1434 * @return the key identifier (or <code>null</code>)
1435 * @see #setSubjectKeyIdentifier
1436 */
1437 public byte[] getSubjectKeyIdentifier() {
1438 if (subjectKeyID == null) {
1439 return null;
1440 }
1441 return (byte[])subjectKeyID.clone();
1442 }
1443
1444 /**
1445 * Returns the authorityKeyIdentifier criterion. The
1446 * <code>X509Certificate</code> must contain a AuthorityKeyIdentifier
1447 * extension with the specified value. If <code>null</code>, no
1448 * authorityKeyIdentifier check will be done.
1449 * <p>
1450 * Note that the byte array returned is cloned to protect against
1451 * subsequent modifications.
1452 *
1453 * @return the key identifier (or <code>null</code>)
1454 * @see #setAuthorityKeyIdentifier
1455 */
1456 public byte[] getAuthorityKeyIdentifier() {
1457 if (authorityKeyID == null) {
1458 return null;
1459 }
1460 return (byte[])authorityKeyID.clone();
1461 }
1462
1463 /**
1464 * Returns the certificateValid criterion. The specified date must fall
1465 * within the certificate validity period for the
1466 * <code>X509Certificate</code>. If <code>null</code>, no certificateValid
1467 * check will be done.
1468 * <p>
1469 * Note that the <code>Date</code> returned is cloned to protect against
1470 * subsequent modifications.
1471 *
1472 * @return the <code>Date</code> to check (or <code>null</code>)
1473 * @see #setCertificateValid
1474 */
1475 public Date getCertificateValid() {
1476 if (certificateValid == null) {
1477 return null;
1478 }
1479 return (Date)certificateValid.clone();
1480 }
1529 }
1530
1531 /**
1532 * Returns the keyUsage criterion. The <code>X509Certificate</code>
1533 * must allow the specified keyUsage values. If null, no keyUsage
1534 * check will be done.
1535 * <p>
1536 * Note that the boolean array returned is cloned to protect against
1537 * subsequent modifications.
1538 *
1539 * @return a boolean array in the same format as the boolean
1540 * array returned by
1541 * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
1542 * Or <code>null</code>.
1543 * @see #setKeyUsage
1544 */
1545 public boolean[] getKeyUsage() {
1546 if (keyUsage == null) {
1547 return null;
1548 }
1549 return (boolean[])keyUsage.clone();
1550 }
1551
1552 /**
1553 * Returns the extendedKeyUsage criterion. The <code>X509Certificate</code>
1554 * must allow the specified key purposes in its extended key usage
1555 * extension. If the <code>keyPurposeSet</code> returned is empty or
1556 * <code>null</code>, no extendedKeyUsage check will be done. Note that an
1557 * <code>X509Certificate</code> that has no extendedKeyUsage extension
1558 * implicitly allows all key purposes.
1559 *
1560 * @return an immutable <code>Set</code> of key purpose OIDs in string
1561 * format (or <code>null</code>)
1562 * @see #setExtendedKeyUsage
1563 */
1564 public Set<String> getExtendedKeyUsage() {
1565 return keyPurposeSet;
1566 }
1567
1568 /**
1569 * Indicates if the <code>X509Certificate</code> must contain all
1655 }
1656
1657 /**
1658 * Clone and check an argument of the form passed to
1659 * setSubjectAlternativeNames and setPathToNames.
1660 * Throw an <code>IOException</code> if the argument is malformed.
1661 *
1662 * @param names a <code>Collection</code> with one entry per name.
1663 * Each entry is a <code>List</code> whose first entry
1664 * is an Integer (the name type, 0-8) and whose second
1665 * entry is a String or a byte array (the name, in
1666 * string or ASN.1 DER encoded form, respectively).
1667 * There can be multiple names of the same type.
1668 * <code>null</code> is not an acceptable value.
1669 * @return a deep copy of the specified <code>Collection</code>
1670 * @throws IOException if a parsing error occurs
1671 */
1672 private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException {
1673 // Copy the Lists and Collection
1674 Set<List<?>> namesCopy = new HashSet<List<?>>();
1675 Iterator<List<?>> i = names.iterator();
1676 while (i.hasNext()) {
1677 Object o = i.next();
1678 if (!(o instanceof List)) {
1679 throw new IOException("expected a List");
1680 }
1681 namesCopy.add(new ArrayList<Object>((List<?>)o));
1682 }
1683
1684 // Check the contents of the Lists and clone any byte arrays
1685 i = namesCopy.iterator();
1686 while (i.hasNext()) {
1687 List<Object> nameList = (List<Object>)i.next();
1688 if (nameList.size() != 2) {
1689 throw new IOException("name list size not 2");
1690 }
1691 Object o = nameList.get(0);
1692 if (!(o instanceof Integer)) {
1693 throw new IOException("expected an Integer");
1694 }
1695 int nameType = ((Integer)o).intValue();
1696 if ((nameType < 0) || (nameType > 8)) {
1697 throw new IOException("name type not 0-8");
1698 }
1699 Object nameObject = nameList.get(1);
1700 if (!(nameObject instanceof byte[]) &&
1701 !(nameObject instanceof String)) {
1702 if (debug != null) {
1703 debug.println("X509CertSelector.cloneAndCheckNames() "
1704 + "name not byte array");
1705 }
1706 throw new IOException("name not byte array or String");
1707 }
1719 * <p>
1720 * The name constraints are returned as a byte array. This byte array
1721 * contains the DER encoded form of the name constraints, as they
1722 * would appear in the NameConstraints structure defined in RFC 3280
1723 * and X.509. The ASN.1 notation for this structure is supplied in the
1724 * documentation for
1725 * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.
1726 * <p>
1727 * Note that the byte array returned is cloned to protect against
1728 * subsequent modifications.
1729 *
1730 * @return a byte array containing the ASN.1 DER encoding of
1731 * a NameConstraints extension used for checking name constraints.
1732 * <code>null</code> if no name constraints check will be performed.
1733 * @see #setNameConstraints
1734 */
1735 public byte[] getNameConstraints() {
1736 if (ncBytes == null) {
1737 return null;
1738 } else {
1739 return (byte[]) ncBytes.clone();
1740 }
1741 }
1742
1743 /**
1744 * Returns the basic constraints constraint. If the value is greater than
1745 * or equal to zero, the <code>X509Certificates</code> must include a
1746 * basicConstraints extension with a pathLen of at least this value.
1747 * If the value is -2, only end-entity certificates are accepted. If
1748 * the value is -1, no basicConstraints check is done.
1749 *
1750 * @return the value for the basic constraints constraint
1751 * @see #setBasicConstraints
1752 */
1753 public int getBasicConstraints() {
1754 return basicConstraints;
1755 }
1756
1757 /**
1758 * Returns the policy criterion. The <code>X509Certificate</code> must
1759 * include at least one of the specified policies in its certificate policies
2167 }
2168 return true;
2169 }
2170
2171 /* match on private key usage range */
2172 private boolean matchPrivateKeyValid(X509Certificate xcert) {
2173 if (privateKeyValid == null) {
2174 return true;
2175 }
2176 PrivateKeyUsageExtension ext = null;
2177 try {
2178 ext = (PrivateKeyUsageExtension)
2179 getExtensionObject(xcert, PRIVATE_KEY_USAGE_ID);
2180 if (ext != null) {
2181 ext.valid(privateKeyValid);
2182 }
2183 } catch (CertificateExpiredException e1) {
2184 if (debug != null) {
2185 String time = "n/a";
2186 try {
2187 Date notAfter =
2188 (Date)ext.get(PrivateKeyUsageExtension.NOT_AFTER);
2189 time = notAfter.toString();
2190 } catch (CertificateException ex) {
2191 // not able to retrieve notAfter value
2192 }
2193 debug.println("X509CertSelector.match: private key usage not "
2194 + "within validity date; ext.NOT_After: "
2195 + time + "; X509CertSelector: "
2196 + this.toString());
2197 e1.printStackTrace();
2198 }
2199 return false;
2200 } catch (CertificateNotYetValidException e2) {
2201 if (debug != null) {
2202 String time = "n/a";
2203 try {
2204 Date notBefore = (Date)
2205 ext.get(PrivateKeyUsageExtension.NOT_BEFORE);
2206 time = notBefore.toString();
2207 } catch (CertificateException ex) {
2208 // not able to retrieve notBefore value
2209 }
2210 debug.println("X509CertSelector.match: private key usage not "
2211 + "within validity date; ext.NOT_BEFORE: "
2212 + time + "; X509CertSelector: "
2213 + this.toString());
2214 e2.printStackTrace();
2215 }
2216 return false;
2217 } catch (CertificateException e3) {
2218 if (debug != null) {
2219 debug.println("X509CertSelector.match: CertificateException "
2220 + "in private key usage check; X509CertSelector: "
2221 + this.toString());
2222 e3.printStackTrace();
2223 }
2224 return false;
2225 } catch (IOException e4) {
2226 if (debug != null) {
2227 debug.println("X509CertSelector.match: IOException in "
2228 + "private key usage check; X509CertSelector: "
2229 + this.toString());
2230 e4.printStackTrace();
2231 }
2232 return false;
2233 }
2234 return true;
2235 }
2236
2237 /* match on subject public key algorithm OID */
2238 private boolean matchSubjectPublicKeyAlgID(X509Certificate xcert) {
2239 if (subjectPublicKeyAlgID == null) {
2240 return true;
2241 }
2242 try {
2243 byte[] encodedKey = xcert.getPublicKey().getEncoded();
2244 DerValue val = new DerValue(encodedKey);
2245 if (val.tag != DerValue.tag_Sequence) {
2246 throw new IOException("invalid key format");
2247 }
2248
2249 AlgorithmId algID = AlgorithmId.parse(val.data.getDerValue());
2250 if (debug != null) {
2251 debug.println("X509CertSelector.match: subjectPublicKeyAlgID = "
2252 + subjectPublicKeyAlgID + ", xcert subjectPublicKeyAlgID = "
2253 + algID.getOID());
2254 }
2255 if (!subjectPublicKeyAlgID.equals(algID.getOID())) {
2256 if (debug != null) {
2257 debug.println("X509CertSelector.match: "
2258 + "subject public key alg IDs don't match");
2259 }
2260 return false;
2261 }
2262 } catch (IOException e5) {
2263 if (debug != null) {
2264 debug.println("X509CertSelector.match: IOException in subject "
2265 + "public key algorithm OID check");
2266 }
2267 return false;
2268 }
2269 return true;
2270 }
2271
2272 /* match on key usage extension value */
2273 private boolean matchKeyUsage(X509Certificate xcert) {
2274 if (keyUsage == null) {
2275 return true;
2284 + "key usage bits don't match");
2285 }
2286 return false;
2287 }
2288 }
2289 }
2290 return true;
2291 }
2292
2293 /* match on extended key usage purpose OIDs */
2294 private boolean matchExtendedKeyUsage(X509Certificate xcert) {
2295 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
2296 return true;
2297 }
2298 try {
2299 ExtendedKeyUsageExtension ext =
2300 (ExtendedKeyUsageExtension)getExtensionObject(xcert,
2301 EXTENDED_KEY_USAGE_ID);
2302 if (ext != null) {
2303 Vector<ObjectIdentifier> certKeyPurposeVector =
2304 (Vector<ObjectIdentifier>)ext.get(ExtendedKeyUsageExtension.USAGES);
2305 if (!certKeyPurposeVector.contains(ANY_EXTENDED_KEY_USAGE)
2306 && !certKeyPurposeVector.containsAll(keyPurposeOIDSet)) {
2307 if (debug != null) {
2308 debug.println("X509CertSelector.match: cert failed "
2309 + "extendedKeyUsage criterion");
2310 }
2311 return false;
2312 }
2313 }
2314 } catch (IOException ex) {
2315 if (debug != null) {
2316 debug.println("X509CertSelector.match: "
2317 + "IOException in extended key usage check");
2318 }
2319 return false;
2320 }
2321 return true;
2322 }
2323
2324 /* match on subject alternative name extension names */
2325 private boolean matchSubjectAlternativeNames(X509Certificate xcert) {
2326 if ((subjectAlternativeNames == null) || subjectAlternativeNames.isEmpty()) {
2327 return true;
2328 }
2329 try {
2330 SubjectAlternativeNameExtension sanExt =
2331 (SubjectAlternativeNameExtension) getExtensionObject(xcert,
2332 SUBJECT_ALT_NAME_ID);
2333 if (sanExt == null) {
2334 if (debug != null) {
2335 debug.println("X509CertSelector.match: "
2336 + "no subject alternative name extension");
2337 }
2338 return false;
2339 }
2340 GeneralNames certNames = (GeneralNames)
2341 sanExt.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
2342 Iterator<GeneralNameInterface> i =
2343 subjectAlternativeGeneralNames.iterator();
2344 while (i.hasNext()) {
2345 GeneralNameInterface matchName = i.next();
2346 boolean found = false;
2347 for (Iterator<GeneralName> t = certNames.iterator();
2348 t.hasNext() && !found; ) {
2349 GeneralNameInterface certName = (t.next()).getName();
2350 found = certName.equals(matchName);
2351 }
2352 if (!found && (matchAllSubjectAltNames || !i.hasNext())) {
2353 if (debug != null) {
2354 debug.println("X509CertSelector.match: subject alternative "
2355 + "name " + matchName + " not found");
2356 }
2357 return false;
2358 } else if (found && !matchAllSubjectAltNames) {
2359 break;
2360 }
2389 return false;
2390 }
2391 return true;
2392 }
2393
2394 /* match on policy OIDs */
2395 private boolean matchPolicy(X509Certificate xcert) {
2396 if (policy == null) {
2397 return true;
2398 }
2399 try {
2400 CertificatePoliciesExtension ext = (CertificatePoliciesExtension)
2401 getExtensionObject(xcert, CERT_POLICIES_ID);
2402 if (ext == null) {
2403 if (debug != null) {
2404 debug.println("X509CertSelector.match: "
2405 + "no certificate policy extension");
2406 }
2407 return false;
2408 }
2409 List<PolicyInformation> policies = (List<PolicyInformation>)ext.get(CertificatePoliciesExtension.POLICIES);
2410 /*
2411 * Convert the Vector of PolicyInformation to a Vector
2412 * of CertificatePolicyIds for easier comparison.
2413 */
2414 List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(policies.size());
2415 for (PolicyInformation info : policies) {
2416 policyIDs.add(info.getPolicyIdentifier());
2417 }
2418 if (policy != null) {
2419 boolean foundOne = false;
2420 /*
2421 * if the user passes in an empty policy Set, then
2422 * we just want to make sure that the candidate certificate
2423 * has some policy OID in its CertPoliciesExtension
2424 */
2425 if (policy.getCertPolicyIds().isEmpty()) {
2426 if (policyIDs.isEmpty()) {
2427 if (debug != null) {
2428 debug.println("X509CertSelector.match: "
2429 + "cert failed policyAny criterion");
2450 if (debug != null) {
2451 debug.println("X509CertSelector.match: "
2452 + "IOException in certificate policy ID check");
2453 }
2454 return false;
2455 }
2456 return true;
2457 }
2458
2459 /* match on pathToNames */
2460 private boolean matchPathToNames(X509Certificate xcert) {
2461 if (pathToGeneralNames == null) {
2462 return true;
2463 }
2464 try {
2465 NameConstraintsExtension ext = (NameConstraintsExtension)
2466 getExtensionObject(xcert, NAME_CONSTRAINTS_ID);
2467 if (ext == null) {
2468 return true;
2469 }
2470 if ((debug != null) && debug.isOn("certpath")) {
2471 debug.println("X509CertSelector.match pathToNames:\n");
2472 Iterator<GeneralNameInterface> i =
2473 pathToGeneralNames.iterator();
2474 while (i.hasNext()) {
2475 debug.println(" " + i.next() + "\n");
2476 }
2477 }
2478
2479 GeneralSubtrees permitted = (GeneralSubtrees)
2480 ext.get(NameConstraintsExtension.PERMITTED_SUBTREES);
2481 GeneralSubtrees excluded = (GeneralSubtrees)
2482 ext.get(NameConstraintsExtension.EXCLUDED_SUBTREES);
2483 if (excluded != null) {
2484 if (matchExcluded(excluded) == false) {
2485 return false;
2486 }
2487 }
2488 if (permitted != null) {
2489 if (matchPermitted(permitted) == false) {
2490 return false;
2491 }
2492 }
2493 } catch (IOException ex) {
2494 if (debug != null) {
2495 debug.println("X509CertSelector.match: "
2496 + "IOException in name constraints check");
2497 }
2498 return false;
2499 }
2500 return true;
2501 }
2580 int maxPathLen = xcert.getBasicConstraints();
2581 if (basicConstraints == -2) {
2582 if (maxPathLen != -1) {
2583 if (debug != null) {
2584 debug.println("X509CertSelector.match: not an EE cert");
2585 }
2586 return false;
2587 }
2588 } else {
2589 if (maxPathLen < basicConstraints) {
2590 if (debug != null) {
2591 debug.println("X509CertSelector.match: maxPathLen too small ("
2592 + maxPathLen + " < " + basicConstraints + ")");
2593 }
2594 return false;
2595 }
2596 }
2597 return true;
2598 }
2599
2600 private static Set<?> cloneSet(Set<?> set) {
2601 if (set instanceof HashSet) {
2602 Object clone = ((HashSet<?>)set).clone();
2603 return (Set<?>)clone;
2604 } else {
2605 return new HashSet<Object>(set);
2606 }
2607 }
2608
2609 /**
2610 * Returns a copy of this object.
2611 *
2612 * @return the copy
2613 */
2614 public Object clone() {
2615 try {
2616 X509CertSelector copy = (X509CertSelector)super.clone();
2617 // Must clone these because addPathToName et al. modify them
2618 if (subjectAlternativeNames != null) {
2619 copy.subjectAlternativeNames =
2620 (Set<List<?>>)cloneSet(subjectAlternativeNames);
2621 copy.subjectAlternativeGeneralNames =
2622 (Set<GeneralNameInterface>)cloneSet
2623 (subjectAlternativeGeneralNames);
2624 }
2625 if (pathToGeneralNames != null) {
2626 copy.pathToNames =
2627 (Set<List<?>>)cloneSet(pathToNames);
2628 copy.pathToGeneralNames =
2629 (Set<GeneralNameInterface>)cloneSet
2630 (pathToGeneralNames);
2631 }
2632 return copy;
2633 } catch (CloneNotSupportedException e) {
2634 /* Cannot happen */
2635 throw new InternalError(e.toString());
2636 }
2637 }
2638 }
| 1 /*
2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
260 * ....
261 * DirectoryString ::= CHOICE {
262 * teletexString TeletexString (SIZE (1..MAX)),
263 * printableString PrintableString (SIZE (1..MAX)),
264 * universalString UniversalString (SIZE (1..MAX)),
265 * utf8String UTF8String (SIZE (1.. MAX)),
266 * bmpString BMPString (SIZE (1..MAX)) }
267 * </code></pre>
268 * <p>
269 * Note that the byte array specified here is cloned to protect against
270 * subsequent modifications.
271 *
272 * @param issuerDN a byte array containing the distinguished name
273 * in ASN.1 DER encoded form (or <code>null</code>)
274 * @throws IOException if an encoding error occurs (incorrect form for DN)
275 */
276 public void setIssuer(byte[] issuerDN) throws IOException {
277 try {
278 issuer = (issuerDN == null ? null : new X500Principal(issuerDN));
279 } catch (IllegalArgumentException e) {
280 throw new IOException("Invalid name", e);
281 }
282 }
283
284 /**
285 * Sets the subject criterion. The specified distinguished name
286 * must match the subject distinguished name in the
287 * <code>X509Certificate</code>. If <code>null</code>, any subject
288 * distinguished name will do.
289 *
290 * @param subject a distinguished name as X500Principal
291 * (or <code>null</code>)
292 * @since 1.5
293 */
294 public void setSubject(X500Principal subject) {
295 this.subject = subject;
296 }
297
298 /**
299 * <strong>Denigrated</strong>, use {@linkplain #setSubject(X500Principal)}
300 * or {@linkplain #setSubject(byte[])} instead. This method should not be
324
325 /**
326 * Sets the subject criterion. The specified distinguished name
327 * must match the subject distinguished name in the
328 * <code>X509Certificate</code>. If <code>null</code>, any subject
329 * distinguished name will do.
330 * <p>
331 * If <code>subjectDN</code> is not <code>null</code>, it should contain a
332 * single DER encoded distinguished name, as defined in X.501. For the ASN.1
333 * notation for this structure, see
334 * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
335 *
336 * @param subjectDN a byte array containing the distinguished name in
337 * ASN.1 DER format (or <code>null</code>)
338 * @throws IOException if an encoding error occurs (incorrect form for DN)
339 */
340 public void setSubject(byte[] subjectDN) throws IOException {
341 try {
342 subject = (subjectDN == null ? null : new X500Principal(subjectDN));
343 } catch (IllegalArgumentException e) {
344 throw new IOException("Invalid name", e);
345 }
346 }
347
348 /**
349 * Sets the subjectKeyIdentifier criterion. The
350 * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
351 * extension for which the contents of the extension
352 * matches the specified criterion value.
353 * If the criterion value is <code>null</code>, no
354 * subjectKeyIdentifier check will be done.
355 * <p>
356 * If <code>subjectKeyID</code> is not <code>null</code>, it
357 * should contain a single DER encoded value corresponding to the contents
358 * of the extension value (not including the object identifier,
359 * criticality setting, and encapsulating OCTET STRING)
360 * for a SubjectKeyIdentifier extension.
361 * The ASN.1 notation for this structure follows.
362 * <p>
363 * <pre><code>
364 * SubjectKeyIdentifier ::= KeyIdentifier
365 *
366 * KeyIdentifier ::= OCTET STRING
367 * </code></pre>
368 * <p>
369 * Since the format of subject key identifiers is not mandated by
370 * any standard, subject key identifiers are not parsed by the
371 * <code>X509CertSelector</code>. Instead, the values are compared using
372 * a byte-by-byte comparison.
373 * <p>
374 * Note that the byte array supplied here is cloned to protect against
375 * subsequent modifications.
376 *
377 * @param subjectKeyID the subject key identifier (or <code>null</code>)
378 * @see #getSubjectKeyIdentifier
379 */
380 public void setSubjectKeyIdentifier(byte[] subjectKeyID) {
381 if (subjectKeyID == null) {
382 this.subjectKeyID = null;
383 } else {
384 this.subjectKeyID = subjectKeyID.clone();
385 }
386 }
387
388 /**
389 * Sets the authorityKeyIdentifier criterion. The
390 * <code>X509Certificate</code> must contain an
391 * AuthorityKeyIdentifier extension for which the contents of the
392 * extension value matches the specified criterion value.
393 * If the criterion value is <code>null</code>, no
394 * authorityKeyIdentifier check will be done.
395 * <p>
396 * If <code>authorityKeyID</code> is not <code>null</code>, it
397 * should contain a single DER encoded value corresponding to the contents
398 * of the extension value (not including the object identifier,
399 * criticality setting, and encapsulating OCTET STRING)
400 * for an AuthorityKeyIdentifier extension.
401 * The ASN.1 notation for this structure follows.
402 * <p>
403 * <pre><code>
404 * AuthorityKeyIdentifier ::= SEQUENCE {
425 * KeyIdentifier, GeneralNames, and CertificateSerialNumber.
426 * In order to use the extension value of the issuer certificate's
427 * <code>SubjectKeyIdentifier</code>
428 * extension, it will be necessary to extract the value of the embedded
429 * <code>KeyIdentifier</code> OCTET STRING, then DER encode this OCTET
430 * STRING inside a SEQUENCE.
431 * For more details on SubjectKeyIdentifier, see
432 * {@link #setSubjectKeyIdentifier(byte[] subjectKeyID)}.
433 * <p>
434 * Note also that the byte array supplied here is cloned to protect against
435 * subsequent modifications.
436 *
437 * @param authorityKeyID the authority key identifier
438 * (or <code>null</code>)
439 * @see #getAuthorityKeyIdentifier
440 */
441 public void setAuthorityKeyIdentifier(byte[] authorityKeyID) {
442 if (authorityKeyID == null) {
443 this.authorityKeyID = null;
444 } else {
445 this.authorityKeyID = authorityKeyID.clone();
446 }
447 }
448
449 /**
450 * Sets the certificateValid criterion. The specified date must fall
451 * within the certificate validity period for the
452 * <code>X509Certificate</code>. If <code>null</code>, no certificateValid
453 * check will be done.
454 * <p>
455 * Note that the <code>Date</code> supplied here is cloned to protect
456 * against subsequent modifications.
457 *
458 * @param certValid the <code>Date</code> to check (or <code>null</code>)
459 * @see #getCertificateValid
460 */
461 public void setCertificateValid(Date certValid) {
462 if (certValid == null) {
463 certificateValid = null;
464 } else {
465 certificateValid = (Date)certValid.clone();
549 * parameters ANY DEFINED BY algorithm OPTIONAL }
550 * -- contains a value of the type
551 * -- registered for use with the
552 * -- algorithm object identifier value
553 * </code></pre>
554 * <p>
555 * Note that the byte array supplied here is cloned to protect against
556 * subsequent modifications.
557 *
558 * @param key a byte array containing the subject public key in ASN.1 DER
559 * form (or <code>null</code>)
560 * @throws IOException if an encoding error occurs (incorrect form for
561 * subject public key)
562 * @see #getSubjectPublicKey
563 */
564 public void setSubjectPublicKey(byte[] key) throws IOException {
565 if (key == null) {
566 subjectPublicKey = null;
567 subjectPublicKeyBytes = null;
568 } else {
569 subjectPublicKeyBytes = key.clone();
570 subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes));
571 }
572 }
573
574 /**
575 * Sets the keyUsage criterion. The <code>X509Certificate</code>
576 * must allow the specified keyUsage values. If <code>null</code>, no
577 * keyUsage check will be done. Note that an <code>X509Certificate</code>
578 * that has no keyUsage extension implicitly allows all keyUsage values.
579 * <p>
580 * Note that the boolean array supplied here is cloned to protect against
581 * subsequent modifications.
582 *
583 * @param keyUsage a boolean array in the same format as the boolean
584 * array returned by
585 * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
586 * Or <code>null</code>.
587 * @see #getKeyUsage
588 */
589 public void setKeyUsage(boolean[] keyUsage) {
590 if (keyUsage == null) {
591 this.keyUsage = null;
592 } else {
593 this.keyUsage = keyUsage.clone();
594 }
595 }
596
597 /**
598 * Sets the extendedKeyUsage criterion. The <code>X509Certificate</code>
599 * must allow the specified key purposes in its extended key usage
600 * extension. If <code>keyPurposeSet</code> is empty or <code>null</code>,
601 * no extendedKeyUsage check will be done. Note that an
602 * <code>X509Certificate</code> that has no extendedKeyUsage extension
603 * implicitly allows all key purposes.
604 * <p>
605 * Note that the <code>Set</code> is cloned to protect against
606 * subsequent modifications.
607 *
608 * @param keyPurposeSet a <code>Set</code> of key purpose OIDs in string
609 * format (or <code>null</code>). Each OID is represented by a set of
610 * nonnegative integers separated by periods.
611 * @throws IOException if the OID is invalid, such as
612 * the first component being not 0, 1 or 2 or the second component
613 * being greater than 39.
855 throw new IOException("expected an Integer");
856 }
857 int nameType = ((Integer)o).intValue();
858 o = nameList.get(1);
859 genNames.add(makeGeneralNameInterface(nameType, o));
860 }
861
862 return genNames;
863 }
864
865 /**
866 * Compare for equality two objects of the form passed to
867 * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames).
868 * Throw an <code>IllegalArgumentException</code> or a
869 * <code>ClassCastException</code> if one of the objects is malformed.
870 *
871 * @param object1 a Collection containing the first object to compare
872 * @param object2 a Collection containing the second object to compare
873 * @return true if the objects are equal, false otherwise
874 */
875 static boolean equalNames(Collection<?> object1, Collection<?> object2) {
876 if ((object1 == null) || (object2 == null)) {
877 return object1 == object2;
878 }
879 return object1.equals(object2);
880 }
881
882 /**
883 * Make a <code>GeneralNameInterface</code> out of a name type (0-8) and an
884 * Object that may be a byte array holding the ASN.1 DER encoded
885 * name or a String form of the name. Except for X.509
886 * Distinguished Names, the String form of the name must not be the
887 * result from calling toString on an existing GeneralNameInterface
888 * implementing class. The output of toString is not compatible
889 * with the String constructors for names other than Distinguished
890 * Names.
891 *
892 * @param type name type (0-8)
893 * @param name name as ASN.1 Der-encoded byte array or String
894 * @return a GeneralNameInterface name
895 * @throws IOException if a parsing error occurs
1024 * registeredID [8] OBJECT IDENTIFIER}
1025 * </code></pre>
1026 * <p>
1027 * Note that the byte array supplied here is cloned to protect against
1028 * subsequent modifications.
1029 *
1030 * @param bytes a byte array containing the ASN.1 DER encoding of
1031 * a NameConstraints extension to be used for checking
1032 * name constraints. Only the value of the extension is
1033 * included, not the OID or criticality flag. Can be
1034 * <code>null</code>,
1035 * in which case no name constraints check will be performed.
1036 * @throws IOException if a parsing error occurs
1037 * @see #getNameConstraints
1038 */
1039 public void setNameConstraints(byte[] bytes) throws IOException {
1040 if (bytes == null) {
1041 ncBytes = null;
1042 nc = null;
1043 } else {
1044 ncBytes = bytes.clone();
1045 nc = new NameConstraintsExtension(FALSE, bytes);
1046 }
1047 }
1048
1049 /**
1050 * Sets the basic constraints constraint. If the value is greater than or
1051 * equal to zero, <code>X509Certificates</code> must include a
1052 * basicConstraints extension with
1053 * a pathLen of at least this value. If the value is -2, only end-entity
1054 * certificates are accepted. If the value is -1, no check is done.
1055 * <p>
1056 * This constraint is useful when building a certification path forward
1057 * (from the target toward the trust anchor. If a partial path has been
1058 * built, any candidate certificate must have a maxPathLen value greater
1059 * than or equal to the number of certificates in the partial path.
1060 *
1061 * @param minMaxPathLen the value for the basic constraints constraint
1062 * @throws IllegalArgumentException if the value is less than -2
1063 * @see #getBasicConstraints
1064 */
1421 public byte[] getSubjectAsBytes() throws IOException {
1422 return (subject == null ? null : subject.getEncoded());
1423 }
1424
1425 /**
1426 * Returns the subjectKeyIdentifier criterion. The
1427 * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
1428 * extension with the specified value. If <code>null</code>, no
1429 * subjectKeyIdentifier check will be done.
1430 * <p>
1431 * Note that the byte array returned is cloned to protect against
1432 * subsequent modifications.
1433 *
1434 * @return the key identifier (or <code>null</code>)
1435 * @see #setSubjectKeyIdentifier
1436 */
1437 public byte[] getSubjectKeyIdentifier() {
1438 if (subjectKeyID == null) {
1439 return null;
1440 }
1441 return subjectKeyID.clone();
1442 }
1443
1444 /**
1445 * Returns the authorityKeyIdentifier criterion. The
1446 * <code>X509Certificate</code> must contain a AuthorityKeyIdentifier
1447 * extension with the specified value. If <code>null</code>, no
1448 * authorityKeyIdentifier check will be done.
1449 * <p>
1450 * Note that the byte array returned is cloned to protect against
1451 * subsequent modifications.
1452 *
1453 * @return the key identifier (or <code>null</code>)
1454 * @see #setAuthorityKeyIdentifier
1455 */
1456 public byte[] getAuthorityKeyIdentifier() {
1457 if (authorityKeyID == null) {
1458 return null;
1459 }
1460 return authorityKeyID.clone();
1461 }
1462
1463 /**
1464 * Returns the certificateValid criterion. The specified date must fall
1465 * within the certificate validity period for the
1466 * <code>X509Certificate</code>. If <code>null</code>, no certificateValid
1467 * check will be done.
1468 * <p>
1469 * Note that the <code>Date</code> returned is cloned to protect against
1470 * subsequent modifications.
1471 *
1472 * @return the <code>Date</code> to check (or <code>null</code>)
1473 * @see #setCertificateValid
1474 */
1475 public Date getCertificateValid() {
1476 if (certificateValid == null) {
1477 return null;
1478 }
1479 return (Date)certificateValid.clone();
1480 }
1529 }
1530
1531 /**
1532 * Returns the keyUsage criterion. The <code>X509Certificate</code>
1533 * must allow the specified keyUsage values. If null, no keyUsage
1534 * check will be done.
1535 * <p>
1536 * Note that the boolean array returned is cloned to protect against
1537 * subsequent modifications.
1538 *
1539 * @return a boolean array in the same format as the boolean
1540 * array returned by
1541 * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
1542 * Or <code>null</code>.
1543 * @see #setKeyUsage
1544 */
1545 public boolean[] getKeyUsage() {
1546 if (keyUsage == null) {
1547 return null;
1548 }
1549 return keyUsage.clone();
1550 }
1551
1552 /**
1553 * Returns the extendedKeyUsage criterion. The <code>X509Certificate</code>
1554 * must allow the specified key purposes in its extended key usage
1555 * extension. If the <code>keyPurposeSet</code> returned is empty or
1556 * <code>null</code>, no extendedKeyUsage check will be done. Note that an
1557 * <code>X509Certificate</code> that has no extendedKeyUsage extension
1558 * implicitly allows all key purposes.
1559 *
1560 * @return an immutable <code>Set</code> of key purpose OIDs in string
1561 * format (or <code>null</code>)
1562 * @see #setExtendedKeyUsage
1563 */
1564 public Set<String> getExtendedKeyUsage() {
1565 return keyPurposeSet;
1566 }
1567
1568 /**
1569 * Indicates if the <code>X509Certificate</code> must contain all
1655 }
1656
1657 /**
1658 * Clone and check an argument of the form passed to
1659 * setSubjectAlternativeNames and setPathToNames.
1660 * Throw an <code>IOException</code> if the argument is malformed.
1661 *
1662 * @param names a <code>Collection</code> with one entry per name.
1663 * Each entry is a <code>List</code> whose first entry
1664 * is an Integer (the name type, 0-8) and whose second
1665 * entry is a String or a byte array (the name, in
1666 * string or ASN.1 DER encoded form, respectively).
1667 * There can be multiple names of the same type.
1668 * <code>null</code> is not an acceptable value.
1669 * @return a deep copy of the specified <code>Collection</code>
1670 * @throws IOException if a parsing error occurs
1671 */
1672 private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException {
1673 // Copy the Lists and Collection
1674 Set<List<?>> namesCopy = new HashSet<List<?>>();
1675 for (List<?> o : names)
1676 {
1677 namesCopy.add(new ArrayList<Object>(o));
1678 }
1679
1680 // Check the contents of the Lists and clone any byte arrays
1681 for (List<?> list : namesCopy) {
1682 @SuppressWarnings("unchecked") // See javadoc for parameter "names".
1683 List<Object> nameList = (List<Object>)list;
1684 if (nameList.size() != 2) {
1685 throw new IOException("name list size not 2");
1686 }
1687 Object o = nameList.get(0);
1688 if (!(o instanceof Integer)) {
1689 throw new IOException("expected an Integer");
1690 }
1691 int nameType = ((Integer)o).intValue();
1692 if ((nameType < 0) || (nameType > 8)) {
1693 throw new IOException("name type not 0-8");
1694 }
1695 Object nameObject = nameList.get(1);
1696 if (!(nameObject instanceof byte[]) &&
1697 !(nameObject instanceof String)) {
1698 if (debug != null) {
1699 debug.println("X509CertSelector.cloneAndCheckNames() "
1700 + "name not byte array");
1701 }
1702 throw new IOException("name not byte array or String");
1703 }
1715 * <p>
1716 * The name constraints are returned as a byte array. This byte array
1717 * contains the DER encoded form of the name constraints, as they
1718 * would appear in the NameConstraints structure defined in RFC 3280
1719 * and X.509. The ASN.1 notation for this structure is supplied in the
1720 * documentation for
1721 * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.
1722 * <p>
1723 * Note that the byte array returned is cloned to protect against
1724 * subsequent modifications.
1725 *
1726 * @return a byte array containing the ASN.1 DER encoding of
1727 * a NameConstraints extension used for checking name constraints.
1728 * <code>null</code> if no name constraints check will be performed.
1729 * @see #setNameConstraints
1730 */
1731 public byte[] getNameConstraints() {
1732 if (ncBytes == null) {
1733 return null;
1734 } else {
1735 return ncBytes.clone();
1736 }
1737 }
1738
1739 /**
1740 * Returns the basic constraints constraint. If the value is greater than
1741 * or equal to zero, the <code>X509Certificates</code> must include a
1742 * basicConstraints extension with a pathLen of at least this value.
1743 * If the value is -2, only end-entity certificates are accepted. If
1744 * the value is -1, no basicConstraints check is done.
1745 *
1746 * @return the value for the basic constraints constraint
1747 * @see #setBasicConstraints
1748 */
1749 public int getBasicConstraints() {
1750 return basicConstraints;
1751 }
1752
1753 /**
1754 * Returns the policy criterion. The <code>X509Certificate</code> must
1755 * include at least one of the specified policies in its certificate policies
2163 }
2164 return true;
2165 }
2166
2167 /* match on private key usage range */
2168 private boolean matchPrivateKeyValid(X509Certificate xcert) {
2169 if (privateKeyValid == null) {
2170 return true;
2171 }
2172 PrivateKeyUsageExtension ext = null;
2173 try {
2174 ext = (PrivateKeyUsageExtension)
2175 getExtensionObject(xcert, PRIVATE_KEY_USAGE_ID);
2176 if (ext != null) {
2177 ext.valid(privateKeyValid);
2178 }
2179 } catch (CertificateExpiredException e1) {
2180 if (debug != null) {
2181 String time = "n/a";
2182 try {
2183 Date notAfter = ext.get(PrivateKeyUsageExtension.NOT_AFTER);
2184 time = notAfter.toString();
2185 } catch (CertificateException ex) {
2186 // not able to retrieve notAfter value
2187 }
2188 debug.println("X509CertSelector.match: private key usage not "
2189 + "within validity date; ext.NOT_After: "
2190 + time + "; X509CertSelector: "
2191 + this.toString());
2192 e1.printStackTrace();
2193 }
2194 return false;
2195 } catch (CertificateNotYetValidException e2) {
2196 if (debug != null) {
2197 String time = "n/a";
2198 try {
2199 Date notBefore = ext.get(PrivateKeyUsageExtension.NOT_BEFORE);
2200 time = notBefore.toString();
2201 } catch (CertificateException ex) {
2202 // not able to retrieve notBefore value
2203 }
2204 debug.println("X509CertSelector.match: private key usage not "
2205 + "within validity date; ext.NOT_BEFORE: "
2206 + time + "; X509CertSelector: "
2207 + this.toString());
2208 e2.printStackTrace();
2209 }
2210 return false;
2211 } catch (IOException e4) {
2212 if (debug != null) {
2213 debug.println("X509CertSelector.match: IOException in "
2214 + "private key usage check; X509CertSelector: "
2215 + this.toString());
2216 e4.printStackTrace();
2217 }
2218 return false;
2219 }
2220 return true;
2221 }
2222
2223 /* match on subject public key algorithm OID */
2224 private boolean matchSubjectPublicKeyAlgID(X509Certificate xcert) {
2225 if (subjectPublicKeyAlgID == null) {
2226 return true;
2227 }
2228 try {
2229 byte[] encodedKey = xcert.getPublicKey().getEncoded();
2230 DerValue val = new DerValue(encodedKey);
2231 if (val.tag != DerValue.tag_Sequence) {
2232 throw new IOException("invalid key format");
2233 }
2234
2235 AlgorithmId algID = AlgorithmId.parse(val.data.getDerValue());
2236 if (debug != null) {
2237 debug.println("X509CertSelector.match: subjectPublicKeyAlgID = "
2238 + subjectPublicKeyAlgID + ", xcert subjectPublicKeyAlgID = "
2239 + algID.getOID());
2240 }
2241 if (!subjectPublicKeyAlgID.equals((Object)algID.getOID())) {
2242 if (debug != null) {
2243 debug.println("X509CertSelector.match: "
2244 + "subject public key alg IDs don't match");
2245 }
2246 return false;
2247 }
2248 } catch (IOException e5) {
2249 if (debug != null) {
2250 debug.println("X509CertSelector.match: IOException in subject "
2251 + "public key algorithm OID check");
2252 }
2253 return false;
2254 }
2255 return true;
2256 }
2257
2258 /* match on key usage extension value */
2259 private boolean matchKeyUsage(X509Certificate xcert) {
2260 if (keyUsage == null) {
2261 return true;
2270 + "key usage bits don't match");
2271 }
2272 return false;
2273 }
2274 }
2275 }
2276 return true;
2277 }
2278
2279 /* match on extended key usage purpose OIDs */
2280 private boolean matchExtendedKeyUsage(X509Certificate xcert) {
2281 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
2282 return true;
2283 }
2284 try {
2285 ExtendedKeyUsageExtension ext =
2286 (ExtendedKeyUsageExtension)getExtensionObject(xcert,
2287 EXTENDED_KEY_USAGE_ID);
2288 if (ext != null) {
2289 Vector<ObjectIdentifier> certKeyPurposeVector =
2290 ext.get(ExtendedKeyUsageExtension.USAGES);
2291 if (!certKeyPurposeVector.contains(ANY_EXTENDED_KEY_USAGE)
2292 && !certKeyPurposeVector.containsAll(keyPurposeOIDSet)) {
2293 if (debug != null) {
2294 debug.println("X509CertSelector.match: cert failed "
2295 + "extendedKeyUsage criterion");
2296 }
2297 return false;
2298 }
2299 }
2300 } catch (IOException ex) {
2301 if (debug != null) {
2302 debug.println("X509CertSelector.match: "
2303 + "IOException in extended key usage check");
2304 }
2305 return false;
2306 }
2307 return true;
2308 }
2309
2310 /* match on subject alternative name extension names */
2311 private boolean matchSubjectAlternativeNames(X509Certificate xcert) {
2312 if ((subjectAlternativeNames == null) || subjectAlternativeNames.isEmpty()) {
2313 return true;
2314 }
2315 try {
2316 SubjectAlternativeNameExtension sanExt =
2317 (SubjectAlternativeNameExtension) getExtensionObject(xcert,
2318 SUBJECT_ALT_NAME_ID);
2319 if (sanExt == null) {
2320 if (debug != null) {
2321 debug.println("X509CertSelector.match: "
2322 + "no subject alternative name extension");
2323 }
2324 return false;
2325 }
2326 GeneralNames certNames =
2327 sanExt.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
2328 Iterator<GeneralNameInterface> i =
2329 subjectAlternativeGeneralNames.iterator();
2330 while (i.hasNext()) {
2331 GeneralNameInterface matchName = i.next();
2332 boolean found = false;
2333 for (Iterator<GeneralName> t = certNames.iterator();
2334 t.hasNext() && !found; ) {
2335 GeneralNameInterface certName = (t.next()).getName();
2336 found = certName.equals(matchName);
2337 }
2338 if (!found && (matchAllSubjectAltNames || !i.hasNext())) {
2339 if (debug != null) {
2340 debug.println("X509CertSelector.match: subject alternative "
2341 + "name " + matchName + " not found");
2342 }
2343 return false;
2344 } else if (found && !matchAllSubjectAltNames) {
2345 break;
2346 }
2375 return false;
2376 }
2377 return true;
2378 }
2379
2380 /* match on policy OIDs */
2381 private boolean matchPolicy(X509Certificate xcert) {
2382 if (policy == null) {
2383 return true;
2384 }
2385 try {
2386 CertificatePoliciesExtension ext = (CertificatePoliciesExtension)
2387 getExtensionObject(xcert, CERT_POLICIES_ID);
2388 if (ext == null) {
2389 if (debug != null) {
2390 debug.println("X509CertSelector.match: "
2391 + "no certificate policy extension");
2392 }
2393 return false;
2394 }
2395 List<PolicyInformation> policies = ext.get(CertificatePoliciesExtension.POLICIES);
2396 /*
2397 * Convert the Vector of PolicyInformation to a Vector
2398 * of CertificatePolicyIds for easier comparison.
2399 */
2400 List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(policies.size());
2401 for (PolicyInformation info : policies) {
2402 policyIDs.add(info.getPolicyIdentifier());
2403 }
2404 if (policy != null) {
2405 boolean foundOne = false;
2406 /*
2407 * if the user passes in an empty policy Set, then
2408 * we just want to make sure that the candidate certificate
2409 * has some policy OID in its CertPoliciesExtension
2410 */
2411 if (policy.getCertPolicyIds().isEmpty()) {
2412 if (policyIDs.isEmpty()) {
2413 if (debug != null) {
2414 debug.println("X509CertSelector.match: "
2415 + "cert failed policyAny criterion");
2436 if (debug != null) {
2437 debug.println("X509CertSelector.match: "
2438 + "IOException in certificate policy ID check");
2439 }
2440 return false;
2441 }
2442 return true;
2443 }
2444
2445 /* match on pathToNames */
2446 private boolean matchPathToNames(X509Certificate xcert) {
2447 if (pathToGeneralNames == null) {
2448 return true;
2449 }
2450 try {
2451 NameConstraintsExtension ext = (NameConstraintsExtension)
2452 getExtensionObject(xcert, NAME_CONSTRAINTS_ID);
2453 if (ext == null) {
2454 return true;
2455 }
2456 if ((debug != null) && Debug.isOn("certpath")) {
2457 debug.println("X509CertSelector.match pathToNames:\n");
2458 Iterator<GeneralNameInterface> i =
2459 pathToGeneralNames.iterator();
2460 while (i.hasNext()) {
2461 debug.println(" " + i.next() + "\n");
2462 }
2463 }
2464
2465 GeneralSubtrees permitted =
2466 ext.get(NameConstraintsExtension.PERMITTED_SUBTREES);
2467 GeneralSubtrees excluded =
2468 ext.get(NameConstraintsExtension.EXCLUDED_SUBTREES);
2469 if (excluded != null) {
2470 if (matchExcluded(excluded) == false) {
2471 return false;
2472 }
2473 }
2474 if (permitted != null) {
2475 if (matchPermitted(permitted) == false) {
2476 return false;
2477 }
2478 }
2479 } catch (IOException ex) {
2480 if (debug != null) {
2481 debug.println("X509CertSelector.match: "
2482 + "IOException in name constraints check");
2483 }
2484 return false;
2485 }
2486 return true;
2487 }
2566 int maxPathLen = xcert.getBasicConstraints();
2567 if (basicConstraints == -2) {
2568 if (maxPathLen != -1) {
2569 if (debug != null) {
2570 debug.println("X509CertSelector.match: not an EE cert");
2571 }
2572 return false;
2573 }
2574 } else {
2575 if (maxPathLen < basicConstraints) {
2576 if (debug != null) {
2577 debug.println("X509CertSelector.match: maxPathLen too small ("
2578 + maxPathLen + " < " + basicConstraints + ")");
2579 }
2580 return false;
2581 }
2582 }
2583 return true;
2584 }
2585
2586 @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
2587 private static <T> Set<T> cloneSet(Set<T> set) {
2588 if (set instanceof HashSet) {
2589 Object clone = ((HashSet<T>)set).clone();
2590 return (Set<T>)clone;
2591 } else {
2592 return new HashSet<T>(set);
2593 }
2594 }
2595
2596 /**
2597 * Returns a copy of this object.
2598 *
2599 * @return the copy
2600 */
2601 public Object clone() {
2602 try {
2603 X509CertSelector copy = (X509CertSelector)super.clone();
2604 // Must clone these because addPathToName et al. modify them
2605 if (subjectAlternativeNames != null) {
2606 copy.subjectAlternativeNames =
2607 cloneSet(subjectAlternativeNames);
2608 copy.subjectAlternativeGeneralNames =
2609 cloneSet(subjectAlternativeGeneralNames);
2610 }
2611 if (pathToGeneralNames != null) {
2612 copy.pathToNames = cloneSet(pathToNames);
2613 copy.pathToGeneralNames = cloneSet(pathToGeneralNames);
2614 }
2615 return copy;
2616 } catch (CloneNotSupportedException e) {
2617 /* Cannot happen */
2618 throw new InternalError(e.toString());
2619 }
2620 }
2621 }
|