Mercurial > hg > release > icedtea-web-1.5
changeset 957:ede0279b5c53
Applets can be granted temporary permissions from security dialogs
Applets can be temporarily granted permission levels above fully sandboxed
but below all-permission
* netx/net/sourceforge/jnlp/resources/Messages.properties:
(STempPermNoFile, STempPermNoNetwork, STempPermNoExec,
STempPermNoFileOrNetwork, STempPermNoExecOrNetwork, STempPermNoFileOrExec,
STempPermNoFileOrNetworkOrExec, STempAllMedia, STempSoundOnly,
STempClipboardOnly, STempPrintOnly, STempAllFileAndPropertyAccess,
STempReadLocalFilesAndProperties, STempReflectionOnly): new messages
* netx/net/sourceforge/jnlp/security/SecurityDialog.java: (installPanel)
pass SecurityDelegate to partially signed dialog
* netx/net/sourceforge/jnlp/security/SecurityDialogs.java:
(showPartiallySignedWarningDialog) added SecutityDelegate param for
message extras
* netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java:
(checkPartiallySignedWithUserIfRequired) added SecurityDelegate param
* netx/net/sourceforge/jnlp/security/dialogs/CertWarningPane.java:
(createPolicyPermissionsMenu, PolicyEditorLaunchListener,
PolicyEditorPopupListener) removed in favour of TemporaryPermissionsButton
* netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java:
same
* netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java:
(partiallySigned) SecurityDelegate param
* netx/net/sourceforge/jnlp/security/policyeditor/PermissionActions.java:
(DELETE, READLINK, FILE_ALL) new actions. (rawActions, rawString) can
retrieve raw String representation of the action
* netx/net/sourceforge/jnlp/security/policyeditor/PermissionTarget.java:
(USER_HOME, TMPDIR) grant permissions to entire directory, not only
children
* netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java:
(DELETE_LOCAL_FILES, DELETE_TMP_FILES) new permissions.
(Group.WriteFileSystem) added DELETE* permissions
* nests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorParsingTest.java:
update for change in PermissionTarget
* netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissions.java:
new class
* netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissionsButton.java:
new class
line wrap: on
line diff
--- a/ChangeLog Thu Mar 27 14:08:54 2014 +0100 +++ b/ChangeLog Thu Mar 27 11:08:09 2014 -0400 @@ -1,3 +1,43 @@ +2014-03-27 Andrew Azores <aazores@redhat.com> + + Applets can be temporarily granted permission levels above fully sandboxed + but below all-permission + * netx/net/sourceforge/jnlp/resources/Messages.properties: + (STempPermNoFile, STempPermNoNetwork, STempPermNoExec, + STempPermNoFileOrNetwork, STempPermNoExecOrNetwork, STempPermNoFileOrExec, + STempPermNoFileOrNetworkOrExec, STempAllMedia, STempSoundOnly, + STempClipboardOnly, STempPrintOnly, STempAllFileAndPropertyAccess, + STempReadLocalFilesAndProperties, STempReflectionOnly): new messages + * netx/net/sourceforge/jnlp/security/SecurityDialog.java: (installPanel) + pass SecurityDelegate to partially signed dialog + * netx/net/sourceforge/jnlp/security/SecurityDialogs.java: + (showPartiallySignedWarningDialog) added SecutityDelegate param for + message extras + * netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java: + (checkPartiallySignedWithUserIfRequired) added SecurityDelegate param + * netx/net/sourceforge/jnlp/security/dialogs/CertWarningPane.java: + (createPolicyPermissionsMenu, PolicyEditorLaunchListener, + PolicyEditorPopupListener) removed in favour of TemporaryPermissionsButton + * netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java: + same + * netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java: + (partiallySigned) SecurityDelegate param + * netx/net/sourceforge/jnlp/security/policyeditor/PermissionActions.java: + (DELETE, READLINK, FILE_ALL) new actions. (rawActions, rawString) can + retrieve raw String representation of the action + * netx/net/sourceforge/jnlp/security/policyeditor/PermissionTarget.java: + (USER_HOME, TMPDIR) grant permissions to entire directory, not only + children + * netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java: + (DELETE_LOCAL_FILES, DELETE_TMP_FILES) new permissions. + (Group.WriteFileSystem) added DELETE* permissions + * nests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorParsingTest.java: + update for change in PermissionTarget + * netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissions.java: + new class + * netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissionsButton.java: + new class + 2014-03-27 Jiri Vanek <jvanek@redhat.com> Clenaup in PolicyEditor tests and MVC
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/resources/Messages.properties Thu Mar 27 11:08:09 2014 -0400 @@ -305,6 +305,20 @@ STOAsignedMsgFully = The applet is fully signed STOAsignedMsgAndSandbox = The applet is fully signed and sandboxed STOAsignedMsgPartiall = The applet is not fully signed +STempPermNoFile=No file access +STempPermNoNetwork=No network access +STempPermNoExec=No command execution +STempNoFileOrNetwork=No file or network access +STempNoExecOrNetwork=No command execution or network access +STempNoFileOrExec=No file access or command execution +STempNoFileOrNetworkOrExec=No file access, network access, or command execution +STempAllMedia=All media +STempSoundOnly=Play audio +STempClipboardOnly=Access clipboard +STempPrintOnly=Print documents +STempAllFileAndPropertyAccess=All file and properties access +STempReadLocalFilesAndProperties=Read-only local files and properties +STempReflectionOnly=Java Reflection only # Security - used for the More Information dialog SBadKeyUsage=Resources contain entries whose signer certificate's KeyUsage extension doesn't allow code signing. @@ -501,6 +515,8 @@ PEReadFilesDetail=Allow applets to read from files in your home directory PEWriteFiles=Write to local files PEWriteFilesDetail=Allow applets to write to files in your home directory +PEDeleteFiles=Delete local files +PEDeleteFilesDetail=Allow applets to delete files in your home directory PEReadSystemFiles=Read all system files PEReadSystemFilesDetail=Allow applets read-only access to all locations on your computer PEWriteSystemFiles=Write all system files @@ -509,6 +525,8 @@ PEReadTempFilesDetail=Allow applets to read from your temporary files directory PEWriteTempFiles=Write to temp files PEWriteTempFilesDetail=Allow applets to write to your temporary files directory +PEDeleteTempFiles=Delete temp files +PEDeleteTempFilesDetail=Allow applets to delete files in your temporary files directory PEAWTPermission=Window System Access PEAWTPermissionDetail=Allow applets all AWT windowing system access PEClipboard=Access clipboard
--- a/netx/net/sourceforge/jnlp/security/SecurityDialog.java Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/security/SecurityDialog.java Thu Mar 27 11:08:09 2014 -0400 @@ -315,7 +315,7 @@ 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)
--- a/netx/net/sourceforge/jnlp/security/SecurityDialogs.java Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/security/SecurityDialogs.java Thu Mar 27 11:08:09 2014 -0400 @@ -221,13 +221,15 @@ * * @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); }
--- a/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java Thu Mar 27 11:08:09 2014 -0400 @@ -239,7 +239,7 @@ 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) {
--- a/netx/net/sourceforge/jnlp/security/dialogs/CertWarningPane.java Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/security/dialogs/CertWarningPane.java Thu Mar 27 11:08:09 2014 -0400 @@ -41,20 +41,15 @@ import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Dialog.ModalityType; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URL; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.X509Certificate; @@ -65,16 +60,13 @@ import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; -import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.SwingConstants; import net.sourceforge.jnlp.JNLPFile; import net.sourceforge.jnlp.PluginBridge; -import net.sourceforge.jnlp.config.DeploymentConfiguration; import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate; -import net.sourceforge.jnlp.runtime.JNLPRuntime; import net.sourceforge.jnlp.security.CertVerifier; import net.sourceforge.jnlp.security.CertificateUtils; import net.sourceforge.jnlp.security.HttpsCertVerifier; @@ -84,7 +76,6 @@ import net.sourceforge.jnlp.security.SecurityDialog; import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; import net.sourceforge.jnlp.security.SecurityUtil; -import net.sourceforge.jnlp.security.policyeditor.PolicyEditor; import net.sourceforge.jnlp.security.policyeditor.PolicyEditor.PolicyEditorWindow; import net.sourceforge.jnlp.util.FileUtils; import net.sourceforge.jnlp.util.logging.OutputController; @@ -225,8 +216,6 @@ } private void addButtons() { - createPolicyPermissionsMenu(); - alwaysTrust = new JCheckBox(R("SAlwaysTrustPublisher")); alwaysTrust.setEnabled(true); alwaysTrust.setSelected(alwaysTrustSelected); @@ -246,7 +235,7 @@ buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); run = new JButton(R("ButRun")); sandbox = new JButton(R("ButSandbox")); - advancedOptions = new JButton("\u2630"); // "hamburger" navicon + advancedOptions = new TemporaryPermissionsButton(file, securityDelegate, sandbox); cancel = new JButton(R("ButCancel")); run.setToolTipText(R("CertWarnRunTip")); @@ -273,8 +262,6 @@ sandbox.addActionListener(createSetValueListener(parent, 1)); - advancedOptions.addMouseListener(new PolicyEditorPopupListener()); - cancel.addActionListener(createSetValueListener(parent, 2)); initialFocusComponent = cancel; @@ -310,65 +297,6 @@ add(bottomPanel); } - private void createPolicyPermissionsMenu() { - policyMenu = new JPopupMenu(); - - JMenuItem launchPolicyEditor = new JMenuItem(R("CertWarnPolicyEditorItem")); - launchPolicyEditor.addActionListener(new PolicyEditorLaunchListener()); - - policyMenu.add(launchPolicyEditor); - policyMenu.setSize(policyMenu.getMinimumSize()); - policyMenu.setVisible(false); - } - - private class PolicyEditorLaunchListener implements ActionListener { - @Override - public void actionPerformed(final ActionEvent e) { - final String rawFilepath = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_SECURITY_POLICY); - String filepath; - try { - filepath = new URL(rawFilepath).getPath(); - } catch (final MalformedURLException mfue) { - filepath = null; - } - - if (policyEditor == null || policyEditor.getPolicyEditor().isClosed()) { - policyEditor = PolicyEditor.getPolicyEditorDialog(filepath); - } else { - policyEditor.asWindow().toFront(); - policyEditor.asWindow().repaint(); - } - policyEditor.setModalityType(ModalityType.DOCUMENT_MODAL); - policyEditor.getPolicyEditor().addNewCodebase(file.getCodeBase().toString()); - policyEditor.asWindow().setVisible(true); - policyMenu.setVisible(false); - } - } - - private class PolicyEditorPopupListener implements MouseListener { - @Override - public void mouseClicked(final MouseEvent e) { - policyMenu.setLocation(e.getLocationOnScreen()); - policyMenu.setVisible(!policyMenu.isVisible()); - } - - @Override - public void mousePressed(final MouseEvent e) { - } - - @Override - public void mouseReleased(final MouseEvent e) { - } - - @Override - public void mouseEntered(final MouseEvent e) { - } - - @Override - public void mouseExited(final MouseEvent e) { - } - } - private class MoreInfoButtonListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissions.java Thu Mar 27 11:08:09 2014 -0400 @@ -0,0 +1,204 @@ +/* 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. + */ + +package net.sourceforge.jnlp.security.dialogs; + +import java.awt.AWTPermission; +import java.io.FilePermission; +import java.lang.reflect.ReflectPermission; +import java.net.SocketPermission; +import java.security.Permission; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.PropertyPermission; + +import javax.sound.sampled.AudioPermission; + +import static net.sourceforge.jnlp.security.policyeditor.PolicyEditorPermissions.*; + +public class TemporaryPermissions { + + // We can't use the PolicyEditorPermissions versions of these, because they rely on System Property expansion, which is perfomed + // by the policy parser, but not by the Permissions constructors. + private static final String USER_HOME = System.getProperty("user.home"); + private static final String TMPDIR = System.getProperty("java.io.tmpdir"); + + public static final FilePermission READ_LOCAL_FILES_PERMISSION = new FilePermission(USER_HOME, READ_LOCAL_FILES.getActions().rawString()); + public static final FilePermission WRITE_LOCAL_FILES_PERMISSION = new FilePermission(USER_HOME, WRITE_LOCAL_FILES.getActions().rawString()); + public static final FilePermission DELETE_LOCAL_FILES_PERMISSION = new FilePermission(USER_HOME, DELETE_LOCAL_FILES.getActions().rawString()); + public static final FilePermission READ_TMP_FILES_PERMISSION = new FilePermission(TMPDIR, READ_TMP_FILES.getActions().rawString()); + public static final FilePermission WRITE_TMP_FILES_PERMISSION = new FilePermission(TMPDIR, WRITE_TMP_FILES.getActions().rawString()); + public static final FilePermission DELETE_TMP_FILES_PERMISSION = new FilePermission(TMPDIR, DELETE_TMP_FILES.getActions().rawString()); + public static final FilePermission READ_SYSTEM_FILES_PERMISSION = new FilePermission(READ_SYSTEM_FILES.getTarget().target, READ_SYSTEM_FILES.getActions() + .rawString()); + public static final FilePermission WRITE_SYSTEM_FILES_PERMISSION = new FilePermission(WRITE_SYSTEM_FILES.getTarget().target, WRITE_SYSTEM_FILES + .getActions().rawString()); + + public static final PropertyPermission READ_PROPERTIES_PERMISSION = new PropertyPermission(READ_PROPERTIES.getTarget().target, READ_PROPERTIES.getActions() + .rawString()); + public static final PropertyPermission WRITE_PROPERTIES_PERMISSION = new PropertyPermission(WRITE_PROPERTIES.getTarget().target, WRITE_PROPERTIES + .getActions().rawString()); + + public static final FilePermission EXEC_PERMISSION = new FilePermission(EXEC_COMMANDS.getTarget().target, EXEC_COMMANDS.getActions().rawString()); + public static final RuntimePermission GETENV_PERMISSION = new RuntimePermission(GET_ENV.getTarget().target); + + public static final SocketPermission NETWORK_PERMISSION = new SocketPermission(NETWORK.getTarget().target, NETWORK.getActions().rawString()); + + public static final ReflectPermission REFLECTION_PERMISSION = new ReflectPermission(JAVA_REFLECTION.getTarget().target); + public static final RuntimePermission CLASSLOADER_PERMISSION = new RuntimePermission(GET_CLASSLOADER.getTarget().target); + public static final RuntimePermission ACCESS_CLASS_IN_PACKAGE_PERMISSION = new RuntimePermission(ACCESS_CLASS_IN_PACKAGE.getTarget().target); + public static final RuntimePermission ACCESS_DECLARED_MEMBERS_PERMISSION = new RuntimePermission(ACCESS_DECLARED_MEMBERS.getTarget().target); + + public static final AWTPermission AWT_PERMISSION = new AWTPermission(ALL_AWT.getTarget().target); + public static final AudioPermission PLAY_AUDIO_PERMISSION = new AudioPermission(PLAY_AUDIO.getTarget().target); + public static final AudioPermission RECORD_AUDIO_PERMISSION = new AudioPermission(RECORD_AUDIO.getTarget().target); + public static final AWTPermission CLIPBOARD_PERMISSION = new AWTPermission(CLIPBOARD.getTarget().target); + public static final RuntimePermission PRINT_PERMISSION = new RuntimePermission(PRINT.getTarget().target); + + public static final Collection<Permission> ALL_PERMISSIONS, FILE_PERMISSIONS, PROPERTY_PERMISSIONS, NETWORK_PERMISSIONS, EXEC_PERMISSIONS, + REFLECTION_PERMISSIONS, MEDIA_PERMISSIONS; + static { + final Collection<Permission> all = new HashSet<Permission>(), file = new HashSet<Permission>(), property = new HashSet<Permission>(), + network = new HashSet<Permission>(), exec = new HashSet<Permission>(), reflection = new HashSet<Permission>(), media = new HashSet<Permission>(); + + file.add(READ_LOCAL_FILES_PERMISSION); + file.add(WRITE_LOCAL_FILES_PERMISSION); + file.add(DELETE_LOCAL_FILES_PERMISSION); + file.add(READ_TMP_FILES_PERMISSION); + file.add(WRITE_TMP_FILES_PERMISSION); + file.add(DELETE_TMP_FILES_PERMISSION); + file.add(READ_SYSTEM_FILES_PERMISSION); + file.add(WRITE_SYSTEM_FILES_PERMISSION); + FILE_PERMISSIONS = Collections.unmodifiableCollection(file); + + property.add(READ_PROPERTIES_PERMISSION); + property.add(WRITE_PROPERTIES_PERMISSION); + PROPERTY_PERMISSIONS = Collections.unmodifiableCollection(property); + + exec.add(EXEC_PERMISSION); + exec.add(GETENV_PERMISSION); + EXEC_PERMISSIONS = Collections.unmodifiableCollection(exec); + + network.add(NETWORK_PERMISSION); + NETWORK_PERMISSIONS = Collections.unmodifiableCollection(network); + + reflection.add(REFLECTION_PERMISSION); + reflection.add(CLASSLOADER_PERMISSION); + reflection.add(ACCESS_CLASS_IN_PACKAGE_PERMISSION); + reflection.add(ACCESS_DECLARED_MEMBERS_PERMISSION); + REFLECTION_PERMISSIONS = Collections.unmodifiableCollection(reflection); + + media.add(AWT_PERMISSION); + media.add(PLAY_AUDIO_PERMISSION); + media.add(RECORD_AUDIO_PERMISSION); + media.add(CLIPBOARD_PERMISSION); + media.add(PRINT_PERMISSION); + MEDIA_PERMISSIONS = Collections.unmodifiableCollection(media); + + all.addAll(file); + all.addAll(property); + all.addAll(exec); + all.addAll(network); + all.addAll(reflection); + all.addAll(media); + ALL_PERMISSIONS = Collections.unmodifiableCollection(all); + } + + private static final Collection<Permission> allMinus(final Collection<Permission> permissions) { + return subtract(ALL_PERMISSIONS, permissions); + } + + private static Collection<Permission> sum(final Permission... permissions) { + final Collection<Permission> result = new HashSet<Permission>(Arrays.asList(permissions)); + return Collections.unmodifiableCollection(result); + } + + private static Collection<Permission> sum(final Collection<Permission> a, final Collection<Permission> b) { + final Collection<Permission> result = new HashSet<Permission>(); + result.addAll(a); + result.addAll(b); + return Collections.unmodifiableCollection(result); + } + + private static final Collection<Permission> subtract(final Collection<Permission> from, final Collection<Permission> remove) { + final Collection<Permission> result = new HashSet<Permission>(from); + result.removeAll(remove); + return Collections.unmodifiableCollection(result); + } + + public static Collection<Permission> noFileAccess() { + return allMinus(FILE_PERMISSIONS); + } + + public static Collection<Permission> noNetworkAccess() { + return allMinus(Arrays.asList(new Permission[] { NETWORK_PERMISSION })); + } + + public static Collection<Permission> noFileOrNetworkAccess() { + return subtract(allMinus(FILE_PERMISSIONS), NETWORK_PERMISSIONS); + } + + public static Collection<Permission> allFileAccessAndProperties() { + return sum(FILE_PERMISSIONS, PROPERTY_PERMISSIONS); + } + + public static Collection<Permission> readLocalFilesAndProperties() { + return sum(READ_LOCAL_FILES_PERMISSION, READ_PROPERTIES_PERMISSION); + } + + public static Collection<Permission> reflectionOnly() { + return REFLECTION_PERMISSIONS; + } + + public static Collection<Permission> allMedia() { + return MEDIA_PERMISSIONS; + } + + public static Collection<Permission> audioOnly() { + return sum(PLAY_AUDIO_PERMISSION, RECORD_AUDIO_PERMISSION); + } + + public static Collection<Permission> clipboardOnly() { + return sum(CLIPBOARD_PERMISSION); + } + + public static Collection<Permission> printOnly() { + return sum(PRINT_PERMISSION); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/security/dialogs/TemporaryPermissionsButton.java Thu Mar 27 11:08:09 2014 -0400 @@ -0,0 +1,191 @@ +/* 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. + */ + +package net.sourceforge.jnlp.security.dialogs; + +import static net.sourceforge.jnlp.runtime.Translator.R; + +import java.awt.Component; +import java.awt.Dialog.ModalityType; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.Permission; +import java.util.Collection; + +import javax.swing.JButton; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +import net.sourceforge.jnlp.JNLPFile; +import net.sourceforge.jnlp.config.DeploymentConfiguration; +import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate; +import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.security.policyeditor.PolicyEditor; +import net.sourceforge.jnlp.security.policyeditor.PolicyEditor.PolicyEditorWindow; + +public class TemporaryPermissionsButton extends JButton { + + private final JPopupMenu menu; + private final JButton linkedButton; + private PolicyEditorWindow policyEditorWindow = null; + private final JNLPFile file; + private final SecurityDelegate securityDelegate; + + public TemporaryPermissionsButton(final JNLPFile file, final SecurityDelegate securityDelegate, final JButton linkedButton) { + super("\u2630"); + this.menu = createPolicyPermissionsMenu(); + this.linkedButton = linkedButton; + this.file = file; + this.securityDelegate = securityDelegate; + + addMouseListener(new PolicyEditorPopupListener(this)); + } + + private JPopupMenu createPolicyPermissionsMenu() { + final JPopupMenu policyMenu = new JPopupMenu(); + + final JMenuItem launchPolicyEditor = new JMenuItem(R("CertWarnPolicyEditorItem")); + launchPolicyEditor.addActionListener(new PolicyEditorLaunchListener()); + policyMenu.add(launchPolicyEditor); + + policyMenu.addSeparator(); + + + final JMenuItem noFileAccess = new JMenuItem(R("STempPermNoFile")); + noFileAccess.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.noFileAccess())); + policyMenu.add(noFileAccess); + + final JMenuItem noNetworkAccess = new JMenuItem(R("STempPermNoNetwork")); + noNetworkAccess.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.noNetworkAccess())); + policyMenu.add(noNetworkAccess); + + final JMenuItem noFileOrNetwork = new JMenuItem(R("STempNoFileOrNetwork")); + noFileOrNetwork.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.noFileOrNetworkAccess())); + policyMenu.add(noFileOrNetwork); + + policyMenu.addSeparator(); + + final JMenuItem allFileAccessOnly = new JMenuItem(R("STempAllFileAndPropertyAccess")); + allFileAccessOnly.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.allFileAccessAndProperties())); + policyMenu.add(allFileAccessOnly); + + final JMenuItem readLocalFilesAndProperties = new JMenuItem(R("STempReadLocalFilesAndProperties")); + readLocalFilesAndProperties.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.readLocalFilesAndProperties())); + policyMenu.add(readLocalFilesAndProperties); + + final JMenuItem reflectionOnly = new JMenuItem(R("STempReflectionOnly")); + reflectionOnly.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.reflectionOnly())); + policyMenu.add(reflectionOnly); + + policyMenu.addSeparator(); + + final JMenuItem allMedia = new JMenuItem(R("STempAllMedia")); + allMedia.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.allMedia())); + policyMenu.add(allMedia); + + final JMenuItem soundOnly = new JMenuItem(R("STempSoundOnly")); + soundOnly.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.audioOnly())); + policyMenu.add(soundOnly); + + final JMenuItem clipboardOnly = new JMenuItem(R("STempClipboardOnly")); + clipboardOnly.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.clipboardOnly())); + policyMenu.add(clipboardOnly); + + final JMenuItem printOnly = new JMenuItem(R("STempPrintOnly")); + printOnly.addActionListener(new TemporaryPermissionsListener(TemporaryPermissions.printOnly())); + policyMenu.add(printOnly); + + return policyMenu; + } + + private class TemporaryPermissionsListener implements ActionListener { + private Collection<Permission> permissions; + + public TemporaryPermissionsListener(final Collection<Permission> permissions) { + this.permissions = permissions; + } + + @Override + public void actionPerformed(final ActionEvent e) { + securityDelegate.addPermissions(permissions); + menu.setVisible(false); + if (linkedButton != null) { + linkedButton.doClick(); + } + } + } + + private class PolicyEditorLaunchListener implements ActionListener { + @Override + public void actionPerformed(final ActionEvent e) { + final String rawFilepath = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_SECURITY_POLICY); + String filepath; + try { + filepath = new URL(rawFilepath).getPath(); + } catch (final MalformedURLException mfue) { + filepath = null; + } + + if (policyEditorWindow == null || policyEditorWindow.getPolicyEditor().isClosed()) { + policyEditorWindow = PolicyEditor.getPolicyEditorDialog(filepath); + } else { + policyEditorWindow.asWindow().toFront(); + policyEditorWindow.asWindow().repaint(); + } + policyEditorWindow.setModalityType(ModalityType.DOCUMENT_MODAL); + policyEditorWindow.getPolicyEditor().addNewCodebase(file.getCodeBase().toString()); + policyEditorWindow.asWindow().setVisible(true); + menu.setVisible(false); + } + } + + private class PolicyEditorPopupListener extends MouseAdapter { + private final Component parent; + + public PolicyEditorPopupListener(final Component parent) { + this.parent = parent; + } + + @Override + public void mouseClicked(final MouseEvent e) { + menu.show(parent, e.getX(), e.getY()); + } + } +}
--- a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java Thu Mar 27 11:08:09 2014 -0400 @@ -37,10 +37,11 @@ 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 @@ 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; }
--- a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java Thu Mar 27 11:08:09 2014 -0400 @@ -1,32 +1,57 @@ +/* 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. + */ + package net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel; import static net.sourceforge.jnlp.runtime.Translator.R; -import java.awt.Dialog.ModalityType; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.net.MalformedURLException; -import java.net.URL; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import javax.swing.ImageIcon; import javax.swing.JButton; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; 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.SecurityDialog; import net.sourceforge.jnlp.security.SecurityUtil; import net.sourceforge.jnlp.security.appletextendedsecurity.ExecuteAppletAction; import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletTrustConfirmation; -import net.sourceforge.jnlp.security.policyeditor.PolicyEditor; -import net.sourceforge.jnlp.security.policyeditor.PolicyEditor.PolicyEditorWindow; +import net.sourceforge.jnlp.security.dialogs.TemporaryPermissionsButton; import net.sourceforge.jnlp.tools.CertInformation; import net.sourceforge.jnlp.tools.JarCertVerifier; @@ -35,10 +60,9 @@ private final JarCertVerifier jcv; private final JButton sandboxButton; private final JButton advancedOptionsButton; - private final JPopupMenu policyMenu; - private PolicyEditorWindow 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.INFO_PANEL_HEIGHT = 200; @@ -47,11 +71,7 @@ sandboxButton.setText(R("ButSandbox")); sandboxButton.addActionListener(chosenActionSetter(ExecuteAppletAction.SANDBOX)); - policyMenu = createPolicyPermissionsMenu(); - advancedOptionsButton = new JButton(); - advancedOptionsButton.setText("\u2630"); - advancedOptionsButton.addMouseListener(new PolicyEditorPopupListener()); - advancedOptionsButton.setToolTipText(R("CertWarnPolicyTip")); + advancedOptionsButton = new TemporaryPermissionsButton(file, securityDelegate, sandboxButton); buttons.add(1, sandboxButton); buttons.add(2, advancedOptionsButton); @@ -153,65 +173,4 @@ return htmlWrap(R(getQuestionPanelTextKey())); } - private JPopupMenu createPolicyPermissionsMenu() { - final JPopupMenu policyMenu = new JPopupMenu(); - - JMenuItem launchPolicyEditor = new JMenuItem(R("CertWarnPolicyEditorItem")); - launchPolicyEditor.addActionListener(new PolicyEditorLaunchListener()); - - policyMenu.add(launchPolicyEditor); - policyMenu.setSize(policyMenu.getMinimumSize()); - policyMenu.setVisible(false); - - return policyMenu; - } - - private class PolicyEditorLaunchListener implements ActionListener { - @Override - public void actionPerformed(final ActionEvent e) { - final String rawFilepath = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_SECURITY_POLICY); - String filepath; - try { - filepath = new URL(rawFilepath).getPath(); - } catch (final MalformedURLException mfue) { - filepath = null; - } - - if (policyEditor == null || policyEditor.getPolicyEditor().isClosed()) { - policyEditor = PolicyEditor.getPolicyEditorDialog(filepath); - } else { - policyEditor.asWindow().toFront(); - policyEditor.asWindow().repaint(); - } - policyEditor.setModalityType(ModalityType.DOCUMENT_MODAL); - policyEditor.getPolicyEditor().addNewCodebase(file.getCodeBase().toString()); - policyEditor.asWindow().setVisible(true); - policyMenu.setVisible(false); - } - } - - private class PolicyEditorPopupListener implements MouseListener { - @Override - public void mouseClicked(final MouseEvent e) { - policyMenu.setLocation(e.getLocationOnScreen()); - policyMenu.setVisible(!policyMenu.isVisible()); - } - - @Override - public void mousePressed(final MouseEvent e) { - } - - @Override - public void mouseReleased(final MouseEvent e) { - } - - @Override - public void mouseEntered(final MouseEvent e) { - } - - @Override - public void mouseExited(final MouseEvent e) { - } - } - }
--- a/netx/net/sourceforge/jnlp/security/policyeditor/PermissionActions.java Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PermissionActions.java Thu Mar 27 11:08:09 2014 -0400 @@ -50,15 +50,20 @@ READ("read"), WRITE("write"), EXECUTE("execute"), + DELETE("delete"), + READLINK("readlink"), + FILE_ALL("read,write,execute,delete,readlink"), ACCEPT("accept"), LISTEN("listen"), CONNECT("connect"), RESOLVE("resolve"), NETALL("accept,listen,connect,resolve"); + private final String rawActions; private final Set<String> actions; private PermissionActions(final String actions) { + this.rawActions = actions; this.actions = setFromString(actions); } @@ -87,4 +92,8 @@ Collections.addAll(set, string.split(",")); return set; } + + public String rawString() { + return rawActions; + } }
--- a/netx/net/sourceforge/jnlp/security/policyeditor/PermissionTarget.java Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PermissionTarget.java Thu Mar 27 11:08:09 2014 -0400 @@ -44,8 +44,8 @@ NONE(""), ALL("*"), ALL_FILES("<<ALL FILES>>"), - USER_HOME("${user.home}${/}*"), - TMPDIR("${java.io.tmpdir}${/}*"), + USER_HOME("${user.home}"), + TMPDIR("${java.io.tmpdir}"), CLIPBOARD("accessClipboard"), PRINT("queuePrintJob"), PLAY("play"),
--- a/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java Thu Mar 27 14:08:54 2014 +0100 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java Thu Mar 27 11:08:09 2014 -0400 @@ -53,6 +53,9 @@ WRITE_LOCAL_FILES(R("PEWriteFiles"), R("PEWriteFilesDetail"), PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.WRITE), + DELETE_LOCAL_FILES(R("PEDeleteFiles"), R("PEDeleteFilesDetail"), + PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.DELETE), + READ_PROPERTIES(R("PEReadProps"), R("PEReadPropsDetail"), PermissionType.PROPERTY_PERMISSION, PermissionTarget.ALL, PermissionActions.READ), @@ -71,6 +74,9 @@ WRITE_TMP_FILES(R("PEWriteTempFiles"), R("PEWriteTempFilesDetail"), PermissionType.FILE_PERMISSION, PermissionTarget.TMPDIR, PermissionActions.WRITE), + DELETE_TMP_FILES(R("PEDeleteTempFiles"), R("PEDeleteTempFilesDetail"), + PermissionType.FILE_PERMISSION, PermissionTarget.TMPDIR, PermissionActions.DELETE), + JAVA_REFLECTION(R("PEReflection"), R("PEReflectionDetail"), PermissionType.REFLECT_PERMISSION, PermissionTarget.REFLECT, PermissionActions.NONE), @@ -107,15 +113,13 @@ PRINT(R("PEPrint"), R("PEPrintDetail"), PermissionType.RUNTIME_PERMISSION, PermissionTarget.PRINT, PermissionActions.NONE); - public static enum Group { - ReadFileSystem(R("PEGReadFileSystem"), READ_LOCAL_FILES, READ_PROPERTIES, READ_SYSTEM_FILES, READ_TMP_FILES, GET_ENV), - WriteFileSystem(R("PEGWriteFileSystem"), WRITE_LOCAL_FILES, WRITE_PROPERTIES, WRITE_SYSTEM_FILES, WRITE_TMP_FILES, EXEC_COMMANDS), + WriteFileSystem(R("PEGWriteFileSystem"), WRITE_LOCAL_FILES, DELETE_LOCAL_FILES, WRITE_PROPERTIES, WRITE_SYSTEM_FILES, WRITE_TMP_FILES, + DELETE_TMP_FILES, EXEC_COMMANDS), AccesUnowenedCode(R("PEGAccesUnowenedCode"), JAVA_REFLECTION, GET_CLASSLOADER, ACCESS_CLASS_IN_PACKAGE, ACCESS_DECLARED_MEMBERS), MediaAccess(R("PEGMediaAccess"), PLAY_AUDIO, RECORD_AUDIO, PRINT, CLIPBOARD); - private final PolicyEditorPermissions[] permissions; private final String title; @@ -124,7 +128,7 @@ this.permissions = permissions; } - + public static boolean anyContains(PolicyEditorPermissions permission) { for (Group g : Group.values()) { if (g.contains(permission)) { @@ -133,7 +137,7 @@ } return false; } - + public static boolean anyContains(JCheckBox view, Map<PolicyEditorPermissions, JCheckBox> checkboxMap) { for (Map.Entry<PolicyEditorPermissions, JCheckBox> pairs : checkboxMap.entrySet()){ if (pairs.getValue() == view) { @@ -146,7 +150,7 @@ } return false; } - + /* * + all is selected * 0 invalid @@ -174,7 +178,7 @@ } return 0; } - + public boolean contains(PolicyEditorPermissions permission) { for (PolicyEditorPermissions policyEditorPermissions : permissions) { if (policyEditorPermissions == permission) { @@ -192,9 +196,7 @@ public PolicyEditorPermissions[] getPermissions() { return permissions; } - - - + }
--- a/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorParsingTest.java Thu Mar 27 14:08:54 2014 +0100 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/policyeditor/PolicyEditorParsingTest.java Thu Mar 27 11:08:09 2014 -0400 @@ -52,8 +52,8 @@ private static final String LINEBREAK = System.getProperty("line.separator"); - private static final String READ_PERMISSION = "permission java.io.FilePermission \"${user.home}${/}*\", \"read\";"; - private static final String WRITE_PERMISSION = "permission java.io.FilePermission \"${user.home}${/}*\", \"write\";"; + private static final String READ_PERMISSION = "permission java.io.FilePermission \"${user.home}\", \"read\";"; + private static final String WRITE_PERMISSION = "permission java.io.FilePermission \"${user.home}\", \"write\";"; private static final String COMMENT_HEADER = "/* TEST COMMENT */" + LINEBREAK; private static final String NORMAL_POLICY = "grant {" + LINEBREAK