Mercurial > hg > release > icedtea6-1.4.1
changeset 1316:c63cc0eff68b
- Fixed a bug in remote->local image url mapping that caused the plugin to
hang in some cases
- Implemented a common interface that is now queried by all security dialogs
- Implemented a user prompt for untrusted https certificates (WIP)
line wrap: on
line diff
--- a/ChangeLog Sat Jan 17 18:41:18 2009 +0100 +++ b/ChangeLog Mon Jan 19 14:41:10 2009 -0500 @@ -1,3 +1,37 @@ +2009-01-19 Deepak Bhole <dbhole@redhat.com> + + * IcedTeaPlugin.cc: Add "Java" in the plugin description string. + * plugin/icedtea/sun/applet/PluginAppletViewer.java: Change the way the + image was searched locally. + * plugin/icedtea/sun/applet/PluginMain.java: Install a custom SSL trust + manager. + * rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Cache file names + from jars. + * rt/net/sourceforge/jnlp/security/AccessWarningPane.java: Accept + CertVerifier as an additional argument. + * rt/net/sourceforge/jnlp/security/AppletWarningPane.java: Same. + * rt/net/sourceforge/jnlp/security/CertWarningPane.java: Same. + * rt/net/sourceforge/jnlp/security/CertsInfoPane.java: Same. + * rt/net/sourceforge/jnlp/security/HttpsCertVerifier.java: New file. + Implements information gathering functions used by various prompt dialogs. + * rt/net/sourceforge/jnlp/security/MoreInfoPane.java: Accept CertVerifier + as an additional argument. + * rt/net/sourceforge/jnlp/security/SecurityDialogUI.java: Same. + * rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Use the new + common CertVerifier interface to gather information. + * rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java: Accept + CertVerifier as an additional argument. + * rt/net/sourceforge/jnlp/security/VariableX509TrustManager.java: + Customized trustmanager that can temporarily trust certificates on the + fly. + * rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java: Accept + CertVerifier as an additional argument. + * rt/net/sourceforge/jnlp/tools/CertVerifier.java: New common interface + that all security related dialogs now query for certificate info (jar and + https). + * rt/net/sourceforge/jnlp/tools/JarSigner.java: Implement the new + CertVerifier verifier interface. + 2009-01-17 Mark Wielaard <mark@klomp.org> * patches/icedtea-version.patch (samejvmsafe): Removed the following
--- a/IcedTeaPlugin.cc Sat Jan 17 18:41:18 2009 +0100 +++ b/IcedTeaPlugin.cc Mon Jan 19 14:41:10 2009 -0500 @@ -275,7 +275,7 @@ #define PLUGIN_CHECK(message, result) #endif -#define PLUGIN_NAME "IcedTea Web Browser Plugin" +#define PLUGIN_NAME "IcedTea Java Web Browser Plugin" #define PLUGIN_DESCRIPTION "The " PLUGIN_NAME PLUGIN_VERSION " executes Java applets." #define PLUGIN_MIME_DESC \ "application/x-java-vm:class,jar:IcedTea;" \
--- a/plugin/icedtea/sun/applet/PluginAppletViewer.java Sat Jan 17 18:41:18 2009 +0100 +++ b/plugin/icedtea/sun/applet/PluginAppletViewer.java Mon Jan 19 14:41:10 2009 -0500 @@ -176,7 +176,7 @@ AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { - panel = new NetxPanel(doc, atts, true); + panel = new NetxPanel(doc, atts, false); AppletViewerPanel.debug("Using NetX panel"); PluginDebug.debug(atts.toString()); } catch (Exception ex) { @@ -612,8 +612,14 @@ // try to fetch it locally if (panel instanceof NetxPanel) { + URL localURL = null; - localURL = ((NetxPanel) panel).getAppletClassLoader().getResource(originalURL.substring(codeBase.length())); + + String resourceName = originalURL.substring(codeBase.length()); + JNLPClassLoader loader = (JNLPClassLoader) ((NetxPanel) panel).getAppletClassLoader(); + + if (loader.resourceAvailableLocally(resourceName)) + localURL = loader.getResource(resourceName); url = localURL != null ? localURL : url; } @@ -630,7 +636,7 @@ return ref; } } catch (Exception e) { - System.err.println("Error occurred wgen trying to fetch image:"); + System.err.println("Error occurred when trying to fetch image:"); e.printStackTrace(); return null; }
--- a/plugin/icedtea/sun/applet/PluginMain.java Sat Jan 17 18:41:18 2009 +0100 +++ b/plugin/icedtea/sun/applet/PluginMain.java Mon Jan 19 14:41:10 2009 -0500 @@ -34,6 +34,14 @@ import java.util.Enumeration; import java.util.Properties; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; + +import javax.net.ssl.HttpsURLConnection; + +import net.sourceforge.jnlp.security.VariableX509TrustManager; + /** * The main entry point into PluginAppletViewer. */ @@ -152,7 +160,19 @@ // INSTALL THE PROPERTY LIST System.setProperties(avProps); - // REMIND: Create and install a socket factory! + + try { + SSLSocketFactory sslSocketFactory; + SSLContext context = SSLContext.getInstance("SSL"); + TrustManager[] trust = new TrustManager[] { VariableX509TrustManager.getInstance() }; + context.init(null, trust, null); + sslSocketFactory = context.getSocketFactory(); + + HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory); + } catch (Exception e) { + System.err.println("Unable to set SSLSocketfactory (may _prevent_ access to sites that should be trusted)! Continuing anyway..."); + e.printStackTrace(); + } } static boolean messageAvailable() {
--- a/rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Mon Jan 19 14:41:10 2009 -0500 @@ -29,7 +29,6 @@ import java.security.Permission; import java.security.PermissionCollection; import java.security.Permissions; -import java.security.Policy; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Enumeration; @@ -38,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.Random; +import java.util.TreeSet; import java.util.Vector; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -131,7 +131,11 @@ private boolean signing = false; + /** ArrayList containing jar indexes for various jars available to this classloader */ private ArrayList<JarIndex> jarIndexes = new ArrayList<JarIndex>(); + + /** File entries in the jar files available to this classloader */ + private TreeSet jarEntries = new TreeSet(); /** * Create a new JNLPClassLoader from the specified file. @@ -478,7 +482,6 @@ // transfer the Jars waitForJars(jars); - for (int i=0; i < jars.size(); i++) { JARDesc jar = (JARDesc) jars.get(i); @@ -488,8 +491,23 @@ File localFile = tracker.getCacheFile(jar.getLocation()); try { URL location = jar.getLocation(); // non-cacheable, use source location - if (localFile != null) + if (localFile != null) { location = localFile.toURL(); // cached file + + // This is really not the best way.. but we need some way for + // PluginAppletViewer::getCachedImageRef() to check if the image + // is available locally, and it cannot use getResources() because + // that prefetches the resource, which confuses MediaTracker.waitForAll() + // which does a wait(), waiting for notification (presumably + // thrown after a resource is fetched). This bug manifests itself + // particularly when using The FileManager applet from Webmin. + + JarFile jarFile = new JarFile(localFile); + Enumeration e = jarFile.entries(); + while (e.hasMoreElements()) + jarEntries.add(((JarEntry) e.nextElement()).getName()); + + } addURL(location); @@ -829,6 +847,16 @@ return resources.elements(); } + + /** + * Returns if the specified resource is available locally from a cached jar + * + * @param s The name of the resource + * @return Whether or not the resource is available locally + */ + public boolean resourceAvailableLocally(String s) { + return jarEntries.contains(s); + } /** * Adds whatever resources have already been downloaded in the
--- a/rt/net/sourceforge/jnlp/security/AccessWarningPane.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/security/AccessWarningPane.java Mon Jan 19 14:41:10 2009 -0500 @@ -37,14 +37,28 @@ package net.sourceforge.jnlp.security; -import java.awt.*; -import javax.swing.*; +import java.awt.BorderLayout; +import java.awt.Color; +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.ActionEvent; -import java.net.URL; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; import net.sourceforge.jnlp.JNLPFile; import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.tools.CertVerifier; /** * Provides the look and feel for a SecurityWarningDialog. These dialogs are @@ -59,12 +73,12 @@ JCheckBox alwaysAllow; Object[] extras; - public AccessWarningPane(JComponent x) { - super(x); + public AccessWarningPane(JComponent x, CertVerifier certVerifier) { + super(x, certVerifier); } - public AccessWarningPane(JComponent x, Object[] extras) { - super(x); + public AccessWarningPane(JComponent x, Object[] extras, CertVerifier certVerifier) { + super(x, certVerifier); this.extras = extras; }
--- a/rt/net/sourceforge/jnlp/security/AppletWarningPane.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/security/AppletWarningPane.java Mon Jan 19 14:41:10 2009 -0500 @@ -50,10 +50,12 @@ import javax.swing.JLabel; import javax.swing.JPanel; +import net.sourceforge.jnlp.tools.CertVerifier; + public class AppletWarningPane extends SecurityDialogUI { - public AppletWarningPane(JComponent x) { - super(x); + public AppletWarningPane(JComponent x, CertVerifier certVerifier) { + super(x, certVerifier); } protected void installComponents() {
--- a/rt/net/sourceforge/jnlp/security/CertWarningPane.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/security/CertWarningPane.java Mon Jan 19 14:41:10 2009 -0500 @@ -37,18 +37,31 @@ package net.sourceforge.jnlp.security; -import java.awt.*; -import javax.swing.*; - - +import java.awt.BorderLayout; +import java.awt.Color; +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.ActionEvent; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + import net.sourceforge.jnlp.JNLPFile; import net.sourceforge.jnlp.PluginBridge; import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.tools.CertVerifier; import net.sourceforge.jnlp.tools.KeyTool; /** @@ -63,8 +76,8 @@ JCheckBox alwaysTrust; - public CertWarningPane(JComponent x) { - super(x); + public CertWarningPane(JComponent x, CertVerifier certVerifier) { + super(x, certVerifier); } /**
--- a/rt/net/sourceforge/jnlp/security/CertsInfoPane.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/security/CertsInfoPane.java Mon Jan 19 14:41:10 2009 -0500 @@ -76,8 +76,8 @@ private String[] columnNames = { "Field", "Value" }; protected ArrayList<String[][]> certsData; - public CertsInfoPane(JComponent x) { - super(x); + public CertsInfoPane(JComponent x, CertVerifier certVerifier) { + super(x, certVerifier); } /**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/net/sourceforge/jnlp/security/HttpsCertVerifier.java Mon Jan 19 14:41:10 2009 -0500 @@ -0,0 +1,119 @@ +/* VariableX509TrustManager.java + Copyright (C) 2009 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.security.cert.CertPath; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; + +import net.sourceforge.jnlp.tools.CertVerifier; + +public class HttpsCertVerifier implements CertVerifier { + + private VariableX509TrustManager tm; + private X509Certificate[] chain; + private String authType; + + public HttpsCertVerifier(VariableX509TrustManager tm, X509Certificate[] chain, String authType) { + this.tm = tm; + this.chain = chain; + this.authType = authType; + } + + public boolean getAlreadyTrustPublisher() { + try { + tm.checkServerTrusted(chain, authType, true); + return true; + } catch (CertificateException ce) { + return false; + } + } + + public ArrayList<CertPath> getCerts() { + + ArrayList<X509Certificate> list = new ArrayList<X509Certificate>(); + for (int i=0; i < chain.length; i++) + list.add(chain[i]); + + ArrayList<CertPath> certPaths = new ArrayList<CertPath>(); + + try { + certPaths.add(CertificateFactory.getInstance("X.509").generateCertPath(list)); + } catch (CertificateException ce) { + ce.printStackTrace(); + + // carry on + } + + return certPaths; + } + + public ArrayList<String> getDetails() { + // TODO Auto-generated method stub + return new ArrayList<String>(); + } + + public Certificate getPublisher() { + // TODO Auto-generated method stub + return null; + } + + public Certificate getRoot() { + // TODO Auto-generated method stub + return null; + } + + public boolean getRootInCacerts() { + // TODO Auto-generated method stub + return false; + } + + public boolean hasSigningIssues() { + // TODO Auto-generated method stub + return false; + } + + public boolean noSigningIssues() { + // TODO Auto-generated method stub + return false; + } + +}
--- a/rt/net/sourceforge/jnlp/security/MoreInfoPane.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/security/MoreInfoPane.java Mon Jan 19 14:41:10 2009 -0500 @@ -37,15 +37,23 @@ package net.sourceforge.jnlp.security; -import java.awt.*; -import javax.swing.*; - -import net.sourceforge.jnlp.runtime.*; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; -import java.util.ArrayList; -import java.awt.event.ActionListener; -import java.awt.event.ActionEvent; -import javax.swing.border.Border; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.tools.CertVerifier; /** * Provides the UI for the More Info dialog. This dialog shows details about an @@ -55,17 +63,15 @@ */ public class MoreInfoPane extends SecurityDialogUI { - public MoreInfoPane(JComponent x) { - super(x); + public MoreInfoPane(JComponent x, CertVerifier certVerifier) { + super(x, certVerifier); } /** * Constructs the GUI components of this UI */ protected void installComponents() { - ArrayList<String> details = - ((SecurityWarningDialog)optionPane) - .getJarSigner().getDetails(); + ArrayList<String> details = certVerifier.getDetails(); int numLabels = details.size(); JPanel errorPanel = new JPanel(new GridLayout(numLabels,1));
--- a/rt/net/sourceforge/jnlp/security/SecurityDialogUI.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/security/SecurityDialogUI.java Mon Jan 19 14:41:10 2009 -0500 @@ -37,19 +37,24 @@ package net.sourceforge.jnlp.security; -import java.awt.*; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.plaf.OptionPaneUI; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeEvent; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.ActionEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.ComponentAdapter; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; -import net.sourceforge.jnlp.JNLPFile; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.JRootPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.OptionPaneUI; + import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.tools.CertVerifier; /** * Provides a base for JNLP warning dialogs. @@ -63,13 +68,16 @@ /** Component to receive focus when messaged with selectInitialValue. */ Component initialFocusComponent; + + CertVerifier certVerifier; /** PropertyChangeListener for <code>optionPane</code> */ private PropertyChangeListener propertyChangeListener; private Handler handler; - public SecurityDialogUI(JComponent x){ + public SecurityDialogUI(JComponent x, CertVerifier certVerifier){ optionPane = (JOptionPane)x; + this.certVerifier = certVerifier; } /**
--- a/rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java Mon Jan 19 14:41:10 2009 -0500 @@ -38,7 +38,7 @@ package net.sourceforge.jnlp.security; import net.sourceforge.jnlp.JNLPFile; -import net.sourceforge.jnlp.tools.JarSigner; +import net.sourceforge.jnlp.tools.CertVerifier; import java.awt.*; import javax.swing.*; @@ -86,10 +86,10 @@ /** The type of access that this dialog is for */ private AccessType accessType; - /** The application file assocated with this security warning */ + /** The application file associated with this security warning */ private JNLPFile file; - private JarSigner jarSigner; + private CertVerifier certVerifier; private X509Certificate cert; @@ -107,27 +107,37 @@ this.dialogType = dialogType; this.accessType = accessType; this.file = file; - this.jarSigner = null; + this.certVerifier = null; + initialized = true; + updateUI(); + } + + public SecurityWarningDialog(DialogType dialogType, AccessType accessType, + JNLPFile file, CertVerifier jarSigner) { + this.dialogType = dialogType; + this.accessType = accessType; + this.file = file; + this.certVerifier = jarSigner; initialized = true; updateUI(); } public SecurityWarningDialog(DialogType dialogType, AccessType accessType, - JNLPFile file, JarSigner jarSigner) { - this.dialogType = dialogType; - this.accessType = accessType; - this.file = file; - this.jarSigner = jarSigner; - initialized = true; - updateUI(); + CertVerifier certVerifier) { + this.dialogType = dialogType; + this.accessType = accessType; + this.file = null; + this.certVerifier = certVerifier; + initialized = true; + updateUI(); } - + public SecurityWarningDialog(DialogType dialogType, AccessType accessType, JNLPFile file, Object[] extras) { this.dialogType = dialogType; this.accessType = accessType; this.file = file; - this.jarSigner = null; + this.certVerifier = null; initialized = true; this.extras = extras; updateUI(); @@ -138,7 +148,7 @@ this.dialogType = dialogType; this.accessType = null; this.file = null; - this.jarSigner = null; + this.certVerifier = null; this.cert = c; initialized = true; updateUI(); @@ -210,7 +220,7 @@ * @param jarSigner the JarSigner used to verify this application */ public static boolean showCertWarningDialog(AccessType accessType, - JNLPFile file, JarSigner jarSigner) { + JNLPFile file, CertVerifier jarSigner) { SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.CERT_WARNING, accessType, file, jarSigner); @@ -241,7 +251,7 @@ * @param parent the parent option pane */ public static void showMoreInfoDialog( - JarSigner jarSigner, JOptionPane parent) { + CertVerifier jarSigner, JOptionPane parent) { SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.MORE_INFO, null, null, @@ -259,7 +269,7 @@ * * @param certs the certificates used in signing. */ - public static void showCertInfoDialog(JarSigner jarSigner, + public static void showCertInfoDialog(CertVerifier jarSigner, JOptionPane parent) { SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.CERT_INFO, null, null, jarSigner); @@ -291,7 +301,7 @@ public static int showAppletWarning() { SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.APPLET_WARNING, - null, null, (JarSigner) null); + null, null, (CertVerifier) null); JDialog dialog = swd.createDialog(); centerDialog(dialog); swd.selectInitialValue(); @@ -382,8 +392,8 @@ return file; } - public JarSigner getJarSigner() { - return jarSigner; + public CertVerifier getJarSigner() { + return certVerifier; } public X509Certificate getCert() { @@ -397,17 +407,17 @@ public void updateUI() { if (dialogType == DialogType.CERT_WARNING) - setUI((OptionPaneUI) new CertWarningPane(this)); + setUI((OptionPaneUI) new CertWarningPane(this, this.certVerifier)); else if (dialogType == DialogType.MORE_INFO) - setUI((OptionPaneUI) new MoreInfoPane(this)); + setUI((OptionPaneUI) new MoreInfoPane(this, this.certVerifier)); else if (dialogType == DialogType.CERT_INFO) - setUI((OptionPaneUI) new CertsInfoPane(this)); + setUI((OptionPaneUI) new CertsInfoPane(this, this.certVerifier)); else if (dialogType == DialogType.SINGLE_CERT_INFO) - setUI((OptionPaneUI) new SingleCertInfoPane(this)); + setUI((OptionPaneUI) new SingleCertInfoPane(this, this.certVerifier)); else if (dialogType == DialogType.ACCESS_WARNING) - setUI((OptionPaneUI) new AccessWarningPane(this, extras)); + setUI((OptionPaneUI) new AccessWarningPane(this, extras, this.certVerifier)); else if (dialogType == DialogType.APPLET_WARNING) - setUI((OptionPaneUI) new AppletWarningPane(this)); + setUI((OptionPaneUI) new AppletWarningPane(this, this.certVerifier)); } private static void centerDialog(JDialog dialog) {
--- a/rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java Mon Jan 19 14:41:10 2009 -0500 @@ -45,10 +45,12 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeSelectionModel; +import net.sourceforge.jnlp.tools.CertVerifier; + public class SingleCertInfoPane extends CertsInfoPane { - public SingleCertInfoPane(JComponent x) { - super(x); + public SingleCertInfoPane(JComponent x, CertVerifier certVerifier) { + super(x, certVerifier); } protected void buildTree() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/net/sourceforge/jnlp/security/VariableX509TrustManager.java Mon Jan 19 14:41:10 2009 -0500 @@ -0,0 +1,222 @@ +/* VariableX509TrustManager.java + Copyright (C) 2009 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.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import sun.security.validator.ValidatorException; + +/** + * This class implements an X509 Trust Manager. The certificates it trusts are + * "variable", in the sense that it can dynamically, and temporarily support + * different certificates that are not in the keystore. + */ + +public class VariableX509TrustManager implements X509TrustManager { + + KeyStore userKeyStore = null; + KeyStore caKeyStore = null; + + X509TrustManager userTrustManager = null; + X509TrustManager caTrustManager = null; + + ArrayList<Certificate> temporarilyTrusted = new ArrayList(); + + static VariableX509TrustManager instance = null; + + /** + * Constructor initializes the system, user and custom stores + */ + public VariableX509TrustManager() { + + try { + userKeyStore = SecurityUtil.getUserKeyStore(); + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); + tmFactory.init(userKeyStore); + + // tm factory initialized, now get the managers so we can assign the X509 one + TrustManager[] trustManagers = tmFactory.getTrustManagers(); + + for (int i=0; i < trustManagers.length; i++) { + if (trustManagers[i] instanceof X509TrustManager) { + userTrustManager = (X509TrustManager) trustManagers[i]; + } + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + try { + caKeyStore = SecurityUtil.getCacertsKeyStore(); + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); + tmFactory.init(caKeyStore); + + // tm factory initialized, now get the managers so we can extract the X509 one + TrustManager[] trustManagers = tmFactory.getTrustManagers(); + + for (int i=0; i < trustManagers.length; i++) { + if (trustManagers[i] instanceof X509TrustManager) { + caTrustManager = (X509TrustManager) trustManagers[i]; + } + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Check if client is trusted (not support for custom here, only system/user) + */ + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + + // First try catrustmanager, then try usertrustmanager + try { + caTrustManager.checkClientTrusted(chain, authType); + } catch (Exception caex) { + try { + userTrustManager.checkClientTrusted(chain, authType); + } catch (Exception userex) { + // Do nothing here. This trust manager is intended to be used + // only in the plugin instance vm, which does not act as a + // server + } + } + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + checkServerTrusted(chain, authType, false); + } + + /** + * Check if the server is trusted + * + * @param chain The cert chain + * @param authType The auth type algorithm + * @param checkOnly Whether to "check only" i.e. no user prompt, or to prompt for permission + */ + public void checkServerTrusted(X509Certificate[] chain, String authType, boolean checkOnly) throws CertificateException { + for (int i=0; i < chain.length; i++) + System.err.println("checkServerTrusted chain@" + i + " = " + chain[i]); + + try { + checkAllManagers(chain, authType); + } catch (CertificateException ce) { + + if (checkOnly) { + throw ce; + } else { + + boolean b = askUser(chain,authType); + + if (b) { + temporarilyTrust(chain[0]); + } + + checkAllManagers(chain, authType); + } + } + } + + /** + * Check system, user and custom trust manager + */ + private void checkAllManagers(X509Certificate[] chain, String authType) throws CertificateException { + // First try catrustmanager, then try usertrustmanager, and finally, check temp trusted certs + try { + caTrustManager.checkServerTrusted(chain, authType); + } catch (ValidatorException caex) { + try { + userTrustManager.checkServerTrusted(chain, authType); + } catch (ValidatorException uex) { + if (!temporarilyTrusted.contains(chain[0])) + throw (CertificateException) uex; + } + } + } + + public X509Certificate[] getAcceptedIssuers() { + // delegate to default + return caTrustManager.getAcceptedIssuers(); + } + + /** + * Temporarily trust the given cert (runtime) + * + * @param c The certificate to trust + */ + private void temporarilyTrust(Certificate c) { + temporarilyTrusted.add(c); + } + + /** + * Ask user if the certificate should be trusted + * + * @param chain The certificate chain + * @param authType The authentication algorithm + * @return user's response + */ + private boolean askUser(X509Certificate[] chain, String authType) { + return SecurityWarningDialog.showCertWarningDialog(SecurityWarningDialog.AccessType.UNVERIFIED, null, new HttpsCertVerifier(this, chain, authType)); + } + + /** + * Return an instance of this singleton + * + * @return The instance + */ + public static VariableX509TrustManager getInstance() { + if (instance == null) + instance = new VariableX509TrustManager(); + + return instance; + } +}
--- a/rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java Mon Jan 19 14:41:10 2009 -0500 @@ -43,38 +43,30 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; -import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.PrintStream; import java.security.KeyStore; import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Enumeration; - import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JRootPane; +import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTable; -import javax.swing.ListSelectionModel; -import javax.swing.SwingUtilities; import javax.swing.UIManager; -import javax.swing.plaf.OptionPaneUI; import javax.swing.table.DefaultTableModel; -import javax.swing.JScrollPane; -import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.security.SecurityDialogUI; import net.sourceforge.jnlp.security.SecurityUtil; import net.sourceforge.jnlp.security.SecurityWarningDialog; -import net.sourceforge.jnlp.security.SecurityDialogUI; +import net.sourceforge.jnlp.tools.CertVerifier; import net.sourceforge.jnlp.tools.KeyTool; //import java.security.KeyStoreException; @@ -106,7 +98,7 @@ private KeyStore keyStore = null; public CertificatePane(JComponent x) { - super(x); + super(x, null); initializeKeyStore(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/net/sourceforge/jnlp/tools/CertVerifier.java Mon Jan 19 14:41:10 2009 -0500 @@ -0,0 +1,92 @@ +/* VariableX509TrustManager.java + Copyright (C) 2009 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.tools; + +import java.security.cert.CertPath; +import java.security.cert.Certificate; +import java.util.ArrayList; + +/** + * An interface that provides various details about a certificate + */ + +public interface CertVerifier { + + /** + * Return if the publisher is already trusted + */ + public boolean getAlreadyTrustPublisher(); + + /** + * Return if the root is in CA certs + */ + public boolean getRootInCacerts(); + + /** + * Return if there are signing issues with the certificate(s) being veried + */ + public boolean hasSigningIssues(); + + /** + * Return if there are no signing issues with this cert (!hasSigningIssues()) + */ + public boolean noSigningIssues(); + + /** + * Get the details regarding issue(s) with this certificate + */ + public ArrayList<String> getDetails(); + + /** + * Return a valid certificate path to this certificate(s) being verified + * @return The CertPath + */ + public ArrayList<CertPath> getCerts(); + + /** + * Returns the application's publisher's certificate. + */ + public abstract Certificate getPublisher(); + + /** + * Returns the application's root's certificate. This + * may return the same certificate as getPublisher() in + * the event that the application is self signed. + */ + public abstract Certificate getRoot(); +} \ No newline at end of file
--- a/rt/net/sourceforge/jnlp/tools/JarSigner.java Sat Jan 17 18:41:18 2009 +0100 +++ b/rt/net/sourceforge/jnlp/tools/JarSigner.java Mon Jan 19 14:41:10 2009 -0500 @@ -50,7 +50,7 @@ * @author Jan Luehe */ -public class JarSigner { +public class JarSigner implements CertVerifier { private static String R(String key) { return JNLPRuntime.getMessage(key); @@ -145,10 +145,16 @@ /** details of this signing */ private ArrayList<String> details = new ArrayList<String>(); + /* (non-Javadoc) + * @see net.sourceforge.jnlp.tools.CertVerifier2#getAlreadyTrustPublisher() + */ public boolean getAlreadyTrustPublisher() { return alreadyTrustPublisher; } + /* (non-Javadoc) + * @see net.sourceforge.jnlp.tools.CertVerifier2#getRootInCacerts() + */ public boolean getRootInCacerts() { return rootInCacerts; } @@ -157,11 +163,17 @@ return certPath; } + /* (non-Javadoc) + * @see net.sourceforge.jnlp.tools.CertVerifier2#hasSigningIssues() + */ public boolean hasSigningIssues() { return hasExpiredCert || notYetValidCert || badKeyUsage || badExtendedKeyUsage || badNetscapeCertType; } + /* (non-Javadoc) + * @see net.sourceforge.jnlp.tools.CertVerifier2#noSigningIssues() + */ public boolean noSigningIssues() { return noSigningIssues; } @@ -170,10 +182,16 @@ return anyJarsSigned; } + /* (non-Javadoc) + * @see net.sourceforge.jnlp.tools.CertVerifier2#getDetails() + */ public ArrayList<String> getDetails() { return details; } + /* (non-Javadoc) + * @see net.sourceforge.jnlp.tools.CertVerifier2#getCerts() + */ public ArrayList<CertPath> getCerts() { return certs; } @@ -366,8 +384,8 @@ } } - /** - * Returns the application's publisher's certificate. + /* (non-Javadoc) + * @see net.sourceforge.jnlp.tools.CertVerifier2#getPublisher() */ public Certificate getPublisher() { if (certPath != null) { @@ -383,10 +401,8 @@ } } - /** - * Returns the application's root's certificate. This - * may return the same certificate as getPublisher() in - * the event that the application is self signed. + /* (non-Javadoc) + * @see net.sourceforge.jnlp.tools.CertVerifier2#getRoot() */ public Certificate getRoot() { if (certPath != null) {