# HG changeset patch # User Andrew John Hughes # Date 1311166684 -3600 # Node ID d40e83dd3bb2ee0c8e431739b959cdeed49fbbbe # Parent c5121c10ed2fc3f9483ed9577efbbf97ea52e106 RH718164, CVE-2011-2513: Home directory path disclosure to untrusted apps 2011-07-20 Andrew John Hughes * NEWS: List security fix. 2011-07-14 Omair Majid * 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. diff -r c5121c10ed2f -r d40e83dd3bb2 ChangeLog --- a/ChangeLog Wed Jul 20 00:59:54 2011 +0100 +++ b/ChangeLog Wed Jul 20 13:58:04 2011 +0100 @@ -1,3 +1,23 @@ +2011-07-20 Andrew John Hughes + + * NEWS: List security fix. + +2011-07-14 Omair Majid + + * 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-28 Andrew John Hughes * Makefile.am: Add new patch. diff -r c5121c10ed2f -r d40e83dd3bb2 NEWS --- a/NEWS Wed Jul 20 00:59:54 2011 +0100 +++ b/NEWS Wed Jul 20 13:58:04 2011 +0100 @@ -10,6 +10,8 @@ New in release 1.8.9 (20XX-XX-XX): +* Security fixes + - RH718164, CVE-2011-2513: Home directory path disclosure to untrusted apps * Bug fixes - PR744: icedtea6-1.10.2 : patching error - PR748: Icedtea6 fails to build with Linux 3.0. diff -r c5121c10ed2f -r d40e83dd3bb2 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 Wed Jul 20 13:58:04 2011 +0100 @@ -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 c5121c10ed2f -r d40e83dd3bb2 netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java --- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Wed Jul 20 00:59:54 2011 +0100 +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Wed Jul 20 13:58:04 2011 +0100 @@ -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(); /** @@ -457,7 +457,7 @@ } } - jarLocationSecurityMap.put(location, jarSecurity); + jarLocationSecurityMap.put(jarDesc.getLocation(), jarSecurity); } catch (MalformedURLException mfe) { System.err.println(mfe.getMessage()); } @@ -675,8 +675,11 @@ 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(); if (file instanceof PluginBridge) { @@ -696,7 +699,7 @@ codebase.getHost()); } - jarLocationSecurityMap.put(fileURL, jarSecurity); + jarLocationSecurityMap.put(fakeRemote, jarSecurity); } catch (MalformedURLException mfue) { if (JNLPRuntime.isDebug()) @@ -711,15 +714,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()) @@ -985,8 +991,10 @@ throw new ClassNotFoundException(name); } - if (u != null) - addURL(u); + if (u != null) { + addURL(remoteURL); + CachedJarFileCallback.getInstance().addMapping(remoteURL, u); + } } @@ -1173,7 +1181,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 c5121c10ed2f -r d40e83dd3bb2 netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java --- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java Wed Jul 20 00:59:54 2011 +0100 +++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java Wed Jul 20 13:58:04 2011 +0100 @@ -25,6 +25,8 @@ import java.security.*; import javax.jnlp.*; +import sun.net.www.protocol.jar.URLJarFile; + import net.sourceforge.jnlp.*; import net.sourceforge.jnlp.cache.*; import net.sourceforge.jnlp.services.*; @@ -201,6 +203,8 @@ System.setSecurityManager(security); } + URLJarFile.setCallBack(CachedJarFileCallback.getInstance()); + initialized = true; } diff -r c5121c10ed2f -r d40e83dd3bb2 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 Wed Jul 20 13:58:04 2011 +0100 @@ -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; + } +}