Update JarURLConnection to only require file read permission

Previously, JarURLConnection didn't override getPermission(). This
meant that it required all permissions. This was at odds with the
Oracle JVM's concrete sun.net.www.protocol.jar.JarURLConnection which
overrides getPermission to return a FilePermission with the read
action for the path of the underlying jar.

This commit updates our JarURLConnection to align its behaviour with
sun.net.www.protocol.jar.JarURLConnection.

Closes gh-5411
This commit is contained in:
Andy Wilkinson 2016-06-01 15:33:36 +01:00
parent 28bd6d60c8
commit 3772d9f937
2 changed files with 27 additions and 1 deletions

View File

@ -18,12 +18,14 @@ package org.springframework.boot.loader.jar;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FilePermission;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.security.Permission;
import java.util.jar.Manifest;
import org.springframework.boot.loader.util.AsciiBytes;
@ -32,6 +34,7 @@ import org.springframework.boot.loader.util.AsciiBytes;
* {@link java.net.JarURLConnection} used to support {@link JarFile#getUrl()}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
class JarURLConnection extends java.net.JarURLConnection {
@ -61,10 +64,14 @@ class JarURLConnection extends java.net.JarURLConnection {
private static final String FILE_COLON_DOUBLE_SLASH = "file://";
private static final String READ_ACTION = "read";
private static ThreadLocal<Boolean> useFastExceptions = new ThreadLocal<Boolean>();
private final JarFile jarFile;
private final Permission permission;
private JarEntryData jarEntryData;
private URL jarFileUrl;
@ -84,6 +91,8 @@ class JarURLConnection extends java.net.JarURLConnection {
}
this.jarFile = jarFile;
this.jarEntryName = getJarEntryName(spec);
this.permission = new FilePermission(jarFile.getRootJarFile().getFile().getPath(),
READ_ACTION);
}
private String getNormalizedFile(URL url) {
@ -214,6 +223,11 @@ class JarURLConnection extends java.net.JarURLConnection {
return this.jarEntryName.getContentType();
}
@Override
public Permission getPermission() throws IOException {
return this.permission;
}
static void setUseFastExceptions(boolean useFastExceptions) {
JarURLConnection.useFastExceptions.set(useFastExceptions);
}

View File

@ -20,6 +20,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilePermission;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@ -45,6 +46,7 @@ import org.springframework.util.StreamUtils;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.sameInstance;
@ -58,6 +60,7 @@ import static org.mockito.Mockito.verify;
*
* @author Phillip Webb
* @author Martin Lau
* @author Andy Wilkinson
*/
public class JarFileTests {
@ -216,6 +219,11 @@ public class JarFileTests {
assertThat(jarURLConnection.getContentLength(), equalTo(1));
assertThat(jarURLConnection.getContent(), instanceOf(InputStream.class));
assertThat(jarURLConnection.getContentType(), equalTo("content/unknown"));
assertThat(jarURLConnection.getPermission(),
is(instanceOf(FilePermission.class)));
FilePermission permission = (FilePermission) jarURLConnection.getPermission();
assertThat(permission.getActions(), equalTo("read"));
assertThat(permission.getName(), equalTo(this.rootJarFile.getPath()));
}
@Test
@ -269,6 +277,10 @@ public class JarFileTests {
assertThat(conn.getJarFile(), sameInstance(nestedJarFile));
assertThat(conn.getJarFileURL().toString(),
equalTo("jar:" + this.rootJarFile.toURI() + "!/nested.jar"));
assertThat(conn.getPermission(), is(instanceOf(FilePermission.class)));
FilePermission permission = (FilePermission) conn.getPermission();
assertThat(permission.getActions(), equalTo("read"));
assertThat(permission.getName(), equalTo(this.rootJarFile.getPath()));
}
@Test
@ -292,7 +304,7 @@ public class JarFileTests {
}
@Test
public void getNestJarEntryUrl() throws Exception {
public void getNestedJarEntryUrl() throws Exception {
JarFile nestedJarFile = this.jarFile
.getNestedJarFile(this.jarFile.getEntry("nested.jar"));
URL url = nestedJarFile.getJarEntry("3.dat").getUrl();