changeset 2323:0165a4d30876

Add new security dialog that prompts the user if there is mixed signed and unsigned code present.
author Deepak Bhole <dbhole@redhat.com>
date Wed, 28 Jul 2010 15:36:19 -0400
parents af0efa63ddfe
children 3918f39eab4d
files ChangeLog netx/net/sourceforge/jnlp/resources/Messages.properties netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java netx/net/sourceforge/jnlp/tools/JarSigner.java
diffstat 7 files changed, 202 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Jul 28 15:23:50 2010 -0400
+++ b/ChangeLog	Wed Jul 28 15:36:19 2010 -0400
@@ -1,9 +1,30 @@
-2010-07-21  Deepak Bhole <dbhole@redhat.com>
+2010-07-28  Deepak Bhole <dbhole@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add new strings.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java (getInstance):
+	Prompt user if the main app code is signed, but the extentions aren't.
+	(initializeResources): Prompt user if there are any unsigned jars mixed
+	with signed jars.
+	* netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java: New file.
+	Dialog shown to user if the main app code is signed but the extentions aren't.
+	* netx/net/sourceforge/jnlp/security/SecurityDialogUI.java
+	(SecurityDialogUI): Add a constructor that doesn't take a CertVerifier
+	object.
+	* netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Added
+	dialog and accesstype enum elements for a 'Not all jars signed' case.
+	(showNotAllSignedWarningDialog): New function. Prompts the user if the
+	main app code is signed but the extentions aren't.
+	(createDialog): Wire in the 'Not all jars signed' case.
+	(updateUI): Same.
+	* netx/net/sourceforge/jnlp/tools/JarSigner.java (allJarsSigned): New
+	function. Returns if there are any unsigned jars.
+
+2010-07-28  Deepak Bhole <dbhole@redhat.com>
 
 	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java (getInstance):
 	Collapse extention loaders into baseloader rather than vice-verse.
 
-2010-07-21  Deepak Bhole <dbhole@redhat.com>
+2010-07-28  Deepak Bhole <dbhole@redhat.com>
 
 	* netx/net/sourceforge/jnlp/SecurityDesc.java: Converge all property
 	permission settings info a single class.
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties	Wed Jul 28 15:23:50 2010 -0400
+++ b/netx/net/sourceforge/jnlp/resources/Messages.properties	Wed Jul 28 15:36:19 2010 -0400
@@ -52,6 +52,8 @@
 LCantDetermineMainClassInfo=Could not determine the main class for this application.
 LUnsignedJarWithSecurity=Cannot grant permissions to unsigned jars.
 LUnsignedJarWithSecurityInfo=Application requested security permissions, but jars are not signed.
+LSignedAppJarUsingUnsignedJar=Signed application using unsigned jars.
+LSignedAppJarUsingUnsignedJarInfo=The main application jar is signed, but some of the jars it is using aren't.
 
 JNotApplet=File is not an applet.
 JNotApplication=File is not an application.
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Wed Jul 28 15:23:50 2010 -0400
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Wed Jul 28 15:36:19 2010 -0400
@@ -249,6 +249,10 @@
                         JNLPClassLoader extLoader = (JNLPClassLoader) urlToLoader.get(uniqueKey);
 
                         if (extLoader != null && extLoader != loader) {
+                            if (loader.signing && !extLoader.signing)
+                                if (!SecurityWarningDialog.showNotAllSignedWarningDialog(file))
+                                    throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LSignedAppJarUsingUnsignedJar"), R("LSignedAppJarUsingUnsignedJarInfo"));
+
                             for (URL u : extLoader.getURLs())
                                 loader.addURL(u);
                             for (File nativeDirectory: extLoader.getNativeDirectories())
@@ -400,6 +404,11 @@
                         if (js.anyJarsSigned()){
                                 signing = true;
 
+                                if (!js.allJarsSigned() &&
+                                    !SecurityWarningDialog.showNotAllSignedWarningDialog(file))
+                                    throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LSignedAppJarUsingUnsignedJar"), R("LSignedAppJarUsingUnsignedJarInfo"));
+
+
                                 //user does not trust this publisher
                                 if (!js.getAlreadyTrustPublisher()) {
                                     checkTrustWithUser(js);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java	Wed Jul 28 15:36:19 2010 -0400
@@ -0,0 +1,121 @@
+/* NotAllSignedWarningPane.java
+   Copyright (C) 2008 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;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import net.sourceforge.jnlp.JNLPFile;
+
+
+public class NotAllSignedWarningPane extends SecurityDialogPanel {
+
+        public NotAllSignedWarningPane(SecurityWarningDialog x) {
+                super(x);
+                addComponents();
+        }
+
+        /**
+         * Creates the actual GUI components, and adds it to this panel
+         */
+        private void addComponents() {
+                SecurityWarningDialog.AccessType type = parent.getType();
+                JNLPFile file = parent.getFile();
+
+                String topLabelText = "Only parts of this application code are signed.";
+                String infoLabelText = "This application contains both signed and" +
+                " unsigned code. While signed code is safe if you trust the " +
+                "provider, unsigned code may imply code outside of the trusted " +
+                "provider's control.";
+                String questionLabelText = "Do you wish to proceed and run this " +
+                "application anyway?";
+
+                ImageIcon icon = new ImageIcon((new sun.misc.Launcher()).getClassLoader().getResource("net/sourceforge/jnlp/resources/warning.png"));
+                JLabel 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.setBackground(Color.WHITE);
+                topPanel.add(topLabel, BorderLayout.CENTER);
+                topPanel.setPreferredSize(new Dimension(500,80));
+                topPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+                JLabel infoLabel = new JLabel(htmlWrap(infoLabelText));
+                JPanel infoPanel = new JPanel(new BorderLayout());
+                infoPanel.add(infoLabel, BorderLayout.CENTER);
+                infoPanel.setPreferredSize(new Dimension(500,100));
+                infoPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+                JLabel questionLabel = new JLabel(htmlWrap(questionLabelText));
+                JPanel questionPanel = new JPanel(new BorderLayout());
+                questionPanel.add(questionLabel, BorderLayout.CENTER);
+                questionPanel.setPreferredSize(new Dimension(500,100));
+                questionPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+                //run and cancel buttons
+                JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+
+                JButton run = new JButton("Proceed");
+                JButton cancel = new JButton("Cancel");
+                run.addActionListener(createSetValueListener(parent,0));
+                cancel.addActionListener(createSetValueListener(parent, 1));
+                initialFocusComponent = cancel;
+                buttonPanel.add(run);
+                buttonPanel.add(cancel);
+                buttonPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+                //all of the above
+                setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+                add(topPanel);
+                add(infoPanel);
+                add(questionPanel);
+                add(buttonPanel);
+
+        }
+}
--- a/netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java	Wed Jul 28 15:23:50 2010 -0400
+++ b/netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java	Wed Jul 28 15:36:19 2010 -0400
@@ -56,7 +56,7 @@
 
         JComponent initialFocusComponent = null;
 
-        CertVerifier certVerifier;
+        CertVerifier certVerifier = null;
 
         public SecurityDialogPanel(SecurityWarningDialog dialog, CertVerifier certVerifier){
                 this.parent = dialog;
@@ -64,6 +64,11 @@
                 this.setLayout(new BorderLayout());
         }
 
+        public SecurityDialogPanel(SecurityWarningDialog dialog) {
+                this.parent = dialog;
+                this.setLayout(new BorderLayout());
+        }
+
         /*
          * String translation functions
          */
--- a/netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java	Wed Jul 28 15:23:50 2010 -0400
+++ b/netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java	Wed Jul 28 15:36:19 2010 -0400
@@ -63,6 +63,7 @@
                 CERT_INFO,
                 SINGLE_CERT_INFO,
                 ACCESS_WARNING,
+                NOTALLSIGNED_WARNING,
                 APPLET_WARNING
         }
 
@@ -77,6 +78,7 @@
         NETWORK,
         VERIFIED,
         UNVERIFIED,
+        NOTALLSIGNED,
         SIGNING_ERROR
     }
 
@@ -219,6 +221,31 @@
                 }
 
         /**
+         * Shows a warning dialog for when the main application jars are signed,
+         * but extensions aren't
+         *
+         * @return true if permission was granted by the user, false otherwise.
+         */
+        public static boolean showNotAllSignedWarningDialog(JNLPFile file) {
+                        SecurityWarningDialog dialog = new SecurityWarningDialog(
+                                        DialogType.NOTALLSIGNED_WARNING, AccessType.NOTALLSIGNED, file, (new Object[0]));
+                        dialog.setVisible(true);
+                        dialog.dispose();
+
+                        Object selectedValue = dialog.getValue();
+                        if (selectedValue == null) {
+                                return false;
+                        } else if (selectedValue instanceof Integer) {
+                                if (((Integer)selectedValue).intValue() == 0)
+                                        return true;
+                                else
+                                        return false;
+                        } else {
+                                return false;
+                        }
+                }
+
+        /**
          * Shows a security warning dialog according to the specified type of
          * access. If <code>type</code> is one of AccessType.VERIFIED or
          * AccessType.UNVERIFIED, extra details will be available with regards
@@ -325,6 +352,8 @@
                         dialogTitle = "Security Warning";
                 else if (dialogType == DialogType.APPLET_WARNING)
                         dialogTitle = "Applet Warning";
+                else if (dialogType == DialogType.NOTALLSIGNED_WARNING)
+                        dialogTitle = "Security Warning";
 
                 setTitle(dialogTitle);
                 setModal(true);
@@ -397,6 +426,8 @@
                         panel = new AccessWarningPane(this, extras, this.certVerifier);
                 else if (dialogType == DialogType.APPLET_WARNING)
                         panel = new AppletWarningPane(this, this.certVerifier);
+                else if (dialogType == DialogType.NOTALLSIGNED_WARNING)
+                        panel = new NotAllSignedWarningPane(this);
 
                 add(panel, BorderLayout.CENTER);
         }
--- a/netx/net/sourceforge/jnlp/tools/JarSigner.java	Wed Jul 28 15:23:50 2010 -0400
+++ b/netx/net/sourceforge/jnlp/tools/JarSigner.java	Wed Jul 28 15:36:19 2010 -0400
@@ -538,4 +538,14 @@
         }
     }
 
+
+    /**
+     * Returns if all jars are signed.
+     *
+     * @return True if all jars are signed, false if there are one or more unsigned jars
+     */
+    public boolean allJarsSigned() {
+       return this.unverifiedJars.size() == 0;
+    }
+
 }