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