# HG changeset patch # User Deepak Bhole # Date 1310758958 14400 # Node ID b29fdd0f4d041d639f930c50bac7b8388e874887 # Parent 7e1ca05d223f3770b45596348f99a37889d061fc RH718164, CVE-2011-2513: Home directory path disclosure to untrusted applications diff -r 7e1ca05d223f -r b29fdd0f4d04 ChangeLog --- a/ChangeLog Mon Jun 13 17:26:41 2011 -0400 +++ b/ChangeLog Fri Jul 15 15:42:38 2011 -0400 @@ -1,3 +1,21 @@ +2011-07-14 Omair Majid + + RH718164, CVE-2011-2513: Home directory path disclosure to untrusted + applications + * netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java: New file. + * netx/net/sourceforge/jnlp/util/UrlUtils.java: New file. + * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: + jarLocationSecurityMap now contains originating urls, not cache urls. + (initializeResources): Add remote url to map instead of local url. + (activateJars): Add remote url to the classloader's urls. Add mapping for + remote to local url. Put remote url in jarLocationSecurityMap. + (loadClass): Add remote url to the classloader's urls. Add mapping for + remote to local url. + (getCodeSourceSecurity): Update javadoc to note that the url must be + remote. + * netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java + (initialize): Set the callback for URLJarFile. + 2011-06-13 Deepak Bhole * configure.ac: Prepare for 1.0.4. diff -r 7e1ca05d223f -r b29fdd0f4d04 NEWS --- a/NEWS Mon Jun 13 17:26:41 2011 -0400 +++ b/NEWS Fri Jul 15 15:42:38 2011 -0400 @@ -9,6 +9,8 @@ CVE-XXXX-YYYY: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=XXXX-YYYY New in release 1.0.4 (2011-XX-XX): +* Security updates: + - RH718164, CVE-2011-2513: Home directory path disclosure to untrusted applications New in release 1.0.3 (2011-06-13): * Plugin diff -r 7e1ca05d223f -r b29fdd0f4d04 netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java Fri Jul 15 15:42:38 2011 -0400 @@ -0,0 +1,157 @@ +/* CachedJarFileCallback.java + Copyright (C) 2011 Red Hat, Inc. + Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + +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.runtime; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.jar.JarFile; + +import net.sourceforge.jnlp.util.UrlUtils; + +import sun.net.www.protocol.jar.URLJarFile; +import sun.net.www.protocol.jar.URLJarFileCallBack; + +/** + * Invoked by URLJarFile to get a JarFile corresponding to a URL. + * + * Large parts of this class are based on JarFileFactory and URLJarFile. + */ +final class CachedJarFileCallback implements URLJarFileCallBack { + + private static final CachedJarFileCallback INSTANCE = new CachedJarFileCallback(); + + public synchronized static CachedJarFileCallback getInstance() { + return INSTANCE; + } + + /* our managed cache */ + private final Map mapping; + + private CachedJarFileCallback() { + mapping = new ConcurrentHashMap(); + } + + protected void addMapping(URL remoteUrl, URL localUrl) { + mapping.put(remoteUrl, localUrl); + } + + @Override + public JarFile retrieve(URL url) throws IOException { + URL localUrl = mapping.get(url); + + if (localUrl == null) { + /* + * If the jar url is not known, treat it as it would be treated in + * general by URLJarFile. + */ + return cacheJarFile(url); + } + + if (UrlUtils.isLocalFile(localUrl)) { + // if it is known to us, just return the cached file + return new JarFile(localUrl.getPath()); + } else { + // throw new IllegalStateException("a non-local file in cache"); + return null; + } + + } + + /* + * This method is a copy of URLJarFile.retrieve() without the callback check. + */ + private JarFile cacheJarFile(URL url) throws IOException { + JarFile result = null; + + final int BUF_SIZE = 2048; + + /* get the stream before asserting privileges */ + final InputStream in = url.openConnection().getInputStream(); + + try { + result = + AccessController.doPrivileged(new PrivilegedExceptionAction() { + @Override + public JarFile run() throws IOException { + OutputStream out = null; + File tmpFile = null; + try { + tmpFile = File.createTempFile("jar_cache", null); + tmpFile.deleteOnExit(); + out = new FileOutputStream(tmpFile); + int read = 0; + byte[] buf = new byte[BUF_SIZE]; + while ((read = in.read(buf)) != -1) { + out.write(buf, 0, read); + } + out.close(); + out = null; + return new URLJarFile(tmpFile, null); + } catch (IOException e) { + if (tmpFile != null) { + tmpFile.delete(); + } + throw e; + } finally { + if (in != null) { + in.close(); + } + if (out != null) { + out.close(); + } + } + } + }); + } catch (PrivilegedActionException pae) { + throw (IOException) pae.getException(); + } + + return result; + } + +} diff -r 7e1ca05d223f -r b29fdd0f4d04 netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java --- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Mon Jun 13 17:26:41 2011 -0400 +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Fri Jul 15 15:42:38 2011 -0400 @@ -141,7 +141,7 @@ /** File entries in the jar files available to this classloader */ private TreeSet jarEntries = new TreeSet(); - /** Map of specific codesources to securitydesc */ + /** Map of specific original (remote) CodeSource Urls to securitydesc */ private HashMap jarLocationSecurityMap = new HashMap(); @@ -490,7 +490,7 @@ } } - jarLocationSecurityMap.put(location, jarSecurity); + jarLocationSecurityMap.put(jarDesc.getLocation(), jarSecurity); } catch (MalformedURLException mfe) { System.err.println(mfe.getMessage()); } @@ -711,7 +711,10 @@ try { URL fileURL = new URL("file://" + extractedJarLocation); - addURL(fileURL); + // there is no remote URL for this, so lets fake one + URL fakeRemote = new URL(jar.getLocation().toString() + "!" + je.getName()); + CachedJarFileCallback.getInstance().addMapping(fakeRemote, fileURL); + addURL(fakeRemote); SecurityDesc jarSecurity = file.getSecurity(); @@ -732,7 +735,7 @@ codebase.getHost()); } - jarLocationSecurityMap.put(fileURL, jarSecurity); + jarLocationSecurityMap.put(fakeRemote, jarSecurity); } catch (MalformedURLException mfue) { if (JNLPRuntime.isDebug()) @@ -747,15 +750,18 @@ } - addURL(location); + addURL(jar.getLocation()); // there is currently no mechanism to cache files per // instance.. so only index cached files if (localFile != null) { + CachedJarFileCallback.getInstance().addMapping(jar.getLocation(), localFile.toURL()); JarIndex index = JarIndex.getJarIndex(new JarFile(localFile.getAbsolutePath()), null); if (index != null) jarIndexes.add(index); + } else { + CachedJarFileCallback.getInstance().addMapping(jar.getLocation(), jar.getLocation()); } if (JNLPRuntime.isDebug()) @@ -1031,8 +1037,10 @@ throw new ClassNotFoundException(name); } - if (u != null) - addURL(u); + if (u != null) { + addURL(remoteURL); + CachedJarFileCallback.getInstance().addMapping(remoteURL, u); + } } @@ -1222,7 +1230,7 @@ /** * Returns the security descriptor for given code source URL * - * @param source The code source + * @param source the origin (remote) url of the code * @return The SecurityDescriptor for that source */ diff -r 7e1ca05d223f -r b29fdd0f4d04 netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java --- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java Mon Jun 13 17:26:41 2011 -0400 +++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java Fri Jul 15 15:42:38 2011 -0400 @@ -34,6 +34,8 @@ import javax.swing.UIManager; import javax.swing.text.html.parser.ParserDelegator; +import sun.net.www.protocol.jar.URLJarFile; + import net.sourceforge.jnlp.*; import net.sourceforge.jnlp.cache.*; import net.sourceforge.jnlp.security.JNLPAuthenticator; @@ -223,6 +225,8 @@ Security.setProperty("package.access", Security.getProperty("package.access")+",net.sourceforge.jnlp"); + URLJarFile.setCallBack(CachedJarFileCallback.getInstance()); + initialized = true; } diff -r 7e1ca05d223f -r b29fdd0f4d04 netx/net/sourceforge/jnlp/util/UrlUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/util/UrlUtils.java Fri Jul 15 15:42:38 2011 -0400 @@ -0,0 +1,53 @@ +/* UrlUtils.java + Copyright (C) 2011 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.util; + +import java.net.URL; + +public class UrlUtils { + + public static boolean isLocalFile(URL url) { + + if (url.getProtocol().equals("file") && + (url.getAuthority() == null || url.getAuthority().equals("")) && + (url.getHost() == null || url.getHost().equals(("")))) { + return true; + } + return false; + } +}