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}/../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 */ CertStore(CertStoreSpi storeSpi, Provider provider, String type, CertStoreParameters params)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 */ getCertificates(CertSelector selector)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 */ getCRLs(CRLSelector selector)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}/../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 */ getInstance(String type, CertStoreParameters params)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 handleException(NoSuchAlgorithmException e)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}/../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 */ getInstance(String type, CertStoreParameters params, String provider)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}/../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 */ getInstance(String type, CertStoreParameters params, Provider provider)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 */ getCertStoreParameters()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 */ getType()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 */ getProvider()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 */ getDefaultType()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