From 259c3ec2e9dbe259b759daa1dadec0c71a8d1e8c Mon Sep 17 00:00:00 2001 From: Raghu Nair Date: Wed, 3 Sep 2014 02:11:16 +0000 Subject: [PATCH] 8048362: Tests for doPrivileged with accomplice Reviewed-by: vinnie --- .../AccessController/DoPrivAccomplice.java | 34 +++ .../DoPrivAccompliceTest.java | 97 ++++++++ .../security/AccessController/DoPrivTest.java | 32 +++ jdk/test/lib/testlibrary/JavaToolUtils.java | 209 ++++++++++++++++++ 4 files changed, 372 insertions(+) create mode 100644 jdk/test/java/security/AccessController/DoPrivAccomplice.java create mode 100644 jdk/test/java/security/AccessController/DoPrivAccompliceTest.java create mode 100644 jdk/test/java/security/AccessController/DoPrivTest.java create mode 100644 jdk/test/lib/testlibrary/JavaToolUtils.java diff --git a/jdk/test/java/security/AccessController/DoPrivAccomplice.java b/jdk/test/java/security/AccessController/DoPrivAccomplice.java new file mode 100644 index 00000000000..6cc2846deee --- /dev/null +++ b/jdk/test/java/security/AccessController/DoPrivAccomplice.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +public class DoPrivAccomplice { + + public String go() { + String name = (String)java.security.AccessController. + doPrivileged((java.security.PrivilegedAction)() -> + System.getProperty("user.name")); + return name; + } +} diff --git a/jdk/test/java/security/AccessController/DoPrivAccompliceTest.java b/jdk/test/java/security/AccessController/DoPrivAccompliceTest.java new file mode 100644 index 00000000000..d18038c9a87 --- /dev/null +++ b/jdk/test/java/security/AccessController/DoPrivAccompliceTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2007, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @test + * @bug 8048362 + * @compile ../../../lib/testlibrary/JavaToolUtils.java + * DoPrivAccomplice.java DoPrivTest.java + * @summary Tests the doPrivileged with accomplice Generate two jars + * (DoPrivTest.jar and DoPrivAccomplice.jar) and grant permission to + * DoPrivAccmplice.jar for reading user.home property from a PrivilagedAction. + * Run DoPrivTest.jar and try to access user.home property using + * DoPrivAccmplice.jar. + * @run main/othervm DoPrivAccompliceTest + */ + +public class DoPrivAccompliceTest { + + private static final String PWD = System.getProperty("test.classes", "./"); + private static final String ACTION_SOURCE = "DoPrivAccomplice"; + private static final String TEST_SOURCE = "DoPrivTest"; + + public static void createPolicyFile(URI codebaseURL) throws IOException { + String codebase = codebaseURL.toString(); + String quotes = "\""; + StringBuilder policyFile = new StringBuilder(); + policyFile.append("grant codeBase ").append(quotes). + append(codebase).append(quotes).append("{\n"). + append("permission java.util.PropertyPermission "). + append(quotes).append("user.name").append(quotes). + append(",").append(quotes).append("read").append(quotes). + append(";\n};"); + try (FileWriter writer = new FileWriter(new File(PWD, "java.policy"))) { + writer.write(policyFile.toString()); + writer.close(); + } catch (IOException e) { + System.err.println("Error while creating policy file"); + throw e; + } + } + + public static void main(String[] args) throws Exception { + final File class1 = new File(PWD, ACTION_SOURCE + ".class"); + final File class2 = new File(PWD, TEST_SOURCE + ".class"); + final File jarFile1 = new File(PWD, ACTION_SOURCE + ".jar"); + final File jarFile2 = new File(PWD, TEST_SOURCE + ".jar"); + System.out.println("Compilation successfull"); + JavaToolUtils.createJar(jarFile1, Arrays.asList(new File[]{class1})); + System.out.println("Created jar file " + jarFile1); + JavaToolUtils.createJar(jarFile2, Arrays.asList(new File[]{class2})); + System.out.println("Created jar file " + jarFile2); + createPolicyFile(jarFile1.toURI()); + + List commands = new ArrayList<>(); + final String pathSepartor = System.getProperty("path.separator"); + commands.add("-Djava.security.manager"); + commands.add("-Djava.security.policy=" + PWD + "/java.policy"); + commands.add("-classpath"); + commands.add(PWD + "/" + TEST_SOURCE + ".jar" + pathSepartor + + PWD + "/" + ACTION_SOURCE + ".jar"); + commands.add(TEST_SOURCE); + if (JavaToolUtils.runJava(commands) == 0) { + System.out.println("Test PASSES"); + } + } + +} diff --git a/jdk/test/java/security/AccessController/DoPrivTest.java b/jdk/test/java/security/AccessController/DoPrivTest.java new file mode 100644 index 00000000000..9ed0f97d000 --- /dev/null +++ b/jdk/test/java/security/AccessController/DoPrivTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2007, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +public class DoPrivTest { + + public static void main(String[] args) { + String name = new DoPrivAccomplice().go(); + System.out.println("Received Name : " + name); + } +} diff --git a/jdk/test/lib/testlibrary/JavaToolUtils.java b/jdk/test/lib/testlibrary/JavaToolUtils.java new file mode 100644 index 00000000000..c9736bcf9a0 --- /dev/null +++ b/jdk/test/lib/testlibrary/JavaToolUtils.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +/** + * Utils class for compiling , creating jar file and executing a java command + * + * @author Raghu Nair + */ + +public class JavaToolUtils { + + public static final long DEFAULT_WAIT_TIME = 10000; + + private JavaToolUtils() { + } + + /** + * Takes a list of files and compile these files into the working directory. + * + * @param files + * @throws IOException + */ + public static void compileFiles(List files) throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + try (StandardJavaFileManager fileManager = compiler. + getStandardFileManager(null, null, null)) { + Iterable compilationUnit + = fileManager.getJavaFileObjectsFromFiles(files); + compiler.getTask(null, fileManager, null, null, null, + compilationUnit).call(); + } + } + + /** + * Create a jar file using the list of files provided. + * + * @param jar + * @param files + * @throws IOException + */ + public static void createJar(File jar, List files) + throws IOException { + Manifest manifest = new Manifest(); + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, + "1.0"); + try (JarOutputStream target = new JarOutputStream( + new FileOutputStream(jar), manifest)) { + for (File file : files) { + add(file, target); + } + } + } + + private static void add(File source, JarOutputStream target) + throws IOException { + Objects.requireNonNull(source, "source cannot be null"); + Objects.requireNonNull(target, "target cannot be null"); + // not tested against directories and from different path. + String name = source.getName(); + if (source.isDirectory()) { + if (!name.isEmpty()) { + if (!name.endsWith("/")) { + name += "/"; + } + JarEntry entry = new JarEntry(name); + entry.setTime(source.lastModified()); + target.putNextEntry(entry); + target.closeEntry(); + } + for (File nestedFile : source.listFiles()) { + add(nestedFile, target); + } + return; + } + System.out.println("Adding entry " + name); + JarEntry entry = new JarEntry(name); + entry.setTime(source.lastModified()); + target.putNextEntry(entry); + Files.copy(source.toPath(), target); + target.closeEntry(); + } + + /** + * Runs java command with provided arguments. Caller should not pass java + * command in the argument list. + * + * @param commands + * @param waitTime time to wait for the command to exit in milli seconds + * @return + * @throws Exception + */ + public static int runJava(List commands,long waitTime) + throws Exception { + String java = System.getProperty("java.home") + "/bin/java"; + commands.add(0, java); + String command = commands.toString().replace(",", " "); + System.out.println("Executing the following command \n" + command); + ProcessBuilder processBuilder = new ProcessBuilder(commands); + final Process process = processBuilder.start(); + BufferedReader errorStream = new BufferedReader( + new InputStreamReader(process.getErrorStream())); + BufferedReader outStream = new BufferedReader( + new InputStreamReader(process.getInputStream())); + String errorLine; + StringBuilder errors = new StringBuilder(); + String outLines; + while ((errorLine = errorStream.readLine()) != null) { + errors.append(errorLine).append("\n"); + } + while ((outLines = outStream.readLine()) != null) { + System.out.println(outLines); + } + errorLine = errors.toString(); + System.err.println(errorLine); + process.waitFor(waitTime, TimeUnit.MILLISECONDS); + int exitStatus = process.exitValue(); + if (exitStatus != 0 && errorLine != null && errorLine.isEmpty()) { + throw new RuntimeException(errorLine); + } + return exitStatus; + } + + /** + * Runs java command with provided arguments. Caller should not pass java + * command in the argument list. + * + * @param commands + * @return + * @throws Exception + */ + public static int runJava(List commands) throws Exception { + return runJava(commands, DEFAULT_WAIT_TIME); + } + + /** + * Run any command + * @param commands + * @return + * @throws Exception + */ + public static int runCommand(List commands) throws Exception { + String command = commands.toString().replace(",", " "); + System.out.println("Executing the following command \n" + command); + ProcessBuilder processBuilder = new ProcessBuilder(commands); + final Process process = processBuilder.start(); + BufferedReader errorStream = new BufferedReader( + new InputStreamReader(process.getErrorStream())); + BufferedReader outStream = new BufferedReader( + new InputStreamReader(process.getInputStream())); + String errorLine; + StringBuilder errors = new StringBuilder(); + String outLines; + while ((errorLine = errorStream.readLine()) != null) { + errors.append(errorLine).append("\n"); + } + while ((outLines = outStream.readLine()) != null) { + System.out.println(outLines); + } + errorLine = errors.toString(); + System.err.println(errorLine); + int exitStatus = process.exitValue(); + if (exitStatus != 0 && errorLine != null && errorLine.isEmpty()) { + throw new RuntimeException(errorLine); + } + return exitStatus; + } + + +}