1 /* 2 * Copyright (c) 2001, 2015, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.BufferedOutputStream; 25 import java.io.File; 26 import java.io.FileInputStream; 27 import java.io.FileOutputStream; 28 import java.io.IOException; 29 import java.security.AccessControlContext; 30 import java.security.AccessControlException; 31 import java.security.AccessController; 32 import java.security.PrivilegedAction; 33 import java.security.PrivilegedActionException; 34 import java.security.PrivilegedExceptionAction; 35 import java.util.ArrayList; 36 import java.util.Arrays; 37 import java.util.Collections; 38 import java.util.List; 39 import java.util.jar.JarEntry; 40 import java.util.jar.JarOutputStream; 41 import java.util.jar.Manifest; 42 import javax.security.auth.Subject; 43 import javax.security.auth.x500.X500Principal; 44 import jdk.testlibrary.ProcessTools; 45 46 /** 47 * @test 48 * @bug 8048147 49 * @summary Check if proper AccessControlException is thrown 50 * in case of nested Subject.doAs() invocations 51 * when one of protection domains doesn't have permissions 52 * 53 * @library /lib/testlibrary 54 * 55 * @run main NestedActions jar NestedActionsACE.jar 56 * NestedActionsACE.class Utils.class 57 * @run main NestedActions jar NestedActionsPAE.jar 58 * NestedActionsPAE.class Utils.class 59 * @run main NestedActions jar NestedActionsOnePrincipal.jar 60 * NestedActionsOnePrincipal.class Utils.class 61 * @run main NestedActions jar NestedActionsTwoPrincipals.jar 62 * NestedActionsTwoPrincipals.class Utils.class 63 * @run main NestedActions jar WriteToFileAction.jar 64 * WriteToFileAction.class 65 * @run main NestedActions jar WriteToFileNegativeAction.jar 66 * WriteToFileNegativeAction.class 67 * @run main NestedActions jar WriteToFileExceptionAction.jar 68 * WriteToFileExceptionAction.class 69 * @run main NestedActions jar ReadFromFileAction.jar 70 * ReadFromFileAction.class 71 * @run main NestedActions jar ReadFromFileNegativeAction.jar 72 * ReadFromFileNegativeAction.class 73 * @run main NestedActions jar ReadFromFileExceptionAction.jar 74 * ReadFromFileExceptionAction.class 75 * @run main NestedActions jar ReadPropertyAction.jar 76 * ReadPropertyAction.class 77 * @run main NestedActions jar ReadPropertyNegativeAction.jar 78 * ReadPropertyNegativeAction.class 79 * @run main NestedActions jar ReadPropertyExceptionAction.jar 80 * ReadPropertyExceptionAction.class ReadPropertyException.class 81 * 82 * @run main NestedActions NestedActionsACE policy.expect.ace 83 * NestedActionsACE.jar WriteToFileNegativeAction.jar 84 * ReadFromFileNegativeAction.jar ReadPropertyNegativeAction.jar 85 * @run main NestedActions NestedActionsPAE policy.expect.pae 86 * NestedActionsPAE.jar WriteToFileExceptionAction.jar 87 * ReadFromFileExceptionAction.jar ReadPropertyExceptionAction.jar 88 * @run main NestedActions NestedActionsOnePrincipal policy.one.principal 89 * NestedActionsOnePrincipal.jar WriteToFileAction.jar 90 * ReadFromFileAction.jar ReadPropertyAction.jar 91 * @run main NestedActions NestedActionsTwoPrincipals policy.two.principals 92 * NestedActionsTwoPrincipals.jar WriteToFileAction.jar 93 * ReadFromFileAction.jar ReadPropertyAction.jar 94 */ 95 public class NestedActions { 96 97 static final String file = "NestedActions.tmp"; 98 static final String PS = System.getProperty("path.separator"); 99 static final String FS = System.getProperty("file.separator"); 100 static final String TEST_CLASSES = System.getProperty("test.classes"); 101 static final String TEST_SOURCES = System.getProperty("test.src"); 102 static final String JAVA_OPTS = System.getProperty("test.java.opts"); 103 static final String JAVA = System.getProperty("java.home") 104 + FS + "bin" + FS + "java"; 105 106 public static void main(String[] args) throws IOException { 107 if (args.length > 0) { 108 if ("jar".equals(args[0]) && args.length > 2) { 109 createJar(args[1], 110 Arrays.copyOfRange(args, 2, args.length)); 111 } else { 112 runJava(args); 113 } 114 } else { 115 throw new RuntimeException("Wrong parameters"); 116 } 117 } 118 119 static void createJar(String dest, String... files) throws IOException { 120 System.out.println("Create " + dest + " with the following content:"); 121 try (JarOutputStream jos = new JarOutputStream( 122 new FileOutputStream(dest), new Manifest())) { 123 for (String file : files) { 124 System.out.println(" " + file); 125 jos.putNextEntry(new JarEntry(file)); 126 try (FileInputStream fis = new FileInputStream( 127 TEST_CLASSES + FS + file)) { 128 fis.transferTo(jos); 129 } 130 } 131 } 132 } 133 134 static void runJava(String[] args) { 135 if (args == null || args.length < 3) { 136 throw new IllegalArgumentException("wrong parameters"); 137 } 138 139 List<String> cmds = new ArrayList<>(); 140 cmds.add(JAVA); 141 StringBuilder sb = new StringBuilder(); 142 cmds.add("-classpath"); 143 for (int i=2; i<args.length; i++) { 144 sb.append(args[i]).append(PS); 145 } 146 cmds.add(sb.toString()); 147 if (JAVA_OPTS != null && !JAVA_OPTS.isEmpty()) { 148 Collections.addAll(cmds, JAVA_OPTS.trim().split("\\s+")); 149 } 150 cmds.add("-Djava.security.manager"); 151 cmds.add("-Djava.security.policy=" + TEST_SOURCES + FS + args[1]); 152 cmds.add(args[0]); 153 try { 154 ProcessTools.executeCommand(cmds.toArray(new String[cmds.size()])) 155 .shouldHaveExitValue(0); 156 } catch (Throwable e) { 157 throw new RuntimeException(e); 158 } 159 } 160 } 161 162 /** 163 * Test for nested Subject.doAs() invocation: 164 * 165 * WriteToFileAction (CN=Duke principal) -> 166 * ReadFromFileAction (CN=Duke principal) -> 167 * ReadPropertyAction (CN=Duke principal) 168 * 169 * The test expects AccessControllException. 170 */ 171 class NestedActionsACE { 172 173 public static void main(String args[]) { 174 Subject subject = new Subject(); 175 subject.getPrincipals().add(new X500Principal("CN=Duke")); 176 WriteToFileNegativeAction writeToFile 177 = new WriteToFileNegativeAction(NestedActions.file); 178 Subject.doAs(subject, writeToFile); 179 } 180 } 181 182 /** 183 * Test for nested Subject.doAs() invocation: 184 * 185 * WriteToFileAction (CN=Duke principal) -> 186 * ReadFromFileAction (CN=Duke principal) -> 187 * ReadPropertyAction (CN=Duke principal) 188 * 189 * The test expects PrivilegedActionException 190 * that caused by AccessControlEception. 191 */ 192 class NestedActionsPAE { 193 194 public static void main(String args[]) { 195 Subject subject = new Subject(); 196 subject.getPrincipals().add(new X500Principal("CN=Duke")); 197 try { 198 WriteToFileExceptionAction writeToFile = 199 new WriteToFileExceptionAction(NestedActions.file); 200 Subject.doAs(subject, writeToFile); 201 throw new RuntimeException( 202 "Test failed: no PrivilegedActionException thrown"); 203 } catch (PrivilegedActionException pae) { 204 System.out.println( 205 "PrivilegedActionException thrown as expected: " 206 + pae); 207 208 // check if AccessControlException caused PrivilegedActionException 209 Throwable exception = pae.getException(); 210 do { 211 if (!(exception instanceof PrivilegedActionException)) { 212 break; 213 } 214 exception = ((PrivilegedActionException) exception). 215 getException(); 216 } while (true); 217 218 if (!(exception instanceof ReadPropertyException)) { 219 throw new RuntimeException( 220 "Test failed: PrivilegedActionException " 221 + "was not caused by ReadPropertyException"); 222 } 223 224 exception = exception.getCause(); 225 if (!(exception instanceof AccessControlException)) { 226 throw new RuntimeException( 227 "Test failed: PrivilegedActionException " 228 + "was not caused by ReadPropertyException"); 229 } 230 231 System.out.println( 232 "Test passed: PrivilegedActionException " 233 + "was caused by AccessControlException"); 234 } 235 } 236 } 237 238 /** 239 * Test for nested Subject.doAs() invocation: 240 * 241 * WriteToFileAction (CN=Duke principal) -> 242 * ReadFromFileAction (CN=Duke principal) -> 243 * ReadPropertyAction (CN=Duke principal) 244 */ 245 class NestedActionsOnePrincipal { 246 247 public static void main(String args[]) { 248 Subject subject = new Subject(); 249 subject.getPrincipals().add(new X500Principal("CN=Duke")); 250 WriteToFileAction writeToFile = 251 new WriteToFileAction(NestedActions.file); 252 Subject.doAs(subject, writeToFile); 253 } 254 } 255 256 /** 257 * Test for nested Subject.doAs() invocation: 258 * 259 * WriteToFileAction (CN=Duke principal) -> 260 * ReadFromFileAction (CN=Duke principal) -> 261 * ReadPropertyAction (CN=Java principal) 262 */ 263 class NestedActionsTwoPrincipals { 264 265 public static void main(String args[]) { 266 Subject subject = new Subject(); 267 subject.getPrincipals().add(new X500Principal("CN=Duke")); 268 Subject anotherSubject = new Subject(); 269 anotherSubject.getPrincipals().add(new X500Principal("CN=Java")); 270 ReadFromFileAction readFromFile 271 = new ReadFromFileAction(NestedActions.file, anotherSubject); 272 WriteToFileAction writeToFile 273 = new WriteToFileAction(NestedActions.file, readFromFile); 274 Subject.doAs(subject, writeToFile); 275 } 276 } 277 278 /** 279 * Helper class. 280 */ 281 class Utils { 282 283 static void readFile(String filename) { 284 System.out.println("ReadFromFileAction: try to read " + filename); 285 AccessControlContext acc = AccessController.getContext(); 286 Subject subject = Subject.getSubject(acc); 287 System.out.println("principals = " + subject.getPrincipals()); 288 try (FileInputStream fis = new FileInputStream(filename)) { 289 // do nothing 290 } catch (IOException e) { 291 throw new RuntimeException("Unexpected IOException", e); 292 } 293 } 294 295 static void writeFile(String filename) { 296 System.out.println("WriteToFileAction: try to write to " + filename); 297 AccessControlContext acc = AccessController.getContext(); 298 Subject subject = Subject.getSubject(acc); 299 System.out.println("principals = " + subject.getPrincipals()); 300 try (BufferedOutputStream bos = new BufferedOutputStream( 301 new FileOutputStream(filename))) { 302 bos.write(0); 303 bos.flush(); 304 } catch (IOException e) { 305 throw new RuntimeException("Unexpected IOException", e); 306 } 307 } 308 309 } 310 311 class WriteToFileAction implements PrivilegedAction { 312 313 private final String filename; 314 private final PrivilegedAction nextAction; 315 316 WriteToFileAction(String filename, PrivilegedAction nextAction) { 317 this.filename = filename; 318 this.nextAction = nextAction; 319 } 320 321 WriteToFileAction(String filename) { 322 this(filename, new ReadFromFileAction(filename)); 323 } 324 325 @Override 326 public Object run() { 327 Utils.writeFile(filename); 328 AccessControlContext acc = AccessController.getContext(); 329 Subject subject = Subject.getSubject(acc); 330 return Subject.doAs(subject, nextAction); 331 } 332 333 } 334 335 class ReadFromFileAction implements PrivilegedAction { 336 337 private final String filename; 338 private final Subject anotherSubject; 339 340 ReadFromFileAction(String filename) { 341 this(filename, null); 342 } 343 344 ReadFromFileAction(String filename, Subject anotherSubject) { 345 this.filename = filename; 346 this.anotherSubject = anotherSubject; 347 } 348 349 @Override 350 public Object run() { 351 Utils.readFile(filename); 352 353 AccessControlContext acc = AccessController.getContext(); 354 Subject subject = Subject.getSubject(acc); 355 ReadPropertyAction readProperty = new ReadPropertyAction(); 356 if (anotherSubject != null) { 357 return Subject.doAs(anotherSubject, readProperty); 358 } else { 359 return Subject.doAs(subject, readProperty); 360 } 361 } 362 363 } 364 365 class ReadPropertyAction implements PrivilegedAction { 366 367 @Override 368 public java.lang.Object run() { 369 System.out.println("ReadPropertyAction: " 370 + "try to read 'java.class.path' property"); 371 372 AccessControlContext acc = AccessController.getContext(); 373 Subject s = Subject.getSubject(acc); 374 System.out.println("principals = " + s.getPrincipals()); 375 System.out.println("java.class.path = " 376 + System.getProperty("java.class.path")); 377 378 return null; 379 } 380 381 } 382 383 class WriteToFileNegativeAction implements PrivilegedAction { 384 385 private final String filename; 386 387 public WriteToFileNegativeAction(String filename) { 388 this.filename = filename; 389 } 390 391 @Override 392 public Object run() { 393 AccessControlContext acc = AccessController.getContext(); 394 Subject subject = Subject.getSubject(acc); 395 System.out.println("principals = " + subject.getPrincipals()); 396 397 try { 398 Utils.writeFile(filename); 399 new File(filename).delete(); 400 throw new RuntimeException( 401 "Test failed: no AccessControlException thrown"); 402 } catch (AccessControlException ace) { 403 System.out.println( 404 "AccessControlException thrown as expected: " 405 + ace.getMessage()); 406 } 407 408 ReadFromFileNegativeAction readFromFile 409 = new ReadFromFileNegativeAction(filename); 410 return Subject.doAs(subject, readFromFile); 411 } 412 413 } 414 415 class ReadFromFileNegativeAction implements PrivilegedAction { 416 417 private final String filename; 418 419 public ReadFromFileNegativeAction(String filename) { 420 this.filename = filename; 421 } 422 423 @Override 424 public Object run() { 425 AccessControlContext acc = AccessController.getContext(); 426 Subject subject = Subject.getSubject(acc); 427 System.out.println("principals = " + subject.getPrincipals()); 428 429 try { 430 Utils.readFile(filename); 431 throw new RuntimeException( 432 "Test failed: no AccessControlException thrown"); 433 } catch (AccessControlException ace) { 434 System.out.println( 435 "AccessControlException thrown as expected: " 436 + ace.getMessage()); 437 } 438 439 ReadPropertyNegativeAction readProperty = 440 new ReadPropertyNegativeAction(); 441 return Subject.doAs(subject, readProperty); 442 } 443 444 } 445 446 class ReadPropertyNegativeAction implements PrivilegedAction { 447 448 @Override 449 public java.lang.Object run() { 450 System.out.println("Try to read 'java.class.path' property"); 451 452 AccessControlContext acc = AccessController.getContext(); 453 Subject s = Subject.getSubject(acc); 454 System.out.println("principals = " + s.getPrincipals()); 455 456 try { 457 System.out.println("java.class.path = " 458 + System.getProperty("java.class.path")); 459 throw new RuntimeException( 460 "Test failed: no AccessControlException thrown"); 461 } catch (AccessControlException ace) { 462 System.out.println( 463 "AccessControlException thrown as expected: " 464 + ace.getMessage()); 465 } 466 467 return null; 468 } 469 470 } 471 472 class WriteToFileExceptionAction implements PrivilegedExceptionAction { 473 474 private final String filename; 475 476 WriteToFileExceptionAction(String filename) { 477 this.filename = filename; 478 } 479 480 @Override 481 public Object run() throws Exception { 482 Utils.writeFile(filename); 483 AccessControlContext acc = AccessController.getContext(); 484 Subject subject = Subject.getSubject(acc); 485 ReadFromFileExceptionAction readFromFile = 486 new ReadFromFileExceptionAction(filename); 487 return Subject.doAs(subject, readFromFile); 488 } 489 490 } 491 492 class ReadFromFileExceptionAction implements PrivilegedExceptionAction { 493 494 private final String filename; 495 496 ReadFromFileExceptionAction(String filename) { 497 this.filename = filename; 498 } 499 500 @Override 501 public Object run() throws Exception { 502 Utils.readFile(filename); 503 AccessControlContext acc = AccessController.getContext(); 504 Subject subject = Subject.getSubject(acc); 505 ReadPropertyExceptionAction readProperty = 506 new ReadPropertyExceptionAction(); 507 return Subject.doAs(subject, readProperty); 508 } 509 510 } 511 512 class ReadPropertyExceptionAction implements PrivilegedExceptionAction { 513 514 @Override 515 public java.lang.Object run() throws Exception { 516 System.out.println("Try to read 'java.class.path' property"); 517 518 AccessControlContext acc = AccessController.getContext(); 519 Subject s = Subject.getSubject(acc); 520 System.out.println("principals = " + s.getPrincipals()); 521 522 try { 523 System.out.println("java.class.path = " 524 + System.getProperty("java.class.path")); 525 throw new RuntimeException( 526 "Test failed: no AccessControlException thrown"); 527 } catch (AccessControlException ace) { 528 System.out.println( 529 "AccessControlException thrown as expected: " 530 + ace.getMessage()); 531 throw new ReadPropertyException(ace); 532 } 533 } 534 535 } 536 537 class ReadPropertyException extends Exception { 538 539 ReadPropertyException(Throwable cause) { 540 super(cause); 541 } 542 }