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