diff --git a/netx/net/sourceforge/jnlp/resources/Messages.properties b/netx/net/sourceforge/jnlp/resources/Messages.properties --- a/netx/net/sourceforge/jnlp/resources/Messages.properties +++ b/netx/net/sourceforge/jnlp/resources/Messages.properties @@ -302,6 +302,8 @@ SAuthenticationPrompt=The {0} server at SJNLPFileIsNotSigned=This application contains a digital signature in which the launching JNLP file is not signed. SAppletTitle=Applet title: {0} STrustedOnlyAttributeFailure=This application specifies Trusted-only as True in its Manifest. {0} and requests permission level: {1}. This is not allowed. +STempPermNoFile=No file access +STempPermNoNetwork=No network access # Security - used for the More Information dialog SBadKeyUsage=Resources contain entries whose signer certificate's KeyUsage extension doesn't allow code signing. diff --git a/netx/net/sourceforge/jnlp/security/Permissions.java b/netx/net/sourceforge/jnlp/security/Permissions.java new file mode 100644 --- /dev/null +++ b/netx/net/sourceforge/jnlp/security/Permissions.java @@ -0,0 +1,24 @@ +package net.sourceforge.jnlp.security; + +import java.awt.AWTPermission; +import java.io.FilePermission; +import java.net.SocketPermission; +import java.security.Permission; +import java.util.PropertyPermission; + +import javax.sound.sampled.AudioPermission; + +public class Permissions { + + public static final Permission READ_LOCAL_FILES = new FilePermission("${user.home}${/}*", "read"); + public static final Permission WRITE_LOCAL_FILES = new FilePermission("${user.home}${/}*", "write"); + public static final Permission READ_TMP_FILES = new FilePermission("${java.io.tmpdir}${/}*", "read"); + public static final Permission WRITE_TMP_FILES = new FilePermission("${java.io.tmpdir}${/}*", "write"); + public static final Permission READ_PROPERTIES = new PropertyPermission("*", "read"); + public static final Permission WRITE_PROPERTIES = new PropertyPermission("*", "write"); + public static final Permission NETWORK_ACCESS = new SocketPermission("*", "listen,connect,accept,resolve"); + public static final Permission CLIPBOARD_ACCESS = new AWTPermission("accessClipboard"); + public static final Permission PRINT_DOCUMENTS = new RuntimePermission("queuePrintJob"); + public static final Permission PLAY_AUDIO = new AudioPermission("play"); + +} diff --git a/netx/net/sourceforge/jnlp/security/SecurityDialog.java b/netx/net/sourceforge/jnlp/security/SecurityDialog.java --- a/netx/net/sourceforge/jnlp/security/SecurityDialog.java +++ b/netx/net/sourceforge/jnlp/security/SecurityDialog.java @@ -315,7 +315,7 @@ public class SecurityDialog extends JDia else if (dialogType == DialogType.APPLET_WARNING) panel = new AppletWarningPane(this, this.certVerifier); else if (dialogType == DialogType.PARTIALLYSIGNED_WARNING) - panel = AppTrustWarningDialog.partiallySigned(this, file); + panel = AppTrustWarningDialog.partiallySigned(this, file, (SecurityDelegate) extras[0]); else if (dialogType == DialogType.UNSIGNED_WARNING) // Only necessary for applets on 'high security' or above panel = AppTrustWarningDialog.unsigned(this, file); else if (dialogType == DialogType.AUTHENTICATION) diff --git a/netx/net/sourceforge/jnlp/security/SecurityDialogs.java b/netx/net/sourceforge/jnlp/security/SecurityDialogs.java --- a/netx/net/sourceforge/jnlp/security/SecurityDialogs.java +++ b/netx/net/sourceforge/jnlp/security/SecurityDialogs.java @@ -221,13 +221,15 @@ public class SecurityDialogs { * * @return true if permission was granted by the user, false otherwise. */ - public static AppSigningWarningAction showPartiallySignedWarningDialog(JNLPFile file, CertVerifier certVerifier) { + public static AppSigningWarningAction showPartiallySignedWarningDialog(JNLPFile file, CertVerifier certVerifier, + SecurityDelegate securityDelegate) { final SecurityDialogMessage message = new SecurityDialogMessage(); message.dialogType = DialogType.PARTIALLYSIGNED_WARNING; message.accessType = AccessType.PARTIALLYSIGNED; message.file = file; message.certVerifier = certVerifier; + message.extras = new Object[] { securityDelegate }; return (AppSigningWarningAction) getUserResponse(message); } diff --git a/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java b/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java --- a/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java +++ b/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java @@ -239,7 +239,7 @@ public class UnsignedAppletTrustConfirma appletOK = false; } else { // No remembered decision, prompt the user - AppSigningWarningAction warningResponse = SecurityDialogs.showPartiallySignedWarningDialog(file, certVerifier); + AppSigningWarningAction warningResponse = SecurityDialogs.showPartiallySignedWarningDialog(file, certVerifier, securityDelegate); ExecuteAppletAction executeAction = warningResponse.getAction(); if (executeAction == ExecuteAppletAction.SANDBOX) { diff --git a/netx/net/sourceforge/jnlp/security/dialogs/CertWarningPane.java b/netx/net/sourceforge/jnlp/security/dialogs/CertWarningPane.java --- a/netx/net/sourceforge/jnlp/security/dialogs/CertWarningPane.java +++ b/netx/net/sourceforge/jnlp/security/dialogs/CertWarningPane.java @@ -55,8 +55,11 @@ import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.security.KeyStore; +import java.security.Permission; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collection; import javax.swing.BorderFactory; import javax.swing.BoxLayout; @@ -80,6 +83,7 @@ import net.sourceforge.jnlp.security.Htt import net.sourceforge.jnlp.security.KeyStores; import net.sourceforge.jnlp.security.KeyStores.Level; import net.sourceforge.jnlp.security.KeyStores.Type; +import net.sourceforge.jnlp.security.Permissions; import net.sourceforge.jnlp.security.SecurityDialog; import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; import net.sourceforge.jnlp.security.SecurityUtil; @@ -311,14 +315,45 @@ public class CertWarningPane extends Sec private void createPolicyPermissionsMenu() { policyMenu = new JPopupMenu(); - JMenuItem launchPolicyEditor = new JMenuItem(R("CertWarnPolicyEditorItem")); + final JMenuItem launchPolicyEditor = new JMenuItem(R("CertWarnPolicyEditorItem")); launchPolicyEditor.addActionListener(new PolicyEditorLaunchListener()); + policyMenu.add(launchPolicyEditor); - policyMenu.add(launchPolicyEditor); + policyMenu.addSeparator(); + + final JMenuItem noFileAccess = new JMenuItem(R("STempPermNoFile")); + noFileAccess.addActionListener(new TemporaryPermissionsListener( + Permissions.NETWORK_ACCESS, Permissions.READ_PROPERTIES, Permissions.WRITE_PROPERTIES, + Permissions.CLIPBOARD_ACCESS, Permissions.PLAY_AUDIO, Permissions.PRINT_DOCUMENTS)); + policyMenu.add(noFileAccess); + + final JMenuItem noNetworkAccess = new JMenuItem(R("STempPermNoNetwork")); + noNetworkAccess.addActionListener(new TemporaryPermissionsListener( + Permissions.READ_LOCAL_FILES, Permissions.WRITE_LOCAL_FILES, + Permissions.READ_TMP_FILES, Permissions.WRITE_TMP_FILES, + Permissions.READ_PROPERTIES, Permissions.WRITE_PROPERTIES, + Permissions.CLIPBOARD_ACCESS, Permissions.PLAY_AUDIO, Permissions.PRINT_DOCUMENTS)); + policyMenu.add(noNetworkAccess); + policyMenu.setSize(policyMenu.getMinimumSize()); policyMenu.setVisible(false); } + private class TemporaryPermissionsListener implements ActionListener { + private Collection permissions; + + public TemporaryPermissionsListener(final Permission... permissions) { + this.permissions = Arrays.asList(permissions); + } + + @Override + public void actionPerformed(final ActionEvent e) { + securityDelegate.addPermissions(permissions); + policyMenu.setVisible(false); + sandbox.doClick(); + } + } + private class PolicyEditorLaunchListener implements ActionListener { @Override public void actionPerformed(final ActionEvent e) { diff --git a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java --- a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java +++ b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java @@ -37,10 +37,11 @@ exception statement from your version. package net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel; import net.sourceforge.jnlp.JNLPFile; +import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate; import net.sourceforge.jnlp.security.SecurityDialog; +import net.sourceforge.jnlp.security.dialogs.SecurityDialogPanel; import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.AppTrustWarningPanel.ActionChoiceListener; import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.AppTrustWarningPanel.AppSigningWarningAction; -import net.sourceforge.jnlp.security.dialogs.SecurityDialogPanel; /** * A panel that confirms that the user is OK with unsigned code running. @@ -57,9 +58,9 @@ public class AppTrustWarningDialog exten return warningDialog; } - public static AppTrustWarningDialog partiallySigned(final SecurityDialog dialog, final JNLPFile file) { + public static AppTrustWarningDialog partiallySigned(final SecurityDialog dialog, final JNLPFile file, final SecurityDelegate securityDelegate) { final AppTrustWarningDialog warningDialog = new AppTrustWarningDialog(dialog); - warningDialog.add(new PartiallySignedAppTrustWarningPanel(file, warningDialog.getActionChoiceListener(), dialog)); + warningDialog.add(new PartiallySignedAppTrustWarningPanel(file, warningDialog.getActionChoiceListener(), dialog, securityDelegate)); return warningDialog; } diff --git a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java --- a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java +++ b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java @@ -8,8 +8,11 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.net.MalformedURLException; import java.net.URL; +import java.security.Permission; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collection; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -20,6 +23,8 @@ import net.sourceforge.jnlp.JNLPFile; import net.sourceforge.jnlp.PluginBridge; import net.sourceforge.jnlp.config.DeploymentConfiguration; import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate; +import net.sourceforge.jnlp.security.Permissions; import net.sourceforge.jnlp.security.SecurityDialog; import net.sourceforge.jnlp.security.SecurityUtil; import net.sourceforge.jnlp.security.appletextendedsecurity.ExecuteAppletAction; @@ -34,11 +39,14 @@ public class PartiallySignedAppTrustWarn private final JButton sandboxButton; private final JButton advancedOptionsButton; private final JPopupMenu policyMenu; + private final SecurityDelegate securityDelegate; private PolicyEditor policyEditor = null; - public PartiallySignedAppTrustWarningPanel(JNLPFile file, ActionChoiceListener actionChoiceListener, SecurityDialog securityDialog) { + public PartiallySignedAppTrustWarningPanel(JNLPFile file, ActionChoiceListener actionChoiceListener, + SecurityDialog securityDialog, SecurityDelegate securityDelegate) { super(file, actionChoiceListener); this.jcv = (JarCertVerifier) securityDialog.getCertVerifier(); + this.securityDelegate = securityDelegate; this.INFO_PANEL_HEIGHT = 200; sandboxButton = new JButton(); @@ -154,16 +162,47 @@ public class PartiallySignedAppTrustWarn private JPopupMenu createPolicyPermissionsMenu() { final JPopupMenu policyMenu = new JPopupMenu(); - JMenuItem launchPolicyEditor = new JMenuItem(R("CertWarnPolicyEditorItem")); + final JMenuItem launchPolicyEditor = new JMenuItem(R("CertWarnPolicyEditorItem")); launchPolicyEditor.addActionListener(new PolicyEditorLaunchListener()); + policyMenu.add(launchPolicyEditor); - policyMenu.add(launchPolicyEditor); + policyMenu.addSeparator(); + + final JMenuItem noFileAccess = new JMenuItem(R("STempPermNoFile")); + noFileAccess.addActionListener(new TemporaryPermissionsListener( + Permissions.NETWORK_ACCESS, Permissions.READ_PROPERTIES, Permissions.WRITE_PROPERTIES, + Permissions.CLIPBOARD_ACCESS, Permissions.PLAY_AUDIO, Permissions.PRINT_DOCUMENTS)); + policyMenu.add(noFileAccess); + + final JMenuItem noNetworkAccess = new JMenuItem(R("STempPermNoNetwork")); + noNetworkAccess.addActionListener(new TemporaryPermissionsListener( + Permissions.READ_LOCAL_FILES, Permissions.WRITE_LOCAL_FILES, + Permissions.READ_TMP_FILES, Permissions.WRITE_TMP_FILES, + Permissions.READ_PROPERTIES, Permissions.WRITE_PROPERTIES, + Permissions.CLIPBOARD_ACCESS, Permissions.PLAY_AUDIO, Permissions.PRINT_DOCUMENTS)); + policyMenu.add(noNetworkAccess); + policyMenu.setSize(policyMenu.getMinimumSize()); policyMenu.setVisible(false); return policyMenu; } + private class TemporaryPermissionsListener implements ActionListener { + private Collection permissions; + + public TemporaryPermissionsListener(final Permission... permissions) { + this.permissions = Arrays.asList(permissions); + } + + @Override + public void actionPerformed(final ActionEvent e) { + securityDelegate.addPermissions(permissions); + policyMenu.setVisible(false); + sandboxButton.doClick(); + } + } + private class PolicyEditorLaunchListener implements ActionListener { @Override public void actionPerformed(final ActionEvent e) {