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