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)
author Deepak Bhole <dbhole@redhat.com>
date Mon, 19 Jan 2009 14:41:10 -0500
parents 3a265e06dc74
children 15b39cd337dc
files ChangeLog IcedTeaPlugin.cc plugin/icedtea/sun/applet/PluginAppletViewer.java plugin/icedtea/sun/applet/PluginMain.java rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java rt/net/sourceforge/jnlp/security/AccessWarningPane.java rt/net/sourceforge/jnlp/security/AppletWarningPane.java rt/net/sourceforge/jnlp/security/CertWarningPane.java rt/net/sourceforge/jnlp/security/CertsInfoPane.java rt/net/sourceforge/jnlp/security/HttpsCertVerifier.java rt/net/sourceforge/jnlp/security/MoreInfoPane.java rt/net/sourceforge/jnlp/security/SecurityDialogUI.java rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java rt/net/sourceforge/jnlp/security/VariableX509TrustManager.java rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java rt/net/sourceforge/jnlp/tools/CertVerifier.java rt/net/sourceforge/jnlp/tools/JarSigner.java
diffstat 18 files changed, 682 insertions(+), 98 deletions(-) [+]
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) {