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