1 /*
   2  * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.security.cert;
  27 
  28 import java.security.AccessController;
  29 import java.security.InvalidAlgorithmParameterException;
  30 import java.security.NoSuchAlgorithmException;
  31 import java.security.NoSuchProviderException;
  32 import java.security.PrivilegedAction;
  33 import java.security.Provider;
  34 import java.security.Security;
  35 import sun.security.util.Debug;
  36 
  37 import sun.security.jca.*;
  38 import sun.security.jca.GetInstance.Instance;
  39 
  40 /**
  41  * A class for validating certification paths (also known as certificate
  42  * chains).
  43  * <p>
  44  * This class uses a provider-based architecture.
  45  * To create a <code>CertPathValidator</code>,
  46  * call one of the static <code>getInstance</code> methods, passing in the
  47  * algorithm name of the <code>CertPathValidator</code> desired and
  48  * optionally the name of the provider desired.
  49  * <p>
  50  * Once a <code>CertPathValidator</code> object has been created, it can
  51  * be used to validate certification paths by calling the {@link #validate
  52  * validate} method and passing it the <code>CertPath</code> to be validated
  53  * and an algorithm-specific set of parameters. If successful, the result is
  54  * returned in an object that implements the
  55  * <code>CertPathValidatorResult</code> interface.
  56  *
  57  * <p> Every implementation of the Java platform is required to support the
  58  * following standard <code>CertPathValidator</code> algorithm:
  59  * <ul>
  60  * <li><tt>PKIX</tt></li>
  61  * </ul>
  62  * This algorithm is described in the <a href=
  63  * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator">
  64  * CertPathValidator section</a> of the
  65  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  66  * Consult the release documentation for your implementation to see if any
  67  * other algorithms are supported.
  68  *
  69  * <p>
  70  * <b>Concurrent Access</b>
  71  * <p>
  72  * The static methods of this class are guaranteed to be thread-safe.
  73  * Multiple threads may concurrently invoke the static methods defined in
  74  * this class with no ill effects.
  75  * <p>
  76  * However, this is not true for the non-static methods defined by this class.
  77  * Unless otherwise documented by a specific provider, threads that need to
  78  * access a single <code>CertPathValidator</code> instance concurrently should
  79  * synchronize amongst themselves and provide the necessary locking. Multiple
  80  * threads each manipulating a different <code>CertPathValidator</code>
  81  * instance need not synchronize.
  82  *
  83  * @see CertPath
  84  *
  85  * @since       1.4
  86  * @author      Yassir Elley
  87  */
  88 public class CertPathValidator {
  89 
  90     /*
  91      * Constant to lookup in the Security properties file to determine
  92      * the default certpathvalidator type. In the Security properties file,
  93      * the default certpathvalidator type is given as:
  94      * <pre>
  95      * certpathvalidator.type=PKIX
  96      * </pre>
  97      */
  98     private static final String CPV_TYPE = "certpathvalidator.type";
  99     private static final Debug debug = Debug.getInstance("certpath");
 100     private CertPathValidatorSpi validatorSpi;
 101     private Provider provider;
 102     private String algorithm;
 103 
 104     /**
 105      * Creates a <code>CertPathValidator</code> object of the given algorithm,
 106      * and encapsulates the given provider implementation (SPI object) in it.
 107      *
 108      * @param validatorSpi the provider implementation
 109      * @param provider the provider
 110      * @param algorithm the algorithm name
 111      */
 112     protected CertPathValidator(CertPathValidatorSpi validatorSpi,
 113         Provider provider, String algorithm)
 114     {
 115         this.validatorSpi = validatorSpi;
 116         this.provider = provider;
 117         this.algorithm = algorithm;
 118     }
 119 
 120     /**
 121      * Returns a <code>CertPathValidator</code> object that implements the
 122      * specified algorithm.
 123      *
 124      * <p> This method traverses the list of registered security Providers,
 125      * starting with the most preferred Provider.
 126      * A new CertPathValidator object encapsulating the
 127      * CertPathValidatorSpi implementation from the first
 128      * Provider that supports the specified algorithm is returned.
 129      *
 130      * <p> Note that the list of registered providers may be retrieved via
 131      * the {@link Security#getProviders() Security.getProviders()} method.
 132      *
 133      * @param algorithm the name of the requested <code>CertPathValidator</code>
 134      *  algorithm. See the CertPathValidator section in the <a href=
 135      *  "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator">
 136      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 137      * for information about standard algorithm names.
 138      *
 139      * @return a <code>CertPathValidator</code> object that implements the
 140      *          specified algorithm.
 141      *
 142      * @exception NoSuchAlgorithmException if no Provider supports a
 143      *          CertPathValidatorSpi implementation for the
 144      *          specified algorithm.
 145      *
 146      * @see java.security.Provider
 147      */
 148     public static CertPathValidator getInstance(String algorithm)
 149             throws NoSuchAlgorithmException {
 150         Instance instance = GetInstance.getInstance("CertPathValidator",
 151             CertPathValidatorSpi.class, algorithm);
 152         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
 153             instance.provider, algorithm);
 154     }
 155 
 156     /**
 157      * Returns a <code>CertPathValidator</code> object that implements the
 158      * specified algorithm.
 159      *
 160      * <p> A new CertPathValidator object encapsulating the
 161      * CertPathValidatorSpi implementation from the specified provider
 162      * is returned.  The specified provider must be registered
 163      * in the security provider list.
 164      *
 165      * <p> Note that the list of registered providers may be retrieved via
 166      * the {@link Security#getProviders() Security.getProviders()} method.
 167      *
 168      * @param algorithm the name of the requested <code>CertPathValidator</code>
 169      *  algorithm. See the CertPathValidator section in the <a href=
 170      *  "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator">
 171      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 172      * for information about standard algorithm names.
 173      *
 174      * @param provider the name of the provider.
 175      *
 176      * @return a <code>CertPathValidator</code> object that implements the
 177      *          specified algorithm.
 178      *
 179      * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
 180      *          implementation for the specified algorithm is not
 181      *          available from the specified provider.
 182      *
 183      * @exception NoSuchProviderException if the specified provider is not
 184      *          registered in the security provider list.
 185      *
 186      * @exception IllegalArgumentException if the <code>provider</code> is
 187      *          null or empty.
 188      *
 189      * @see java.security.Provider
 190      */
 191     public static CertPathValidator getInstance(String algorithm,
 192             String provider) throws NoSuchAlgorithmException,
 193             NoSuchProviderException {
 194         Instance instance = GetInstance.getInstance("CertPathValidator",
 195             CertPathValidatorSpi.class, algorithm, provider);
 196         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
 197             instance.provider, algorithm);
 198     }
 199 
 200     /**
 201      * Returns a <code>CertPathValidator</code> object that implements the
 202      * specified algorithm.
 203      *
 204      * <p> A new CertPathValidator object encapsulating the
 205      * CertPathValidatorSpi implementation from the specified Provider
 206      * object is returned.  Note that the specified Provider object
 207      * does not have to be registered in the provider list.
 208      *
 209      * @param algorithm the name of the requested <code>CertPathValidator</code>
 210      * algorithm. See the CertPathValidator section in the <a href=
 211      * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator">
 212      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 213      * for information about standard algorithm names.
 214      *
 215      * @param provider the provider.
 216      *
 217      * @return a <code>CertPathValidator</code> object that implements the
 218      *          specified algorithm.
 219      *
 220      * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
 221      *          implementation for the specified algorithm is not available
 222      *          from the specified Provider object.
 223      *
 224      * @exception IllegalArgumentException if the <code>provider</code> is
 225      *          null.
 226      *
 227      * @see java.security.Provider
 228      */
 229     public static CertPathValidator getInstance(String algorithm,
 230             Provider provider) throws NoSuchAlgorithmException {
 231         Instance instance = GetInstance.getInstance("CertPathValidator",
 232             CertPathValidatorSpi.class, algorithm, provider);
 233         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
 234             instance.provider, algorithm);
 235     }
 236 
 237     /**
 238      * Returns the <code>Provider</code> of this
 239      * <code>CertPathValidator</code>.
 240      *
 241      * @return the <code>Provider</code> of this <code>CertPathValidator</code>
 242      */
 243     public final Provider getProvider() {
 244         return this.provider;
 245     }
 246 
 247     /**
 248      * Returns the algorithm name of this <code>CertPathValidator</code>.
 249      *
 250      * @return the algorithm name of this <code>CertPathValidator</code>
 251      */
 252     public final String getAlgorithm() {
 253         return this.algorithm;
 254     }
 255 
 256     /**
 257      * Validates the specified certification path using the specified
 258      * algorithm parameter set.
 259      * <p>
 260      * The <code>CertPath</code> specified must be of a type that is
 261      * supported by the validation algorithm, otherwise an
 262      * <code>InvalidAlgorithmParameterException</code> will be thrown. For
 263      * example, a <code>CertPathValidator</code> that implements the PKIX
 264      * algorithm validates <code>CertPath</code> objects of type X.509.
 265      *
 266      * @param certPath the <code>CertPath</code> to be validated
 267      * @param params the algorithm parameters
 268      * @return the result of the validation algorithm
 269      * @exception CertPathValidatorException if the <code>CertPath</code>
 270      * does not validate
 271      * @exception InvalidAlgorithmParameterException if the specified
 272      * parameters or the type of the specified <code>CertPath</code> are
 273      * inappropriate for this <code>CertPathValidator</code>
 274      */
 275     public final CertPathValidatorResult validate(CertPath certPath,
 276         CertPathParameters params)
 277         throws CertPathValidatorException, InvalidAlgorithmParameterException
 278     {
 279         return validatorSpi.engineValidate(certPath, params);
 280     }
 281 
 282     /**
 283      * Returns the default <code>CertPathValidator</code> type as specified in
 284      * the Java security properties file, or the string &quot;PKIX&quot;
 285      * if no such property exists. The Java security properties file is
 286      * located in the file named &lt;JAVA_HOME&gt;/lib/security/java.security.
 287      * &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
 288      * and specifies the directory where the JRE is installed.
 289      *
 290      * <p>The default <code>CertPathValidator</code> type can be used by
 291      * applications that do not want to use a hard-coded type when calling one
 292      * of the <code>getInstance</code> methods, and want to provide a default
 293      * type in case a user does not specify its own.
 294      *
 295      * <p>The default <code>CertPathValidator</code> type can be changed by
 296      * setting the value of the "certpathvalidator.type" security property
 297      * (in the Java security properties file) to the desired type.
 298      *
 299      * @return the default <code>CertPathValidator</code> type as specified
 300      * in the Java security properties file, or the string &quot;PKIX&quot;
 301      * if no such property exists.
 302      */
 303     public final static String getDefaultType() {
 304         String cpvtype;
 305         cpvtype = AccessController.doPrivileged(new PrivilegedAction<String>() {
 306             public String run() {
 307                 return Security.getProperty(CPV_TYPE);
 308             }
 309         });
 310         if (cpvtype == null) {
 311             cpvtype = "PKIX";
 312         }
 313         return cpvtype;
 314     }
 315 }