< prev index next >

src/share/classes/java/security/cert/X509CertSelector.java

Print this page
rev 1387 : 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
Reviewed-by: xuelei, mullan
Contributed-by: alexandre.boulgakov@oracle.com
rev 1388 : 6600143: Remove another 450 unnecessary casts
Reviewed-by: alanb, iris, lmalvent, bristor, peterjones, darcy, wetmore
   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 }
< prev index next >