1 /*
2  * Copyright (c) 2000, 2013, 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},
46  * call one of the static {@code getInstance} methods, passing in the
47  * algorithm name of the {@code CertPathValidator} desired and
48  * optionally the name of the provider desired.
49  *
50  * <p>Once a {@code CertPathValidator} 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} 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} interface.
56  *
57  * <p>The {@link #getRevocationChecker} method allows an application to specify
58  * additional algorithm-specific parameters and options used by the
59  * {@code CertPathValidator} when checking the revocation status of
60  * certificates. Here is an example demonstrating how it is used with the PKIX
61  * algorithm:
62  *
63  * <pre>
64  * CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
65  * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpv.getRevocationChecker();
66  * rc.setOptions(EnumSet.of(Option.SOFT_FAIL));
67  * params.addCertPathChecker(rc);
68  * CertPathValidatorResult cpvr = cpv.validate(path, params);
69  * </pre>
70  *
71  * <p>Every implementation of the Java platform is required to support the
72  * following standard {@code CertPathValidator} algorithm:
73  * <ul>
74  * <li>{@code PKIX}</li>
75  * </ul>
76  * This algorithm is described in the <a href=
77  * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator">
78  * CertPathValidator section</a> of the
79  * Java Cryptography Architecture Standard Algorithm Name Documentation.
80  * Consult the release documentation for your implementation to see if any
81  * other algorithms are supported.
82  *
83  * <p>
84  * <b>Concurrent Access</b>
85  * <p>
86  * The static methods of this class are guaranteed to be thread-safe.
87  * Multiple threads may concurrently invoke the static methods defined in
88  * this class with no ill effects.
89  * <p>
90  * However, this is not true for the non-static methods defined by this class.
91  * Unless otherwise documented by a specific provider, threads that need to
92  * access a single {@code CertPathValidator} instance concurrently should
93  * synchronize amongst themselves and provide the necessary locking. Multiple
94  * threads each manipulating a different {@code CertPathValidator}
95  * instance need not synchronize.
96  *
97  * @see CertPath
98  *
99  * @since       1.4
100  * @author      Yassir Elley
101  */
102 public class CertPathValidator {
103 
104     /*
105      * Constant to lookup in the Security properties file to determine
106      * the default certpathvalidator type. In the Security properties file,
107      * the default certpathvalidator type is given as:
108      * <pre>
109      * certpathvalidator.type=PKIX
110      * </pre>
111      */
112     private static final String CPV_TYPE = "certpathvalidator.type";
113     private final CertPathValidatorSpi validatorSpi;
114     private final Provider provider;
115     private final String algorithm;
116 
117     /**
118      * Creates a {@code CertPathValidator} object of the given algorithm,
119      * and encapsulates the given provider implementation (SPI object) in it.
120      *
121      * @param validatorSpi the provider implementation
122      * @param provider the provider
123      * @param algorithm the algorithm name
124      */
CertPathValidator(CertPathValidatorSpi validatorSpi, Provider provider, String algorithm)125     protected CertPathValidator(CertPathValidatorSpi validatorSpi,
126         Provider provider, String algorithm)
127     {
128         this.validatorSpi = validatorSpi;
129         this.provider = provider;
130         this.algorithm = algorithm;
131     }
132 
133     /**
134      * Returns a {@code CertPathValidator} object that implements the
135      * specified algorithm.
136      *
137      * <p> This method traverses the list of registered security Providers,
138      * starting with the most preferred Provider.
139      * A new CertPathValidator object encapsulating the
140      * CertPathValidatorSpi implementation from the first
141      * Provider that supports the specified algorithm is returned.
142      *
143      * <p> Note that the list of registered providers may be retrieved via
144      * the {@link Security#getProviders() Security.getProviders()} method.
145      *
146      * @param algorithm the name of the requested {@code CertPathValidator}
147      *  algorithm. See the CertPathValidator section in the <a href=
148      *  "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator">
149      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
150      * for information about standard algorithm names.
151      *
152      * @return a {@code CertPathValidator} object that implements the
153      *          specified algorithm.
154      *
155      * @exception NoSuchAlgorithmException if no Provider supports a
156      *          CertPathValidatorSpi implementation for the
157      *          specified algorithm.
158      *
159      * @see java.security.Provider
160      */
getInstance(String algorithm)161     public static CertPathValidator getInstance(String algorithm)
162             throws NoSuchAlgorithmException {
163         Instance instance = GetInstance.getInstance("CertPathValidator",
164             CertPathValidatorSpi.class, algorithm);
165         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
166             instance.provider, algorithm);
167     }
168 
169     /**
170      * Returns a {@code CertPathValidator} object that implements the
171      * specified algorithm.
172      *
173      * <p> A new CertPathValidator object encapsulating the
174      * CertPathValidatorSpi implementation from the specified provider
175      * is returned.  The specified provider must be registered
176      * in the security provider list.
177      *
178      * <p> Note that the list of registered providers may be retrieved via
179      * the {@link Security#getProviders() Security.getProviders()} method.
180      *
181      * @param algorithm the name of the requested {@code CertPathValidator}
182      *  algorithm. See the CertPathValidator section in the <a href=
183      *  "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator">
184      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
185      * for information about standard algorithm names.
186      *
187      * @param provider the name of the provider.
188      *
189      * @return a {@code CertPathValidator} object that implements the
190      *          specified algorithm.
191      *
192      * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
193      *          implementation for the specified algorithm is not
194      *          available from the specified provider.
195      *
196      * @exception NoSuchProviderException if the specified provider is not
197      *          registered in the security provider list.
198      *
199      * @exception IllegalArgumentException if the {@code provider} is
200      *          null or empty.
201      *
202      * @see java.security.Provider
203      */
getInstance(String algorithm, String provider)204     public static CertPathValidator getInstance(String algorithm,
205             String provider) throws NoSuchAlgorithmException,
206             NoSuchProviderException {
207         Instance instance = GetInstance.getInstance("CertPathValidator",
208             CertPathValidatorSpi.class, algorithm, provider);
209         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
210             instance.provider, algorithm);
211     }
212 
213     /**
214      * Returns a {@code CertPathValidator} object that implements the
215      * specified algorithm.
216      *
217      * <p> A new CertPathValidator object encapsulating the
218      * CertPathValidatorSpi implementation from the specified Provider
219      * object is returned.  Note that the specified Provider object
220      * does not have to be registered in the provider list.
221      *
222      * @param algorithm the name of the requested {@code CertPathValidator}
223      * algorithm. See the CertPathValidator section in the <a href=
224      * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator">
225      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
226      * for information about standard algorithm names.
227      *
228      * @param provider the provider.
229      *
230      * @return a {@code CertPathValidator} object that implements the
231      *          specified algorithm.
232      *
233      * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
234      *          implementation for the specified algorithm is not available
235      *          from the specified Provider object.
236      *
237      * @exception IllegalArgumentException if the {@code provider} is
238      *          null.
239      *
240      * @see java.security.Provider
241      */
getInstance(String algorithm, Provider provider)242     public static CertPathValidator getInstance(String algorithm,
243             Provider provider) throws NoSuchAlgorithmException {
244         Instance instance = GetInstance.getInstance("CertPathValidator",
245             CertPathValidatorSpi.class, algorithm, provider);
246         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
247             instance.provider, algorithm);
248     }
249 
250     /**
251      * Returns the {@code Provider} of this
252      * {@code CertPathValidator}.
253      *
254      * @return the {@code Provider} of this {@code CertPathValidator}
255      */
getProvider()256     public final Provider getProvider() {
257         return this.provider;
258     }
259 
260     /**
261      * Returns the algorithm name of this {@code CertPathValidator}.
262      *
263      * @return the algorithm name of this {@code CertPathValidator}
264      */
getAlgorithm()265     public final String getAlgorithm() {
266         return this.algorithm;
267     }
268 
269     /**
270      * Validates the specified certification path using the specified
271      * algorithm parameter set.
272      * <p>
273      * The {@code CertPath} specified must be of a type that is
274      * supported by the validation algorithm, otherwise an
275      * {@code InvalidAlgorithmParameterException} will be thrown. For
276      * example, a {@code CertPathValidator} that implements the PKIX
277      * algorithm validates {@code CertPath} objects of type X.509.
278      *
279      * @param certPath the {@code CertPath} to be validated
280      * @param params the algorithm parameters
281      * @return the result of the validation algorithm
282      * @exception CertPathValidatorException if the {@code CertPath}
283      * does not validate
284      * @exception InvalidAlgorithmParameterException if the specified
285      * parameters or the type of the specified {@code CertPath} are
286      * inappropriate for this {@code CertPathValidator}
287      */
validate(CertPath certPath, CertPathParameters params)288     public final CertPathValidatorResult validate(CertPath certPath,
289         CertPathParameters params)
290         throws CertPathValidatorException, InvalidAlgorithmParameterException
291     {
292         return validatorSpi.engineValidate(certPath, params);
293     }
294 
295     /**
296      * Returns the default {@code CertPathValidator} type as specified by
297      * the {@code certpathvalidator.type} security property, or the string
298      * {@literal "PKIX"} if no such property exists.
299      *
300      * <p>The default {@code CertPathValidator} type can be used by
301      * applications that do not want to use a hard-coded type when calling one
302      * of the {@code getInstance} methods, and want to provide a default
303      * type in case a user does not specify its own.
304      *
305      * <p>The default {@code CertPathValidator} type can be changed by
306      * setting the value of the {@code certpathvalidator.type} security
307      * property to the desired type.
308      *
309      * @see java.security.Security security properties
310      * @return the default {@code CertPathValidator} type as specified
311      * by the {@code certpathvalidator.type} security property, or the string
312      * {@literal "PKIX"} if no such property exists.
313      */
getDefaultType()314     public final static String getDefaultType() {
315         String cpvtype =
316             AccessController.doPrivileged(new PrivilegedAction<String>() {
317                 public String run() {
318                     return Security.getProperty(CPV_TYPE);
319                 }
320             });
321         return (cpvtype == null) ? "PKIX" : cpvtype;
322     }
323 
324     /**
325      * Returns a {@code CertPathChecker} that the encapsulated
326      * {@code CertPathValidatorSpi} implementation uses to check the revocation
327      * status of certificates. A PKIX implementation returns objects of
328      * type {@code PKIXRevocationChecker}. Each invocation of this method
329      * returns a new instance of {@code CertPathChecker}.
330      *
331      * <p>The primary purpose of this method is to allow callers to specify
332      * additional input parameters and options specific to revocation checking.
333      * See the class description for an example.
334      *
335      * @return a {@code CertPathChecker}
336      * @throws UnsupportedOperationException if the service provider does not
337      *         support this method
338      * @since 1.8
339      */
getRevocationChecker()340     public final CertPathChecker getRevocationChecker() {
341         return validatorSpi.engineGetRevocationChecker();
342     }
343 }
344