1 /*
   2  * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.validator;
  27 
  28 import java.util.*;
  29 
  30 import java.security.AlgorithmConstraints;
  31 import java.security.KeyStore;
  32 import java.security.cert.*;
  33 
  34 /**
  35  * Validator abstract base class. Concrete classes are instantiated by calling
  36  * one of the getInstance() methods. All methods defined in this class
  37  * must be safe for concurrent use by multiple threads.<p>
  38  *
  39  * The model is that a Validator instance is created specifying validation
  40  * settings, such as trust anchors or PKIX parameters. Then one or more
  41  * paths are validated using those parameters. In some cases, additional
  42  * information can be provided per path validation. This is independent of
  43  * the validation parameters and currently only used for TLS server validation.
  44  * <p>
  45  * Path validation is performed by calling one of the validate() methods. It
  46  * specifies a suggested path to be used for validation if available, or only
  47  * the end entity certificate otherwise. Optionally additional certificates can
  48  * be specified that the caller believes could be helpful. Implementations are
  49  * free to make use of this information or validate the path using other means.
  50  * validate() also checks that the end entity certificate is suitable for the
  51  * intended purpose as described below.
  52  *
  53  * <p>There are two orthogonal parameters to select the Validator
  54  * implementation: type and variant. Type selects the validation algorithm.
  55  * Currently supported are TYPE_SIMPLE and TYPE_PKIX. See SimpleValidator and
  56  * PKIXValidator for details.
  57  * <p>
  58  * Variant controls additional extension checks. Currently supported are
  59  * five variants:
  60  * <ul>
  61  * <li>VAR_GENERIC (no additional checks),
  62  * <li>VAR_TLS_CLIENT (TLS client specific checks)
  63  * <li>VAR_TLS_SERVER (TLS server specific checks), and
  64  * <li>VAR_CODE_SIGNING (code signing specific checks).
  65  * <li>VAR_JCE_SIGNING (JCE code signing specific checks).
  66  * <li>VAR_TSA_SERVER (TSA server specific checks).
  67  * <li>VAR_PLUGIN_CODE_SIGNING (Plugin/WebStart code signing specific checks).
  68  * </ul>
  69  * See EndEntityChecker for more information.
  70  * <p>
  71  * Examples:
  72  * <pre>
  73  *   // instantiate validator specifying type, variant, and trust anchors
  74  *   Validator validator = Validator.getInstance(Validator.TYPE_PKIX,
  75  *                                               Validator.VAR_TLS_CLIENT,
  76  *                                               trustedCerts);
  77  *   // validate one or more chains using the validator
  78  *   validator.validate(chain); // throws CertificateException if failed
  79  * </pre>
  80  *
  81  * @see SimpleValidator
  82  * @see PKIXValidator
  83  * @see EndEntityChecker
  84  *
  85  * @author Andreas Sterbenz
  86  */
  87 public abstract class Validator {
  88 
  89     final static X509Certificate[] CHAIN0 = {};
  90 
  91     /**
  92      * Constant for a validator of type Simple.
  93      * @see #getInstance
  94      */
  95     public final static String TYPE_SIMPLE = "Simple";
  96 
  97     /**
  98      * Constant for a validator of type PKIX.
  99      * @see #getInstance
 100      */
 101     public final static String TYPE_PKIX = "PKIX";
 102 
 103     /**
 104      * Constant for a Generic variant of a validator.
 105      * @see #getInstance
 106      */
 107     public final static String VAR_GENERIC = "generic";
 108 
 109     /**
 110      * Constant for a Code Signing variant of a validator.
 111      * @see #getInstance
 112      */
 113     public final static String VAR_CODE_SIGNING = "code signing";
 114 
 115     /**
 116      * Constant for a JCE Code Signing variant of a validator.
 117      * @see #getInstance
 118      */
 119     public final static String VAR_JCE_SIGNING = "jce signing";
 120 
 121     /**
 122      * Constant for a TLS Client variant of a validator.
 123      * @see #getInstance
 124      */
 125     public final static String VAR_TLS_CLIENT = "tls client";
 126 
 127     /**
 128      * Constant for a TLS Server variant of a validator.
 129      * @see #getInstance
 130      */
 131     public final static String VAR_TLS_SERVER = "tls server";
 132 
 133     /**
 134      * Constant for a TSA Server variant of a validator.
 135      * @see #getInstance
 136      */
 137     public final static String VAR_TSA_SERVER = "tsa server";
 138 
 139     /**
 140      * Constant for a Code Signing variant of a validator for use by
 141      * the J2SE Plugin/WebStart code.
 142      * @see #getInstance
 143      */
 144     public final static String VAR_PLUGIN_CODE_SIGNING = "plugin code signing";
 145 
 146     private final String type;
 147     final EndEntityChecker endEntityChecker;
 148     final String variant;
 149 
 150     /**
 151      * @deprecated
 152      * @see #setValidationDate
 153      */
 154     @Deprecated
 155     volatile Date validationDate;
 156 
 157     Validator(String type, String variant) {
 158         this.type = type;
 159         this.variant = variant;
 160         endEntityChecker = EndEntityChecker.getInstance(type, variant);
 161     }
 162 
 163     /**
 164      * Get a new Validator instance using the trusted certificates from the
 165      * specified KeyStore as trust anchors.
 166      */
 167     public static Validator getInstance(String type, String variant,
 168             KeyStore ks) {
 169         return getInstance(type, variant, KeyStores.getTrustedCerts(ks));
 170     }
 171 
 172     /**
 173      * Get a new Validator instance using the Set of X509Certificates as trust
 174      * anchors.
 175      */
 176     public static Validator getInstance(String type, String variant,
 177             Collection<X509Certificate> trustedCerts) {
 178         if (type.equals(TYPE_SIMPLE)) {
 179             return new SimpleValidator(variant, trustedCerts);
 180         } else if (type.equals(TYPE_PKIX)) {
 181             return new PKIXValidator(variant, trustedCerts);
 182         } else {
 183             throw new IllegalArgumentException
 184                 ("Unknown validator type: " + type);
 185         }
 186     }
 187 
 188     /**
 189      * Get a new Validator instance using the provided PKIXBuilderParameters.
 190      * This method can only be used with the PKIX validator.
 191      */
 192     public static Validator getInstance(String type, String variant,
 193             PKIXBuilderParameters params) {
 194         if (type.equals(TYPE_PKIX) == false) {
 195             throw new IllegalArgumentException
 196                 ("getInstance(PKIXBuilderParameters) can only be used "
 197                 + "with PKIX validator");
 198         }
 199         return new PKIXValidator(variant, params);
 200     }
 201 
 202     /**
 203      * Validate the given certificate chain.
 204      */
 205     public final X509Certificate[] validate(X509Certificate[] chain)
 206             throws CertificateException {
 207         return validate(chain, null, null);
 208     }
 209 
 210     /**
 211      * Validate the given certificate chain. If otherCerts is non-null, it is
 212      * a Collection of additional X509Certificates that could be helpful for
 213      * path building.
 214      */
 215     public final X509Certificate[] validate(X509Certificate[] chain,
 216         Collection<X509Certificate> otherCerts) throws CertificateException {
 217         return validate(chain, otherCerts, null);
 218     }
 219 
 220     /**
 221      * Validate the given certificate chain. If otherCerts is non-null, it is
 222      * a Collection of additional X509Certificates that could be helpful for
 223      * path building.
 224      * <p>
 225      * Parameter is an additional parameter with variant specific meaning.
 226      * Currently, it is only defined for TLS_SERVER variant validators, where
 227      * it must be non null and the name of the TLS key exchange algorithm being
 228      * used (see JSSE X509TrustManager specification). In the future, it
 229      * could be used to pass in a PKCS#7 object for code signing to check time
 230      * stamps.
 231      * <p>
 232      * @return a non-empty chain that was used to validate the path. The
 233      * end entity cert is at index 0, the trust anchor at index n-1.
 234      */
 235     public final X509Certificate[] validate(X509Certificate[] chain,
 236             Collection<X509Certificate> otherCerts, Object parameter)
 237             throws CertificateException {
 238         return validate(chain, otherCerts, null, parameter);
 239     }
 240 
 241     /**
 242      * Validate the given certificate chain.
 243      *
 244      * @param chain the target certificate chain
 245      * @param otherCerts a Collection of additional X509Certificates that
 246      *        could be helpful for path building (or null)
 247      * @param constraints algorithm constraints for certification path
 248      *        processing
 249      * @param parameter an additional parameter with variant specific meaning.
 250      *        Currently, it is only defined for TLS_SERVER variant validators,
 251      *        where it must be non null and the name of the TLS key exchange
 252      *        algorithm being used (see JSSE X509TrustManager specification).
 253      *        In the future, it could be used to pass in a PKCS#7 object for
 254      *        code signing to check time stamps.
 255      * @return a non-empty chain that was used to validate the path. The
 256      *        end entity cert is at index 0, the trust anchor at index n-1.
 257      */
 258     public final X509Certificate[] validate(X509Certificate[] chain,
 259                 Collection<X509Certificate> otherCerts,
 260                 AlgorithmConstraints constraints,
 261                 Object parameter) throws CertificateException {
 262         chain = engineValidate(chain, otherCerts, constraints, parameter);
 263 
 264         // omit EE extension check if EE cert is also trust anchor
 265         if (chain.length > 1) {
 266             // EndEntityChecker does not need to check unresolved critical
 267             // extensions when validating with a TYPE_PKIX Validator.
 268             // A TYPE_PKIX Validator will already have run checks on all
 269             // certs' extensions, including checks by any PKIXCertPathCheckers
 270             // included in the PKIXParameters, so the extra checks would be
 271             // redundant.
 272             boolean checkUnresolvedCritExts =
 273                     (type == TYPE_PKIX) ? false : true;
 274             endEntityChecker.check(chain[0], parameter,
 275                                    checkUnresolvedCritExts);
 276         }
 277 
 278         return chain;
 279     }
 280 
 281     abstract X509Certificate[] engineValidate(X509Certificate[] chain,
 282                 Collection<X509Certificate> otherCerts,
 283                 AlgorithmConstraints constraints,
 284                 Object parameter) throws CertificateException;
 285 
 286     /**
 287      * Returns an immutable Collection of the X509Certificates this instance
 288      * uses as trust anchors.
 289      */
 290     public abstract Collection<X509Certificate> getTrustedCertificates();
 291 
 292     /**
 293      * Set the date to be used for subsequent validations. NOTE that
 294      * this is not a supported API, it is provided to simplify
 295      * writing tests only.
 296      *
 297      * @deprecated
 298      */
 299     @Deprecated
 300     public void setValidationDate(Date validationDate) {
 301         this.validationDate = validationDate;
 302     }
 303 
 304 }