1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.security; 27 28 import sun.security.util.Debug; 29 import sun.reflect.CallerSensitive; 30 import sun.reflect.Reflection; 31 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, 43 * <li>to mark code as being "privileged", thus affecting subsequent 44 * access determinations, and 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 <T> the type of the value returned by the PrivilegedAction's 283 * {@code run} method. 284 * 285 * @param action the action to be performed. 286 * 287 * @return the value returned by the action's {@code run} method. 288 * 289 * @exception NullPointerException if the action is {@code null} 290 * 291 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 292 * @see #doPrivileged(PrivilegedExceptionAction) 293 * @see #doPrivilegedWithCombiner(PrivilegedAction) 294 * @see java.security.DomainCombiner 295 */ 296 297 @CallerSensitive 298 public static native <T> T doPrivileged(PrivilegedAction<T> action); 299 300 /** 301 * Performs the specified {@code PrivilegedAction} with privileges 302 * enabled. The action is performed with <i>all</i> of the permissions 303 * possessed by the caller's protection domain. 304 * 305 * <p> If the action's {@code run} method throws an (unchecked) 306 * exception, it will propagate through this method. 307 * 308 * <p> This method preserves the current AccessControlContext's 309 * DomainCombiner (which may be null) while the action is performed. 310 * 311 * @param <T> the type of the value returned by the PrivilegedAction's 312 * {@code run} method. 313 * 314 * @param action the action to be performed. 315 * 316 * @return the value returned by the action's {@code run} method. 317 * 318 * @exception NullPointerException if the action is {@code null} 319 * 320 * @see #doPrivileged(PrivilegedAction) 321 * @see java.security.DomainCombiner 322 * 323 * @since 1.6 324 */ 325 @CallerSensitive 326 public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) { 327 AccessControlContext acc = getStackAccessControlContext(); 328 if (acc == null) { 329 return AccessController.doPrivileged(action); 330 } 331 DomainCombiner dc = acc.getAssignedCombiner(); 332 return AccessController.doPrivileged(action, 333 preserveCombiner(dc, Reflection.getCallerClass())); 334 } 335 336 337 /** 338 * Performs the specified {@code PrivilegedAction} with privileges 339 * enabled and restricted by the specified {@code AccessControlContext}. 340 * The action is performed with the intersection of the permissions 341 * possessed by the caller's protection domain, and those possessed 342 * by the domains represented by the specified {@code AccessControlContext}. 343 * <p> 344 * If the action's {@code run} method throws an (unchecked) exception, 345 * it will propagate through this method. 346 * <p> 347 * If a security manager is installed and the specified 348 * {@code AccessControlContext} was not created by system code and the 349 * caller's {@code ProtectionDomain} has not been granted the 350 * {@literal "createAccessControlContext"} 351 * {@link java.security.SecurityPermission}, then the action is performed 352 * with no permissions. 353 * 354 * @param <T> the type of the value returned by the PrivilegedAction's 355 * {@code run} method. 356 * @param action the action to be performed. 357 * @param context an <i>access control context</i> 358 * representing the restriction to be applied to the 359 * caller's domain's privileges before performing 360 * the specified action. If the context is 361 * {@code null}, then no additional restriction is applied. 362 * 363 * @return the value returned by the action's {@code run} method. 364 * 365 * @exception NullPointerException if the action is {@code null} 366 * 367 * @see #doPrivileged(PrivilegedAction) 368 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 369 */ 370 @CallerSensitive 371 public static native <T> T doPrivileged(PrivilegedAction<T> action, 372 AccessControlContext context); 373 374 375 /** 376 * Performs the specified {@code PrivilegedAction} with privileges 377 * enabled and restricted by the specified 378 * {@code AccessControlContext} and with a privilege scope limited 379 * by specified {@code Permission} arguments. 380 * 381 * The action is performed with the intersection of the permissions 382 * possessed by the caller's protection domain, and those possessed 383 * by the domains represented by the specified 384 * {@code AccessControlContext}. 385 * <p> 386 * If the action's {@code run} method throws an (unchecked) exception, 387 * it will propagate through this method. 388 * <p> 389 * If a security manager is installed and the specified 390 * {@code AccessControlContext} was not created by system code and the 391 * caller's {@code ProtectionDomain} has not been granted the 392 * {@literal "createAccessControlContext"} 393 * {@link java.security.SecurityPermission}, then the action is performed 394 * with no permissions. 395 * 396 * @param <T> the type of the value returned by the PrivilegedAction's 397 * {@code run} method. 398 * @param action the action to be performed. 399 * @param context an <i>access control context</i> 400 * representing the restriction to be applied to the 401 * caller's domain's privileges before performing 402 * the specified action. If the context is 403 * {@code null}, 404 * then no additional restriction is applied. 405 * @param perms the {@code Permission} arguments which limit the 406 * scope of the caller's privileges. The number of arguments 407 * is variable. 408 * 409 * @return the value returned by the action's {@code run} method. 410 * 411 * @throws NullPointerException if action or perms or any element of 412 * perms is {@code null} 413 * 414 * @see #doPrivileged(PrivilegedAction) 415 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 416 * 417 * @since 1.8 418 */ 419 @CallerSensitive 420 public static <T> T doPrivileged(PrivilegedAction<T> action, 421 AccessControlContext context, Permission... perms) { 422 423 AccessControlContext parent = getContext(); 424 if (perms == null) { 425 throw new NullPointerException("null permissions parameter"); 426 } 427 Class <?> caller = Reflection.getCallerClass(); 428 return AccessController.doPrivileged(action, createWrapper(null, 429 caller, parent, context, perms)); 430 } 431 432 433 /** 434 * Performs the specified {@code PrivilegedAction} with privileges 435 * enabled and restricted by the specified 436 * {@code AccessControlContext} and with a privilege scope limited 437 * by specified {@code Permission} arguments. 438 * 439 * The action is performed with the intersection of the permissions 440 * possessed by the caller's protection domain, and those possessed 441 * by the domains represented by the specified 442 * {@code AccessControlContext}. 443 * <p> 444 * If the action's {@code run} method throws an (unchecked) exception, 445 * it will propagate through this method. 446 * 447 * <p> This method preserves the current AccessControlContext's 448 * DomainCombiner (which may be null) while the action is performed. 449 * <p> 450 * If a security manager is installed and the specified 451 * {@code AccessControlContext} was not created by system code and the 452 * caller's {@code ProtectionDomain} has not been granted the 453 * {@literal "createAccessControlContext"} 454 * {@link java.security.SecurityPermission}, then the action is performed 455 * with no permissions. 456 * 457 * @param <T> the type of the value returned by the PrivilegedAction's 458 * {@code run} method. 459 * @param action the action to be performed. 460 * @param context an <i>access control context</i> 461 * representing the restriction to be applied to the 462 * caller's domain's privileges before performing 463 * the specified action. If the context is 464 * {@code null}, 465 * then no additional restriction is applied. 466 * @param perms the {@code Permission} arguments which limit the 467 * scope of the caller's privileges. The number of arguments 468 * is variable. 469 * 470 * @return the value returned by the action's {@code run} method. 471 * 472 * @throws NullPointerException if action or perms or any element of 473 * perms is {@code null} 474 * 475 * @see #doPrivileged(PrivilegedAction) 476 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 477 * @see java.security.DomainCombiner 478 * 479 * @since 1.8 480 */ 481 @CallerSensitive 482 public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action, 483 AccessControlContext context, Permission... perms) { 484 485 AccessControlContext parent = getContext(); 486 DomainCombiner dc = parent.getCombiner(); 487 if (dc == null && context != null) { 488 dc = context.getCombiner(); 489 } 490 if (perms == null) { 491 throw new NullPointerException("null permissions parameter"); 492 } 493 Class <?> caller = Reflection.getCallerClass(); 494 return AccessController.doPrivileged(action, createWrapper(dc, caller, 495 parent, context, perms)); 496 } 497 498 /** 499 * Performs the specified {@code PrivilegedExceptionAction} with 500 * privileges enabled. The action is performed with <i>all</i> of the 501 * permissions possessed by the caller's protection domain. 502 * 503 * <p> If the action's {@code run} method throws an <i>unchecked</i> 504 * exception, it will propagate through this method. 505 * 506 * <p> Note that any DomainCombiner associated with the current 507 * AccessControlContext will be ignored while the action is performed. 508 * 509 * @param <T> the type of the value returned by the 510 * PrivilegedExceptionAction's {@code run} method. 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 #doPrivilegedWithCombiner(PrivilegedExceptionAction) 523 * @see java.security.DomainCombiner 524 */ 525 @CallerSensitive 526 public static native <T> T 527 doPrivileged(PrivilegedExceptionAction<T> action) 528 throws PrivilegedActionException; 529 530 531 /** 532 * Performs the specified {@code PrivilegedExceptionAction} with 533 * privileges enabled. The action is performed with <i>all</i> of the 534 * permissions possessed by the caller's protection domain. 535 * 536 * <p> If the action's {@code run} method throws an <i>unchecked</i> 537 * exception, it will propagate through this method. 538 * 539 * <p> This method preserves the current AccessControlContext's 540 * DomainCombiner (which may be null) while the action is performed. 541 * 542 * @param <T> the type of the value returned by the 543 * PrivilegedExceptionAction's {@code run} method. 544 * 545 * @param action the action to be performed. 546 * 547 * @return the value returned by the action's {@code run} method 548 * 549 * @exception PrivilegedActionException if the specified action's 550 * {@code run} method threw a <i>checked</i> exception 551 * @exception NullPointerException if the action is {@code null} 552 * 553 * @see #doPrivileged(PrivilegedAction) 554 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 555 * @see java.security.DomainCombiner 556 * 557 * @since 1.6 558 */ 559 @CallerSensitive 560 public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action) 561 throws PrivilegedActionException 562 { 563 AccessControlContext acc = getStackAccessControlContext(); 564 if (acc == null) { 565 return AccessController.doPrivileged(action); 566 } 567 DomainCombiner dc = acc.getAssignedCombiner(); 568 return AccessController.doPrivileged(action, 569 preserveCombiner(dc, Reflection.getCallerClass())); 570 } 571 572 /** 573 * preserve the combiner across the doPrivileged call 574 */ 575 private static AccessControlContext preserveCombiner(DomainCombiner combiner, 576 Class<?> caller) 577 { 578 return createWrapper(combiner, caller, null, null, null); 579 } 580 581 /** 582 * Create a wrapper to contain the limited privilege scope data. 583 */ 584 private static AccessControlContext 585 createWrapper(DomainCombiner combiner, Class<?> caller, 586 AccessControlContext parent, AccessControlContext context, 587 Permission[] perms) 588 { 589 ProtectionDomain callerPD = getCallerPD(caller); 590 // check if caller is authorized to create context 591 if (context != null && !context.isAuthorized() && 592 System.getSecurityManager() != null && 593 !callerPD.impliesCreateAccessControlContext()) 594 { 595 return getInnocuousAcc(); 596 } else { 597 return new AccessControlContext(callerPD, combiner, parent, 598 context, perms); 599 } 600 } 601 602 private static class AccHolder { 603 // An AccessControlContext with no granted permissions. 604 // Only initialized on demand when getInnocuousAcc() is called. 605 static final AccessControlContext innocuousAcc = 606 new AccessControlContext(new ProtectionDomain[] { 607 new ProtectionDomain(null, null) }); 608 } 609 private static AccessControlContext getInnocuousAcc() { 610 return AccHolder.innocuousAcc; 611 } 612 613 private static ProtectionDomain getCallerPD(final Class <?> caller) { 614 ProtectionDomain callerPd = doPrivileged 615 (new PrivilegedAction<>() { 616 public ProtectionDomain run() { 617 return caller.getProtectionDomain(); 618 } 619 }); 620 621 return callerPd; 622 } 623 624 /** 625 * Performs the specified {@code PrivilegedExceptionAction} with 626 * privileges enabled and restricted by the specified 627 * {@code AccessControlContext}. The action is performed with the 628 * intersection of the permissions possessed by the caller's 629 * protection domain, and those possessed by the domains represented by the 630 * specified {@code AccessControlContext}. 631 * <p> 632 * If the action's {@code run} method throws an <i>unchecked</i> 633 * exception, it will propagate through this method. 634 * <p> 635 * If a security manager is installed and the specified 636 * {@code AccessControlContext} was not created by system code and the 637 * caller's {@code ProtectionDomain} has not been granted the 638 * {@literal "createAccessControlContext"} 639 * {@link java.security.SecurityPermission}, then the action is performed 640 * with no permissions. 641 * 642 * @param <T> the type of the value returned by the 643 * PrivilegedExceptionAction's {@code run} method. 644 * @param action the action to be performed 645 * @param context an <i>access control context</i> 646 * representing the restriction to be applied to the 647 * caller's domain's privileges before performing 648 * the specified action. If the context is 649 * {@code null}, then no additional restriction is applied. 650 * 651 * @return the value returned by the action's {@code run} method 652 * 653 * @exception PrivilegedActionException if the specified action's 654 * {@code run} method threw a <i>checked</i> exception 655 * @exception NullPointerException if the action is {@code null} 656 * 657 * @see #doPrivileged(PrivilegedAction) 658 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 659 */ 660 @CallerSensitive 661 public static native <T> T 662 doPrivileged(PrivilegedExceptionAction<T> action, 663 AccessControlContext context) 664 throws PrivilegedActionException; 665 666 667 /** 668 * Performs the specified {@code PrivilegedExceptionAction} with 669 * privileges enabled and restricted by the specified 670 * {@code AccessControlContext} and with a privilege scope limited by 671 * specified {@code Permission} arguments. 672 * 673 * The action is performed with the intersection of the permissions 674 * possessed by the caller's protection domain, and those possessed 675 * by the domains represented by the specified 676 * {@code AccessControlContext}. 677 * <p> 678 * If the action's {@code run} method throws an (unchecked) exception, 679 * it will propagate through this method. 680 * <p> 681 * If a security manager is installed and the specified 682 * {@code AccessControlContext} was not created by system code and the 683 * caller's {@code ProtectionDomain} has not been granted the 684 * {@literal "createAccessControlContext"} 685 * {@link java.security.SecurityPermission}, then the action is performed 686 * with no permissions. 687 * 688 * @param <T> the type of the value returned by the 689 * PrivilegedExceptionAction's {@code run} method. 690 * @param action the action to be performed. 691 * @param context an <i>access control context</i> 692 * representing the restriction to be applied to the 693 * caller's domain's privileges before performing 694 * the specified action. If the context is 695 * {@code null}, 696 * then no additional restriction is applied. 697 * @param perms the {@code Permission} arguments which limit the 698 * scope of the caller's privileges. The number of arguments 699 * is variable. 700 * 701 * @return the value returned by the action's {@code run} method. 702 * 703 * @throws PrivilegedActionException if the specified action's 704 * {@code run} method threw a <i>checked</i> exception 705 * @throws NullPointerException if action or perms or any element of 706 * perms is {@code null} 707 * 708 * @see #doPrivileged(PrivilegedAction) 709 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 710 * 711 * @since 1.8 712 */ 713 @CallerSensitive 714 public static <T> T doPrivileged(PrivilegedExceptionAction<T> action, 715 AccessControlContext context, Permission... perms) 716 throws PrivilegedActionException 717 { 718 AccessControlContext parent = getContext(); 719 if (perms == null) { 720 throw new NullPointerException("null permissions parameter"); 721 } 722 Class <?> caller = Reflection.getCallerClass(); 723 return AccessController.doPrivileged(action, createWrapper(null, caller, parent, context, perms)); 724 } 725 726 727 /** 728 * Performs the specified {@code PrivilegedExceptionAction} with 729 * privileges enabled and restricted by the specified 730 * {@code AccessControlContext} and with a privilege scope limited by 731 * specified {@code Permission} arguments. 732 * 733 * The action is performed with the intersection of the permissions 734 * possessed by the caller's protection domain, and those possessed 735 * by the domains represented by the specified 736 * {@code AccessControlContext}. 737 * <p> 738 * If the action's {@code run} method throws an (unchecked) exception, 739 * it will propagate through this method. 740 * 741 * <p> This method preserves the current AccessControlContext's 742 * DomainCombiner (which may be null) while the action is performed. 743 * <p> 744 * If a security manager is installed and the specified 745 * {@code AccessControlContext} was not created by system code and the 746 * caller's {@code ProtectionDomain} has not been granted the 747 * {@literal "createAccessControlContext"} 748 * {@link java.security.SecurityPermission}, then the action is performed 749 * with no permissions. 750 * 751 * @param <T> the type of the value returned by the 752 * PrivilegedExceptionAction's {@code run} method. 753 * @param action the action to be performed. 754 * @param context an <i>access control context</i> 755 * representing the restriction to be applied to the 756 * caller's domain's privileges before performing 757 * the specified action. If the context is 758 * {@code null}, 759 * then no additional restriction is applied. 760 * @param perms the {@code Permission} arguments which limit the 761 * scope of the caller's privileges. The number of arguments 762 * is variable. 763 * 764 * @return the value returned by the action's {@code run} method. 765 * 766 * @throws PrivilegedActionException if the specified action's 767 * {@code run} method threw a <i>checked</i> exception 768 * @throws NullPointerException if action or perms or any element of 769 * perms is {@code null} 770 * 771 * @see #doPrivileged(PrivilegedAction) 772 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 773 * @see java.security.DomainCombiner 774 * 775 * @since 1.8 776 */ 777 @CallerSensitive 778 public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action, 779 AccessControlContext context, 780 Permission... perms) 781 throws PrivilegedActionException 782 { 783 AccessControlContext parent = getContext(); 784 DomainCombiner dc = parent.getCombiner(); 785 if (dc == null && context != null) { 786 dc = context.getCombiner(); 787 } 788 if (perms == null) { 789 throw new NullPointerException("null permissions parameter"); 790 } 791 Class <?> caller = Reflection.getCallerClass(); 792 return AccessController.doPrivileged(action, createWrapper(dc, caller, 793 parent, context, perms)); 794 } 795 796 /** 797 * Returns the AccessControl context. i.e., it gets 798 * the protection domains of all the callers on the stack, 799 * starting at the first class with a non-null 800 * ProtectionDomain. 801 * 802 * @return the access control context based on the current stack or 803 * null if there was only privileged system code. 804 */ 805 806 private static native AccessControlContext getStackAccessControlContext(); 807 808 809 /** 810 * Returns the "inherited" AccessControl context. This is the context 811 * that existed when the thread was created. Package private so 812 * AccessControlContext can use it. 813 */ 814 815 static native AccessControlContext getInheritedAccessControlContext(); 816 817 /** 818 * This method takes a "snapshot" of the current calling context, which 819 * includes the current Thread's inherited AccessControlContext and any 820 * limited privilege scope, and places it in an AccessControlContext object. 821 * This context may then be checked at a later point, possibly in another thread. 822 * 823 * @see AccessControlContext 824 * 825 * @return the AccessControlContext based on the current context. 826 */ 827 828 public static AccessControlContext getContext() 829 { 830 AccessControlContext acc = getStackAccessControlContext(); 831 if (acc == null) { 832 // all we had was privileged system code. We don't want 833 // to return null though, so we construct a real ACC. 834 return new AccessControlContext(null, true); 835 } else { 836 return acc.optimize(); 837 } 838 } 839 840 /** 841 * Determines whether the access request indicated by the 842 * specified permission should be allowed or denied, based on 843 * the current AccessControlContext and security policy. 844 * This method quietly returns if the access request 845 * is permitted, or throws an AccessControlException otherwise. The 846 * getPermission method of the AccessControlException returns the 847 * {@code perm} Permission object instance. 848 * 849 * @param perm the requested permission. 850 * 851 * @exception AccessControlException if the specified permission 852 * is not permitted, based on the current security policy. 853 * @exception NullPointerException if the specified permission 854 * is {@code null} and is checked based on the 855 * security policy currently in effect. 856 */ 857 858 public static void checkPermission(Permission perm) 859 throws AccessControlException 860 { 861 //System.err.println("checkPermission "+perm); 862 //Thread.currentThread().dumpStack(); 863 864 if (perm == null) { 865 throw new NullPointerException("permission can't be null"); 866 } 867 868 AccessControlContext stack = getStackAccessControlContext(); 869 // if context is null, we had privileged system code on the stack. 870 if (stack == null) { 871 Debug debug = AccessControlContext.getDebug(); 872 boolean dumpDebug = false; 873 if (debug != null) { 874 dumpDebug = !Debug.isOn("codebase="); 875 dumpDebug &= !Debug.isOn("permission=") || 876 Debug.isOn("permission=" + perm.getClass().getCanonicalName()); 877 } 878 879 if (dumpDebug && Debug.isOn("stack")) { 880 Thread.dumpStack(); 881 } 882 883 if (dumpDebug && Debug.isOn("domain")) { 884 debug.println("domain (context is null)"); 885 } 886 887 if (dumpDebug) { 888 debug.println("access allowed "+perm); 889 } 890 return; 891 } 892 893 AccessControlContext acc = stack.optimize(); 894 acc.checkPermission(perm); 895 } 896 }