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 java.util.Collection;
36 
37 import sun.security.jca.*;
38 import sun.security.jca.GetInstance.Instance;
39 
40 /**
41  * A class for retrieving {@code Certificate}s and {@code CRL}s
42  * from a repository.
43  * <p>
44  * This class uses a provider-based architecture.
45  * To create a {@code CertStore}, call one of the static
46  * {@code getInstance} methods, passing in the type of
47  * {@code CertStore} desired, any applicable initialization parameters
48  * and optionally the name of the provider desired.
49  * <p>
50  * Once the {@code CertStore} has been created, it can be used to
51  * retrieve {@code Certificate}s and {@code CRL}s by calling its
52  * {@link #getCertificates(CertSelector selector) getCertificates} and
53  * {@link #getCRLs(CRLSelector selector) getCRLs} methods.
54  * <p>
55  * Unlike a {@link java.security.KeyStore KeyStore}, which provides access
56  * to a cache of private keys and trusted certificates, a
57  * {@code CertStore} is designed to provide access to a potentially
58  * vast repository of untrusted certificates and CRLs. For example, an LDAP
59  * implementation of {@code CertStore} provides access to certificates
60  * and CRLs stored in one or more directories using the LDAP protocol and the
61  * schema as defined in the RFC service attribute.
62  *
63  * <p> Android provides the following <code>CertStore</code> types:
64  * <table>
65  *   <thead>
66  *     <tr>
67  *       <th>Algorithm</th>
68  *       <th>Supported API Levels</th>
69  *     </tr>
70  *   </thead>
71  *   <tbody>
72  *     <tr>
73  *       <td>Collection</td>
74  *       <td>1+</td>
75  *     </tr>
76  *   </tbody>
77  * </table>
78  *
79  * This type is described in the <a href=
80  * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertStore">
81  * CertStore section</a> of the
82  * Java Cryptography Architecture Standard Algorithm Name Documentation.
83  *
84  * <p>
85  * <b>Concurrent Access</b>
86  * <p>
87  * All public methods of {@code CertStore} objects must be thread-safe.
88  * That is, multiple threads may concurrently invoke these methods on a
89  * single {@code CertStore} object (or more than one) with no
90  * ill effects. This allows a {@code CertPathBuilder} to search for a
91  * CRL while simultaneously searching for further certificates, for instance.
92  * <p>
93  * The static methods of this class are also guaranteed to be thread-safe.
94  * Multiple threads may concurrently invoke the static methods defined in
95  * this class with no ill effects.
96  *
97  * @since       1.4
98  * @author      Sean Mullan, Steve Hanna
99  */
100 public class CertStore {
101     /*
102      * Constant to lookup in the Security properties file to determine
103      * the default certstore type. In the Security properties file, the
104      * default certstore type is given as:
105      * <pre>
106      * certstore.type=LDAP
107      * </pre>
108      */
109     private static final String CERTSTORE_TYPE = "certstore.type";
110     private CertStoreSpi storeSpi;
111     private Provider provider;
112     private String type;
113     private CertStoreParameters params;
114 
115     /**
116      * Creates a {@code CertStore} object of the given type, and
117      * encapsulates the given provider implementation (SPI object) in it.
118      *
119      * @param storeSpi the provider implementation
120      * @param provider the provider
121      * @param type the type
122      * @param params the initialization parameters (may be {@code null})
123      */
CertStore(CertStoreSpi storeSpi, Provider provider, String type, CertStoreParameters params)124     protected CertStore(CertStoreSpi storeSpi, Provider provider,
125                         String type, CertStoreParameters params) {
126         this.storeSpi = storeSpi;
127         this.provider = provider;
128         this.type = type;
129         if (params != null)
130             this.params = (CertStoreParameters) params.clone();
131     }
132 
133     /**
134      * Returns a {@code Collection} of {@code Certificate}s that
135      * match the specified selector. If no {@code Certificate}s
136      * match the selector, an empty {@code Collection} will be returned.
137      * <p>
138      * For some {@code CertStore} types, the resulting
139      * {@code Collection} may not contain <b>all</b> of the
140      * {@code Certificate}s that match the selector. For instance,
141      * an LDAP {@code CertStore} may not search all entries in the
142      * directory. Instead, it may just search entries that are likely to
143      * contain the {@code Certificate}s it is looking for.
144      * <p>
145      * Some {@code CertStore} implementations (especially LDAP
146      * {@code CertStore}s) may throw a {@code CertStoreException}
147      * unless a non-null {@code CertSelector} is provided that
148      * includes specific criteria that can be used to find the certificates.
149      * Issuer and/or subject names are especially useful criteria.
150      *
151      * @param selector A {@code CertSelector} used to select which
152      *  {@code Certificate}s should be returned. Specify {@code null}
153      *  to return all {@code Certificate}s (if supported).
154      * @return A {@code Collection} of {@code Certificate}s that
155      *         match the specified selector (never {@code null})
156      * @throws CertStoreException if an exception occurs
157      */
getCertificates(CertSelector selector)158     public final Collection<? extends Certificate> getCertificates
159             (CertSelector selector) throws CertStoreException {
160         return storeSpi.engineGetCertificates(selector);
161     }
162 
163     /**
164      * Returns a {@code Collection} of {@code CRL}s that
165      * match the specified selector. If no {@code CRL}s
166      * match the selector, an empty {@code Collection} will be returned.
167      * <p>
168      * For some {@code CertStore} types, the resulting
169      * {@code Collection} may not contain <b>all</b> of the
170      * {@code CRL}s that match the selector. For instance,
171      * an LDAP {@code CertStore} may not search all entries in the
172      * directory. Instead, it may just search entries that are likely to
173      * contain the {@code CRL}s it is looking for.
174      * <p>
175      * Some {@code CertStore} implementations (especially LDAP
176      * {@code CertStore}s) may throw a {@code CertStoreException}
177      * unless a non-null {@code CRLSelector} is provided that
178      * includes specific criteria that can be used to find the CRLs.
179      * Issuer names and/or the certificate to be checked are especially useful.
180      *
181      * @param selector A {@code CRLSelector} used to select which
182      *  {@code CRL}s should be returned. Specify {@code null}
183      *  to return all {@code CRL}s (if supported).
184      * @return A {@code Collection} of {@code CRL}s that
185      *         match the specified selector (never {@code null})
186      * @throws CertStoreException if an exception occurs
187      */
getCRLs(CRLSelector selector)188     public final Collection<? extends CRL> getCRLs(CRLSelector selector)
189             throws CertStoreException {
190         return storeSpi.engineGetCRLs(selector);
191     }
192 
193     /**
194      * Returns a {@code CertStore} object that implements the specified
195      * {@code CertStore} type and is initialized with the specified
196      * parameters.
197      *
198      * <p> This method traverses the list of registered security Providers,
199      * starting with the most preferred Provider.
200      * A new CertStore object encapsulating the
201      * CertStoreSpi implementation from the first
202      * Provider that supports the specified type is returned.
203      *
204      * <p> Note that the list of registered providers may be retrieved via
205      * the {@link Security#getProviders() Security.getProviders()} method.
206      *
207      * <p>The {@code CertStore} that is returned is initialized with the
208      * specified {@code CertStoreParameters}. The type of parameters
209      * needed may vary between different types of {@code CertStore}s.
210      * Note that the specified {@code CertStoreParameters} object is
211      * cloned.
212      *
213      * @param type the name of the requested {@code CertStore} type.
214      * See the CertStore section in the <a href=
215      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertStore">
216      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
217      * for information about standard types.
218      *
219      * @param params the initialization parameters (may be {@code null}).
220      *
221      * @return a {@code CertStore} object that implements the specified
222      *          {@code CertStore} type.
223      *
224      * @throws NoSuchAlgorithmException if no Provider supports a
225      *          CertStoreSpi implementation for the specified type.
226      *
227      * @throws InvalidAlgorithmParameterException if the specified
228      *          initialization parameters are inappropriate for this
229      *          {@code CertStore}.
230      *
231      * @see java.security.Provider
232      */
getInstance(String type, CertStoreParameters params)233     public static CertStore getInstance(String type, CertStoreParameters params)
234             throws InvalidAlgorithmParameterException,
235             NoSuchAlgorithmException {
236         try {
237             Instance instance = GetInstance.getInstance("CertStore",
238                 CertStoreSpi.class, type, params);
239             return new CertStore((CertStoreSpi)instance.impl,
240                 instance.provider, type, params);
241         } catch (NoSuchAlgorithmException e) {
242             return handleException(e);
243         }
244     }
245 
handleException(NoSuchAlgorithmException e)246     private static CertStore handleException(NoSuchAlgorithmException e)
247             throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
248         Throwable cause = e.getCause();
249         if (cause instanceof InvalidAlgorithmParameterException) {
250             throw (InvalidAlgorithmParameterException)cause;
251         }
252         throw e;
253     }
254 
255     /**
256      * Returns a {@code CertStore} object that implements the specified
257      * {@code CertStore} type.
258      *
259      * <p> A new CertStore object encapsulating the
260      * CertStoreSpi implementation from the specified provider
261      * is returned.  The specified provider must be registered
262      * in the security provider list.
263      *
264      * <p> Note that the list of registered providers may be retrieved via
265      * the {@link Security#getProviders() Security.getProviders()} method.
266      *
267      * <p>The {@code CertStore} that is returned is initialized with the
268      * specified {@code CertStoreParameters}. The type of parameters
269      * needed may vary between different types of {@code CertStore}s.
270      * Note that the specified {@code CertStoreParameters} object is
271      * cloned.
272      *
273      * @param type the requested {@code CertStore} type.
274      * See the CertStore section in the <a href=
275      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertStore">
276      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
277      * for information about standard types.
278      *
279      * @param params the initialization parameters (may be {@code null}).
280      *
281      * @param provider the name of the provider.
282      *
283      * @return a {@code CertStore} object that implements the
284      *          specified type.
285      *
286      * @throws NoSuchAlgorithmException if a CertStoreSpi
287      *          implementation for the specified type is not
288      *          available from the specified provider.
289      *
290      * @throws InvalidAlgorithmParameterException if the specified
291      *          initialization parameters are inappropriate for this
292      *          {@code CertStore}.
293      *
294      * @throws NoSuchProviderException if the specified provider is not
295      *          registered in the security provider list.
296      *
297      * @exception IllegalArgumentException if the {@code provider} is
298      *          null or empty.
299      *
300      * @see java.security.Provider
301      */
getInstance(String type, CertStoreParameters params, String provider)302     public static CertStore getInstance(String type,
303             CertStoreParameters params, String provider)
304             throws InvalidAlgorithmParameterException,
305             NoSuchAlgorithmException, NoSuchProviderException {
306         try {
307             Instance instance = GetInstance.getInstance("CertStore",
308                 CertStoreSpi.class, type, params, provider);
309             return new CertStore((CertStoreSpi)instance.impl,
310                 instance.provider, type, params);
311         } catch (NoSuchAlgorithmException e) {
312             return handleException(e);
313         }
314     }
315 
316     /**
317      * Returns a {@code CertStore} object that implements the specified
318      * {@code CertStore} type.
319      *
320      * <p> A new CertStore object encapsulating the
321      * CertStoreSpi implementation from the specified Provider
322      * object is returned.  Note that the specified Provider object
323      * does not have to be registered in the provider list.
324      *
325      * <p>The {@code CertStore} that is returned is initialized with the
326      * specified {@code CertStoreParameters}. The type of parameters
327      * needed may vary between different types of {@code CertStore}s.
328      * Note that the specified {@code CertStoreParameters} object is
329      * cloned.
330      *
331      * @param type the requested {@code CertStore} type.
332      * See the CertStore section in the <a href=
333      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertStore">
334      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
335      * for information about standard types.
336      *
337      * @param params the initialization parameters (may be {@code null}).
338      *
339      * @param provider the provider.
340      *
341      * @return a {@code CertStore} object that implements the
342      *          specified type.
343      *
344      * @exception NoSuchAlgorithmException if a CertStoreSpi
345      *          implementation for the specified type is not available
346      *          from the specified Provider object.
347      *
348      * @throws InvalidAlgorithmParameterException if the specified
349      *          initialization parameters are inappropriate for this
350      *          {@code CertStore}
351      *
352      * @exception IllegalArgumentException if the {@code provider} is
353      *          null.
354      *
355      * @see java.security.Provider
356      */
getInstance(String type, CertStoreParameters params, Provider provider)357     public static CertStore getInstance(String type, CertStoreParameters params,
358             Provider provider) throws NoSuchAlgorithmException,
359             InvalidAlgorithmParameterException {
360         try {
361             Instance instance = GetInstance.getInstance("CertStore",
362                 CertStoreSpi.class, type, params, provider);
363             return new CertStore((CertStoreSpi)instance.impl,
364                 instance.provider, type, params);
365         } catch (NoSuchAlgorithmException e) {
366             return handleException(e);
367         }
368     }
369 
370     /**
371      * Returns the parameters used to initialize this {@code CertStore}.
372      * Note that the {@code CertStoreParameters} object is cloned before
373      * it is returned.
374      *
375      * @return the parameters used to initialize this {@code CertStore}
376      * (may be {@code null})
377      */
getCertStoreParameters()378     public final CertStoreParameters getCertStoreParameters() {
379         return (params == null ? null : (CertStoreParameters) params.clone());
380     }
381 
382     /**
383      * Returns the type of this {@code CertStore}.
384      *
385      * @return the type of this {@code CertStore}
386      */
getType()387     public final String getType() {
388         return this.type;
389     }
390 
391     /**
392      * Returns the provider of this {@code CertStore}.
393      *
394      * @return the provider of this {@code CertStore}
395      */
getProvider()396     public final Provider getProvider() {
397         return this.provider;
398     }
399 
400     /**
401      * Returns the default {@code CertStore} type as specified by the
402      * {@code certstore.type} security property, or the string
403      * {@literal "LDAP"} if no such property exists.
404      *
405      * <p>The default {@code CertStore} type can be used by applications
406      * that do not want to use a hard-coded type when calling one of the
407      * {@code getInstance} methods, and want to provide a default
408      * {@code CertStore} type in case a user does not specify its own.
409      *
410      * <p>The default {@code CertStore} type can be changed by setting
411      * the value of the {@code certstore.type} security property to the
412      * desired type.
413      *
414      * @see java.security.Security security properties
415      * @return the default {@code CertStore} type as specified by the
416      * {@code certstore.type} security property, or the string
417      * {@literal "LDAP"} if no such property exists.
418      */
getDefaultType()419     public final static String getDefaultType() {
420         String cstype;
421         cstype = AccessController.doPrivileged(new PrivilegedAction<String>() {
422             public String run() {
423                 return Security.getProperty(CERTSTORE_TYPE);
424             }
425         });
426         if (cstype == null) {
427             cstype = "LDAP";
428         }
429         return cstype;
430     }
431 }
432