2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package java.security;
21 import java.io.BufferedInputStream;
22 import java.io.InputStream;
23 import java.util.Enumeration;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Iterator;
27 import java.util.List;
29 import java.util.Map.Entry;
30 import java.util.Properties;
32 import java.util.logging.Level;
33 import java.util.logging.Logger;
34 import org.apache.harmony.security.Util;
35 import org.apache.harmony.security.fortress.Engine;
36 import org.apache.harmony.security.fortress.SecurityAccess;
37 import org.apache.harmony.security.fortress.Services;
40 * {@code Security} is the central class in the Java Security API. It manages
41 * the list of security {@code Provider} that have been installed into this
42 * runtime environment.
44 public final class Security {
46 // Security properties
47 private static Properties secprops = new Properties();
49 // static initialization
50 // - load security properties files
51 // - load statically registered providers
52 // - if no provider description file found then load default providers
54 AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {
56 boolean loaded = false;
58 // BEGIN android-added
60 * Android only uses a local "security.properties" resource
61 * for configuration. TODO: Reevaluate this decision.
64 InputStream configStream =
65 getClass().getResourceAsStream("security.properties");
66 InputStream input = new BufferedInputStream(configStream);
70 } catch (Exception ex) {
71 Logger.global.log(Level.SEVERE,
72 "Could not load Security properties.", ex);
76 // BEGIN android-removed
77 // if (Util.equalsIgnoreCase("true", secprops.getProperty("security.allowCustomPropertiesFile", "true"))) {
78 // String securityFile = System.getProperty("java.security.properties");
79 // if (securityFile != null) {
80 // if (securityFile.startsWith("=")) { // overwrite
81 // secprops = new Properties();
83 // securityFile = securityFile.substring(1);
86 // securityFile = PolicyUtils.expand(securityFile, System.getProperties());
87 // } catch (PolicyUtils.ExpansionFailedException e) {
88 //// System.err.println("Could not load custom Security properties file "
89 //// + securityFile +": " + e);
91 // f = new File(securityFile);
95 // FileInputStream fis = new FileInputStream(f);
96 // is = new BufferedInputStream(fis);
98 // URL url = new URL(securityFile);
99 // is = new BufferedInputStream(url.openStream());
101 // secprops.load(is);
104 // } catch (IOException e) {
105 // // System.err.println("Could not load custom Security properties file "
106 // // + securityFile +": " + e);
110 // END android-removed
112 registerDefaultProviders();
114 Engine.door = new SecurityDoor();
121 * This class can't be instantiated.
126 // Register default providers
127 private static void registerDefaultProviders() {
128 secprops.put("security.provider.1", "org.apache.harmony.xnet.provider.jsse.OpenSSLProvider");
129 secprops.put("security.provider.2", "org.apache.harmony.security.provider.cert.DRLCertFactory");
130 secprops.put("security.provider.3", "org.bouncycastle.jce.provider.BouncyCastleProvider");
131 secprops.put("security.provider.4", "org.apache.harmony.security.provider.crypto.CryptoProvider");
132 secprops.put("security.provider.5", "org.apache.harmony.xnet.provider.jsse.JSSEProvider");
136 * Returns value for the specified algorithm with the specified name.
139 * the name of the algorithm.
141 * the name of the property.
142 * @return value of the property.
143 * @deprecated Use {@link AlgorithmParameters} and {@link KeyFactory}
147 public static String getAlgorithmProperty(String algName, String propName) {
148 if (algName == null || propName == null) {
151 // BEGIN android-changed
152 String prop = "Alg." + propName + "." + algName;
153 // END android-changed
154 Provider[] providers = getProviders();
155 for (int i = 0; i < providers.length; i++) {
156 for (Enumeration e = providers[i].propertyNames(); e
157 .hasMoreElements();) {
158 String pname = (String) e.nextElement();
159 if (Util.equalsIgnoreCase(prop, pname)) {
160 return providers[i].getProperty(pname);
168 * Insert the given {@code Provider} at the specified {@code position}. The
169 * positions define the preference order in which providers are searched for
170 * requested algorithms.
172 * If a {@code SecurityManager} is installed, code calling this method needs
173 * the {@code SecurityPermission} {@code insertProvider.NAME} (where NAME is
174 * the provider name) to be granted, otherwise a {@code SecurityException}
178 * the provider to insert.
180 * the position (starting from 1).
181 * @return the actual position or {@code -1} if the given {@code provider}
182 * was already in the list. The actual position may be different
183 * from the desired position.
184 * @throws SecurityException
185 * if a {@code SecurityManager} is installed and the caller does
186 * not have permission to invoke this method.
188 public static synchronized int insertProviderAt(Provider provider,
190 // check security access; check that provider is not already
191 // installed, else return -1; if (position <1) or (position > max
192 // position) position = max position + 1; insert provider, shift up
193 // one position for next providers; Note: The position is 1-based
194 SecurityManager sm = System.getSecurityManager();
196 sm.checkSecurityAccess("insertProvider." + provider.getName());
198 if (getProvider(provider.getName()) != null) {
201 int result = Services.insertProviderAt(provider, position);
207 * Adds the given {@code provider} to the collection of providers at the
208 * next available position.
210 * If a {@code SecurityManager} is installed, code calling this method needs
211 * the {@code SecurityPermission} {@code insertProvider.NAME} (where NAME is
212 * the provider name) to be granted, otherwise a {@code SecurityException}
216 * the provider to be added.
217 * @return the actual position or {@code -1} if the given {@code provider}
218 * was already in the list.
219 * @throws SecurityException
220 * if a {@code SecurityManager} is installed and the caller does
221 * not have permission to invoke this method.
223 public static int addProvider(Provider provider) {
224 return insertProviderAt(provider, 0);
228 * Removes the {@code Provider} with the specified name form the collection
229 * of providers. If the the {@code Provider} with the specified name is
230 * removed, all provider at a greater position are shifted down one
233 * Returns silently if {@code name} is {@code null} or no provider with the
234 * specified name is installed.
236 * If a {@code SecurityManager} is installed, code calling this method needs
237 * the {@code SecurityPermission} {@code removeProvider.NAME} (where NAME is
238 * the provider name) to be granted, otherwise a {@code SecurityException}
242 * the name of the provider to remove.
243 * @throws SecurityException
244 * if a {@code SecurityManager} is installed and the caller does
245 * not have permission to invoke this method.
247 public static synchronized void removeProvider(String name) {
248 // It is not clear from spec.:
249 // 1. if name is null, should we checkSecurityAccess or not?
250 // throw SecurityException or not?
251 // 2. as 1 but provider is not installed
252 // 3. behavior if name is empty string?
255 if ((name == null) || (name.length() == 0)) {
258 p = getProvider(name);
262 SecurityManager sm = System.getSecurityManager();
264 sm.checkSecurityAccess("removeProvider." + name);
266 Services.removeProvider(p.getProviderNumber());
268 p.setProviderNumber(-1);
272 * Returns an array containing all installed providers. The providers are
273 * ordered according their preference order.
275 * @return an array containing all installed providers.
277 public static synchronized Provider[] getProviders() {
278 return Services.getProviders();
282 * Returns the {@code Provider} with the specified name. Returns {@code
283 * null} if name is {@code null} or no provider with the specified name is
287 * the name of the requested provider.
288 * @return the provider with the specified name, maybe {@code null}.
290 public static synchronized Provider getProvider(String name) {
291 return Services.getProvider(name);
295 * Returns the array of providers which meet the user supplied string
296 * filter. The specified filter must be supplied in one of two formats:
298 * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
300 * (for example: "MessageDigest.SHA")
301 * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
302 * ATTR_NAME:ATTR_VALUE
304 * (for example: "Signature.MD2withRSA KeySize:512")
308 * case-insensitive filter.
309 * @return the providers which meet the user supplied string filter {@code
310 * filter}. A {@code null} value signifies that none of the
311 * installed providers meets the filter specification.
312 * @throws InvalidParameterException
313 * if an unusable filter is supplied.
314 * @throws NullPointerException
315 * if {@code filter} is {@code null}.
317 public static Provider[] getProviders(String filter) {
318 if (filter == null) {
319 throw new NullPointerException();
321 if (filter.length() == 0) {
322 throw new InvalidParameterException();
324 HashMap<String, String> hm = new HashMap<String, String>();
325 int i = filter.indexOf(':');
326 if ((i == filter.length() - 1) || (i == 0)) {
327 throw new InvalidParameterException();
332 hm.put(filter.substring(0, i), filter.substring(i + 1));
334 return getProviders(hm);
338 * Returns the array of providers which meet the user supplied set of
339 * filters. The filter must be supplied in one of two formats:
341 * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
343 * for example: "MessageDigest.SHA" The value associated with the key must
344 * be an empty string. <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
345 * ATTR_NAME:ATTR_VALUE
347 * for example: "Signature.MD2withRSA KeySize:512" where "KeySize:512" is
348 * the value of the filter map entry.
352 * case-insensitive filter.
353 * @return the providers which meet the user supplied string filter {@code
354 * filter}. A {@code null} value signifies that none of the
355 * installed providers meets the filter specification.
356 * @throws InvalidParameterException
357 * if an unusable filter is supplied.
358 * @throws NullPointerException
359 * if {@code filter} is {@code null}.
361 public static synchronized Provider[] getProviders(Map<String,String> filter) {
362 if (filter == null) {
363 throw new NullPointerException();
365 if (filter.isEmpty()) {
368 java.util.List<Provider> result = Services.getProvidersList();
369 Set<Entry<String, String>> keys = filter.entrySet();
370 Map.Entry<String, String> entry;
371 for (Iterator<Entry<String, String>> it = keys.iterator(); it.hasNext();) {
373 String key = entry.getKey();
374 String val = entry.getValue();
375 String attribute = null;
376 int i = key.indexOf(' ');
377 int j = key.indexOf('.');
379 throw new InvalidParameterException();
381 if (i == -1) { // <crypto_service>.<algorithm_or_type>
382 if (val.length() != 0) {
383 throw new InvalidParameterException();
385 } else { // <crypto_service>.<algorithm_or_type> <attribute_name>
386 if (val.length() == 0) {
387 throw new InvalidParameterException();
389 attribute = key.substring(i + 1);
390 if (attribute.trim().length() == 0) {
391 throw new InvalidParameterException();
393 key = key.substring(0, i);
395 String serv = key.substring(0, j);
396 String alg = key.substring(j + 1);
397 if (serv.length() == 0 || alg.length() == 0) {
398 throw new InvalidParameterException();
401 for (int k = 0; k < result.size(); k++) {
404 } catch (IndexOutOfBoundsException e) {
407 if (!p.implementsAlg(serv, alg, attribute, val)) {
413 if (result.size() > 0) {
414 return result.toArray(new Provider[result.size()]);
420 * Returns the value of the security property named by the argument.
422 * If a {@code SecurityManager} is installed, code calling this method needs
423 * the {@code SecurityPermission} {@code getProperty.KEY} (where KEY is the
424 * specified {@code key}) to be granted, otherwise a {@code
425 * SecurityException} will be thrown.
428 * the name of the requested security property.
429 * @return the value of the security property.
430 * @throws SecurityException
431 * if a {@code SecurityManager} is installed and the caller does
432 * not have permission to invoke this method.
434 public static String getProperty(String key) {
436 throw new NullPointerException("key == null");
438 SecurityManager sm = System.getSecurityManager();
440 sm.checkSecurityAccess("getProperty." + key);
442 String property = secprops.getProperty(key);
443 if (property != null) {
444 property = property.trim();
450 * Sets the value of the specified security property.
452 * If a {@code SecurityManager} is installed, code calling this method needs
453 * the {@code SecurityPermission} {@code setProperty.KEY} (where KEY is the
454 * specified {@code key}) to be granted, otherwise a {@code
455 * SecurityException} will be thrown.
458 * the name of the security property.
460 * the value of the security property.
461 * @throws SecurityException
462 * if a {@code SecurityManager} is installed and the caller does
463 * not have permission to invoke this method.
465 public static void setProperty(String key, String datnum) {
466 SecurityManager sm = System.getSecurityManager();
468 sm.checkSecurityAccess("setProperty." + key);
470 secprops.put(key, datnum);
474 * Returns a {@code Set} of all registered algorithms for the specified
475 * cryptographic service. {@code "Signature"}, {@code "Cipher"} and {@code
476 * "KeyStore"} are examples for such kind of services.
479 * the case-insensitive name of the service.
480 * @return a {@code Set} of all registered algorithms for the specified
481 * cryptographic service, or an empty {@code Set} if {@code
482 * serviceName} is {@code null} or if no registered provider
483 * provides the requested service.
485 public static Set<String> getAlgorithms(String serviceName) {
486 Set<String> result = new HashSet<String>();
487 // BEGIN android-added
488 // compatibility with RI
489 if (serviceName == null) {
493 Provider[] p = getProviders();
494 for (int i = 0; i < p.length; i++) {
495 for (Iterator it = p[i].getServices().iterator(); it.hasNext();) {
496 Provider.Service s = (Provider.Service) it.next();
497 if (Util.equalsIgnoreCase(s.getType(),serviceName)) {
498 result.add(s.getAlgorithm());
507 * Update sequence numbers of all providers.
510 private static void renumProviders() {
511 Provider[] p = Services.getProviders();
512 for (int i = 0; i < p.length; i++) {
513 p[i].setProviderNumber(i + 1);
517 private static class SecurityDoor implements SecurityAccess {
518 // Access to Security.renumProviders()
519 public void renumProviders() {
520 Security.renumProviders();
523 // Access to Security.getAliases()
524 public List<String> getAliases(Provider.Service s) {
525 return s.getAliases();
528 // Access to Provider.getService()
529 public Provider.Service getService(Provider p, String type) {
530 return p.getService(type);