blob: f02b2ff47dc4390ce157231818bb398bfd79b255 [file] [log] [blame]
/*
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights
* reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.testlibrary.ProcessTools;
import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;
import java.io.*;
import java.security.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
/**
* @test
* @bug 8048147
* @summary Check if proper AccessControlException is thrown
* in case of nested Subject.doAs() invocations
* when one of protection domains doesn't have permissions
*
* @library /lib/testlibrary
*
* @run main NestedActions jar NestedActionsACE.jar
* NestedActionsACE.class Utils.class
* @run main NestedActions jar NestedActionsPAE.jar
* NestedActionsPAE.class Utils.class
* @run main NestedActions jar NestedActionsOnePrincipal.jar
* NestedActionsOnePrincipal.class Utils.class
* @run main NestedActions jar NestedActionsTwoPrincipals.jar
* NestedActionsTwoPrincipals.class Utils.class
* @run main NestedActions jar WriteToFileAction.jar
* WriteToFileAction.class
* @run main NestedActions jar WriteToFileNegativeAction.jar
* WriteToFileNegativeAction.class
* @run main NestedActions jar WriteToFileExceptionAction.jar
* WriteToFileExceptionAction.class
* @run main NestedActions jar ReadFromFileAction.jar
* ReadFromFileAction.class
* @run main NestedActions jar ReadFromFileNegativeAction.jar
* ReadFromFileNegativeAction.class
* @run main NestedActions jar ReadFromFileExceptionAction.jar
* ReadFromFileExceptionAction.class
* @run main NestedActions jar ReadPropertyAction.jar
* ReadPropertyAction.class
* @run main NestedActions jar ReadPropertyNegativeAction.jar
* ReadPropertyNegativeAction.class
* @run main NestedActions jar ReadPropertyExceptionAction.jar
* ReadPropertyExceptionAction.class ReadPropertyException.class
*
* @run main NestedActions NestedActionsACE policy.expect.ace
* NestedActionsACE.jar WriteToFileNegativeAction.jar
* ReadFromFileNegativeAction.jar ReadPropertyNegativeAction.jar
* @run main NestedActions NestedActionsPAE policy.expect.pae
* NestedActionsPAE.jar WriteToFileExceptionAction.jar
* ReadFromFileExceptionAction.jar ReadPropertyExceptionAction.jar
* @run main NestedActions NestedActionsOnePrincipal policy.one.principal
* NestedActionsOnePrincipal.jar WriteToFileAction.jar
* ReadFromFileAction.jar ReadPropertyAction.jar
* @run main NestedActions NestedActionsTwoPrincipals policy.two.principals
* NestedActionsTwoPrincipals.jar WriteToFileAction.jar
* ReadFromFileAction.jar ReadPropertyAction.jar
*/
public class NestedActions {
static final String file = "NestedActions.tmp";
static final String PS = System.getProperty("path.separator");
static final String FS = System.getProperty("file.separator");
static final String TEST_CLASSES = System.getProperty("test.classes");
static final String TEST_SOURCES = System.getProperty("test.src");
static final String JAVA_OPTS = System.getProperty("test.java.opts");
static final String JAVA = System.getProperty("java.home")
+ FS + "bin" + FS + "java";
public static void main(String[] args) throws IOException {
if (args.length > 0) {
if ("jar".equals(args[0]) && args.length > 2) {
createJar(args[1],
Arrays.copyOfRange(args, 2, args.length));
} else {
runJava(args);
}
} else {
throw new RuntimeException("Wrong parameters");
}
}
static void createJar(String dest, String... files) throws IOException {
System.out.println("Create " + dest + " with the following content:");
try (JarOutputStream jos = new JarOutputStream(
new FileOutputStream(dest), new Manifest())) {
for (String file : files) {
System.out.println(" " + file);
jos.putNextEntry(new JarEntry(file));
try (FileInputStream fis = new FileInputStream(
TEST_CLASSES + FS + file)) {
byte[] buffer = new byte[1024];
int read;
while ((read = fis.read(buffer, 0, buffer.length)) > 0) {
jos.write(buffer, 0, read);
}
}
}
}
}
static void runJava(String[] args) {
if (args == null || args.length < 3) {
throw new IllegalArgumentException("wrong parameters");
}
List<String> cmds = new ArrayList<>();
cmds.add(JAVA);
StringBuilder sb = new StringBuilder();
cmds.add("-classpath");
for (int i=2; i<args.length; i++) {
sb.append(args[i]).append(PS);
}
cmds.add(sb.toString());
if (JAVA_OPTS != null && !JAVA_OPTS.isEmpty()) {
Collections.addAll(cmds, JAVA_OPTS.trim().split("\\s+"));
}
cmds.add("-Djava.security.manager");
cmds.add("-Djava.security.policy=" + TEST_SOURCES + FS + args[1]);
cmds.add(args[0]);
try {
ProcessTools.executeCommand(cmds.toArray(new String[cmds.size()]))
.shouldHaveExitValue(0);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
/**
* Test for nested Subject.doAs() invocation:
*
* WriteToFileAction (CN=Duke principal) ->
* ReadFromFileAction (CN=Duke principal) ->
* ReadPropertyAction (CN=Duke principal)
*
* The test expects AccessControllException.
*/
class NestedActionsACE {
public static void main(String args[]) {
Subject subject = new Subject();
subject.getPrincipals().add(new X500Principal("CN=Duke"));
WriteToFileNegativeAction writeToFile
= new WriteToFileNegativeAction(NestedActions.file);
Subject.doAs(subject, writeToFile);
}
}
/**
* Test for nested Subject.doAs() invocation:
*
* WriteToFileAction (CN=Duke principal) ->
* ReadFromFileAction (CN=Duke principal) ->
* ReadPropertyAction (CN=Duke principal)
*
* The test expects PrivilegedActionException
* that caused by AccessControlEception.
*/
class NestedActionsPAE {
public static void main(String args[]) {
Subject subject = new Subject();
subject.getPrincipals().add(new X500Principal("CN=Duke"));
try {
WriteToFileExceptionAction writeToFile =
new WriteToFileExceptionAction(NestedActions.file);
Subject.doAs(subject, writeToFile);
throw new RuntimeException(
"Test failed: no PrivilegedActionException thrown");
} catch (PrivilegedActionException pae) {
System.out.println(
"PrivilegedActionException thrown as expected: "
+ pae);
// check if AccessControlException caused PrivilegedActionException
Throwable exception = pae.getException();
do {
if (!(exception instanceof PrivilegedActionException)) {
break;
}
exception = ((PrivilegedActionException) exception).
getException();
} while (true);
if (!(exception instanceof ReadPropertyException)) {
throw new RuntimeException(
"Test failed: PrivilegedActionException "
+ "was not caused by ReadPropertyException");
}
exception = exception.getCause();
if (!(exception instanceof AccessControlException)) {
throw new RuntimeException(
"Test failed: PrivilegedActionException "
+ "was not caused by ReadPropertyException");
}
System.out.println(
"Test passed: PrivilegedActionException "
+ "was caused by AccessControlException");
}
}
}
/**
* Test for nested Subject.doAs() invocation:
*
* WriteToFileAction (CN=Duke principal) ->
* ReadFromFileAction (CN=Duke principal) ->
* ReadPropertyAction (CN=Duke principal)
*/
class NestedActionsOnePrincipal {
public static void main(String args[]) {
Subject subject = new Subject();
subject.getPrincipals().add(new X500Principal("CN=Duke"));
WriteToFileAction writeToFile =
new WriteToFileAction(NestedActions.file);
Subject.doAs(subject, writeToFile);
}
}
/**
* Test for nested Subject.doAs() invocation:
*
* WriteToFileAction (CN=Duke principal) ->
* ReadFromFileAction (CN=Duke principal) ->
* ReadPropertyAction (CN=Java principal)
*/
class NestedActionsTwoPrincipals {
public static void main(String args[]) {
Subject subject = new Subject();
subject.getPrincipals().add(new X500Principal("CN=Duke"));
Subject anotherSubject = new Subject();
anotherSubject.getPrincipals().add(new X500Principal("CN=Java"));
ReadFromFileAction readFromFile
= new ReadFromFileAction(NestedActions.file, anotherSubject);
WriteToFileAction writeToFile
= new WriteToFileAction(NestedActions.file, readFromFile);
Subject.doAs(subject, writeToFile);
}
}
/**
* Helper class.
*/
class Utils {
static void readFile(String filename) {
System.out.println("ReadFromFileAction: try to read " + filename);
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
System.out.println("principals = " + subject.getPrincipals());
try (FileInputStream fis = new FileInputStream(filename)) {
// do nothing
} catch (IOException e) {
throw new RuntimeException("Unexpected IOException", e);
}
}
static void writeFile(String filename) {
System.out.println("WriteToFileAction: try to write to " + filename);
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
System.out.println("principals = " + subject.getPrincipals());
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(filename))) {
bos.write(0);
bos.flush();
} catch (IOException e) {
throw new RuntimeException("Unexpected IOException", e);
}
}
}
class WriteToFileAction implements PrivilegedAction {
private final String filename;
private final PrivilegedAction nextAction;
WriteToFileAction(String filename, PrivilegedAction nextAction) {
this.filename = filename;
this.nextAction = nextAction;
}
WriteToFileAction(String filename) {
this(filename, new ReadFromFileAction(filename));
}
@Override
public Object run() {
Utils.writeFile(filename);
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
return Subject.doAs(subject, nextAction);
}
}
class ReadFromFileAction implements PrivilegedAction {
private final String filename;
private final Subject anotherSubject;
ReadFromFileAction(String filename) {
this(filename, null);
}
ReadFromFileAction(String filename, Subject anotherSubject) {
this.filename = filename;
this.anotherSubject = anotherSubject;
}
@Override
public Object run() {
Utils.readFile(filename);
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
ReadPropertyAction readProperty = new ReadPropertyAction();
if (anotherSubject != null) {
return Subject.doAs(anotherSubject, readProperty);
} else {
return Subject.doAs(subject, readProperty);
}
}
}
class ReadPropertyAction implements PrivilegedAction {
@Override
public java.lang.Object run() {
System.out.println("ReadPropertyAction: "
+ "try to read 'java.class.path' property");
AccessControlContext acc = AccessController.getContext();
Subject s = Subject.getSubject(acc);
System.out.println("principals = " + s.getPrincipals());
System.out.println("java.class.path = "
+ System.getProperty("java.class.path"));
return null;
}
}
class WriteToFileNegativeAction implements PrivilegedAction {
private final String filename;
public WriteToFileNegativeAction(String filename) {
this.filename = filename;
}
@Override
public Object run() {
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
System.out.println("principals = " + subject.getPrincipals());
try {
Utils.writeFile(filename);
new File(filename).delete();
throw new RuntimeException(
"Test failed: no AccessControlException thrown");
} catch (AccessControlException ace) {
System.out.println(
"AccessControlException thrown as expected: "
+ ace.getMessage());
}
ReadFromFileNegativeAction readFromFile
= new ReadFromFileNegativeAction(filename);
return Subject.doAs(subject, readFromFile);
}
}
class ReadFromFileNegativeAction implements PrivilegedAction {
private final String filename;
public ReadFromFileNegativeAction(String filename) {
this.filename = filename;
}
@Override
public Object run() {
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
System.out.println("principals = " + subject.getPrincipals());
try {
Utils.readFile(filename);
throw new RuntimeException(
"Test failed: no AccessControlException thrown");
} catch (AccessControlException ace) {
System.out.println(
"AccessControlException thrown as expected: "
+ ace.getMessage());
}
ReadPropertyNegativeAction readProperty =
new ReadPropertyNegativeAction();
return Subject.doAs(subject, readProperty);
}
}
class ReadPropertyNegativeAction implements PrivilegedAction {
@Override
public java.lang.Object run() {
System.out.println("Try to read 'java.class.path' property");
AccessControlContext acc = AccessController.getContext();
Subject s = Subject.getSubject(acc);
System.out.println("principals = " + s.getPrincipals());
try {
System.out.println("java.class.path = "
+ System.getProperty("java.class.path"));
throw new RuntimeException(
"Test failed: no AccessControlException thrown");
} catch (AccessControlException ace) {
System.out.println(
"AccessControlException thrown as expected: "
+ ace.getMessage());
}
return null;
}
}
class WriteToFileExceptionAction implements PrivilegedExceptionAction {
private final String filename;
WriteToFileExceptionAction(String filename) {
this.filename = filename;
}
@Override
public Object run() throws Exception {
Utils.writeFile(filename);
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
ReadFromFileExceptionAction readFromFile =
new ReadFromFileExceptionAction(filename);
return Subject.doAs(subject, readFromFile);
}
}
class ReadFromFileExceptionAction implements PrivilegedExceptionAction {
private final String filename;
ReadFromFileExceptionAction(String filename) {
this.filename = filename;
}
@Override
public Object run() throws Exception {
Utils.readFile(filename);
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
ReadPropertyExceptionAction readProperty =
new ReadPropertyExceptionAction();
return Subject.doAs(subject, readProperty);
}
}
class ReadPropertyExceptionAction implements PrivilegedExceptionAction {
@Override
public java.lang.Object run() throws Exception {
System.out.println("Try to read 'java.class.path' property");
AccessControlContext acc = AccessController.getContext();
Subject s = Subject.getSubject(acc);
System.out.println("principals = " + s.getPrincipals());
try {
System.out.println("java.class.path = "
+ System.getProperty("java.class.path"));
throw new RuntimeException(
"Test failed: no AccessControlException thrown");
} catch (AccessControlException ace) {
System.out.println(
"AccessControlException thrown as expected: "
+ ace.getMessage());
throw new ReadPropertyException(ace);
}
}
}
class ReadPropertyException extends Exception {
ReadPropertyException(Throwable cause) {
super(cause);
}
}