32 /** 33 * <p> The AccessController class is used for access control operations 34 * and decisions. 35 * 36 * <p> More specifically, the AccessController class is used for 37 * three purposes: 38 * 39 * <ul> 40 * <li> to decide whether an access to a critical system 41 * resource is to be allowed or denied, based on the security policy 42 * currently in effect,<p> 43 * <li>to mark code as being "privileged", thus affecting subsequent 44 * access determinations, and<p> 45 * <li>to obtain a "snapshot" of the current calling context so 46 * access-control decisions from a different context can be made with 47 * respect to the saved context. </ul> 48 * 49 * <p> The {@link #checkPermission(Permission) checkPermission} method 50 * determines whether the access request indicated by a specified 51 * permission should be granted or denied. A sample call appears 52 * below. In this example, <code>checkPermission</code> will determine 53 * whether or not to grant "read" access to the file named "testFile" in 54 * the "/temp" directory. 55 * 56 * <pre> 57 * 58 * FilePermission perm = new FilePermission("/temp/testFile", "read"); 59 * AccessController.checkPermission(perm); 60 * 61 * </pre> 62 * 63 * <p> If a requested access is allowed, 64 * <code>checkPermission</code> returns quietly. If denied, an 65 * AccessControlException is 66 * thrown. AccessControlException can also be thrown if the requested 67 * permission is of an incorrect type or contains an invalid value. 68 * Such information is given whenever possible. 69 * 70 * Suppose the current thread traversed m callers, in the order of caller 1 71 * to caller 2 to caller m. Then caller m invoked the 72 * <code>checkPermission</code> method. 73 * The <code>checkPermission </code>method determines whether access 74 * is granted or denied based on the following algorithm: 75 * 76 * <pre> {@code 77 * for (int i = m; i > 0; i--) { 78 * 79 * if (caller i's domain does not have the permission) 80 * throw AccessControlException 81 * 82 * else if (caller i is marked as privileged) { 83 * if (a context was specified in the call to doPrivileged) 84 * context.checkPermission(permission) 85 * if (limited permissions were specified in the call to doPrivileged) { 86 * for (each limited permission) { 87 * if (the limited permission implies the requested permission) 88 * return; 89 * } 90 * } else 91 * return; 92 * } 93 * } 94 * 95 * // Next, check the context inherited when the thread was created. 96 * // Whenever a new thread is created, the AccessControlContext at 97 * // that time is stored and associated with the new thread, as the 98 * // "inherited" context. 99 * 100 * inheritedContext.checkPermission(permission); 101 * }</pre> 102 * 103 * <p> A caller can be marked as being "privileged" 104 * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below). 105 * When making access control decisions, the <code>checkPermission</code> 106 * method stops checking if it reaches a caller that 107 * was marked as "privileged" via a <code>doPrivileged</code> 108 * call without a context argument (see below for information about a 109 * context argument). If that caller's domain has the 110 * specified permission and at least one limiting permission argument (if any) 111 * implies the requested permission, no further checking is done and 112 * <code>checkPermission</code> 113 * returns quietly, indicating that the requested access is allowed. 114 * If that domain does not have the specified permission, an exception 115 * is thrown, as usual. If the caller's domain had the specified permission 116 * but it was not implied by any limiting permission arguments given in the call 117 * to <code>doPrivileged</code> then the permission checking continues 118 * until there are no more callers or another <code>doPrivileged</code> 119 * call matches the requested permission and returns normally. 120 * 121 * <p> The normal use of the "privileged" feature is as follows. If you 122 * don't need to return a value from within the "privileged" block, do 123 * the following: 124 * 125 * <pre> {@code 126 * somemethod() { 127 * ...normal code here... 128 * AccessController.doPrivileged(new PrivilegedAction<Void>() { 129 * public Void run() { 130 * // privileged code goes here, for example: 131 * System.loadLibrary("awt"); 132 * return null; // nothing to return 133 * } 134 * }); 135 * ...normal code here... 136 * }}</pre> 137 * 138 * <p> 139 * PrivilegedAction is an interface with a single method, named 140 * <code>run</code>. 141 * The above example shows creation of an implementation 142 * of that interface; a concrete implementation of the 143 * <code>run</code> method is supplied. 144 * When the call to <code>doPrivileged</code> is made, an 145 * instance of the PrivilegedAction implementation is passed 146 * to it. The <code>doPrivileged</code> method calls the 147 * <code>run</code> method from the PrivilegedAction 148 * implementation after enabling privileges, and returns the 149 * <code>run</code> method's return value as the 150 * <code>doPrivileged</code> return value (which is 151 * ignored in this example). 152 * 153 * <p> If you need to return a value, you can do something like the following: 154 * 155 * <pre> {@code 156 * somemethod() { 157 * ...normal code here... 158 * String user = AccessController.doPrivileged( 159 * new PrivilegedAction<String>() { 160 * public String run() { 161 * return System.getProperty("user.name"); 162 * } 163 * }); 164 * ...normal code here... 165 * }}</pre> 166 * 167 * <p>If the action performed in your <code>run</code> method could 168 * throw a "checked" exception (those listed in the <code>throws</code> clause 169 * of a method), then you need to use the 170 * <code>PrivilegedExceptionAction</code> interface instead of the 171 * <code>PrivilegedAction</code> interface: 172 * 173 * <pre> {@code 174 * somemethod() throws FileNotFoundException { 175 * ...normal code here... 176 * try { 177 * FileInputStream fis = AccessController.doPrivileged( 178 * new PrivilegedExceptionAction<FileInputStream>() { 179 * public FileInputStream run() throws FileNotFoundException { 180 * return new FileInputStream("someFile"); 181 * } 182 * }); 183 * } catch (PrivilegedActionException e) { 184 * // e.getException() should be an instance of FileNotFoundException, 185 * // as only "checked" exceptions will be "wrapped" in a 186 * // PrivilegedActionException. 187 * throw (FileNotFoundException) e.getException(); 188 * } 189 * ...normal code here... 190 * }}</pre> 191 * 192 * <p> Be *very* careful in your use of the "privileged" construct, and 193 * always remember to make the privileged code section as small as possible. 194 * You can pass <code>Permission</code> arguments to further limit the 195 * scope of the "privilege" (see below). 196 * 197 * 198 * <p> Note that <code>checkPermission</code> always performs security checks 199 * within the context of the currently executing thread. 200 * Sometimes a security check that should be made within a given context 201 * will actually need to be done from within a 202 * <i>different</i> context (for example, from within a worker thread). 203 * The {@link #getContext() getContext} method and 204 * AccessControlContext class are provided 205 * for this situation. The <code>getContext</code> method takes a "snapshot" 206 * of the current calling context, and places 207 * it in an AccessControlContext object, which it returns. A sample call is 208 * the following: 209 * 210 * <pre> 211 * 212 * AccessControlContext acc = AccessController.getContext() 213 * 214 * </pre> 215 * 216 * <p> 217 * AccessControlContext itself has a <code>checkPermission</code> method 218 * that makes access decisions based on the context <i>it</i> encapsulates, 219 * rather than that of the current execution thread. 220 * Code within a different context can thus call that method on the 221 * previously-saved AccessControlContext object. A sample call is the 222 * following: 223 * 224 * <pre> 225 * 226 * acc.checkPermission(permission) 227 * 228 * </pre> 229 * 230 * <p> There are also times where you don't know a priori which permissions 231 * to check the context against. In these cases you can use the 232 * doPrivileged method that takes a context. You can also limit the scope 233 * of the privileged code by passing additional <code>Permission</code> 234 * parameters. 235 * 236 * <pre> {@code 237 * somemethod() { 238 * AccessController.doPrivileged(new PrivilegedAction<Object>() { 239 * public Object run() { 240 * // Code goes here. Any permission checks within this 241 * // run method will require that the intersection of the 242 * // caller's protection domain and the snapshot's 243 * // context have the desired permission. If a requested 244 * // permission is not implied by the limiting FilePermission 245 * // argument then checking of the thread continues beyond the 246 * // caller of doPrivileged. 247 * } 248 * }, acc, new FilePermission("/temp/*", read)); 249 * ...normal code here... 250 * }}</pre> 251 * <p> Passing a limiting <code>Permission</code> argument of an instance of 252 * <code>AllPermission</code> is equivalent to calling the equivalent 253 * <code>doPrivileged</code> method without limiting <code>Permission</code> 254 * arguments. Passing a zero length array of <code>Permission</code> disables 255 * the code privileges so that checking always continues beyond the caller of 256 * that <code>doPrivileged</code> method. 257 * 258 * @see AccessControlContext 259 * 260 * @author Li Gong 261 * @author Roland Schemers 262 */ 263 264 public final class AccessController { 265 266 /** 267 * Don't allow anyone to instantiate an AccessController 268 */ 269 private AccessController() { } 270 271 /** 272 * Performs the specified <code>PrivilegedAction</code> with privileges 273 * enabled. The action is performed with <i>all</i> of the permissions 274 * possessed by the caller's protection domain. 275 * 276 * <p> If the action's <code>run</code> method throws an (unchecked) 277 * exception, it will propagate through this method. 278 * 279 * <p> Note that any DomainCombiner associated with the current 280 * AccessControlContext will be ignored while the action is performed. 281 * 282 * @param action the action to be performed. 283 * 284 * @return the value returned by the action's <code>run</code> method. 285 * 286 * @exception NullPointerException if the action is <code>null</code> 287 * 288 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 289 * @see #doPrivileged(PrivilegedExceptionAction) 290 * @see #doPrivilegedWithCombiner(PrivilegedAction) 291 * @see java.security.DomainCombiner 292 */ 293 294 @CallerSensitive 295 public static native <T> T doPrivileged(PrivilegedAction<T> action); 296 297 /** 298 * Performs the specified <code>PrivilegedAction</code> with privileges 299 * enabled. The action is performed with <i>all</i> of the permissions 300 * possessed by the caller's protection domain. 301 * 302 * <p> If the action's <code>run</code> method throws an (unchecked) 303 * exception, it will propagate through this method. 304 * 305 * <p> This method preserves the current AccessControlContext's 306 * DomainCombiner (which may be null) while the action is performed. 307 * 308 * @param action the action to be performed. 309 * 310 * @return the value returned by the action's <code>run</code> method. 311 * 312 * @exception NullPointerException if the action is <code>null</code> 313 * 314 * @see #doPrivileged(PrivilegedAction) 315 * @see java.security.DomainCombiner 316 * 317 * @since 1.6 318 */ 319 @CallerSensitive 320 public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) { 321 AccessControlContext acc = getStackAccessControlContext(); 322 if (acc == null) { 323 return AccessController.doPrivileged(action); 324 } 325 DomainCombiner dc = acc.getAssignedCombiner(); 326 return AccessController.doPrivileged(action, 327 preserveCombiner(dc, Reflection.getCallerClass())); 328 } 329 330 331 /** 332 * Performs the specified {@code PrivilegedAction} with privileges 347 * @param action the action to be performed. 348 * @param context an <i>access control context</i> 349 * representing the restriction to be applied to the 350 * caller's domain's privileges before performing 351 * the specified action. If the context is 352 * {@code null}, then no additional restriction is applied. 353 * 354 * @return the value returned by the action's {@code run} method. 355 * 356 * @exception NullPointerException if the action is {@code null} 357 * 358 * @see #doPrivileged(PrivilegedAction) 359 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 360 */ 361 @CallerSensitive 362 public static native <T> T doPrivileged(PrivilegedAction<T> action, 363 AccessControlContext context); 364 365 366 /** 367 * Performs the specified <code>PrivilegedAction</code> with privileges 368 * enabled and restricted by the specified 369 * <code>AccessControlContext</code> and with a privilege scope limited 370 * by specified <code>Permission</code> arguments. 371 * 372 * The action is performed with the intersection of the permissions 373 * possessed by the caller's protection domain, and those possessed 374 * by the domains represented by the specified 375 * <code>AccessControlContext</code>. 376 * <p> 377 * If the action's <code>run</code> method throws an (unchecked) exception, 378 * it will propagate through this method. 379 * 380 * @param action the action to be performed. 381 * @param context an <i>access control context</i> 382 * representing the restriction to be applied to the 383 * caller's domain's privileges before performing 384 * the specified action. If the context is 385 * <code>null</code>, 386 * then no additional restriction is applied. 387 * @param perms the <code>Permission</code> arguments which limit the 388 * scope of the caller's privileges. The number of arguments 389 * is variable. 390 * 391 * @return the value returned by the action's <code>run</code> method. 392 * 393 * @throws NullPointerException if action or perms or any element of 394 * perms is <code>null</code> 395 * 396 * @see #doPrivileged(PrivilegedAction) 397 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 398 * 399 * @since 1.8 400 */ 401 @CallerSensitive 402 public static <T> T doPrivileged(PrivilegedAction<T> action, 403 AccessControlContext context, Permission... perms) { 404 405 AccessControlContext parent = getContext(); 406 if (perms == null) { 407 throw new NullPointerException("null permissions parameter"); 408 } 409 Class <?> caller = Reflection.getCallerClass(); 410 return AccessController.doPrivileged(action, createWrapper(null, 411 caller, parent, context, perms)); 412 } 413 414 415 /** 416 * Performs the specified <code>PrivilegedAction</code> with privileges 417 * enabled and restricted by the specified 418 * <code>AccessControlContext</code> and with a privilege scope limited 419 * by specified <code>Permission</code> arguments. 420 * 421 * The action is performed with the intersection of the permissions 422 * possessed by the caller's protection domain, and those possessed 423 * by the domains represented by the specified 424 * <code>AccessControlContext</code>. 425 * <p> 426 * If the action's <code>run</code> method throws an (unchecked) exception, 427 * it will propagate through this method. 428 * 429 * <p> This method preserves the current AccessControlContext's 430 * DomainCombiner (which may be null) while the action is performed. 431 * 432 * @param action the action to be performed. 433 * @param context an <i>access control context</i> 434 * representing the restriction to be applied to the 435 * caller's domain's privileges before performing 436 * the specified action. If the context is 437 * <code>null</code>, 438 * then no additional restriction is applied. 439 * @param perms the <code>Permission</code> arguments which limit the 440 * scope of the caller's privileges. The number of arguments 441 * is variable. 442 * 443 * @return the value returned by the action's <code>run</code> method. 444 * 445 * @throws NullPointerException if action or perms or any element of 446 * perms is <code>null</code> 447 * 448 * @see #doPrivileged(PrivilegedAction) 449 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 450 * @see java.security.DomainCombiner 451 * 452 * @since 1.8 453 */ 454 @CallerSensitive 455 public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action, 456 AccessControlContext context, Permission... perms) { 457 458 AccessControlContext parent = getContext(); 459 DomainCombiner dc = parent.getCombiner(); 460 if (dc == null && context != null) { 461 dc = context.getCombiner(); 462 } 463 if (perms == null) { 464 throw new NullPointerException("null permissions parameter"); 465 } 466 Class <?> caller = Reflection.getCallerClass(); 467 return AccessController.doPrivileged(action, createWrapper(dc, caller, 468 parent, context, perms)); 469 } 470 471 /** 472 * Performs the specified <code>PrivilegedExceptionAction</code> with 473 * privileges enabled. The action is performed with <i>all</i> of the 474 * permissions possessed by the caller's protection domain. 475 * 476 * <p> If the action's <code>run</code> method throws an <i>unchecked</i> 477 * exception, it will propagate through this method. 478 * 479 * <p> Note that any DomainCombiner associated with the current 480 * AccessControlContext will be ignored while the action is performed. 481 * 482 * @param action the action to be performed 483 * 484 * @return the value returned by the action's <code>run</code> method 485 * 486 * @exception PrivilegedActionException if the specified action's 487 * <code>run</code> method threw a <i>checked</i> exception 488 * @exception NullPointerException if the action is <code>null</code> 489 * 490 * @see #doPrivileged(PrivilegedAction) 491 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 492 * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction) 493 * @see java.security.DomainCombiner 494 */ 495 @CallerSensitive 496 public static native <T> T 497 doPrivileged(PrivilegedExceptionAction<T> action) 498 throws PrivilegedActionException; 499 500 501 /** 502 * Performs the specified <code>PrivilegedExceptionAction</code> with 503 * privileges enabled. The action is performed with <i>all</i> of the 504 * permissions possessed by the caller's protection domain. 505 * 506 * <p> If the action's <code>run</code> method throws an <i>unchecked</i> 507 * exception, it will propagate through this method. 508 * 509 * <p> This method preserves the current AccessControlContext's 510 * DomainCombiner (which may be null) while the action is performed. 511 * 512 * @param action the action to be performed. 513 * 514 * @return the value returned by the action's <code>run</code> method 515 * 516 * @exception PrivilegedActionException if the specified action's 517 * <code>run</code> method threw a <i>checked</i> exception 518 * @exception NullPointerException if the action is <code>null</code> 519 * 520 * @see #doPrivileged(PrivilegedAction) 521 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 522 * @see java.security.DomainCombiner 523 * 524 * @since 1.6 525 */ 526 @CallerSensitive 527 public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action) 528 throws PrivilegedActionException 529 { 530 AccessControlContext acc = getStackAccessControlContext(); 531 if (acc == null) { 532 return AccessController.doPrivileged(action); 533 } 534 DomainCombiner dc = acc.getAssignedCombiner(); 535 return AccessController.doPrivileged(action, 536 preserveCombiner(dc, Reflection.getCallerClass())); 537 } 538 592 * the specified action. If the context is 593 * {@code null}, then no additional restriction is applied. 594 * 595 * @return the value returned by the action's {@code run} method 596 * 597 * @exception PrivilegedActionException if the specified action's 598 * {@code run} method threw a <i>checked</i> exception 599 * @exception NullPointerException if the action is {@code null} 600 * 601 * @see #doPrivileged(PrivilegedAction) 602 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 603 */ 604 @CallerSensitive 605 public static native <T> T 606 doPrivileged(PrivilegedExceptionAction<T> action, 607 AccessControlContext context) 608 throws PrivilegedActionException; 609 610 611 /** 612 * Performs the specified <code>PrivilegedExceptionAction</code> with 613 * privileges enabled and restricted by the specified 614 * <code>AccessControlContext</code> and with a privilege scope limited by 615 * specified <code>Permission</code> arguments. 616 * 617 * The action is performed with the intersection of the permissions 618 * possessed by the caller's protection domain, and those possessed 619 * by the domains represented by the specified 620 * <code>AccessControlContext</code>. 621 * <p> 622 * If the action's <code>run</code> method throws an (unchecked) exception, 623 * it will propagate through this method. 624 * 625 * @param action the action to be performed. 626 * @param context an <i>access control context</i> 627 * representing the restriction to be applied to the 628 * caller's domain's privileges before performing 629 * the specified action. If the context is 630 * <code>null</code>, 631 * then no additional restriction is applied. 632 * @param perms the <code>Permission</code> arguments which limit the 633 * scope of the caller's privileges. The number of arguments 634 * is variable. 635 * 636 * @return the value returned by the action's <code>run</code> method. 637 * 638 * @throws PrivilegedActionException if the specified action's 639 * <code>run</code> method threw a <i>checked</i> exception 640 * @throws NullPointerException if action or perms or any element of 641 * perms is <code>null</code> 642 * 643 * @see #doPrivileged(PrivilegedAction) 644 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 645 * 646 * @since 1.8 647 */ 648 @CallerSensitive 649 public static <T> T doPrivileged(PrivilegedExceptionAction<T> action, 650 AccessControlContext context, Permission... perms) 651 throws PrivilegedActionException 652 { 653 AccessControlContext parent = getContext(); 654 if (perms == null) { 655 throw new NullPointerException("null permissions parameter"); 656 } 657 Class <?> caller = Reflection.getCallerClass(); 658 return AccessController.doPrivileged(action, createWrapper(null, caller, parent, context, perms)); 659 } 660 661 662 /** 663 * Performs the specified <code>PrivilegedExceptionAction</code> with 664 * privileges enabled and restricted by the specified 665 * <code>AccessControlContext</code> and with a privilege scope limited by 666 * specified <code>Permission</code> arguments. 667 * 668 * The action is performed with the intersection of the permissions 669 * possessed by the caller's protection domain, and those possessed 670 * by the domains represented by the specified 671 * <code>AccessControlContext</code>. 672 * <p> 673 * If the action's <code>run</code> method throws an (unchecked) exception, 674 * it will propagate through this method. 675 * 676 * <p> This method preserves the current AccessControlContext's 677 * DomainCombiner (which may be null) while the action is performed. 678 * 679 * @param action the action to be performed. 680 * @param context an <i>access control context</i> 681 * representing the restriction to be applied to the 682 * caller's domain's privileges before performing 683 * the specified action. If the context is 684 * <code>null</code>, 685 * then no additional restriction is applied. 686 * @param perms the <code>Permission</code> arguments which limit the 687 * scope of the caller's privileges. The number of arguments 688 * is variable. 689 * 690 * @return the value returned by the action's <code>run</code> method. 691 * 692 * @throws PrivilegedActionException if the specified action's 693 * <code>run</code> method threw a <i>checked</i> exception 694 * @throws NullPointerException if action or perms or any element of 695 * perms is <code>null</code> 696 * 697 * @see #doPrivileged(PrivilegedAction) 698 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 699 * @see java.security.DomainCombiner 700 * 701 * @since 1.8 702 */ 703 @CallerSensitive 704 public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action, 705 AccessControlContext context, 706 Permission... perms) 707 throws PrivilegedActionException 708 { 709 AccessControlContext parent = getContext(); 710 DomainCombiner dc = parent.getCombiner(); 711 if (dc == null && context != null) { 712 dc = context.getCombiner(); 713 } 714 if (perms == null) { 715 throw new NullPointerException("null permissions parameter"); 753 754 public static AccessControlContext getContext() 755 { 756 AccessControlContext acc = getStackAccessControlContext(); 757 if (acc == null) { 758 // all we had was privileged system code. We don't want 759 // to return null though, so we construct a real ACC. 760 return new AccessControlContext(null, true); 761 } else { 762 return acc.optimize(); 763 } 764 } 765 766 /** 767 * Determines whether the access request indicated by the 768 * specified permission should be allowed or denied, based on 769 * the current AccessControlContext and security policy. 770 * This method quietly returns if the access request 771 * is permitted, or throws an AccessControlException otherwise. The 772 * getPermission method of the AccessControlException returns the 773 * <code>perm</code> Permission object instance. 774 * 775 * @param perm the requested permission. 776 * 777 * @exception AccessControlException if the specified permission 778 * is not permitted, based on the current security policy. 779 * @exception NullPointerException if the specified permission 780 * is <code>null</code> and is checked based on the 781 * security policy currently in effect. 782 */ 783 784 public static void checkPermission(Permission perm) 785 throws AccessControlException 786 { 787 //System.err.println("checkPermission "+perm); 788 //Thread.currentThread().dumpStack(); 789 790 if (perm == null) { 791 throw new NullPointerException("permission can't be null"); 792 } 793 794 AccessControlContext stack = getStackAccessControlContext(); 795 // if context is null, we had privileged system code on the stack. 796 if (stack == null) { 797 Debug debug = AccessControlContext.getDebug(); 798 boolean dumpDebug = false; 799 if (debug != null) { 800 dumpDebug = !Debug.isOn("codebase="); | 32 /** 33 * <p> The AccessController class is used for access control operations 34 * and decisions. 35 * 36 * <p> More specifically, the AccessController class is used for 37 * three purposes: 38 * 39 * <ul> 40 * <li> to decide whether an access to a critical system 41 * resource is to be allowed or denied, based on the security policy 42 * currently in effect,<p> 43 * <li>to mark code as being "privileged", thus affecting subsequent 44 * access determinations, and<p> 45 * <li>to obtain a "snapshot" of the current calling context so 46 * access-control decisions from a different context can be made with 47 * respect to the saved context. </ul> 48 * 49 * <p> The {@link #checkPermission(Permission) checkPermission} method 50 * determines whether the access request indicated by a specified 51 * permission should be granted or denied. A sample call appears 52 * below. In this example, {@code checkPermission} will determine 53 * whether or not to grant "read" access to the file named "testFile" in 54 * the "/temp" directory. 55 * 56 * <pre> 57 * 58 * FilePermission perm = new FilePermission("/temp/testFile", "read"); 59 * AccessController.checkPermission(perm); 60 * 61 * </pre> 62 * 63 * <p> If a requested access is allowed, 64 * {@code checkPermission} returns quietly. If denied, an 65 * AccessControlException is 66 * thrown. AccessControlException can also be thrown if the requested 67 * permission is of an incorrect type or contains an invalid value. 68 * Such information is given whenever possible. 69 * 70 * Suppose the current thread traversed m callers, in the order of caller 1 71 * to caller 2 to caller m. Then caller m invoked the 72 * {@code checkPermission} method. 73 * The {@code checkPermission} method determines whether access 74 * is granted or denied based on the following algorithm: 75 * 76 * <pre> {@code 77 * for (int i = m; i > 0; i--) { 78 * 79 * if (caller i's domain does not have the permission) 80 * throw AccessControlException 81 * 82 * else if (caller i is marked as privileged) { 83 * if (a context was specified in the call to doPrivileged) 84 * context.checkPermission(permission) 85 * if (limited permissions were specified in the call to doPrivileged) { 86 * for (each limited permission) { 87 * if (the limited permission implies the requested permission) 88 * return; 89 * } 90 * } else 91 * return; 92 * } 93 * } 94 * 95 * // Next, check the context inherited when the thread was created. 96 * // Whenever a new thread is created, the AccessControlContext at 97 * // that time is stored and associated with the new thread, as the 98 * // "inherited" context. 99 * 100 * inheritedContext.checkPermission(permission); 101 * }</pre> 102 * 103 * <p> A caller can be marked as being "privileged" 104 * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below). 105 * When making access control decisions, the {@code checkPermission} 106 * method stops checking if it reaches a caller that 107 * was marked as "privileged" via a {@code doPrivileged} 108 * call without a context argument (see below for information about a 109 * context argument). If that caller's domain has the 110 * specified permission and at least one limiting permission argument (if any) 111 * implies the requested permission, no further checking is done and 112 * {@code checkPermission} 113 * returns quietly, indicating that the requested access is allowed. 114 * If that domain does not have the specified permission, an exception 115 * is thrown, as usual. If the caller's domain had the specified permission 116 * but it was not implied by any limiting permission arguments given in the call 117 * to {@code doPrivileged} then the permission checking continues 118 * until there are no more callers or another {@code doPrivileged} 119 * call matches the requested permission and returns normally. 120 * 121 * <p> The normal use of the "privileged" feature is as follows. If you 122 * don't need to return a value from within the "privileged" block, do 123 * the following: 124 * 125 * <pre> {@code 126 * somemethod() { 127 * ...normal code here... 128 * AccessController.doPrivileged(new PrivilegedAction<Void>() { 129 * public Void run() { 130 * // privileged code goes here, for example: 131 * System.loadLibrary("awt"); 132 * return null; // nothing to return 133 * } 134 * }); 135 * ...normal code here... 136 * }}</pre> 137 * 138 * <p> 139 * PrivilegedAction is an interface with a single method, named 140 * {@code run}. 141 * The above example shows creation of an implementation 142 * of that interface; a concrete implementation of the 143 * {@code run} method is supplied. 144 * When the call to {@code doPrivileged} is made, an 145 * instance of the PrivilegedAction implementation is passed 146 * to it. The {@code doPrivileged} method calls the 147 * {@code run} method from the PrivilegedAction 148 * implementation after enabling privileges, and returns the 149 * {@code run} method's return value as the 150 * {@code doPrivileged} return value (which is 151 * ignored in this example). 152 * 153 * <p> If you need to return a value, you can do something like the following: 154 * 155 * <pre> {@code 156 * somemethod() { 157 * ...normal code here... 158 * String user = AccessController.doPrivileged( 159 * new PrivilegedAction<String>() { 160 * public String run() { 161 * return System.getProperty("user.name"); 162 * } 163 * }); 164 * ...normal code here... 165 * }}</pre> 166 * 167 * <p>If the action performed in your {@code run} method could 168 * throw a "checked" exception (those listed in the {@code throws} clause 169 * of a method), then you need to use the 170 * {@code PrivilegedExceptionAction} interface instead of the 171 * {@code PrivilegedAction} interface: 172 * 173 * <pre> {@code 174 * somemethod() throws FileNotFoundException { 175 * ...normal code here... 176 * try { 177 * FileInputStream fis = AccessController.doPrivileged( 178 * new PrivilegedExceptionAction<FileInputStream>() { 179 * public FileInputStream run() throws FileNotFoundException { 180 * return new FileInputStream("someFile"); 181 * } 182 * }); 183 * } catch (PrivilegedActionException e) { 184 * // e.getException() should be an instance of FileNotFoundException, 185 * // as only "checked" exceptions will be "wrapped" in a 186 * // PrivilegedActionException. 187 * throw (FileNotFoundException) e.getException(); 188 * } 189 * ...normal code here... 190 * }}</pre> 191 * 192 * <p> Be *very* careful in your use of the "privileged" construct, and 193 * always remember to make the privileged code section as small as possible. 194 * You can pass {@code Permission} arguments to further limit the 195 * scope of the "privilege" (see below). 196 * 197 * 198 * <p> Note that {@code checkPermission} always performs security checks 199 * within the context of the currently executing thread. 200 * Sometimes a security check that should be made within a given context 201 * will actually need to be done from within a 202 * <i>different</i> context (for example, from within a worker thread). 203 * The {@link #getContext() getContext} method and 204 * AccessControlContext class are provided 205 * for this situation. The {@code getContext} method takes a "snapshot" 206 * of the current calling context, and places 207 * it in an AccessControlContext object, which it returns. A sample call is 208 * the following: 209 * 210 * <pre> 211 * 212 * AccessControlContext acc = AccessController.getContext() 213 * 214 * </pre> 215 * 216 * <p> 217 * AccessControlContext itself has a {@code checkPermission} method 218 * that makes access decisions based on the context <i>it</i> encapsulates, 219 * rather than that of the current execution thread. 220 * Code within a different context can thus call that method on the 221 * previously-saved AccessControlContext object. A sample call is the 222 * following: 223 * 224 * <pre> 225 * 226 * acc.checkPermission(permission) 227 * 228 * </pre> 229 * 230 * <p> There are also times where you don't know a priori which permissions 231 * to check the context against. In these cases you can use the 232 * doPrivileged method that takes a context. You can also limit the scope 233 * of the privileged code by passing additional {@code Permission} 234 * parameters. 235 * 236 * <pre> {@code 237 * somemethod() { 238 * AccessController.doPrivileged(new PrivilegedAction<Object>() { 239 * public Object run() { 240 * // Code goes here. Any permission checks within this 241 * // run method will require that the intersection of the 242 * // caller's protection domain and the snapshot's 243 * // context have the desired permission. If a requested 244 * // permission is not implied by the limiting FilePermission 245 * // argument then checking of the thread continues beyond the 246 * // caller of doPrivileged. 247 * } 248 * }, acc, new FilePermission("/temp/*", read)); 249 * ...normal code here... 250 * }}</pre> 251 * <p> Passing a limiting {@code Permission} argument of an instance of 252 * {@code AllPermission} is equivalent to calling the equivalent 253 * {@code doPrivileged} method without limiting {@code Permission} 254 * arguments. Passing a zero length array of {@code Permission} disables 255 * the code privileges so that checking always continues beyond the caller of 256 * that {@code doPrivileged} method. 257 * 258 * @see AccessControlContext 259 * 260 * @author Li Gong 261 * @author Roland Schemers 262 */ 263 264 public final class AccessController { 265 266 /** 267 * Don't allow anyone to instantiate an AccessController 268 */ 269 private AccessController() { } 270 271 /** 272 * Performs the specified {@code PrivilegedAction} with privileges 273 * enabled. The action is performed with <i>all</i> of the permissions 274 * possessed by the caller's protection domain. 275 * 276 * <p> If the action's {@code run} method throws an (unchecked) 277 * exception, it will propagate through this method. 278 * 279 * <p> Note that any DomainCombiner associated with the current 280 * AccessControlContext will be ignored while the action is performed. 281 * 282 * @param action the action to be performed. 283 * 284 * @return the value returned by the action's {@code run} method. 285 * 286 * @exception NullPointerException if the action is {@code null} 287 * 288 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 289 * @see #doPrivileged(PrivilegedExceptionAction) 290 * @see #doPrivilegedWithCombiner(PrivilegedAction) 291 * @see java.security.DomainCombiner 292 */ 293 294 @CallerSensitive 295 public static native <T> T doPrivileged(PrivilegedAction<T> action); 296 297 /** 298 * Performs the specified {@code PrivilegedAction} with privileges 299 * enabled. The action is performed with <i>all</i> of the permissions 300 * possessed by the caller's protection domain. 301 * 302 * <p> If the action's {@code run} method throws an (unchecked) 303 * exception, it will propagate through this method. 304 * 305 * <p> This method preserves the current AccessControlContext's 306 * DomainCombiner (which may be null) while the action is performed. 307 * 308 * @param action the action to be performed. 309 * 310 * @return the value returned by the action's {@code run} method. 311 * 312 * @exception NullPointerException if the action is {@code null} 313 * 314 * @see #doPrivileged(PrivilegedAction) 315 * @see java.security.DomainCombiner 316 * 317 * @since 1.6 318 */ 319 @CallerSensitive 320 public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) { 321 AccessControlContext acc = getStackAccessControlContext(); 322 if (acc == null) { 323 return AccessController.doPrivileged(action); 324 } 325 DomainCombiner dc = acc.getAssignedCombiner(); 326 return AccessController.doPrivileged(action, 327 preserveCombiner(dc, Reflection.getCallerClass())); 328 } 329 330 331 /** 332 * Performs the specified {@code PrivilegedAction} with privileges 347 * @param action the action to be performed. 348 * @param context an <i>access control context</i> 349 * representing the restriction to be applied to the 350 * caller's domain's privileges before performing 351 * the specified action. If the context is 352 * {@code null}, then no additional restriction is applied. 353 * 354 * @return the value returned by the action's {@code run} method. 355 * 356 * @exception NullPointerException if the action is {@code null} 357 * 358 * @see #doPrivileged(PrivilegedAction) 359 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 360 */ 361 @CallerSensitive 362 public static native <T> T doPrivileged(PrivilegedAction<T> action, 363 AccessControlContext context); 364 365 366 /** 367 * Performs the specified {@code PrivilegedAction} with privileges 368 * enabled and restricted by the specified 369 * {@code AccessControlContext} and with a privilege scope limited 370 * by specified {@code Permission} arguments. 371 * 372 * The action is performed with the intersection of the permissions 373 * possessed by the caller's protection domain, and those possessed 374 * by the domains represented by the specified 375 * {@code AccessControlContext}. 376 * <p> 377 * If the action's {@code run} method throws an (unchecked) exception, 378 * it will propagate through this method. 379 * 380 * @param action the action to be performed. 381 * @param context an <i>access control context</i> 382 * representing the restriction to be applied to the 383 * caller's domain's privileges before performing 384 * the specified action. If the context is 385 * {@code null}, 386 * then no additional restriction is applied. 387 * @param perms the {@code Permission} arguments which limit the 388 * scope of the caller's privileges. The number of arguments 389 * is variable. 390 * 391 * @return the value returned by the action's {@code run} method. 392 * 393 * @throws NullPointerException if action or perms or any element of 394 * perms is {@code null} 395 * 396 * @see #doPrivileged(PrivilegedAction) 397 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 398 * 399 * @since 1.8 400 */ 401 @CallerSensitive 402 public static <T> T doPrivileged(PrivilegedAction<T> action, 403 AccessControlContext context, Permission... perms) { 404 405 AccessControlContext parent = getContext(); 406 if (perms == null) { 407 throw new NullPointerException("null permissions parameter"); 408 } 409 Class <?> caller = Reflection.getCallerClass(); 410 return AccessController.doPrivileged(action, createWrapper(null, 411 caller, parent, context, perms)); 412 } 413 414 415 /** 416 * Performs the specified {@code PrivilegedAction} with privileges 417 * enabled and restricted by the specified 418 * {@code AccessControlContext} and with a privilege scope limited 419 * by specified {@code Permission} arguments. 420 * 421 * The action is performed with the intersection of the permissions 422 * possessed by the caller's protection domain, and those possessed 423 * by the domains represented by the specified 424 * {@code AccessControlContext}. 425 * <p> 426 * If the action's {@code run} method throws an (unchecked) exception, 427 * it will propagate through this method. 428 * 429 * <p> This method preserves the current AccessControlContext's 430 * DomainCombiner (which may be null) while the action is performed. 431 * 432 * @param action the action to be performed. 433 * @param context an <i>access control context</i> 434 * representing the restriction to be applied to the 435 * caller's domain's privileges before performing 436 * the specified action. If the context is 437 * {@code null}, 438 * then no additional restriction is applied. 439 * @param perms the {@code Permission} arguments which limit the 440 * scope of the caller's privileges. The number of arguments 441 * is variable. 442 * 443 * @return the value returned by the action's {@code run} method. 444 * 445 * @throws NullPointerException if action or perms or any element of 446 * perms is {@code null} 447 * 448 * @see #doPrivileged(PrivilegedAction) 449 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 450 * @see java.security.DomainCombiner 451 * 452 * @since 1.8 453 */ 454 @CallerSensitive 455 public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action, 456 AccessControlContext context, Permission... perms) { 457 458 AccessControlContext parent = getContext(); 459 DomainCombiner dc = parent.getCombiner(); 460 if (dc == null && context != null) { 461 dc = context.getCombiner(); 462 } 463 if (perms == null) { 464 throw new NullPointerException("null permissions parameter"); 465 } 466 Class <?> caller = Reflection.getCallerClass(); 467 return AccessController.doPrivileged(action, createWrapper(dc, caller, 468 parent, context, perms)); 469 } 470 471 /** 472 * Performs the specified {@code PrivilegedExceptionAction} with 473 * privileges enabled. The action is performed with <i>all</i> of the 474 * permissions possessed by the caller's protection domain. 475 * 476 * <p> If the action's {@code run} method throws an <i>unchecked</i> 477 * exception, it will propagate through this method. 478 * 479 * <p> Note that any DomainCombiner associated with the current 480 * AccessControlContext will be ignored while the action is performed. 481 * 482 * @param action the action to be performed 483 * 484 * @return the value returned by the action's {@code run} method 485 * 486 * @exception PrivilegedActionException if the specified action's 487 * {@code run} method threw a <i>checked</i> exception 488 * @exception NullPointerException if the action is {@code null} 489 * 490 * @see #doPrivileged(PrivilegedAction) 491 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 492 * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction) 493 * @see java.security.DomainCombiner 494 */ 495 @CallerSensitive 496 public static native <T> T 497 doPrivileged(PrivilegedExceptionAction<T> action) 498 throws PrivilegedActionException; 499 500 501 /** 502 * Performs the specified {@code PrivilegedExceptionAction} with 503 * privileges enabled. The action is performed with <i>all</i> of the 504 * permissions possessed by the caller's protection domain. 505 * 506 * <p> If the action's {@code run} method throws an <i>unchecked</i> 507 * exception, it will propagate through this method. 508 * 509 * <p> This method preserves the current AccessControlContext's 510 * DomainCombiner (which may be null) while the action is performed. 511 * 512 * @param action the action to be performed. 513 * 514 * @return the value returned by the action's {@code run} method 515 * 516 * @exception PrivilegedActionException if the specified action's 517 * {@code run} method threw a <i>checked</i> exception 518 * @exception NullPointerException if the action is {@code null} 519 * 520 * @see #doPrivileged(PrivilegedAction) 521 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 522 * @see java.security.DomainCombiner 523 * 524 * @since 1.6 525 */ 526 @CallerSensitive 527 public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action) 528 throws PrivilegedActionException 529 { 530 AccessControlContext acc = getStackAccessControlContext(); 531 if (acc == null) { 532 return AccessController.doPrivileged(action); 533 } 534 DomainCombiner dc = acc.getAssignedCombiner(); 535 return AccessController.doPrivileged(action, 536 preserveCombiner(dc, Reflection.getCallerClass())); 537 } 538 592 * the specified action. If the context is 593 * {@code null}, then no additional restriction is applied. 594 * 595 * @return the value returned by the action's {@code run} method 596 * 597 * @exception PrivilegedActionException if the specified action's 598 * {@code run} method threw a <i>checked</i> exception 599 * @exception NullPointerException if the action is {@code null} 600 * 601 * @see #doPrivileged(PrivilegedAction) 602 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 603 */ 604 @CallerSensitive 605 public static native <T> T 606 doPrivileged(PrivilegedExceptionAction<T> action, 607 AccessControlContext context) 608 throws PrivilegedActionException; 609 610 611 /** 612 * Performs the specified {@code PrivilegedExceptionAction} with 613 * privileges enabled and restricted by the specified 614 * {@code AccessControlContext} and with a privilege scope limited by 615 * specified {@code Permission} arguments. 616 * 617 * The action is performed with the intersection of the permissions 618 * possessed by the caller's protection domain, and those possessed 619 * by the domains represented by the specified 620 * {@code AccessControlContext}. 621 * <p> 622 * If the action's {@code run} method throws an (unchecked) exception, 623 * it will propagate through this method. 624 * 625 * @param action the action to be performed. 626 * @param context an <i>access control context</i> 627 * representing the restriction to be applied to the 628 * caller's domain's privileges before performing 629 * the specified action. If the context is 630 * {@code null}, 631 * then no additional restriction is applied. 632 * @param perms the {@code Permission} arguments which limit the 633 * scope of the caller's privileges. The number of arguments 634 * is variable. 635 * 636 * @return the value returned by the action's {@code run} method. 637 * 638 * @throws PrivilegedActionException if the specified action's 639 * {@code run} method threw a <i>checked</i> exception 640 * @throws NullPointerException if action or perms or any element of 641 * perms is {@code null} 642 * 643 * @see #doPrivileged(PrivilegedAction) 644 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 645 * 646 * @since 1.8 647 */ 648 @CallerSensitive 649 public static <T> T doPrivileged(PrivilegedExceptionAction<T> action, 650 AccessControlContext context, Permission... perms) 651 throws PrivilegedActionException 652 { 653 AccessControlContext parent = getContext(); 654 if (perms == null) { 655 throw new NullPointerException("null permissions parameter"); 656 } 657 Class <?> caller = Reflection.getCallerClass(); 658 return AccessController.doPrivileged(action, createWrapper(null, caller, parent, context, perms)); 659 } 660 661 662 /** 663 * Performs the specified {@code PrivilegedExceptionAction} with 664 * privileges enabled and restricted by the specified 665 * {@code AccessControlContext} and with a privilege scope limited by 666 * specified {@code Permission} arguments. 667 * 668 * The action is performed with the intersection of the permissions 669 * possessed by the caller's protection domain, and those possessed 670 * by the domains represented by the specified 671 * {@code AccessControlContext}. 672 * <p> 673 * If the action's {@code run} method throws an (unchecked) exception, 674 * it will propagate through this method. 675 * 676 * <p> This method preserves the current AccessControlContext's 677 * DomainCombiner (which may be null) while the action is performed. 678 * 679 * @param action the action to be performed. 680 * @param context an <i>access control context</i> 681 * representing the restriction to be applied to the 682 * caller's domain's privileges before performing 683 * the specified action. If the context is 684 * {@code null}, 685 * then no additional restriction is applied. 686 * @param perms the {@code Permission} arguments which limit the 687 * scope of the caller's privileges. The number of arguments 688 * is variable. 689 * 690 * @return the value returned by the action's {@code run} method. 691 * 692 * @throws PrivilegedActionException if the specified action's 693 * {@code run} method threw a <i>checked</i> exception 694 * @throws NullPointerException if action or perms or any element of 695 * perms is {@code null} 696 * 697 * @see #doPrivileged(PrivilegedAction) 698 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 699 * @see java.security.DomainCombiner 700 * 701 * @since 1.8 702 */ 703 @CallerSensitive 704 public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action, 705 AccessControlContext context, 706 Permission... perms) 707 throws PrivilegedActionException 708 { 709 AccessControlContext parent = getContext(); 710 DomainCombiner dc = parent.getCombiner(); 711 if (dc == null && context != null) { 712 dc = context.getCombiner(); 713 } 714 if (perms == null) { 715 throw new NullPointerException("null permissions parameter"); 753 754 public static AccessControlContext getContext() 755 { 756 AccessControlContext acc = getStackAccessControlContext(); 757 if (acc == null) { 758 // all we had was privileged system code. We don't want 759 // to return null though, so we construct a real ACC. 760 return new AccessControlContext(null, true); 761 } else { 762 return acc.optimize(); 763 } 764 } 765 766 /** 767 * Determines whether the access request indicated by the 768 * specified permission should be allowed or denied, based on 769 * the current AccessControlContext and security policy. 770 * This method quietly returns if the access request 771 * is permitted, or throws an AccessControlException otherwise. The 772 * getPermission method of the AccessControlException returns the 773 * {@code perm} Permission object instance. 774 * 775 * @param perm the requested permission. 776 * 777 * @exception AccessControlException if the specified permission 778 * is not permitted, based on the current security policy. 779 * @exception NullPointerException if the specified permission 780 * is {@code null} and is checked based on the 781 * security policy currently in effect. 782 */ 783 784 public static void checkPermission(Permission perm) 785 throws AccessControlException 786 { 787 //System.err.println("checkPermission "+perm); 788 //Thread.currentThread().dumpStack(); 789 790 if (perm == null) { 791 throw new NullPointerException("permission can't be null"); 792 } 793 794 AccessControlContext stack = getStackAccessControlContext(); 795 // if context is null, we had privileged system code on the stack. 796 if (stack == null) { 797 Debug debug = AccessControlContext.getDebug(); 798 boolean dumpDebug = false; 799 if (debug != null) { 800 dumpDebug = !Debug.isOn("codebase="); |