Skip to content

Commits on Source 3

2019-08-02 George Adams <george@jclarity.com>
Release changes
* configure.ac: (AC_INIT) bumped to 1.8.3
2019-06-26 Jiri Vanek <jvanek@redhat.com>
All files, except signatures files, are now checked for signatures - CVE-2019-10181
* netx/net/sourceforge/jnlp/tools/JarCertVerifier.java: (isMetaInfFile) fixed bug, when anything in META-INF was not
checked for signature. Now only signature files are skipped
* tests/netx/unit/net/sourceforge/jnlp/tools/JarCertVerifierTest.java: added tests for check if file should be skipped from
signature check
2019-06-26 Jiri Vanek <jvanek@redhat.com>
Nested jar, if by relative path point up, is stored as hashed - CVE-2019-10185
* tests/netx/unit/net/sourceforge/jnlp/runtime/jar03_dotdotN1.jar: crafted jar with hacked zip entries to be named like ".."
* tests/netx/unit/net/sourceforge/jnlp/runtime/jar_03_dotdot_jarN1.jnlp: jnlp to call jar03_dotdotN1.jar
* netx/net/sourceforge/jnlp/cache/CacheUtil.jsava: (hex) made public to be reused in JNLPClassLoader
* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: if nested jar contains .. in path, is extracted as hashed
2019-06-26 Jiri Vanek <jvanek@redhat.com>
Fixed bug when relative path (..) could leak up (even out of cache) - CVE-2019-10182
* netx/net/sourceforge/jnlp/cache/CacheUtil.java: if path or query contains .. is saved to cache via its hash
* netx/net/sourceforge/jnlp/util/FileUtils.java: added warning about different behavior on win/linux
* tests/netx/unit/net/sourceforge/jnlp/cache/CacheUtilTest.java: added tests for hashing
* tests/netx/unit/net/sourceforge/jnlp/runtime/JNLPClassLoaderTest.java: added test for .. in path. Added test
that verifies encoded .. (%2E%2E) do not leak from cahce
* tests/netx/unit/net/sourceforge/jnlp/runtime/up.jnlp: example jnlp with .. full url
2019-07-15 Andrew Leonard <andrew_m_leonard@uk.ibm.com>
 
Release changes
......
......@@ -8,6 +8,12 @@ GX - http://bugs.gentoo.org/show_bug.cgi?id=X
CVE-XXXX-YYYY: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=XXXX-YYYY
New in release 1.8.3 (2019-08-02):
* Security updates
- CVE-2019-10182 - Fixed bug when relative path (..) could leak up (even out of cache)
- CVE-2019-10185 - Nested jar, if by relative path point up, is stored as hashed
- CVE-2019-10181 - All files, except signatures files, are now checked for signatures
New in release 1.8.2 (2019-07-15):
* fix(JNLPFile): location/sourceLocation confusion
* Fix hang in windows when javaws is launched outside the console
......
AC_INIT([icedtea-web],[1.8.2],[distro-pkg-dev@openjdk.java.net], [icedtea-web], [http://icedtea.classpath.org/wiki/IcedTea-Web])
AC_INIT([icedtea-web],[1.8.3],[distro-pkg-dev@openjdk.java.net], [icedtea-web], [http://icedtea.classpath.org/wiki/IcedTea-Web])
AM_INIT_AUTOMAKE([1.9 tar-pax foreign])
AC_CONFIG_FILES([Makefile netx.manifest])
AM_MAINTAINER_MODE([enable])
......
icedtea-web (1.8.3-1) unstable; urgency=medium
* Team upload.
* New upstream release (Closes: #934319)
- Fixes CVE-2019-10181: Unsigned code injection in a signed JAR file
- Fixes CVE-2019-10182: Path traversal while processing <jar/> elements
of JNLP files results in arbitrary file overwrite
- Fixes CVE-2019-10185: Directory traversal in the nested jar
auto-extraction leading to arbitrary file overwrite
-- Emmanuel Bourg <ebourg@apache.org> Fri, 09 Aug 2019 18:57:41 +0200
icedtea-web (1.8.2-2) unstable; urgency=medium
* Team upload.
......
......@@ -696,46 +696,72 @@ public class CacheUtil {
path.append(location.getPort());
path.append(File.separatorChar);
}
path.append(location.getPath().replace('/', File.separatorChar));
String locationPath = location.getPath().replace('/', File.separatorChar);
String query = "";
if (location.getQuery() != null) {
query = location.getQuery();
}
if (locationPath.contains("..") || query.contains("..")){
try {
/**
* if path contains .. then it can harm lcoal system
* So without mercy, hash it
*/
String hexed = hex(new File(locationPath).getName(), locationPath);
return new File(path.toString(), hexed.toString());
} catch (NoSuchAlgorithmException ex) {
// should not occur, cite from javadoc:
// every java implementation should support
// MD5 SHA-1 SHA-256
throw new RuntimeException(ex);
}
} else {
path.append(locationPath);
if (location.getQuery() != null && !location.getQuery().trim().isEmpty()) {
path.append(".").append(location.getQuery());
}
File candidate = new File(FileUtils.sanitizePath(path.toString()));
try {
if (candidate.getName().length() > 255) {
/**
* When filename is longer then 255 chars, then then various
* filesytems have issues to save it. By saving the file by its
* summ, we are trying to prevent collision of two files differs in
* filesystems have issues to save it. By saving the file by its
* sum, we are trying to prevent collision of two files differs in
* suffixes (general suffix of name, not only 'filetype suffix')
* only. It is also preventing bug when truncate (files with 1000
* chars hash in query) cuts to much.
*/
try {
String hexed = hex(candidate.getName(), candidate.getName());
candidate = new File(candidate.getParentFile(), hexed.toString());
}
} catch (NoSuchAlgorithmException ex) {
// should not occur, cite from javadoc:
// every java implementation should support
// MD5 SHA-1 SHA-256
throw new RuntimeException(ex);
}
return candidate;
}
}
public static String hex(String origName, String candidate) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] sum = md.digest(candidate.getName().getBytes(StandardCharsets.UTF_8));
byte[] sum = md.digest(candidate.getBytes(StandardCharsets.UTF_8));
//convert the byte to hex format method 2
StringBuilder hexString = new StringBuilder();
for (int i = 0; i < sum.length; i++) {
hexString.append(Integer.toHexString(0xFF & sum[i]));
}
String extension = "";
int i = candidate.getName().lastIndexOf('.');
int i = origName.lastIndexOf('.');
if (i > 0) {
extension = candidate.getName().substring(i);//contains dot
extension = origName.substring(i);//contains dot
}
if (extension.length() < 10 && extension.length() > 1) {
hexString.append(extension);
}
candidate = new File(candidate.getParentFile(), hexString.toString());
} catch (NoSuchAlgorithmException ex) {
// should not occure, cite from javadoc:
// every java iomplementation should support
// MD5 SHA-1 SHA-256
throw new RuntimeException(ex);
}
}
return candidate;
return hexString.toString();
}
/**
......
......@@ -1340,7 +1340,11 @@ public class JNLPClassLoader extends URLClassLoader {
// (inline loading with "jar:..!/..." path will not work
// with standard classloader methods)
String extractedJarLocation = localFile + ".nested/" + je.getName();
String name = je.getName();
if (name.contains("..")){
name=CacheUtil.hex(name, name);
}
String extractedJarLocation = localFile + ".nested/" + name;
File parentDir = new File(extractedJarLocation).getParentFile();
if (!parentDir.isDirectory() && !parentDir.mkdirs()) {
throw new RuntimeException(R("RNestedJarExtration"));
......
......@@ -41,6 +41,7 @@ import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.regex.Pattern;
import net.sourceforge.jnlp.JARDesc;
import net.sourceforge.jnlp.JNLPFile;
......@@ -67,6 +68,7 @@ import sun.security.x509.NetscapeCertTypeExtension;
public class JarCertVerifier implements CertVerifier {
private static final String META_INF = "META-INF/";
private static final Pattern SIG = Pattern.compile(".*" + META_INF + "SIG-.*");
// prefix for new signature-related files in META-INF directory
private static final String SIG_PREFIX = META_INF + "SIG-";
......@@ -500,12 +502,20 @@ public class JarCertVerifier implements CertVerifier {
/**
* Returns whether a file is in META-INF, and thus does not require signing.
*
* <p>
* Signature-related files under META-INF include: . META-INF/MANIFEST.MF . META-INF/SIG-* . META-INF/*.SF . META-INF/*.DSA . META-INF/*.RSA
*/
static boolean isMetaInfFile(String name) {
String ucName = name.toUpperCase();
return ucName.startsWith(META_INF);
if (name.endsWith("class")) {
return false;
}
return name.startsWith(META_INF) && (
name.endsWith(".MF") ||
name.endsWith(".SF") ||
name.endsWith(".DSA") ||
name.endsWith(".RSA") ||
SIG.matcher(name).matches()
);
}
/**
......
......@@ -183,6 +183,13 @@ public final class FileUtils {
*/
public static void createParentDir(File f, String eMsg) throws IOException {
File parent = f.getParentFile();
// warning, linux and windows behave differently. Below snippet will pass on win(security hole), fail on linux
// warning mkdir is canonicaling, but exists/isDirectory is not. So where mkdirs return true, and really creates dir, isDirectory can still return false
// can be seen on this example
// mkdirs /a/b/../c
// where b do not exists will lead creation of /a/c
// but exists on /a/b/../c is false on linux even afterwards
// without hexing of .. paths,
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException(R("RCantCreateDir",
eMsg == null ? parent : eMsg));
......
......@@ -99,11 +99,12 @@ public class WindowsDesktopEntry implements GenericDesktopEntry {
sl.setIconLocation(iconLocation);
ul.setIconLocation(iconLocation);
}
sl.saveTo(path + "/" + file.getInformation().getTitle()+ ".lnk");
ul.saveTo(path + "/Uninstall " + file.getInformation().getTitle() + ".lnk");
final String link = FileUtils.sanitizeFileName(file.getInformation().getTitle() + ".lnk", '-');
sl.saveTo(path + "/" + link);
ul.saveTo(path + "/Uninstall " + link);
// write shortcuts to list
manageShortcutList(ManageMode.A, path + "/" + file.getInformation().getTitle() + ".lnk");
manageShortcutList(ManageMode.A, path + "/Uninstall " + file.getInformation().getTitle() + ".lnk");
manageShortcutList(ManageMode.A, path + "/" + link);
manageShortcutList(ManageMode.A, path + "/Uninstall " + link);
}
private void manageShortcutList(ManageMode mode, String path) throws IOException {
......
......@@ -89,6 +89,68 @@ public class CacheUtilTest {
Assert.assertEquals(expected, CacheUtil.urlToPath(u, "/tmp"));
}
@Test
public void tesPathUpNoGoBasic() throws Exception {
final URL u = new URL("https://example.com/applet/../my.jar");
final File expected = new File("/tmp/https/example.com/abca4723622ed60db3dea12cbe2402622a74f7a49b73e23b55988e4eee5ded.jar");
File r = CacheUtil.urlToPath(u, "/tmp/");
Assert.assertEquals(expected, r);
}
@Test
public void tesPathUpNoGoBasicLong() throws Exception {
final URL u = new URL("https://example.com/applet/../my.jar.q_SlNFU1NJT05JRD02OUY1ODVCNkJBOTM1NThCQjdBMTA5RkQyNDZEQjEwRi5wcm9kX3RwdG9tY2F0MjE1X2p2bTsgRW50cnVzdFRydWVQYXNzUmVkaXJlY3RVcmw9Imh0dHBzOi8vZWZzLnVzcHRvLmdvdi9FRlNXZWJVSVJlZ2lzdGVyZWQvRUZTV2ViUmVnaXN0ZXJlZCI7IFRDUFJPRFBQQUlSc2Vzc2lvbj02MjIxMjk0MTguMjA0ODAuMDAwMA\"");
final File expected = new File("/tmp/https/example.com/ec97413e3f6eee8215ecc8375478cc1ae5f44f18241b9375361d5dfcd7b0ec");
File r = CacheUtil.urlToPath(u, "/tmp/");
Assert.assertEquals(expected, r);
}
@Test
public void tesPathUpNoGoBasic2() throws Exception {
final URL u = new URL("https://example.com/../my.jar");
final File expected = new File("/tmp/https/example.com/eb1a56bed34523dbe7ad84d893ebc31a8bbbba9ce3f370e42741b6a5f067c140.jar");
File r = CacheUtil.urlToPath(u, "/tmp/");
Assert.assertEquals(expected, r);
}
@Test
public void tesPathUpNoGoBasicEvil() throws Exception {
final URL u = new URL("https://example.com/../../my.jar");
final File expected = new File("/tmp/https/example.com/db464f11d68af73e37eefaef674517b6be23f0e4a5738aaee774ecf5b58f1bfc.jar");
File r = CacheUtil.urlToPath(u, "/tmp/");
Assert.assertEquals(expected, r);
}
@Test
public void tesPathUpNoGoBasicEvil2() throws Exception {
final URL u = new URL("https://example.com:99/../../../my.jar");
final File expected = new File("/tmp/https/example.com/99/95401524c345e0d554d4d77330e86c98a77b9bb58a0f93094204df446b356.jar");
File r = CacheUtil.urlToPath(u, "/tmp/");
Assert.assertEquals(expected, r);
}
@Test
public void tesPathUpNoGoBasicEvilest() throws Exception {
final URL u = new URL("https://example2.com/something/../../../../../../../../../../../my.jar");
final File expected = new File("/tmp/https/example2.com/a8df64388f5b84d5f635e4d6dea5f4d2f692ae5381f8ec6736825ff8d6ff2c0.jar");
File r = CacheUtil.urlToPath(u, "/tmp/");
Assert.assertEquals(expected, r);
}
@Test
public void testQueryGotHAshedToo() throws Exception {
final URL u = new URL("https://example2.com/something/my.jar?../../harm");
final File expected = new File("/tmp/https/example2.com/2844b3c690ea355159ed61de6e727f2e9169ab55bf58b8fa3f4b64f6a25bd7.jar");
File r = CacheUtil.urlToPath(u, "/tmp/");
Assert.assertEquals(expected, r);
}
@Test
public void testNameGotHashedToo() throws Exception {
final URL u = new URL("https://example2.com/something/..my.jar");
final File expected = new File("/tmp/https/example2.com/c0c13e25fbe26876938eecd15227ab6299f9a4b8c11746e5451fb88cb775cb0.jar");
File r = CacheUtil.urlToPath(u, "/tmp/");
Assert.assertEquals(expected, r);
}
@Test
public void testUrlToPathWithQuery() throws Exception {
......
......@@ -43,6 +43,10 @@ import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import net.sourceforge.jnlp.ResourcesDesc;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
......@@ -55,6 +59,12 @@ import net.sourceforge.jnlp.annotations.Bug;
import net.sourceforge.jnlp.browsertesting.browsers.firefox.FirefoxProfilesOperator;
import net.sourceforge.jnlp.cache.UpdatePolicy;
import net.sourceforge.jnlp.config.DeploymentConfiguration;
import net.sourceforge.jnlp.config.PathsAndFiles;
import net.sourceforge.jnlp.JNLPFile;
import net.sourceforge.jnlp.ServerAccess;
import net.sourceforge.jnlp.ServerLauncher;
import net.sourceforge.jnlp.util.StreamUtils;
import net.sourceforge.jnlp.cache.CacheUtil;
import net.sourceforge.jnlp.mock.DummyJNLPFileWithJar;
import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel;
import net.sourceforge.jnlp.security.appletextendedsecurity.AppletStartupSecuritySettings;
......@@ -65,6 +75,7 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.Ignore;
public class JNLPClassLoaderTest extends NoStdOutErrTest {
......@@ -138,7 +149,8 @@ public class JNLPClassLoaderTest extends NoStdOutErrTest {
File tempDirectory = FileTestUtils.createTempDirectory();
File jarLocation = new File(tempDirectory, "test.jar");
/* Test with main-class in manifest */ {
/* Test with main-class in manifest */
{
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, "DummyClass");
FileTestUtils.createJarWithContents(jarLocation, manifest);
......@@ -156,8 +168,10 @@ public class JNLPClassLoaderTest extends NoStdOutErrTest {
}
@Test
@Ignore
public void getMainClassNameTestEmpty() throws Exception {
/* Test with-out any main-class specified */ {
/* Test with-out any main-class specified */
{
File tempDirectory = FileTestUtils.createTempDirectory();
File jarLocation = new File(tempDirectory, "test.jar");
FileTestUtils.createJarWithContents(jarLocation /* No contents */);
......@@ -363,4 +377,223 @@ public class JNLPClassLoaderTest extends NoStdOutErrTest {
}
}
@Test
public void testRelativePathInUrl() throws Exception {
CacheUtil.clearCache();
int port = ServerAccess.findFreePort();
File dir = FileTestUtils.createTempDirectory();
dir.deleteOnExit();
dir = new File(dir,"base");
dir.mkdir();
File jar = new File(dir,"j1.jar");
File jnlp = new File(dir+"/a/b/up.jnlp");
jnlp.getParentFile().mkdirs();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/up.jnlp");
String jnlpString = StreamUtils.readStreamAsString(is, true, "utf-8");
is.close();
jnlpString = jnlpString.replaceAll("8080", ""+port);
is = ClassLoader.getSystemClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/j1.jar");
StreamUtils.copyStream(is, new FileOutputStream(jar));
Files.write(jnlp.toPath(),jnlpString.getBytes("utf-8"));
ServerLauncher as = ServerAccess.getIndependentInstance(jnlp.getParent(), port);
boolean verifyBackup = JNLPRuntime.isVerifying();
boolean trustBackup= JNLPRuntime.isTrustAll();
boolean securityBAckup= JNLPRuntime.isSecurityEnabled();
boolean verbose= JNLPRuntime.isDebug();
JNLPRuntime.setVerify(false);
JNLPRuntime.setTrustAll(true);
JNLPRuntime.setSecurityEnabled(false);
JNLPRuntime.setDebug(true);
String manifestAttsBackup = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK);
JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, "NONE");
try {
final JNLPFile jnlpFile1 = new JNLPFile(new URL("http://localhost:" + port + "/up.jnlp"));
final JNLPClassLoader classLoader1 = JNLPClassLoader.getInstance(jnlpFile1, UpdatePolicy.ALWAYS, false);
InputStream is1 = classLoader1.getResourceAsStream("Hello1.class");
is1.close();
is1 = classLoader1.getResourceAsStream("META-INF/MANIFEST.MF");
is1.close();
Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/0/http/localhost/"+port+"/up.jnlp").exists());
Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/1/http/localhost/"+port+"/f812acb32c857fd916c842e2bf4fb32b9c3837ef63922b167a7e163305058b7.jar").exists());
} finally {
JNLPRuntime.setVerify(verifyBackup);
JNLPRuntime.setTrustAll(trustBackup);
JNLPRuntime.setSecurityEnabled(securityBAckup);
JNLPRuntime.setDebug(verbose);
JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, manifestAttsBackup);
as.stop();
}
}
@Test
public void testRelativePathInNestedJars() throws Exception {
CacheUtil.clearCache();
int port = ServerAccess.findFreePort();
File dir = FileTestUtils.createTempDirectory();
dir.deleteOnExit();
File jar = new File(dir,"jar03_dotdotN1.jar");
File jnlp = new File(dir,"jar_03_dotdot_jarN1.jnlp");
InputStream is1 = ClassLoader.getSystemClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/jar_03_dotdot_jarN1.jnlp");
InputStream is2 = ClassLoader.getSystemClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/jar03_dotdotN1.jar");
OutputStream fos1 = new FileOutputStream(jnlp);
OutputStream fos2 = new FileOutputStream(jar);
StreamUtils.copyStream(is1, fos1);
StreamUtils.copyStream(is2, fos2);
fos1.flush();;
fos2.flush();
fos1.close();
fos2.close();
ServerLauncher as = ServerAccess.getIndependentInstance(dir.getAbsolutePath(), port);
boolean verifyBackup = JNLPRuntime.isVerifying();
boolean trustBackup= JNLPRuntime.isTrustAll();
boolean securityBAckup= JNLPRuntime.isSecurityEnabled();
boolean verbose= JNLPRuntime.isDebug();
JNLPRuntime.setVerify(false);
JNLPRuntime.setTrustAll(true);
JNLPRuntime.setSecurityEnabled(false);
JNLPRuntime.setDebug(true);
//fix of "All files, except signaturre files, are now checked for signatures" make this actually correctly failing ahead of time
String ignoreBackup = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES);
JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES, "true");
String manifestAttsBackup = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK);
JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, "NONE");
try {
//it is invalid jar, so we have to disable checks first
final JNLPFile jnlpFile = new JNLPFile(new URL("http://localhost:" + port + "/jar_03_dotdot_jarN1.jnlp"));
final JNLPClassLoader classLoader = JNLPClassLoader.getInstance(jnlpFile, UpdatePolicy.ALWAYS, false);
//ThreadGroup group = Thread.currentThread().getThreadGroup();
//ApplicationInstance app = new ApplicationInstance(jnlpFile, group, classLoader);
//classLoader.setApplication(app);
//app.initialize();
//this test is actually not testing mutch. The app must be accessing the nested jar in plugin-like way
InputStream is = classLoader.getResourceAsStream("application/abev/nyomtatvanyinfo/1965.teminfo.enyk");
is.close();
is = classLoader.getResourceAsStream("META-INF/MANIFEST.MF");
is.close();
is = classLoader.getResourceAsStream("META-INF/j1.jar");
is.close();
is = classLoader.getResourceAsStream("META-INF/../../jar01_to_be_injected.jar");
//the .. is not recognized correctly
//is.close();
//Class c = classLoader.getClass().forName("Hello1");
// in j1.jar
is = classLoader.getResourceAsStream("Hello1.class");
//is.close(); nested jar is not on defualt CP
//in jar01
//c = classLoader.getClass().forName("com.devdaily.FileUtilities");
is = classLoader.getResourceAsStream("com/devdaily/FileUtilities.class");
// is.close(); nested jar is not on defualt CP
Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/0/http/localhost/"+port+"/jar_03_dotdot_jarN1.jnlp").exists());
Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/1/http/localhost/"+port+"/jar03_dotdotN1.jar").exists());
Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/1/http/localhost/"+port+"/jar03_dotdotN1.jar.nested/99a90686bfbe84e3f9dbeed8127bba85672ed73688d3c69191aa1ee70916a.jar").exists());
Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/1/http/localhost/"+port+"/jar03_dotdotN1.jar.nested/META-INF/j1.jar").exists());
} finally {
JNLPRuntime.setVerify(verifyBackup);
JNLPRuntime.setTrustAll(trustBackup);
JNLPRuntime.setSecurityEnabled(securityBAckup);
JNLPRuntime.setDebug(verbose);
JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES, ignoreBackup);
JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, manifestAttsBackup);
as.stop();
}
}
@Test(expected = Exception.class)
public void testDifferentSignatureInManifestMf() throws Exception {
CacheUtil.clearCache();
int port = ServerAccess.findFreePort();
File dir = FileTestUtils.createTempDirectory();
dir.deleteOnExit();
File jar = new File(dir,"jar03_dotdotN1.jar");
File jnlp = new File(dir,"jar_03_dotdot_jarN1.jnlp");
InputStream is1 = ClassLoader.getSystemClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/jar_03_dotdot_jarN1.jnlp");
InputStream is2 = ClassLoader.getSystemClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/jar03_dotdotN1.jar");
OutputStream fos1 = new FileOutputStream(jnlp);
OutputStream fos2 = new FileOutputStream(jar);
StreamUtils.copyStream(is1, fos1);
StreamUtils.copyStream(is2, fos2);
fos1.flush();;
fos2.flush();
fos1.close();
fos2.close();
ServerLauncher as = ServerAccess.getIndependentInstance(dir.getAbsolutePath(), port);
boolean verifyBackup = JNLPRuntime.isVerifying();
boolean trustBackup= JNLPRuntime.isTrustAll();
boolean securityBAckup= JNLPRuntime.isSecurityEnabled();
boolean verbose= JNLPRuntime.isDebug();
JNLPRuntime.setVerify(false);
JNLPRuntime.setTrustAll(true);
JNLPRuntime.setSecurityEnabled(false);
JNLPRuntime.setDebug(true);
String ignoreBackup = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES);
JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES, "false");
try {
//it is invalid jar, so we have to disable checks first
final JNLPFile jnlpFile = new JNLPFile(new URL("http://localhost:" + port + "/jar_03_dotdot_jarN1.jnlp"));
final JNLPClassLoader classLoader = JNLPClassLoader.getInstance(jnlpFile, UpdatePolicy.ALWAYS, false);
} finally {
JNLPRuntime.setVerify(verifyBackup);
JNLPRuntime.setTrustAll(trustBackup);
JNLPRuntime.setSecurityEnabled(securityBAckup);
JNLPRuntime.setDebug(verbose);
JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES, ignoreBackup);
as.stop();
}
}
@Test
public void testEncodedPathIsNotDecodedForCache() throws Exception {
CacheUtil.clearCache();
int port = ServerAccess.findFreePort();
File dir = FileTestUtils.createTempDirectory();
dir.deleteOnExit();
dir = new File(dir,"base");
dir.mkdir();
File jar = new File(dir,"j1.jar");
File jnlp = new File(dir+"/a/b/upEncoded.jnlp");
jnlp.getParentFile().mkdirs();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/upEncoded.jnlp");
String jnlpString = StreamUtils.readStreamAsString(is, true, "utf-8");
is.close();
jnlpString = jnlpString.replaceAll("8080", ""+port);
is = ClassLoader.getSystemClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/j1.jar");
StreamUtils.copyStream(is, new FileOutputStream(jar));
Files.write(jnlp.toPath(),jnlpString.getBytes("utf-8"));
ServerLauncher as = ServerAccess.getIndependentInstance(jnlp.getParent(), port);
boolean verifyBackup = JNLPRuntime.isVerifying();
boolean trustBackup= JNLPRuntime.isTrustAll();
boolean securityBAckup= JNLPRuntime.isSecurityEnabled();
boolean verbose= JNLPRuntime.isDebug();
JNLPRuntime.setVerify(false);
JNLPRuntime.setTrustAll(true);
JNLPRuntime.setSecurityEnabled(false);
JNLPRuntime.setDebug(true);
String manifestAttsBackup = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK); JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, "NONE");
try {
final JNLPFile jnlpFile1 = new JNLPFile(new URL("http://localhost:" + port + "/upEncoded.jnlp"));
final JNLPClassLoader classLoader1 = JNLPClassLoader.getInstance(jnlpFile1, UpdatePolicy.ALWAYS, false);
InputStream is1 = classLoader1.getResourceAsStream("Hello1.class");
is1.close();
is1 = classLoader1.getResourceAsStream("META-INF/MANIFEST.MF");
is1.close();
Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/0/http/localhost/"+port+"/upEncoded.jnlp").exists());
//be aware; if decoding ever come in play here, thios will leak out of cache folder. Thus harm user system. See fix for " Fixed bug when relative path (..) could leak up (even out of cache)"
Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/1/http/localhost/"+port+"/%2E%2E/%2E%2E/%2E%2E/base").exists());
} finally {
JNLPRuntime.setVerify(verifyBackup);
JNLPRuntime.setTrustAll(trustBackup);
JNLPRuntime.setSecurityEnabled(securityBAckup);
JNLPRuntime.setDebug(verbose);
JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, manifestAttsBackup);
as.stop();
}
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jnlp spec="6.0+" >
<information><title>1965</title><vendor>Nemzeti Ado- es Vamhivatal</vendor><offline-allowed/></information>
<security><all-permissions/></security>
<resources>
<j2se href="http://java.sun.com/products/autodl/j2se" version="1.8+" />
<jar href="jar03_dotdotN1.jar" version="2.0"/>
</resources>
<application-desc main-class="http://localhost/jar01.jar!META-INF/jar01_to_be_injected.jar!METAxINF.Test" />
</jnlp>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jnlp spec="6.0+" codebase=".">
<information><title>1965</title><vendor>Nemzeti Ado- es Vamhivatal</vendor><offline-allowed/></information>
<resources>
<j2se href="http://java.sun.com/products/autodl/j2se" version="1.8+" />
<!-- absolute url is a must -->
<jar href="http://localhost:8080/../../../base/j1.jar" version="2.0"/>
</resources>
<application-desc main-class="Hello1" />
</jnlp>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jnlp spec="6.0+" codebase=".">
<information><title>1965</title><vendor>Nemzeti Ado- es Vamhivatal</vendor><offline-allowed/></information>
<resources>
<j2se href="http://java.sun.com/products/autodl/j2se" version="1.8+" />
<!-- absolute url is a must -->
<jar href="http://localhost:8080/%2E%2E/%2E%2E/%2E%2E/base/j1.jar" version="2.0"/>
</resources>
<application-desc main-class="Hello1" />
</jnlp>
......@@ -59,9 +59,22 @@ public class JarCertVerifierTest {
@Test
public void testIsMetaInfFile() {
final String METAINF = "META-INF";
assertTrue(JarCertVerifier.isMetaInfFile(METAINF + "/file.MF"));
assertTrue(JarCertVerifier.isMetaInfFile(METAINF + "/file.SF"));
assertTrue(JarCertVerifier.isMetaInfFile(METAINF + "/file.DSA"));
assertTrue(JarCertVerifier.isMetaInfFile(METAINF + "/file.RSA"));
assertTrue(JarCertVerifier.isMetaInfFile(METAINF + "/SIG-blah.blah"));
assertFalse(JarCertVerifier.isMetaInfFile(METAINF + "/file.MF.class"));
assertFalse(JarCertVerifier.isMetaInfFile(METAINF + "/file.SF.class"));
assertFalse(JarCertVerifier.isMetaInfFile(METAINF + "/file.DSA.class"));
assertFalse(JarCertVerifier.isMetaInfFile(METAINF + "/file.RSA.class"));
assertFalse(JarCertVerifier.isMetaInfFile(METAINF + "/SIG-blah.blah.class"));
assertFalse(JarCertVerifier.isMetaInfFile("some_dir/" + METAINF + "/filename"));
assertFalse(JarCertVerifier.isMetaInfFile(METAINF + "filename"));
assertTrue(JarCertVerifier.isMetaInfFile(METAINF + "/filename"));
assertFalse(JarCertVerifier.isMetaInfFile(METAINF + "/filename"));
assertFalse(JarCertVerifier.isMetaInfFile(METAINF + "/filename"));
}
class JarCertVerifierEntry extends JarEntry {
......