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