History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/security/AccessController.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/security/AccessController.java+557−0
@@ -0,0 +1,557 @@
1+/*
2+ * Copyright (c) 1997, 2007, 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;
27+
28+import sun.security.util.Debug;
29+
30+/**
31+ * <p> The AccessController class is used for access control operations
32+ * and decisions.
33+ *
34+ * <p> More specifically, the AccessController class is used for
35+ * three purposes:
36+ *
37+ * <ul>
38+ * <li> to decide whether an access to a critical system
39+ * resource is to be allowed or denied, based on the security policy
40+ * currently in effect,<p>
41+ * <li>to mark code as being "privileged", thus affecting subsequent
42+ * access determinations, and<p>
43+ * <li>to obtain a "snapshot" of the current calling context so
44+ * access-control decisions from a different context can be made with
45+ * respect to the saved context. </ul>
46+ *
47+ * <p> The {@link #checkPermission(Permission) checkPermission} method
48+ * determines whether the access request indicated by a specified
49+ * permission should be granted or denied. A sample call appears
50+ * below. In this example, <code>checkPermission</code> will determine
51+ * whether or not to grant "read" access to the file named "testFile" in
52+ * the "/temp" directory.
53+ *
54+ * <pre>
55+ *
56+ * FilePermission perm = new FilePermission("/temp/testFile", "read");
57+ * AccessController.checkPermission(perm);
58+ *
59+ * </pre>
60+ *
61+ * <p> If a requested access is allowed,
62+ * <code>checkPermission</code> returns quietly. If denied, an
63+ * AccessControlException is
64+ * thrown. AccessControlException can also be thrown if the requested
65+ * permission is of an incorrect type or contains an invalid value.
66+ * Such information is given whenever possible.
67+ *
68+ * Suppose the current thread traversed m callers, in the order of caller 1
69+ * to caller 2 to caller m. Then caller m invoked the
70+ * <code>checkPermission</code> method.
71+ * The <code>checkPermission </code>method determines whether access
72+ * is granted or denied based on the following algorithm:
73+ *
74+ * <pre> {@code
75+ * for (int i = m; i > 0; i--) {
76+ *
77+ * if (caller i's domain does not have the permission)
78+ * throw AccessControlException
79+ *
80+ * else if (caller i is marked as privileged) {
81+ * if (a context was specified in the call to doPrivileged)
82+ * context.checkPermission(permission)
83+ * return;
84+ * }
85+ * };
86+ *
87+ * // Next, check the context inherited when the thread was created.
88+ * // Whenever a new thread is created, the AccessControlContext at
89+ * // that time is stored and associated with the new thread, as the
90+ * // "inherited" context.
91+ *
92+ * inheritedContext.checkPermission(permission);
93+ * }</pre>
94+ *
95+ * <p> A caller can be marked as being "privileged"
96+ * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below).
97+ * When making access control decisions, the <code>checkPermission</code>
98+ * method stops checking if it reaches a caller that
99+ * was marked as "privileged" via a <code>doPrivileged</code>
100+ * call without a context argument (see below for information about a
101+ * context argument). If that caller's domain has the
102+ * specified permission, no further checking is done and
103+ * <code>checkPermission</code>
104+ * returns quietly, indicating that the requested access is allowed.
105+ * If that domain does not have the specified permission, an exception
106+ * is thrown, as usual.
107+ *
108+ * <p> The normal use of the "privileged" feature is as follows. If you
109+ * don't need to return a value from within the "privileged" block, do
110+ * the following:
111+ *
112+ * <pre> {@code
113+ * somemethod() {
114+ * ...normal code here...
115+ * AccessController.doPrivileged(new PrivilegedAction<Void>() {
116+ * public Void run() {
117+ * // privileged code goes here, for example:
118+ * System.loadLibrary("awt");
119+ * return null; // nothing to return
120+ * }
121+ * });
122+ * ...normal code here...
123+ * }}</pre>
124+ *
125+ * <p>
126+ * PrivilegedAction is an interface with a single method, named
127+ * <code>run</code>.
128+ * The above example shows creation of an implementation
129+ * of that interface; a concrete implementation of the
130+ * <code>run</code> method is supplied.
131+ * When the call to <code>doPrivileged</code> is made, an
132+ * instance of the PrivilegedAction implementation is passed
133+ * to it. The <code>doPrivileged</code> method calls the
134+ * <code>run</code> method from the PrivilegedAction
135+ * implementation after enabling privileges, and returns the
136+ * <code>run</code> method's return value as the
137+ * <code>doPrivileged</code> return value (which is
138+ * ignored in this example).
139+ *
140+ * <p> If you need to return a value, you can do something like the following:
141+ *
142+ * <pre> {@code
143+ * somemethod() {
144+ * ...normal code here...
145+ * String user = AccessController.doPrivileged(
146+ * new PrivilegedAction<String>() {
147+ * public String run() {
148+ * return System.getProperty("user.name");
149+ * }
150+ * });
151+ * ...normal code here...
152+ * }}</pre>
153+ *
154+ * <p>If the action performed in your <code>run</code> method could
155+ * throw a "checked" exception (those listed in the <code>throws</code> clause
156+ * of a method), then you need to use the
157+ * <code>PrivilegedExceptionAction</code> interface instead of the
158+ * <code>PrivilegedAction</code> interface:
159+ *
160+ * <pre> {@code
161+ * somemethod() throws FileNotFoundException {
162+ * ...normal code here...
163+ * try {
164+ * FileInputStream fis = AccessController.doPrivileged(
165+ * new PrivilegedExceptionAction<FileInputStream>() {
166+ * public FileInputStream run() throws FileNotFoundException {
167+ * return new FileInputStream("someFile");
168+ * }
169+ * });
170+ * } catch (PrivilegedActionException e) {
171+ * // e.getException() should be an instance of FileNotFoundException,
172+ * // as only "checked" exceptions will be "wrapped" in a
173+ * // PrivilegedActionException.
174+ * throw (FileNotFoundException) e.getException();
175+ * }
176+ * ...normal code here...
177+ * }}</pre>
178+ *
179+ * <p> Be *very* careful in your use of the "privileged" construct, and
180+ * always remember to make the privileged code section as small as possible.
181+ *
182+ * <p> Note that <code>checkPermission</code> always performs security checks
183+ * within the context of the currently executing thread.
184+ * Sometimes a security check that should be made within a given context
185+ * will actually need to be done from within a
186+ * <i>different</i> context (for example, from within a worker thread).
187+ * The {@link #getContext() getContext} method and
188+ * AccessControlContext class are provided
189+ * for this situation. The <code>getContext</code> method takes a "snapshot"
190+ * of the current calling context, and places
191+ * it in an AccessControlContext object, which it returns. A sample call is
192+ * the following:
193+ *
194+ * <pre>
195+ *
196+ * AccessControlContext acc = AccessController.getContext()
197+ *
198+ * </pre>
199+ *
200+ * <p>
201+ * AccessControlContext itself has a <code>checkPermission</code> method
202+ * that makes access decisions based on the context <i>it</i> encapsulates,
203+ * rather than that of the current execution thread.
204+ * Code within a different context can thus call that method on the
205+ * previously-saved AccessControlContext object. A sample call is the
206+ * following:
207+ *
208+ * <pre>
209+ *
210+ * acc.checkPermission(permission)
211+ *
212+ * </pre>
213+ *
214+ * <p> There are also times where you don't know a priori which permissions
215+ * to check the context against. In these cases you can use the
216+ * doPrivileged method that takes a context:
217+ *
218+ * <pre> {@code
219+ * somemethod() {
220+ * AccessController.doPrivileged(new PrivilegedAction<Object>() {
221+ * public Object run() {
222+ * // Code goes here. Any permission checks within this
223+ * // run method will require that the intersection of the
224+ * // callers protection domain and the snapshot's
225+ * // context have the desired permission.
226+ * }
227+ * }, acc);
228+ * ...normal code here...
229+ * }}</pre>
230+ *
231+ * @see AccessControlContext
232+ *
233+ * @author Li Gong
234+ * @author Roland Schemers
235+ */
236+
237+public final class AccessController {
238+
239+ /**
240+ * Don't allow anyone to instantiate an AccessController
241+ */
242+ private AccessController() { }
243+
244+ /**
245+ * Performs the specified <code>PrivilegedAction</code> with privileges
246+ * enabled. The action is performed with <i>all</i> of the permissions
247+ * possessed by the caller's protection domain.
248+ *
249+ * <p> If the action's <code>run</code> method throws an (unchecked)
250+ * exception, it will propagate through this method.
251+ *
252+ * <p> Note that any DomainCombiner associated with the current
253+ * AccessControlContext will be ignored while the action is performed.
254+ *
255+ * @param action the action to be performed.
256+ *
257+ * @return the value returned by the action's <code>run</code> method.
258+ *
259+ * @exception NullPointerException if the action is <code>null</code>
260+ *
261+ * @see #doPrivileged(PrivilegedAction,AccessControlContext)
262+ * @see #doPrivileged(PrivilegedExceptionAction)
263+ * @see #doPrivilegedWithCombiner(PrivilegedAction)
264+ * @see java.security.DomainCombiner
265+ */
266+
267+ public static native <T> T doPrivileged(PrivilegedAction<T> action);
268+
269+ /**
270+ * Performs the specified <code>PrivilegedAction</code> with privileges
271+ * enabled. The action is performed with <i>all</i> of the permissions
272+ * possessed by the caller's protection domain.
273+ *
274+ * <p> If the action's <code>run</code> method throws an (unchecked)
275+ * exception, it will propagate through this method.
276+ *
277+ * <p> This method preserves the current AccessControlContext's
278+ * DomainCombiner (which may be null) while the action is performed.
279+ *
280+ * @param action the action to be performed.
281+ *
282+ * @return the value returned by the action's <code>run</code> method.
283+ *
284+ * @exception NullPointerException if the action is <code>null</code>
285+ *
286+ * @see #doPrivileged(PrivilegedAction)
287+ * @see java.security.DomainCombiner
288+ *
289+ * @since 1.6
290+ */
291+ public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
292+
293+ DomainCombiner dc = null;
294+ AccessControlContext acc = getStackAccessControlContext();
295+ if (acc == null || (dc = acc.getAssignedCombiner()) == null) {
296+ return AccessController.doPrivileged(action);
297+ }
298+ return AccessController.doPrivileged(action, preserveCombiner(dc));
299+ }
300+
301+
302+ /**
303+ * Performs the specified <code>PrivilegedAction</code> with privileges
304+ * enabled and restricted by the specified
305+ * <code>AccessControlContext</code>.
306+ * The action is performed with the intersection of the permissions
307+ * possessed by the caller's protection domain, and those possessed
308+ * by the domains represented by the specified
309+ * <code>AccessControlContext</code>.
310+ * <p>
311+ * If the action's <code>run</code> method throws an (unchecked) exception,
312+ * it will propagate through this method.
313+ *
314+ * @param action the action to be performed.
315+ * @param context an <i>access control context</i>
316+ * representing the restriction to be applied to the
317+ * caller's domain's privileges before performing
318+ * the specified action. If the context is
319+ * <code>null</code>,
320+ * then no additional restriction is applied.
321+ *
322+ * @return the value returned by the action's <code>run</code> method.
323+ *
324+ * @exception NullPointerException if the action is <code>null</code>
325+ *
326+ * @see #doPrivileged(PrivilegedAction)
327+ * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
328+ */
329+ public static native <T> T doPrivileged(PrivilegedAction<T> action,
330+ AccessControlContext context);
331+
332+ /**
333+ * Performs the specified <code>PrivilegedExceptionAction</code> with
334+ * privileges enabled. The action is performed with <i>all</i> of the
335+ * permissions possessed by the caller's protection domain.
336+ *
337+ * <p> If the action's <code>run</code> method throws an <i>unchecked</i>
338+ * exception, it will propagate through this method.
339+ *
340+ * <p> Note that any DomainCombiner associated with the current
341+ * AccessControlContext will be ignored while the action is performed.
342+ *
343+ * @param action the action to be performed
344+ *
345+ * @return the value returned by the action's <code>run</code> method
346+ *
347+ * @exception PrivilegedActionException if the specified action's
348+ * <code>run</code> method threw a <i>checked</i> exception
349+ * @exception NullPointerException if the action is <code>null</code>
350+ *
351+ * @see #doPrivileged(PrivilegedAction)
352+ * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
353+ * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
354+ * @see java.security.DomainCombiner
355+ */
356+ public static native <T> T
357+ doPrivileged(PrivilegedExceptionAction<T> action)
358+ throws PrivilegedActionException;
359+
360+
361+ /**
362+ * Performs the specified <code>PrivilegedExceptionAction</code> with
363+ * privileges enabled. The action is performed with <i>all</i> of the
364+ * permissions possessed by the caller's protection domain.
365+ *
366+ * <p> If the action's <code>run</code> method throws an <i>unchecked</i>
367+ * exception, it will propagate through this method.
368+ *
369+ * <p> This method preserves the current AccessControlContext's
370+ * DomainCombiner (which may be null) while the action is performed.
371+ *
372+ * @param action the action to be performed.
373+ *
374+ * @return the value returned by the action's <code>run</code> method
375+ *
376+ * @exception PrivilegedActionException if the specified action's
377+ * <code>run</code> method threw a <i>checked</i> exception
378+ * @exception NullPointerException if the action is <code>null</code>
379+ *
380+ * @see #doPrivileged(PrivilegedAction)
381+ * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
382+ * @see java.security.DomainCombiner
383+ *
384+ * @since 1.6
385+ */
386+ public static <T> T doPrivilegedWithCombiner
387+ (PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
388+
389+ DomainCombiner dc = null;
390+ AccessControlContext acc = getStackAccessControlContext();
391+ if (acc == null || (dc = acc.getAssignedCombiner()) == null) {
392+ return AccessController.doPrivileged(action);
393+ }
394+ return AccessController.doPrivileged(action, preserveCombiner(dc));
395+ }
396+
397+ /**
398+ * preserve the combiner across the doPrivileged call
399+ */
400+ private static AccessControlContext preserveCombiner
401+ (DomainCombiner combiner) {
402+
403+ /**
404+ * callerClass[0] = Reflection.getCallerClass
405+ * callerClass[1] = AccessController.preserveCombiner
406+ * callerClass[2] = AccessController.doPrivileged
407+ * callerClass[3] = caller
408+ */
409+ final Class callerClass = sun.reflect.Reflection.getCallerClass(3);
410+ ProtectionDomain callerPd = doPrivileged
411+ (new PrivilegedAction<ProtectionDomain>() {
412+ public ProtectionDomain run() {
413+ return callerClass.getProtectionDomain();
414+ }
415+ });
416+
417+ // perform 'combine' on the caller of doPrivileged,
418+ // even if the caller is from the bootclasspath
419+ ProtectionDomain[] pds = new ProtectionDomain[] {callerPd};
420+ return new AccessControlContext(combiner.combine(pds, null), combiner);
421+ }
422+
423+
424+ /**
425+ * Performs the specified <code>PrivilegedExceptionAction</code> with
426+ * privileges enabled and restricted by the specified
427+ * <code>AccessControlContext</code>. The action is performed with the
428+ * intersection of the permissions possessed by the caller's
429+ * protection domain, and those possessed by the domains represented by the
430+ * specified <code>AccessControlContext</code>.
431+ * <p>
432+ * If the action's <code>run</code> method throws an <i>unchecked</i>
433+ * exception, it will propagate through this method.
434+ *
435+ * @param action the action to be performed
436+ * @param context an <i>access control context</i>
437+ * representing the restriction to be applied to the
438+ * caller's domain's privileges before performing
439+ * the specified action. If the context is
440+ * <code>null</code>,
441+ * then no additional restriction is applied.
442+ *
443+ * @return the value returned by the action's <code>run</code> method
444+ *
445+ * @exception PrivilegedActionException if the specified action's
446+ * <code>run</code> method
447+ * threw a <i>checked</i> exception
448+ * @exception NullPointerException if the action is <code>null</code>
449+ *
450+ * @see #doPrivileged(PrivilegedAction)
451+ * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
452+ */
453+ public static native <T> T
454+ doPrivileged(PrivilegedExceptionAction<T> action,
455+ AccessControlContext context)
456+ throws PrivilegedActionException;
457+
458+ /**
459+ * Returns the AccessControl context. i.e., it gets
460+ * the protection domains of all the callers on the stack,
461+ * starting at the first class with a non-null
462+ * ProtectionDomain.
463+ *
464+ * @return the access control context based on the current stack or
465+ * null if there was only privileged system code.
466+ */
467+
468+ private static native AccessControlContext getStackAccessControlContext();
469+
470+ /**
471+ * Returns the "inherited" AccessControl context. This is the context
472+ * that existed when the thread was created. Package private so
473+ * AccessControlContext can use it.
474+ */
475+
476+ static native AccessControlContext getInheritedAccessControlContext();
477+
478+ /**
479+ * This method takes a "snapshot" of the current calling context, which
480+ * includes the current Thread's inherited AccessControlContext,
481+ * and places it in an AccessControlContext object. This context may then
482+ * be checked at a later point, possibly in another thread.
483+ *
484+ * @see AccessControlContext
485+ *
486+ * @return the AccessControlContext based on the current context.
487+ */
488+
489+ public static AccessControlContext getContext()
490+ {
491+ AccessControlContext acc = getStackAccessControlContext();
492+ if (acc == null) {
493+ // all we had was privileged system code. We don't want
494+ // to return null though, so we construct a real ACC.
495+ return new AccessControlContext(null, true);
496+ } else {
497+ return acc.optimize();
498+ }
499+ }
500+
501+ /**
502+ * Determines whether the access request indicated by the
503+ * specified permission should be allowed or denied, based on
504+ * the current AccessControlContext and security policy.
505+ * This method quietly returns if the access request
506+ * is permitted, or throws an AccessControlException otherwise. The
507+ * getPermission method of the AccessControlException returns the
508+ * <code>perm</code> Permission object instance.
509+ *
510+ * @param perm the requested permission.
511+ *
512+ * @exception AccessControlException if the specified permission
513+ * is not permitted, based on the current security policy.
514+ * @exception NullPointerException if the specified permission
515+ * is <code>null</code> and is checked based on the
516+ * security policy currently in effect.
517+ */
518+
519+ public static void checkPermission(Permission perm)
520+ throws AccessControlException
521+ {
522+ //System.err.println("checkPermission "+perm);
523+ //Thread.currentThread().dumpStack();
524+
525+ if (perm == null) {
526+ throw new NullPointerException("permission can't be null");
527+ }
528+
529+ AccessControlContext stack = getStackAccessControlContext();
530+ // if context is null, we had privileged system code on the stack.
531+ if (stack == null) {
532+ Debug debug = AccessControlContext.getDebug();
533+ boolean dumpDebug = false;
534+ if (debug != null) {
535+ dumpDebug = !Debug.isOn("codebase=");
536+ dumpDebug &= !Debug.isOn("permission=") ||
537+ Debug.isOn("permission=" + perm.getClass().getCanonicalName());
538+ }
539+
540+ if (dumpDebug && Debug.isOn("stack")) {
541+ Thread.currentThread().dumpStack();
542+ }
543+
544+ if (dumpDebug && Debug.isOn("domain")) {
545+ debug.println("domain (context is null)");
546+ }
547+
548+ if (dumpDebug) {
549+ debug.println("access allowed "+perm);
550+ }
551+ return;
552+ }
553+
554+ AccessControlContext acc = stack.optimize();
555+ acc.checkPermission(perm);
556+ }
557+}