changeset 902:ededca6b0659

Add Run In Sandbox button Added "Sandbox" button to CertWarning dialogs, allowing signed applets to be run with restricted permissions * netx/net/sourceforge/jnlp/resources/Messages.properties: (ButSandbox, LRunInSandboxError, LRunInSandboxErrorInfo, CertWarnRunTip, CertWarnSandboxTip, CertWarnCancelTip): new messages * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: (createInstance) added check to not display unsigned warning dialog if the cert warning dialog has been presented and the applet is sandboxed. (checkTrustWithUser) updated for Run In Sandbox functionality. (setRunInSandbox, userPromptedForSandbox) new functions * netx/net/sourceforge/jnlp/security/AppVerifier.java: (checkTrustWithUser) added SecurityDelegate param * netx/net/sourceforge/jnlp/security/CertWarningPane.java: added Sandbox button * netx/net/sourceforge/jnlp/security/JNLPAppVerifier.java: (checkTrustWithUser) uses AppletAction enum type, calls JNLPClassLoader#setRunInSandbox if AppletAction is SANDBOX * netx/net/sourceforge/jnlp/security/PluginAppVerifier.java: same * netx/net/sourceforge/jnlp/security/SecurityDialogs.java: added (AppletAction) enum type. (showCertWarning) returns AppletAction rather than boolean * netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java: (askUser) refactor to use AppletAction rather than boolean * netx/net/sourceforge/jnlp/tools/JarCertVerifier.java: (checkTrustWithUser) added SecurityDelegate param * tests/netx/unit/net/sourceforge/jnlp/security/SecurityDialogsTest.java: (testGetIntegerResponseAsAppletAction) new tests for converting Object references into AppletActions
author Andrew Azores <aazores@redhat.com>
date Fri, 28 Feb 2014 16:45:24 -0500
parents 2bb356915cc1
children 61bfad46e9cc
files ChangeLog netx/net/sourceforge/jnlp/resources/Messages.properties netx/net/sourceforge/jnlp/runtime/Boot.java netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java netx/net/sourceforge/jnlp/security/AppVerifier.java netx/net/sourceforge/jnlp/security/CertWarningPane.java netx/net/sourceforge/jnlp/security/JNLPAppVerifier.java netx/net/sourceforge/jnlp/security/PluginAppVerifier.java netx/net/sourceforge/jnlp/security/SecurityDialogs.java netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java netx/net/sourceforge/jnlp/tools/JarCertVerifier.java tests/netx/unit/net/sourceforge/jnlp/security/SecurityDialogsTest.java tests/reproducers/signed/RunInSandbox/resources/RunInSandbox.html tests/reproducers/signed/RunInSandbox/resources/RunInSandboxApplet.jnlp tests/reproducers/signed/RunInSandbox/resources/RunInSandboxApplication.jnlp tests/reproducers/signed/RunInSandbox/resources/RunInSandboxJnlpHref.html tests/reproducers/signed/RunInSandbox/srcs/RunInSandbox.java tests/reproducers/signed/RunInSandbox/testcases/RunInSandboxTest.java
diffstat 19 files changed, 537 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Feb 28 16:33:48 2014 -0500
+++ b/ChangeLog	Fri Feb 28 16:45:24 2014 -0500
@@ -1,7 +1,39 @@
+2014-02-28  Andrew Azores  <aazores@redhat.com>
+
+	Added "Sandbox" button to CertWarning dialogs, allowing signed applets
+	to be run with restricted permissions
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: (ButSandbox,
+	LRunInSandboxError, LRunInSandboxErrorInfo, CertWarnRunTip,
+	CertWarnSandboxTip, CertWarnCancelTip): new messages
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: (createInstance)
+	added check to not display unsigned warning dialog if the cert warning
+	dialog has been presented and the applet is sandboxed.
+	(checkTrustWithUser) updated for Run In Sandbox functionality.
+	(setRunInSandbox, userPromptedForSandbox) new functions
+	* netx/net/sourceforge/jnlp/security/AppVerifier.java:
+	(checkTrustWithUser) added SecurityDelegate param
+	* netx/net/sourceforge/jnlp/security/CertWarningPane.java: added Sandbox
+	button
+	* netx/net/sourceforge/jnlp/security/JNLPAppVerifier.java:
+	(checkTrustWithUser) uses AppletAction enum type, calls
+	JNLPClassLoader#setRunInSandbox if AppletAction is SANDBOX
+	* netx/net/sourceforge/jnlp/security/PluginAppVerifier.java: same
+	* netx/net/sourceforge/jnlp/security/SecurityDialogs.java: added
+	(AppletAction) enum type. (showCertWarning) returns AppletAction
+	rather than boolean
+	* netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java:
+	(askUser) refactor to use AppletAction rather than boolean
+	* netx/net/sourceforge/jnlp/tools/JarCertVerifier.java:
+	(checkTrustWithUser) added SecurityDelegate param
+	* tests/netx/unit/net/sourceforge/jnlp/security/SecurityDialogsTest.java:
+	(testGetIntegerResponseAsAppletAction) new tests for converting Object
+	references into AppletActions 
+
 2014-02-28  Andrew Azores  <aazores@redhat.com>
 
 	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java:
 	(SecurityDelegate, SecurityDelegateImpl) new interface and implementation.
+	Includes logic for Run In Sandbox, which is not yet used
 	(initializeResources, setSecurity, activateJars, addNewJar) refactored to
 	use SecurityDelegate
 
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/resources/Messages.properties	Fri Feb 28 16:45:24 2014 -0500
@@ -12,11 +12,16 @@
 ButOk=OK
 ButProceed=Proceed
 ButRun=Run
+ButSandbox=Sandbox
 ButApply=Apply
 ButDone=Done
 ButShowDetails=Show Details
 ButHideDetails=Hide Details
 
+CertWarnRunTip=Trust this applet and run with full permissions
+CertWarnSandboxTip=Do not trust this applet and run with restricted permissions
+CertWarnCancelTip=Do not run this applet
+
 AFileOnTheMachine=a file on the machine
 AlwaysAllowAction=Always allow this action
 Usage=Usage:
@@ -93,6 +98,8 @@
 LUnsignedAppletUserDenied=The applet was unsigned, and was not trusted.
 LSignedAppJarUsingUnsignedJar=Signed application using unsigned jars.
 LSignedAppJarUsingUnsignedJarInfo=The main application jar is signed, but some of the jars it is using aren't.
+LRunInSandboxError=Run in Sandbox call performed too late.
+LRunInSandboxErrorInfo=The classloader was notified to run the applet sandboxed, but security settings were already initialized.
 LSignedJNLPFileDidNotMatch=The signed JNLP file did not match the launching JNLP file.
 LNoSecInstance=Error: No security instance for {0}. The application may have trouble continuing
 LCertFoundIn={0} found in cacerts ({1})
--- a/netx/net/sourceforge/jnlp/runtime/Boot.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/runtime/Boot.java	Fri Feb 28 16:45:24 2014 -0500
@@ -184,6 +184,9 @@
         if (null != getOption("-Xtrustall")) {
             JNLPRuntime.setTrustAll(true);
         }
+        if (null != getOption("-Xtrustnone")) {
+            JNLPRuntime.setTrustNone(true);
+        }
         if (null != getOption("-Xignoreheaders")) {
             JNLPRuntime.setIgnoreHeaders(true);
         }
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Fri Feb 28 16:45:24 2014 -0500
@@ -354,8 +354,12 @@
 
         // If security level is 'high' or greater, we must check if the user allows unsigned applets 
         // when the JNLPClassLoader is created. We do so here, because doing so in the constructor 
-        // causes unwanted side-effects for some applets
-        if (!loader.getSigning() && file instanceof PluginBridge) {
+        // causes unwanted side-effects for some applets. However, if the loader has been tagged
+        // with "runInSandbox", then we do not show this dialog - since this tag indicates that
+        // the user was already shown a CertWarning dialog and has chosen to run the applet sandboxed.
+        // This means they've already agreed to running the applet and have specified with which
+        // permission level to do it!
+        if (!loader.getSigning() && !loader.securityDelegate.userPromptedForSandbox() && file instanceof PluginBridge) {
             UnsignedAppletTrustConfirmation.checkUnsignedWithUserIfRequired((PluginBridge)file);
         }
 
@@ -1035,15 +1039,37 @@
      * @throws LaunchException if the user does not approve every dialog prompt.
      */
     private void checkTrustWithUser() throws LaunchException {
-        if (JNLPRuntime.isTrustAll()){
+        if (JNLPRuntime.isTrustNone()) {
+            if (!securityDelegate.getRunInSandbox()) {
+                setRunInSandbox();
+            }
+            return;
+        }
+        if (JNLPRuntime.isTrustAll() || securityDelegate.getRunInSandbox()) {
             return;
         }
 
         if (jcv.isFullySigned() && !jcv.getAlreadyTrustPublisher()) {
-            jcv.checkTrustWithUser(file);
+            jcv.checkTrustWithUser(securityDelegate, file);
         }
     }
 
+    /*
+     * Sets whether applets are to be run sandboxed, regardless of JAR
+     * signing. This MUST be called before any call to initializeResources,
+     * setSecurity, activateJars, or any other method that sets the value
+     * of this.security or adds entries into this.jarLocationSecurityMap.
+     * @throws LaunchException if security settings have been initialized before
+     * this method is called
+     */
+    public void setRunInSandbox() throws LaunchException {
+        securityDelegate.setRunInSandbox();
+    }
+
+    public boolean userPromptedForSandbox() {
+        return securityDelegate.getRunInSandbox();
+    }
+
     /**
      * Display a dialog prompting the user to proceed on applets with mixed signing.
      * @param file the JNLPFile or PluginBridge describing the applet/application to be launched
--- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Fri Feb 28 16:45:24 2014 -0500
@@ -143,6 +143,9 @@
 
     /** all security dialogs will be consumed and pretented as being verified by user and allowed.*/
     private static boolean trustAll=false;
+
+    /** all security dialogs will be consumed and we will pretend the Sandbox option was chosen */
+    private static boolean trustNone = false;
     
     /** allows 301.302.303.307.308 redirects to be followed when downloading resources*/
     private static boolean allowRedirect = false;;
@@ -794,6 +797,14 @@
         return trustAll;
     }
 
+    static void setTrustNone(final boolean b) {
+        trustNone = b;
+    }
+
+    public static boolean isTrustNone() {
+        return trustNone;
+    }
+
     public static boolean isIgnoreHeaders() {
         return ignoreHeaders;
     }
--- a/netx/net/sourceforge/jnlp/security/AppVerifier.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/security/AppVerifier.java	Fri Feb 28 16:45:24 2014 -0500
@@ -42,6 +42,7 @@
 
 import net.sourceforge.jnlp.JNLPFile;
 import net.sourceforge.jnlp.LaunchException;
+import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate;
 import net.sourceforge.jnlp.tools.CertInformation;
 import net.sourceforge.jnlp.tools.JarCertVerifier;
 
@@ -85,6 +86,6 @@
      * Prompt the user with requests for trusting the certificates used by this app
      * @throws LaunchException
      */
-    public void checkTrustWithUser(JarCertVerifier jcv, JNLPFile file)
+    public void checkTrustWithUser(SecurityDelegate securityDelegate, JarCertVerifier jcv, JNLPFile file)
             throws LaunchException;
 }
--- a/netx/net/sourceforge/jnlp/security/CertWarningPane.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/security/CertWarningPane.java	Fri Feb 28 16:45:24 2014 -0500
@@ -206,18 +206,37 @@
         //run and cancel buttons
         JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
         JButton run = new JButton(R("ButRun"));
+        JButton sandbox = new JButton(R("ButSandbox"));
         JButton cancel = new JButton(R("ButCancel"));
+        run.setToolTipText(R("CertWarnRunTip"));
+        sandbox.setToolTipText(R("CertWarnSandboxTip"));
+        cancel.setToolTipText(R("CertWarnCancelTip"));
+
+        alwaysTrust.addActionListener(new ButtonDisableListener(sandbox));
         int buttonWidth = Math.max(run.getMinimumSize().width,
-                        cancel.getMinimumSize().width);
+                sandbox.getMinimumSize().width);
+        buttonWidth = Math.max(buttonWidth, cancel.getMinimumSize().width);
         int buttonHeight = run.getMinimumSize().height;
         Dimension d = new Dimension(buttonWidth, buttonHeight);
         run.setPreferredSize(d);
+        sandbox.setPreferredSize(d);
         cancel.setPreferredSize(d);
+
+        sandbox.setEnabled(!alwaysTrust.isSelected());
+
         run.addActionListener(createSetValueListener(parent, 0));
         run.addActionListener(new CheckBoxListener());
-        cancel.addActionListener(createSetValueListener(parent, 1));
+        sandbox.addActionListener(createSetValueListener(parent, 1));
+        cancel.addActionListener(createSetValueListener(parent, 2));
         initialFocusComponent = cancel;
         buttonPanel.add(run);
+        // file will be null iff this dialog is being called from VariableX509TrustManager.
+        // In this case, the "sandbox" button does not make any sense, as we are asking
+        // the user if they trust some certificate that is not being used to sign an app.
+        // Since there is no app, there is nothing to run sandboxed.
+        if (file != null) {
+            buttonPanel.add(sandbox);
+        }
         buttonPanel.add(cancel);
         buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
 
@@ -242,6 +261,7 @@
     }
 
     private class MoreInfoButtonListener implements ActionListener {
+        @Override
         public void actionPerformed(ActionEvent e) {
             SecurityDialog.showMoreInfoDialog(parent.getCertVerifier(),
                                 parent);
@@ -249,9 +269,26 @@
     }
 
     /**
+     * Disable the Sandbox button when the AlwaysTrust checkbox is checked
+     */
+    private class ButtonDisableListener implements ActionListener {
+        private JButton button;
+
+        public ButtonDisableListener(JButton button) {
+            this.button = button;
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            button.setEnabled(!alwaysTrust.isSelected());
+        }
+    }
+
+    /**
      * Updates the user's KeyStore of trusted Certificates.
      */
     private class CheckBoxListener implements ActionListener {
+        @Override
         public void actionPerformed(ActionEvent e) {
             if (alwaysTrust != null && alwaysTrust.isSelected()) {
                 try {
--- a/netx/net/sourceforge/jnlp/security/JNLPAppVerifier.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/security/JNLPAppVerifier.java	Fri Feb 28 16:45:24 2014 -0500
@@ -44,7 +44,9 @@
 
 import net.sourceforge.jnlp.JNLPFile;
 import net.sourceforge.jnlp.LaunchException;
+import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate;
 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.security.SecurityDialogs.AppletAction;
 import net.sourceforge.jnlp.tools.CertInformation;
 import net.sourceforge.jnlp.tools.JarCertVerifier;
 
@@ -97,7 +99,7 @@
     }
 
     @Override
-    public void checkTrustWithUser(JarCertVerifier jcv, JNLPFile file)
+    public void checkTrustWithUser(SecurityDelegate securityDelegate, JarCertVerifier jcv, JNLPFile file)
             throws LaunchException {
 
         int sumOfSignableEntries = JarCertVerifier.getTotalJarEntries(jcv.getJarSignableEntries());
@@ -118,9 +120,12 @@
                     dialogType = AccessType.UNVERIFIED;
                 }
 
-                boolean wasApproved = SecurityDialogs.showCertWarningDialog(
+                AppletAction action = SecurityDialogs.showCertWarningDialog(
                         dialogType, file, jcv);
-                if (wasApproved) {
+                if (action != AppletAction.CANCEL) {
+                    if (action == AppletAction.SANDBOX) {
+                        securityDelegate.setRunInSandbox();
+                    }
                     return;
                 }
             }
--- a/netx/net/sourceforge/jnlp/security/PluginAppVerifier.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/security/PluginAppVerifier.java	Fri Feb 28 16:45:24 2014 -0500
@@ -46,7 +46,9 @@
 
 import net.sourceforge.jnlp.JNLPFile;
 import net.sourceforge.jnlp.LaunchException;
+import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate;
 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.security.SecurityDialogs.AppletAction;
 import net.sourceforge.jnlp.tools.CertInformation;
 import net.sourceforge.jnlp.tools.JarCertVerifier;
 
@@ -126,7 +128,7 @@
     }
 
     @Override
-    public void checkTrustWithUser(JarCertVerifier jcv, JNLPFile file)
+    public void checkTrustWithUser(SecurityDelegate securityDelegate, JarCertVerifier jcv, JNLPFile file)
             throws LaunchException {
         List<CertPath> certPaths = buildCertPathsList(jcv);
         List<CertPath> alreadyApprovedByUser = new ArrayList<CertPath>();
@@ -165,9 +167,12 @@
                         dialogType = AccessType.UNVERIFIED;
                     }
 
-                    boolean wasApproved = SecurityDialogs.showCertWarningDialog(
+                    AppletAction action = SecurityDialogs.showCertWarningDialog(
                             dialogType, file, jcv);
-                    if (wasApproved) {
+                    if (action != AppletAction.CANCEL) {
+                        if (action == AppletAction.SANDBOX) {
+                            securityDelegate.setRunInSandbox();
+                        }
                         alreadyApprovedByUser.add(cPath);
                         trustFoundOrApproved = true;
                         break;
--- a/netx/net/sourceforge/jnlp/security/SecurityDialogs.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/security/SecurityDialogs.java	Fri Feb 28 16:45:24 2014 -0500
@@ -98,6 +98,24 @@
         SIGNING_ERROR
     }
 
+    public static enum AppletAction {
+        RUN,
+        SANDBOX,
+        CANCEL;
+        public static AppletAction fromInteger(int i) {
+            switch (i) {
+                case 0:
+                    return RUN;
+                case 1:
+                    return SANDBOX;
+                case 2:
+                    return CANCEL;
+                default:
+                    return CANCEL;
+            }
+        }
+    }
+
     /**
      * Shows a warning dialog for different types of system access (i.e. file
      * open/save, clipboard read/write, printing, etc).
@@ -192,13 +210,15 @@
      * @param file the JNLPFile associated with this warning
      * @param certVerifier the JarCertVerifier used to verify this application
      *
-     * @return true if the user accepted the certificate
+     * @return RUN if the user accepted the certificate, SANDBOX if the user
+     * wants the applet to run with only sandbox permissions, or CANCEL if the
+     * user did not accept running the applet
      */
-    public static boolean showCertWarningDialog(AccessType accessType,
+    public static AppletAction showCertWarningDialog(AccessType accessType,
             JNLPFile file, CertVerifier certVerifier) {
 
         if (!shouldPromptUser()) {
-            return false;
+            return AppletAction.CANCEL;
         }
 
         final SecurityDialogMessage message = new SecurityDialogMessage();
@@ -209,7 +229,7 @@
 
         Object selectedValue = getUserResponse(message);
 
-        return getIntegerResponseAsBoolean(selectedValue);
+        return getIntegerResponseAsAppletAction(selectedValue);
     }
 
     /**
@@ -362,6 +382,13 @@
         return false;
     }
 
+    public static AppletAction getIntegerResponseAsAppletAction(Object ref) {
+        if (ref instanceof Integer) {
+            return AppletAction.fromInteger((Integer) ref);
+        }
+        return AppletAction.CANCEL;
+    }
+
     /**
      * Returns whether the current runtime configuration allows prompting user
      * for security warnings.
--- a/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java	Fri Feb 28 16:45:24 2014 -0500
@@ -58,6 +58,7 @@
 
 import net.sourceforge.jnlp.runtime.JNLPRuntime;
 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.security.SecurityDialogs.AppletAction;
 import net.sourceforge.jnlp.util.logging.OutputController;
 import sun.security.util.HostnameChecker;
 import sun.security.validator.ValidatorException;
@@ -417,7 +418,6 @@
         if (JNLPRuntime.isTrustAll()){
             return true;
         }
-        final VariableX509TrustManager trustManager = this;
         return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
             @Override
             public Boolean run() {
@@ -425,7 +425,7 @@
                         AccessType.UNVERIFIED, null,
                         new HttpsCertVerifier(chain, authType,
                                               isTrusted, hostMatched,
-                                              hostName));
+                                hostName)) == AppletAction.RUN;
             }
         });
     }
--- a/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java	Fri Feb 28 16:45:24 2014 -0500
@@ -41,17 +41,17 @@
 import java.util.Map;
 import java.util.Vector;
 import java.util.jar.JarEntry;
-import net.sourceforge.jnlp.util.JarFile;
 
 import net.sourceforge.jnlp.JARDesc;
 import net.sourceforge.jnlp.JNLPFile;
 import net.sourceforge.jnlp.LaunchException;
 import net.sourceforge.jnlp.cache.ResourceTracker;
-import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate;
 import net.sourceforge.jnlp.security.AppVerifier;
 import net.sourceforge.jnlp.security.CertVerifier;
 import net.sourceforge.jnlp.security.CertificateUtils;
 import net.sourceforge.jnlp.security.KeyStores;
+import net.sourceforge.jnlp.util.JarFile;
 import net.sourceforge.jnlp.util.logging.OutputController;
 import sun.security.util.DerInputStream;
 import sun.security.util.DerValue;
@@ -598,8 +598,8 @@
         return this.unverifiedJars.size() == 0;
     }
 
-    public void checkTrustWithUser(JNLPFile file) throws LaunchException {
-        appVerifier.checkTrustWithUser(this, file);
+    public void checkTrustWithUser(SecurityDelegate securityDelegate, JNLPFile file) throws LaunchException {
+        appVerifier.checkTrustWithUser(securityDelegate, this, file);
     }
 
     public Map<String, Integer> getJarSignableEntries() {
--- a/tests/netx/unit/net/sourceforge/jnlp/security/SecurityDialogsTest.java	Fri Feb 28 16:33:48 2014 -0500
+++ b/tests/netx/unit/net/sourceforge/jnlp/security/SecurityDialogsTest.java	Fri Feb 28 16:45:24 2014 -0500
@@ -36,9 +36,13 @@
 
 package net.sourceforge.jnlp.security;
 
+import static net.sourceforge.jnlp.security.SecurityDialogs.getIntegerResponseAsAppletAction;
 import static net.sourceforge.jnlp.security.SecurityDialogs.getIntegerResponseAsBoolean;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static net.sourceforge.jnlp.security.SecurityDialogs.AppletAction.*;
+
 import org.junit.Test;
 
 public class SecurityDialogsTest {
@@ -67,4 +71,33 @@
         assertFalse("Non-0 Integer reference should have resulted in false", getIntegerResponseAsBoolean(intRef1));
         assertTrue("0 Integer reference should have resulted in true", getIntegerResponseAsBoolean(intRef2));
     }
+
+    @Test
+    public void testGetIntegerResponseAsAppletAction() throws Exception {
+        Object nullRef = null;
+        Object objRef = new Object();
+        Float floatRef = new Float(0.0f);
+        Double doubleRef = new Double(0.0d);
+        Long longRef = new Long(0);
+        Byte byteRef = new Byte((byte) 0);
+        Short shortRef = new Short((short) 0);
+        String strRef = "0";
+        Integer intRef1 = new Integer(0);
+        Integer intRef2 = new Integer(1);
+        Integer intRef3 = new Integer(2);
+        Integer intRef4 = new Integer(3);
+
+        assertEquals("null reference should have resulted in CANCEL", getIntegerResponseAsAppletAction(nullRef), CANCEL);
+        assertEquals("Object reference should have resulted in CANCEL", getIntegerResponseAsAppletAction(objRef), CANCEL);
+        assertEquals("Float reference should have resulted in CANCEL", getIntegerResponseAsAppletAction(floatRef), CANCEL);
+        assertEquals("Double reference should have resulted in CANCEL", getIntegerResponseAsAppletAction(doubleRef), CANCEL);
+        assertEquals("Long reference should have resulted in CANCEL", getIntegerResponseAsAppletAction(longRef), CANCEL);
+        assertEquals("Byte reference should have resulted in CANCEL", getIntegerResponseAsAppletAction(byteRef), CANCEL);
+        assertEquals("Short reference should have resulted in CANCEL", getIntegerResponseAsAppletAction(shortRef), CANCEL);
+        assertEquals("String reference should have resulted in CANCEL", getIntegerResponseAsAppletAction(strRef), CANCEL);
+        assertEquals("Integer reference 0 should have resulted in RUN", getIntegerResponseAsAppletAction(intRef1), RUN);
+        assertEquals("Integer reference 1 should have resulted in SANDBOX", getIntegerResponseAsAppletAction(intRef2), SANDBOX);
+        assertEquals("Integer reference 2 should have resulted in CANCEL", getIntegerResponseAsAppletAction(intRef3), CANCEL);
+        assertEquals("Integer reference 3 should have resulted in CANCEL", getIntegerResponseAsAppletAction(intRef4), CANCEL);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/signed/RunInSandbox/resources/RunInSandbox.html	Fri Feb 28 16:45:24 2014 -0500
@@ -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="RunInSandbox.class"
+            archive="RunInSandbox.jar"
+            codebase="."
+            width="800"
+            height="600">
+    </applet>
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/signed/RunInSandbox/resources/RunInSandboxApplet.jnlp	Fri Feb 28 16:45:24 2014 -0500
@@ -0,0 +1,58 @@
+<!--
+
+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="RunInSandboxApplet.jnlp" codebase=".">
+  <information>
+    <title>UsesSignedJar</title>
+    <vendor>IcedTea</vendor>
+    <homepage href="http://icedtea.classpath.org/wiki/IcedTea-Web#Testing_IcedTea-Web"/>
+    <description>Test "Run in Sandbox" functionality for signed applets</description>
+    <offline/>
+  </information>
+
+  <security>
+      <all-permissions/>
+  </security>
+
+  <resources>
+    <j2se version="1.6+"/>
+    <jar href="RunInSandbox.jar" main="true"/>
+  </resources>
+
+  <application-desc main-class="RunInSandbox">
+  </application-desc>
+</jnlp>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/signed/RunInSandbox/resources/RunInSandboxApplication.jnlp	Fri Feb 28 16:45:24 2014 -0500
@@ -0,0 +1,58 @@
+<!--
+
+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="RunInSandboxApplication.jnlp" codebase=".">
+  <information>
+    <title>UsesSignedJar</title>
+    <vendor>IcedTea</vendor>
+    <homepage href="http://icedtea.classpath.org/wiki/IcedTea-Web#Testing_IcedTea-Web"/>
+    <description>Test "Run in Sandbox" functionality for signed applets</description>
+    <offline/>
+  </information>
+
+  <security>
+      <all-permissions/>
+  </security>
+
+  <resources>
+    <j2se version="1.6+"/>
+    <jar href="RunInSandbox.jar" main="true"/>
+  </resources>
+
+  <applet-desc main-class="RunInSandbox">
+  </applet-desc>
+</jnlp>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/signed/RunInSandbox/resources/RunInSandboxJnlpHref.html	Fri Feb 28 16:45:24 2014 -0500
@@ -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="RunInSandbox">
+		<param name="jnlp_href" value="RunInSandboxApplet.jnlp">
+	</applet>
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/signed/RunInSandbox/srcs/RunInSandbox.java	Fri Feb 28 16:45:24 2014 -0500
@@ -0,0 +1,23 @@
+import java.applet.Applet;
+
+public class RunInSandbox extends Applet {
+
+    @Override
+    public void start() {
+        System.out.println("RunInSandbox read: " + read("user.home"));
+        System.out.println("*** APPLET FINISHED ***");
+        System.exit(0);
+    }
+
+    public static void main(String[] args) {
+        new RunInSandbox().start();
+    }
+
+    private String read(String key) {
+        try {
+            return System.getProperty(key);
+        } catch (Exception e) {
+            return e.toString();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/signed/RunInSandbox/testcases/RunInSandboxTest.java	Fri Feb 28 16:45:24 2014 -0500
@@ -0,0 +1,95 @@
+/* RunInSandboxTest.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.closinglisteners.AutoOkClosingListener;
+import net.sourceforge.jnlp.browsertesting.BrowserTest;
+import java.util.List;
+import java.util.Collections;
+import java.util.Arrays;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+public class RunInSandboxTest extends BrowserTest {
+
+    private final List<String> TRUSTALL = Collections.unmodifiableList(Arrays.asList(new String[] { "-Xtrustall" }));
+    private final List<String> TRUSTNONE = Collections.unmodifiableList(Arrays.asList(new String[] { "-Xtrustnone" }));
+    private static final String appletCloseString = AutoOkClosingListener.MAGICAL_OK_CLOSING_STRING;
+
+    @Test
+    public void testTrustAllJnlpAppletLaunch() throws Exception {
+        ProcessResult pr = server.executeJavawsHeadless(TRUSTALL, "RunInSandboxApplet.jnlp");
+        assertReadProperty(pr);
+        assertProperClose(pr);
+    }
+
+    @Test
+    public void testTrustNoneJnlpAppletLaunch() throws Exception {
+        ProcessResult pr = server.executeJavawsHeadless(TRUSTNONE, "RunInSandboxApplet.jnlp");
+        assertAccessControlException(pr);
+        assertProperClose(pr);
+    }
+
+    @Test
+    public void testTrustAllStandardJnlpApplicationLaunch() throws Exception {
+        ProcessResult pr = server.executeJavawsHeadless(TRUSTALL, "RunInSandboxApplication.jnlp");
+        assertReadProperty(pr);
+        assertProperClose(pr);
+    }
+
+    @Test
+    public void testTrustNoneJnlpApplicationLaunch() throws Exception {
+        ProcessResult pr = server.executeJavawsHeadless(TRUSTNONE, "RunInSandboxApplication.jnlp");
+        assertAccessControlException(pr);
+        assertProperClose(pr);
+    }
+
+    private void assertProperClose(ProcessResult pr) {
+        assertTrue("applet should have closed correctly", pr.stdout.contains(appletCloseString));
+    }
+
+    private void assertReadProperty(ProcessResult pr) {
+        assertTrue("applet should have been able to read user.home", pr.stdout.contains(System.getProperty("user.home")));
+    }
+
+    private void assertAccessControlException(ProcessResult pr) {
+        String ace = "java.security.AccessControlException: access denied (\"java.util.PropertyPermission\" \"user.home\" \"read\")";
+        assertTrue("applet should not have been able to read user.home", pr.stdout.contains(ace));
+    }
+
+}