KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > AccessController


1 /*
2  * @(#)AccessController.java 1.55 04/05/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7  
8 package java.security;
9
10 import sun.security.util.Debug;
11
12 /**
13  * <p> The AccessController class is used for access control operations
14  * and decisions.
15  *
16  * <p> More specifically, the AccessController class is used for
17  * three purposes:
18  *
19  * <ul>
20  * <li> to decide whether an access to a critical system
21  * resource is to be allowed or denied, based on the security policy
22  * currently in effect,<p>
23  * <li>to mark code as being "privileged", thus affecting subsequent
24  * access determinations, and<p>
25  * <li>to obtain a "snapshot" of the current calling context so
26  * access-control decisions from a different context can be made with
27  * respect to the saved context. </ul>
28  *
29  * <p> The {@link #checkPermission(Permission) checkPermission} method
30  * determines whether the access request indicated by a specified
31  * permission should be granted or denied. A sample call appears
32  * below. In this example, <code>checkPermission</code> will determine
33  * whether or not to grant "read" access to the file named "testFile" in
34  * the "/temp" directory.
35  *
36  * <pre>
37  *
38  * FilePermission perm = new FilePermission("/temp/testFile", "read");
39  * AccessController.checkPermission(perm);
40  *
41  * </pre>
42  *
43  * <p> If a requested access is allowed,
44  * <code>checkPermission</code> returns quietly. If denied, an
45  * AccessControlException is
46  * thrown. AccessControlException can also be thrown if the requested
47  * permission is of an incorrect type or contains an invalid value.
48  * Such information is given whenever possible.
49  *
50  * Suppose the current thread traversed m callers, in the order of caller 1
51  * to caller 2 to caller m. Then caller m invoked the
52  * <code>checkPermission</code> method.
53  * The <code>checkPermission </code>method determines whether access
54  * is granted or denied based on the following algorithm:
55  *
56  * <pre>
57  * i = m;
58  *
59  * while (i > 0) {
60  *
61  * if (caller i's domain does not have the permission)
62  * throw AccessControlException
63  *
64  * else if (caller i is marked as privileged) {
65  * if (a context was specified in the call to doPrivileged)
66  * context.checkPermission(permission)
67  * return;
68  * }
69  * i = i - 1;
70  * };
71  *
72  * // Next, check the context inherited when
73  * // the thread was created. Whenever a new thread is created, the
74  * // AccessControlContext at that time is
75  * // stored and associated with the new thread, as the "inherited"
76  * // context.
77  *
78  * inheritedContext.checkPermission(permission);
79  * </pre>
80  *
81  * <p> A caller can be marked as being "privileged"
82  * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below).
83  * When making access control decisions, the <code>checkPermission</code>
84  * method stops checking if it reaches a caller that
85  * was marked as "privileged" via a <code>doPrivileged</code>
86  * call without a context argument (see below for information about a
87  * context argument). If that caller's domain has the
88  * specified permission, no further checking is done and
89  * <code>checkPermission</code>
90  * returns quietly, indicating that the requested access is allowed.
91  * If that domain does not have the specified permission, an exception
92  * is thrown, as usual.
93  *
94  * <p> The normal use of the "privileged" feature is as follows. If you
95  * don't need to return a value from within the "privileged" block, do
96  * the following:
97  *
98  * <pre>
99  * somemethod() {
100  * ...normal code here...
101  * AccessController.doPrivileged(new PrivilegedAction() {
102  * public Object run() {
103  * // privileged code goes here, for example:
104  * System.loadLibrary("awt");
105  * return null; // nothing to return
106  * }
107  * });
108   * ...normal code here...
109  * }
110  * </pre>
111  *
112  * <p>
113  * PrivilegedAction is an interface with a single method, named
114  * <code>run</code>, that returns an Object.
115  * The above example shows creation of an implementation
116  * of that interface; a concrete implementation of the
117  * <code>run</code> method is supplied.
118  * When the call to <code>doPrivileged</code> is made, an
119  * instance of the PrivilegedAction implementation is passed
120  * to it. The <code>doPrivileged</code> method calls the
121  * <code>run</code> method from the PrivilegedAction
122  * implementation after enabling privileges, and returns the
123  * <code>run</code> method's return value as the
124  * <code>doPrivileged</code> return value (which is
125  * ignored in this example).
126  *
127  * <p> If you need to return a value, you can do something like the following:
128  *
129  * <pre>
130  * somemethod() {
131  * ...normal code here...
132  * String user = (String) AccessController.doPrivileged(
133  * new PrivilegedAction() {
134  * public Object run() {
135  * return System.getProperty("user.name");
136  * }
137  * }
138  * );
139  * ...normal code here...
140  * }
141  * </pre>
142  *
143  * <p>If the action performed in your <code>run</code> method could
144  * throw a "checked" exception (those listed in the <code>throws</code> clause
145  * of a method), then you need to use the
146  * <code>PrivilegedExceptionAction</code> interface instead of the
147  * <code>PrivilegedAction</code> interface:
148  *
149  * <pre>
150  * somemethod() throws FileNotFoundException {
151  * ...normal code here...
152  * try {
153  * FileInputStream fis = (FileInputStream) AccessController.doPrivileged(
154  * new PrivilegedExceptionAction() {
155  * public Object run() throws FileNotFoundException {
156  * return new FileInputStream("someFile");
157  * }
158  * }
159  * );
160  * } catch (PrivilegedActionException e) {
161  * // e.getException() should be an instance of FileNotFoundException,
162  * // as only "checked" exceptions will be "wrapped" in a
163  * // <code>PrivilegedActionException</code>.
164  * throw (FileNotFoundException) e.getException();
165  * }
166  * ...normal code here...
167  * }
168  * </pre>
169  *
170  * <p> Be *very* careful in your use of the "privileged" construct, and
171  * always remember to make the privileged code section as small as possible.
172  *
173  * <p> Note that <code>checkPermission</code> always performs security checks
174  * within the context of the currently executing thread.
175  * Sometimes a security check that should be made within a given context
176  * will actually need to be done from within a
177  * <i>different</i> context (for example, from within a worker thread).
178  * The {@link #getContext() getContext} method and
179  * AccessControlContext class are provided
180  * for this situation. The <code>getContext</code> method takes a "snapshot"
181  * of the current calling context, and places
182  * it in an AccessControlContext object, which it returns. A sample call is
183  * the following:
184  *
185  * <pre>
186  *
187  * AccessControlContext acc = AccessController.getContext()
188  *
189  * </pre>
190  *
191  * <p>
192  * AccessControlContext itself has a <code>checkPermission</code> method
193  * that makes access decisions based on the context <i>it</i> encapsulates,
194  * rather than that of the current execution thread.
195  * Code within a different context can thus call that method on the
196  * previously-saved AccessControlContext object. A sample call is the
197  * following:
198  *
199  * <pre>
200  *
201  * acc.checkPermission(permission)
202  *
203  * </pre>
204  *
205  * <p> There are also times where you don't know a priori which permissions
206  * to check the context against. In these cases you can use the
207  * doPrivileged method that takes a context:
208  *
209  * <pre>
210  * somemethod() {
211  * AccessController.doPrivileged(new PrivilegedAction() {
212  * public Object run() {
213  * // Code goes here. Any permission checks within this
214  * // run method will require that the intersection of the
215  * // callers protection domain and the snapshot's
216  * // context have the desired permission.
217  * }
218  * }, acc);
219  * ...normal code here...
220  * }
221  * </pre>
222  *
223  * @see AccessControlContext
224  *
225  * @version 1.55 04/05/05
226  * @author Li Gong
227  * @author Roland Schemers
228  */

229
230 public final class AccessController {
231
232     /**
233      * Don't allow anyone to instantiate an AccessController
234      */

235     private AccessController() { }
236
237     /**
238      * Performs the specified <code>PrivilegedAction</code> with privileges
239      * enabled. The action is performed with <i>all</i> of the permissions
240      * possessed by the caller's protection domain.
241      * <p>
242      * If the action's <code>run</code> method throws an (unchecked) exception,
243      * it will propagate through this method.
244      *
245      * @param action the action to be performed.
246      *
247      * @return the value returned by the action's <code>run</code> method.
248      *
249      * @exception NullPointerException if the action is <code>null</code>
250      *
251      * @see #doPrivileged(PrivilegedAction,AccessControlContext)
252      * @see #doPrivileged(PrivilegedExceptionAction)
253      */

254
255     public static native <T> T doPrivileged(PrivilegedAction JavaDoc<T> action);
256
257
258     /**
259      * Performs the specified <code>PrivilegedAction</code> with privileges
260      * enabled and restricted by the specified
261      * <code>AccessControlContext</code>.
262      * The action is performed with the intersection of the permissions
263      * possessed by the caller's protection domain, and those possessed
264      * by the domains represented by the specified
265      * <code>AccessControlContext</code>.
266      * <p>
267      * If the action's <code>run</code> method throws an (unchecked) exception,
268      * it will propagate through this method.
269      *
270      * @param action the action to be performed.
271      * @param context an <i>access control context</i>
272      * representing the restriction to be applied to the
273      * caller's domain's privileges before performing
274      * the specified action. If the context is
275      * <code>null</code>,
276      * then no additional restriction is applied.
277      *
278      * @return the value returned by the action's <code>run</code> method.
279      *
280      * @exception NullPointerException if the action is <code>null</code>
281      *
282      * @see #doPrivileged(PrivilegedAction)
283      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
284      */

285     public static native <T> T doPrivileged(PrivilegedAction JavaDoc<T> action,
286                         AccessControlContext JavaDoc context);
287
288     /**
289      * Performs the specified <code>PrivilegedExceptionAction</code> with
290      * privileges enabled. The action is performed with <i>all</i> of the
291      * permissions possessed by the caller's protection domain.
292      * <p>
293      * If the action's <code>run</code> method throws an <i>unchecked</i>
294      * exception, it will propagate through this method.
295      *
296      * @param action the action to be performed
297      *
298      * @return the value returned by the action's <code>run</code> method
299      *
300      * @exception PrivilegedActionException if the specified action's
301      * <code>run</code> method threw a <i>checked</i> exception
302      * @exception NullPointerException if the action is <code>null</code>
303      *
304      * @see #doPrivileged(PrivilegedAction)
305      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
306      */

307     public static native <T> T
308     doPrivileged(PrivilegedExceptionAction JavaDoc<T> action)
309     throws PrivilegedActionException JavaDoc;
310
311
312     /**
313      * Performs the specified <code>PrivilegedExceptionAction</code> with
314      * privileges enabled and restricted by the specified
315      * <code>AccessControlContext</code>. The action is performed with the
316      * intersection of the the permissions possessed by the caller's
317      * protection domain, and those possessed by the domains represented by the
318      * specified <code>AccessControlContext</code>.
319      * <p>
320      * If the action's <code>run</code> method throws an <i>unchecked</i>
321      * exception, it will propagate through this method.
322      *
323      * @param action the action to be performed
324      * @param context an <i>access control context</i>
325      * representing the restriction to be applied to the
326      * caller's domain's privileges before performing
327      * the specified action. If the context is
328      * <code>null</code>,
329      * then no additional restriction is applied.
330      *
331      * @return the value returned by the action's <code>run</code> method
332      *
333      * @exception PrivilegedActionException if the specified action's
334      * <code>run</code> method
335      * threw a <i>checked</i> exception
336      * @exception NullPointerException if the action is <code>null</code>
337      *
338      * @see #doPrivileged(PrivilegedAction)
339      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
340      */

341     public static native <T> T
342     doPrivileged(PrivilegedExceptionAction JavaDoc<T> action,
343              AccessControlContext JavaDoc context)
344     throws PrivilegedActionException JavaDoc;
345
346     /**
347      * Returns the AccessControl context. i.e., it gets
348      * the protection domains of all the callers on the stack,
349      * starting at the first class with a non-null
350      * ProtectionDomain.
351      *
352      * @return the access control context based on the current stack or
353      * null if there was only privileged system code.
354      */

355
356     private static native AccessControlContext JavaDoc getStackAccessControlContext();
357
358     /**
359      * Returns the "inherited" AccessControl context. This is the context
360      * that existed when the thread was created. Package private so
361      * AccessControlContext can use it.
362      */

363
364     static native AccessControlContext JavaDoc getInheritedAccessControlContext();
365
366     /**
367      * This method takes a "snapshot" of the current calling context, which
368      * includes the current Thread's inherited AccessControlContext,
369      * and places it in an AccessControlContext object. This context may then
370      * be checked at a later point, possibly in another thread.
371      *
372      * @see AccessControlContext
373      *
374      * @return the AccessControlContext based on the current context.
375      */

376
377     public static AccessControlContext JavaDoc getContext()
378     {
379     AccessControlContext JavaDoc acc = getStackAccessControlContext();
380     if (acc == null) {
381         // all we had was privileged system code. We don't want
382
// to return null though, so we construct a real ACC.
383
return new AccessControlContext JavaDoc(null, true);
384     } else {
385         return acc.optimize();
386     }
387     }
388
389     /**
390      * Determines whether the access request indicated by the
391      * specified permission should be allowed or denied, based on
392      * the security policy currently in effect.
393      * This method quietly returns if the access request
394      * is permitted, or throws a suitable AccessControlException otherwise.
395      *
396      * @param perm the requested permission.
397      *
398      * @exception AccessControlException if the specified permission
399      * is not permitted, based on the current security policy.
400      * @exception NullPointerException if the specified permission
401      * is <code>null</code> and is checked based on the
402      * security policy currently in effect.
403      */

404
405     public static void checkPermission(Permission JavaDoc perm)
406          throws AccessControlException JavaDoc
407     {
408     //System.err.println("checkPermission "+perm);
409
//Thread.currentThread().dumpStack();
410

411     AccessControlContext JavaDoc stack = getStackAccessControlContext();
412     // if context is null, we had privileged system code on the stack.
413
if (stack == null) {
414         Debug debug = AccessControlContext.getDebug();
415         if (debug != null) {
416         if (Debug.isOn("stack"))
417             Thread.currentThread().dumpStack();
418         if (Debug.isOn("domain")) {
419             debug.println("domain (context is null)");
420         }
421         debug.println("access allowed "+perm);
422         }
423         return;
424     }
425
426     AccessControlContext JavaDoc acc = stack.optimize();
427     acc.checkPermission(perm);
428
429     }
430 }
431
Popular Tags