aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Azores <[email protected]>2014-01-17 13:43:09 -0500
committerAndrew Azores <[email protected]>2014-01-17 13:43:09 -0500
commitc4bef6cad39892b850022c8f85c1edd97b0c7b40 (patch)
tree50e5af192a64a3a7da0f04eaf5fae1a2c6eeee48
parent4cc1ae82645431a5c1f0958a800e8e5dfc012086 (diff)
Added PolicyPanel to itweb-settings for custom policies
Added itweb-settings panel to explain custom policy files and allow launching a policy editor for user's policy file. * netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java: (createMainSettingsPanel, createPolicySettingsPanel) added PolicyPanel * netx/net/sourceforge/jnlp/resources/Messages.properties: new messages for PolicyPanel * netx/net/sourceforge/jnlp/controlpanel/PolicyPanel.java: new panel to allow launching of external policy editor * tests/reproducers/simple/CustomPolicies/resources/CustomPolicies.html: new test to ensure custom user policy files work correctly * tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplet.jnlp * tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplication.jnlp * tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesJnlpHref.html * tests/reproducers/simple/CustomPolicies/srcs/CustomPolicies.java * tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTest.java
-rw-r--r--ChangeLog18
-rw-r--r--netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java7
-rw-r--r--netx/net/sourceforge/jnlp/controlpanel/PolicyPanel.java239
-rw-r--r--netx/net/sourceforge/jnlp/resources/Messages.properties10
-rw-r--r--tests/reproducers/simple/CustomPolicies/resources/CustomPolicies.html48
-rw-r--r--tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplet.jnlp53
-rw-r--r--tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplication.jnlp53
-rw-r--r--tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesJnlpHref.html45
-rw-r--r--tests/reproducers/simple/CustomPolicies/srcs/CustomPolicies.java23
-rw-r--r--tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTest.java227
10 files changed, 722 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 65cbee4..d31c0f9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
2014-01-17 Andrew Azores <[email protected]>
+ Added itweb-settings panel to explain custom policy files and allow
+ launching a policy editor for user's policy file.
+ * netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java:
+ (createMainSettingsPanel, createPolicySettingsPanel) added PolicyPanel
+ * netx/net/sourceforge/jnlp/resources/Messages.properties: new messages
+ for PolicyPanel
+ * netx/net/sourceforge/jnlp/controlpanel/PolicyPanel.java: new panel to
+ allow launching of external policy editor
+ * tests/reproducers/simple/CustomPolicies/resources/CustomPolicies.html:
+ new test to ensure custom user policy files work correctly
+ * tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplet.jnlp
+ * tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplication.jnlp
+ * tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesJnlpHref.html
+ * tests/reproducers/simple/CustomPolicies/srcs/CustomPolicies.java
+ * tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTest.java
+
+2014-01-17 Andrew Azores <[email protected]>
+
Fixes JS reproducer regression.
http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2014-January/025764.html
* plugin/icedteanp/IcedTeaScriptablePluginObject.cc: (hasMethod) fixed
diff --git a/netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java b/netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
index 3caa4a2..bccf24b 100644
--- a/netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
+++ b/netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
@@ -264,7 +264,8 @@ public class ControlPanel extends JFrame {
// new SettingsPanel(Translator.R("CPTabRuntimes"), createRuntimesSettingsPanel()),
new SettingsPanel(Translator.R("CPTabSecurity"), createSecuritySettingsPanel()),
//todo refactor to work with tmp file and apply as asu designed it
- new SettingsPanel(Translator.R("APPEXTSECControlPanelExtendedAppletSecurityTitle"), new UnsignedAppletsTrustingListPanel(DeploymentConfiguration.getAppletTrustGlobalSettingsPath(),DeploymentConfiguration.getAppletTrustUserSettingsPath(), this.config) )
+ new SettingsPanel(Translator.R("CPTabPolicy"), createPolicySettingsPanel()),
+ new SettingsPanel(Translator.R("APPEXTSECControlPanelExtendedAppletSecurityTitle"), new UnsignedAppletsTrustingListPanel(DeploymentConfiguration.getAppletTrustGlobalSettingsPath(), DeploymentConfiguration.getAppletTrustUserSettingsPath(), this.config))
};
// Add panels.
@@ -357,6 +358,10 @@ public class ControlPanel extends JFrame {
return new SecuritySettingsPanel(this.config);
}
+ private JPanel createPolicySettingsPanel() {
+ return new PolicyPanel(this, this.config);
+ }
+
private JPanel createJVMSettingsPanel() {
return new JVMPanel(this.config);
}
diff --git a/netx/net/sourceforge/jnlp/controlpanel/PolicyPanel.java b/netx/net/sourceforge/jnlp/controlpanel/PolicyPanel.java
new file mode 100644
index 0000000..c75611d
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/controlpanel/PolicyPanel.java
@@ -0,0 +1,239 @@
+package net.sourceforge.jnlp.controlpanel;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.config.DirectoryValidator;
+import net.sourceforge.jnlp.config.DirectoryValidator.DirectoryCheckResults;
+import net.sourceforge.jnlp.util.FileUtils;
+import net.sourceforge.jnlp.util.logging.OutputController;
+import sun.security.tools.policytool.PolicyTool;
+
+public class PolicyPanel extends NamedBorderPanel {
+
+ private enum OpenFileResult {
+ SUCCESS, FAILURE, CANT_CREATE, CANT_WRITE, NOT_FILE
+ }
+
+ public PolicyPanel(final JFrame frame, final DeploymentConfiguration config) {
+ super(R("CPHeadPolicy"), new GridBagLayout());
+ addComponents(frame, config);
+ }
+
+ private void addComponents(final JFrame frame, final DeploymentConfiguration config) {
+ JLabel aboutLabel = new JLabel("<html>" + R("CPPolicyDetail") + "</html>");
+
+ final String fileUrlString = config.getProperty(DeploymentConfiguration.KEY_USER_SECURITY_POLICY);
+ JButton showUserPolicyButton = new JButton(R("CPButPolicy"));
+ showUserPolicyButton.addActionListener(new ViewPolicyButtonAction(frame, fileUrlString));
+
+ String pathPart = localFilePathFromUrlString(fileUrlString);
+ showUserPolicyButton.setToolTipText(R("CPPolicyTooltip", FileUtils.displayablePath(pathPart, 60)));
+
+ JTextField locationField = new JTextField(pathPart);
+ locationField.setEditable(false);
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.BOTH;
+ c.gridx = 1;
+ c.gridy = 0;
+ c.weightx = 1;
+ add(aboutLabel, c);
+
+ c.weighty = 0;
+ c.weightx = 0;
+ c.gridy++;
+ add(locationField, c);
+
+ c.fill = GridBagConstraints.NONE;
+ c.gridx++;
+ add(showUserPolicyButton, c);
+
+ /* Keep all the elements at the top of the panel (Extra padding) */
+ c.fill = GridBagConstraints.BOTH;
+ Component filler1 = Box.createRigidArea(new Dimension(240, 1));
+ Component filler2 = Box.createRigidArea(new Dimension(1, 1));
+ c.gridx++;
+ add(filler1, c);
+ c.gridx--;
+ c.weighty = 1;
+ c.gridy++;
+ add(filler2, c);
+ }
+
+ /**
+ * Launch the policytool for a specified file path
+ * @param filePath the policy file path to be opened with policytool
+ */
+ private static void launchPolicyTool(final JFrame frame, final String filePath) {
+ try {
+ final File policyFile = new File(filePath).getCanonicalFile();
+ OpenFileResult result = canOpenPolicyFile(policyFile);
+ if (result == OpenFileResult.SUCCESS) {
+ PolicyTool.main(new String[] { "-file", policyFile.getPath() });
+ } else if (result == OpenFileResult.CANT_WRITE) {
+ showReadOnlyDialog(frame);
+ PolicyTool.main(new String[] { "-file", policyFile.getPath() });
+ } else {
+ showCouldNotOpenFileDialog(frame, policyFile.getPath(), result);
+ }
+ } catch (IOException e) {
+ OutputController.getLogger().log(e);
+ showCouldNotOpenFileDialog(frame, filePath);
+ }
+ }
+
+ /**
+ * Verify that a given file object points to a real, accessible plain file.
+ * As a side effect, if the file is accessible but does not yet exist, it will be created
+ * as an empty plain file.
+ * @param policyFile the file to verify
+ * @throws IOException if the file is not accessible
+ */
+ private static OpenFileResult canOpenPolicyFile(final File policyFile) {
+ DirectoryCheckResults dcr = testPolicyFileDirectory(policyFile);
+ if (dcr.getFailures() == 0) {
+ if (policyFile.isDirectory())
+ return OpenFileResult.NOT_FILE;
+ try {
+ if (!policyFile.exists() && !policyFile.createNewFile()) {
+ return OpenFileResult.CANT_CREATE;
+ }
+ } catch (IOException e) {
+ return OpenFileResult.CANT_CREATE;
+ }
+ boolean read = policyFile.canRead(), write = policyFile.canWrite();
+ if (read && write)
+ return OpenFileResult.SUCCESS;
+ else if (read)
+ return OpenFileResult.CANT_WRITE;
+ else
+ return OpenFileResult.FAILURE;
+ }
+ return OpenFileResult.FAILURE;
+ }
+
+ /**
+ * Ensure that the parent directory of the Policy File exists and that we are
+ * able to create and access files within this directory
+ * @param policyFile the location of the policy file
+ * @return an object representing the results of the test
+ */
+ private static DirectoryCheckResults testPolicyFileDirectory(final File policyFile) {
+ List<File> policyDirectory = new ArrayList<File>();
+ policyDirectory.add(policyFile.getParentFile());
+ DirectoryValidator validator = new DirectoryValidator(policyDirectory);
+ DirectoryCheckResults result = validator.ensureDirs();
+
+ return result;
+ }
+
+ private static void showCouldNotOpenFileDialog(final JFrame frame, final String filePath) {
+ showCouldNotOpenFileDialog(frame, filePath, OpenFileResult.FAILURE);
+ }
+
+ private static void showCouldNotOpenFileDialog(final JFrame frame, final String filePath, final OpenFileResult reason) {
+ String message;
+ switch (reason) {
+ case CANT_CREATE:
+ message = R("RCantCreateFile", filePath);
+ break;
+ case CANT_WRITE:
+ message = R("RCantWriteFile", filePath);
+ break;
+ case NOT_FILE:
+ message = R("RExpectedFile", filePath);
+ break;
+ default:
+ message = R("RCantOpenFile", filePath);
+ break;
+ }
+ showCouldNotOpenFileDialog(frame, filePath, message);
+ }
+
+ /**
+ * Show a dialog informing the user that the policy file could not be opened
+ * @param frame the parent frame for this dialog
+ * @param filePath the path to the file we tried to open
+ * @param message the specific reason the file could not be opened
+ */
+ private static void showCouldNotOpenFileDialog(final JFrame frame, final String filePath, final String message) {
+ OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Could not open user JNLP policy");
+ JOptionPane.showMessageDialog(frame, message, R("Error"), JOptionPane.ERROR_MESSAGE);
+ }
+
+ /**
+ * Show a dialog informing the user that the policy file is currently read-only
+ * @param frame the parent frame for this dialog
+ */
+ private static void showReadOnlyDialog(final JFrame frame) {
+ OutputController.getLogger().log(OutputController.Level.WARNING_ALL, "Opening user JNLP policy read-only");
+ JOptionPane.showMessageDialog(frame, R("RFileReadOnly"), R("Warning"), JOptionPane.WARNING_MESSAGE);
+ }
+
+ /**
+ * Loosely attempt to get the path part of a file URL string. If this fails,
+ * simply return back the input. This is only intended to be used for displaying
+ * GUI elements such as the CPPolicyTooltip.
+ * @param url the String representing the URL whose path is desired
+ * @return a String representing the local filepath of the given file:/ URL
+ */
+ private static String localFilePathFromUrlString(String url) {
+ try {
+ URL u = new URL(url);
+ return u.getPath();
+ } catch (MalformedURLException e) {
+ return url;
+ }
+ }
+
+ /*
+ * Implements the action to be performed when the "View Policy" button is clicked
+ */
+ private class ViewPolicyButtonAction implements ActionListener {
+ private final JFrame frame;
+ private final String fileUrlString;
+
+ public ViewPolicyButtonAction(final JFrame frame, final String fileUrlString) {
+ this.fileUrlString = fileUrlString;
+ this.frame = frame;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ try {
+ final URL fileUrl = new URL(fileUrlString);
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ launchPolicyTool(frame, fileUrl.getPath());
+ }
+ });
+ } catch (MalformedURLException ex) {
+ OutputController.getLogger().log(ex);
+ showCouldNotOpenFileDialog(frame, fileUrlString);
+ }
+ }
+ }
+}
diff --git a/netx/net/sourceforge/jnlp/resources/Messages.properties b/netx/net/sourceforge/jnlp/resources/Messages.properties
index be28762..bff5e34 100644
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties
+++ b/netx/net/sourceforge/jnlp/resources/Messages.properties
@@ -21,6 +21,7 @@ AFileOnTheMachine=a file on the machine
AlwaysAllowAction=Always allow this action
Usage=Usage:
Error=Error
+Warning=Warning
Continue=Do you want to continue?
Field=Field
@@ -159,6 +160,10 @@ RExitTaken=Exit class already set and caller is not exit class.
RCantReplaceSM=Changing the SecurityManager is not allowed.
RCantCreateFile=Cant create file {0}
RCantDeleteFile=Cant delete file {0}
+RCantOpenFile=Could not open file {0}
+RCantWriteFile=Could not write to file {0}
+RFileReadOnly=Opening file in read-only mode
+RExpectedFile=Expected {0} to be a file but it was not
RRemoveRPermFailed=Removing read permission on file {0} failed
RRemoveWPermFailed=Removing write permissions on file {0} failed
RRemoveXPermFailed=Removing execute permissions on file {0} failed
@@ -353,6 +358,8 @@ CPJVMNotokMessage1=You have entered invalid JDK value <u>({0})</u> with followin
CPJVMNotokMessage2=You might be seeing this message because: <blockquote> * Some validity tests have not been passed<br> * Non-OpenJDK is detected</blockquote>With invalid JDK IcedTea-Web will probably not be able to start.<br>You will have to modify or remove <u>{0}</u> property in your configuration file <u>{1}</u>. <br>You should try to search for OpenJDK in your system or be sure you know what you are doing.
CPJVMconfirmInvalidJdkTitle=Confirm invalid JDK
CPJVMconfirmReset=Reset to default?
+CPPolicyDetail=View or edit your user-level Java Policy File. This allows you to grant or deny runtime permissions to applets regardless of the standard security sandboxing rules.
+CPPolicyTooltip=Open {0} in policy editor
# Control Panel - Buttons
CPButAbout=About...
@@ -360,6 +367,7 @@ CPButNetworkSettings=Network Settings...
CPButSettings=Settings...
CPButView=View...
CPButCertificates=Certificates...
+CPButPolicy=View/Edit with Policy Tool
# Control Panel - Headers
CPHead=IcedTea-Web Control Panel
@@ -372,6 +380,7 @@ CPHeadDebugging=\u00a0Debugging\u00a0Settings\u00a0
CPHeadDesktopIntegration=\u00a0Desktop\u00a0Integrations\u00a0
CPHeadSecurity=\u00a0Security\u00a0Settings\u00a0
CPHeadJVMSettings=\u00a0JVM\u00a0Settings\u00a0
+CPHeadPolicy=\u00a0Custom\u00a0Policy\u00a0Settings\u00a0
# Control Panel - Tabs
CPTabAbout=About IcedTea-Web
@@ -384,6 +393,7 @@ CPTabNetwork=Network
CPTabRuntimes=Runtimes
CPTabSecurity=Security
CPTabJVMSettings=JVM Settings
+CPTabPolicy=Policy Settings
# Control Panel - AboutPanel
CPAboutInfo=This is the control panel for setting deployments.properties.<br/>Not all options will take effect until implemented.<br/>The use of multiple JREs is currently limited to OpenJDK.<br/>
diff --git a/tests/reproducers/simple/CustomPolicies/resources/CustomPolicies.html b/tests/reproducers/simple/CustomPolicies/resources/CustomPolicies.html
new file mode 100644
index 0000000..06d4508
--- /dev/null
+++ b/tests/reproducers/simple/CustomPolicies/resources/CustomPolicies.html
@@ -0,0 +1,48 @@
+<!--
+
+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; either version 2, or (at your option)
+any later version.
+
+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.
+
+ -->
+<html>
+ <head></head>
+ <body>
+ <applet code="CustomPolicies.class"
+ archive="CustomPolicies.jar"
+ codebase="."
+ width="800"
+ height="600">
+ </applet>
+ </body>
+</html>
diff --git a/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplet.jnlp b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplet.jnlp
new file mode 100644
index 0000000..00d6a83
--- /dev/null
+++ b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplet.jnlp
@@ -0,0 +1,53 @@
+<!--
+
+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; either version 2, or (at your option)
+any later version.
+
+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.
+
+ -->
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp spec="1.0" href="CustomPoliciesApplet.jnlp" codebase=".">
+ <information>
+ <title>CustomPoliciesApplet</title>
+ <vendor>IcedTea</vendor>
+ <homepage href="http://icedtea.classpath.org/wiki/IcedTea-Web#Testing_IcedTea-Web"/>
+ <description>Test that unsigned applets can perform privileged actions when granted by custom policies</description>
+ <offline/>
+ </information>
+ <resources>
+ <j2se version="1.4+"/>
+ <jar href="CustomPolicies.jar"/>
+ </resources>
+ <applet-desc main-class="CustomPolicies">
+ </applet-desc>
+</jnlp>
diff --git a/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplication.jnlp b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplication.jnlp
new file mode 100644
index 0000000..31624e8
--- /dev/null
+++ b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesApplication.jnlp
@@ -0,0 +1,53 @@
+<!--
+
+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; either version 2, or (at your option)
+any later version.
+
+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.
+
+ -->
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp spec="1.0" href="CustomPoliciesApplication.jnlp" codebase=".">
+ <information>
+ <title>CustomPoliciesApplication</title>
+ <vendor>IcedTea</vendor>
+ <homepage href="http://icedtea.classpath.org/wiki/IcedTea-Web#Testing_IcedTea-Web"/>
+ <description>Test that unsigned applets can perform privileged actions when granted by custom policies</description>
+ <offline/>
+ </information>
+ <resources>
+ <j2se version="1.4+"/>
+ <jar href="CustomPolicies.jar"/>
+ </resources>
+ <application-desc main-class="CustomPolicies">
+ </application-desc>
+</jnlp>
diff --git a/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesJnlpHref.html b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesJnlpHref.html
new file mode 100644
index 0000000..49727e5
--- /dev/null
+++ b/tests/reproducers/simple/CustomPolicies/resources/CustomPoliciesJnlpHref.html
@@ -0,0 +1,45 @@
+<!--
+
+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; either version 2, or (at your option)
+any later version.
+
+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.
+
+ -->
+<html>
+ <head></head>
+ <body>
+ <applet width="800" height="600" code="CustomPolicies">
+ <param name="jnlp_href" value="CustomPoliciesApplet.jnlp">
+ </applet>
+ </body>
+</html>
diff --git a/tests/reproducers/simple/CustomPolicies/srcs/CustomPolicies.java b/tests/reproducers/simple/CustomPolicies/srcs/CustomPolicies.java
new file mode 100644
index 0000000..2446f55
--- /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
index 0000000..24bdc4c
--- /dev/null
+++ b/tests/reproducers/simple/CustomPolicies/testcases/CustomPoliciesTest.java
@@ -0,0 +1,227 @@
+/* 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.net.URL;
+
+import net.sourceforge.jnlp.ProcessResult;
+import net.sourceforge.jnlp.ServerAccess;
+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 net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/* 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 DeploymentConfiguration config = JNLPRuntime.getConfiguration();
+ private static File policy, policyBackup;
+
+ @BeforeClass
+ public static void setPolicyLocation() throws Exception {
+ policy = new File(new URL(config.getProperty(DeploymentConfiguration.KEY_USER_SECURITY_POLICY)).getPath());
+ File securityDir = policy.getParentFile();
+ File[] previousBackups = securityDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith("java.policy.bak");
+ }
+ });
+ for (File backup : previousBackups) {
+ ServerAccess.logErrorReprint("Warning: found previous policy file backup at " + backup);
+ }
+ }
+
+ @Before
+ public void backupPolicy() throws Exception {
+ if (policy.isFile()) {
+ policyBackup = File.createTempFile("java.policy.bak", null, policy.getParentFile());
+ if (!policy.renameTo(policyBackup)) {
+ ServerAccess.logErrorReprint("Could not back up existing policy file");
+ throw new RuntimeException("Could not back up existing policy file");
+ }
+ }
+
+ }
+
+ @After
+ public void restorePolicy() {
+ policy.delete();
+ if (policyBackup != null && policyBackup.isFile()) {
+ policyBackup.renameTo(policy);
+ }
+ }
+
+ private void writePolicy() throws IOException {
+ FileWriter out = new FileWriter(policy);
+ try {
+ String policyText="grant {\n permission java.util.PropertyPermission \"user.home\", \"read\";\n};\n";
+ out.write(policyText, 0, policyText.length());
+ } finally {
+ out.close();
+ }
+ }
+
+ @NeedsDisplay
+ @Test
+ @TestInBrowsers(testIn={Browsers.one})
+ public void testHtmlLaunchWithPolicy() throws Exception {
+ writePolicy();
+ assertPolicyExists();
+ RulesFolowingClosingListener listener = new RulesFolowingClosingListener();
+ listener.addContainsRule("CustomPolicies applet read:");
+ ProcessResult pr = server.executeBrowser("CustomPolicies.html", listener, null);
+ assertInit(pr);
+ assertReadProps(pr);
+ assertNoAccessControlException(pr);
+ }
+
+ @NeedsDisplay
+ @Test
+ @TestInBrowsers(testIn={Browsers.one})
+ public void testHtmlJnlpHrefLaunchWithPolicy() throws Exception {
+ writePolicy();
+ assertPolicyExists();
+ RulesFolowingClosingListener listener = new RulesFolowingClosingListener();
+ listener.addContainsRule("CustomPolicies applet read:");
+ ProcessResult pr = server.executeBrowser("CustomPoliciesJnlpHref.html", listener, null);
+ assertInit(pr);
+ assertReadProps(pr);
+ assertNoAccessControlException(pr);
+ }
+
+ @Test
+ public void testJnlpAppletLaunchWithPolicy() throws Exception {
+ writePolicy();
+ assertPolicyExists();
+ ProcessResult pr = server.executeJavawsHeadless("CustomPoliciesApplet.jnlp");
+ assertInit(pr);
+ assertReadProps(pr);
+ assertNoAccessControlException(pr);
+ }
+
+ @Test
+ public void testJnlpApplicationLaunchWithPolicy() throws Exception {
+ writePolicy();
+ assertPolicyExists();
+ ProcessResult pr = server.executeJavawsHeadless("CustomPoliciesApplication.jnlp");
+ assertInit(pr);
+ assertReadProps(pr);
+ assertNoAccessControlException(pr);
+ }
+
+ @NeedsDisplay
+ @Test
+ @TestInBrowsers(testIn = { Browsers.one })
+ public void testHtmlLaunch() throws Exception {
+ assertNoPolicyExists();
+ RulesFolowingClosingListener listener = new RulesFolowingClosingListener();
+ listener.addContainsRule("CustomPolicies applet read:");
+ ProcessResult pr = server.executeBrowser("CustomPolicies.html", listener, null);
+ assertInit(pr);
+ assertAccessControlException(pr);
+ }
+
+ @NeedsDisplay
+ @Test
+ @TestInBrowsers(testIn = { Browsers.one })
+ public void testHtmlJnlpHrefLaunch() throws Exception {
+ assertNoPolicyExists();
+ RulesFolowingClosingListener listener = new RulesFolowingClosingListener();
+ listener.addContainsRule("CustomPolicies applet read:");
+ ProcessResult pr = server.executeBrowser("CustomPoliciesJnlpHref.html", listener, null);
+ assertInit(pr);
+ assertAccessControlException(pr);
+ }
+
+ @Test
+ public void testJnlpAppletLaunch() throws Exception {
+ assertNoPolicyExists();
+ ProcessResult pr = server.executeJavawsHeadless("CustomPoliciesApplet.jnlp");
+ assertInit(pr);
+ assertAccessControlException(pr);
+ }
+
+ @Test
+ public void testJnlpApplicationLaunch() throws Exception {
+ assertNoPolicyExists();
+ ProcessResult pr = server.executeJavawsHeadless("CustomPoliciesApplication.jnlp");
+ assertInit(pr);
+ assertAccessControlException(pr);
+ }
+
+ private void assertAccessControlException(ProcessResult pr) {
+ assertTrue("Applet should not have been able to read user.home", pr.stdout.contains("AccessControlException: access denied"));
+ }
+
+ private void assertPolicyExists() {
+ assertTrue("A user policy file should be installed", policy.isFile());
+ }
+
+ private void assertNoPolicyExists() {
+ 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 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"));
+ }
+
+}