# HG changeset patch # User Jiri Vanek # Date 1441718672 -7200 # Node ID b668c06dcb3674fc56faf4e7a6879ed6b71a7ae6 # Parent f45e2b0ee1741e711ce6f867d9826a941ad19031 Saving of status of dialogs for "whole codebase" now includes also document base diff -r f45e2b0ee174 -r b668c06dcb36 ChangeLog --- a/ChangeLog Tue Sep 08 15:02:10 2015 +0200 +++ b/ChangeLog Tue Sep 08 15:24:32 2015 +0200 @@ -1,3 +1,19 @@ +2015-09-01 Jiri Vanek + + Saving of status of dialogs for "whole codebase" now includes also document base + * netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java: + (updateAppletAction) now saves base of docbase instead of .* "for remember for codebase" + stripFile - new method, ensuring docbase do not contains file + * tests/netx/unit/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmationTest.java: + added testSripFile unit test for new method + * tests/reproducers/simple/FakeCodebase/resources/FakeCodebase.html.in: + * tests/reproducers/simple/FakeCodebase/resources/FakeCodebase.jnlp.in: + * tests/reproducers/simple/FakeCodebase/resources/OriginalCodebase.html: + * tests/reproducers/simple/FakeCodebase/resources/OriginalCodebase.jnlp: + * tests/reproducers/simple/FakeCodebase/srcs/FakeCodebase.java: + * tests/reproducers/simple/FakeCodebase/testcases/FakeCodebaseTests.java: + Reproducer of this behavior + 2015-09-01 Jiri Vanek application-library-allowable-codebase dialog made available for unsigned apps diff -r f45e2b0ee174 -r b668c06dcb36 netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java --- a/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java Tue Sep 08 15:02:10 2015 +0200 +++ b/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java Tue Sep 08 15:24:32 2015 +0200 @@ -36,6 +36,7 @@ package net.sourceforge.jnlp.security.appletextendedsecurity; +import java.net.MalformedURLException; import static net.sourceforge.jnlp.runtime.Translator.R; import java.net.URL; @@ -139,7 +140,7 @@ /* Else, create a new entry */ UrlRegEx codebaseRegex = new UrlRegEx("\\Q" + codebase + "\\E"); - UrlRegEx documentbaseRegex = new UrlRegEx(".*"); // Match any from codebase + UrlRegEx documentbaseRegex = new UrlRegEx("\\Q" + stripFile(documentbase)+ "\\E.*"); // Match any from codebase and sourceFile "base" List archiveMatches = null; // Match any from codebase if (!rememberForCodeBase) { @@ -262,4 +263,48 @@ } + static String stripFile(URL documentbase) { + //whenused in generation of regec, the trailing slash is very important + //see the result between http:/some.url/path.* and http:/some.url/path/.* + return ensureSlashTail(stripFileImp(documentbase)); + } + + private static String stripFileImp(URL documentbase) { + try { + String normlaized = UrlUtils.normalizeUrlAndStripParams(documentbase).toExternalForm().trim(); + if (normlaized.endsWith("/") || normlaized.endsWith("\\")) { + return normlaized; + } + URL middleway = new URL(normlaized); + String file = middleway.getFile(); + int i = Math.max(file.lastIndexOf('/'), file.lastIndexOf('\\')); + if (i<0){ + return normlaized; + } + String parent = file.substring(0, i+1); + String stripped = normlaized.replace(file, parent); + return stripped; + } catch (Exception ex) { + OutputController.getLogger().log(ex); + return documentbase.toExternalForm(); + } + + } + + private static String ensureSlashTail(String s) { + if (s.endsWith("/")) { + return s; + } + if (s.endsWith("\\")) { + return s; + } + if (s.contains("/")) { + return s + "/"; + } + if (s.contains("\\")) { + return s + "\\"; + } + return s + "/"; + } + } \ No newline at end of file diff -r f45e2b0ee174 -r b668c06dcb36 tests/netx/unit/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmationTest.java --- a/tests/netx/unit/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmationTest.java Tue Sep 08 15:02:10 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmationTest.java Tue Sep 08 15:24:32 2015 +0200 @@ -29,4 +29,34 @@ assertEquals(Arrays.asList("test .jar"), UnsignedAppletTrustConfirmation.toRelativePaths(Arrays.asList("http://example.com/test .jar"), "http://example.com/")); } + + + @Test + public void testSripFile() throws Exception { + String sample = "http://aa.bb/"; + String result = UnsignedAppletTrustConfirmation.stripFile(new URL(sample)); + assertEquals(sample, result); + sample = "http://aa.bb"; + result = UnsignedAppletTrustConfirmation.stripFile(new URL(sample)); + assertEquals(sample + "/", result); + sample = "http://aa.bb/"; + result = UnsignedAppletTrustConfirmation.stripFile(new URL(sample + "cc")); + assertEquals(sample, result); + sample = "http://aa.bb/cc/"; + result = UnsignedAppletTrustConfirmation.stripFile(new URL(sample)); + assertEquals(sample, result); + sample = "http://aa.bb/some/complicated/"; + result = UnsignedAppletTrustConfirmation.stripFile(new URL(sample + "some")); + assertEquals(sample, result); + sample = "http://aa.bb/some/complicated/some/"; + result = UnsignedAppletTrustConfirmation.stripFile(new URL(sample)); + assertEquals(sample, result); + sample = "http://aa.bb/some/"; + result = UnsignedAppletTrustConfirmation.stripFile(new URL(sample + "strange?a=b")); + assertEquals(sample, result); + sample = "http://aa.bb/some/strange/"; + result = UnsignedAppletTrustConfirmation.stripFile(new URL(sample + "?a=b")); + assertEquals(sample, result); + + } } diff -r f45e2b0ee174 -r b668c06dcb36 tests/reproducers/simple/FakeCodebase/resources/FakeCodebase.html.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/simple/FakeCodebase/resources/FakeCodebase.html.in Tue Sep 08 15:24:32 2015 +0200 @@ -0,0 +1,44 @@ + + + +

+

+ + + diff -r f45e2b0ee174 -r b668c06dcb36 tests/reproducers/simple/FakeCodebase/resources/FakeCodebase.jnlp.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/simple/FakeCodebase/resources/FakeCodebase.jnlp.in Tue Sep 08 15:24:32 2015 +0200 @@ -0,0 +1,14 @@ + + + + OriginalCodebase FakeCodebase + IcedTea + + + + + + + + \ No newline at end of file diff -r f45e2b0ee174 -r b668c06dcb36 tests/reproducers/simple/FakeCodebase/resources/OriginalCodebase.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/simple/FakeCodebase/resources/OriginalCodebase.html Tue Sep 08 15:24:32 2015 +0200 @@ -0,0 +1,44 @@ + + + +

+

+ + + diff -r f45e2b0ee174 -r b668c06dcb36 tests/reproducers/simple/FakeCodebase/resources/OriginalCodebase.jnlp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/simple/FakeCodebase/resources/OriginalCodebase.jnlp Tue Sep 08 15:24:32 2015 +0200 @@ -0,0 +1,14 @@ + + + + OriginalCodebase FakeCodebase + IcedTea + + + + + + + + diff -r f45e2b0ee174 -r b668c06dcb36 tests/reproducers/simple/FakeCodebase/srcs/FakeCodebase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/simple/FakeCodebase/srcs/FakeCodebase.java Tue Sep 08 15:24:32 2015 +0200 @@ -0,0 +1,55 @@ + +import java.applet.Applet; + +/* 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 FakeCodebase extends Applet { + + @Override + public void init() { + confirm(); + } + + public static void main(String... s) { + confirm(); + } + + private static void confirm() { + System.out.println("*** APPLET FINISHED ***"); + } + +} diff -r f45e2b0ee174 -r b668c06dcb36 tests/reproducers/simple/FakeCodebase/testcases/FakeCodebaseTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/simple/FakeCodebase/testcases/FakeCodebaseTests.java Tue Sep 08 15:24:32 2015 +0200 @@ -0,0 +1,161 @@ +/* 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.io.File; +import java.io.IOException; +import static org.junit.Assert.assertTrue; + +import net.sourceforge.jnlp.ProcessResult; +import net.sourceforge.jnlp.ServerAccess; +import net.sourceforge.jnlp.ServerAccess.AutoClose; +import net.sourceforge.jnlp.ServerLauncher; +import net.sourceforge.jnlp.browsertesting.BrowserTest; +import net.sourceforge.jnlp.browsertesting.Browsers; +import net.sourceforge.jnlp.closinglisteners.AutoOkClosingListener; +import net.sourceforge.jnlp.annotations.NeedsDisplay; +import net.sourceforge.jnlp.annotations.TestInBrowsers; +import net.sourceforge.jnlp.browsertesting.browsers.firefox.FirefoxProfilesOperator; +import net.sourceforge.jnlp.config.DeploymentConfiguration; +import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel; +import net.sourceforge.jnlp.util.FileUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; + +import org.junit.Test; + +public class FakeCodebaseTests extends BrowserTest { + + private static String originalProperties; + private static final File depPropsFile = new File(System.getProperty("user.home") + "/.config/icedtea-web/deployment.properties"); + private static final File trustFile = new File(System.getProperty("user.home") + "/.config/icedtea-web/.appletTrustSettings"); + + private static File backup; + private static final String HTMLIN = "FakeCodebase.html"; + private static final String ORIG_BASE = "OriginalCodebase.html"; + + private static final String JHTMLIN = "FakeCodebase.jnlp"; + private static final String JORIG_BASE = "OriginalCodebase.jnlp"; + + private static final ServerLauncher evilServer1 = ServerAccess.getIndependentInstance(); + private static final ServerLauncher evilServer2 = ServerAccess.getIndependentInstance(); + + @AfterClass + public static void killServer1() throws IOException { + evilServer1.stop(); + } + + @AfterClass + public static void killServer2() throws IOException { + evilServer2.stop(); + } + + @BeforeClass + public static void setSecurity() throws IOException { + originalProperties = FileUtils.loadFileAsString(depPropsFile); + FileUtils.saveFile(DeploymentConfiguration.KEY_SECURITY_LEVEL+"="+AppletSecurityLevel.ASK_UNSIGNED.name()+"n"+ + DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK+"="+false + , depPropsFile); + + } + + @BeforeClass + public static void backupAppTrust() throws IOException { + backup = File.createTempFile("fakeCodebase", "itwReproducers"); + backup.deleteOnExit(); + FirefoxProfilesOperator.copyFile(trustFile, backup); + } + + @AfterClass + public static void restoreAppTrust() throws IOException { + FirefoxProfilesOperator.copyFile(backup, trustFile); + } + + @AfterClass + public static void resetSecurity() throws IOException { + FileUtils.saveFile(originalProperties, depPropsFile); + + } + + //placeholder to make unittest happy + @Test + public void FakeCodebaseTestFake() throws Exception { + } + + //headless dialogues now works only for javaws. + //@Test + @TestInBrowsers(testIn = {Browsers.all}) + @NeedsDisplay + public void FakeCodebaseTest() throws Exception { + try { + String ob1 = FileUtils.loadFileAsString(new File(server.getDir(), ORIG_BASE)); + assertTrue(ob1.contains("id=\"FakeCodebase0\"")); //check orig.html is correct one + trustFile.delete(); //clean file is an must + //run normal applet on normal codebase with standard server + //answer YES + rember for ever + for codebase + ProcessResult pr1 = server.executeBrowser("/" + ORIG_BASE, AutoClose.CLOSE_ON_CORRECT_END); + assertTrue(pr1.stdout.contains(AutoOkClosingListener.MAGICAL_OK_CLOSING_STRING)); + //the record was added to .appletSecuritySettings + String s2 = FileUtils.loadFileAsString(trustFile).trim(); + String[] ss2 = s2.split("\n"); + Assert.assertEquals(1, ss2.length); + //create atacker + String htmlin = FileUtils.loadFileAsString(new File(server.getDir(), HTMLIN + ".in")); + //now change codebase to be same as ^ but launch applet from evilServer1 + htmlin = htmlin.replaceAll("EVILURL2", server.getUrl().toExternalForm()); + //and as bonus get resources from evilServer2 + htmlin = htmlin.replaceAll("EVILURL1", evilServer2.getUrl().toExternalForm()); + FileUtils.saveFile(htmlin, new File(server.getDir(), HTMLIN)); + String ob2 = FileUtils.loadFileAsString(new File(server.getDir(), HTMLIN)); + assertTrue(ob2.contains("id=\"FakeCodebase1\"")); + ProcessResult pr2 = ServerAccess.executeProcessUponURL( + server.getBrowserLocation(), + null, + evilServer1.getUrl("/" + HTMLIN), + new AutoOkClosingListener(), + null + ); + //this MUST ask for permissions to run, otherwise fail + assertTrue(pr2.stdout.contains(AutoOkClosingListener.MAGICAL_OK_CLOSING_STRING)); + String s1 = FileUtils.loadFileAsString(trustFile).trim(); + String[] ss1 = s1.split("\n"); + Assert.assertEquals(2, ss1.length); + } finally { + } + } + +}