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