1 /* 2 * Copyright (c) 1997, 2019, 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 */ AccessController()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 doPrivileged(PrivilegedAction<T> action)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 doPrivilegedWithCombiner(PrivilegedAction<T> action)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 doPrivileged(PrivilegedAction<T> action, AccessControlContext context)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 doPrivileged(PrivilegedAction<T> action, AccessControlContext context, Permission... perms)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 DomainCombiner dc = (context == null) ? null : context.getCombiner(); 429 return AccessController.doPrivileged(action, createWrapper(dc, 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 doPrivilegedWithCombiner(PrivilegedAction<T> action, AccessControlContext context, Permission... perms)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 doPrivileged(PrivilegedExceptionAction<T> action)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 doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action)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 */ preserveCombiner(DomainCombiner combiner, Class<?> caller)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 createWrapper(DomainCombiner combiner, Class<?> caller, AccessControlContext parent, AccessControlContext context, Permission[] perms)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 ProtectionDomain nullPD = new ProtectionDomain(null, null); 597 return new AccessControlContext(new ProtectionDomain[] { nullPD }); 598 } else { 599 return new AccessControlContext(callerPD, combiner, parent, 600 context, perms); 601 } 602 } 603 getCallerPD(final Class <?> caller)604 private static ProtectionDomain getCallerPD(final Class <?> caller) { 605 ProtectionDomain callerPd = doPrivileged 606 (new PrivilegedAction<ProtectionDomain>() { 607 public ProtectionDomain run() { 608 return caller.getProtectionDomain(); 609 } 610 }); 611 612 return callerPd; 613 } 614 615 /** 616 * Performs the specified {@code PrivilegedExceptionAction} with 617 * privileges enabled and restricted by the specified 618 * {@code AccessControlContext}. The action is performed with the 619 * intersection of the permissions possessed by the caller's 620 * protection domain, and those possessed by the domains represented by the 621 * specified {@code AccessControlContext}. 622 * <p> 623 * If the action's {@code run} method throws an <i>unchecked</i> 624 * exception, it will propagate through this method. 625 * <p> 626 * If a security manager is installed and the specified 627 * {@code AccessControlContext} was not created by system code and the 628 * caller's {@code ProtectionDomain} has not been granted the 629 * {@literal "createAccessControlContext"} 630 * {@link java.security.SecurityPermission}, then the action is performed 631 * with no permissions. 632 * 633 * @param <T> the type of the value returned by the 634 * PrivilegedExceptionAction's {@code run} method. 635 * @param action the action to be performed 636 * @param context an <i>access control context</i> 637 * representing the restriction to be applied to the 638 * caller's domain's privileges before performing 639 * the specified action. If the context is 640 * {@code null}, then no additional restriction is applied. 641 * 642 * @return the value returned by the action's {@code run} method 643 * 644 * @exception PrivilegedActionException if the specified action's 645 * {@code run} method threw a <i>checked</i> exception 646 * @exception NullPointerException if the action is {@code null} 647 * 648 * @see #doPrivileged(PrivilegedAction) 649 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 650 */ 651 @CallerSensitive 652 public static native <T> T doPrivileged(PrivilegedExceptionAction<T> action, AccessControlContext context)653 doPrivileged(PrivilegedExceptionAction<T> action, 654 AccessControlContext context) 655 throws PrivilegedActionException; 656 657 658 /** 659 * Performs the specified {@code PrivilegedExceptionAction} with 660 * privileges enabled and restricted by the specified 661 * {@code AccessControlContext} and with a privilege scope limited by 662 * specified {@code Permission} arguments. 663 * 664 * The action is performed with the intersection of the permissions 665 * possessed by the caller's protection domain, and those possessed 666 * by the domains represented by the specified 667 * {@code AccessControlContext}. 668 * <p> 669 * If the action's {@code run} method throws an (unchecked) exception, 670 * it will propagate through this method. 671 * <p> 672 * If a security manager is installed and the specified 673 * {@code AccessControlContext} was not created by system code and the 674 * caller's {@code ProtectionDomain} has not been granted the 675 * {@literal "createAccessControlContext"} 676 * {@link java.security.SecurityPermission}, then the action is performed 677 * with no permissions. 678 * 679 * @param <T> the type of the value returned by the 680 * PrivilegedExceptionAction's {@code run} method. 681 * @param action the action to be performed. 682 * @param context an <i>access control context</i> 683 * representing the restriction to be applied to the 684 * caller's domain's privileges before performing 685 * the specified action. If the context is 686 * {@code null}, 687 * then no additional restriction is applied. 688 * @param perms the {@code Permission} arguments which limit the 689 * scope of the caller's privileges. The number of arguments 690 * is variable. 691 * 692 * @return the value returned by the action's {@code run} method. 693 * 694 * @throws PrivilegedActionException if the specified action's 695 * {@code run} method threw a <i>checked</i> exception 696 * @throws NullPointerException if action or perms or any element of 697 * perms is {@code null} 698 * 699 * @see #doPrivileged(PrivilegedAction) 700 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 701 * 702 * @since 1.8 703 */ 704 @CallerSensitive doPrivileged(PrivilegedExceptionAction<T> action, AccessControlContext context, Permission... perms)705 public static <T> T doPrivileged(PrivilegedExceptionAction<T> action, 706 AccessControlContext context, Permission... perms) 707 throws PrivilegedActionException 708 { 709 AccessControlContext parent = getContext(); 710 if (perms == null) { 711 throw new NullPointerException("null permissions parameter"); 712 } 713 Class <?> caller = Reflection.getCallerClass(); 714 DomainCombiner dc = (context == null) ? null : context.getCombiner(); 715 return AccessController.doPrivileged(action, createWrapper(dc, caller, parent, context, perms)); 716 } 717 718 719 /** 720 * Performs the specified {@code PrivilegedExceptionAction} with 721 * privileges enabled and restricted by the specified 722 * {@code AccessControlContext} and with a privilege scope limited by 723 * specified {@code Permission} arguments. 724 * 725 * The action is performed with the intersection of the permissions 726 * possessed by the caller's protection domain, and those possessed 727 * by the domains represented by the specified 728 * {@code AccessControlContext}. 729 * <p> 730 * If the action's {@code run} method throws an (unchecked) exception, 731 * it will propagate through this method. 732 * 733 * <p> This method preserves the current AccessControlContext's 734 * DomainCombiner (which may be null) while the action is performed. 735 * <p> 736 * If a security manager is installed and the specified 737 * {@code AccessControlContext} was not created by system code and the 738 * caller's {@code ProtectionDomain} has not been granted the 739 * {@literal "createAccessControlContext"} 740 * {@link java.security.SecurityPermission}, then the action is performed 741 * with no permissions. 742 * 743 * @param <T> the type of the value returned by the 744 * PrivilegedExceptionAction's {@code run} method. 745 * @param action the action to be performed. 746 * @param context an <i>access control context</i> 747 * representing the restriction to be applied to the 748 * caller's domain's privileges before performing 749 * the specified action. If the context is 750 * {@code null}, 751 * then no additional restriction is applied. 752 * @param perms the {@code Permission} arguments which limit the 753 * scope of the caller's privileges. The number of arguments 754 * is variable. 755 * 756 * @return the value returned by the action's {@code run} method. 757 * 758 * @throws PrivilegedActionException if the specified action's 759 * {@code run} method threw a <i>checked</i> exception 760 * @throws NullPointerException if action or perms or any element of 761 * perms is {@code null} 762 * 763 * @see #doPrivileged(PrivilegedAction) 764 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 765 * @see java.security.DomainCombiner 766 * 767 * @since 1.8 768 */ 769 @CallerSensitive doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action, AccessControlContext context, Permission... perms)770 public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action, 771 AccessControlContext context, 772 Permission... perms) 773 throws PrivilegedActionException 774 { 775 AccessControlContext parent = getContext(); 776 DomainCombiner dc = parent.getCombiner(); 777 if (dc == null && context != null) { 778 dc = context.getCombiner(); 779 } 780 if (perms == null) { 781 throw new NullPointerException("null permissions parameter"); 782 } 783 Class <?> caller = Reflection.getCallerClass(); 784 return AccessController.doPrivileged(action, createWrapper(dc, caller, 785 parent, context, perms)); 786 } 787 788 /** 789 * Returns the AccessControl context. i.e., it gets 790 * the protection domains of all the callers on the stack, 791 * starting at the first class with a non-null 792 * ProtectionDomain. 793 * 794 * @return the access control context based on the current stack or 795 * null if there was only privileged system code. 796 */ 797 getStackAccessControlContext()798 private static native AccessControlContext getStackAccessControlContext(); 799 800 801 /** 802 * Returns the "inherited" AccessControl context. This is the context 803 * that existed when the thread was created. Package private so 804 * AccessControlContext can use it. 805 */ 806 getInheritedAccessControlContext()807 static native AccessControlContext getInheritedAccessControlContext(); 808 809 /** 810 * This method takes a "snapshot" of the current calling context, which 811 * includes the current Thread's inherited AccessControlContext and any 812 * limited privilege scope, and places it in an AccessControlContext object. 813 * This context may then be checked at a later point, possibly in another thread. 814 * 815 * @see AccessControlContext 816 * 817 * @return the AccessControlContext based on the current context. 818 */ 819 getContext()820 public static AccessControlContext getContext() 821 { 822 AccessControlContext acc = getStackAccessControlContext(); 823 if (acc == null) { 824 // all we had was privileged system code. We don't want 825 // to return null though, so we construct a real ACC. 826 return new AccessControlContext(null, true); 827 } else { 828 return acc.optimize(); 829 } 830 } 831 832 /** 833 * Determines whether the access request indicated by the 834 * specified permission should be allowed or denied, based on 835 * the current AccessControlContext and security policy. 836 * This method quietly returns if the access request 837 * is permitted, or throws an AccessControlException otherwise. The 838 * getPermission method of the AccessControlException returns the 839 * {@code perm} Permission object instance. 840 * 841 * @param perm the requested permission. 842 * 843 * @exception AccessControlException if the specified permission 844 * is not permitted, based on the current security policy. 845 * @exception NullPointerException if the specified permission 846 * is {@code null} and is checked based on the 847 * security policy currently in effect. 848 */ 849 checkPermission(Permission perm)850 public static void checkPermission(Permission perm) 851 throws AccessControlException 852 { 853 //System.err.println("checkPermission "+perm); 854 //Thread.currentThread().dumpStack(); 855 856 if (perm == null) { 857 throw new NullPointerException("permission can't be null"); 858 } 859 860 AccessControlContext stack = getStackAccessControlContext(); 861 // if context is null, we had privileged system code on the stack. 862 if (stack == null) { 863 Debug debug = AccessControlContext.getDebug(); 864 boolean dumpDebug = false; 865 if (debug != null) { 866 dumpDebug = !Debug.isOn("codebase="); 867 dumpDebug &= !Debug.isOn("permission=") || 868 Debug.isOn("permission=" + perm.getClass().getCanonicalName()); 869 } 870 871 if (dumpDebug && Debug.isOn("stack")) { 872 Thread.dumpStack(); 873 } 874 875 if (dumpDebug && Debug.isOn("domain")) { 876 debug.println("domain (context is null)"); 877 } 878 879 if (dumpDebug) { 880 debug.println("access allowed "+perm); 881 } 882 return; 883 } 884 885 AccessControlContext acc = stack.optimize(); 886 acc.checkPermission(perm); 887 } 888 } 889