michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: const Cr = Components.results; michael@0: michael@0: //load('CSPUtils.jsm'); michael@0: Cu.import('resource://gre/modules/CSPUtils.jsm'); michael@0: Cu.import('resource://gre/modules/NetUtil.jsm'); michael@0: michael@0: var httpServer = new HttpServer(); michael@0: httpServer.start(-1); michael@0: michael@0: const POLICY_FROM_URI = "default-src 'self'; img-src *"; michael@0: const POLICY_PORT = httpServer.identity.primaryPort; michael@0: const POLICY_URI = "http://localhost:" + POLICY_PORT + "/policy"; michael@0: const POLICY_URI_RELATIVE = "/policy"; michael@0: michael@0: //converts string to nsIURI michael@0: function URI(uriString) { michael@0: var ioService = Cc["@mozilla.org/network/io-service;1"] michael@0: .getService(Ci.nsIIOService); michael@0: return ioService.newURI(uriString, null, null); michael@0: } michael@0: michael@0: michael@0: // helper to assert that an array has the given value somewhere. michael@0: function do_check_in_array(arr, val, stack) { michael@0: if (!stack) michael@0: stack = Components.stack.caller; michael@0: michael@0: var text = val + " in [" + arr.join(",") + "]"; michael@0: michael@0: for(var i in arr) { michael@0: dump(".......... " + i + "> " + arr[i] + "\n"); michael@0: if(arr[i] == val) { michael@0: //succeed michael@0: ++_passedChecks; michael@0: dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " + michael@0: stack.lineNumber + "] " + text + "\n"); michael@0: return; michael@0: } michael@0: } michael@0: do_throw(text, stack); michael@0: } michael@0: michael@0: // helper to assert that an object or array must have a given key michael@0: function do_check_has_key(foo, key, stack) { michael@0: if (!stack) michael@0: stack = Components.stack.caller; michael@0: michael@0: var keys = []; michael@0: for (let k in foo) { keys.push(k); } michael@0: var text = key + " in [" + keys.join(",") + "]"; michael@0: michael@0: for (var x in foo) { michael@0: if (x == key) { michael@0: //succeed michael@0: ++_passedChecks; michael@0: dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " + michael@0: stack.lineNumber + "] " + text + "\n"); michael@0: return; michael@0: } michael@0: } michael@0: do_throw(text, stack); michael@0: } michael@0: michael@0: // helper to use .equals on stuff michael@0: function do_check_equivalent(foo, bar, stack) { michael@0: if (!stack) michael@0: stack = Components.stack.caller; michael@0: michael@0: var text = foo + ".equals(" + bar + ")"; michael@0: michael@0: if(foo.equals && foo.equals(bar)) { michael@0: ++_passedChecks; michael@0: dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " + michael@0: stack.lineNumber + "] " + text + "\n"); michael@0: return; michael@0: } michael@0: do_throw(text, stack); michael@0: } michael@0: michael@0: var tests = []; michael@0: function test(fcn) { michael@0: tests.push(fcn); michael@0: } michael@0: michael@0: test( michael@0: function test_CSPHost_fromstring() { michael@0: var h; michael@0: michael@0: h = CSPHost.fromString("*"); michael@0: do_check_neq(null, h); // "* lone wildcard should work" michael@0: michael@0: h = CSPHost.fromString("foo.bar"); michael@0: do_check_neq(null, h); // "standard tuple failed" michael@0: michael@0: h = CSPHost.fromString("*.bar"); michael@0: do_check_neq(null, h); // "wildcard failed" michael@0: michael@0: h = CSPHost.fromString("foo.*.bar"); michael@0: do_check_eq(null, h); // "wildcard in wrong place worked" michael@0: michael@0: h = CSPHost.fromString("com"); michael@0: do_check_neq(null, h); // "lone symbol should not fail" michael@0: michael@0: h = CSPHost.fromString("f00b4r.com"); michael@0: do_check_neq(null, h); // "Numbers in hosts should work" michael@0: michael@0: h = CSPHost.fromString("foo-bar.com"); michael@0: do_check_neq(null, h); // "dashes in hosts should work" michael@0: michael@0: michael@0: h = CSPHost.fromString("foo!bar.com"); michael@0: do_check_eq(null, h); // "special chars in hosts should fail" michael@0: michael@0: h = CSPHost.fromString("{app-url-is-uid}"); michael@0: do_check_neq(null, h); // "Packaged apps URLs failed" michael@0: }); michael@0: michael@0: test( michael@0: function test_CSPHost_clone() { michael@0: h = CSPHost.fromString("*.a.b.c"); michael@0: h2 = h.clone(); michael@0: for(var i in h._segments) { michael@0: // "cloned segments should match" michael@0: do_check_eq(h._segments[i], h2._segments[i]); michael@0: } michael@0: }); michael@0: michael@0: test( michael@0: function test_CSPHost_permits() { michael@0: var h = CSPHost.fromString("*.b.c"); michael@0: var h2 = CSPHost.fromString("a.b.c"); michael@0: do_check_true( h.permits(h2)); //"CSPHost *.b.c should allow CSPHost a.b.c" michael@0: do_check_true( h.permits("a.b.c")); //"CSPHost *.b.c should allow string a.b.c" michael@0: do_check_false(h.permits("b.c")); //"CSPHost *.b.c should not allow string b.c" michael@0: do_check_false(h.permits("a.a.c")); //"CSPHost *.b.c should not allow string a.a.c" michael@0: do_check_false(h2.permits(h)); //"CSPHost a.b.c should not allow CSPHost *.b.c" michael@0: do_check_false(h2.permits("b.c")); //"CSPHost a.b.c should not allow string b.c" michael@0: do_check_true( h2.permits("a.b.c")); //"CSPHost a.b.c should allow string a.b.c" michael@0: }); michael@0: michael@0: michael@0: ///////////////////// Test the Source object ////////////////////// michael@0: michael@0: test( michael@0: function test_CSPSource_fromString() { michael@0: // can't do these tests because "self" is not defined. michael@0: //"basic source should not be null."); michael@0: do_check_neq(null, CSPSource.fromString("a.com", undefined, "http://abc.com")); michael@0: michael@0: //"ldh characters should all work for host."); michael@0: do_check_neq(null, CSPSource.fromString("a2-c.com", undefined, "https://a.com")); michael@0: michael@0: //"wildcard should work in first token for host."); michael@0: do_check_neq(null, CSPSource.fromString("*.a.com", undefined, "http://abc.com")); michael@0: michael@0: //print(" --- Ignore the following two errors if they print ---"); michael@0: //"wildcard should not work in non-first token for host."); michael@0: do_check_eq(null, CSPSource.fromString("x.*.a.com", undefined, "http://a.com")); michael@0: michael@0: //"funny characters (#) should not work for host."); michael@0: do_check_eq(null, CSPSource.fromString("a#2-c.com", undefined, "http://a.com")); michael@0: michael@0: //print(" --- Stop ignoring errors that print ---\n"); michael@0: michael@0: //"failed to parse host with port."); michael@0: do_check_neq(null, CSPSource.create("a.com:23", undefined, "http://a.com")); michael@0: //"failed to parse host with scheme."); michael@0: do_check_neq(null, CSPSource.create("https://a.com", undefined, "http://a.com")); michael@0: //"failed to parse host with scheme and port."); michael@0: do_check_neq(null, CSPSource.create("https://a.com:200", undefined, "http://a.com")); michael@0: michael@0: //Check to make sure we don't match multiple instances with regex michael@0: do_check_eq(null, CSPSource.create("http://foo.com:bar.com:23")); michael@0: //Port parsing should work for all schemes michael@0: do_check_neq(null, CSPSource.create("data:")); michael@0: do_check_neq(null, CSPSource.create("javascript:")); michael@0: michael@0: //"app:// URLs should work, including the {} characters."); michael@0: do_check_neq(null, CSPSource.fromString("{app-host-is-uid}", undefined, "app://{app-host-is-uid}")); michael@0: }); michael@0: michael@0: test( michael@0: function test_CSPSource_fromString_withSelf() { michael@0: var src; michael@0: src = CSPSource.create("a.com", undefined, "https://foobar.com:443"); michael@0: //"src should inherit port * michael@0: do_check_true(src.permits("https://a.com:443")); michael@0: //"src should inherit and require https scheme michael@0: do_check_false(src.permits("http://a.com")); michael@0: //"src should inherit scheme 'https'" michael@0: do_check_true(src.permits("https://a.com")); michael@0: michael@0: src = CSPSource.create("http://a.com", undefined, "https://foobar.com:443"); michael@0: //"src should inherit and require http scheme" michael@0: do_check_false(src.permits("https://a.com")); michael@0: //"src should inherit scheme 'http'" michael@0: do_check_true(src.permits("http://a.com")); michael@0: //"src should inherit port and scheme from parent" michael@0: //"src should inherit default port for 'http'" michael@0: do_check_true(src.permits("http://a.com:80")); michael@0: michael@0: src = CSPSource.create("'self'", undefined, "https://foobar.com:443"); michael@0: //"src should inherit port * michael@0: do_check_true(src.permits("https://foobar.com:443")); michael@0: //"src should inherit and require https scheme michael@0: do_check_false(src.permits("http://foobar.com")); michael@0: //"src should inherit scheme 'https'" michael@0: do_check_true(src.permits("https://foobar.com")); michael@0: //"src should reject other hosts" michael@0: do_check_false(src.permits("https://a.com")); michael@0: michael@0: src = CSPSource.create("javascript:", undefined, "https://foobar.com:443"); michael@0: //"hostless schemes should be parseable." michael@0: var aUri = NetUtil.newURI("javascript:alert('foo');"); michael@0: do_check_true(src.permits(aUri)); michael@0: //"src should reject other hosts" michael@0: do_check_false(src.permits("https://a.com")); michael@0: //"nothing else should be allowed" michael@0: do_check_false(src.permits("https://foobar.com")); michael@0: michael@0: src = CSPSource.create("{app-host-is-uid}", undefined, "app://{app-host-is-uid}"); michael@0: //"src should inherit and require 'app' scheme" michael@0: do_check_false(src.permits("https://{app-host-is-uid}")); michael@0: //"src should inherit scheme 'app'" michael@0: do_check_true(src.permits("app://{app-host-is-uid}")); michael@0: michael@0: }); michael@0: michael@0: ///////////////////// Test the source list ////////////////////// michael@0: michael@0: test( michael@0: function test_CSPSourceList_fromString() { michael@0: var sd = CSPSourceList.fromString("'none'"); michael@0: //"'none' -- should parse" michael@0: do_check_neq(null,sd); michael@0: // "'none' should be a zero-length list" michael@0: do_check_eq(0, sd._sources.length); michael@0: do_check_true(sd.isNone()); michael@0: michael@0: sd = CSPSourceList.fromString("*"); michael@0: //"'*' should be a zero-length list" michael@0: do_check_eq(0, sd._sources.length); michael@0: michael@0: //print(" --- Ignore the following three errors if they print ---"); michael@0: //"funny char in host" michael@0: do_check_true(CSPSourceList.fromString("f!oo.bar").isNone()); michael@0: //"funny char in scheme" michael@0: do_check_true(CSPSourceList.fromString("ht!ps://f-oo.bar").isNone()); michael@0: //"funny char in port" michael@0: do_check_true(CSPSourceList.fromString("https://f-oo.bar:3f").isNone()); michael@0: //print(" --- Stop ignoring errors that print ---\n"); michael@0: }); michael@0: michael@0: test( michael@0: function test_CSPSourceList_fromString_twohost() { michael@0: var str = "foo.bar:21 https://ras.bar"; michael@0: var parsed = "http://foo.bar:21 https://ras.bar:443"; michael@0: var sd = CSPSourceList.fromString(str, undefined, URI("http://self.com:80")); michael@0: //"two-host list should parse" michael@0: do_check_neq(null,sd); michael@0: //"two-host list should parse to two hosts" michael@0: do_check_eq(2, sd._sources.length); michael@0: //"two-host list should contain original data" michael@0: do_check_eq(parsed, sd.toString()); michael@0: }); michael@0: michael@0: test( michael@0: function test_CSPSourceList_permits() { michael@0: var nullSourceList = CSPSourceList.fromString("'none'"); michael@0: var simpleSourceList = CSPSourceList.fromString("a.com", undefined, URI("http://self.com")); michael@0: var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88", michael@0: undefined, michael@0: URI("http://self.com:88")); michael@0: var allSourceList = CSPSourceList.fromString("*"); michael@0: var allAndMoreSourceList = CSPSourceList.fromString("* https://bar.com 'none'"); michael@0: var wildcardHostSourceList = CSPSourceList.fromString("*.foo.com", michael@0: undefined, URI("http://self.com")); michael@0: var allDoubledHostSourceList = CSPSourceList.fromString("**"); michael@0: var allGarbageHostSourceList = CSPSourceList.fromString("*a"); michael@0: michael@0: //'none' should permit none." michael@0: do_check_false( nullSourceList.permits("http://a.com")); michael@0: //a.com should permit a.com" michael@0: do_check_true( simpleSourceList.permits("http://a.com")); michael@0: //wrong host" michael@0: do_check_false( simpleSourceList.permits("http://b.com")); michael@0: //double list permits http://bar.com:88" michael@0: do_check_true( doubleSourceList.permits("http://bar.com:88")); michael@0: //double list permits https://bar.com:88" michael@0: do_check_false( doubleSourceList.permits("https://bar.com:88")); michael@0: //double list does not permit http://bar.com:443" michael@0: do_check_false( doubleSourceList.permits("http://bar.com:443")); michael@0: //"double list permits https://foo.com:88" (should not inherit port) michael@0: do_check_false( doubleSourceList.permits("https://foo.com:88")); michael@0: //"double list does not permit foo.com on http" michael@0: do_check_false( doubleSourceList.permits("http://foo.com")); michael@0: michael@0: //"* does not permit specific host" michael@0: do_check_true( allSourceList.permits("http://x.com:23")); michael@0: //"* does not permit a long host with no port" michael@0: do_check_true( allSourceList.permits("http://a.b.c.d.e.f.g.h.i.j.k.l.x.com")); michael@0: michael@0: //* short circuts parsing michael@0: do_check_true(allAndMoreSourceList.permits("http://a.com")); michael@0: michael@0: //"** permits all" michael@0: do_check_false(allDoubledHostSourceList.permits("http://barbaz.com")); michael@0: //"*a permits all" michael@0: do_check_false(allGarbageHostSourceList.permits("http://barbaz.com")); michael@0: michael@0: //"*.foo.com does not permit somerandom.foo.com" michael@0: do_check_true(wildcardHostSourceList.permits("http://somerandom.foo.com")); michael@0: //"*.foo.com permits all" michael@0: do_check_false(wildcardHostSourceList.permits("http://barbaz.com")); michael@0: }); michael@0: michael@0: ///////////////////// Test the Whole CSP rep object ////////////////////// michael@0: michael@0: test( michael@0: function test_CSPRep_fromString() { michael@0: michael@0: // check default init michael@0: //ASSERT(!(new CSPRep())._isInitialized, "Uninitialized rep thinks it is.") michael@0: michael@0: var cspr; michael@0: var cspr_allowval; michael@0: var SD = CSPRep.SRC_DIRECTIVES_OLD; michael@0: michael@0: // check default policy "allow *" michael@0: cspr = CSPRep.fromString("allow *", URI("http://self.com:80")); michael@0: // "DEFAULT_SRC directive is missing when specified in fromString" michael@0: do_check_has_key(cspr._directives, SD.DEFAULT_SRC); michael@0: michael@0: }); michael@0: michael@0: michael@0: test( michael@0: function test_CSPRep_defaultSrc() { michael@0: var cspr, cspr_default_val, cspr_allow; michael@0: var SD = CSPRep.SRC_DIRECTIVES_OLD; michael@0: michael@0: // apply policy of "default-src *" (e.g. "allow *") michael@0: cspr = CSPRep.fromString("default-src *", URI("http://self.com:80")); michael@0: // "DEFAULT_SRC directive is missing when specified in fromString" michael@0: do_check_has_key(cspr._directives, SD.DEFAULT_SRC); michael@0: michael@0: // check that |allow *| and |default-src *| are parsed equivalently and michael@0: // result in the same set of explicit policy directives michael@0: cspr = CSPRep.fromString("default-src *", URI("http://self.com:80")); michael@0: cspr_allow = CSPRep.fromString("allow *", URI("http://self.com:80")); michael@0: michael@0: do_check_equivalent(cspr._directives['default-src'], michael@0: cspr_allow._directives['default-src']); michael@0: }); michael@0: michael@0: michael@0: test( michael@0: function test_CSPRep_fromString_oneDir() { michael@0: michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_OLD; michael@0: var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, SD.FRAME_SRC]; michael@0: michael@0: // check one-directive policies michael@0: cspr = CSPRep.fromString("allow bar.com; script-src https://foo.com", michael@0: URI("http://self.com")); michael@0: michael@0: for(var x in DEFAULTS) { michael@0: //DEFAULTS[x] + " does not use default rule." michael@0: do_check_false(cspr.permits("http://bar.com:22", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule." michael@0: do_check_true(cspr.permits("http://bar.com:80", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule." michael@0: do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule." michael@0: do_check_false(cspr.permits("https://foo.com", DEFAULTS[x])); michael@0: } michael@0: //"script-src false positive in policy. michael@0: do_check_false(cspr.permits("http://bar.com:22", SD.SCRIPT_SRC)); michael@0: //"script-src false negative in policy. michael@0: do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC)); michael@0: }); michael@0: michael@0: test( michael@0: function test_CSPRep_fromString_twodir() { michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_OLD; michael@0: var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_SRC]; michael@0: michael@0: // check two-directive policies michael@0: var polstr = "allow allow.com; " michael@0: + "script-src https://foo.com; " michael@0: + "img-src bar.com:*"; michael@0: cspr = CSPRep.fromString(polstr, URI("http://self.com")); michael@0: michael@0: for(var x in DEFAULTS) { michael@0: do_check_true(cspr.permits("http://allow.com", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule. michael@0: do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule. michael@0: do_check_false(cspr.permits("http://bar.com:400", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule. michael@0: } michael@0: //"img-src does not use default rule. michael@0: do_check_false(cspr.permits("http://allow.com:22", SD.IMG_SRC)); michael@0: //"img-src does not use default rule. michael@0: do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC)); michael@0: //"img-src does not use default rule. michael@0: do_check_true(cspr.permits("http://bar.com:88", SD.IMG_SRC)); michael@0: michael@0: //"script-src does not use default rule. michael@0: do_check_false(cspr.permits("http://allow.com:22", SD.SCRIPT_SRC)); michael@0: //"script-src does not use default rule. michael@0: do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC)); michael@0: //"script-src does not use default rule. michael@0: do_check_false(cspr.permits("http://bar.com:400", SD.SCRIPT_SRC)); michael@0: }); michael@0: michael@0: test(function test_CSPRep_fromString_withself() { michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_OLD; michael@0: var self = "https://self.com:34"; michael@0: michael@0: // check one-directive policies michael@0: cspr = CSPRep.fromString("allow 'self'; script-src 'self' https://*:*", michael@0: URI(self)); michael@0: //"img-src does not enforce default rule, 'self'. michael@0: do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC)); michael@0: //"img-src does not allow self michael@0: do_check_true(cspr.permits(self, SD.IMG_SRC)); michael@0: //"script-src is too relaxed michael@0: do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC)); michael@0: //"script-src should allow self michael@0: do_check_true(cspr.permits(self, SD.SCRIPT_SRC)); michael@0: //"script-src is too strict on host/port michael@0: do_check_true(cspr.permits("https://evil.com:100", SD.SCRIPT_SRC)); michael@0: }); michael@0: michael@0: michael@0: //////////////// TEST CSP REP SPEC COMPLIANT PARSER //////////// michael@0: test( michael@0: function test_CSPRep_fromStringSpecCompliant() { michael@0: michael@0: var cspr; michael@0: var cspr_allowval; michael@0: var SD = CSPRep.SRC_DIRECTIVES_NEW; michael@0: var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, SD.SCRIPT_SRC, SD.FONT_SRC, michael@0: SD.OBJECT_SRC, SD.FRAME_SRC, SD.CONNECT_SRC]; michael@0: michael@0: // check default policy "default-src *" michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *", URI("http://self.com:80")); michael@0: // "DEFAULT_SRC directive is missing when specified in michael@0: // fromStringSpecCompliant" michael@0: do_check_has_key(cspr._directives, SD.DEFAULT_SRC); michael@0: michael@0: for(var x in DEFAULTS) { michael@0: // each of these should be equivalent to DEFAULT_SRC michael@0: //DEFAULTS[x] + " does not use default rule." michael@0: do_check_true(cspr.permits("http://bar.com", DEFAULTS[x])); michael@0: } michael@0: }); michael@0: michael@0: michael@0: test( michael@0: function test_CSPRep_fromStringSpecCompliant_oneDir() { michael@0: michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_NEW; michael@0: var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, michael@0: SD.FRAME_SRC, SD.CONNECT_SRC]; michael@0: michael@0: // check one-directive policies michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src bar.com; script-src https://foo.com", michael@0: URI("http://self.com")); michael@0: michael@0: for(var x in DEFAULTS) { michael@0: //DEFAULTS[x] + " does not use default rule." michael@0: do_check_false(cspr.permits("http://bar.com:22", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule." michael@0: do_check_true(cspr.permits("http://bar.com:80", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule." michael@0: do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule." michael@0: do_check_false(cspr.permits("https://foo.com", DEFAULTS[x])); michael@0: } michael@0: //"script-src false positive in policy. michael@0: do_check_false(cspr.permits("http://bar.com:22", SD.SCRIPT_SRC)); michael@0: //"script-src false negative in policy. michael@0: do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC)); michael@0: }); michael@0: michael@0: test( michael@0: function test_CSPRep_fromStringSpecCompliant_twodir() { michael@0: var cspr; michael@0: michael@0: var SD = CSPRep.SRC_DIRECTIVES_NEW; michael@0: michael@0: var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_SRC, michael@0: SD.CONNECT_SRC]; michael@0: michael@0: // check two-directive policies michael@0: var polstr = "default-src allow.com; " + michael@0: "script-src https://foo.com; " + michael@0: "img-src bar.com:*"; michael@0: cspr = CSPRep.fromStringSpecCompliant(polstr, URI("http://self.com")); michael@0: michael@0: for(var x in DEFAULTS) { michael@0: do_check_true(cspr.permits("http://allow.com", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule. michael@0: do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule. michael@0: do_check_false(cspr.permits("http://bar.com:400", DEFAULTS[x])); michael@0: //DEFAULTS[x] + " does not use default rule. michael@0: } michael@0: //"img-src does not use default rule. michael@0: do_check_false(cspr.permits("http://allow.com:22", SD.IMG_SRC)); michael@0: //"img-src does not use default rule. michael@0: do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC)); michael@0: //"img-src does not use default rule. michael@0: do_check_true(cspr.permits("http://bar.com:88", SD.IMG_SRC)); michael@0: michael@0: //"script-src does not use default rule. michael@0: do_check_false(cspr.permits("http://allow.com:22", SD.SCRIPT_SRC)); michael@0: //"script-src does not use default rule. michael@0: do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC)); michael@0: //"script-src does not use default rule. michael@0: do_check_false(cspr.permits("http://bar.com:400", SD.SCRIPT_SRC)); michael@0: }); michael@0: michael@0: test(function test_CSPRep_fromStringSpecCompliant_withself() { michael@0: var cspr; michael@0: var self = "https://self.com:34"; michael@0: var SD = CSPRep.SRC_DIRECTIVES_NEW; michael@0: michael@0: // check one-directive policies michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src 'self'; script-src 'self' https://*:*", michael@0: URI(self)); michael@0: //"img-src does not enforce default rule, 'self'. michael@0: do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC)); michael@0: //"img-src does not allow self michael@0: do_check_true(cspr.permits(self, SD.IMG_SRC)); michael@0: //"script-src is too relaxed michael@0: do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC)); michael@0: //"script-src should allow self michael@0: do_check_true(cspr.permits(self, SD.SCRIPT_SRC)); michael@0: //"script-src is too strict on host/port michael@0: do_check_true(cspr.permits("https://evil.com:100", SD.SCRIPT_SRC)); michael@0: }); michael@0: michael@0: michael@0: //////////////// TEST FRAME ANCESTOR DEFAULTS ///////////////// michael@0: // (see bug 555068) michael@0: test(function test_FrameAncestor_defaults() { michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_OLD; michael@0: var self = "http://self.com:34"; michael@0: michael@0: cspr = CSPRep.fromString("allow 'none'", URI(self)); michael@0: michael@0: //"frame-ancestors should default to * not 'allow' value" michael@0: do_check_true(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://self.com", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS)); michael@0: michael@0: cspr = CSPRep.fromString("allow 'none'; frame-ancestors 'self'", URI(self)); michael@0: michael@0: //"frame-ancestors should only allow self" michael@0: do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("http://self.com", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS)); michael@0: }); michael@0: michael@0: test(function test_FrameAncestor_defaults_specCompliant() { michael@0: var cspr; michael@0: var self = "http://self.com:34"; michael@0: var SD = CSPRep.SRC_DIRECTIVES_NEW; michael@0: michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src 'none'", URI(self)); michael@0: michael@0: //"frame-ancestors should default to * not 'default-src' value" michael@0: do_check_true(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://self.com", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS)); michael@0: michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src 'none'; frame-ancestors 'self'", URI(self)); michael@0: michael@0: //"frame-ancestors should only allow self" michael@0: do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("http://self.com", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS)); michael@0: }); michael@0: michael@0: michael@0: test(function test_FrameAncestor_TLD_defaultPorts() { michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_OLD; michael@0: var self = "http://self"; //TLD only, no .com or anything. michael@0: michael@0: cspr = CSPRep.fromString("allow 'self'; frame-ancestors 'self' http://foo:80 bar:80 http://three", URI(self)); michael@0: michael@0: //"frame-ancestors should default to * not 'allow' value" michael@0: do_check_true(cspr.permits("http://self", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://self:80", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://foo", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://foo:80", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://bar", SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits("http://three:80", SD.FRAME_ANCESTORS)); michael@0: michael@0: do_check_false(cspr.permits("https://foo:400", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("https://self:34", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("https://bar", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("http://three:81", SD.FRAME_ANCESTORS)); michael@0: do_check_false(cspr.permits("https://three:81", SD.FRAME_ANCESTORS)); michael@0: }); michael@0: michael@0: test(function test_FrameAncestor_ignores_userpass_bug779918() { michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_OLD; michael@0: var self = "http://self.com/bar"; michael@0: var testPolicy = "default-src 'self'; frame-ancestors 'self'"; michael@0: michael@0: cspr = CSPRep.fromString(testPolicy, URI(self)); michael@0: michael@0: // wrapped in URI() because of source parsing michael@0: do_check_true(cspr.permits(URI("http://username:password@self.com/foo"), SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits(URI("http://other:pass1@self.com/foo"), SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits(URI("http://self.com:80/foo"), SD.FRAME_ANCESTORS)); michael@0: do_check_true(cspr.permits(URI("http://self.com/foo"), SD.FRAME_ANCESTORS)); michael@0: michael@0: // construct fake ancestry with CSP applied to the child. michael@0: // [aChildUri] -> [aParentUri] -> (root/top) michael@0: // and then test "permitsAncestry" on the child/self docshell. michael@0: function testPermits(aChildUri, aParentUri, aContentType) { michael@0: let cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"] michael@0: .createInstance(Ci.nsIContentSecurityPolicy); michael@0: cspObj.appendPolicy(testPolicy, aChildUri, false, false); michael@0: let docshellparent = Cc["@mozilla.org/docshell;1"] michael@0: .createInstance(Ci.nsIDocShell); michael@0: let docshellchild = Cc["@mozilla.org/docshell;1"] michael@0: .createInstance(Ci.nsIDocShell); michael@0: docshellparent.setCurrentURI(aParentUri); michael@0: docshellchild.setCurrentURI(aChildUri); michael@0: docshellparent.addChild(docshellchild); michael@0: return cspObj.permitsAncestry(docshellchild); michael@0: }; michael@0: michael@0: // check parent without userpass michael@0: do_check_true(testPermits(URI("http://username:password@self.com/foo"), michael@0: URI("http://self.com/bar"))); michael@0: do_check_true(testPermits(URI("http://user1:pass1@self.com/foo"), michael@0: URI("http://self.com/bar"))); michael@0: do_check_true(testPermits(URI("http://self.com/foo"), michael@0: URI("http://self.com/bar"))); michael@0: michael@0: // check parent with userpass michael@0: do_check_true(testPermits(URI("http://username:password@self.com/foo"), michael@0: URI("http://username:password@self.com/bar"))); michael@0: do_check_true(testPermits(URI("http://user1:pass1@self.com/foo"), michael@0: URI("http://username:password@self.com/bar"))); michael@0: do_check_true(testPermits(URI("http://self.com/foo"), michael@0: URI("http://username:password@self.com/bar"))); michael@0: }); michael@0: michael@0: test(function test_CSP_ReportURI_parsing() { michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_NEW; michael@0: var self = "http://self.com:34"; michael@0: var parsedURIs = []; michael@0: michael@0: var uri_valid_absolute = self + "/report.py"; michael@0: var uri_other_host_absolute = "http://foo.org:34/report.py"; michael@0: var uri_valid_relative = "/report.py"; michael@0: var uri_valid_relative_expanded = self + uri_valid_relative; michael@0: var uri_valid_relative2 = "foo/bar/report.py"; michael@0: var uri_valid_relative2_expanded = self + "/" + uri_valid_relative2; michael@0: var uri_invalid_relative = "javascript:alert(1)"; michael@0: var uri_other_scheme_absolute = "https://self.com/report.py"; michael@0: var uri_other_scheme_and_host_absolute = "https://foo.com/report.py"; michael@0: michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_valid_absolute, URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: do_check_in_array(parsedURIs, uri_valid_absolute); michael@0: do_check_eq(parsedURIs.length, 1); michael@0: michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_other_host_absolute, URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: do_check_in_array(parsedURIs, uri_other_host_absolute); michael@0: do_check_eq(parsedURIs.length, 1); // the empty string is in there. michael@0: michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_invalid_relative, URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: do_check_in_array(parsedURIs, ""); michael@0: do_check_eq(parsedURIs.length, 1); michael@0: michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_valid_relative, URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: do_check_in_array(parsedURIs, uri_valid_relative_expanded); michael@0: do_check_eq(parsedURIs.length, 1); michael@0: michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_valid_relative2, URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: dump(parsedURIs.length); michael@0: do_check_in_array(parsedURIs, uri_valid_relative2_expanded); michael@0: do_check_eq(parsedURIs.length, 1); michael@0: michael@0: // make sure cross-scheme reporting works michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_other_scheme_absolute, URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: dump(parsedURIs.length); michael@0: do_check_in_array(parsedURIs, uri_other_scheme_absolute); michael@0: do_check_eq(parsedURIs.length, 1); michael@0: michael@0: // make sure cross-scheme, cross-host reporting works michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_other_scheme_and_host_absolute, URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: dump(parsedURIs.length); michael@0: do_check_in_array(parsedURIs, uri_other_scheme_and_host_absolute); michael@0: do_check_eq(parsedURIs.length, 1); michael@0: michael@0: // combination! michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + michael@0: uri_valid_relative2 + " " + michael@0: uri_valid_absolute, URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: do_check_in_array(parsedURIs, uri_valid_relative2_expanded); michael@0: do_check_in_array(parsedURIs, uri_valid_absolute); michael@0: do_check_eq(parsedURIs.length, 2); michael@0: michael@0: cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + michael@0: uri_valid_relative2 + " " + michael@0: uri_other_host_absolute + " " + michael@0: uri_valid_absolute, URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: do_check_in_array(parsedURIs, uri_valid_relative2_expanded); michael@0: do_check_in_array(parsedURIs, uri_other_host_absolute); michael@0: do_check_in_array(parsedURIs, uri_valid_absolute); michael@0: do_check_eq(parsedURIs.length, 3); michael@0: }); michael@0: michael@0: test( michael@0: function test_bug634778_duplicateDirective_Detection() { michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_OLD; michael@0: var self = "http://self.com:34"; michael@0: var firstDomain = "http://first.com"; michael@0: var secondDomain = "http://second.com"; michael@0: var thirdDomain = "http://third.com"; michael@0: michael@0: // check for duplicate "default-src" directives michael@0: cspr = CSPRep.fromString("default-src " + self + "; default-src " + michael@0: firstDomain, URI(self)); michael@0: do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); michael@0: do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC)); michael@0: michael@0: // check for duplicate "allow" directives michael@0: cspr = CSPRep.fromString("allow " + self + "; allow " + firstDomain, michael@0: URI(self)); michael@0: do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); michael@0: do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC)); michael@0: michael@0: // check for duplicate "allow" + "default-src" directives michael@0: cspr = CSPRep.fromString("allow " + self + "; default-src " + firstDomain, michael@0: URI(self)); michael@0: do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); michael@0: do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC)); michael@0: michael@0: // check for duplicate report-uri directives michael@0: cspr = CSPRep.fromString("allow *; report-uri " + self + "/report.py; report-uri " michael@0: + firstDomain + "/report.py", URI(self)); michael@0: parsedURIs = cspr.getReportURIs().split(/\s+/); michael@0: do_check_in_array(parsedURIs, self + "/report.py"); michael@0: do_check_eq(parsedURIs.length, 1); michael@0: michael@0: // check for three directives with duplicates michael@0: cspr = CSPRep.fromString("img-src " + firstDomain + "; default-src " + self michael@0: + "; img-src " + secondDomain, URI(self)); michael@0: do_check_true(cspr.permits(firstDomain, SD.IMG_SRC)); michael@0: do_check_false(cspr.permits(secondDomain, SD.IMG_SRC)); michael@0: do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); michael@0: michael@0: // check for three directives with duplicates michael@0: cspr = CSPRep.fromString("img-src " + firstDomain + "; default-src " + self michael@0: + "; img-src " + secondDomain, URI(self)); michael@0: do_check_true(cspr.permits(firstDomain, SD.IMG_SRC)); michael@0: do_check_false(cspr.permits(secondDomain, SD.IMG_SRC)); michael@0: michael@0: // check for three directives with duplicates michael@0: cspr = CSPRep.fromString("default-src " + self + "; img-src " + firstDomain michael@0: + "; img-src " + secondDomain, URI(self)); michael@0: do_check_true(cspr.permits(firstDomain, SD.IMG_SRC)); michael@0: do_check_false(cspr.permits(secondDomain, SD.IMG_SRC)); michael@0: michael@0: // check for four directives with duplicates michael@0: cspr = CSPRep.fromString("default-src " + self + "; img-src " + firstDomain michael@0: + "; img-src " + secondDomain + "; img-src " michael@0: + thirdDomain, URI(self)); michael@0: do_check_true(cspr.permits(firstDomain, SD.IMG_SRC)); michael@0: do_check_false(cspr.permits(secondDomain, SD.IMG_SRC)); michael@0: do_check_false(cspr.permits(thirdDomain, SD.IMG_SRC)); michael@0: michael@0: // check for four directives with two duplicates michael@0: cspr = CSPRep.fromString("default-src " + self + "; style-src " michael@0: + firstDomain + "; media-src " + firstDomain michael@0: + "; media-src " + secondDomain + "; style-src " michael@0: + thirdDomain, URI(self)); michael@0: do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); michael@0: do_check_true(cspr.permits(firstDomain, SD.STYLE_SRC)); michael@0: do_check_true(cspr.permits(firstDomain, SD.MEDIA_SRC)); michael@0: do_check_false(cspr.permits(secondDomain, SD.MEDIA_SRC)); michael@0: do_check_false(cspr.permits(thirdDomain, SD.STYLE_SRC)); michael@0: }); michael@0: michael@0: test( michael@0: function test_bug672961_withNonstandardSelfPort() { michael@0: /** michael@0: * When a protected document has a non-standard port, other host names michael@0: * listed as sources should inherit the scheme of the protected document michael@0: * but NOT the port. Other hosts should use the default port for the michael@0: * inherited scheme. For example, since 443 is default for HTTPS: michael@0: * michael@0: * Document with CSP: https://foobar.com:4443 michael@0: * Transmitted policy: michael@0: * "allow 'self' a.com" michael@0: * Explicit policy: michael@0: * "allow https://foobar.com:4443 https://a.com:443" michael@0: * michael@0: * This test examines scheme and nonstandard port inheritance. michael@0: */ michael@0: michael@0: var src; michael@0: src = CSPSource.create("a.com", undefined, "https://foobar.com:4443"); michael@0: //"src should inherit and require https scheme michael@0: do_check_false(src.permits("http://a.com")); michael@0: //"src should inherit scheme 'https'" michael@0: do_check_true(src.permits("https://a.com")); michael@0: //"src should get default port michael@0: do_check_true(src.permits("https://a.com:443")); michael@0: michael@0: src = CSPSource.create("http://a.com", undefined, "https://foobar.com:4443"); michael@0: //"src should require http scheme" michael@0: do_check_false(src.permits("https://a.com")); michael@0: //"src should keep scheme 'http'" michael@0: do_check_true(src.permits("http://a.com")); michael@0: //"src should inherit default port for 'http'" michael@0: do_check_true(src.permits("http://a.com:80")); michael@0: michael@0: src = CSPSource.create("'self'", undefined, "https://foobar.com:4443"); michael@0: //"src should inherit nonstandard port from self michael@0: do_check_true(src.permits("https://foobar.com:4443")); michael@0: do_check_false(src.permits("https://foobar.com")); michael@0: do_check_false(src.permits("https://foobar.com:443")); michael@0: michael@0: //"src should inherit and require https scheme from self michael@0: do_check_false(src.permits("http://foobar.com:4443")); michael@0: do_check_false(src.permits("http://foobar.com")); michael@0: michael@0: }); michael@0: michael@0: test( michael@0: function test_bug634773_noneAndStarAreDifferent() { michael@0: /** michael@0: * Bug 634773 is that allow * and allow 'none' end up "equal" via michael@0: * CSPSourceList.prototype.equals(), which is wrong. This tests that michael@0: * doesn't happen. michael@0: */ michael@0: michael@0: var p_none = CSPSourceList.fromString("'none'", undefined, "http://foo.com", false); michael@0: var p_all = CSPSourceList.fromString("*", undefined, "http://foo.com", false); michael@0: var p_one = CSPSourceList.fromString("bar.com", undefined, "http://foo.com", false); michael@0: michael@0: do_check_false(p_none.equals(p_all)); michael@0: do_check_false(p_none.equals(p_one)); michael@0: do_check_false(p_all.equals(p_none)); michael@0: do_check_false(p_all.equals(p_one)); michael@0: michael@0: do_check_true(p_all.permits("http://bar.com")); michael@0: do_check_true(p_one.permits("http://bar.com")); michael@0: do_check_false(p_none.permits("http://bar.com")); michael@0: }); michael@0: michael@0: michael@0: test( michael@0: function test_bug764937_defaultSrcMissing() { michael@0: var cspObjSpecCompliant = Cc["@mozilla.org/contentsecuritypolicy;1"] michael@0: .createInstance(Ci.nsIContentSecurityPolicy); michael@0: var cspObjOld = Cc["@mozilla.org/contentsecuritypolicy;1"] michael@0: .createInstance(Ci.nsIContentSecurityPolicy); michael@0: var selfURI = URI("http://self.com/"); michael@0: michael@0: function testPermits(cspObj, aUri, aContentType) { michael@0: return cspObj.shouldLoad(aContentType, aUri, null, null, null, null) michael@0: == Ci.nsIContentPolicy.ACCEPT; michael@0: }; michael@0: michael@0: const policy = "script-src 'self'"; michael@0: cspObjSpecCompliant.appendPolicy(policy, selfURI, false, true); michael@0: michael@0: // Spec-Compliant policy default-src defaults to *. michael@0: // This means all images are allowed, and only 'self' michael@0: // script is allowed. michael@0: do_check_true(testPermits(cspObjSpecCompliant, michael@0: URI("http://bar.com/foo.png"), michael@0: Ci.nsIContentPolicy.TYPE_IMAGE)); michael@0: do_check_true(testPermits(cspObjSpecCompliant, michael@0: URI("http://self.com/foo.png"), michael@0: Ci.nsIContentPolicy.TYPE_IMAGE)); michael@0: do_check_true(testPermits(cspObjSpecCompliant, michael@0: URI("http://self.com/foo.js"), michael@0: Ci.nsIContentPolicy.TYPE_SCRIPT)); michael@0: do_check_false(testPermits(cspObjSpecCompliant, michael@0: URI("http://bar.com/foo.js"), michael@0: Ci.nsIContentPolicy.TYPE_SCRIPT)); michael@0: michael@0: cspObjOld.appendPolicy(policy, selfURI, false, false); michael@0: michael@0: // non-Spec-Compliant policy default-src defaults to 'none' michael@0: // This means all images are blocked, and so are all scripts (because the michael@0: // policy is ignored and fails closed). michael@0: do_check_false(testPermits(cspObjOld, michael@0: URI("http://bar.com/foo.png"), michael@0: Ci.nsIContentPolicy.TYPE_IMAGE)); michael@0: do_check_false(testPermits(cspObjOld, michael@0: URI("http://self.com/foo.png"), michael@0: Ci.nsIContentPolicy.TYPE_IMAGE)); michael@0: do_check_false(testPermits(cspObjOld, michael@0: URI("http://self.com/foo.js"), michael@0: Ci.nsIContentPolicy.TYPE_SCRIPT)); michael@0: do_check_false(testPermits(cspObjOld, michael@0: URI("http://bar.com/foo.js"), michael@0: Ci.nsIContentPolicy.TYPE_SCRIPT)); michael@0: michael@0: }); michael@0: michael@0: test(function test_equals_does_case_insensitive_comparison() { michael@0: // NOTE: For scheme, host and keyword-host: michael@0: // (1) compare the same lower-case in two distinct objects michael@0: // (2) compare upper-case with lower-case inputs michael@0: // to test case insensitivity. michael@0: michael@0: // CSPSource equals ignores case michael@0: var upperCaseHost = "http://FOO.COM"; michael@0: var lowerCaseHost = "http://foo.com"; michael@0: src1 = CSPSource.fromString(lowerCaseHost); michael@0: src2 = CSPSource.fromString(lowerCaseHost); michael@0: do_check_true(src1.equals(src2)) michael@0: src3 = CSPSource.fromString(upperCaseHost); michael@0: do_check_true(src1.equals(src3)) michael@0: michael@0: // CSPHost equals ignores case michael@0: var upperCaseScheme = "HTTP"; michael@0: var lowerCaseScheme = "http"; michael@0: src1 = CSPHost.fromString(lowerCaseScheme); michael@0: src2 = CSPHost.fromString(lowerCaseScheme); michael@0: do_check_true(src1.equals(src2)); michael@0: src3 = CSPHost.fromString(upperCaseScheme); michael@0: do_check_true(src1.equals(src3)); michael@0: michael@0: // CSPSourceList equals (mainly for testing keywords) michael@0: var upperCaseKeywords = "'SELF'"; michael@0: var lowerCaseKeywords = "'self'"; michael@0: src1 = CSPSourceList.fromString(lowerCaseKeywords); michael@0: src2 = CSPSourceList.fromString(lowerCaseKeywords); michael@0: do_check_true(src1.equals(src2)) michael@0: src3 = CSPSourceList.fromString(upperCaseKeywords); michael@0: do_check_true(src1.equals(src3)) michael@0: michael@0: }); michael@0: michael@0: test(function test_csp_permits_case_insensitive() { michael@0: var cspr; michael@0: var SD = CSPRep.SRC_DIRECTIVES_NEW; michael@0: michael@0: // checks directives can be case-insensitive michael@0: var selfHost = "http://self.com"; michael@0: var testPolicy1 = "DEFAULT-src 'self';"; michael@0: cspr = CSPRep.fromString(testPolicy1, URI(selfHost)); michael@0: do_check_true(cspr.permits(URI("http://self.com"), SD.DEFAULT_SRC)); michael@0: michael@0: // checks hosts can be case-insensitive michael@0: var testPolicy2 = "default-src 'self' http://FOO.COM"; michael@0: cspr = CSPRep.fromString(testPolicy2, URI(selfHost)); michael@0: do_check_true(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC)); michael@0: michael@0: // checks schemes can be case-insensitive michael@0: var testPolicy3 = "default-src 'self' HTTP://foo.com"; michael@0: cspr = CSPRep.fromString(testPolicy3, URI(selfHost)); michael@0: do_check_true(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC)); michael@0: michael@0: // checks keywords can be case-insensitive michael@0: var testPolicy4 = "default-src 'NONE'"; michael@0: cspr = CSPRep.fromString(testPolicy4, URI(selfHost)); michael@0: do_check_false(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC)); michael@0: }); michael@0: /* michael@0: michael@0: test(function test_CSPRep_fromPolicyURI_failswhenmixed() { michael@0: var cspr; michael@0: var self = "http://localhost:" + POLICY_PORT; michael@0: var closed_policy = CSPRep.fromString("allow 'none'"); michael@0: var my_uri_policy = "policy-uri " + POLICY_URI; michael@0: michael@0: //print(" --- Ignore the following two errors if they print ---"); michael@0: cspr = CSPRep.fromString("allow *; " + my_uri_policy, URI(self)); michael@0: michael@0: //"Parsing should fail when 'policy-uri' is mixed with allow directive" michael@0: do_check_equivalent(cspr, closed_policy); michael@0: cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, URI(self)); michael@0: michael@0: //"Parsing should fail when 'policy-uri' is mixed with other directives" michael@0: do_check_equivalent(cspr, closed_policy); michael@0: //print(" --- Stop ignoring errors that print ---\n"); michael@0: michael@0: }); michael@0: */ michael@0: michael@0: // TODO: test reporting michael@0: // TODO: test refinements (?) michael@0: // TODO: test 'eval' and 'inline' keywords michael@0: michael@0: function run_test() { michael@0: function policyresponder(request,response) { michael@0: response.setStatusLine(request.httpVersion, 200, "OK"); michael@0: response.setHeader("Content-Type", "text/csp", false); michael@0: response.bodyOutputStream.write(POLICY_FROM_URI, POLICY_FROM_URI.length); michael@0: } michael@0: //server.registerDirectory("/", nsILocalFileForBasePath); michael@0: httpServer.registerPathHandler("/policy", policyresponder); michael@0: michael@0: for(let i in tests) { michael@0: tests[i](); michael@0: } michael@0: michael@0: //teardown michael@0: httpServer.stop(function() { }); michael@0: do_test_finished(); michael@0: } michael@0: michael@0: michael@0: