Home | History | Annotate | Download | only in cert
      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      */
    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