KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > Policy


1 /*
2  * @(#)Policy.java 1.95 06/09/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8
9 package java.security;
10
11 import java.io.*;
12 import java.lang.RuntimePermission JavaDoc;
13 import java.net.MalformedURLException JavaDoc;
14 import java.net.URL JavaDoc;
15 import java.util.Enumeration JavaDoc;
16 import java.util.Hashtable JavaDoc;
17 import java.util.Vector JavaDoc;
18 import java.util.StringTokenizer JavaDoc;
19 import java.util.PropertyPermission JavaDoc;
20
21 import java.lang.reflect.*;
22
23 import java.util.WeakHashMap JavaDoc;
24 import sun.security.util.Debug;
25 import sun.security.util.SecurityConstants;
26
27
28 /**
29  * This is an abstract class for representing the system security
30  * policy for a Java application environment (specifying
31  * which permissions are available for code from various sources).
32  * That is, the security policy is represented by a Policy subclass
33  * providing an implementation of the abstract methods
34  * in this Policy class.
35  *
36  * <p>There is only one Policy object in effect at any given time.
37  *
38  * <p>The source location for the policy information utilized by the
39  * Policy object is up to the Policy implementation.
40  * The policy configuration may be stored, for example, as a
41  * flat ASCII file, as a serialized binary file of
42  * the Policy class, or as a database.
43  *
44  * <p>The currently-installed Policy object can be obtained by
45  * calling the <code>getPolicy</code> method, and it can be
46  * changed by a call to the <code>setPolicy</code> method (by
47  * code with permission to reset the Policy).
48  *
49  * <p>The <code>refresh</code> method causes the policy
50  * object to refresh/reload its current configuration.
51  *
52  * <p>This is implementation-dependent. For example, if the policy
53  * object stores its policy in configuration files, calling
54  * <code>refresh</code> will cause it to re-read the configuration
55  * policy files. The refreshed policy may not have an effect on classes
56  * in a particular ProtectionDomain. This is dependent on the Policy
57  * provider's implementation of the
58  * {@link #implies(ProtectionDomain,Permission) implies}
59  * method and the PermissionCollection caching strategy.
60  *
61  * <p>The default Policy implementation can be changed by setting the
62  * value of the "policy.provider" security property (in the Java
63  * security properties file) to the fully qualified name of
64  * the desired Policy implementation class.
65  * The Java security properties file is located in the file named
66  * &lt;JAVA_HOME&gt;/lib/security/java.security, where &lt;JAVA_HOME&gt;
67  * refers to the directory where the JDK was installed.
68  *
69  * @author Roland Schemers
70  * @author Gary Ellison
71  * @version 1.94, 06/28/04
72  * @see java.security.CodeSource
73  * @see java.security.PermissionCollection
74  * @see java.security.SecureClassLoader
75  */

76
77 public abstract class Policy {
78
79     /** the system-wide policy. */
80     private static Policy JavaDoc policy; // package private for AccessControlContext
81
private static final Debug debug = Debug.getInstance("policy");
82
83     // Cache mapping ProtectionDomain to PermissionCollection
84
private WeakHashMap JavaDoc pdMapping;
85
86     /** package private for AccessControlContext */
87     static boolean isSet()
88     {
89     return policy != null;
90     }
91
92     /**
93      * Returns the installed Policy object. This value should not be cached,
94      * as it may be changed by a call to <code>setPolicy</code>.
95      * This method first calls
96      * <code>SecurityManager.checkPermission</code> with a
97      * <code>SecurityPermission("getPolicy")</code> permission
98      * to ensure it's ok to get the Policy object..
99      *
100      * @return the installed Policy.
101      *
102      * @throws SecurityException
103      * if a security manager exists and its
104      * <code>checkPermission</code> method doesn't allow
105      * getting the Policy object.
106      *
107      * @see SecurityManager#checkPermission(Permission)
108      * @see #setPolicy(java.security.Policy)
109      */

110     public static Policy JavaDoc getPolicy()
111     {
112         SecurityManager JavaDoc sm = System.getSecurityManager();
113         if (sm != null)
114         sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
115     return getPolicyNoCheck();
116     }
117
118     /**
119      * Returns the installed Policy object, skipping the security check.
120      * Used by SecureClassLoader and getPolicy.
121      *
122      * @return the installed Policy.
123      *
124      */

125     static synchronized Policy JavaDoc getPolicyNoCheck()
126     {
127     if (policy == null) {
128         String JavaDoc policy_class = null;
129         policy_class = (String JavaDoc)AccessController.doPrivileged(
130                 new PrivilegedAction JavaDoc() {
131             public Object JavaDoc run() {
132             return Security.getProperty("policy.provider");
133             }
134         });
135         if (policy_class == null) {
136         policy_class = "sun.security.provider.PolicyFile";
137         }
138
139     /**
140           * Install a bootstrap (sandbox) policy to avoid recursion
141           * while the configured policy implementation initializes itself.
142           * After the configured implementation loads, install it over
143           * the bootstrap policy.
144           */

145         policy = new sun.security.provider.PolicyFile(true);
146
147         try {
148         policy = (Policy JavaDoc)
149             Class.forName(policy_class).newInstance();
150         } catch (Exception JavaDoc e) {
151
152         // policy_class seems to be an extension
153

154         final String JavaDoc pc = policy_class;
155         Policy JavaDoc p = (Policy JavaDoc)
156             AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
157             public Object JavaDoc run() {
158                 try {
159                 ClassLoader JavaDoc cl =
160                     ClassLoader.getSystemClassLoader();
161                 // we want the extension loader
162
ClassLoader JavaDoc extcl = null;
163                 while (cl != null) {
164                     extcl = cl;
165                     cl = cl.getParent();
166                 }
167                 return (extcl != null? Class.forName
168                     (pc, true, extcl).newInstance():
169                     null);
170                 } catch (Exception JavaDoc e) {
171                 return null;
172                 }
173             }
174             });
175         /*
176          * if it loaded install it as the policy provider. Otherwise
177          * continue to use the bootstrap implementation
178          */

179         if (p != null)
180             policy = p;
181             
182         if (p == null && debug != null) {
183             debug.println("policy provider " +
184                   policy_class + " not available;using " +
185                   "sun.security.provider.PolicyFile");
186             e.printStackTrace();
187         }
188         }
189     }
190     return policy;
191     }
192
193     /**
194      * Sets the system-wide Policy object. This method first calls
195      * <code>SecurityManager.checkPermission</code> with a
196      * <code>SecurityPermission("setPolicy")</code>
197      * permission to ensure it's ok to set the Policy.
198      *
199      * @param p the new system Policy object.
200      *
201      * @throws SecurityException
202      * if a security manager exists and its
203      * <code>checkPermission</code> method doesn't allow
204      * setting the Policy.
205      *
206      * @see SecurityManager#checkPermission(Permission)
207      * @see #getPolicy()
208      *
209      */

210     public static void setPolicy(Policy JavaDoc p)
211     {
212     SecurityManager JavaDoc sm = System.getSecurityManager();
213     if (sm != null) sm.checkPermission(
214                  new SecurityPermission JavaDoc("setPolicy"));
215     if (p != null) {
216         initPolicy(p);
217     }
218     synchronized (Policy JavaDoc.class) {
219         Policy.policy = p;
220     }
221     }
222
223     /**
224      * Initialize superclass state such that a legacy provider can
225      * handle queries for itself.
226      *
227      * @since 1.4
228      */

229     private static void initPolicy (final Policy JavaDoc p) {
230     /*
231      * A policy provider not on the bootclasspath could trigger
232      * security checks fulfilling a call to either Policy.implies
233      * or Policy.getPermissions. If this does occur the provider
234      * must be able to answer for it's own ProtectionDomain
235      * without triggering additional security checks, otherwise
236      * the policy implementation will end up in an infinite
237      * recursion.
238      *
239      * To mitigate this, the provider can collect it's own
240      * ProtectionDomain and associate a PermissionCollection while
241      * it is being installed. The currently installed policy
242      * provider (if there is one) will handle calls to
243      * Policy.implies or Policy.getPermissions during this
244      * process.
245      *
246      * This Policy superclass caches away the ProtectionDomain and
247      * statically binds permissions so that legacy Policy
248      * implementations will continue to function.
249      */

250
251     ProtectionDomain JavaDoc policyDomain = (ProtectionDomain JavaDoc)
252         AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
253             public Object JavaDoc run() {
254             return p.getClass().getProtectionDomain();
255             }
256         });
257
258     /*
259      * Collect the permissions granted to this protection domain
260      * so that the provider can be security checked while processing
261      * calls to Policy.implies or Policy.getPermissions.
262      */

263     PermissionCollection JavaDoc policyPerms = null;
264     synchronized (p) {
265        if (p.pdMapping == null) {
266            p.pdMapping = new WeakHashMap JavaDoc();
267        }
268     }
269
270     if (policyDomain.getCodeSource() != null) {
271         if (Policy.isSet()) {
272         policyPerms = policy.getPermissions(policyDomain);
273         }
274
275         if (policyPerms == null) { // assume it has all
276
policyPerms = new Permissions JavaDoc();
277         policyPerms.add(SecurityConstants.ALL_PERMISSION);
278         }
279
280         synchronized (p.pdMapping) {
281         // cache of pd to permissions
282
p.pdMapping.put(policyDomain, policyPerms);
283         }
284     }
285     return;
286     }
287     
288     /**
289      * Evaluates the global policy and returns a
290      * PermissionCollection object specifying the set of
291      * permissions allowed for code from the specified
292      * code source.
293      *
294      * @param codesource the CodeSource associated with the caller.
295      * This encapsulates the original location of the code (where the code
296      * came from) and the public key(s) of its signer.
297      *
298      * @return the set of permissions allowed for code from <i>codesource</i>
299      * according to the policy.The returned set of permissions must be
300      * a new mutable instance and it must support heterogeneous
301      * Permission types.
302      *
303      */

304     public abstract PermissionCollection JavaDoc getPermissions(CodeSource JavaDoc codesource);
305
306     /**
307      * Evaluates the global policy and returns a
308      * PermissionCollection object specifying the set of
309      * permissions allowed given the characteristics of the
310      * protection domain.
311      *
312      * @param domain the ProtectionDomain associated with the caller.
313      *
314      * @return the set of permissions allowed for the <i>domain</i>
315      * according to the policy.The returned set of permissions must be
316      * a new mutable instance and it must support heterogeneous
317      * Permission types.
318      *
319      * @see java.security.ProtectionDomain
320      * @see java.security.SecureClassLoader
321      * @since 1.4
322      */

323     public PermissionCollection JavaDoc getPermissions(ProtectionDomain JavaDoc domain) {
324     PermissionCollection JavaDoc pc = null;
325
326     if (domain == null)
327         return new Permissions JavaDoc();
328
329     if (pdMapping == null) {
330         initPolicy(this);
331     }
332
333     synchronized (pdMapping) {
334         pc = (PermissionCollection JavaDoc)pdMapping.get(domain);
335     }
336
337     if (pc != null) {
338         Permissions JavaDoc perms = new Permissions JavaDoc();
339         synchronized (pc) {
340         for (Enumeration JavaDoc e = pc.elements() ; e.hasMoreElements() ;) {
341             perms.add((Permission JavaDoc)e.nextElement());
342         }
343         }
344         return perms;
345     }
346
347     pc = getPermissions(domain.getCodeSource());
348     if (pc == null) {
349         pc = new Permissions JavaDoc();
350     }
351
352     addStaticPerms(pc, domain.getPermissions());
353     return pc;
354     }
355
356     /**
357      * add static permissions to provided permission collection
358      */

359     private void addStaticPerms(PermissionCollection JavaDoc perms,
360                 PermissionCollection JavaDoc statics) {
361     if (statics != null) {
362         synchronized (statics) {
363         Enumeration JavaDoc e = statics.elements();
364         while (e.hasMoreElements()) {
365             perms.add((Permission JavaDoc)e.nextElement());
366         }
367         }
368     }
369     }
370
371     /**
372      * Evaluates the global policy for the permissions granted to
373      * the ProtectionDomain and tests whether the permission is
374      * granted.
375      *
376      * @param domain the ProtectionDomain to test
377      * @param permission the Permission object to be tested for implication.
378      *
379      * @return true if "permission" is a proper subset of a permission
380      * granted to this ProtectionDomain.
381      *
382      * @see java.security.ProtectionDomain
383      * @since 1.4
384      */

385     public boolean implies(ProtectionDomain JavaDoc domain, Permission JavaDoc permission) {
386     PermissionCollection JavaDoc pc;
387
388     if (pdMapping == null) {
389         initPolicy(this);
390     }
391
392     synchronized (pdMapping) {
393         pc = (PermissionCollection JavaDoc)pdMapping.get(domain);
394     }
395
396     if (pc != null) {
397         return pc.implies(permission);
398     }
399     
400     pc = getPermissions(domain);
401     if (pc == null) {
402         return false;
403     }
404
405     synchronized (pdMapping) {
406         // cache it
407
pdMapping.put(domain, pc);
408     }
409     
410     return pc.implies(permission);
411     }
412
413     /**
414      * Refreshes/reloads the policy configuration. The behavior of this method
415      * depends on the implementation. For example, calling <code>refresh</code>
416      * on a file-based policy will cause the file to be re-read.
417      *
418      */

419     public abstract void refresh();
420 }
421
Popular Tags