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 @@ -23,6 +23,8 @@ ButNo=No 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 +CertWarnPolicyTip=Advanced sandbox settings +CertWarnPolicyEditorItem=Launch PolicyEditor AFileOnTheMachine=a file on the machine AlwaysAllowAction=Always allow this action diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java --- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java @@ -284,7 +284,7 @@ public class JNLPClassLoader extends URL setSecurity(); - ManifestsAttributesValidator mav = new ManifestsAttributesValidator(security, file, signing); + ManifestsAttributesValidator mav = new ManifestsAttributesValidator(security, file, signing, securityDelegate); mav.checkCodebaseAttribute(); mav.checkPermissionsAttribute(); mav.checkApplicationLibraryAllowableCodebaseAttribute(); diff --git a/netx/net/sourceforge/jnlp/runtime/ManifestsAttributesValidator.java b/netx/net/sourceforge/jnlp/runtime/ManifestsAttributesValidator.java --- a/netx/net/sourceforge/jnlp/runtime/ManifestsAttributesValidator.java +++ b/netx/net/sourceforge/jnlp/runtime/ManifestsAttributesValidator.java @@ -39,6 +39,7 @@ package net.sourceforge.jnlp.runtime; import java.net.URL; import java.util.HashSet; import java.util.Set; + import net.sourceforge.jnlp.ExtensionDesc; import net.sourceforge.jnlp.JARDesc; import net.sourceforge.jnlp.JNLPFile; @@ -47,6 +48,7 @@ import net.sourceforge.jnlp.LaunchExcept import net.sourceforge.jnlp.PluginBridge; import net.sourceforge.jnlp.ResourcesDesc; import net.sourceforge.jnlp.SecurityDesc; +import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate; import net.sourceforge.jnlp.runtime.JNLPClassLoader.SigningState; import net.sourceforge.jnlp.security.SecurityDialogs; import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel; @@ -60,14 +62,15 @@ public class ManifestsAttributesValidato private final SecurityDesc security; private final JNLPFile file; private final SigningState signing; + private final SecurityDelegate securityDelegate; - public ManifestsAttributesValidator(SecurityDesc security, JNLPFile file, SigningState signing) { + public ManifestsAttributesValidator(final SecurityDesc security, final JNLPFile file, + final SigningState signing, final SecurityDelegate securityDelegate) { this.security = security; this.file = file; this.signing = signing; + this.securityDelegate = securityDelegate; } - - /** * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#codebase @@ -110,8 +113,9 @@ public class ManifestsAttributesValidato void checkPermissionsAttribute() throws LaunchException { final ManifestBoolean permissions = file.getManifestsAttributes().isSandboxForced(); AppletSecurityLevel level = AppletStartupSecuritySettings.getInstance().getSecurityLevel(); - if (level == AppletSecurityLevel.ALLOW_UNSIGNED) { - OutputController.getLogger().log(OutputController.Level.WARNING_ALL, "Although 'permissions' attribute of this application is '" + file.getManifestsAttributes().permissionsToString() + "' Your Extended applets security is at 'low', continuing"); + if (level == AppletSecurityLevel.ALLOW_UNSIGNED || securityDelegate.getRunInSandbox()) { + OutputController.getLogger().log(OutputController.Level.WARNING_ALL, "Although 'permissions' attribute of this application is '" + file.getManifestsAttributes().permissionsToString() + + "' Your Extended applets security is at 'low', or you have specifically chosen to run the applet Sandboxed. Continuing"); return; } switch (permissions) { 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 @@ -45,11 +45,16 @@ import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridLayout; +import java.awt.Image; 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; @@ -60,11 +65,15 @@ import javax.swing.ImageIcon; 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.JNLPRuntime; import net.sourceforge.jnlp.security.CertVerifier; import net.sourceforge.jnlp.security.CertificateUtils; import net.sourceforge.jnlp.security.HttpsCertVerifier; @@ -74,6 +83,7 @@ import net.sourceforge.jnlp.security.Key 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.util.FileUtils; import net.sourceforge.jnlp.util.logging.OutputController; @@ -87,12 +97,27 @@ import net.sourceforge.jnlp.util.logging */ public class CertWarningPane extends SecurityDialogPanel { + JNLPFile file; + AccessType accessType; + Certificate cert; JCheckBox alwaysTrust; CertVerifier certVerifier; + JPopupMenu policyMenu; + JPanel topPanel, infoPanel, buttonPanel, bottomPanel; + JLabel topLabel, nameLabel, publisherLabel, fromLabel, bottomLabel; + JButton run, sandbox, advancedOptions, cancel, moreInfo; + boolean alwaysTrustSelected; + String bottomLabelWarningText; + PolicyEditor policyEditor = null; public CertWarningPane(SecurityDialog x, CertVerifier certVerifier) { super(x, certVerifier); this.certVerifier = certVerifier; + + accessType = parent.getAccessType(); + file = parent.getFile(); + cert = parent.getCertVerifier().getPublisher(null); + addComponents(); } @@ -100,10 +125,11 @@ public class CertWarningPane extends Sec * Creates the actual GUI components, and adds it to this panel */ private void addComponents() { - AccessType type = parent.getAccessType(); - JNLPFile file = parent.getFile(); - Certificate c = parent.getCertVerifier().getPublisher(null); + setTextAndLabels(); + addButtons(); + } + private void setTextAndLabels() { String name = ""; String publisher = ""; String from = ""; @@ -112,8 +138,8 @@ public class CertWarningPane extends Sec //these strings -- we just want to fill in as many as possible. try { if ((certVerifier instanceof HttpsCertVerifier) && - (c instanceof X509Certificate)) { - name = SecurityUtil.getCN(((X509Certificate) c) + (cert instanceof X509Certificate)) { + name = SecurityUtil.getCN(((X509Certificate) cert) .getSubjectX500Principal().getName()); } else if (file instanceof PluginBridge) { name = file.getTitle(); @@ -124,8 +150,8 @@ public class CertWarningPane extends Sec } try { - if (c instanceof X509Certificate) { - publisher = SecurityUtil.getCN(((X509Certificate) c) + if (cert instanceof X509Certificate) { + publisher = SecurityUtil.getCN(((X509Certificate) cert) .getSubjectX500Principal().getName()); } } catch (Exception e) { @@ -142,63 +168,66 @@ public class CertWarningPane extends Sec // Labels String topLabelText = ""; - String bottomLabelText = parent.getCertVerifier().getRootInCacerts() ? - R("STrustedSource") : R("SUntrustedSource"); - String propertyName = ""; + bottomLabelWarningText = parent.getCertVerifier().getRootInCacerts() ? + R("STrustedSource") : R("SUntrustedSource"); String iconLocation = "net/sourceforge/jnlp/resources/"; - boolean alwaysTrustSelected = false; + alwaysTrustSelected = false; if (certVerifier instanceof HttpsCertVerifier) { // HTTPS certs that are verified do not prompt for a dialog. // @see VariableX509TrustManager#checkServerTrusted topLabelText = R("SHttpsUnverified") + " " + R("Continue"); - propertyName = "OptionPane.warningIcon"; iconLocation += "warning.png"; } else { - switch (type) { + switch (accessType) { case VERIFIED: topLabelText = R("SSigVerified"); - propertyName = "OptionPane.informationIcon"; iconLocation += "question.png"; alwaysTrustSelected = true; break; case UNVERIFIED: topLabelText = R("SSigUnverified"); - propertyName = "OptionPane.warningIcon"; iconLocation += "warning.png"; - bottomLabelText += " " + R("SWarnFullPermissionsIgnorePolicy"); + bottomLabelWarningText += " " + R("SWarnFullPermissionsIgnorePolicy"); break; case SIGNING_ERROR: topLabelText = R("SSignatureError"); - propertyName = "OptionPane.warningIcon"; iconLocation += "warning.png"; - bottomLabelText += " " + R("SWarnFullPermissionsIgnorePolicy"); + bottomLabelWarningText += " " + R("SWarnFullPermissionsIgnorePolicy"); break; } } - ImageIcon icon = new ImageIcon((new sun.misc.Launcher()) - .getClassLoader().getResource(iconLocation)); - JLabel topLabel = new JLabel(htmlWrap(topLabelText), icon, SwingConstants.LEFT); + ImageIcon icon = getImageIcon(iconLocation); + topLabel = new JLabel(htmlWrap(topLabelText), icon, SwingConstants.LEFT); topLabel.setFont(new Font(topLabel.getFont().toString(), Font.BOLD, 12)); - JPanel topPanel = new JPanel(new BorderLayout()); + topPanel = new JPanel(new BorderLayout()); topPanel.setBackground(Color.WHITE); topPanel.add(topLabel, BorderLayout.CENTER); topPanel.setPreferredSize(new Dimension(400, 75)); topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); //application info - JLabel nameLabel = new JLabel(R("Name") + ": " + name); + nameLabel = new JLabel(R("Name") + ": " + name); nameLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - JLabel publisherLabel = new JLabel(R("Publisher") + ": " + publisher); + publisherLabel = new JLabel(R("Publisher") + ": " + publisher); publisherLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - JLabel fromLabel = new JLabel(R("From") + ": " + from); + fromLabel = new JLabel(R("From") + ": " + from); fromLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + } + + private ImageIcon getImageIcon(final String imageLocation) { + return new ImageIcon((new sun.misc.Launcher()) + .getClassLoader().getResource(imageLocation)); + } + + private void addButtons() { + createPolicyPermissionsMenu(); alwaysTrust = new JCheckBox(R("SAlwaysTrustPublisher")); alwaysTrust.setEnabled(true); alwaysTrust.setSelected(alwaysTrustSelected); - JPanel infoPanel = new JPanel(new GridLayout(4, 1)); + infoPanel = new JPanel(new GridLayout(4, 1)); infoPanel.add(nameLabel); infoPanel.add(publisherLabel); @@ -210,12 +239,15 @@ public class CertWarningPane extends Sec infoPanel.setBorder(BorderFactory.createEmptyBorder(25, 25, 25, 25)); //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")); + buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + run = new JButton(R("ButRun")); + sandbox = new JButton(R("ButSandbox")); + advancedOptions = new JButton("\u2630"); // "hamburger" navicon + cancel = new JButton(R("ButCancel")); + run.setToolTipText(R("CertWarnRunTip")); sandbox.setToolTipText(R("CertWarnSandboxTip")); + advancedOptions.setToolTipText(R("CertWarnPolicyTip")); cancel.setToolTipText(R("CertWarnCancelTip")); alwaysTrust.addActionListener(new ButtonDisableListener(sandbox)); @@ -224,16 +256,23 @@ public class CertWarningPane extends Sec buttonWidth = Math.max(buttonWidth, cancel.getMinimumSize().width); int buttonHeight = run.getMinimumSize().height; Dimension d = new Dimension(buttonWidth, buttonHeight); + run.setPreferredSize(d); sandbox.setPreferredSize(d); + advancedOptions.setPreferredSize(new Dimension(advancedOptions.getMinimumSize().width, buttonHeight)); cancel.setPreferredSize(d); sandbox.setEnabled(!alwaysTrust.isSelected()); run.addActionListener(createSetValueListener(parent, 0)); run.addActionListener(new CheckBoxListener()); + sandbox.addActionListener(createSetValueListener(parent, 1)); + + advancedOptions.addMouseListener(new PolicyEditorPopupListener()); + cancel.addActionListener(createSetValueListener(parent, 2)); + initialFocusComponent = cancel; buttonPanel.add(run); // file will be null iff this dialog is being called from VariableX509TrustManager. @@ -242,8 +281,10 @@ public class CertWarningPane extends Sec // Since there is no app, there is nothing to run sandboxed. if (file != null) { buttonPanel.add(sandbox); + buttonPanel.add(advancedOptions); } buttonPanel.add(cancel); + buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); //all of the above @@ -252,18 +293,75 @@ public class CertWarningPane extends Sec add(infoPanel); add(buttonPanel); - JLabel bottomLabel = new JLabel(htmlWrap(bottomLabelText)); - JButton moreInfo = new JButton(R("ButMoreInformation")); + bottomLabel = new JLabel(htmlWrap(bottomLabelWarningText)); + moreInfo = new JButton(R("ButMoreInformation")); moreInfo.addActionListener(new MoreInfoButtonListener()); - JPanel bottomPanel = new JPanel(); + bottomPanel = new JPanel(); bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS)); bottomPanel.add(bottomLabel); bottomPanel.add(moreInfo); bottomPanel.setPreferredSize(new Dimension(600, 100)); bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 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.isClosed()) { + policyEditor = PolicyEditor.createInstance(filepath); + } else { + policyEditor.toFront(); + policyEditor.repaint(); + } + policyEditor.addNewCodebase(file.getCodeBase().toString()); + policyEditor.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 { 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 @@ -2,34 +2,41 @@ package net.sourceforge.jnlp.security.di import static net.sourceforge.jnlp.runtime.Translator.R; -import java.awt.BorderLayout; +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.JFrame; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; import net.sourceforge.jnlp.JNLPFile; import net.sourceforge.jnlp.PluginBridge; -import net.sourceforge.jnlp.PluginParameters; +import net.sourceforge.jnlp.config.DeploymentConfiguration; +import net.sourceforge.jnlp.runtime.JNLPRuntime; import net.sourceforge.jnlp.security.SecurityDialog; -import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; -import net.sourceforge.jnlp.security.SecurityDialogs.DialogType; 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.tools.CertInformation; import net.sourceforge.jnlp.tools.JarCertVerifier; public class PartiallySignedAppTrustWarningPanel extends AppTrustWarningPanel { - private JarCertVerifier jcv; - private JButton sandboxButton; + private final JarCertVerifier jcv; + private final JButton sandboxButton; + private final JButton advancedOptionsButton; + private final JPopupMenu policyMenu; + private PolicyEditor policyEditor = null; - public PartiallySignedAppTrustWarningPanel(JNLPFile file, ActionChoiceListener actionChoiceListener, - SecurityDialog securityDialog) { + public PartiallySignedAppTrustWarningPanel(JNLPFile file, ActionChoiceListener actionChoiceListener, SecurityDialog securityDialog) { super(file, actionChoiceListener); this.jcv = (JarCertVerifier) securityDialog.getCertVerifier(); this.INFO_PANEL_HEIGHT = 200; @@ -37,7 +44,16 @@ public class PartiallySignedAppTrustWarn sandboxButton = new JButton(); 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")); + buttons.add(1, sandboxButton); + buttons.add(2, advancedOptionsButton); + addComponents(); } @@ -64,8 +80,7 @@ public class PartiallySignedAppTrustWarn try { if (c instanceof X509Certificate) { - publisher = SecurityUtil.getCN(((X509Certificate) c) - .getSubjectX500Principal().getName()); + publisher = SecurityUtil.getCN(((X509Certificate) c).getSubjectX500Principal().getName()); } } catch (Exception e) { } @@ -79,8 +94,7 @@ public class PartiallySignedAppTrustWarn } catch (Exception e) { } - return "
" + R("Publisher") + ": " + publisher - + "
" + R("From") + ": " + from; + return "
" + R("Publisher") + ": " + publisher + "
" + R("From") + ": " + from; } private String getSigningInfo() { @@ -137,4 +151,64 @@ public class PartiallySignedAppTrustWarn 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.isClosed()) { + policyEditor = PolicyEditor.createInstance(filepath); + } else { + policyEditor.toFront(); + policyEditor.repaint(); + } + policyEditor.addNewCodebase(file.getCodeBase().toString()); + policyEditor.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) { + } + } + }