Mercurial > hg > release > icedtea-web-1.3
changeset 510:19f5282f53e8
Fixed gifar vulnereability with automated testcase
line wrap: on
line diff
--- a/ChangeLog Wed Apr 10 15:37:00 2013 +0200 +++ b/ChangeLog Wed Apr 10 17:49:20 2013 +0200 @@ -1,3 +1,43 @@ +2013-04-10 Jiri Vanek <jvanek@redhat.com> + + Fixed gifar vulnereability with automated testcase + * netx/net/sourceforge/jnlp/util/JarFile.java: IcedTea-Web replacement for + java.util.jar.JarFile.java with capability to verify if the jar starts as jar + and not as something else (eg gif) + * netx/net/sourceforge/jnlp/Launcher.java: migrated to new JarFile + * netx/net/sourceforge/jnlp/resources/Messages.properties: added + BXignoreheaders key with description to new -Xignoreheaders switch + * netx/net/sourceforge/jnlp/runtime/Boot.java: added switch Xignoreheaders + to allow to disable the header verification. + * netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java: + migrated to new JarFile + * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: improved + reporting of new JarFile exceptions + * netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java: new field + ignoreHeaders, informing about new JarFile whether to verify or not verify + headers. By default verifying, so have value of false. + * netx/net/sourceforge/jnlp/tools/JarCertVerifier.java: migrated to new JarFile + * netx/net/sourceforge/jnlp/util/InvalidJarHeaderException.java: new + not-checked exception to signify that jar is corrupted on headers level. + * tests/reproducers/custom/GifarCreator/srcs/Makefile: makefile to + join gif and jar to create gifar + * tests/reproducers/signed/GifarBase/resources/gifarView_hacked.html: + html with hacked gifar + * tests/reproducers/signed/GifarBase/resources/gifarView_ok.html: + html with valid gifs and jars + * tests/reproducers/signed/GifarBase/resources/gifar_applet.jnlp: + jnlp applet constructed from hacked gifar + * tests/reproducers/signed/GifarBase/resources/gifar_application.jnlp: + jnlp application constructed from hacked gifar + * tests/reproducers/signed/GifarBase/srcs/GifarMain.java: + Main method of reproducer + * tests/reproducers/signed/GifarBase/testcases/GifarTestcases.java: + Testing methods + * tests/reproducers/signed/GifarBase/resources/happyNonAnimated.gif: + binary file, image, gif, used to create hacked gifars + + + 2013-04-10 Jiri Vanek <jvanek@redhat.com> Fixed news
--- a/netx/net/sourceforge/jnlp/Launcher.java Wed Apr 10 15:37:00 2013 +0200 +++ b/netx/net/sourceforge/jnlp/Launcher.java Wed Apr 10 17:49:20 2013 +0200 @@ -29,7 +29,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.jar.JarFile; +import net.sourceforge.jnlp.util.JarFile; import net.sourceforge.jnlp.cache.CacheUtil; import net.sourceforge.jnlp.cache.UpdatePolicy;
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties Wed Apr 10 15:37:00 2013 +0200 +++ b/netx/net/sourceforge/jnlp/resources/Messages.properties Wed Apr 10 17:49:20 2013 +0200 @@ -94,7 +94,7 @@ LNotVerified=Jars not verified. LCancelOnUserRequest=Canceled on user request. LFatalVerification=A fatal error occurred while trying to verify jars. -LFatalVerificationInfo= +LFatalVerificationInfo=Description LNotVerifiedDialog=Not all jars could be verified. LAskToContinue=Would you still like to continue running this application? @@ -185,6 +185,7 @@ BOViewer = Shows the trusted certificate viewer. BXnofork = Do not create another JVM. BXclearcache= Clean the JNLP application cache. +BXignoreheaders= Skip jar header verification. BOHelp = Print this message and exit. # Cache
--- a/netx/net/sourceforge/jnlp/runtime/Boot.java Wed Apr 10 15:37:00 2013 +0200 +++ b/netx/net/sourceforge/jnlp/runtime/Boot.java Wed Apr 10 17:49:20 2013 +0200 @@ -102,6 +102,7 @@ + " -strict " + R("BOStrict") + "\n" + " -Xnofork " + R("BXnofork") + "\n" + " -Xclearcache " + R("BXclearcache") + "\n" + + " -Xignoreheaders " + R("BXignoreheaders") + "\n" + " -help " + R("BOHelp") + "\n"; private static final String doubleArgs = "-basedir -jnlp -arg -param -property -update"; @@ -159,6 +160,9 @@ if (null != getOption("-Xtrustall")) { JNLPRuntime.setTrustAll(true); } + if (null != getOption("-Xignoreheaders")) { + JNLPRuntime.setIgnoreHeaders(true); + } JNLPRuntime.setInitialArgments(Arrays.asList(argsIn));
--- a/netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java Wed Apr 10 15:37:00 2013 +0200 +++ b/netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java Wed Apr 10 17:49:20 2013 +0200 @@ -49,7 +49,7 @@ import java.security.PrivilegedExceptionAction; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.jar.JarFile; +import net.sourceforge.jnlp.util.JarFile; import net.sourceforge.jnlp.util.UrlUtils; @@ -81,7 +81,7 @@ } @Override - public JarFile retrieve(URL url) throws IOException { + public java.util.jar.JarFile retrieve(URL url) throws IOException { URL localUrl = mapping.get(url); if (localUrl == null) { @@ -122,8 +122,8 @@ /* * This method is a copy of URLJarFile.retrieve() without the callback check. */ - private JarFile cacheJarFile(URL url) throws IOException { - JarFile result = null; + private java.util.jar.JarFile cacheJarFile(URL url) throws IOException { + java.util.jar.JarFile result = null; final int BUF_SIZE = 2048; @@ -132,9 +132,9 @@ try { result = - AccessController.doPrivileged(new PrivilegedExceptionAction<JarFile>() { + AccessController.doPrivileged(new PrivilegedExceptionAction<java.util.jar.JarFile>() { @Override - public JarFile run() throws IOException { + public java.util.jar.JarFile run() throws IOException { OutputStream out = null; File tmpFile = null; try {
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Wed Apr 10 15:37:00 2013 +0200 +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Wed Apr 10 17:49:20 2013 +0200 @@ -56,7 +56,7 @@ import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.jar.JarEntry; -import java.util.jar.JarFile; +import net.sourceforge.jnlp.util.JarFile; import java.util.jar.Manifest; import net.sourceforge.jnlp.AppletDesc; @@ -612,7 +612,7 @@ //to read the cacerts or trusted.certs files. e.printStackTrace(); throw new LaunchException(null, null, R("LSFatal"), - R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo")); + R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo") + ": " +e.getMessage()); } //Case when at least one jar has some signing
--- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java Wed Apr 10 15:37:00 2013 +0200 +++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java Wed Apr 10 17:49:20 2013 +0200 @@ -87,7 +87,7 @@ * @version $Revision: 1.19 $ */ public class JNLPRuntime { - + static { loadResources(); } @@ -142,8 +142,16 @@ /** set to false to indicate another JVM should not be spawned, even if necessary */ private static boolean forksAllowed = true; - /** all security dialogs will be consumed and pretented as beeing verified by user and allowed.*/ + /** all security dialogs will be consumed and pretented as being verified by user and allowed.*/ private static boolean trustAll=false; + /** + * Header is not checked and so eg. gifar exploit is possible + * @see http://en.wikipedia.org/wiki/Gifar for this kind of attack. + * However if jar file is a bit corrupted, then it sometimes can work so + * this switch can disable the header check. + * + */ + private static boolean ignoreHeaders=false; /** contains the arguments passed to the jnlp runtime */ private static List<String> initialArguments; @@ -775,4 +783,14 @@ return trustAll; } + public static boolean isIgnoreHeaders() { + return ignoreHeaders; + } + + public static void setIgnoreHeaders(boolean ignoreHeaders) { + JNLPRuntime.ignoreHeaders = ignoreHeaders; + } + + + }
--- a/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java Wed Apr 10 15:37:00 2013 +0200 +++ b/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java Wed Apr 10 17:49:20 2013 +0200 @@ -27,19 +27,35 @@ import static net.sourceforge.jnlp.runtime.Translator.R; -import java.io.*; -import java.util.*; -import java.util.jar.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.security.CodeSigner; +import java.security.KeyStore; +import java.security.cert.CertPath; import java.security.cert.Certificate; import java.security.cert.X509Certificate; -import java.security.cert.CertPath; -import java.security.*; -import sun.security.x509.*; -import sun.security.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Vector; +import java.util.jar.JarEntry; +import net.sourceforge.jnlp.util.JarFile; -import net.sourceforge.jnlp.*; -import net.sourceforge.jnlp.cache.*; -import net.sourceforge.jnlp.security.*; +import net.sourceforge.jnlp.JARDesc; +import net.sourceforge.jnlp.JNLPFile; +import net.sourceforge.jnlp.LaunchException; +import net.sourceforge.jnlp.cache.ResourceTracker; +import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.security.CertVerifier; +import net.sourceforge.jnlp.security.CertificateUtils; +import net.sourceforge.jnlp.security.KeyStores; +import sun.security.util.DerInputStream; +import sun.security.util.DerValue; +import sun.security.x509.NetscapeCertTypeExtension; /** * <p>The jar certificate verifier utility.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/util/InvalidJarHeaderException.java Wed Apr 10 17:49:20 2013 +0200 @@ -0,0 +1,49 @@ +/* +Copyright (C) 2012 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; either version 2, or (at your option) +any later version. + +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; + +/** + * Thrown from net.sourceforge.jnlp.utilJArFile when verification of headers fails + * + */ +public class InvalidJarHeaderException extends RuntimeException{ + + public InvalidJarHeaderException(String string) { + super(string); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/util/JarFile.java Wed Apr 10 17:49:20 2013 +0200 @@ -0,0 +1,153 @@ +/* + Copyright (C) 2012 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; either version 2, or (at your option) + any later version. + + 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.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipFile; +import net.sourceforge.jnlp.runtime.JNLPRuntime; + +public class JarFile extends java.util.jar.JarFile { + + public JarFile(String name) throws IOException { + super(name); + verifyZipHeader(new File(name)); + } + + /** + */ + public JarFile(String name, boolean verify) throws IOException { + super(name, verify); + verifyZipHeader(new File(name)); + } + + /** + */ + public JarFile(File file) throws IOException { + super(file); + verifyZipHeader(file); + } + + /** + */ + public JarFile(File file, boolean verify) throws IOException { + super(file, verify); + verifyZipHeader(file); + } + + /* + */ + public JarFile(File file, boolean verify, int mode) throws IOException { + super(file, verify, mode); + verifyZipHeader(file); + } + + + + + /** + * According to specification - + * http://www.pkware.com/documents/casestudies/APPNOTE.TXT or just google + * around zip header all entries in zip-compressed must start with well + * known "PK" which is defined as hexa x50 x4b x03 x04, which in decimal are + * 80 75 3 4. + * + * Note - this is not file-header, it is item-header. + * + * Actually most of compressing formats have some n-bytes header se eg: + * http://www.gzip.org/zlib/rfc-gzip.html#header-trailer for ID1 and ID2 so + * in case that some differently compressed jars will come to play, this is + * the palce where to fix it. + * + */ + private static final byte[] ZIP_LOCAL_FILE_HEADER_SIGNATURE = new byte[]{80, 75, 3, 4}; + + /** + * This method is checking first four bytes of jar-file against + * ZIP_LOCAL_FILE_HEADER_SIGNATURE + * + * Although zip specification allows to skip all corrupted entries, it is + * not safe for jars. If first four bytes of file are not zip + * ZIP_LOCAL_FILE_HEADER_SIGNATURE then exception is thrown + * + * As noted, ZIP_LOCAL_FILE_HEADER_SIGNATURE is not ile-header, but is item-header. + * Possible attack is using the fact that entries without header are considered + * corrupted and so can be ignoered. However, for other they can have some meaning. + * + * So for our purposes we must insists on first record to be valid. + * + * @param file + * @throws IOException, InvalidJarHeaderException + */ + public static void verifyZipHeader(File file) throws IOException { + if (!JNLPRuntime.isIgnoreHeaders()) { + InputStream s = new FileInputStream(file); + try { + byte[] buffer = new byte[ZIP_LOCAL_FILE_HEADER_SIGNATURE.length]; + /* + * for case that new byte[] will accidently initialize same + * sequence as zip header and during the read the buffer will not be filled + */ + for (int i = 0; i < buffer.length; i++) { + buffer[i] = 0; + } + int toRead = ZIP_LOCAL_FILE_HEADER_SIGNATURE.length; + int readSoFar = 0; + int n = 0; + /* + * this is used instead of s.read(buffer) for case of block and + * so returned not-fully-filled dbuffer + */ + while ((n = s.read(buffer, readSoFar, buffer.length - readSoFar)) != -1) { + readSoFar += n; + if (readSoFar == toRead) { + break; + } + } + for (int i = 0; i < buffer.length; i++) { + if (buffer[i] != ZIP_LOCAL_FILE_HEADER_SIGNATURE[i]) { + throw new InvalidJarHeaderException("Jar " + file.getName() + " do not heave valid header. You can skip this check by -Xignoreheaders"); + } + } + } finally { + s.close(); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/custom/GifarCreator/srcs/Makefile Wed Apr 10 17:49:20 2013 +0200 @@ -0,0 +1,17 @@ +DEPLOY_SUBDIR=$(REPRODUCERS_TESTS_SERVER_DEPLOYDIR) +GIF=$(DEPLOY_SUBDIR)/happyNonAnimated.gif +JAR=$(DEPLOY_SUBDIR)/GifarBase.jar +RESULT1=$(DEPLOY_SUBDIR)/Gifar.jar +RESULT2=$(DEPLOY_SUBDIR)/Gifar.gif + +#this is dependent on reproducers/signed/GifarBase + +prepare-reproducer: + cat $(GIF) > $(RESULT1) + cat $(JAR) >> $(RESULT1) + cp $(RESULT1) $(RESULT2) + +clean-reproducer: + rm -rf $(RESULT1) + rm -rf $(RESULT2) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/signed/GifarBase/resources/gifarView_hacked.html Wed Apr 10 17:49:20 2013 +0200 @@ -0,0 +1,48 @@ +<!-- + +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; either version 2, or (at your option) +any later version. + +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. + + --> +<html><head></head><body bgcolor="blue"> +<p><applet code="GifarMain.class" archive="Gifar.gif" codebase="." width="250" height="200"> + <param name="image" value="Gifar.jar"> +</applet></p> +<p> +<img alt="There should be gif image" src="happyNonAnimated.gif"/> +<img alt="There should be gif image" src="Gifar.jar"/> +<img alt="There should be gif image" src="Gifar.gif"/> +</p> +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/signed/GifarBase/resources/gifarView_ok.html Wed Apr 10 17:49:20 2013 +0200 @@ -0,0 +1,48 @@ +<!-- + +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; either version 2, or (at your option) +any later version. + +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. + + --> +<html><head></head><body bgcolor="blue"> +<p><applet code="GifarMain.class" archive="GifarBase.jar" codebase="." width="250" height="200"> + <param name="image" value="Gifar.jar"> +</applet></p> +<p> +<img alt="There should be gif image" src="happyNonAnimated.gif"/> +<img alt="There should be gif image" src="Gifar.jar"/> +<img alt="There should be gif image" src="Gifar.gif"/> +</p> +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/signed/GifarBase/resources/gifar_applet.jnlp Wed Apr 10 17:49:20 2013 +0200 @@ -0,0 +1,65 @@ +<!-- + +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; either version 2, or (at your option) +any later version. + +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. + + --> +<?xml version="1.0" encoding="utf-8"?> +<jnlp spec="1.0" href="gifar_applet.jnlp" codebase="."> + <information> + <title>GifarView</title> + <vendor>IcedTea</vendor> + <homepage href="http://icedtea.classpath.org/wiki/IcedTea-Web#Testing_IcedTea-Web"/> + <description>Gifar issue</description> + <offline/> + </information> + <resources> + <j2se version="1.4+"/> + <jar href="Gifar.gif"/> + </resources> + <security> + <all-permissions/> + </security> + <applet-desc + documentBase="." + name="Gifar" + main-class="GifarMain" + width="250" + height="200"> + <param name="image" value="Gifar.jar"/> + </applet-desc> +</jnlp> + + +</applet-desc>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/signed/GifarBase/resources/gifar_application.jnlp Wed Apr 10 17:49:20 2013 +0200 @@ -0,0 +1,60 @@ +<!-- + +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; either version 2, or (at your option) +any later version. + +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. + + --> +<?xml version="1.0" encoding="utf-8"?> +<jnlp spec="1.0" href="gifar_application.jnlp" codebase="."> + <information> + <title>GifarView</title> + <vendor>IcedTea</vendor> + <homepage href="http://icedtea.classpath.org/wiki/IcedTea-Web#Testing_IcedTea-Web"/> + <description>Gifar issue</description> + <offline/> + </information> + <security> + <all-permissions/> + </security> + <resources> + <j2se version="1.4+"/> + <jar href="Gifar.gif"/> + </resources> + <application-desc main-class="GifarMain"> + <argument>Gifar.jar</argument> + </application-desc> +</jnlp> + + +</applet-desc>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/signed/GifarBase/srcs/GifarMain.java Wed Apr 10 17:49:20 2013 +0200 @@ -0,0 +1,212 @@ + +import java.awt.BorderLayout; +import java.awt.image.BufferedImage; +import java.net.URL; +import javax.imageio.ImageIO; +import javax.jnlp.BasicService; +import javax.jnlp.ServiceManager; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JApplet; +import javax.swing.JFrame; +import javax.swing.JLabel; + +/* AppletTest.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. + */ +public class GifarMain extends JApplet { + + boolean isApplet = true; + String defaultPath = "happyNonAnimated.gif"; + String imageName; + URL path = null; + + private class Killer extends Thread { + + public int n = 3000; + + @Override + public void run() { + try { + Thread.sleep(n); + System.out.println("gifar killing himself after " + n + " ms of life"); + System.exit(0); + } catch (Exception ex) { + } + } + } + private Killer killer; + + @Override + public void init() { + System.out.println("gifar was initialised"); + killer = new Killer(); + this.setLayout(new BorderLayout()); + String futurePath = null; + if (isApplet) { + futurePath = getParameter("image"); + if ("yes".equals(futurePath)) { + imageName = defaultPath; + } else if (futurePath != null) { + imageName = futurePath; + } + } + } + + @Override + public void start() { + System.out.println("gifar is starting"); + String s = "<html>" + System.getProperty("java.vm.version") + "<br>" + + System.getProperty("java.vm.vendor") + "<br>" + + System.getProperty("java.vm.name") + "<br>" + + System.getProperty("java.specification.version") + "<br>" + + System.getProperty("java.specification.vendor") + "<br>" + + System.getProperty("java.specification.name") + "</html>"; + JLabel jLabel1 = new JLabel(s); + this.add(jLabel1, BorderLayout.NORTH); + System.out.println("Used image: " + imageName); + if (imageName != null) { + try { + path = new URL(getIndependentCodebase(), imageName); + System.out.println("Loading: "+path.toString()); + JLabel jLabel2 = new JLabel(loadIcon(path)); + System.out.println("Image loaded"); + this.add(jLabel2, BorderLayout.SOUTH); + } catch (Exception ex) { + //ex.printStackTrace(); + throw new RuntimeException(ex); + } + } + killer.start(); + System.out.println("is applet: " + isApplet); + System.out.println("gifar was started"); + } + + Icon loadIcon(URL u) { + try { + BufferedImage i = ImageIO.read(u.openStream()); + return new ImageIcon(i); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + + + } + + public URL getIndependentCodebase() { + try { + URL u1 = getCodeBaseApplet(); + URL u2 = getCodeBaseJavaws(); + if (u1 != null) { + return u1; + } + if (u2 != null) { + return u2; + } + return new URL("http://localhost:44321/"); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + + } + + public URL getCodeBaseApplet() { + try { + URL codebase = getCodeBase(); + if (codebase != null) { + System.out.println("applet codebase: " + codebase.toString()); + return codebase; + } else { + System.out.println("applet codebase: null"); + } + } catch (Exception ex) { + ex.printStackTrace(); + System.out.println("applet codebase: null"); + } + return null; + } + + public URL getCodeBaseJavaws() { + try { + BasicService bs = (BasicService) ServiceManager.lookup("javax.jnlp.BasicService"); + URL codebase = bs.getCodeBase(); + if (codebase != null) { + System.out.println("javaws codebase: " + codebase.toString()); + return codebase; + } else { + System.out.println("javaws codebase: null"); + } + } catch (Exception ex) { + ex.printStackTrace(); + System.out.println("javaws codebase: null"); + } + return null; + } + + @Override + public void stop() { + System.out.println("gifar was stopped"); + } + + @Override + public void destroy() { + System.out.println("gifar will be destroyed"); + } + + public static void main(String args[]) { + final JFrame f = new JFrame(); + f.setLayout(new BorderLayout()); + f.setSize(250, 200); + GifarMain gm = new GifarMain(); + gm.isApplet = false; + f.add(gm); + gm.init(); + if (args.length > 0) { + if ("yes".equals(args[0])) { + gm.imageName = gm.defaultPath; + } else { + gm.imageName = args[0]; + } + } + gm.start(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + f.setVisible(true); + } + }); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/signed/GifarBase/testcases/GifarTestcases.java Wed Apr 10 17:49:20 2013 +0200 @@ -0,0 +1,221 @@ +/* AppletTestTests.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. + */ + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import javax.imageio.ImageIO; +import net.sourceforge.jnlp.ProcessResult; +import net.sourceforge.jnlp.ServerAccess; +import net.sourceforge.jnlp.annotations.NeedsDisplay; +import net.sourceforge.jnlp.annotations.TestInBrowsers; +import net.sourceforge.jnlp.browsertesting.BrowserTest; +import net.sourceforge.jnlp.browsertesting.Browsers; +import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.util.InvalidJarHeaderException; +import net.sourceforge.jnlp.util.JarFile; +import org.junit.Assert; +import org.junit.Test; + +public class GifarTestcases extends BrowserTest { + + List<String> trustIgnore = Arrays.asList(new String[]{ServerAccess.HEADLES_OPTION, "-Xtrustall", "-Xignoreheaders"}); + List<String> trust = Arrays.asList(new String[]{ServerAccess.HEADLES_OPTION, "-Xtrustall"}); + private static String exceptionString = InvalidJarHeaderException.class.getName(); + private static String okString = "Image loaded"; + private static String sucideString = "gifar killing himself"; + + private static boolean evaluate(String what, String doContains) { + return what.contains(doContains); + } + + private static boolean exceptionRule(String what) { + return evaluate(what, exceptionString); + } + + private static boolean okRule(String what) { + return evaluate(what, okString); + } + + private static boolean sucideRule(String what) { + return evaluate(what, sucideString); + } + + private static String toPassingString(String rule) { + return "should contain `" + rule + "`"; + } + + private static String toFailingString(String rule) { + return "should NOT contain `" + rule + "`"; + } + + File okJar = new File(server.getDir(), "GifarBase.jar"); + File hackedJar = new File(server.getDir(), "Gifar.jar"); + File okImage = new File(server.getDir(), "happyNonAnimated.gif"); + File hackedImage = new File(server.getDir(), "Gifar.gif"); + + @Test + public void unittest_verify_okJar() throws IOException { + JNLPRuntime.setIgnoreHeaders(false); + JarFile j1 = new JarFile(okJar); + Assert.assertNotNull(j1); + JNLPRuntime.setIgnoreHeaders(true); + JarFile j2 = new JarFile(okJar); + Assert.assertNotNull(j2); + + } + + @Test + public void unittest_verify_badJar() throws IOException { + JNLPRuntime.setIgnoreHeaders(false); + Exception ex = null; + JarFile j1 = null; + try { + j1 = new JarFile(hackedJar); + } catch (InvalidJarHeaderException e) { + ex = e; + } + Assert.assertNull(j1); + Assert.assertNotNull(ex); + Assert.assertEquals(InvalidJarHeaderException.class, ex.getClass()); + JNLPRuntime.setIgnoreHeaders(true); + JarFile j2 = new JarFile(hackedJar); + Assert.assertNotNull(j2); + + } + + @Test + public void unittest_verify_badImageAsJar() throws IOException { + JNLPRuntime.setIgnoreHeaders(false); + Exception ex = null; + JarFile j1 = null; + try { + j1 = new JarFile(hackedImage); + } catch (InvalidJarHeaderException e) { + ex = e; + } + Assert.assertNull(j1); + Assert.assertNotNull(ex); + Assert.assertEquals(InvalidJarHeaderException.class, ex.getClass()); + JNLPRuntime.setIgnoreHeaders(true); + JarFile j2 = new JarFile(hackedImage); + Assert.assertNotNull(j2); + + } + + @Test + public void unittest_verify_okImage() throws IOException { + JNLPRuntime.setIgnoreHeaders(false); + BufferedImage j1 = ImageIO.read(okImage); + Assert.assertNotNull(j1); + JNLPRuntime.setIgnoreHeaders(true); + BufferedImage j2 = ImageIO.read(okImage); + Assert.assertNotNull(j2); + + } + + @Test + public void unittest_verify_badImaqe() throws IOException { + JNLPRuntime.setIgnoreHeaders(false); + BufferedImage j1 = ImageIO.read(hackedImage); + Assert.assertNotNull(j1); + JNLPRuntime.setIgnoreHeaders(true); + BufferedImage j2 = ImageIO.read(hackedImage); + Assert.assertNotNull(j2); + + } + + @Test + @NeedsDisplay + public void GifarViaJnlp_application() throws Exception { + ProcessResult pr = server.executeJavaws(trust, "gifar_application.jnlp"); + Assert.assertEquals((Integer) 0, pr.returnValue); + Assert.assertFalse("stdout " + toFailingString(okString) + " but did", okRule(pr.stdout)); + Assert.assertTrue("stderr " + toPassingString(exceptionString) + " but did'nt", exceptionRule(pr.stderr)); + } + + @Test + @NeedsDisplay + public void GifarViaJnlp_application_ignoreHeaders() throws Exception { + ProcessResult pr = server.executeJavaws(trustIgnore, "gifar_application.jnlp"); + Assert.assertEquals((Integer) 0, pr.returnValue); + Assert.assertTrue("stdout " + toPassingString(okString) + " but didn't", okRule(pr.stdout)); + Assert.assertFalse("stderr " + toFailingString(exceptionString) + " but did", exceptionRule(pr.stderr)); + } + + @Test + @NeedsDisplay + public void GifarViaJnlp_applet() throws Exception { + ProcessResult pr = server.executeJavaws(trust, "gifar_applet.jnlp"); + Assert.assertEquals((Integer) 0, pr.returnValue); + Assert.assertFalse("stdout " + toFailingString(okString) + " but did", okRule(pr.stdout)); + Assert.assertTrue("stderr " + toPassingString(exceptionString) + " but didn't", exceptionRule(pr.stderr)); + } + + @Test + @NeedsDisplay + public void GifarViaJnlp_applet_ignoreHeaders() throws Exception { + ProcessResult pr = server.executeJavaws(trustIgnore, "gifar_applet.jnlp"); + Assert.assertEquals((Integer) 0, pr.returnValue); + Assert.assertTrue("stdout " + toPassingString(okString) + " but didn't", okRule(pr.stdout)); + Assert.assertFalse("stderr " + toFailingString(exceptionString) + " but did", exceptionRule(pr.stderr)); + } + + @Test + @TestInBrowsers(testIn = {Browsers.all}) + @NeedsDisplay + public void GifarViaBrowser_hacked() throws Exception { + ProcessResult pr = server.executeBrowser("gifarView_hacked.html"); + Assert.assertFalse("stdout " + toFailingString(okString) + " but did", okRule(pr.stdout)); + Assert.assertTrue("stderr " + toPassingString(exceptionString) + " but didn't", exceptionRule(pr.stderr)); + + + } + + @Test + @TestInBrowsers(testIn = {Browsers.one}) + @NeedsDisplay + public void GifarViaBrowser_ok() throws Exception { + ProcessResult pr = server.executeBrowser("gifarView_ok.html"); + Assert.assertTrue("stdout " + toPassingString(okString) + " but didn't", okRule(pr.stdout)); + Assert.assertFalse("stderr " + toFailingString(exceptionString) + " but did", exceptionRule(pr.stderr)); + + + } +}