changeset 2022:6f7d633c355a

RH663680, CVE-2010-4351: JNLP SecurityManager bypass 2010-12-16 Omair Majid <omajid@redhat.com> RH663680, CVE-2010-4351: * NEWS: List issue. * rt/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java: Make sure SecurityException is thrown if necessary.
author Andrew John Hughes <ahughes@redhat.com>
date Thu, 16 Dec 2010 19:51:32 +0000
parents af20d64bc8b9
children 8784e22fa289
files ChangeLog NEWS rt/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
diffstat 3 files changed, 150 insertions(+), 139 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Dec 16 19:41:01 2010 +0000
+++ b/ChangeLog	Thu Dec 16 19:51:32 2010 +0000
@@ -1,3 +1,10 @@
+2010-12-16  Omair Majid  <omajid@redhat.com>
+
+	RH663680, CVE-2010-4351:
+	* NEWS: List issue.
+	* rt/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java:
+	Make sure SecurityException is thrown if necessary.
+
 2010-12-16  Andrew John Hughes  <ahughes@redhat.com>
 
 	* NEWS: Fix issue placement.
--- a/NEWS	Thu Dec 16 19:41:01 2010 +0000
+++ b/NEWS	Thu Dec 16 19:51:32 2010 +0000
@@ -8,7 +8,9 @@
 
 CVE-XXXX-YYYY: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=XXXX-YYYY
 
-New in release 1.7.7 (201X-XX-XX):
+New in release 1.7.7 (2011-01-12):
+* Security updates
+  - RH663680, CVE-2010-4351: IcedTea JNLP SecurityManager bypass
 * Backports
   - S6438179, RH569121: XToolkit.isTraySupported() result has nothing to do with the system tray
   - S4356282: RFE: JDK should support OpenType/CFF fonts
--- a/rt/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	Thu Dec 16 19:41:01 2010 +0000
+++ b/rt/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	Thu Dec 16 19:51:32 2010 +0000
@@ -188,21 +188,21 @@
      * Return the current Application, or null.
      */
     protected ApplicationInstance getApplication(Class stack[], int maxDepth) {
-    	if (maxDepth <= 0)
-    		maxDepth = stack.length;
+        if (maxDepth <= 0)
+                maxDepth = stack.length;
 
-    	// this needs to be tightened up
-    	for (int i=0; i < stack.length && i < maxDepth; i++) {
-    		if (stack[i].getClassLoader() instanceof JNLPClassLoader) {
-    			JNLPClassLoader loader = (JNLPClassLoader) stack[i].getClassLoader();
+        // this needs to be tightened up
+        for (int i=0; i < stack.length && i < maxDepth; i++) {
+                if (stack[i].getClassLoader() instanceof JNLPClassLoader) {
+                        JNLPClassLoader loader = (JNLPClassLoader) stack[i].getClassLoader();
 
-    			if (loader != null && loader.getApplication() != null) {
-    				return loader.getApplication();
-    			}
-    		} 
-    	}
+                        if (loader != null && loader.getApplication() != null) {
+                                return loader.getApplication();
+                        }
+                }
+        }
 
-    	return null;
+        return null;
     }
 
     /**
@@ -227,17 +227,17 @@
 
         // Enable this manually -- it'll produce too much output for -verbose
         // otherwise.
-	//	if (true)
-	//  	  System.out.println("Checking permission: " + perm.toString());
+        //      if (true)
+        //        System.out.println("Checking permission: " + perm.toString());
 
-        if (!JNLPRuntime.isWebstartApplication() && 
-	      ("setPolicy".equals(name) || "setSecurityManager".equals(name)))
+        if (!JNLPRuntime.isWebstartApplication() &&
+              ("setPolicy".equals(name) || "setSecurityManager".equals(name)))
             throw new SecurityException(R("RCantReplaceSM"));
 
         try {
             // deny all permissions to stopped applications
-        	// The call to getApplication() below might not work if an 
-        	// application hasn't been fully initialized yet.
+                // The call to getApplication() below might not work if an
+                // application hasn't been fully initialized yet.
 //            if (JNLPRuntime.isDebug()) {
 //                if (!"getClassLoader".equals(name)) {
 //                    ApplicationInstance app = getApplication();
@@ -245,95 +245,97 @@
 //                        throw new SecurityException(R("RDenyStopped"));
 //                }
 //            }
-        	
-			try {
-				super.checkPermission(perm);
-			} catch (SecurityException se) {
+
+                        try {
+                                super.checkPermission(perm);
+                        } catch (SecurityException se) {
 
-				//This section is a special case for dealing with SocketPermissions.
-				if (JNLPRuntime.isDebug())
-					System.err.println("Requesting permission: " + perm.toString());
+                                //This section is a special case for dealing with SocketPermissions.
+                                if (JNLPRuntime.isDebug())
+                                        System.err.println("Requesting permission: " + perm.toString());
+
+                                //Change this SocketPermission's action to connect and accept
+                                //(and resolve). This is to avoid asking for connect permission
+                                //on every address resolve.
+                                Permission tmpPerm = null;
+                                if (perm instanceof SocketPermission) {
+                                        tmpPerm = new SocketPermission(perm.getName(),
+                                                        SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION);
 
-				//Change this SocketPermission's action to connect and accept
-				//(and resolve). This is to avoid asking for connect permission 
-				//on every address resolve.
-				Permission tmpPerm = null;
-				if (perm instanceof SocketPermission) {
-					tmpPerm = new SocketPermission(perm.getName(), 
-							SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION);
-					
-					// before proceeding, check if we are trying to connect to same origin
-					ApplicationInstance app = getApplication();
-					JNLPFile file = app.getJNLPFile();
+                                        // before proceeding, check if we are trying to connect to same origin
+                                        ApplicationInstance app = getApplication();
+                                        JNLPFile file = app.getJNLPFile();
+
+                                        String srcHost =  file.getSourceLocation().getAuthority();
+                                        String destHost = name;
+
+                                        // host = abc.xyz.com or abc.xyz.com:<port>
+                                        if (destHost.indexOf(':') >= 0)
+                                                destHost = destHost.substring(0, destHost.indexOf(':'));
 
-					String srcHost =  file.getSourceLocation().getAuthority();
-					String destHost = name;
-					
-					// host = abc.xyz.com or abc.xyz.com:<port> 
-					if (destHost.indexOf(':') >= 0)
-						destHost = destHost.substring(0, destHost.indexOf(':'));
-					
-					// host = abc.xyz.com
-					String[] hostComponents = destHost.split("\\.");
-					
-					int length = hostComponents.length;
-					if (length >= 2) {
-						
-						// address is in xxx.xxx.xxx format
-						destHost = hostComponents[length -2] + "." + hostComponents[length -1];
-					
-						// host = xyz.com i.e. origin
-						boolean isDestHostName = false;
+                                        // host = abc.xyz.com
+                                        String[] hostComponents = destHost.split("\\.");
+
+                                        int length = hostComponents.length;
+                                        if (length >= 2) {
+
+                                                // address is in xxx.xxx.xxx format
+                                                destHost = hostComponents[length -2] + "." + hostComponents[length -1];
+
+                                                // host = xyz.com i.e. origin
+                                                boolean isDestHostName = false;
 
-						// make sure that it is not an ip address
-						try {
-							Integer.parseInt(hostComponents[length -1]);
-						} catch (NumberFormatException e) {
-							isDestHostName = true;
-						}
+                                                // make sure that it is not an ip address
+                                                try {
+                                                        Integer.parseInt(hostComponents[length -1]);
+                                                } catch (NumberFormatException e) {
+                                                        isDestHostName = true;
+                                                }
 
-						if (isDestHostName) {
-							// okay, destination is hostname. Now figure out if it is a subset of origin
-							if (srcHost.endsWith(destHost)) {
-								addPermission(tmpPerm);
-								return;
-							}
-						}
-					}
+                                                if (isDestHostName) {
+                                                        // okay, destination is hostname. Now figure out if it is a subset of origin
+                                                        if (srcHost.endsWith(destHost)) {
+                                                                addPermission(tmpPerm);
+                                                                return;
+                                                        }
+                                                }
+                                        }
 
-				} else if (perm instanceof SecurityPermission) {
+                                } else if (perm instanceof SecurityPermission) {
+                                    tmpPerm = perm;
 
-				    // JCE's initialization requires putProviderProperty permission
-				    if (perm.equals(new SecurityPermission("putProviderProperty.SunJCE"))) {
-				        if (inTrustedCallChain("com.sun.crypto.provider.SunJCE", "run")) {
-				            return;
-				        }
-				    }
+                                    // JCE's initialization requires putProviderProperty permission
+                                    if (perm.equals(new SecurityPermission("putProviderProperty.SunJCE"))) {
+                                        if (inTrustedCallChain("com.sun.crypto.provider.SunJCE", "run")) {
+                                            return;
+                                        }
+                                    }
 
-				} else if (perm instanceof RuntimePermission) {
+                                } else if (perm instanceof RuntimePermission) {
+                                    tmpPerm = perm;
 
-				    // KeyGenerator's init method requires internal spec access
-				    if (perm.equals(new SecurityPermission("accessClassInPackage.sun.security.internal.spec"))) {
-				        if (inTrustedCallChain("javax.crypto.KeyGenerator", "init")) {
-				            return;
-				        }
-				    }
+                                    // KeyGenerator's init method requires internal spec access
+                                    if (perm.equals(new SecurityPermission("accessClassInPackage.sun.security.internal.spec"))) {
+                                        if (inTrustedCallChain("javax.crypto.KeyGenerator", "init")) {
+                                            return;
+                                        }
+                                    }
 
-				} else {
-				    tmpPerm = perm;
-				}
+                                } else {
+                                    tmpPerm = perm;
+                                }
 
-				if (tmpPerm != null) {
-				    //askPermission will only prompt the user on SocketPermission 
-				    //meaning we're denying all other SecurityExceptions that may arise.
-				    if (askPermission(tmpPerm)) {
-				        addPermission(tmpPerm);
-				        //return quietly.
-				    } else {
-				        throw se;
-				    }
-				}
-			}
+                                if (tmpPerm != null) {
+                                    //askPermission will only prompt the user on SocketPermission
+                                    //meaning we're denying all other SecurityExceptions that may arise.
+                                    if (askPermission(tmpPerm)) {
+                                        addPermission(tmpPerm);
+                                        //return quietly.
+                                    } else {
+                                        throw se;
+                                    }
+                                }
+                        }
         }
         catch (SecurityException ex) {
             if (JNLPRuntime.isDebug()) {
@@ -343,18 +345,18 @@
         }
     }
 
-    /** 
-     * Returns weather the given class and method are in the current stack, 
+    /**
+     * Returns weather the given class and method are in the current stack,
      * and whether or not everything upto then is trusted
-     * 
+     *
      * @param className The name of the class to look for in the stack
      * @param methodName The name of the method for the given class to look for in the stack
      * @return Weather or not class::method() are in the chain, and everything upto there is trusted
      */
     private boolean inTrustedCallChain(String className, String methodName) {
-        
+
         StackTraceElement[] stack =  Thread.currentThread().getStackTrace();
-        
+
         for (int i=0; i < stack.length; i++) {
 
             // Everything up to the desired class/method must be trusted
@@ -367,49 +369,49 @@
                 return true;
             }
         }
-        
+
         return false;
     }
-    
+
     /**
      * Asks the user whether or not to grant permission.
      * @param perm the permission to be granted
      * @return true if the permission was granted, false otherwise.
      */
-    private boolean askPermission(Permission perm)	{
-    	
-    	ApplicationInstance app = getApplication();
-    	if (app != null && !app.isSigned()) {
-        	if (perm instanceof SocketPermission 
-        			&& ServiceUtil.checkAccess(SecurityWarningDialog.AccessType.NETWORK, perm.getName())) {
-        		return true;
-        	}
-    	}
+    private boolean askPermission(Permission perm)      {
 
-    	return false;
+        ApplicationInstance app = getApplication();
+        if (app != null && !app.isSigned()) {
+                if (perm instanceof SocketPermission
+                                && ServiceUtil.checkAccess(SecurityWarningDialog.AccessType.NETWORK, perm.getName())) {
+                        return true;
+                }
+        }
+
+        return false;
     }
 
     /**
      * Adds a permission to the JNLPClassLoader.
      * @param perm the permission to add to the JNLPClassLoader
      */
-    private void addPermission(Permission perm)	{
-    	if (JNLPRuntime.getApplication().getClassLoader() instanceof JNLPClassLoader) {
+    private void addPermission(Permission perm) {
+        if (JNLPRuntime.getApplication().getClassLoader() instanceof JNLPClassLoader) {
 
-    		JNLPClassLoader cl = (JNLPClassLoader) JNLPRuntime.getApplication().getClassLoader();
-    		cl.addPermission(perm);
-        	if (JNLPRuntime.isDebug()) {
-        		if (cl.getPermissions(null).implies(perm))
-        			System.err.println("Added permission: " + perm.toString());
-        		else
-        			System.err.println("Unable to add permission: " + perm.toString());
-        	}
-    	} else {
-        	if (JNLPRuntime.isDebug())
-        		System.err.println("Unable to add permission: " + perm + ", classloader not JNLP.");
-    	}
+                JNLPClassLoader cl = (JNLPClassLoader) JNLPRuntime.getApplication().getClassLoader();
+                cl.addPermission(perm);
+                if (JNLPRuntime.isDebug()) {
+                        if (cl.getPermissions(null).implies(perm))
+                                System.err.println("Added permission: " + perm.toString());
+                        else
+                                System.err.println("Unable to add permission: " + perm.toString());
+                }
+        } else {
+                if (JNLPRuntime.isDebug())
+                        System.err.println("Unable to add permission: " + perm + ", classloader not JNLP.");
+        }
     }
-    
+
     /**
      * Checks whether the window can be displayed without an applet
      * warning banner, and adds the window to the list of windows to
@@ -418,7 +420,7 @@
     public boolean checkTopLevelWindow(Object window) {
         ApplicationInstance app = getApplication();
 
-        // remember window -> application mapping for focus, close on exit 
+        // remember window -> application mapping for focus, close on exit
         if (app != null && window instanceof Window) {
             Window w = (Window) window;
 
@@ -439,7 +441,7 @@
 
         // todo: set awt.appletWarning to custom message
         // todo: logo on with glass pane on JFrame/JWindow?
-        
+
         return super.checkTopLevelWindow(window);
     }
 
@@ -458,16 +460,16 @@
      */
     public void checkExit(int status) {
 
-    	// applets are not allowed to exit, but the plugin main class (primordial loader) is
+        // applets are not allowed to exit, but the plugin main class (primordial loader) is
         Class stack[] = getClassContext();
         if (!exitAllowed) {
-        	for (int i=0; i < stack.length; i++)
-        		if (stack[i].getClassLoader() != null)
-        			throw new AccessControlException("Applets may not call System.exit()");
+                for (int i=0; i < stack.length; i++)
+                        if (stack[i].getClassLoader() != null)
+                                throw new AccessControlException("Applets may not call System.exit()");
         }
 
-    	super.checkExit(status);
-        
+        super.checkExit(status);
+
         boolean realCall = (stack[1] == Runtime.class);
 
         if (isExitClass(stack)) // either exitClass called or no exitClass set
@@ -498,9 +500,9 @@
     }
 
     protected void disableExit() {
-    	exitAllowed = false;
+        exitAllowed = false;
     }
-    
+
 }