1. /*
  2. * @(#)AccessController.java 1.46 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.security;
  8. import sun.security.util.Debug;
  9. /**
  10. * <p> The AccessController class is used for three purposes:
  11. *
  12. * <ul>
  13. * <li> to decide whether an access to a critical system
  14. * resource is to be allowed or denied, based on the security policy
  15. * currently in effect,<p>
  16. * <li>to mark code as being "privileged", thus affecting subsequent
  17. * access determinations, and<p>
  18. * <li>to obtain a "snapshot" of the current calling context so
  19. * access-control decisions from a different context can be made with
  20. * respect to the saved context. </ul>
  21. *
  22. * <p> The {@link #checkPermission(Permission) checkPermission} method
  23. * determines whether the access request indicated by a specified
  24. * permission should be granted or denied. A sample call appears
  25. * below. In this example, <code>checkPermission</code> will determine
  26. * whether or not to grant "read" access to the file named "testFile" in
  27. * the "/temp" directory.
  28. *
  29. * <pre>
  30. *
  31. * FilePermission perm = new FilePermission("/temp/testFile", "read");
  32. * AccessController.checkPermission(perm);
  33. *
  34. * </pre>
  35. *
  36. * <p> If a requested access is allowed,
  37. * <code>checkPermission</code> returns quietly. If denied, an
  38. * AccessControlException is
  39. * thrown. AccessControlException can also be thrown if the requested
  40. * permission is of an incorrect type or contains an invalid value.
  41. * Such information is given whenever possible.
  42. *
  43. * Suppose the current thread traversed m callers, in the order of caller 1
  44. * to caller 2 to caller m. Then caller m invoked the
  45. * <code>checkPermission</code> method.
  46. * The <code>checkPermission </code>method determines whether access
  47. * is granted or denied based on the following algorithm:
  48. *
  49. * <pre>
  50. * i = m;
  51. *
  52. * while (i > 0) {
  53. *
  54. * if (caller i's domain does not have the permission)
  55. * throw AccessControlException
  56. *
  57. * else if (caller i is marked as privileged) {
  58. * if (a context was specified in the call to doPrivileged)
  59. * context.checkPermission(permission)
  60. * return;
  61. * }
  62. * i = i - 1;
  63. * };
  64. *
  65. * // Next, check the context inherited when
  66. * // the thread was created. Whenever a new thread is created, the
  67. * // AccessControlContext at that time is
  68. * // stored and associated with the new thread, as the "inherited"
  69. * // context.
  70. *
  71. * inheritedContext.checkPermission(permission);
  72. * </pre>
  73. *
  74. * <p> A caller can be marked as being "privileged"
  75. * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below).
  76. * When making access control decisions, the <code>checkPermission</code>
  77. * method stops checking if it reaches a caller that
  78. * was marked as "privileged" via a <code>doPrivileged</code>
  79. * call without a context argument (see below for information about a
  80. * context argument). If that caller's domain has the
  81. * specified permission, no further checking is done and
  82. * <code>checkPermission</code>
  83. * returns quietly, indicating that the requested access is allowed.
  84. * If that domain does not have the specified permission, an exception
  85. * is thrown, as usual.
  86. *
  87. * <p> The normal use of the "privileged" feature is as follows. If you
  88. * don't need to return a value from within the "privileged" block, do
  89. * the following:
  90. *
  91. * <pre>
  92. * somemethod() {
  93. * ...normal code here...
  94. * AccessController.doPrivileged(new PrivilegedAction() {
  95. * public Object run() {
  96. * // privileged code goes here, for example:
  97. * System.loadLibrary("awt");
  98. * return null; // nothing to return
  99. * }
  100. * });
  101. * ...normal code here...
  102. * }
  103. * </pre>
  104. *
  105. * <p>
  106. * PrivilegedAction is an interface with a single method, named
  107. * <code>run</code>, that returns an Object.
  108. * The above example shows creation of an implementation
  109. * of that interface; a concrete implementation of the
  110. * <code>run</code> method is supplied.
  111. * When the call to <code>doPrivileged</code> is made, an
  112. * instance of the PrivilegedAction implementation is passed
  113. * to it. The <code>doPrivileged</code> method calls the
  114. * <code>run</code> method from the PrivilegedAction
  115. * implementation after enabling privileges, and returns the
  116. * <code>run</code> method's return value as the
  117. * <code>doPrivileged</code> return value (which is
  118. * ignored in this example).
  119. *
  120. * <p> If you need to return a value, you can do something like the following:
  121. *
  122. * <pre>
  123. * somemethod() {
  124. * ...normal code here...
  125. * String user = (String) AccessController.doPrivileged(
  126. * new PrivilegedAction() {
  127. * public Object run() {
  128. * return System.getProperty("user.name");
  129. * }
  130. * }
  131. * );
  132. * ...normal code here...
  133. * }
  134. * </pre>
  135. *
  136. * <p>If the action performed in your <code>run</code> method could
  137. * throw a "checked" exception (those listed in the <code>throws</code> clause
  138. * of a method), then you need to use the
  139. * <code>PrivilegedExceptionAction</code> interface instead of the
  140. * <code>PrivilegedAction</code> interface:
  141. *
  142. * <pre>
  143. * somemethod() throws FileNotFoundException {
  144. * ...normal code here...
  145. * try {
  146. * FileInputStream fis = (FileInputStream) AccessController.doPrivileged(
  147. * new PrivilegedExceptionAction() {
  148. * public Object run() throws FileNotFoundException {
  149. * return new FileInputStream("someFile");
  150. * }
  151. * }
  152. * );
  153. * } catch (PrivilegedActionException e) {
  154. * // e.getException() should be an instance of FileNotFoundException,
  155. * // as only "checked" exceptions will be "wrapped" in a
  156. * // <code>PrivilegedActionException</code>.
  157. * throw (FileNotFoundException) e.getException();
  158. * }
  159. * ...normal code here...
  160. * }
  161. * </pre>
  162. *
  163. * <p> Be *very* careful in your use of the "privileged" construct, and
  164. * always remember to make the privileged code section as small as possible.
  165. *
  166. * <p> Note that <code>checkPermission</code> always performs security checks
  167. * within the context of the currently executing thread.
  168. * Sometimes a security check that should be made within a given context
  169. * will actually need to be done from within a
  170. * <i>different</i> context (for example, from within a worker thread).
  171. * The {@link #getContext() getContext} method and
  172. * AccessControlContext class are provided
  173. * for this situation. The <code>getContext</code> method takes a "snapshot"
  174. * of the current calling context, and places
  175. * it in an AccessControlContext object, which it returns. A sample call is
  176. * the following:
  177. *
  178. * <pre>
  179. *
  180. * AccessControlContext acc = AccessController.getContext()
  181. *
  182. * </pre>
  183. *
  184. * <p>
  185. * AccessControlContext itself has a <code>checkPermission</code> method
  186. * that makes access decisions based on the context <i>it</i> encapsulates,
  187. * rather than that of the current execution thread.
  188. * Code within a different context can thus call that method on the
  189. * previously-saved AccessControlContext object. A sample call is the
  190. * following:
  191. *
  192. * <pre>
  193. *
  194. * acc.checkPermission(permission)
  195. *
  196. * </pre>
  197. *
  198. * <p> There are also times where you don't know a priori which permissions
  199. * to check the context against. In these cases you can use the
  200. * doPrivileged method that takes a context:
  201. *
  202. * <pre>
  203. * somemethod() {
  204. * AccessController.doPrivileged(new PrivilegedAction() {
  205. * public Object run() {
  206. * // Code goes here. Any permission checks from this
  207. * // point forward require both the current context and
  208. * // the snapshot's context to have the desired permission.
  209. * }
  210. * }, acc);
  211. * ...normal code here...
  212. * }
  213. * </pre>
  214. *
  215. * @see AccessControlContext
  216. *
  217. * @version 1.46 01/11/29
  218. * @author Li Gong
  219. * @author Roland Schemers
  220. */
  221. public final class AccessController {
  222. /**
  223. * Don't allow anyone to instantiate an AccessController
  224. */
  225. private AccessController() { }
  226. /**
  227. * Performs the specified <code>PrivilegedAction</code> with privileges
  228. * enabled. The action is performed with <i>all</i> of the permissions
  229. * possessed by the caller's protection domain.
  230. * <p>
  231. * If the action's <code>run</code> method throws an (unchecked) exception,
  232. * it will propagate through this method.
  233. *
  234. * @param action the action to be performed.
  235. * @return the value returned by the action's <code>run</code> method.
  236. * @see #doPrivileged(PrivilegedAction,AccessControlContext)
  237. * @see #doPrivileged(PrivilegedExceptionAction)
  238. */
  239. public static native Object doPrivileged(PrivilegedAction action);
  240. /**
  241. * Performs the specified <code>PrivilegedAction</code> with privileges
  242. * enabled and restricted by the specified <code>AccessControlContext</code>.
  243. * The action is performed with the intersection of the permissions
  244. * possessed by the caller's protection domain, and those possessed
  245. * by the domains represented by the specified
  246. * <code>AccessControlContext</code>.
  247. * <p>
  248. * If the action's <code>run</code> method throws an (unchecked) exception,
  249. * it will propagate through this method.
  250. *
  251. * @param action the action to be performed.
  252. * @param context an <i>access control context</i> representing the
  253. * restriction to be applied to the caller's domain's
  254. * privileges before performing the specified action.
  255. * @return the value returned by the action's <code>run</code> method.
  256. * @see #doPrivileged(PrivilegedAction)
  257. * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  258. */
  259. public static native Object doPrivileged(PrivilegedAction action,
  260. AccessControlContext context);
  261. /**
  262. * Performs the specified <code>PrivilegedExceptionAction</code> with
  263. * privileges enabled. The action is performed with <i>all</i> of the
  264. * permissions possessed by the caller's protection domain.
  265. * <p>
  266. * If the action's <code>run</code> method throws an <i>unchecked</i>
  267. * exception, it will propagate through this method.
  268. *
  269. * @param action the action to be performed.
  270. * @return the value returned by the action's <code>run</code> method.
  271. * @throws PrivilgedActionException the specified action's
  272. * <code>run</code> method threw a <i>checked</i> exception.
  273. * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  274. * @see #doPrivileged(PrivilegedAction)
  275. */
  276. public static native Object doPrivileged(PrivilegedExceptionAction action)
  277. throws PrivilegedActionException;
  278. /**
  279. * Performs the specified <code>PrivilegedExceptionAction</code> with
  280. * privileges enabled and restricted by the specified
  281. * <code>AccessControlContext</code>. The action is performed with the
  282. * intersection of the the permissions possessed by the caller's
  283. * protection domain, and those possessed by the domains represented by the
  284. * specified <code>AccessControlContext</code>.
  285. * <p>
  286. * If the action's <code>run</code> method throws an <i>unchecked</i>
  287. * exception, it will propagate through this method.
  288. *
  289. * @param action the action to be performed.
  290. * @param context an <i>access control context</i> representing the
  291. * restriction to be applied to the caller's domain's
  292. * privileges before performing the specified action.
  293. * @return the value returned by the action's <code>run</code> method.
  294. * @throws PrivilegedActionException the specified action's
  295. * <code>run</code> method
  296. * threw a <i>checked</i> exception.
  297. * @see #doPrivileged(PrivilegedAction)
  298. * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  299. */
  300. public static native Object doPrivileged(PrivilegedExceptionAction action,
  301. AccessControlContext context)
  302. throws PrivilegedActionException;
  303. /**
  304. * Returns the AccessControl context. i.e., it gets
  305. * the protection domains of all the callers on the stack,
  306. * starting at the first class with a non-null
  307. * ProtectionDomain.
  308. *
  309. * @return the access control context based on the current stack or
  310. * null if there was only privileged system code.
  311. *
  312. *
  313. */
  314. private static native AccessControlContext getStackAccessControlContext();
  315. /**
  316. * Returns the "inherited" AccessControl context. This is the context
  317. * that existed when the thread was created. Package private so
  318. * AccessControlContext can use it.
  319. */
  320. static native AccessControlContext getInheritedAccessControlContext();
  321. /**
  322. * This method takes a "snapshot" of the current calling context, which
  323. * includes the current Thread's inherited AccessControlContext,
  324. * and places it in an AccessControlContext object. This context may then
  325. * be checked at a later point, possibly in another thread.
  326. *
  327. * @see AccessControlContext
  328. *
  329. * @return the AccessControlContext based on the current context.
  330. */
  331. public static AccessControlContext getContext()
  332. {
  333. AccessControlContext acc = getStackAccessControlContext();
  334. if (acc == null) {
  335. // all we had was privileged system code. We don't want
  336. // to return null though, so we construct a real ACC.
  337. return new AccessControlContext(null, true);
  338. } else {
  339. return acc.optimize();
  340. }
  341. }
  342. /**
  343. * Determines whether the access request indicated by the
  344. * specified permission should be allowed or denied, based on
  345. * the security policy currently in effect.
  346. * This method quietly returns if the access request
  347. * is permitted, or throws a suitable AccessControlException otherwise.
  348. *
  349. * @param perm the requested permission.
  350. *
  351. * @exception AccessControlException if the specified permission
  352. * is not permitted, based on the current security policy.
  353. */
  354. public static void checkPermission(Permission perm)
  355. throws AccessControlException
  356. {
  357. //System.err.println("checkPermission "+perm);
  358. //Thread.currentThread().dumpStack();
  359. AccessControlContext stack = getStackAccessControlContext();
  360. // if context is null, we had privileged system code on the stack.
  361. if (stack == null) {
  362. Debug debug = AccessControlContext.getDebug();
  363. if (debug != null) {
  364. if (Debug.isOn("stack"))
  365. Thread.currentThread().dumpStack();
  366. if (Debug.isOn("domain")) {
  367. debug.println("domain (context is null)");
  368. }
  369. debug.println("access allowed "+perm);
  370. }
  371. return;
  372. }
  373. AccessControlContext acc = stack.optimize();
  374. acc.checkPermission(perm);
  375. }
  376. }