0001 /*
0002 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.security.cert;
0027
0028 import java.io.IOException;
0029 import java.math.BigInteger;
0030 import java.security.PublicKey;
0031 import java.util.*;
0032 import javax.security.auth.x500.X500Principal;
0033
0034 import sun.misc.HexDumpEncoder;
0035 import sun.security.util.Debug;
0036 import sun.security.util.DerInputStream;
0037 import sun.security.util.DerValue;
0038 import sun.security.util.ObjectIdentifier;
0039 import sun.security.x509.*;
0040
0041 /**
0042 * A <code>CertSelector</code> that selects <code>X509Certificates</code> that
0043 * match all specified criteria. This class is particularly useful when
0044 * selecting certificates from a <code>CertStore</code> to build a
0045 * PKIX-compliant certification path.
0046 * <p>
0047 * When first constructed, an <code>X509CertSelector</code> has no criteria
0048 * enabled and each of the <code>get</code> methods return a default value
0049 * (<code>null</code>, or <code>-1</code> for the {@link #getBasicConstraints
0050 * getBasicConstraints} method). Therefore, the {@link #match match}
0051 * method would return <code>true</code> for any <code>X509Certificate</code>.
0052 * Typically, several criteria are enabled (by calling
0053 * {@link #setIssuer setIssuer} or
0054 * {@link #setKeyUsage setKeyUsage}, for instance) and then the
0055 * <code>X509CertSelector</code> is passed to
0056 * {@link CertStore#getCertificates CertStore.getCertificates} or some similar
0057 * method.
0058 * <p>
0059 * Several criteria can be enabled (by calling {@link #setIssuer setIssuer}
0060 * and {@link #setSerialNumber setSerialNumber},
0061 * for example) such that the <code>match</code> method
0062 * usually uniquely matches a single <code>X509Certificate</code>. We say
0063 * usually, since it is possible for two issuing CAs to have the same
0064 * distinguished name and each issue a certificate with the same serial
0065 * number. Other unique combinations include the issuer, subject,
0066 * subjectKeyIdentifier and/or the subjectPublicKey criteria.
0067 * <p>
0068 * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
0069 * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a> for
0070 * definitions of the X.509 certificate extensions mentioned below.
0071 * <p>
0072 * <b>Concurrent Access</b>
0073 * <p>
0074 * Unless otherwise specified, the methods defined in this class are not
0075 * thread-safe. Multiple threads that need to access a single
0076 * object concurrently should synchronize amongst themselves and
0077 * provide the necessary locking. Multiple threads each manipulating
0078 * separate objects need not synchronize.
0079 *
0080 * @see CertSelector
0081 * @see X509Certificate
0082 *
0083 * @version 1.29, 05/05/07
0084 * @since 1.4
0085 * @author Steve Hanna
0086 */
0087 public class X509CertSelector implements CertSelector {
0088
0089 private static final Debug debug = Debug.getInstance("certpath");
0090
0091 private final static ObjectIdentifier ANY_EXTENDED_KEY_USAGE = ObjectIdentifier
0092 .newInternal(new int[] { 2, 5, 29, 37, 0 });
0093
0094 static {
0095 CertPathHelperImpl.initialize();
0096 }
0097
0098 private BigInteger serialNumber;
0099 private X500Principal issuer;
0100 private X500Principal subject;
0101 private byte[] subjectKeyID;
0102 private byte[] authorityKeyID;
0103 private Date certificateValid;
0104 private Date privateKeyValid;
0105 private ObjectIdentifier subjectPublicKeyAlgID;
0106 private PublicKey subjectPublicKey;
0107 private byte[] subjectPublicKeyBytes;
0108 private boolean[] keyUsage;
0109 private Set<String> keyPurposeSet;
0110 private Set<ObjectIdentifier> keyPurposeOIDSet;
0111 private Set<List<?>> subjectAlternativeNames;
0112 private Set<GeneralNameInterface> subjectAlternativeGeneralNames;
0113 private CertificatePolicySet policy;
0114 private Set<String> policySet;
0115 private Set<List<?>> pathToNames;
0116 private Set<GeneralNameInterface> pathToGeneralNames;
0117 private NameConstraintsExtension nc;
0118 private byte[] ncBytes;
0119 private int basicConstraints = -1;
0120 private X509Certificate x509Cert;
0121 private boolean matchAllSubjectAltNames = true;
0122
0123 private static final Boolean FALSE = Boolean.FALSE;
0124
0125 private static final int PRIVATE_KEY_USAGE_ID = 0;
0126 private static final int SUBJECT_ALT_NAME_ID = 1;
0127 private static final int NAME_CONSTRAINTS_ID = 2;
0128 private static final int CERT_POLICIES_ID = 3;
0129 private static final int EXTENDED_KEY_USAGE_ID = 4;
0130 private static final int NUM_OF_EXTENSIONS = 5;
0131 private static final String[] EXTENSION_OIDS = new String[NUM_OF_EXTENSIONS];
0132
0133 static {
0134 EXTENSION_OIDS[PRIVATE_KEY_USAGE_ID] = "2.5.29.16";
0135 EXTENSION_OIDS[SUBJECT_ALT_NAME_ID] = "2.5.29.17";
0136 EXTENSION_OIDS[NAME_CONSTRAINTS_ID] = "2.5.29.30";
0137 EXTENSION_OIDS[CERT_POLICIES_ID] = "2.5.29.32";
0138 EXTENSION_OIDS[EXTENDED_KEY_USAGE_ID] = "2.5.29.37";
0139 };
0140
0141 /* Constants representing the GeneralName types */
0142 static final int NAME_ANY = 0;
0143 static final int NAME_RFC822 = 1;
0144 static final int NAME_DNS = 2;
0145 static final int NAME_X400 = 3;
0146 static final int NAME_DIRECTORY = 4;
0147 static final int NAME_EDI = 5;
0148 static final int NAME_URI = 6;
0149 static final int NAME_IP = 7;
0150 static final int NAME_OID = 8;
0151
0152 /**
0153 * Creates an <code>X509CertSelector</code>. Initially, no criteria are set
0154 * so any <code>X509Certificate</code> will match.
0155 */
0156 public X509CertSelector() {
0157 // empty
0158 }
0159
0160 /**
0161 * Sets the certificateEquals criterion. The specified
0162 * <code>X509Certificate</code> must be equal to the
0163 * <code>X509Certificate</code> passed to the <code>match</code> method.
0164 * If <code>null</code>, then this check is not applied.
0165 *
0166 * <p>This method is particularly useful when it is necessary to
0167 * match a single certificate. Although other criteria can be specified
0168 * in conjunction with the certificateEquals criterion, it is usually not
0169 * practical or necessary.
0170 *
0171 * @param cert the <code>X509Certificate</code> to match (or
0172 * <code>null</code>)
0173 * @see #getCertificate
0174 */
0175 public void setCertificate(X509Certificate cert) {
0176 x509Cert = cert;
0177 }
0178
0179 /**
0180 * Sets the serialNumber criterion. The specified serial number
0181 * must match the certificate serial number in the
0182 * <code>X509Certificate</code>. If <code>null</code>, any certificate
0183 * serial number will do.
0184 *
0185 * @param serial the certificate serial number to match
0186 * (or <code>null</code>)
0187 * @see #getSerialNumber
0188 */
0189 public void setSerialNumber(BigInteger serial) {
0190 serialNumber = serial;
0191 }
0192
0193 /**
0194 * Sets the issuer criterion. The specified distinguished name
0195 * must match the issuer distinguished name in the
0196 * <code>X509Certificate</code>. If <code>null</code>, any issuer
0197 * distinguished name will do.
0198 *
0199 * @param issuer a distinguished name as X500Principal
0200 * (or <code>null</code>)
0201 * @since 1.5
0202 */
0203 public void setIssuer(X500Principal issuer) {
0204 this .issuer = issuer;
0205 }
0206
0207 /**
0208 * <strong>Denigrated</strong>, use {@linkplain #setIssuer(X500Principal)}
0209 * or {@linkplain #setIssuer(byte[])} instead. This method should not be
0210 * relied on as it can fail to match some certificates because of a loss of
0211 * encoding information in the
0212 * <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a> String form
0213 * of some distinguished names.
0214 * <p>
0215 * Sets the issuer criterion. The specified distinguished name
0216 * must match the issuer distinguished name in the
0217 * <code>X509Certificate</code>. If <code>null</code>, any issuer
0218 * distinguished name will do.
0219 * <p>
0220 * If <code>issuerDN</code> is not <code>null</code>, it should contain a
0221 * distinguished name, in RFC 2253 format.
0222 *
0223 * @param issuerDN a distinguished name in RFC 2253 format
0224 * (or <code>null</code>)
0225 * @throws IOException if a parsing error occurs (incorrect form for DN)
0226 */
0227 public void setIssuer(String issuerDN) throws IOException {
0228 if (issuerDN == null) {
0229 issuer = null;
0230 } else {
0231 issuer = new X500Name(issuerDN).asX500Principal();
0232 }
0233 }
0234
0235 /**
0236 * Sets the issuer criterion. The specified distinguished name
0237 * must match the issuer distinguished name in the
0238 * <code>X509Certificate</code>. If <code>null</code> is specified,
0239 * the issuer criterion is disabled and any issuer distinguished name will
0240 * do.
0241 * <p>
0242 * If <code>issuerDN</code> is not <code>null</code>, it should contain a
0243 * single DER encoded distinguished name, as defined in X.501. The ASN.1
0244 * notation for this structure is as follows.
0245 * <pre><code>
0246 * Name ::= CHOICE {
0247 * RDNSequence }
0248 *
0249 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
0250 *
0251 * RelativeDistinguishedName ::=
0252 * SET SIZE (1 .. MAX) OF AttributeTypeAndValue
0253 *
0254 * AttributeTypeAndValue ::= SEQUENCE {
0255 * type AttributeType,
0256 * value AttributeValue }
0257 *
0258 * AttributeType ::= OBJECT IDENTIFIER
0259 *
0260 * AttributeValue ::= ANY DEFINED BY AttributeType
0261 * ....
0262 * DirectoryString ::= CHOICE {
0263 * teletexString TeletexString (SIZE (1..MAX)),
0264 * printableString PrintableString (SIZE (1..MAX)),
0265 * universalString UniversalString (SIZE (1..MAX)),
0266 * utf8String UTF8String (SIZE (1.. MAX)),
0267 * bmpString BMPString (SIZE (1..MAX)) }
0268 * </code></pre>
0269 * <p>
0270 * Note that the byte array specified here is cloned to protect against
0271 * subsequent modifications.
0272 *
0273 * @param issuerDN a byte array containing the distinguished name
0274 * in ASN.1 DER encoded form (or <code>null</code>)
0275 * @throws IOException if an encoding error occurs (incorrect form for DN)
0276 */
0277 public void setIssuer(byte[] issuerDN) throws IOException {
0278 try {
0279 issuer = (issuerDN == null ? null : new X500Principal(
0280 issuerDN));
0281 } catch (IllegalArgumentException e) {
0282 throw (IOException) new IOException("Invalid name")
0283 .initCause(e);
0284 }
0285 }
0286
0287 /**
0288 * Sets the subject criterion. The specified distinguished name
0289 * must match the subject distinguished name in the
0290 * <code>X509Certificate</code>. If <code>null</code>, any subject
0291 * distinguished name will do.
0292 *
0293 * @param subject a distinguished name as X500Principal
0294 * (or <code>null</code>)
0295 * @since 1.5
0296 */
0297 public void setSubject(X500Principal subject) {
0298 this .subject = subject;
0299 }
0300
0301 /**
0302 * <strong>Denigrated</strong>, use {@linkplain #setSubject(X500Principal)}
0303 * or {@linkplain #setSubject(byte[])} instead. This method should not be
0304 * relied on as it can fail to match some certificates because of a loss of
0305 * encoding information in the RFC 2253 String form of some distinguished
0306 * names.
0307 * <p>
0308 * Sets the subject criterion. The specified distinguished name
0309 * must match the subject distinguished name in the
0310 * <code>X509Certificate</code>. If <code>null</code>, any subject
0311 * distinguished name will do.
0312 * <p>
0313 * If <code>subjectDN</code> is not <code>null</code>, it should contain a
0314 * distinguished name, in RFC 2253 format.
0315 *
0316 * @param subjectDN a distinguished name in RFC 2253 format
0317 * (or <code>null</code>)
0318 * @throws IOException if a parsing error occurs (incorrect form for DN)
0319 */
0320 public void setSubject(String subjectDN) throws IOException {
0321 if (subjectDN == null) {
0322 subject = null;
0323 } else {
0324 subject = new X500Name(subjectDN).asX500Principal();
0325 }
0326 }
0327
0328 /**
0329 * Sets the subject criterion. The specified distinguished name
0330 * must match the subject distinguished name in the
0331 * <code>X509Certificate</code>. If <code>null</code>, any subject
0332 * distinguished name will do.
0333 * <p>
0334 * If <code>subjectDN</code> is not <code>null</code>, it should contain a
0335 * single DER encoded distinguished name, as defined in X.501. For the ASN.1
0336 * notation for this structure, see
0337 * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
0338 *
0339 * @param subjectDN a byte array containing the distinguished name in
0340 * ASN.1 DER format (or <code>null</code>)
0341 * @throws IOException if an encoding error occurs (incorrect form for DN)
0342 */
0343 public void setSubject(byte[] subjectDN) throws IOException {
0344 try {
0345 subject = (subjectDN == null ? null : new X500Principal(
0346 subjectDN));
0347 } catch (IllegalArgumentException e) {
0348 throw (IOException) new IOException("Invalid name")
0349 .initCause(e);
0350 }
0351 }
0352
0353 /**
0354 * Sets the subjectKeyIdentifier criterion. The
0355 * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
0356 * extension for which the contents of the extension
0357 * matches the specified criterion value.
0358 * If the criterion value is <code>null</code>, no
0359 * subjectKeyIdentifier check will be done.
0360 * <p>
0361 * If <code>subjectKeyID</code> is not <code>null</code>, it
0362 * should contain a single DER encoded value corresponding to the contents
0363 * of the extension value (not including the object identifier,
0364 * criticality setting, and encapsulating OCTET STRING)
0365 * for a SubjectKeyIdentifier extension.
0366 * The ASN.1 notation for this structure follows.
0367 * <p>
0368 * <pre><code>
0369 * SubjectKeyIdentifier ::= KeyIdentifier
0370 *
0371 * KeyIdentifier ::= OCTET STRING
0372 * </code></pre>
0373 * <p>
0374 * Since the format of subject key identifiers is not mandated by
0375 * any standard, subject key identifiers are not parsed by the
0376 * <code>X509CertSelector</code>. Instead, the values are compared using
0377 * a byte-by-byte comparison.
0378 * <p>
0379 * Note that the byte array supplied here is cloned to protect against
0380 * subsequent modifications.
0381 *
0382 * @param subjectKeyID the subject key identifier (or <code>null</code>)
0383 * @see #getSubjectKeyIdentifier
0384 */
0385 public void setSubjectKeyIdentifier(byte[] subjectKeyID) {
0386 if (subjectKeyID == null) {
0387 this .subjectKeyID = null;
0388 } else {
0389 this .subjectKeyID = (byte[]) subjectKeyID.clone();
0390 }
0391 }
0392
0393 /**
0394 * Sets the authorityKeyIdentifier criterion. The
0395 * <code>X509Certificate</code> must contain an
0396 * AuthorityKeyIdentifier extension for which the contents of the
0397 * extension value matches the specified criterion value.
0398 * If the criterion value is <code>null</code>, no
0399 * authorityKeyIdentifier check will be done.
0400 * <p>
0401 * If <code>authorityKeyID</code> is not <code>null</code>, it
0402 * should contain a single DER encoded value corresponding to the contents
0403 * of the extension value (not including the object identifier,
0404 * criticality setting, and encapsulating OCTET STRING)
0405 * for an AuthorityKeyIdentifier extension.
0406 * The ASN.1 notation for this structure follows.
0407 * <p>
0408 * <pre><code>
0409 * AuthorityKeyIdentifier ::= SEQUENCE {
0410 * keyIdentifier [0] KeyIdentifier OPTIONAL,
0411 * authorityCertIssuer [1] GeneralNames OPTIONAL,
0412 * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
0413 *
0414 * KeyIdentifier ::= OCTET STRING
0415 * </code></pre>
0416 * <p>
0417 * Authority key identifiers are not parsed by the
0418 * <code>X509CertSelector</code>. Instead, the values are
0419 * compared using a byte-by-byte comparison.
0420 * <p>
0421 * When the <code>keyIdentifier</code> field of
0422 * <code>AuthorityKeyIdentifier</code> is populated, the value is
0423 * usually taken from the <code>SubjectKeyIdentifier</code> extension
0424 * in the issuer's certificate. Note, however, that the result of
0425 * <code>X509Certificate.getExtensionValue(<SubjectKeyIdentifier Object
0426 * Identifier>)</code> on the issuer's certificate may NOT be used
0427 * directly as the input to <code>setAuthorityKeyIdentifier</code>.
0428 * This is because the SubjectKeyIdentifier contains
0429 * only a KeyIdentifier OCTET STRING, and not a SEQUENCE of
0430 * KeyIdentifier, GeneralNames, and CertificateSerialNumber.
0431 * In order to use the extension value of the issuer certificate's
0432 * <code>SubjectKeyIdentifier</code>
0433 * extension, it will be necessary to extract the value of the embedded
0434 * <code>KeyIdentifier</code> OCTET STRING, then DER encode this OCTET
0435 * STRING inside a SEQUENCE.
0436 * For more details on SubjectKeyIdentifier, see
0437 * {@link #setSubjectKeyIdentifier(byte[] subjectKeyID)}.
0438 * <p>
0439 * Note also that the byte array supplied here is cloned to protect against
0440 * subsequent modifications.
0441 *
0442 * @param authorityKeyID the authority key identifier
0443 * (or <code>null</code>)
0444 * @see #getAuthorityKeyIdentifier
0445 */
0446 public void setAuthorityKeyIdentifier(byte[] authorityKeyID) {
0447 if (authorityKeyID == null) {
0448 this .authorityKeyID = null;
0449 } else {
0450 this .authorityKeyID = (byte[]) authorityKeyID.clone();
0451 }
0452 }
0453
0454 /**
0455 * Sets the certificateValid criterion. The specified date must fall
0456 * within the certificate validity period for the
0457 * <code>X509Certificate</code>. If <code>null</code>, no certificateValid
0458 * check will be done.
0459 * <p>
0460 * Note that the <code>Date</code> supplied here is cloned to protect
0461 * against subsequent modifications.
0462 *
0463 * @param certValid the <code>Date</code> to check (or <code>null</code>)
0464 * @see #getCertificateValid
0465 */
0466 public void setCertificateValid(Date certValid) {
0467 if (certValid == null) {
0468 certificateValid = null;
0469 } else {
0470 certificateValid = (Date) certValid.clone();
0471 }
0472 }
0473
0474 /**
0475 * Sets the privateKeyValid criterion. The specified date must fall
0476 * within the private key validity period for the
0477 * <code>X509Certificate</code>. If <code>null</code>, no privateKeyValid
0478 * check will be done.
0479 * <p>
0480 * Note that the <code>Date</code> supplied here is cloned to protect
0481 * against subsequent modifications.
0482 *
0483 * @param privateKeyValid the <code>Date</code> to check (or
0484 * <code>null</code>)
0485 * @see #getPrivateKeyValid
0486 */
0487 public void setPrivateKeyValid(Date privateKeyValid) {
0488 if (privateKeyValid == null) {
0489 this .privateKeyValid = null;
0490 } else {
0491 this .privateKeyValid = (Date) privateKeyValid.clone();
0492 }
0493 }
0494
0495 /**
0496 * Sets the subjectPublicKeyAlgID criterion. The
0497 * <code>X509Certificate</code> must contain a subject public key
0498 * with the specified algorithm. If <code>null</code>, no
0499 * subjectPublicKeyAlgID check will be done.
0500 *
0501 * @param oid The object identifier (OID) of the algorithm to check
0502 * for (or <code>null</code>). An OID is represented by a
0503 * set of nonnegative integers separated by periods.
0504 * @throws IOException if the OID is invalid, such as
0505 * the first component being not 0, 1 or 2 or the second component
0506 * being greater than 39.
0507 *
0508 * @see #getSubjectPublicKeyAlgID
0509 */
0510 public void setSubjectPublicKeyAlgID(String oid) throws IOException {
0511 if (oid == null) {
0512 subjectPublicKeyAlgID = null;
0513 } else {
0514 subjectPublicKeyAlgID = new ObjectIdentifier(oid);
0515 }
0516 }
0517
0518 /**
0519 * Sets the subjectPublicKey criterion. The
0520 * <code>X509Certificate</code> must contain the specified subject public
0521 * key. If <code>null</code>, no subjectPublicKey check will be done.
0522 *
0523 * @param key the subject public key to check for (or <code>null</code>)
0524 * @see #getSubjectPublicKey
0525 */
0526 public void setSubjectPublicKey(PublicKey key) {
0527 if (key == null) {
0528 subjectPublicKey = null;
0529 subjectPublicKeyBytes = null;
0530 } else {
0531 subjectPublicKey = key;
0532 subjectPublicKeyBytes = key.getEncoded();
0533 }
0534 }
0535
0536 /**
0537 * Sets the subjectPublicKey criterion. The <code>X509Certificate</code>
0538 * must contain the specified subject public key. If <code>null</code>,
0539 * no subjectPublicKey check will be done.
0540 * <p>
0541 * Because this method allows the public key to be specified as a byte
0542 * array, it may be used for unknown key types.
0543 * <p>
0544 * If <code>key</code> is not <code>null</code>, it should contain a
0545 * single DER encoded SubjectPublicKeyInfo structure, as defined in X.509.
0546 * The ASN.1 notation for this structure is as follows.
0547 * <pre><code>
0548 * SubjectPublicKeyInfo ::= SEQUENCE {
0549 * algorithm AlgorithmIdentifier,
0550 * subjectPublicKey BIT STRING }
0551 *
0552 * AlgorithmIdentifier ::= SEQUENCE {
0553 * algorithm OBJECT IDENTIFIER,
0554 * parameters ANY DEFINED BY algorithm OPTIONAL }
0555 * -- contains a value of the type
0556 * -- registered for use with the
0557 * -- algorithm object identifier value
0558 * </code></pre>
0559 * <p>
0560 * Note that the byte array supplied here is cloned to protect against
0561 * subsequent modifications.
0562 *
0563 * @param key a byte array containing the subject public key in ASN.1 DER
0564 * form (or <code>null</code>)
0565 * @throws IOException if an encoding error occurs (incorrect form for
0566 * subject public key)
0567 * @see #getSubjectPublicKey
0568 */
0569 public void setSubjectPublicKey(byte[] key) throws IOException {
0570 if (key == null) {
0571 subjectPublicKey = null;
0572 subjectPublicKeyBytes = null;
0573 } else {
0574 subjectPublicKeyBytes = (byte[]) key.clone();
0575 subjectPublicKey = X509Key.parse(new DerValue(
0576 subjectPublicKeyBytes));
0577 }
0578 }
0579
0580 /**
0581 * Sets the keyUsage criterion. The <code>X509Certificate</code>
0582 * must allow the specified keyUsage values. If <code>null</code>, no
0583 * keyUsage check will be done. Note that an <code>X509Certificate</code>
0584 * that has no keyUsage extension implicitly allows all keyUsage values.
0585 * <p>
0586 * Note that the boolean array supplied here is cloned to protect against
0587 * subsequent modifications.
0588 *
0589 * @param keyUsage a boolean array in the same format as the boolean
0590 * array returned by
0591 * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
0592 * Or <code>null</code>.
0593 * @see #getKeyUsage
0594 */
0595 public void setKeyUsage(boolean[] keyUsage) {
0596 if (keyUsage == null) {
0597 this .keyUsage = null;
0598 } else {
0599 this .keyUsage = (boolean[]) keyUsage.clone();
0600 }
0601 }
0602
0603 /**
0604 * Sets the extendedKeyUsage criterion. The <code>X509Certificate</code>
0605 * must allow the specified key purposes in its extended key usage
0606 * extension. If <code>keyPurposeSet</code> is empty or <code>null</code>,
0607 * no extendedKeyUsage check will be done. Note that an
0608 * <code>X509Certificate</code> that has no extendedKeyUsage extension
0609 * implicitly allows all key purposes.
0610 * <p>
0611 * Note that the <code>Set</code> is cloned to protect against
0612 * subsequent modifications.
0613 *
0614 * @param keyPurposeSet a <code>Set</code> of key purpose OIDs in string
0615 * format (or <code>null</code>). Each OID is represented by a set of
0616 * nonnegative integers separated by periods.
0617 * @throws IOException if the OID is invalid, such as
0618 * the first component being not 0, 1 or 2 or the second component
0619 * being greater than 39.
0620 * @see #getExtendedKeyUsage
0621 */
0622 public void setExtendedKeyUsage(Set<String> keyPurposeSet)
0623 throws IOException {
0624 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
0625 this .keyPurposeSet = null;
0626 keyPurposeOIDSet = null;
0627 } else {
0628 this .keyPurposeSet = Collections
0629 .unmodifiableSet(new HashSet<String>(keyPurposeSet));
0630 keyPurposeOIDSet = new HashSet<ObjectIdentifier>();
0631 for (String s : this .keyPurposeSet) {
0632 keyPurposeOIDSet.add(new ObjectIdentifier(s));
0633 }
0634 }
0635 }
0636
0637 /**
0638 * Enables/disables matching all of the subjectAlternativeNames
0639 * specified in the {@link #setSubjectAlternativeNames
0640 * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
0641 * addSubjectAlternativeName} methods. If enabled,
0642 * the <code>X509Certificate</code> must contain all of the
0643 * specified subject alternative names. If disabled, the
0644 * <code>X509Certificate</code> must contain at least one of the
0645 * specified subject alternative names.
0646 *
0647 * <p>The matchAllNames flag is <code>true</code> by default.
0648 *
0649 * @param matchAllNames if <code>true</code>, the flag is enabled;
0650 * if <code>false</code>, the flag is disabled.
0651 * @see #getMatchAllSubjectAltNames
0652 */
0653 public void setMatchAllSubjectAltNames(boolean matchAllNames) {
0654 this .matchAllSubjectAltNames = matchAllNames;
0655 }
0656
0657 /**
0658 * Sets the subjectAlternativeNames criterion. The
0659 * <code>X509Certificate</code> must contain all or at least one of the
0660 * specified subjectAlternativeNames, depending on the value of
0661 * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
0662 * setMatchAllSubjectAltNames}).
0663 * <p>
0664 * This method allows the caller to specify, with a single method call,
0665 * the complete set of subject alternative names for the
0666 * subjectAlternativeNames criterion. The specified value replaces
0667 * the previous value for the subjectAlternativeNames criterion.
0668 * <p>
0669 * The <code>names</code> parameter (if not <code>null</code>) is a
0670 * <code>Collection</code> with one
0671 * entry for each name to be included in the subject alternative name
0672 * criterion. Each entry is a <code>List</code> whose first entry is an
0673 * <code>Integer</code> (the name type, 0-8) and whose second
0674 * entry is a <code>String</code> or a byte array (the name, in
0675 * string or ASN.1 DER encoded form, respectively).
0676 * There can be multiple names of the same type. If <code>null</code>
0677 * is supplied as the value for this argument, no
0678 * subjectAlternativeNames check will be performed.
0679 * <p>
0680 * Each subject alternative name in the <code>Collection</code>
0681 * may be specified either as a <code>String</code> or as an ASN.1 encoded
0682 * byte array. For more details about the formats used, see
0683 * {@link #addSubjectAlternativeName(int type, String name)
0684 * addSubjectAlternativeName(int type, String name)} and
0685 * {@link #addSubjectAlternativeName(int type, byte [] name)
0686 * addSubjectAlternativeName(int type, byte [] name)}.
0687 * <p>
0688 * <strong>Note:</strong> for distinguished names, specify the byte
0689 * array form instead of the String form. See the note in
0690 * {@link #addSubjectAlternativeName(int, String)} for more information.
0691 * <p>
0692 * Note that the <code>names</code> parameter can contain duplicate
0693 * names (same name and name type), but they may be removed from the
0694 * <code>Collection</code> of names returned by the
0695 * {@link #getSubjectAlternativeNames getSubjectAlternativeNames} method.
0696 * <p>
0697 * Note that a deep copy is performed on the <code>Collection</code> to
0698 * protect against subsequent modifications.
0699 *
0700 * @param names a <code>Collection</code> of names (or <code>null</code>)
0701 * @throws IOException if a parsing error occurs
0702 * @see #getSubjectAlternativeNames
0703 */
0704 public void setSubjectAlternativeNames(Collection<List<?>> names)
0705 throws IOException {
0706 if (names == null) {
0707 subjectAlternativeNames = null;
0708 subjectAlternativeGeneralNames = null;
0709 } else {
0710 if (names.isEmpty()) {
0711 subjectAlternativeNames = null;
0712 subjectAlternativeGeneralNames = null;
0713 return;
0714 }
0715 Set<List<?>> tempNames = cloneAndCheckNames(names);
0716 // Ensure that we either set both of these or neither
0717 subjectAlternativeGeneralNames = parseNames(tempNames);
0718 subjectAlternativeNames = tempNames;
0719 }
0720 }
0721
0722 /**
0723 * Adds a name to the subjectAlternativeNames criterion. The
0724 * <code>X509Certificate</code> must contain all or at least one
0725 * of the specified subjectAlternativeNames, depending on the value of
0726 * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
0727 * setMatchAllSubjectAltNames}).
0728 * <p>
0729 * This method allows the caller to add a name to the set of subject
0730 * alternative names.
0731 * The specified name is added to any previous value for the
0732 * subjectAlternativeNames criterion. If the specified name is a
0733 * duplicate, it may be ignored.
0734 * <p>
0735 * The name is provided in string format.
0736 * <a href="http://www.ietf.org/rfc/rfc822.txt">RFC 822</a>, DNS, and URI
0737 * names use the well-established string formats for those types (subject to
0738 * the restrictions included in RFC 3280). IPv4 address names are
0739 * supplied using dotted quad notation. OID address names are represented
0740 * as a series of nonnegative integers separated by periods. And
0741 * directory names (distinguished names) are supplied in RFC 2253 format.
0742 * No standard string format is defined for otherNames, X.400 names,
0743 * EDI party names, IPv6 address names, or any other type of names. They
0744 * should be specified using the
0745 * {@link #addSubjectAlternativeName(int type, byte [] name)
0746 * addSubjectAlternativeName(int type, byte [] name)}
0747 * method.
0748 * <p>
0749 * <strong>Note:</strong> for distinguished names, use
0750 * {@linkplain #addSubjectAlternativeName(int, byte[])} instead.
0751 * This method should not be relied on as it can fail to match some
0752 * certificates because of a loss of encoding information in the RFC 2253
0753 * String form of some distinguished names.
0754 *
0755 * @param type the name type (0-8, as specified in
0756 * RFC 3280, section 4.2.1.7)
0757 * @param name the name in string form (not <code>null</code>)
0758 * @throws IOException if a parsing error occurs
0759 */
0760 public void addSubjectAlternativeName(int type, String name)
0761 throws IOException {
0762 addSubjectAlternativeNameInternal(type, name);
0763 }
0764
0765 /**
0766 * Adds a name to the subjectAlternativeNames criterion. The
0767 * <code>X509Certificate</code> must contain all or at least one
0768 * of the specified subjectAlternativeNames, depending on the value of
0769 * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
0770 * setMatchAllSubjectAltNames}).
0771 * <p>
0772 * This method allows the caller to add a name to the set of subject
0773 * alternative names.
0774 * The specified name is added to any previous value for the
0775 * subjectAlternativeNames criterion. If the specified name is a
0776 * duplicate, it may be ignored.
0777 * <p>
0778 * The name is provided as a byte array. This byte array should contain
0779 * the DER encoded name, as it would appear in the GeneralName structure
0780 * defined in RFC 3280 and X.509. The encoded byte array should only contain
0781 * the encoded value of the name, and should not include the tag associated
0782 * with the name in the GeneralName structure. The ASN.1 definition of this
0783 * structure appears below.
0784 * <pre><code>
0785 * GeneralName ::= CHOICE {
0786 * otherName [0] OtherName,
0787 * rfc822Name [1] IA5String,
0788 * dNSName [2] IA5String,
0789 * x400Address [3] ORAddress,
0790 * directoryName [4] Name,
0791 * ediPartyName [5] EDIPartyName,
0792 * uniformResourceIdentifier [6] IA5String,
0793 * iPAddress [7] OCTET STRING,
0794 * registeredID [8] OBJECT IDENTIFIER}
0795 * </code></pre>
0796 * <p>
0797 * Note that the byte array supplied here is cloned to protect against
0798 * subsequent modifications.
0799 *
0800 * @param type the name type (0-8, as listed above)
0801 * @param name a byte array containing the name in ASN.1 DER encoded form
0802 * @throws IOException if a parsing error occurs
0803 */
0804 public void addSubjectAlternativeName(int type, byte[] name)
0805 throws IOException {
0806 // clone because byte arrays are modifiable
0807 addSubjectAlternativeNameInternal(type, name.clone());
0808 }
0809
0810 /**
0811 * A private method that adds a name (String or byte array) to the
0812 * subjectAlternativeNames criterion. The <code>X509Certificate</code>
0813 * must contain the specified subjectAlternativeName.
0814 *
0815 * @param type the name type (0-8, as specified in
0816 * RFC 3280, section 4.2.1.7)
0817 * @param name the name in string or byte array form
0818 * @throws IOException if a parsing error occurs
0819 */
0820 private void addSubjectAlternativeNameInternal(int type, Object name)
0821 throws IOException {
0822 // First, ensure that the name parses
0823 GeneralNameInterface tempName = makeGeneralNameInterface(type,
0824 name);
0825 if (subjectAlternativeNames == null) {
0826 subjectAlternativeNames = new HashSet<List<?>>();
0827 }
0828 if (subjectAlternativeGeneralNames == null) {
0829 subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>();
0830 }
0831 List<Object> list = new ArrayList<Object>(2);
0832 list.add(Integer.valueOf(type));
0833 list.add(name);
0834 subjectAlternativeNames.add(list);
0835 subjectAlternativeGeneralNames.add(tempName);
0836 }
0837
0838 /**
0839 * Parse an argument of the form passed to setSubjectAlternativeNames,
0840 * returning a <code>Collection</code> of
0841 * <code>GeneralNameInterface</code>s.
0842 * Throw an IllegalArgumentException or a ClassCastException
0843 * if the argument is malformed.
0844 *
0845 * @param names a Collection with one entry per name.
0846 * Each entry is a <code>List</code> whose first entry
0847 * is an Integer (the name type, 0-8) and whose second
0848 * entry is a String or a byte array (the name, in
0849 * string or ASN.1 DER encoded form, respectively).
0850 * There can be multiple names of the same type. Null is
0851 * not an acceptable value.
0852 * @return a Set of <code>GeneralNameInterface</code>s
0853 * @throws IOException if a parsing error occurs
0854 */
0855 private static Set<GeneralNameInterface> parseNames(
0856 Collection<List<?>> names) throws IOException {
0857 Set<GeneralNameInterface> genNames = new HashSet<GeneralNameInterface>();
0858 for (List<?> nameList : names) {
0859 if (nameList.size() != 2) {
0860 throw new IOException("name list size not 2");
0861 }
0862 Object o = nameList.get(0);
0863 if (!(o instanceof Integer)) {
0864 throw new IOException("expected an Integer");
0865 }
0866 int nameType = ((Integer) o).intValue();
0867 o = nameList.get(1);
0868 genNames.add(makeGeneralNameInterface(nameType, o));
0869 }
0870
0871 return genNames;
0872 }
0873
0874 /**
0875 * Compare for equality two objects of the form passed to
0876 * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames).
0877 * Throw an <code>IllegalArgumentException</code> or a
0878 * <code>ClassCastException</code> if one of the objects is malformed.
0879 *
0880 * @param object1 a Collection containing the first object to compare
0881 * @param object2 a Collection containing the second object to compare
0882 * @return true if the objects are equal, false otherwise
0883 */
0884 static boolean equalNames(Collection object1, Collection object2) {
0885 if ((object1 == null) || (object2 == null)) {
0886 return object1 == object2;
0887 }
0888 return object1.equals(object2);
0889 }
0890
0891 /**
0892 * Make a <code>GeneralNameInterface</code> out of a name type (0-8) and an
0893 * Object that may be a byte array holding the ASN.1 DER encoded
0894 * name or a String form of the name. Except for X.509
0895 * Distinguished Names, the String form of the name must not be the
0896 * result from calling toString on an existing GeneralNameInterface
0897 * implementing class. The output of toString is not compatible
0898 * with the String constructors for names other than Distinguished
0899 * Names.
0900 *
0901 * @param type name type (0-8)
0902 * @param name name as ASN.1 Der-encoded byte array or String
0903 * @return a GeneralNameInterface name
0904 * @throws IOException if a parsing error occurs
0905 */
0906 static GeneralNameInterface makeGeneralNameInterface(int type,
0907 Object name) throws IOException {
0908 GeneralNameInterface result;
0909 if (debug != null) {
0910 debug.println("X509CertSelector.makeGeneralNameInterface("
0911 + type + ")...");
0912 }
0913
0914 if (name instanceof String) {
0915 if (debug != null) {
0916 debug
0917 .println("X509CertSelector.makeGeneralNameInterface() "
0918 + "name is String: " + name);
0919 }
0920 switch (type) {
0921 case NAME_RFC822:
0922 result = new RFC822Name((String) name);
0923 break;
0924 case NAME_DNS:
0925 result = new DNSName((String) name);
0926 break;
0927 case NAME_DIRECTORY:
0928 result = new X500Name((String) name);
0929 break;
0930 case NAME_URI:
0931 result = new URIName((String) name);
0932 break;
0933 case NAME_IP:
0934 result = new IPAddressName((String) name);
0935 break;
0936 case NAME_OID:
0937 result = new OIDName((String) name);
0938 break;
0939 default:
0940 throw new IOException(
0941 "unable to parse String names of type " + type);
0942 }
0943 if (debug != null) {
0944 debug
0945 .println("X509CertSelector.makeGeneralNameInterface() "
0946 + "result: " + result.toString());
0947 }
0948 } else if (name instanceof byte[]) {
0949 DerValue val = new DerValue((byte[]) name);
0950 if (debug != null) {
0951 debug
0952 .println("X509CertSelector.makeGeneralNameInterface() is byte[]");
0953 }
0954
0955 switch (type) {
0956 case NAME_ANY:
0957 result = new OtherName(val);
0958 break;
0959 case NAME_RFC822:
0960 result = new RFC822Name(val);
0961 break;
0962 case NAME_DNS:
0963 result = new DNSName(val);
0964 break;
0965 case NAME_X400:
0966 result = new X400Address(val);
0967 break;
0968 case NAME_DIRECTORY:
0969 result = new X500Name(val);
0970 break;
0971 case NAME_EDI:
0972 result = new EDIPartyName(val);
0973 break;
0974 case NAME_URI:
0975 result = new URIName(val);
0976 break;
0977 case NAME_IP:
0978 result = new IPAddressName(val);
0979 break;
0980 case NAME_OID:
0981 result = new OIDName(val);
0982 break;
0983 default:
0984 throw new IOException(
0985 "unable to parse byte array names of "
0986 + "type " + type);
0987 }
0988 if (debug != null) {
0989 debug
0990 .println("X509CertSelector.makeGeneralNameInterface() result: "
0991 + result.toString());
0992 }
0993 } else {
0994 if (debug != null) {
0995 debug
0996 .println("X509CertSelector.makeGeneralName() input name "
0997 + "not String or byte array");
0998 }
0999 throw new IOException("name not String or byte array");
1000 }
1001 return result;
1002 }
1003
1004 /**
1005 * Sets the name constraints criterion. The <code>X509Certificate</code>
1006 * must have subject and subject alternative names that
1007 * meet the specified name constraints.
1008 * <p>
1009 * The name constraints are specified as a byte array. This byte array
1010 * should contain the DER encoded form of the name constraints, as they
1011 * would appear in the NameConstraints structure defined in RFC 3280
1012 * and X.509. The ASN.1 definition of this structure appears below.
1013 *
1014 * <pre><code>
1015 * NameConstraints ::= SEQUENCE {
1016 * permittedSubtrees [0] GeneralSubtrees OPTIONAL,
1017 * excludedSubtrees [1] GeneralSubtrees OPTIONAL }
1018 *
1019 * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
1020 *
1021 * GeneralSubtree ::= SEQUENCE {
1022 * base GeneralName,
1023 * minimum [0] BaseDistance DEFAULT 0,
1024 * maximum [1] BaseDistance OPTIONAL }
1025 *
1026 * BaseDistance ::= INTEGER (0..MAX)
1027 *
1028 * GeneralName ::= CHOICE {
1029 * otherName [0] OtherName,
1030 * rfc822Name [1] IA5String,
1031 * dNSName [2] IA5String,
1032 * x400Address [3] ORAddress,
1033 * directoryName [4] Name,
1034 * ediPartyName [5] EDIPartyName,
1035 * uniformResourceIdentifier [6] IA5String,
1036 * iPAddress [7] OCTET STRING,
1037 * registeredID [8] OBJECT IDENTIFIER}
1038 * </code></pre>
1039 * <p>
1040 * Note that the byte array supplied here is cloned to protect against
1041 * subsequent modifications.
1042 *
1043 * @param bytes a byte array containing the ASN.1 DER encoding of
1044 * a NameConstraints extension to be used for checking
1045 * name constraints. Only the value of the extension is
1046 * included, not the OID or criticality flag. Can be
1047 * <code>null</code>,
1048 * in which case no name constraints check will be performed.
1049 * @throws IOException if a parsing error occurs
1050 * @see #getNameConstraints
1051 */
1052 public void setNameConstraints(byte[] bytes) throws IOException {
1053 if (bytes == null) {
1054 ncBytes = null;
1055 nc = null;
1056 } else {
1057 ncBytes = (byte[]) bytes.clone();
1058 nc = new NameConstraintsExtension(FALSE, bytes);
1059 }
1060 }
1061
1062 /**
1063 * Sets the basic constraints constraint. If the value is greater than or
1064 * equal to zero, <code>X509Certificates</code> must include a
1065 * basicConstraints extension with
1066 * a pathLen of at least this value. If the value is -2, only end-entity
1067 * certificates are accepted. If the value is -1, no check is done.
1068 * <p>
1069 * This constraint is useful when building a certification path forward
1070 * (from the target toward the trust anchor. If a partial path has been
1071 * built, any candidate certificate must have a maxPathLen value greater
1072 * than or equal to the number of certificates in the partial path.
1073 *
1074 * @param minMaxPathLen the value for the basic constraints constraint
1075 * @throws IllegalArgumentException if the value is less than -2
1076 * @see #getBasicConstraints
1077 */
1078 public void setBasicConstraints(int minMaxPathLen) {
1079 if (minMaxPathLen < -2) {
1080 throw new IllegalArgumentException(
1081 "basic constraints less than -2");
1082 }
1083 basicConstraints = minMaxPathLen;
1084 }
1085
1086 /**
1087 * Sets the policy constraint. The <code>X509Certificate</code> must
1088 * include at least one of the specified policies in its certificate
1089 * policies extension. If <code>certPolicySet</code> is empty, then the
1090 * <code>X509Certificate</code> must include at least some specified policy
1091 * in its certificate policies extension. If <code>certPolicySet</code> is
1092 * <code>null</code>, no policy check will be performed.
1093 * <p>
1094 * Note that the <code>Set</code> is cloned to protect against
1095 * subsequent modifications.
1096 *
1097 * @param certPolicySet a <code>Set</code> of certificate policy OIDs in
1098 * string format (or <code>null</code>). Each OID is
1099 * represented by a set of nonnegative integers
1100 * separated by periods.
1101 * @throws IOException if a parsing error occurs on the OID such as
1102 * the first component is not 0, 1 or 2 or the second component is
1103 * greater than 39.
1104 * @see #getPolicy
1105 */
1106 public void setPolicy(Set<String> certPolicySet) throws IOException {
1107 if (certPolicySet == null) {
1108 policySet = null;
1109 policy = null;
1110 } else {
1111 // Snapshot set and parse it
1112 Set<String> tempSet = Collections
1113 .unmodifiableSet(new HashSet<String>(certPolicySet));
1114 /* Convert to Vector of ObjectIdentifiers */
1115 Iterator<String> i = tempSet.iterator();
1116 Vector<CertificatePolicyId> polIdVector = new Vector<CertificatePolicyId>();
1117 while (i.hasNext()) {
1118 Object o = i.next();
1119 if (!(o instanceof String)) {
1120 throw new IOException("non String in certPolicySet");
1121 }
1122 polIdVector.add(new CertificatePolicyId(
1123 new ObjectIdentifier((String) o)));
1124 }
1125 // If everything went OK, make the changes
1126 policySet = tempSet;
1127 policy = new CertificatePolicySet(polIdVector);
1128 }
1129 }
1130
1131 /**
1132 * Sets the pathToNames criterion. The <code>X509Certificate</code> must
1133 * not include name constraints that would prohibit building a
1134 * path to the specified names.
1135 * <p>
1136 * This method allows the caller to specify, with a single method call,
1137 * the complete set of names which the <code>X509Certificates</code>'s
1138 * name constraints must permit. The specified value replaces
1139 * the previous value for the pathToNames criterion.
1140 * <p>
1141 * This constraint is useful when building a certification path forward
1142 * (from the target toward the trust anchor. If a partial path has been
1143 * built, any candidate certificate must not include name constraints that
1144 * would prohibit building a path to any of the names in the partial path.
1145 * <p>
1146 * The <code>names</code> parameter (if not <code>null</code>) is a
1147 * <code>Collection</code> with one
1148 * entry for each name to be included in the pathToNames
1149 * criterion. Each entry is a <code>List</code> whose first entry is an
1150 * <code>Integer</code> (the name type, 0-8) and whose second
1151 * entry is a <code>String</code> or a byte array (the name, in
1152 * string or ASN.1 DER encoded form, respectively).
1153 * There can be multiple names of the same type. If <code>null</code>
1154 * is supplied as the value for this argument, no
1155 * pathToNames check will be performed.
1156 * <p>
1157 * Each name in the <code>Collection</code>
1158 * may be specified either as a <code>String</code> or as an ASN.1 encoded
1159 * byte array. For more details about the formats used, see
1160 * {@link #addPathToName(int type, String name)
1161 * addPathToName(int type, String name)} and
1162 * {@link #addPathToName(int type, byte [] name)
1163 * addPathToName(int type, byte [] name)}.
1164 * <p>
1165 * <strong>Note:</strong> for distinguished names, specify the byte
1166 * array form instead of the String form. See the note in
1167 * {@link #addPathToName(int, String)} for more information.
1168 * <p>
1169 * Note that the <code>names</code> parameter can contain duplicate
1170 * names (same name and name type), but they may be removed from the
1171 * <code>Collection</code> of names returned by the
1172 * {@link #getPathToNames getPathToNames} method.
1173 * <p>
1174 * Note that a deep copy is performed on the <code>Collection</code> to
1175 * protect against subsequent modifications.
1176 *
1177 * @param names a <code>Collection</code> with one entry per name
1178 * (or <code>null</code>)
1179 * @throws IOException if a parsing error occurs
1180 * @see #getPathToNames
1181 */
1182 public void setPathToNames(Collection<List<?>> names)
1183 throws IOException {
1184 if ((names == null) || names.isEmpty()) {
1185 pathToNames = null;
1186 pathToGeneralNames = null;
1187 } else {
1188 Set<List<?>> tempNames = cloneAndCheckNames(names);
1189 pathToGeneralNames = parseNames(tempNames);
1190 // Ensure that we either set both of these or neither
1191 pathToNames = tempNames;
1192 }
1193 }
1194
1195 // called from CertPathHelper
1196 void setPathToNamesInternal(Set<GeneralNameInterface> names) {
1197 // set names to non-null dummy value
1198 // this breaks getPathToNames()
1199 pathToNames = Collections.<List<?>> emptySet();
1200 pathToGeneralNames = names;
1201 }
1202
1203 /**
1204 * Adds a name to the pathToNames criterion. The <code>X509Certificate</code>
1205 * must not include name constraints that would prohibit building a
1206 * path to the specified name.
1207 * <p>
1208 * This method allows the caller to add a name to the set of names which
1209 * the <code>X509Certificates</code>'s name constraints must permit.
1210 * The specified name is added to any previous value for the
1211 * pathToNames criterion. If the name is a duplicate, it may be ignored.
1212 * <p>
1213 * The name is provided in string format. RFC 822, DNS, and URI names
1214 * use the well-established string formats for those types (subject to
1215 * the restrictions included in RFC 3280). IPv4 address names are
1216 * supplied using dotted quad notation. OID address names are represented
1217 * as a series of nonnegative integers separated by periods. And
1218 * directory names (distinguished names) are supplied in RFC 2253 format.
1219 * No standard string format is defined for otherNames, X.400 names,
1220 * EDI party names, IPv6 address names, or any other type of names. They
1221 * should be specified using the
1222 * {@link #addPathToName(int type, byte [] name)
1223 * addPathToName(int type, byte [] name)} method.
1224 * <p>
1225 * <strong>Note:</strong> for distinguished names, use
1226 * {@linkplain #addPathToName(int, byte[])} instead.
1227 * This method should not be relied on as it can fail to match some
1228 * certificates because of a loss of encoding information in the RFC 2253
1229 * String form of some distinguished names.
1230 *
1231 * @param type the name type (0-8, as specified in
1232 * RFC 3280, section 4.2.1.7)
1233 * @param name the name in string form
1234 * @throws IOException if a parsing error occurs
1235 */
1236 public void addPathToName(int type, String name) throws IOException {
1237 addPathToNameInternal(type, name);
1238 }
1239
1240 /**
1241 * Adds a name to the pathToNames criterion. The <code>X509Certificate</code>
1242 * must not include name constraints that would prohibit building a
1243 * path to the specified name.
1244 * <p>
1245 * This method allows the caller to add a name to the set of names which
1246 * the <code>X509Certificates</code>'s name constraints must permit.
1247 * The specified name is added to any previous value for the
1248 * pathToNames criterion. If the name is a duplicate, it may be ignored.
1249 * <p>
1250 * The name is provided as a byte array. This byte array should contain
1251 * the DER encoded name, as it would appear in the GeneralName structure
1252 * defined in RFC 3280 and X.509. The ASN.1 definition of this structure
1253 * appears in the documentation for
1254 * {@link #addSubjectAlternativeName(int type, byte [] name)
1255 * addSubjectAlternativeName(int type, byte [] name)}.
1256 * <p>
1257 * Note that the byte array supplied here is cloned to protect against
1258 * subsequent modifications.
1259 *
1260 * @param type the name type (0-8, as specified in
1261 * RFC 3280, section 4.2.1.7)
1262 * @param name a byte array containing the name in ASN.1 DER encoded form
1263 * @throws IOException if a parsing error occurs
1264 */
1265 public void addPathToName(int type, byte[] name) throws IOException {
1266 // clone because byte arrays are modifiable
1267 addPathToNameInternal(type, name.clone());
1268 }
1269
1270 /**
1271 * A private method that adds a name (String or byte array) to the
1272 * pathToNames criterion. The <code>X509Certificate</code> must contain
1273 * the specified pathToName.
1274 *
1275 * @param type the name type (0-8, as specified in
1276 * RFC 3280, section 4.2.1.7)
1277 * @param name the name in string or byte array form
1278 * @throws IOException if an encoding error occurs (incorrect form for DN)
1279 */
1280 private void addPathToNameInternal(int type, Object name)
1281 throws IOException {
1282 // First, ensure that the name parses
1283 GeneralNameInterface tempName = makeGeneralNameInterface(type,
1284 name);
1285 if (pathToGeneralNames == null) {
1286 pathToNames = new HashSet<List<?>>();
1287 pathToGeneralNames = new HashSet<GeneralNameInterface>();
1288 }
1289 List<Object> list = new ArrayList<Object>(2);
1290 list.add(Integer.valueOf(type));
1291 list.add(name);
1292 pathToNames.add(list);
1293 pathToGeneralNames.add(tempName);
1294 }
1295
1296 /**
1297 * Returns the certificateEquals criterion. The specified
1298 * <code>X509Certificate</code> must be equal to the
1299 * <code>X509Certificate</code> passed to the <code>match</code> method.
1300 * If <code>null</code>, this check is not applied.
1301 *
1302 * @return the <code>X509Certificate</code> to match (or <code>null</code>)
1303 * @see #setCertificate
1304 */
1305 public X509Certificate getCertificate() {
1306 return x509Cert;
1307 }
1308
1309 /**
1310 * Returns the serialNumber criterion. The specified serial number
1311 * must match the certificate serial number in the
1312 * <code>X509Certificate</code>. If <code>null</code>, any certificate
1313 * serial number will do.
1314 *
1315 * @return the certificate serial number to match
1316 * (or <code>null</code>)
1317 * @see #setSerialNumber
1318 */
1319 public BigInteger getSerialNumber() {
1320 return serialNumber;
1321 }
1322
1323 /**
1324 * Returns the issuer criterion as an <code>X500Principal</code>. This
1325 * distinguished name must match the issuer distinguished name in the
1326 * <code>X509Certificate</code>. If <code>null</code>, the issuer criterion
1327 * is disabled and any issuer distinguished name will do.
1328 *
1329 * @return the required issuer distinguished name as X500Principal
1330 * (or <code>null</code>)
1331 * @since 1.5
1332 */
1333 public X500Principal getIssuer() {
1334 return issuer;
1335 }
1336
1337 /**
1338 * <strong>Denigrated</strong>, use {@linkplain #getIssuer()} or
1339 * {@linkplain #getIssuerAsBytes()} instead. This method should not be
1340 * relied on as it can fail to match some certificates because of a loss of
1341 * encoding information in the RFC 2253 String form of some distinguished
1342 * names.
1343 * <p>
1344 * Returns the issuer criterion as a <code>String</code>. This
1345 * distinguished name must match the issuer distinguished name in the
1346 * <code>X509Certificate</code>. If <code>null</code>, the issuer criterion
1347 * is disabled and any issuer distinguished name will do.
1348 * <p>
1349 * If the value returned is not <code>null</code>, it is a
1350 * distinguished name, in RFC 2253 format.
1351 *
1352 * @return the required issuer distinguished name in RFC 2253 format
1353 * (or <code>null</code>)
1354 */
1355 public String getIssuerAsString() {
1356 return (issuer == null ? null : issuer.getName());
1357 }
1358
1359 /**
1360 * Returns the issuer criterion as a byte array. This distinguished name
1361 * must match the issuer distinguished name in the
1362 * <code>X509Certificate</code>. If <code>null</code>, the issuer criterion
1363 * is disabled and any issuer distinguished name will do.
1364 * <p>
1365 * If the value returned is not <code>null</code>, it is a byte
1366 * array containing a single DER encoded distinguished name, as defined in
1367 * X.501. The ASN.1 notation for this structure is supplied in the
1368 * documentation for
1369 * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
1370 * <p>
1371 * Note that the byte array returned is cloned to protect against
1372 * subsequent modifications.
1373 *
1374 * @return a byte array containing the required issuer distinguished name
1375 * in ASN.1 DER format (or <code>null</code>)
1376 * @throws IOException if an encoding error occurs
1377 */
1378 public byte[] getIssuerAsBytes() throws IOException {
1379 return (issuer == null ? null : issuer.getEncoded());
1380 }
1381
1382 /**
1383 * Returns the subject criterion as an <code>X500Principal</code>. This
1384 * distinguished name must match the subject distinguished name in the
1385 * <code>X509Certificate</code>. If <code>null</code>, the subject criterion
1386 * is disabled and any subject distinguished name will do.
1387 *
1388 * @return the required subject distinguished name as X500Principal
1389 * (or <code>null</code>)
1390 * @since 1.5
1391 */
1392 public X500Principal getSubject() {
1393 return subject;
1394 }
1395
1396 /**
1397 * <strong>Denigrated</strong>, use {@linkplain #getSubject()} or
1398 * {@linkplain #getSubjectAsBytes()} instead. This method should not be
1399 * relied on as it can fail to match some certificates because of a loss of
1400 * encoding information in the RFC 2253 String form of some distinguished
1401 * names.
1402 * <p>
1403 * Returns the subject criterion as a <code>String</code>. This
1404 * distinguished name must match the subject distinguished name in the
1405 * <code>X509Certificate</code>. If <code>null</code>, the subject criterion
1406 * is disabled and any subject distinguished name will do.
1407 * <p>
1408 * If the value returned is not <code>null</code>, it is a
1409 * distinguished name, in RFC 2253 format.
1410 *
1411 * @return the required subject distinguished name in RFC 2253 format
1412 * (or <code>null</code>)
1413 */
1414 public String getSubjectAsString() {
1415 return (subject == null ? null : subject.getName());
1416 }
1417
1418 /**
1419 * Returns the subject criterion as a byte array. This distinguished name
1420 * must match the subject distinguished name in the
1421 * <code>X509Certificate</code>. If <code>null</code>, the subject criterion
1422 * is disabled and any subject distinguished name will do.
1423 * <p>
1424 * If the value returned is not <code>null</code>, it is a byte
1425 * array containing a single DER encoded distinguished name, as defined in
1426 * X.501. The ASN.1 notation for this structure is supplied in the
1427 * documentation for
1428 * {@link #setSubject(byte [] subjectDN) setSubject(byte [] subjectDN)}.
1429 * <p>
1430 * Note that the byte array returned is cloned to protect against
1431 * subsequent modifications.
1432 *
1433 * @return a byte array containing the required subject distinguished name
1434 * in ASN.1 DER format (or <code>null</code>)
1435 * @throws IOException if an encoding error occurs
1436 */
1437 public byte[] getSubjectAsBytes() throws IOException {
1438 return (subject == null ? null : subject.getEncoded());
1439 }
1440
1441 /**
1442 * Returns the subjectKeyIdentifier criterion. The
1443 * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
1444 * extension with the specified value. If <code>null</code>, no
1445 * subjectKeyIdentifier check will be done.
1446 * <p>
1447 * Note that the byte array returned is cloned to protect against
1448 * subsequent modifications.
1449 *
1450 * @return the key identifier (or <code>null</code>)
1451 * @see #setSubjectKeyIdentifier
1452 */
1453 public byte[] getSubjectKeyIdentifier() {
1454 if (subjectKeyID == null) {
1455 return null;
1456 }
1457 return (byte[]) subjectKeyID.clone();
1458 }
1459
1460 /**
1461 * Returns the authorityKeyIdentifier criterion. The
1462 * <code>X509Certificate</code> must contain a AuthorityKeyIdentifier
1463 * extension with the specified value. If <code>null</code>, no
1464 * authorityKeyIdentifier check will be done.
1465 * <p>
1466 * Note that the byte array returned is cloned to protect against
1467 * subsequent modifications.
1468 *
1469 * @return the key identifier (or <code>null</code>)
1470 * @see #setAuthorityKeyIdentifier
1471 */
1472 public byte[] getAuthorityKeyIdentifier() {
1473 if (authorityKeyID == null) {
1474 return null;
1475 }
1476 return (byte[]) authorityKeyID.clone();
1477 }
1478
1479 /**
1480 * Returns the certificateValid criterion. The specified date must fall
1481 * within the certificate validity period for the
1482 * <code>X509Certificate</code>. If <code>null</code>, no certificateValid
1483 * check will be done.
1484 * <p>
1485 * Note that the <code>Date</code> returned is cloned to protect against
1486 * subsequent modifications.
1487 *
1488 * @return the <code>Date</code> to check (or <code>null</code>)
1489 * @see #setCertificateValid
1490 */
1491 public Date getCertificateValid() {
1492 if (certificateValid == null) {
1493 return null;
1494 }
1495 return (Date) certificateValid.clone();
1496 }
1497
1498 /**
1499 * Returns the privateKeyValid criterion. The specified date must fall
1500 * within the private key validity period for the
1501 * <code>X509Certificate</code>. If <code>null</code>, no privateKeyValid
1502 * check will be done.
1503 * <p>
1504 * Note that the <code>Date</code> returned is cloned to protect against
1505 * subsequent modifications.
1506 *
1507 * @return the <code>Date</code> to check (or <code>null</code>)
1508 * @see #setPrivateKeyValid
1509 */
1510 public Date getPrivateKeyValid() {
1511 if (privateKeyValid == null) {
1512 return null;
1513 }
1514 return (Date) privateKeyValid.clone();
1515 }
1516
1517 /**
1518 * Returns the subjectPublicKeyAlgID criterion. The
1519 * <code>X509Certificate</code> must contain a subject public key
1520 * with the specified algorithm. If <code>null</code>, no
1521 * subjectPublicKeyAlgID check will be done.
1522 *
1523 * @return the object identifier (OID) of the signature algorithm to check
1524 * for (or <code>null</code>). An OID is represented by a set of
1525 * nonnegative integers separated by periods.
1526 * @see #setSubjectPublicKeyAlgID
1527 */
1528 public String getSubjectPublicKeyAlgID() {
1529 if (subjectPublicKeyAlgID == null) {
1530 return null;
1531 }
1532 return subjectPublicKeyAlgID.toString();
1533 }
1534
1535 /**
1536 * Returns the subjectPublicKey criterion. The
1537 * <code>X509Certificate</code> must contain the specified subject
1538 * public key. If <code>null</code>, no subjectPublicKey check will be done.
1539 *
1540 * @return the subject public key to check for (or <code>null</code>)
1541 * @see #setSubjectPublicKey
1542 */
1543 public PublicKey getSubjectPublicKey() {
1544 return subjectPublicKey;
1545 }
1546
1547 /**
1548 * Returns the keyUsage criterion. The <code>X509Certificate</code>
1549 * must allow the specified keyUsage values. If null, no keyUsage
1550 * check will be done.
1551 * <p>
1552 * Note that the boolean array returned is cloned to protect against
1553 * subsequent modifications.
1554 *
1555 * @return a boolean array in the same format as the boolean
1556 * array returned by
1557 * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
1558 * Or <code>null</code>.
1559 * @see #setKeyUsage
1560 */
1561 public boolean[] getKeyUsage() {
1562 if (keyUsage == null) {
1563 return null;
1564 }
1565 return (boolean[]) keyUsage.clone();
1566 }
1567
1568 /**
1569 * Returns the extendedKeyUsage criterion. The <code>X509Certificate</code>
1570 * must allow the specified key purposes in its extended key usage
1571 * extension. If the <code>keyPurposeSet</code> returned is empty or
1572 * <code>null</code>, no extendedKeyUsage check will be done. Note that an
1573 * <code>X509Certificate</code> that has no extendedKeyUsage extension
1574 * implicitly allows all key purposes.
1575 *
1576 * @return an immutable <code>Set</code> of key purpose OIDs in string
1577 * format (or <code>null</code>)
1578 * @see #setExtendedKeyUsage
1579 */
1580 public Set<String> getExtendedKeyUsage() {
1581 return keyPurposeSet;
1582 }
1583
1584 /**
1585 * Indicates if the <code>X509Certificate</code> must contain all
1586 * or at least one of the subjectAlternativeNames
1587 * specified in the {@link #setSubjectAlternativeNames
1588 * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
1589 * addSubjectAlternativeName} methods. If <code>true</code>,
1590 * the <code>X509Certificate</code> must contain all of the
1591 * specified subject alternative names. If <code>false</code>, the
1592 * <code>X509Certificate</code> must contain at least one of the
1593 * specified subject alternative names.
1594 *
1595 * @return <code>true</code> if the flag is enabled;
1596 * <code>false</code> if the flag is disabled. The flag is
1597 * <code>true</code> by default.
1598 * @see #setMatchAllSubjectAltNames
1599 */
1600 public boolean getMatchAllSubjectAltNames() {
1601 return matchAllSubjectAltNames;
1602 }
1603
1604 /**
1605 * Returns a copy of the subjectAlternativeNames criterion.
1606 * The <code>X509Certificate</code> must contain all or at least one
1607 * of the specified subjectAlternativeNames, depending on the value
1608 * of the matchAllNames flag (see {@link #getMatchAllSubjectAltNames
1609 * getMatchAllSubjectAltNames}). If the value returned is
1610 * <code>null</code>, no subjectAlternativeNames check will be performed.
1611 * <p>
1612 * If the value returned is not <code>null</code>, it is a
1613 * <code>Collection</code> with
1614 * one entry for each name to be included in the subject alternative name
1615 * criterion. Each entry is a <code>List</code> whose first entry is an
1616 * <code>Integer</code> (the name type, 0-8) and whose second
1617 * entry is a <code>String</code> or a byte array (the name, in
1618 * string or ASN.1 DER encoded form, respectively).
1619 * There can be multiple names of the same type. Note that the
1620 * <code>Collection</code> returned may contain duplicate names (same name
1621 * and name type).
1622 * <p>
1623 * Each subject alternative name in the <code>Collection</code>
1624 * may be specified either as a <code>String</code> or as an ASN.1 encoded
1625 * byte array. For more details about the formats used, see
1626 * {@link #addSubjectAlternativeName(int type, String name)
1627 * addSubjectAlternativeName(int type, String name)} and
1628 * {@link #addSubjectAlternativeName(int type, byte [] name)
1629 * addSubjectAlternativeName(int type, byte [] name)}.
1630 * <p>
1631 * Note that a deep copy is performed on the <code>Collection</code> to
1632 * protect against subsequent modifications.
1633 *
1634 * @return a <code>Collection</code> of names (or <code>null</code>)
1635 * @see #setSubjectAlternativeNames
1636 */
1637 public Collection<List<?>> getSubjectAlternativeNames() {
1638 if (subjectAlternativeNames == null) {
1639 return null;
1640 }
1641 return cloneNames(subjectAlternativeNames);
1642 }
1643
1644 /**
1645 * Clone an object of the form passed to
1646 * setSubjectAlternativeNames and setPathToNames.
1647 * Throw a <code>RuntimeException</code> if the argument is malformed.
1648 * <p>
1649 * This method wraps cloneAndCheckNames, changing any
1650 * <code>IOException</code> into a <code>RuntimeException</code>. This
1651 * method should be used when the object being
1652 * cloned has already been checked, so there should never be any exceptions.
1653 *
1654 * @param names a <code>Collection</code> with one entry per name.
1655 * Each entry is a <code>List</code> whose first entry
1656 * is an Integer (the name type, 0-8) and whose second
1657 * entry is a String or a byte array (the name, in
1658 * string or ASN.1 DER encoded form, respectively).
1659 * There can be multiple names of the same type. Null
1660 * is not an acceptable value.
1661 * @return a deep copy of the specified <code>Collection</code>
1662 * @throws RuntimeException if a parsing error occurs
1663 */
1664 private static Set<List<?>> cloneNames(Collection<List<?>> names) {
1665 try {
1666 return cloneAndCheckNames(names);
1667 } catch (IOException e) {
1668 throw new RuntimeException(
1669 "cloneNames encountered IOException: "
1670 + e.getMessage());
1671 }
1672 }
1673
1674 /**
1675 * Clone and check an argument of the form passed to
1676 * setSubjectAlternativeNames and setPathToNames.
1677 * Throw an <code>IOException</code> if the argument is malformed.
1678 *
1679 * @param names a <code>Collection</code> with one entry per name.
1680 * Each entry is a <code>List</code> whose first entry
1681 * is an Integer (the name type, 0-8) and whose second
1682 * entry is a String or a byte array (the name, in
1683 * string or ASN.1 DER encoded form, respectively).
1684 * There can be multiple names of the same type.
1685 * <code>null</code> is not an acceptable value.
1686 * @return a deep copy of the specified <code>Collection</code>
1687 * @throws IOException if a parsing error occurs
1688 */
1689 private static Set<List<?>> cloneAndCheckNames(
1690 Collection<List<?>> names) throws IOException {
1691 // Copy the Lists and Collection
1692 Set<List<?>> namesCopy = new HashSet<List<?>>();
1693 Iterator<List<?>> i = names.iterator();
1694 while (i.hasNext()) {
1695 Object o = i.next();
1696 if (!(o instanceof List)) {
1697 throw new IOException("expected a List");
1698 }
1699 namesCopy.add(new ArrayList<Object>((List<?>) o));
1700 }
1701
1702 // Check the contents of the Lists and clone any byte arrays
1703 i = namesCopy.iterator();
1704 while (i.hasNext()) {
1705 List<Object> nameList = (List<Object>) i.next();
1706 if (nameList.size() != 2) {
1707 throw new IOException("name list size not 2");
1708 }
1709 Object o = nameList.get(0);
1710 if (!(o instanceof Integer)) {
1711 throw new IOException("expected an Integer");
1712 }
1713 int nameType = ((Integer) o).intValue();
1714 if ((nameType < 0) || (nameType > 8)) {
1715 throw new IOException("name type not 0-8");
1716 }
1717 Object nameObject = nameList.get(1);
1718 if (!(nameObject instanceof byte[])
1719 && !(nameObject instanceof String)) {
1720 if (debug != null) {
1721 debug
1722 .println("X509CertSelector.cloneAndCheckNames() "
1723 + "name not byte array");
1724 }
1725 throw new IOException("name not byte array or String");
1726 }
1727 if (nameObject instanceof byte[]) {
1728 nameList.set(1, ((byte[]) nameObject).clone());
1729 }
1730 }
1731 return namesCopy;
1732 }
1733
1734 /**
1735 * Returns the name constraints criterion. The <code>X509Certificate</code>
1736 * must have subject and subject alternative names that
1737 * meet the specified name constraints.
1738 * <p>
1739 * The name constraints are returned as a byte array. This byte array
1740 * contains the DER encoded form of the name constraints, as they
1741 * would appear in the NameConstraints structure defined in RFC 3280
1742 * and X.509. The ASN.1 notation for this structure is supplied in the
1743 * documentation for
1744 * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.
1745 * <p>
1746 * Note that the byte array returned is cloned to protect against
1747 * subsequent modifications.
1748 *
1749 * @return a byte array containing the ASN.1 DER encoding of
1750 * a NameConstraints extension used for checking name constraints.
1751 * <code>null</code> if no name constraints check will be performed.
1752 * @see #setNameConstraints
1753 */
1754 public byte[] getNameConstraints() {
1755 if (ncBytes == null) {
1756 return null;
1757 } else {
1758 return (byte[]) ncBytes.clone();
1759 }
1760 }
1761
1762 /**
1763 * Returns the basic constraints constraint. If the value is greater than
1764 * or equal to zero, the <code>X509Certificates</code> must include a
1765 * basicConstraints extension with a pathLen of at least this value.
1766 * If the value is -2, only end-entity certificates are accepted. If
1767 * the value is -1, no basicConstraints check is done.
1768 *
1769 * @return the value for the basic constraints constraint
1770 * @see #setBasicConstraints
1771 */
1772 public int getBasicConstraints() {
1773 return basicConstraints;
1774 }
1775
1776 /**
1777 * Returns the policy criterion. The <code>X509Certificate</code> must
1778 * include at least one of the specified policies in its certificate policies
1779 * extension. If the <code>Set</code> returned is empty, then the
1780 * <code>X509Certificate</code> must include at least some specified policy
1781 * in its certificate policies extension. If the <code>Set</code> returned is
1782 * <code>null</code>, no policy check will be performed.
1783 *
1784 * @return an immutable <code>Set</code> of certificate policy OIDs in
1785 * string format (or <code>null</code>)
1786 * @see #setPolicy
1787 */
1788 public Set<String> getPolicy() {
1789 return policySet;
1790 }
1791
1792 /**
1793 * Returns a copy of the pathToNames criterion. The
1794 * <code>X509Certificate</code> must not include name constraints that would
1795 * prohibit building a path to the specified names. If the value
1796 * returned is <code>null</code>, no pathToNames check will be performed.
1797 * <p>
1798 * If the value returned is not <code>null</code>, it is a
1799 * <code>Collection</code> with one
1800 * entry for each name to be included in the pathToNames
1801 * criterion. Each entry is a <code>List</code> whose first entry is an
1802 * <code>Integer</code> (the name type, 0-8) and whose second
1803 * entry is a <code>String</code> or a byte array (the name, in
1804 * string or ASN.1 DER encoded form, respectively).
1805 * There can be multiple names of the same type. Note that the
1806 * <code>Collection</code> returned may contain duplicate names (same
1807 * name and name type).
1808 * <p>
1809 * Each name in the <code>Collection</code>
1810 * may be specified either as a <code>String</code> or as an ASN.1 encoded
1811 * byte array. For more details about the formats used, see
1812 * {@link #addPathToName(int type, String name)
1813 * addPathToName(int type, String name)} and
1814 * {@link #addPathToName(int type, byte [] name)
1815 * addPathToName(int type, byte [] name)}.
1816 * <p>
1817 * Note that a deep copy is performed on the <code>Collection</code> to
1818 * protect against subsequent modifications.
1819 *
1820 * @return a <code>Collection</code> of names (or <code>null</code>)
1821 * @see #setPathToNames
1822 */
1823 public Collection<List<?>> getPathToNames() {
1824 if (pathToNames == null) {
1825 return null;
1826 }
1827 return cloneNames(pathToNames);
1828 }
1829
1830 /**
1831 * Return a printable representation of the <code>CertSelector</code>.
1832 *
1833 * @return a <code>String</code> describing the contents of the
1834 * <code>CertSelector</code>
1835 */
1836 public String toString() {
1837 StringBuffer sb = new StringBuffer();
1838 sb.append("X509CertSelector: [\n");
1839 if (x509Cert != null) {
1840 sb.append(" Certificate: " + x509Cert.toString() + "\n");
1841 }
1842 if (serialNumber != null) {
1843 sb.append(" Serial Number: " + serialNumber.toString()
1844 + "\n");
1845 }
1846 if (issuer != null) {
1847 sb.append(" Issuer: " + getIssuerAsString() + "\n");
1848 }
1849 if (subject != null) {
1850 sb.append(" Subject: " + getSubjectAsString() + "\n");
1851 }
1852 sb.append(" matchAllSubjectAltNames flag: "
1853 + String.valueOf(matchAllSubjectAltNames) + "\n");
1854 if (subjectAlternativeNames != null) {
1855 sb.append(" SubjectAlternativeNames:\n");
1856 Iterator<List<?>> i = subjectAlternativeNames.iterator();
1857 while (i.hasNext()) {
1858 List<?> list = i.next();
1859 sb.append(" type " + list.get(0) + ", name "
1860 + list.get(1) + "\n");
1861 }
1862 }
1863 if (subjectKeyID != null) {
1864 HexDumpEncoder enc = new HexDumpEncoder();
1865 sb.append(" Subject Key Identifier: "
1866 + enc.encodeBuffer(subjectKeyID) + "\n");
1867 }
1868 if (authorityKeyID != null) {
1869 HexDumpEncoder enc = new HexDumpEncoder();
1870 sb.append(" Authority Key Identifier: "
1871 + enc.encodeBuffer(authorityKeyID) + "\n");
1872 }
1873 if (certificateValid != null) {
1874 sb.append(" Certificate Valid: "
1875 + certificateValid.toString() + "\n");
1876 }
1877 if (privateKeyValid != null) {
1878 sb.append(" Private Key Valid: "
1879 + privateKeyValid.toString() + "\n");
1880 }
1881 if (subjectPublicKeyAlgID != null) {
1882 sb.append(" Subject Public Key AlgID: "
1883 + subjectPublicKeyAlgID.toString() + "\n");
1884 }
1885 if (subjectPublicKey != null) {
1886 sb.append(" Subject Public Key: "
1887 + subjectPublicKey.toString() + "\n");
1888 }
1889 if (keyUsage != null) {
1890 sb.append(" Key Usage: " + keyUsageToString(keyUsage)
1891 + "\n");
1892 }
1893 if (keyPurposeSet != null) {
1894 sb.append(" Extended Key Usage: "
1895 + keyPurposeSet.toString() + "\n");
1896 }
1897 if (policy != null) {
1898 sb.append(" Policy: " + policy.toString() + "\n");
1899 }
1900 if (pathToGeneralNames != null) {
1901 sb.append(" Path to names:\n");
1902 Iterator<GeneralNameInterface> i = pathToGeneralNames
1903 .iterator();
1904 while (i.hasNext()) {
1905 sb.append(" " + i.next() + "\n");
1906 }
1907 }
1908 sb.append("]");
1909 return sb.toString();
1910 }
1911
1912 // Copied from sun.security.x509.KeyUsageExtension
1913 // (without calling the superclass)
1914 /**
1915 * Returns a printable representation of the KeyUsage.
1916 */
1917 private static String keyUsageToString(boolean[] k) {
1918 String s = "KeyUsage [\n";
1919 try {
1920 if (k[0]) {
1921 s += " DigitalSignature\n";
1922 }
1923 if (k[1]) {
1924 s += " Non_repudiation\n";
1925 }
1926 if (k[2]) {
1927 s += " Key_Encipherment\n";
1928 }
1929 if (k[3]) {
1930 s += " Data_Encipherment\n";
1931 }
1932 if (k[4]) {
1933 s += " Key_Agreement\n";
1934 }
1935 if (k[5]) {
1936 s += " Key_CertSign\n";
1937 }
1938 if (k[6]) {
1939 s += " Crl_Sign\n";
1940 }
1941 if (k[7]) {
1942 s += " Encipher_Only\n";
1943 }
1944 if (k[8]) {
1945 s += " Decipher_Only\n";
1946 }
1947 } catch (ArrayIndexOutOfBoundsException ex) {
1948 }
1949
1950 s += "]\n";
1951
1952 return (s);
1953 }
1954
1955 /**
1956 * Returns an Extension object given any X509Certificate and extension oid.
1957 * Throw an <code>IOException</code> if the extension byte value is
1958 * malformed.
1959 *
1960 * @param cert a <code>X509Certificate</code>
1961 * @param extId an <code>integer</code> which specifies the extension index.
1962 * Currently, the supported extensions are as follows:
1963 * index 0 - PrivateKeyUsageExtension
1964 * index 1 - SubjectAlternativeNameExtension
1965 * index 2 - NameConstraintsExtension
1966 * index 3 - CertificatePoliciesExtension
1967 * index 4 - ExtendedKeyUsageExtension
1968 * @return an <code>Extension</code> object whose real type is as specified
1969 * by the extension oid.
1970 * @throws IOException if cannot construct the <code>Extension</code>
1971 * object with the extension encoding retrieved from the passed in
1972 * <code>X509Certificate</code>.
1973 */
1974 private static Extension getExtensionObject(X509Certificate cert,
1975 int extId) throws IOException {
1976 if (cert instanceof X509CertImpl) {
1977 X509CertImpl impl = (X509CertImpl) cert;
1978 switch (extId) {
1979 case PRIVATE_KEY_USAGE_ID:
1980 return impl.getPrivateKeyUsageExtension();
1981 case SUBJECT_ALT_NAME_ID:
1982 return impl.getSubjectAlternativeNameExtension();
1983 case NAME_CONSTRAINTS_ID:
1984 return impl.getNameConstraintsExtension();
1985 case CERT_POLICIES_ID:
1986 return impl.getCertificatePoliciesExtension();
1987 case EXTENDED_KEY_USAGE_ID:
1988 return impl.getExtendedKeyUsageExtension();
1989 default:
1990 return null;
1991 }
1992 }
1993 byte[] rawExtVal = cert
1994 .getExtensionValue(EXTENSION_OIDS[extId]);
1995 if (rawExtVal == null) {
1996 return null;
1997 }
1998 DerInputStream in = new DerInputStream(rawExtVal);
1999 byte[] encoded = in.getOctetString();
2000 switch (extId) {
2001 case PRIVATE_KEY_USAGE_ID:
2002 try {
2003 return new PrivateKeyUsageExtension(FALSE, encoded);
2004 } catch (CertificateException ex) {
2005 throw new IOException(ex.getMessage());
2006 }
2007 case SUBJECT_ALT_NAME_ID:
2008 return new SubjectAlternativeNameExtension(FALSE, encoded);
2009 case NAME_CONSTRAINTS_ID:
2010 return new NameConstraintsExtension(FALSE, encoded);
2011 case CERT_POLICIES_ID:
2012 return new CertificatePoliciesExtension(FALSE, encoded);
2013 case EXTENDED_KEY_USAGE_ID:
2014 return new ExtendedKeyUsageExtension(FALSE, encoded);
2015 default:
2016 return null;
2017 }
2018 }
2019
2020 /**
2021 * Decides whether a <code>Certificate</code> should be selected.
2022 *
2023 * @param cert the <code>Certificate</code> to be checked
2024 * @return <code>true</code> if the <code>Certificate</code> should be
2025 * selected, <code>false</code> otherwise
2026 */
2027 public boolean match(Certificate cert) {
2028 if (!(cert instanceof X509Certificate)) {
2029 return false;
2030 }
2031 X509Certificate xcert = (X509Certificate) cert;
2032
2033 if (debug != null) {
2034 debug.println("X509CertSelector.match(SN: "
2035 + (xcert.getSerialNumber()).toString(16)
2036 + "\n Issuer: " + xcert.getIssuerDN()
2037 + "\n Subject: " + xcert.getSubjectDN() + ")");
2038 }
2039
2040 /* match on X509Certificate */
2041 if (x509Cert != null) {
2042 if (!x509Cert.equals(xcert)) {
2043 if (debug != null) {
2044 debug.println("X509CertSelector.match: "
2045 + "certs don't match");
2046 }
2047 return false;
2048 }
2049 }
2050
2051 /* match on serial number */
2052 if (serialNumber != null) {
2053 if (!serialNumber.equals(xcert.getSerialNumber())) {
2054 if (debug != null) {
2055 debug.println("X509CertSelector.match: "
2056 + "serial numbers don't match");
2057 }
2058 return false;
2059 }
2060 }
2061
2062 /* match on issuer name */
2063 if (issuer != null) {
2064 if (!issuer.equals(xcert.getIssuerX500Principal())) {
2065 if (debug != null) {
2066 debug.println("X509CertSelector.match: "
2067 + "issuer DNs don't match");
2068 }
2069 return false;
2070 }
2071 }
2072
2073 /* match on subject name */
2074 if (subject != null) {
2075 if (!subject.equals(xcert.getSubjectX500Principal())) {
2076 if (debug != null) {
2077 debug.println("X509CertSelector.match: "
2078 + "subject DNs don't match");
2079 }
2080 return false;
2081 }
2082 }
2083
2084 /* match on certificate validity range */
2085 if (certificateValid != null) {
2086 try {
2087 xcert.checkValidity(certificateValid);
2088 } catch (CertificateException e) {
2089 if (debug != null) {
2090 debug.println("X509CertSelector.match: "
2091 + "certificate not within validity period");
2092 }
2093 return false;
2094 }
2095 }
2096
2097 /* match on subject public key */
2098 if (subjectPublicKeyBytes != null) {
2099 byte[] certKey = xcert.getPublicKey().getEncoded();
2100 if (!Arrays.equals(subjectPublicKeyBytes, certKey)) {
2101 if (debug != null) {
2102 debug.println("X509CertSelector.match: "
2103 + "subject public keys don't match");
2104 }
2105 return false;
2106 }
2107 }
2108
2109 boolean result = matchBasicConstraints(xcert)
2110 && matchKeyUsage(xcert) && matchExtendedKeyUsage(xcert)
2111 && matchSubjectKeyID(xcert)
2112 && matchAuthorityKeyID(xcert)
2113 && matchPrivateKeyValid(xcert)
2114 && matchSubjectPublicKeyAlgID(xcert)
2115 && matchPolicy(xcert)
2116 && matchSubjectAlternativeNames(xcert)
2117 && matchPathToNames(xcert)
2118 && matchNameConstraints(xcert);
2119
2120 if (result && (debug != null)) {
2121 debug.println("X509CertSelector.match returning: true");
2122 }
2123 return result;
2124 }
2125
2126 /* match on subject key identifier extension value */
2127 private boolean matchSubjectKeyID(X509Certificate xcert) {
2128 if (subjectKeyID == null) {
2129 return true;
2130 }
2131 try {
2132 byte[] extVal = xcert.getExtensionValue("2.5.29.14");
2133 if (extVal == null) {
2134 if (debug != null) {
2135 debug.println("X509CertSelector.match: "
2136 + "no subject key ID extension");
2137 }
2138 return false;
2139 }
2140 DerInputStream in = new DerInputStream(extVal);
2141 byte[] certSubjectKeyID = in.getOctetString();
2142 if (certSubjectKeyID == null
2143 || !Arrays.equals(subjectKeyID, certSubjectKeyID)) {
2144 if (debug != null) {
2145 debug.println("X509CertSelector.match: "
2146 + "subject key IDs don't match");
2147 }
2148 return false;
2149 }
2150 } catch (IOException ex) {
2151 if (debug != null) {
2152 debug.println("X509CertSelector.match: "
2153 + "exception in subject key ID check");
2154 }
2155 return false;
2156 }
2157 return true;
2158 }
2159
2160 /* match on authority key identifier extension value */
2161 private boolean matchAuthorityKeyID(X509Certificate xcert) {
2162 if (authorityKeyID == null) {
2163 return true;
2164 }
2165 try {
2166 byte[] extVal = xcert.getExtensionValue("2.5.29.35");
2167 if (extVal == null) {
2168 if (debug != null) {
2169 debug.println("X509CertSelector.match: "
2170 + "no authority key ID extension");
2171 }
2172 return false;
2173 }
2174 DerInputStream in = new DerInputStream(extVal);
2175 byte[] certAuthKeyID = in.getOctetString();
2176 if (certAuthKeyID == null
2177 || !Arrays.equals(authorityKeyID, certAuthKeyID)) {
2178 if (debug != null) {
2179 debug.println("X509CertSelector.match: "
2180 + "authority key IDs don't match");
2181 }
2182 return false;
2183 }
2184 } catch (IOException ex) {
2185 if (debug != null) {
2186 debug.println("X509CertSelector.match: "
2187 + "exception in authority key ID check");
2188 }
2189 return false;
2190 }
2191 return true;
2192 }
2193
2194 /* match on private key usage range */
2195 private boolean matchPrivateKeyValid(X509Certificate xcert) {
2196 if (privateKeyValid == null) {
2197 return true;
2198 }
2199 PrivateKeyUsageExtension ext = null;
2200 try {
2201 ext = (PrivateKeyUsageExtension) getExtensionObject(xcert,
2202 PRIVATE_KEY_USAGE_ID);
2203 if (ext != null) {
2204 ext.valid(privateKeyValid);
2205 }
2206 } catch (CertificateExpiredException e1) {
2207 if (debug != null) {
2208 String time = "n/a";
2209 try {
2210 Date notAfter = (Date) ext
2211 .get(PrivateKeyUsageExtension.NOT_AFTER);
2212 time = notAfter.toString();
2213 } catch (CertificateException ex) {
2214 // not able to retrieve notAfter value
2215 }
2216 debug
2217 .println("X509CertSelector.match: private key usage not "
2218 + "within validity date; ext.NOT_After: "
2219 + time
2220 + "; X509CertSelector: "
2221 + this .toString());
2222 e1.printStackTrace();
2223 }
2224 return false;
2225 } catch (CertificateNotYetValidException e2) {
2226 if (debug != null) {
2227 String time = "n/a";
2228 try {
2229 Date notBefore = (Date) ext
2230 .get(PrivateKeyUsageExtension.NOT_BEFORE);
2231 time = notBefore.toString();
2232 } catch (CertificateException ex) {
2233 // not able to retrieve notBefore value
2234 }
2235 debug
2236 .println("X509CertSelector.match: private key usage not "
2237 + "within validity date; ext.NOT_BEFORE: "
2238 + time
2239 + "; X509CertSelector: "
2240 + this .toString());
2241 e2.printStackTrace();
2242 }
2243 return false;
2244 } catch (CertificateException e3) {
2245 if (debug != null) {
2246 debug
2247 .println("X509CertSelector.match: CertificateException "
2248 + "in private key usage check; X509CertSelector: "
2249 + this .toString());
2250 e3.printStackTrace();
2251 }
2252 return false;
2253 } catch (IOException e4) {
2254 if (debug != null) {
2255 debug.println("X509CertSelector.match: IOException in "
2256 + "private key usage check; X509CertSelector: "
2257 + this .toString());
2258 e4.printStackTrace();
2259 }
2260 return false;
2261 }
2262 return true;
2263 }
2264
2265 /* match on subject public key algorithm OID */
2266 private boolean matchSubjectPublicKeyAlgID(X509Certificate xcert) {
2267 if (subjectPublicKeyAlgID == null) {
2268 return true;
2269 }
2270 try {
2271 byte[] encodedKey = xcert.getPublicKey().getEncoded();
2272 DerValue val = new DerValue(encodedKey);
2273 if (val.tag != DerValue.tag_Sequence) {
2274 throw new IOException("invalid key format");
2275 }
2276
2277 AlgorithmId algID = AlgorithmId.parse(val.data
2278 .getDerValue());
2279 if (debug != null) {
2280 debug
2281 .println("X509CertSelector.match: subjectPublicKeyAlgID = "
2282 + subjectPublicKeyAlgID
2283 + ", xcert subjectPublicKeyAlgID = "
2284 + algID.getOID());
2285 }
2286 if (!subjectPublicKeyAlgID.equals(algID.getOID())) {
2287 if (debug != null) {
2288 debug.println("X509CertSelector.match: "
2289 + "subject public key alg IDs don't match");
2290 }
2291 return false;
2292 }
2293 } catch (IOException e5) {
2294 if (debug != null) {
2295 debug
2296 .println("X509CertSelector.match: IOException in subject "
2297 + "public key algorithm OID check");
2298 }
2299 return false;
2300 }
2301 return true;
2302 }
2303
2304 /* match on key usage extension value */
2305 private boolean matchKeyUsage(X509Certificate xcert) {
2306 if (keyUsage == null) {
2307 return true;
2308 }
2309 boolean[] certKeyUsage = xcert.getKeyUsage();
2310 if (certKeyUsage != null) {
2311 for (int keyBit = 0; keyBit < keyUsage.length; keyBit++) {
2312 if (keyUsage[keyBit]
2313 && ((keyBit >= certKeyUsage.length) || !certKeyUsage[keyBit])) {
2314 if (debug != null) {
2315 debug.println("X509CertSelector.match: "
2316 + "key usage bits don't match");
2317 }
2318 return false;
2319 }
2320 }
2321 }
2322 return true;
2323 }
2324
2325 /* match on extended key usage purpose OIDs */
2326 private boolean matchExtendedKeyUsage(X509Certificate xcert) {
2327 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
2328 return true;
2329 }
2330 try {
2331 ExtendedKeyUsageExtension ext = (ExtendedKeyUsageExtension) getExtensionObject(
2332 xcert, EXTENDED_KEY_USAGE_ID);
2333 if (ext != null) {
2334 Vector<ObjectIdentifier> certKeyPurposeVector = (Vector<ObjectIdentifier>) ext
2335 .get(ExtendedKeyUsageExtension.USAGES);
2336 if (!certKeyPurposeVector
2337 .contains(ANY_EXTENDED_KEY_USAGE)
2338 && !certKeyPurposeVector
2339 .containsAll(keyPurposeOIDSet)) {
2340 if (debug != null) {
2341 debug
2342 .println("X509CertSelector.match: cert failed "
2343 + "extendedKeyUsage criterion");
2344 }
2345 return false;
2346 }
2347 }
2348 } catch (IOException ex) {
2349 if (debug != null) {
2350 debug.println("X509CertSelector.match: "
2351 + "IOException in extended key usage check");
2352 }
2353 return false;
2354 }
2355 return true;
2356 }
2357
2358 /* match on subject alternative name extension names */
2359 private boolean matchSubjectAlternativeNames(X509Certificate xcert) {
2360 if ((subjectAlternativeNames == null)
2361 || subjectAlternativeNames.isEmpty()) {
2362 return true;
2363 }
2364 try {
2365 SubjectAlternativeNameExtension sanExt = (SubjectAlternativeNameExtension) getExtensionObject(
2366 xcert, SUBJECT_ALT_NAME_ID);
2367 if (sanExt == null) {
2368 if (debug != null) {
2369 debug.println("X509CertSelector.match: "
2370 + "no subject alternative name extension");
2371 }
2372 return false;
2373 }
2374 GeneralNames certNames = (GeneralNames) sanExt
2375 .get(SubjectAlternativeNameExtension.SUBJECT_NAME);
2376 Iterator<GeneralNameInterface> i = subjectAlternativeGeneralNames
2377 .iterator();
2378 while (i.hasNext()) {
2379 GeneralNameInterface matchName = i.next();
2380 boolean found = false;
2381 for (Iterator<GeneralName> t = certNames.iterator(); t
2382 .hasNext()
2383 && !found;) {
2384 GeneralNameInterface certName = (t.next())
2385 .getName();
2386 found = certName.equals(matchName);
2387 }
2388 if (!found && (matchAllSubjectAltNames || !i.hasNext())) {
2389 if (debug != null) {
2390 debug
2391 .println("X509CertSelector.match: subject alternative "
2392 + "name "
2393 + matchName
2394 + " not found");
2395 }
2396 return false;
2397 } else if (found && !matchAllSubjectAltNames) {
2398 break;
2399 }
2400 }
2401 } catch (IOException ex) {
2402 if (debug != null)
2403 debug
2404 .println("X509CertSelector.match: IOException in subject "
2405 + "alternative name check");
2406 return false;
2407 }
2408 return true;
2409 }
2410
2411 /* match on name constraints */
2412 private boolean matchNameConstraints(X509Certificate xcert) {
2413 if (nc == null) {
2414 return true;
2415 }
2416 try {
2417 if (!nc.verify(xcert)) {
2418 if (debug != null) {
2419 debug.println("X509CertSelector.match: "
2420 + "name constraints not satisfied");
2421 }
2422 return false;
2423 }
2424 } catch (IOException e) {
2425 if (debug != null) {
2426 debug.println("X509CertSelector.match: "
2427 + "IOException in name constraints check");
2428 }
2429 return false;
2430 }
2431 return true;
2432 }
2433
2434 /* match on policy OIDs */
2435 private boolean matchPolicy(X509Certificate xcert) {
2436 if (policy == null) {
2437 return true;
2438 }
2439 try {
2440 CertificatePoliciesExtension ext = (CertificatePoliciesExtension) getExtensionObject(
2441 xcert, CERT_POLICIES_ID);
2442 if (ext == null) {
2443 if (debug != null) {
2444 debug.println("X509CertSelector.match: "
2445 + "no certificate policy extension");
2446 }
2447 return false;
2448 }
2449 List<PolicyInformation> policies = (List<PolicyInformation>) ext
2450 .get(CertificatePoliciesExtension.POLICIES);
2451 /*
2452 * Convert the Vector of PolicyInformation to a Vector
2453 * of CertificatePolicyIds for easier comparison.
2454 */
2455 List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(
2456 policies.size());
2457 for (PolicyInformation info : policies) {
2458 policyIDs.add(info.getPolicyIdentifier());
2459 }
2460 if (policy != null) {
2461 boolean foundOne = false;
2462 /*
2463 * if the user passes in an empty policy Set, then
2464 * we just want to make sure that the candidate certificate
2465 * has some policy OID in its CertPoliciesExtension
2466 */
2467 if (policy.getCertPolicyIds().isEmpty()) {
2468 if (policyIDs.isEmpty()) {
2469 if (debug != null) {
2470 debug
2471 .println("X509CertSelector.match: "
2472 + "cert failed policyAny criterion");
2473 }
2474 return false;
2475 }
2476 } else {
2477 for (CertificatePolicyId id : policy
2478 .getCertPolicyIds()) {
2479 if (policyIDs.contains(id)) {
2480 foundOne = true;
2481 break;
2482 }
2483 }
2484 if (!foundOne) {
2485 if (debug != null) {
2486 debug
2487 .println("X509CertSelector.match: "
2488 + "cert failed policyAny criterion");
2489 }
2490 return false;
2491 }
2492 }
2493 }
2494 } catch (IOException ex) {
2495 if (debug != null) {
2496 debug.println("X509CertSelector.match: "
2497 + "IOException in certificate policy ID check");
2498 }
2499 return false;
2500 }
2501 return true;
2502 }
2503
2504 /* match on pathToNames */
2505 private boolean matchPathToNames(X509Certificate xcert) {
2506 if (pathToGeneralNames == null) {
2507 return true;
2508 }
2509 try {
2510 NameConstraintsExtension ext = (NameConstraintsExtension) getExtensionObject(
2511 xcert, NAME_CONSTRAINTS_ID);
2512 if (ext == null) {
2513 return true;
2514 }
2515 if ((debug != null) && debug.isOn("certpath")) {
2516 debug.println("X509CertSelector.match pathToNames:\n");
2517 Iterator<GeneralNameInterface> i = pathToGeneralNames
2518 .iterator();
2519 while (i.hasNext()) {
2520 debug.println(" " + i.next() + "\n");
2521 }
2522 }
2523
2524 GeneralSubtrees permitted = (GeneralSubtrees) ext
2525 .get(NameConstraintsExtension.PERMITTED_SUBTREES);
2526 GeneralSubtrees excluded = (GeneralSubtrees) ext
2527 .get(NameConstraintsExtension.EXCLUDED_SUBTREES);
2528 if (excluded != null) {
2529 if (matchExcluded(excluded) == false) {
2530 return false;
2531 }
2532 }
2533 if (permitted != null) {
2534 if (matchPermitted(permitted) == false) {
2535 return false;
2536 }
2537 }
2538 } catch (IOException ex) {
2539 if (debug != null) {
2540 debug.println("X509CertSelector.match: "
2541 + "IOException in name constraints check");
2542 }
2543 return false;
2544 }
2545 return true;
2546 }
2547
2548 private boolean matchExcluded(GeneralSubtrees excluded) {
2549 /*
2550 * Enumerate through excluded and compare each entry
2551 * to all pathToNames. If any pathToName is within any of the
2552 * subtrees listed in excluded, return false.
2553 */
2554 for (Iterator<GeneralSubtree> t = excluded.iterator(); t
2555 .hasNext();) {
2556 GeneralSubtree tree = t.next();
2557 GeneralNameInterface excludedName = tree.getName()
2558 .getName();
2559 Iterator<GeneralNameInterface> i = pathToGeneralNames
2560 .iterator();
2561 while (i.hasNext()) {
2562 GeneralNameInterface pathToName = i.next();
2563 if (excludedName.getType() == pathToName.getType()) {
2564 switch (pathToName.constrains(excludedName)) {
2565 case GeneralNameInterface.NAME_WIDENS:
2566 case GeneralNameInterface.NAME_MATCH:
2567 if (debug != null) {
2568 debug
2569 .println("X509CertSelector.match: name constraints "
2570 + "inhibit path to specified name");
2571 debug
2572 .println("X509CertSelector.match: excluded name: "
2573 + pathToName);
2574 }
2575 return false;
2576 default:
2577 }
2578 }
2579 }
2580 }
2581 return true;
2582 }
2583
2584 private boolean matchPermitted(GeneralSubtrees permitted) {
2585 /*
2586 * Enumerate through pathToNames, checking that each pathToName
2587 * is in at least one of the subtrees listed in permitted.
2588 * If not, return false. However, if no subtrees of a given type
2589 * are listed, all names of that type are permitted.
2590 */
2591 Iterator<GeneralNameInterface> i = pathToGeneralNames
2592 .iterator();
2593 while (i.hasNext()) {
2594 GeneralNameInterface pathToName = i.next();
2595 Iterator<GeneralSubtree> t = permitted.iterator();
2596 boolean permittedNameFound = false;
2597 boolean nameTypeFound = false;
2598 String names = "";
2599 while (t.hasNext() && !permittedNameFound) {
2600 GeneralSubtree tree = t.next();
2601 GeneralNameInterface permittedName = tree.getName()
2602 .getName();
2603 if (permittedName.getType() == pathToName.getType()) {
2604 nameTypeFound = true;
2605 names = names + " " + permittedName;
2606 switch (pathToName.constrains(permittedName)) {
2607 case GeneralNameInterface.NAME_WIDENS:
2608 case GeneralNameInterface.NAME_MATCH:
2609 permittedNameFound = true;
2610 break;
2611 default:
2612 }
2613 }
2614 }
2615 if (!permittedNameFound && nameTypeFound) {
2616 if (debug != null)
2617 debug
2618 .println("X509CertSelector.match: "
2619 + "name constraints inhibit path to specified name; "
2620 + "permitted names of type "
2621 + pathToName.getType() + ": "
2622 + names);
2623 return false;
2624 }
2625 }
2626 return true;
2627 }
2628
2629 /* match on basic constraints */
2630 private boolean matchBasicConstraints(X509Certificate xcert) {
2631 if (basicConstraints == -1) {
2632 return true;
2633 }
2634 int maxPathLen = xcert.getBasicConstraints();
2635 if (basicConstraints == -2) {
2636 if (maxPathLen != -1) {
2637 if (debug != null) {
2638 debug
2639 .println("X509CertSelector.match: not an EE cert");
2640 }
2641 return false;
2642 }
2643 } else {
2644 if (maxPathLen < basicConstraints) {
2645 if (debug != null) {
2646 debug
2647 .println("X509CertSelector.match: maxPathLen too small ("
2648 + maxPathLen
2649 + " < "
2650 + basicConstraints + ")");
2651 }
2652 return false;
2653 }
2654 }
2655 return true;
2656 }
2657
2658 private static Set<?> cloneSet(Set<?> set) {
2659 if (set instanceof HashSet) {
2660 Object clone = ((HashSet<?>) set).clone();
2661 return (Set<?>) clone;
2662 } else {
2663 return new HashSet<Object>(set);
2664 }
2665 }
2666
2667 /**
2668 * Returns a copy of this object.
2669 *
2670 * @return the copy
2671 */
2672 public Object clone() {
2673 try {
2674 X509CertSelector copy = (X509CertSelector) super .clone();
2675 // Must clone these because addPathToName et al. modify them
2676 if (subjectAlternativeNames != null) {
2677 copy.subjectAlternativeNames = (Set<List<?>>) cloneSet(subjectAlternativeNames);
2678 copy.subjectAlternativeGeneralNames = (Set<GeneralNameInterface>) cloneSet(subjectAlternativeGeneralNames);
2679 }
2680 if (pathToGeneralNames != null) {
2681 copy.pathToNames = (Set<List<?>>) cloneSet(pathToNames);
2682 copy.pathToGeneralNames = (Set<GeneralNameInterface>) cloneSet(pathToGeneralNames);
2683 }
2684 return copy;
2685 } catch (CloneNotSupportedException e) {
2686 /* Cannot happen */
2687 throw new InternalError(e.toString());
2688 }
2689 }
2690 }
|