1 /* 2 * Copyright (c) 2000, 2017, 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}/../specs/security/standard-names.html#certstore-types"> 71 * CertStore section</a> of the 72 * Java Security Standard Algorithm Names Specification. 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 */ CertStore(CertStoreSpi storeSpi, Provider provider, String type, CertStoreParameters params)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 */ getCertificates(CertSelector selector)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 */ getCRLs(CRLSelector selector)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}/../specs/security/standard-names.html#certstore-types"> 216 * Java Security Standard Algorithm Names Specification</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 */ getInstance(String type, CertStoreParameters params)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 handleException(NoSuchAlgorithmException e)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}/../specs/security/standard-names.html#certstore-types"> 280 * Java Security Standard Algorithm Names Specification</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 */ getInstance(String type, CertStoreParameters params, String provider)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}/../specs/security/standard-names.html#certstore-types"> 341 * Java Security Standard Algorithm Names Specification</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 */ getInstance(String type, CertStoreParameters params, Provider provider)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 */ getCertStoreParameters()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 */ getType()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 */ getProvider()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 */ getDefaultType()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 } 442