changeset in /hg/icedtea: Security patches for netx+plugin.

Andrew John Hughes ahughes at redhat.com
Wed Aug 5 07:19:55 PDT 2009


changeset 77ea95965bad in /hg/icedtea
details: http://icedtea.classpath.org/hg/icedtea?cmd=changeset;node=77ea95965bad
description:
	Security patches for netx+plugin.

	2009-08-05  Lillian Angel  <langel at redhat.com>

		* plugin/icedtea/netscape/javascript/JSObject.java: Security patch
		applied to disallow the ability to run unsigned code as
		signed under some cases.
		* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java:
		Likewise.
		* netx/net/sourceforge/jnlp/SecurityDesc.java: Likewise.
		* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Likewise.
		* plugin/icedtea/netscape/javascript/JSObjectCreatePermission.java:
		Likewise.
		* netx/netscape/javascript/JSObjectCreatePermission.java: Likewise.

diffstat:

7 files changed, 360 insertions(+), 180 deletions(-)
ChangeLog                                                        |   13 
netx/net/sourceforge/jnlp/SecurityDesc.java                      |   24 
netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java           |  366 +++++-----
netx/netscape/javascript/JSObjectCreatePermission.java           |   47 +
plugin/icedtea/netscape/javascript/JSObject.java                 |   37 -
plugin/icedtea/netscape/javascript/JSObjectCreatePermission.java |   47 +
plugin/icedtea/sun/applet/PluginAppletSecurityContext.java       |    6 

diffs (truncated from 826 to 500 lines):

diff -r adadd58eff31 -r 77ea95965bad ChangeLog
--- a/ChangeLog	Wed Aug 05 15:02:51 2009 +0100
+++ b/ChangeLog	Wed Aug 05 15:22:13 2009 +0100
@@ -1,3 +1,16 @@ 2009-08-04  Andrew John Hughes  <ahughes
+2009-08-05  Lillian Angel  <langel at redhat.com>
+
+	* plugin/icedtea/netscape/javascript/JSObject.java: Security patch
+	applied to disallow the ability to run unsigned code as 
+	signed under some cases.
+	* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/SecurityDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Likewise.
+	* plugin/icedtea/netscape/javascript/JSObjectCreatePermission.java:
+	Likewise.
+	* netx/netscape/javascript/JSObjectCreatePermission.java: Likewise.
+
 2009-08-04  Andrew John Hughes  <ahughes at redhat.com>
 
 	* Makefile.am:
diff -r adadd58eff31 -r 77ea95965bad netx/net/sourceforge/jnlp/SecurityDesc.java
--- a/netx/net/sourceforge/jnlp/SecurityDesc.java	Wed Aug 05 15:02:51 2009 +0100
+++ b/netx/net/sourceforge/jnlp/SecurityDesc.java	Wed Aug 05 15:22:13 2009 +0100
@@ -166,6 +166,30 @@ public class SecurityDesc {
 
         return permissions;
     }
+    
+    /**
+     * Returns a PermissionCollection containing the sandbox permissions
+     */
+    public PermissionCollection getSandBoxPermissions() {
+        
+        Permissions permissions = new Permissions();
+
+        for (int i=0; i < sandboxPermissions.length; i++)
+            permissions.add(sandboxPermissions[i]);
+
+        if (downloadHost != null)
+            permissions.add(new SocketPermission(downloadHost,
+                                                 "connect, accept"));
+
+        // properties
+        PropertyDesc props[] = file.getResources().getProperties();
+        for (int i=0; i < props.length; i++) {
+            // should only allow jnlp.* properties if in sandbox?
+            permissions.add(new PropertyPermission(props[i].getKey(), "read,write"));
+        }
+
+        return permissions;
+    }
 
 }
 
diff -r adadd58eff31 -r 77ea95965bad netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Wed Aug 05 15:02:51 2009 +0100
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Wed Aug 05 15:22:13 2009 +0100
@@ -1,15 +1,15 @@
 
-// 
+//
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
 // version 2.1 of the License, or (at your option) any later version.
-// 
+//
 // This library 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
 // Lesser General Public License for more details.
-// 
+//
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -66,7 +66,7 @@ import sun.misc.JarIndex;
  * security context when the classloader was created.
  *
  * @author <a href="mailto:jmaxwell at users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
- * @version $Revision: 1.20 $ 
+ * @version $Revision: 1.20 $
  */
 public class JNLPClassLoader extends URLClassLoader {
 
@@ -115,29 +115,29 @@ public class JNLPClassLoader extends URL
 
     /** the security section */
     private SecurityDesc security;
-    
+
     /** Permissions granted by the user during runtime. */
     private ArrayList<Permission> runtimePermissions = new ArrayList<Permission>();
 
     /** all jars not yet part of classloader or active */
     private List available = new ArrayList();
 
-	/** all of the jar files that were verified */
-	private ArrayList<String> verifiedJars = null;
-
-	/** all of the jar files that were not verified */
-	private ArrayList<String> unverifiedJars = null;
-
-	/** the jarsigner tool to verify our jars */
-	private JarSigner js = null;
-
-	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();
+        /** all of the jar files that were verified */
+        private ArrayList<String> verifiedJars = null;
+
+        /** all of the jar files that were not verified */
+        private ArrayList<String> unverifiedJars = null;
+
+        /** the jarsigner tool to verify our jars */
+        private JarSigner js = null;
+
+        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.
@@ -167,41 +167,41 @@ public class JNLPClassLoader extends URL
     }
 
     private void setSecurity() {
-		/**
-		 * When we're trying to load an applet, file.getSecurity() will return
-		 * null since there is no jnlp file to specify permissions. We
-		 * determine security settings here, after trying to verify jars.
-		 */
-		if (file instanceof PluginBridge) {
-			if (signing == true) {
-				this.security = new SecurityDesc(file, 
-					SecurityDesc.ALL_PERMISSIONS,
-					file.getCodeBase().getHost());
-			} else {
-				this.security = new SecurityDesc(file, 
-					SecurityDesc.SANDBOX_PERMISSIONS, 
-					file.getCodeBase().getHost());
-			}
-		} else { //regular jnlp file
-			
-			/**
-			 * If the application is signed, then we set the SecurityDesc to the
-			 * <security> tag in the jnlp file. Note that if an application is
-			 * signed, but there is no <security> tag in the jnlp file, the
-			 * application will get sandbox permissions.
-			 * If the application is unsigned, we ignore the <security> tag and 
-			 * use a sandbox instead. 
-			 */
-			if (signing == true) {
-				this.security = file.getSecurity();
-			} else {
-				this.security = new SecurityDesc(file, 
-						SecurityDesc.SANDBOX_PERMISSIONS, 
-						file.getCodeBase().getHost());
-			}
-		}
-    }
-    
+                /**
+                 * When we're trying to load an applet, file.getSecurity() will return
+                 * null since there is no jnlp file to specify permissions. We
+                 * determine security settings here, after trying to verify jars.
+                 */
+                if (file instanceof PluginBridge) {
+                        if (signing == true) {
+                                this.security = new SecurityDesc(file,
+                                        SecurityDesc.ALL_PERMISSIONS,
+                                        file.getCodeBase().getHost());
+                        } else {
+                                this.security = new SecurityDesc(file,
+                                        SecurityDesc.SANDBOX_PERMISSIONS,
+                                        file.getCodeBase().getHost());
+                        }
+                } else { //regular jnlp file
+
+                        /**
+                         * If the application is signed, then we set the SecurityDesc to the
+                         * <security> tag in the jnlp file. Note that if an application is
+                         * signed, but there is no <security> tag in the jnlp file, the
+                         * application will get sandbox permissions.
+                         * If the application is unsigned, we ignore the <security> tag and
+                         * use a sandbox instead.
+                         */
+                        if (signing == true) {
+                                this.security = file.getSecurity();
+                        } else {
+                                this.security = new SecurityDesc(file,
+                                                SecurityDesc.SANDBOX_PERMISSIONS,
+                                                file.getCodeBase().getHost());
+                        }
+                }
+    }
+
     /**
      * Returns a JNLP classloader for the specified JNLP file.
      *
@@ -215,12 +215,12 @@ public class JNLPClassLoader extends URL
         if (location != null)
             loader = (JNLPClassLoader) urlToLoader.get(location);
 
-		try {
-        	if (loader == null)
-            	loader = new JNLPClassLoader(file, policy);
-		} catch (LaunchException e) {
-			throw e;
-		}
+                try {
+                if (loader == null)
+                loader = new JNLPClassLoader(file, policy);
+                } catch (LaunchException e) {
+                        throw e;
+                }
 
         if (file.getInformation().isSharingAllowed())
             urlToLoader.put(location, loader);
@@ -230,7 +230,7 @@ public class JNLPClassLoader extends URL
 
     /**
      * Returns a JNLP classloader for the JNLP file at the specified
-     * location. 
+     * location.
      *
      * @param location the file's location
      * @param version the file's version
@@ -256,17 +256,17 @@ public class JNLPClassLoader extends URL
 
         loaderList.add(this);
 
-		//if (ext != null) {
-        	for (int i=0; i < ext.length; i++) {
-            	try {
-               		JNLPClassLoader loader = getInstance(ext[i].getLocation(), ext[i].getVersion(), updatePolicy);
-                	loaderList.add(loader);
-            	}
-            	catch (Exception ex) {
-                	ex.printStackTrace();
-            	}
-        	}
-		//}
+                //if (ext != null) {
+                for (int i=0; i < ext.length; i++) {
+                try {
+                        JNLPClassLoader loader = getInstance(ext[i].getLocation(), ext[i].getVersion(), updatePolicy);
+                        loaderList.add(loader);
+                }
+                catch (Exception ex) {
+                        ex.printStackTrace();
+                }
+                }
+                //}
 
         loaders = (JNLPClassLoader[]) loaderList.toArray(new JNLPClassLoader[ loaderList.size()]);
     }
@@ -283,10 +283,10 @@ public class JNLPClassLoader extends URL
                                                        jars[i].getVersion());
 
             if (JNLPRuntime.isDebug()) {
-            	if (p == null)
-            		System.out.println("Unable to add permission for " + jars[i].getLocation());
-            	else
-            		System.out.println("Permission added: " + p.toString());
+                if (p == null)
+                        System.out.println("Unable to add permission for " + jars[i].getLocation());
+                else
+                        System.out.println("Permission added: " + p.toString());
             }
             if (p != null)
                 resourcePermissions.add(p);
@@ -299,14 +299,14 @@ public class JNLPClassLoader extends URL
      */
     void initializeResources() throws LaunchException {
         JARDesc jars[] = resources.getJARs();
-		if (jars == null || jars.length == 0)
-			return;
-		/*
-		if (jars == null || jars.length == 0) {
-			throw new LaunchException(null, null, R("LSFatal"),
-			                    R("LCInit"), R("LFatalVerification"), "No jars!");
-		}
-		*/
+                if (jars == null || jars.length == 0)
+                        return;
+                /*
+                if (jars == null || jars.length == 0) {
+                        throw new LaunchException(null, null, R("LSFatal"),
+                                            R("LCInit"), R("LFatalVerification"), "No jars!");
+                }
+                */
         List initialJars = new ArrayList();
 
         for (int i=0; i < jars.length; i++) {
@@ -317,7 +317,7 @@ public class JNLPClassLoader extends URL
                 initialJars.add(jars[i]); // regardless of part
 
             tracker.addResource(jars[i].getLocation(),
-                                jars[i].getVersion(), 
+                                jars[i].getVersion(),
                                 jars[i].isCacheable() ? JNLPRuntime.getDefaultUpdatePolicy() : UpdatePolicy.FORCE
                                );
         }
@@ -325,42 +325,42 @@ public class JNLPClassLoader extends URL
         if (strict)
             fillInPartJars(initialJars); // add in each initial part's lazy jars
 
-		if (JNLPRuntime.isVerifying()) {
-
-			JarSigner js;
-			waitForJars(initialJars); //download the jars first.
-
-			try {
-				js = verifyJars(initialJars);
-			} catch (Exception e) {
-				//we caught an Exception from the JarSigner class.
-				//Note: one of these exceptions could be from not being able
-				//to read the cacerts or trusted.certs files.
-				e.printStackTrace();
-				throw new LaunchException(null, null, R("LSFatal"),
-					R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo"));
-			}
-
-			//Case when at least one jar has some signing
-			if (js.anyJarsSigned()){
-				signing = true;
-
-				//user does not trust this publisher
-				if (!js.getAlreadyTrustPublisher()) {
-				    checkTrustWithUser(js);
-				} else {
-					/**
-					 * If the user trusts this publisher (i.e. the publisher's certificate
-					 * is in the user's trusted.certs file), we do not show any dialogs.
-					 */
-				}
-			} else {
-
-				signing = false;
-				//otherwise this jar is simply unsigned -- make sure to ask
-				//for permission on certain actions
-			}
-		}
+                if (JNLPRuntime.isVerifying()) {
+
+                        JarSigner js;
+                        waitForJars(initialJars); //download the jars first.
+
+                        try {
+                                js = verifyJars(initialJars);
+                        } catch (Exception e) {
+                                //we caught an Exception from the JarSigner class.
+                                //Note: one of these exceptions could be from not being able
+                                //to read the cacerts or trusted.certs files.
+                                e.printStackTrace();
+                                throw new LaunchException(null, null, R("LSFatal"),
+                                        R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo"));
+                        }
+
+                        //Case when at least one jar has some signing
+                        if (js.anyJarsSigned()){
+                                signing = true;
+
+                                //user does not trust this publisher
+                                if (!js.getAlreadyTrustPublisher()) {
+                                    checkTrustWithUser(js);
+                                } else {
+                                        /**
+                                         * If the user trusts this publisher (i.e. the publisher's certificate
+                                         * is in the user's trusted.certs file), we do not show any dialogs.
+                                         */
+                                }
+                        } else {
+
+                                signing = false;
+                                //otherwise this jar is simply unsigned -- make sure to ask
+                                //for permission on certain actions
+                        }
+                }
 
         activateJars(initialJars);
     }
@@ -370,7 +370,7 @@ public class JNLPClassLoader extends URL
             boolean b = SecurityWarningDialog.showCertWarningDialog(
                 SecurityWarningDialog.AccessType.UNVERIFIED, file, js);
             if (!b)
-                throw new LaunchException(null, null, R("LSFatal"), 
+                throw new LaunchException(null, null, R("LSFatal"),
                     R("LCLaunching"), R("LNotVerified"), "");
         } else if (js.getRootInCacerts()) { //root cert is in cacerts
             boolean b = false;
@@ -435,11 +435,29 @@ public class JNLPClassLoader extends URL
         // access w/o security dialog once we actually check certificates.
 
         // copy security permissions from SecurityDesc element
-		if (security != null) {
-        	Enumeration e = security.getPermissions().elements();
-        	while (e.hasMoreElements())
-            	result.add((Permission) e.nextElement());
-		}
+        if (security != null) {
+            // Security desc. is used only to track security settings for the
+            // application. However, an application may comprise of multiple
+            // jars, and as such, security must be evaluated on a per jar basis.
+
+            // set default perms
+            PermissionCollection permissions = security.getSandBoxPermissions();
+
+            // If more than default is needed, evaluate based on codesource
+            if (security.getSecurityType().equals(SecurityDesc.ALL_PERMISSIONS) ||
+                security.getSecurityType().equals(SecurityDesc.J2EE_PERMISSIONS)) {
+
+                 if (cs.getCodeSigners() != null) {
+                    permissions = security.getPermissions();
+                }
+            }
+
+            Enumeration<Permission> e = permissions.elements();
+            while (e.hasMoreElements())
+                result.add(e.nextElement());
+        }
+
+
 
         // add in permission to read the cached JAR files
         for (int i=0; i < resourcePermissions.size(); i++)
@@ -447,15 +465,15 @@ public class JNLPClassLoader extends URL
 
         // add in the permissions that the user granted.
         for (int i=0; i < runtimePermissions.size(); i++)
-        	result.add(runtimePermissions.get(i));
+                result.add(runtimePermissions.get(i));
 
         return result;
     }
 
     protected void addPermission(Permission p) {
-    	runtimePermissions.add(p);
-    }
-    
+        runtimePermissions.add(p);
+    }
+
     /**
      * Adds to the specified list of JARS any other JARs that need
      * to be loaded at the same time as the JARs specified (ie, are
@@ -501,25 +519,25 @@ public class JNLPClassLoader extends URL
                         URL location = jar.getLocation(); // non-cacheable, use source location
                         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 
+
+                            // 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()) {
-                                
+
                                 JarEntry je = (JarEntry) e.nextElement();
-                                
-                                // another jar in my jar? it is more likely than you think  
+
+                                // another jar in my jar? it is more likely than you think
                                 if (je.getName().endsWith(".jar")) {
-                                    // We need to extract that jar so that it can be loaded 
-                                    // (inline loading with "jar:..!/..." path will not work 
+                                    // We need to extract that jar so that it can be loaded
+                                    // (inline loading with "jar:..!/..." path will not work
                                     // with standard classloader methods)
 
                                     String extractedJarLocation = localFile.getParent() + "/" + je.getName();
@@ -564,7 +582,7 @@ public class JNLPClassLoader extends URL
 
                         addURL(location);
 
-                        // there is currently no mechanism to cache files per 
+                        // there is currently no mechanism to cache files per



More information about the distro-pkg-dev mailing list