Source Code Cross Referenced for X509CertSelector.java in  » 6.0-JDK-Core » security » java » security » cert » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » security » java.security.cert 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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(&lt;SubjectKeyIdentifier Object 
0426             * Identifier&gt;)</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        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.