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
26package java.security.cert;
27
28import java.security.AccessController;
29import java.security.InvalidAlgorithmParameterException;
30import java.security.NoSuchAlgorithmException;
31import java.security.NoSuchProviderException;
32import java.security.PrivilegedAction;
33import java.security.Provider;
34import java.security.Security;
35import java.util.Collection;
36
37import sun.security.jca.*;
38import 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 */
100public 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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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