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