diff --git a/tests/reproducers/simple/CustomPolicies/resources/CustomPolicies.html b/tests/reproducers/simple/CustomPolicies/resources/CustomPolicies.html new file mode 100644 --- /dev/null +++ b/tests/reproducers/simple/CustomPolicies/resources/CustomPolicies.html @@ -0,0 +1,48 @@ + + + + + + + + diff --git a/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplet.jnlp b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplet.jnlp new file mode 100644 --- /dev/null +++ b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplet.jnlp @@ -0,0 +1,53 @@ + + + + + CustomPoliciesApplet + IcedTea + + Test that unsigned applets can perform privileged actions when granted by custom policies + + + + + + + + + diff --git a/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplication.jnlp b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplication.jnlp new file mode 100644 --- /dev/null +++ b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplication.jnlp @@ -0,0 +1,53 @@ + + + + + CustomPoliciesApplication + IcedTea + + Test that unsigned applets can perform privileged actions when granted by custom policies + + + + + + + + + diff --git a/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesJnlpHref.html b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesJnlpHref.html new file mode 100644 --- /dev/null +++ b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesJnlpHref.html @@ -0,0 +1,45 @@ + + + + + + + + + diff --git a/tests/reproducers/simple/CustomPolicies/resources/ExtensionJnlpTest.html b/tests/reproducers/simple/CustomPolicies/resources/ExtensionJnlpTest.html new file mode 100644 --- /dev/null +++ b/tests/reproducers/simple/CustomPolicies/resources/ExtensionJnlpTest.html @@ -0,0 +1,46 @@ + + + + + + + + + + diff --git a/tests/reproducers/simple/CustomPolicies/srcs/CustomPolicies.java b/tests/reproducers/simple/CustomPolicies/srcs/CustomPolicies.java new file mode 100644 --- /dev/null +++ b/tests/reproducers/simple/CustomPolicies/srcs/CustomPolicies.java @@ -0,0 +1,23 @@ +import java.applet.Applet; +import java.security.AccessControlException; + +public class CustomPolicies extends Applet { + + @Override + public void start() { + System.out.println("CustomPolicies applet read: " + read("user.home")); + System.exit(0); + } + + private String read(String key) { + try { + return System.getProperty(key); + } catch (AccessControlException ace) { + return ace.toString(); + } + } + + public static void main(String[] args) { + new CustomPolicies().start(); + } +} diff --git a/tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTest.java b/tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTest.java new file mode 100644 --- /dev/null +++ b/tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTest.java @@ -0,0 +1,164 @@ +/* CustomPoliciesTest.java +Copyright (C) 2014 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. + */ + +import net.sourceforge.jnlp.ProcessResult; +import net.sourceforge.jnlp.ServerAccess.AutoClose; +import net.sourceforge.jnlp.annotations.Bug; +import net.sourceforge.jnlp.annotations.KnownToFail; +import net.sourceforge.jnlp.annotations.NeedsDisplay; +import net.sourceforge.jnlp.annotations.TestInBrowsers; +import net.sourceforge.jnlp.browsertesting.BrowserTest; +import net.sourceforge.jnlp.browsertesting.Browsers; +import net.sourceforge.jnlp.closinglisteners.RulesFolowingClosingListener; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import static org.junit.Assert.*; +import org.junit.Test; +import org.junit.BeforeClass; +import org.junit.AfterClass; + +/* Test that adding permission for all codesources to read the user.home property + * results in an unsigned applet being able to perform this action + */ +public class CustomPoliciesTest extends BrowserTest { + + private static File policy = new File(System.getProperty("user.home") + "/.config/icedtea-web/security/java.policy"), + policyBackup = new File(System.getProperty("user.home") + "/.config/icedtea-web/security/java.policy.bak"); + + @BeforeClass + public static void backupPolicyAndWriteTestPolicy() { + if (policy.isFile()) { + if (policyBackup.exists()) { + throw new RuntimeException("Backup policy file already exists"); + } + boolean createdBackup = policy.renameTo(policyBackup); + if (!createdBackup) { + throw new RuntimeException("Could not rename java.policy to java.policy.bak"); + } + } + FileWriter out = null; + try { + out = new FileWriter(policy, false /*no append*/); + } catch (IOException e) { + throw new RuntimeException(e); + } + try { + String policyText="grant {\n permission java.util.PropertyPermission \"user.home\", \"read\";\n};\n"; + out.write(policyText, 0, policyText.length()); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + @AfterClass + public static void restoreBackupPolicy() { + policy.delete(); + if (policyBackup.isFile()) { + policyBackup.renameTo(policy); + policyBackup.delete(); + } + } + + @NeedsDisplay + @Test + @TestInBrowsers(testIn={Browsers.one}) + public void testHtmlLaunch() throws Exception { + RulesFolowingClosingListener listener = new RulesFolowingClosingListener(); + listener.addContainsRule("CustomPolicies applet read:"); + ProcessResult pr = server.executeBrowser("CustomPolicies.html", listener, null); + assertPolicyExists(); + assertInit(pr); + assertReadProps(pr); + assertNoAccessControlException(pr); + } + + @NeedsDisplay + @Test + @TestInBrowsers(testIn={Browsers.one}) + public void testHtmlJnlpHrefLaunch() throws Exception { + RulesFolowingClosingListener listener = new RulesFolowingClosingListener(); + listener.addContainsRule("CustomPolicies applet read:"); + ProcessResult pr = server.executeBrowser("CustomPoliciesJnlpHref.html", listener, null); + assertPolicyExists(); + assertInit(pr); + assertReadProps(pr); + assertNoAccessControlException(pr); + } + + @Test + public void testJnlpAppletLaunch() throws Exception { + ProcessResult pr = server.executeJavawsHeadless("CustomPoliciesApplet.jnlp"); + assertPolicyExists(); + assertInit(pr); + assertReadProps(pr); + assertNoAccessControlException(pr); + } + + @Test + public void testJnlpApplicationLaunch() throws Exception { + ProcessResult pr = server.executeJavawsHeadless("CustomPoliciesApplication.jnlp"); + assertPolicyExists(); + assertInit(pr); + assertReadProps(pr); + assertNoAccessControlException(pr); + } + + private void assertPolicyExists() { + assertTrue("A user policy file should be installed", policy.isFile()); + } + + private void assertInit(ProcessResult pr) { + assertTrue("Applet should have initialized", pr.stdout.contains("CustomPolicies applet read:")); + } + + private void assertReadProps(ProcessResult pr) { + assertTrue("stdout should contain user.home", pr.stdout.contains(System.getProperty("user.home"))); + } + + private void assertNoAccessControlException(ProcessResult pr) { + assertFalse("Applet should have been able to read user.home", pr.stdout.contains("AccessControlException: access denied")); + } + +} diff --git a/tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTestWithoutPolicy.java b/tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTestWithoutPolicy.java new file mode 100644 --- /dev/null +++ b/tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTestWithoutPolicy.java @@ -0,0 +1,140 @@ +/* CustomPoliciesTestWithoutPolicy.java +Copyright (C) 2014 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea 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 for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. + */ + +import net.sourceforge.jnlp.ProcessResult; +import net.sourceforge.jnlp.ServerAccess.AutoClose; +import net.sourceforge.jnlp.annotations.Bug; +import net.sourceforge.jnlp.annotations.KnownToFail; +import net.sourceforge.jnlp.annotations.NeedsDisplay; +import net.sourceforge.jnlp.annotations.TestInBrowsers; +import net.sourceforge.jnlp.browsertesting.BrowserTest; +import net.sourceforge.jnlp.browsertesting.Browsers; +import net.sourceforge.jnlp.closinglisteners.RulesFolowingClosingListener; +import java.io.File; + +import static org.junit.Assert.*; +import org.junit.Test; +import org.junit.BeforeClass; +import org.junit.AfterClass; + +/* Test that without a custom policy installed, reading the user.home system property + * is a restricted action that unsigned applets may not perform + */ +public class CustomPoliciesTestWithoutPolicy extends BrowserTest { + + private static final File policy = new File(System.getProperty("user.home") + "/.config/icedtea-web/security/java.policy"), + policyBackup = new File(System.getProperty("user.home") + "/.config/icedtea-web/security/java.policy.bak"); + + @BeforeClass + public static void backupPolicy() { + if (policy.isFile()) { + if (policyBackup.exists()) { + throw new RuntimeException("Policy backup already exists"); + } + boolean renamed = policy.renameTo(policyBackup); + if (!renamed) { + throw new RuntimeException("Could not back up policy file"); + } + } + } + + @AfterClass + public static void restorePolicy() { + if (policyBackup.isFile()) { + if (policy.exists()) { + throw new RuntimeException("Polcy file already exists"); + } + boolean renamed = policyBackup.renameTo(policy); + if (!renamed) { + throw new RuntimeException("Could not restore policy file from backup"); + } + } + } + + @NeedsDisplay + @Test + @TestInBrowsers(testIn={Browsers.one}) + public void testHtmlLaunch() throws Exception { + RulesFolowingClosingListener listener = new RulesFolowingClosingListener(); + listener.addContainsRule("CustomPolicies applet read:"); + ProcessResult pr = server.executeBrowser("CustomPolicies.html", listener, null); + assertPolicyExists(); + assertInit(pr); + assertAccessControlException(pr); + } + + @NeedsDisplay + @Test + @TestInBrowsers(testIn={Browsers.one}) + public void testHtmlJnlpHrefLaunch() throws Exception { + RulesFolowingClosingListener listener = new RulesFolowingClosingListener(); + listener.addContainsRule("CustomPolicies applet read:"); + ProcessResult pr = server.executeBrowser("CustomPoliciesJnlpHref.html", listener, null); + assertPolicyExists(); + assertInit(pr); + assertAccessControlException(pr); + } + + @Test + public void testJnlpAppletLaunch() throws Exception { + ProcessResult pr = server.executeJavawsHeadless("CustomPoliciesApplet.jnlp"); + assertPolicyExists(); + assertInit(pr); + assertAccessControlException(pr); + } + + @Test + public void testJnlpApplicationLaunch() throws Exception { + ProcessResult pr = server.executeJavawsHeadless("CustomPoliciesApplication.jnlp"); + assertPolicyExists(); + assertInit(pr); + assertAccessControlException(pr); + } + + private void assertPolicyExists() { + assertFalse("A user policy file should not be installed", policy.isFile()); + } + + private void assertInit(ProcessResult pr) { + assertTrue("Applet should have initialized", pr.stdout.contains("CustomPolicies applet read:")); + } + + private void assertAccessControlException(ProcessResult pr) { + assertTrue("Applet should not have been able to read user.home", pr.stdout.contains("AccessControlException: access denied")); + } + +}