OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / java / security / Policy.java
1 /*
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 package java.security;
19
20 import java.util.Enumeration;
21 import org.apache.harmony.security.fortress.DefaultPolicy;
22 import org.apache.harmony.security.fortress.Engine;
23 import org.apache.harmony.security.fortress.PolicyUtils;
24
25
26 /**
27  * {@code Policy} is the common super type of classes which represent a system
28  * security policy. The {@code Policy} specifies which permissions apply to
29  * which code sources.
30  * <p>
31  * The system policy can be changed by setting the {@code 'policy.provider'}
32  * property in the file named {@code JAVA_HOME/lib/security/java.security} to
33  * the fully qualified class name of the desired {@code Policy}.
34  * <p>
35  * Only one instance of a {@code Policy} is active at any time.
36  */
37 public abstract class Policy {
38
39     // Key to security properties, defining default policy provider.
40     private static final String POLICY_PROVIDER = "policy.provider";
41
42     // The SecurityPermission required to set custom Policy.
43     private static final SecurityPermission SET_POLICY = new SecurityPermission(
44             "setPolicy");
45
46     // The SecurityPermission required to get current Policy.
47     static final SecurityPermission GET_POLICY = new SecurityPermission("getPolicy");
48
49     // The policy currently in effect.
50     private static Policy activePolicy;
51
52     // Store spi implementation service name
53     private static final String POLICYSERVICE = "Policy";
54
55     // Used to access common engine functionality
56     private static Engine engine = new Engine(POLICYSERVICE);
57
58     private String type;
59
60     private Policy.Parameters params;
61
62     private Provider provider;
63
64     // Store used spi implementation
65     private PolicySpi spiImpl;
66
67     private static final String CREATE_POLICY = "createPolicy.";
68
69     public Policy() {
70         // default constructor
71     }
72
73     private Policy(PolicySpi spi, Provider p, String t, Policy.Parameters para) {
74         this.spiImpl = spi;
75         this.provider = p;
76         this.type = t;
77         this.params = para;
78     }
79
80     private static class PolicyDelegate extends Policy {
81
82         public PolicyDelegate(PolicySpi spi, Provider p, String t,
83                 Policy.Parameters para) {
84             super(spi, p, t, para);
85         }
86     }
87
88     /**
89      * Answers a Policy object with the specified type and the specified
90      * parameter.
91      *
92      * Traverses the list of registered security providers, beginning with the
93      * most preferred Provider. A new Policy object encapsulating the PolicySpi
94      * implementation from the first Provider that supports the specified type
95      * is returned.
96      *
97      * Note that the list of registered providers may be retrieved via the
98      * Security.getProviders() method.
99      *
100      * @param type -
101      *            the specified Policy type. See Appendix A in the Java
102      *            Cryptography Architecture API Specification & Reference for a
103      *            list of standard Policy types.
104      * @param params -
105      *            parameters for the Policy, which may be null.
106      * @return the new Policy object.
107      * @throws NoSuchAlgorithmException -
108      *             if no Provider supports a PolicySpi implementation for the
109      *             specified type.
110      * @throws SecurityException -
111      *             if the caller does not have permission to get a Policy
112      *             instance for the specified type.
113      * @throws NullPointerException -
114      *             if the specified type is null.
115      * @throws IllegalArgumentException -
116      *             if the specified parameters' type are not allowed by the
117      *             PolicySpi implementation from the selected Provider.
118      */
119     public static Policy getInstance(String type, Policy.Parameters params)
120             throws NoSuchAlgorithmException {
121         checkSecurityPermission(new SecurityPermission(CREATE_POLICY + type));
122
123         if (type == null) {
124             throw new NullPointerException();
125         }
126
127         try {
128             synchronized (engine) {
129                 engine.getInstance(type, params);
130                 return new PolicyDelegate((PolicySpi) engine.spi,
131                         engine.provider, type, params);
132             }
133
134         } catch (NoSuchAlgorithmException e) {
135             if (e.getCause() == null) {
136                 throw e;
137             }
138             throw new IllegalArgumentException("Unrecognized policy parameter: " + params);
139         }
140     }
141
142     /**
143      * Answers a Policy object of the specified type.
144      *
145      * A new Policy object encapsulating the PolicySpi implementation from the
146      * specified provider is returned. The specified provider must be registered
147      * in the provider list via the Security.getProviders() method, otherwise
148      * NoSuchProviderException will be thrown.
149      *
150      * @param type -
151      *            the specified Policy type. So far in Java 6, only 'JavaPolicy'
152      *            supported.
153      * @param params -
154      *            the Policy.Parameter object, which may be null.
155      * @param provider -
156      *            the provider.
157      * @return the new Policy object.
158      *
159      * @throws NoSuchProviderException -
160      *             if the specified provider is not registered in the security
161      *             provider list.
162      * @throws NoSuchAlgorithmException -
163      *             if the specified provider does not support a PolicySpi
164      *             implementation for the specified type.
165      * @throws SecurityException -
166      *             if the caller does not have permission to get a Policy
167      *             instance for the specified type.
168      * @throws NullPointerException -
169      *             if the specified type is null.
170      * @throws IllegalArgumentException -
171      *             if the specified Provider is null, or if the specified
172      *             parameters' type are not allowed by the PolicySpi
173      *             implementation from the specified Provider.
174      */
175     public static Policy getInstance(String type, Policy.Parameters params,
176             String provider) throws NoSuchProviderException,
177             NoSuchAlgorithmException {
178         if ((provider == null) || provider.isEmpty()) {
179             throw new IllegalArgumentException("Provider is null or empty string");
180         }
181         checkSecurityPermission(new SecurityPermission(CREATE_POLICY + type));
182
183         Provider impProvider = Security.getProvider(provider);
184         if (impProvider == null) {
185             throw new NoSuchProviderException("Provider " + provider + " is not available");
186         }
187
188         return getInstanceImpl(type, params, impProvider);
189     }
190
191     /**
192      * Answers a Policy object of the specified type.
193      *
194      * A new Policy object encapsulating the PolicySpi implementation from the
195      * specified Provider object is returned. Note that the specified Provider
196      * object does not have to be registered in the provider list.
197      *
198      * @param type -
199      *            the specified Policy type. So far in Java 6, only 'JavaPolicy'
200      *            supported.
201      * @param params -
202      *            the Policy.Parameter object, which may be null.
203      * @param provider -
204      *            the Policy service Provider.
205      * @return the new Policy object.
206      *
207      * @throws NoSuchAlgorithmException -
208      *             if the specified Provider does not support a PolicySpi
209      *             implementation for the specified type.
210      * @throws IllegalArgumentException -
211      *             if the specified Provider is null, or if the specified
212      *             parameters' type are not allowed by the PolicySpi
213      *             implementation from the specified Provider.
214      * @throws NullPointerException -
215      *             if the specified type is null.
216      * @throws SecurityException -
217      *             if the caller does not have permission to get a Policy
218      *             instance for the specified type.
219      */
220     public static Policy getInstance(String type, Policy.Parameters params,
221             Provider provider) throws NoSuchAlgorithmException {
222         if (provider == null) {
223             throw new IllegalArgumentException("provider == null");
224         }
225         checkSecurityPermission(new SecurityPermission(CREATE_POLICY + type));
226
227         return getInstanceImpl(type, params, provider);
228     }
229
230     private static void checkSecurityPermission(SecurityPermission permission) {
231         SecurityManager sm = System.getSecurityManager();
232         if (sm != null) {
233             sm.checkPermission(permission);
234         }
235     }
236
237     private static Policy getInstanceImpl(String type, Policy.Parameters params, Provider provider) throws NoSuchAlgorithmException {
238         if (type == null) {
239             throw new NullPointerException();
240         }
241
242         try {
243             synchronized (engine) {
244                 engine.getInstance(type, provider, params);
245                 return new PolicyDelegate((PolicySpi) engine.spi, provider,
246                         type, params);
247             }
248         } catch (NoSuchAlgorithmException e) {
249             if (e.getCause() == null) {
250                 throw e;
251             }
252             throw new IllegalArgumentException("Unrecognized policy parameter: " + params);
253         }
254     }
255
256     /**
257      * Answers Policy parameters.
258      *
259      * This method will only answer non-null parameters if it was obtained via a
260      * call to Policy.getInstance. Otherwise this method returns null.
261      *
262      * @return Policy parameters, or null.
263      */
264     public Policy.Parameters getParameters() {
265         return params;
266     }
267
268     /**
269      * Answers the Provider of this Policy.
270      *
271      * This method will only answer non-null Provider if it was obtained via a
272      * call to Policy.getInstance. Otherwise this method returns null.
273      *
274      * @return the Provider of this Policy, or null.
275      */
276     public Provider getProvider() {
277         return provider;
278     }
279
280     /**
281      * Answers the type of this Policy.
282      *
283      * This method will only answer non-null type if it was obtained via a call
284      * to Policy.getInstance. Otherwise this method returns null.
285      *
286      * @return the type of this Policy, or null.
287      */
288     public String getType() {
289         return type;
290     }
291
292     /**
293      * A read-only empty PermissionCollection instance.
294      */
295     public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION = new PermissionCollection() {
296
297         private static final long serialVersionUID = 1L;
298
299         @Override
300         public void add(Permission permission) {
301             throw new SecurityException(
302                     "attempt to add a Permission to a readonly Permissions object");
303         }
304
305         @Override
306         public Enumeration<Permission> elements() {
307             return new Permissions().elements();
308         }
309
310         @Override
311         public boolean implies(Permission permission) {
312             if (permission == null) {
313                 throw new NullPointerException();
314             }
315             return false;
316         }
317
318         @Override
319         public boolean isReadOnly() {
320             // always returns true since it is a read-only instance.
321             // RI does not override this method.
322             return true;
323         }
324     };
325
326     /**
327      * A marker interface for Policy parameters.
328      */
329     public static interface Parameters {
330         // a marker interface
331     }
332
333     /**
334      * Returns a {@code PermissionCollection} describing what permissions are
335      * allowed for the specified {@code CodeSource} based on the current
336      * security policy.
337      * <p>
338      * Note that this method is not called for classes which are in the system
339      * domain (i.e. system classes). System classes are always given
340      * full permissions (i.e. AllPermission). This can not be changed by
341      * installing a new policy.
342      *
343      * @param cs
344      *            the {@code CodeSource} to compute the permissions for.
345      * @return the permissions that are granted to the specified {@code
346      *         CodeSource}.
347      */
348     public PermissionCollection getPermissions(CodeSource cs) {
349         return spiImpl == null ? Policy.UNSUPPORTED_EMPTY_COLLECTION : spiImpl
350                 .engineGetPermissions(cs);
351     }
352
353     /**
354      * Reloads the policy configuration for this {@code Policy} instance.
355      */
356     public void refresh() {
357         if (spiImpl != null) {
358             spiImpl.engineRefresh();
359         }
360     }
361
362     /**
363      * Returns a {@code PermissionCollection} describing what permissions are
364      * allowed for the specified {@code ProtectionDomain} (more specifically,
365      * its {@code CodeSource}) based on the current security policy.
366      * <p>
367      * Note that this method is not< called for classes which are in the
368      * system domain (i.e. system classes). System classes are always
369      * given full permissions (i.e. AllPermission). This can not be changed by
370      * installing a new policy.
371      *
372      * @param domain
373      *            the {@code ProtectionDomain} to compute the permissions for.
374      * @return the permissions that are granted to the specified {@code
375      *         CodeSource}.
376      */
377     public PermissionCollection getPermissions(ProtectionDomain domain) {
378         Permissions permissions = new Permissions();
379         if (domain != null) {
380             try {
381                 PermissionCollection cds = getPermissions(domain
382                         .getCodeSource());
383                 if (cds != Policy.UNSUPPORTED_EMPTY_COLLECTION) {
384                     Enumeration<Permission> elements = cds.elements();
385                     while (elements.hasMoreElements()) {
386                         permissions.add(elements.nextElement());
387                     }
388                 }
389             } catch (NullPointerException e) {
390                 // ignore the exception, just add nothing to the result set
391             }
392
393             PermissionCollection pds = domain.getPermissions();
394             if (pds != null) {
395                 Enumeration<Permission> pdElements = pds.elements();
396                 while (pdElements.hasMoreElements()) {
397                     permissions.add(pdElements.nextElement());
398                 }
399             }
400         }
401         return permissions;
402     }
403
404     /**
405      * Indicates whether the specified {@code Permission} is implied by the
406      * {@code PermissionCollection} of the specified {@code ProtectionDomain}.
407      *
408      * @param domain
409      *            the {@code ProtectionDomain} for which the permission should
410      *            be granted.
411      * @param permission
412      *            the {@code Permission} for which authorization is to be
413      *            verified.
414      * @return {@code true} if the {@code Permission} is implied by the {@code
415      *         ProtectionDomain}, {@code false} otherwise.
416      */
417     public boolean implies(ProtectionDomain domain, Permission permission) {
418         return spiImpl == null ? defaultImplies(domain, permission) : spiImpl
419                 .engineImplies(domain, permission);
420     }
421
422     private boolean defaultImplies(ProtectionDomain domain, Permission permission) {
423         if (domain == null && permission == null) {
424             throw new NullPointerException();
425         }
426         boolean implies = false;
427         if (domain != null) {
428             PermissionCollection total = getPermissions(domain);
429             PermissionCollection inherent = domain.getPermissions();
430             if (inherent != null) {
431                 Enumeration<Permission> en = inherent.elements();
432                 while (en.hasMoreElements()) {
433                     total.add(en.nextElement());
434                 }
435             }
436             try {
437                 implies = total.implies(permission);
438             } catch (NullPointerException e) {
439                 // return false instead of throwing the NullPointerException
440                 implies = false;
441             }
442         }
443         return implies;
444     }
445
446     /**
447      * Returns the current system security policy. If no policy has been
448      * instantiated then this is done using the security property {@code
449      * "policy.provider"}.
450      * <p>
451      * If a {@code SecurityManager} is installed, code calling this method needs
452      * the {@code SecurityPermission} {@code getPolicy} to be granted, otherwise
453      * a {@code SecurityException} will be thrown.
454      *
455      * @return the current system security policy.
456      * @throws SecurityException
457      *             if a {@code SecurityManager} is installed and the caller does
458      *             not have permission to invoke this method.
459      */
460     public static Policy getPolicy() {
461         checkSecurityPermission(GET_POLICY);
462         return getAccessiblePolicy();
463     }
464
465     // Reads name of default policy provider from security.properties,
466     // loads the class and instantiates the provider.<br>
467     // In case of any error, including undefined provider name,
468     // returns new instance of org.apache.harmony.security.FilePolicy provider.
469     private static Policy getDefaultProvider() {
470         final String defaultClass = AccessController
471                 .doPrivileged(new PolicyUtils.SecurityPropertyAccessor(
472                         POLICY_PROVIDER));
473         if (defaultClass == null) {
474             // TODO log warning
475             // System.err.println("No policy provider specified. Loading the "
476             // + DefaultPolicy.class.getName());
477             return new DefaultPolicy();
478         }
479
480         // TODO accurate classloading
481         return AccessController.doPrivileged(new PrivilegedAction<Policy>() {
482
483             public Policy run() {
484                 try {
485                     return (Policy) Class.forName(defaultClass, true,
486                             ClassLoader.getSystemClassLoader()).newInstance();
487                 }
488                 catch (Exception e) {
489                     //TODO log error
490                     //System.err.println("Error loading policy provider <"
491                     //                 + defaultClass + "> : " + e
492                     //                 + "\nSwitching to the default "
493                     //                 + DefaultPolicy.class.getName());
494                     return new DefaultPolicy();
495                 }
496             }
497         });
498
499     }
500
501     /**
502      * Returns {@code true} if system policy provider is instantiated.
503      */
504     static boolean isSet() {
505         return activePolicy != null;
506     }
507
508     /**
509      * Shortcut accessor for friendly classes, to skip security checks.
510      * If active policy was set to <code>null</code>, loads default provider,
511      * so this method never returns <code>null</code>. <br>
512      * This method is synchronized with setPolicy()
513      */
514     static synchronized Policy getAccessiblePolicy() {
515         if (activePolicy == null) {
516             activePolicy = getDefaultProvider();
517         }
518         return activePolicy;
519     }
520
521     /**
522      * Sets the system wide policy.
523      * <p>
524      * If a {@code SecurityManager} is installed, code calling this method needs
525      * the {@code SecurityPermission} {@code setPolicy} to be granted, otherwise
526      * a {@code SecurityException} will be thrown.
527      *
528      * @param policy
529      *            the {@code Policy} to set.
530      * @throws SecurityException
531      *             if a {@code SecurityManager} is installed and the caller does
532      *             not have permission to invoke this method.
533      */
534     public static void setPolicy(Policy policy) {
535         checkSecurityPermission(SET_POLICY);
536         synchronized (Policy.class) {
537             activePolicy = policy;
538         }
539     }
540 }