diff options
author | Andrew Azores <[email protected]> | 2014-01-17 13:43:09 -0500 |
---|---|---|
committer | Andrew Azores <[email protected]> | 2014-01-17 13:43:09 -0500 |
commit | c4bef6cad39892b850022c8f85c1edd97b0c7b40 (patch) | |
tree | 50e5af192a64a3a7da0f04eaf5fae1a2c6eeee48 /netx | |
parent | 4cc1ae82645431a5c1f0958a800e8e5dfc012086 (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
Diffstat (limited to 'netx')
3 files changed, 255 insertions, 1 deletions
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/> |