Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | const Cc = Components.classes; |
michael@0 | 6 | const Ci = Components.interfaces; |
michael@0 | 7 | const Cu = Components.utils; |
michael@0 | 8 | const Cr = Components.results; |
michael@0 | 9 | |
michael@0 | 10 | //load('CSPUtils.jsm'); |
michael@0 | 11 | Cu.import('resource://gre/modules/CSPUtils.jsm'); |
michael@0 | 12 | Cu.import('resource://gre/modules/NetUtil.jsm'); |
michael@0 | 13 | |
michael@0 | 14 | var httpServer = new HttpServer(); |
michael@0 | 15 | httpServer.start(-1); |
michael@0 | 16 | |
michael@0 | 17 | const POLICY_FROM_URI = "default-src 'self'; img-src *"; |
michael@0 | 18 | const POLICY_PORT = httpServer.identity.primaryPort; |
michael@0 | 19 | const POLICY_URI = "http://localhost:" + POLICY_PORT + "/policy"; |
michael@0 | 20 | const POLICY_URI_RELATIVE = "/policy"; |
michael@0 | 21 | |
michael@0 | 22 | //converts string to nsIURI |
michael@0 | 23 | function URI(uriString) { |
michael@0 | 24 | var ioService = Cc["@mozilla.org/network/io-service;1"] |
michael@0 | 25 | .getService(Ci.nsIIOService); |
michael@0 | 26 | return ioService.newURI(uriString, null, null); |
michael@0 | 27 | } |
michael@0 | 28 | |
michael@0 | 29 | |
michael@0 | 30 | // helper to assert that an array has the given value somewhere. |
michael@0 | 31 | function do_check_in_array(arr, val, stack) { |
michael@0 | 32 | if (!stack) |
michael@0 | 33 | stack = Components.stack.caller; |
michael@0 | 34 | |
michael@0 | 35 | var text = val + " in [" + arr.join(",") + "]"; |
michael@0 | 36 | |
michael@0 | 37 | for(var i in arr) { |
michael@0 | 38 | dump(".......... " + i + "> " + arr[i] + "\n"); |
michael@0 | 39 | if(arr[i] == val) { |
michael@0 | 40 | //succeed |
michael@0 | 41 | ++_passedChecks; |
michael@0 | 42 | dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " + |
michael@0 | 43 | stack.lineNumber + "] " + text + "\n"); |
michael@0 | 44 | return; |
michael@0 | 45 | } |
michael@0 | 46 | } |
michael@0 | 47 | do_throw(text, stack); |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | // helper to assert that an object or array must have a given key |
michael@0 | 51 | function do_check_has_key(foo, key, stack) { |
michael@0 | 52 | if (!stack) |
michael@0 | 53 | stack = Components.stack.caller; |
michael@0 | 54 | |
michael@0 | 55 | var keys = []; |
michael@0 | 56 | for (let k in foo) { keys.push(k); } |
michael@0 | 57 | var text = key + " in [" + keys.join(",") + "]"; |
michael@0 | 58 | |
michael@0 | 59 | for (var x in foo) { |
michael@0 | 60 | if (x == key) { |
michael@0 | 61 | //succeed |
michael@0 | 62 | ++_passedChecks; |
michael@0 | 63 | dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " + |
michael@0 | 64 | stack.lineNumber + "] " + text + "\n"); |
michael@0 | 65 | return; |
michael@0 | 66 | } |
michael@0 | 67 | } |
michael@0 | 68 | do_throw(text, stack); |
michael@0 | 69 | } |
michael@0 | 70 | |
michael@0 | 71 | // helper to use .equals on stuff |
michael@0 | 72 | function do_check_equivalent(foo, bar, stack) { |
michael@0 | 73 | if (!stack) |
michael@0 | 74 | stack = Components.stack.caller; |
michael@0 | 75 | |
michael@0 | 76 | var text = foo + ".equals(" + bar + ")"; |
michael@0 | 77 | |
michael@0 | 78 | if(foo.equals && foo.equals(bar)) { |
michael@0 | 79 | ++_passedChecks; |
michael@0 | 80 | dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " + |
michael@0 | 81 | stack.lineNumber + "] " + text + "\n"); |
michael@0 | 82 | return; |
michael@0 | 83 | } |
michael@0 | 84 | do_throw(text, stack); |
michael@0 | 85 | } |
michael@0 | 86 | |
michael@0 | 87 | var tests = []; |
michael@0 | 88 | function test(fcn) { |
michael@0 | 89 | tests.push(fcn); |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | test( |
michael@0 | 93 | function test_CSPHost_fromstring() { |
michael@0 | 94 | var h; |
michael@0 | 95 | |
michael@0 | 96 | h = CSPHost.fromString("*"); |
michael@0 | 97 | do_check_neq(null, h); // "* lone wildcard should work" |
michael@0 | 98 | |
michael@0 | 99 | h = CSPHost.fromString("foo.bar"); |
michael@0 | 100 | do_check_neq(null, h); // "standard tuple failed" |
michael@0 | 101 | |
michael@0 | 102 | h = CSPHost.fromString("*.bar"); |
michael@0 | 103 | do_check_neq(null, h); // "wildcard failed" |
michael@0 | 104 | |
michael@0 | 105 | h = CSPHost.fromString("foo.*.bar"); |
michael@0 | 106 | do_check_eq(null, h); // "wildcard in wrong place worked" |
michael@0 | 107 | |
michael@0 | 108 | h = CSPHost.fromString("com"); |
michael@0 | 109 | do_check_neq(null, h); // "lone symbol should not fail" |
michael@0 | 110 | |
michael@0 | 111 | h = CSPHost.fromString("f00b4r.com"); |
michael@0 | 112 | do_check_neq(null, h); // "Numbers in hosts should work" |
michael@0 | 113 | |
michael@0 | 114 | h = CSPHost.fromString("foo-bar.com"); |
michael@0 | 115 | do_check_neq(null, h); // "dashes in hosts should work" |
michael@0 | 116 | |
michael@0 | 117 | |
michael@0 | 118 | h = CSPHost.fromString("foo!bar.com"); |
michael@0 | 119 | do_check_eq(null, h); // "special chars in hosts should fail" |
michael@0 | 120 | |
michael@0 | 121 | h = CSPHost.fromString("{app-url-is-uid}"); |
michael@0 | 122 | do_check_neq(null, h); // "Packaged apps URLs failed" |
michael@0 | 123 | }); |
michael@0 | 124 | |
michael@0 | 125 | test( |
michael@0 | 126 | function test_CSPHost_clone() { |
michael@0 | 127 | h = CSPHost.fromString("*.a.b.c"); |
michael@0 | 128 | h2 = h.clone(); |
michael@0 | 129 | for(var i in h._segments) { |
michael@0 | 130 | // "cloned segments should match" |
michael@0 | 131 | do_check_eq(h._segments[i], h2._segments[i]); |
michael@0 | 132 | } |
michael@0 | 133 | }); |
michael@0 | 134 | |
michael@0 | 135 | test( |
michael@0 | 136 | function test_CSPHost_permits() { |
michael@0 | 137 | var h = CSPHost.fromString("*.b.c"); |
michael@0 | 138 | var h2 = CSPHost.fromString("a.b.c"); |
michael@0 | 139 | do_check_true( h.permits(h2)); //"CSPHost *.b.c should allow CSPHost a.b.c" |
michael@0 | 140 | do_check_true( h.permits("a.b.c")); //"CSPHost *.b.c should allow string a.b.c" |
michael@0 | 141 | do_check_false(h.permits("b.c")); //"CSPHost *.b.c should not allow string b.c" |
michael@0 | 142 | do_check_false(h.permits("a.a.c")); //"CSPHost *.b.c should not allow string a.a.c" |
michael@0 | 143 | do_check_false(h2.permits(h)); //"CSPHost a.b.c should not allow CSPHost *.b.c" |
michael@0 | 144 | do_check_false(h2.permits("b.c")); //"CSPHost a.b.c should not allow string b.c" |
michael@0 | 145 | do_check_true( h2.permits("a.b.c")); //"CSPHost a.b.c should allow string a.b.c" |
michael@0 | 146 | }); |
michael@0 | 147 | |
michael@0 | 148 | |
michael@0 | 149 | ///////////////////// Test the Source object ////////////////////// |
michael@0 | 150 | |
michael@0 | 151 | test( |
michael@0 | 152 | function test_CSPSource_fromString() { |
michael@0 | 153 | // can't do these tests because "self" is not defined. |
michael@0 | 154 | //"basic source should not be null."); |
michael@0 | 155 | do_check_neq(null, CSPSource.fromString("a.com", undefined, "http://abc.com")); |
michael@0 | 156 | |
michael@0 | 157 | //"ldh characters should all work for host."); |
michael@0 | 158 | do_check_neq(null, CSPSource.fromString("a2-c.com", undefined, "https://a.com")); |
michael@0 | 159 | |
michael@0 | 160 | //"wildcard should work in first token for host."); |
michael@0 | 161 | do_check_neq(null, CSPSource.fromString("*.a.com", undefined, "http://abc.com")); |
michael@0 | 162 | |
michael@0 | 163 | //print(" --- Ignore the following two errors if they print ---"); |
michael@0 | 164 | //"wildcard should not work in non-first token for host."); |
michael@0 | 165 | do_check_eq(null, CSPSource.fromString("x.*.a.com", undefined, "http://a.com")); |
michael@0 | 166 | |
michael@0 | 167 | //"funny characters (#) should not work for host."); |
michael@0 | 168 | do_check_eq(null, CSPSource.fromString("a#2-c.com", undefined, "http://a.com")); |
michael@0 | 169 | |
michael@0 | 170 | //print(" --- Stop ignoring errors that print ---\n"); |
michael@0 | 171 | |
michael@0 | 172 | //"failed to parse host with port."); |
michael@0 | 173 | do_check_neq(null, CSPSource.create("a.com:23", undefined, "http://a.com")); |
michael@0 | 174 | //"failed to parse host with scheme."); |
michael@0 | 175 | do_check_neq(null, CSPSource.create("https://a.com", undefined, "http://a.com")); |
michael@0 | 176 | //"failed to parse host with scheme and port."); |
michael@0 | 177 | do_check_neq(null, CSPSource.create("https://a.com:200", undefined, "http://a.com")); |
michael@0 | 178 | |
michael@0 | 179 | //Check to make sure we don't match multiple instances with regex |
michael@0 | 180 | do_check_eq(null, CSPSource.create("http://foo.com:bar.com:23")); |
michael@0 | 181 | //Port parsing should work for all schemes |
michael@0 | 182 | do_check_neq(null, CSPSource.create("data:")); |
michael@0 | 183 | do_check_neq(null, CSPSource.create("javascript:")); |
michael@0 | 184 | |
michael@0 | 185 | //"app:// URLs should work, including the {} characters."); |
michael@0 | 186 | do_check_neq(null, CSPSource.fromString("{app-host-is-uid}", undefined, "app://{app-host-is-uid}")); |
michael@0 | 187 | }); |
michael@0 | 188 | |
michael@0 | 189 | test( |
michael@0 | 190 | function test_CSPSource_fromString_withSelf() { |
michael@0 | 191 | var src; |
michael@0 | 192 | src = CSPSource.create("a.com", undefined, "https://foobar.com:443"); |
michael@0 | 193 | //"src should inherit port * |
michael@0 | 194 | do_check_true(src.permits("https://a.com:443")); |
michael@0 | 195 | //"src should inherit and require https scheme |
michael@0 | 196 | do_check_false(src.permits("http://a.com")); |
michael@0 | 197 | //"src should inherit scheme 'https'" |
michael@0 | 198 | do_check_true(src.permits("https://a.com")); |
michael@0 | 199 | |
michael@0 | 200 | src = CSPSource.create("http://a.com", undefined, "https://foobar.com:443"); |
michael@0 | 201 | //"src should inherit and require http scheme" |
michael@0 | 202 | do_check_false(src.permits("https://a.com")); |
michael@0 | 203 | //"src should inherit scheme 'http'" |
michael@0 | 204 | do_check_true(src.permits("http://a.com")); |
michael@0 | 205 | //"src should inherit port and scheme from parent" |
michael@0 | 206 | //"src should inherit default port for 'http'" |
michael@0 | 207 | do_check_true(src.permits("http://a.com:80")); |
michael@0 | 208 | |
michael@0 | 209 | src = CSPSource.create("'self'", undefined, "https://foobar.com:443"); |
michael@0 | 210 | //"src should inherit port * |
michael@0 | 211 | do_check_true(src.permits("https://foobar.com:443")); |
michael@0 | 212 | //"src should inherit and require https scheme |
michael@0 | 213 | do_check_false(src.permits("http://foobar.com")); |
michael@0 | 214 | //"src should inherit scheme 'https'" |
michael@0 | 215 | do_check_true(src.permits("https://foobar.com")); |
michael@0 | 216 | //"src should reject other hosts" |
michael@0 | 217 | do_check_false(src.permits("https://a.com")); |
michael@0 | 218 | |
michael@0 | 219 | src = CSPSource.create("javascript:", undefined, "https://foobar.com:443"); |
michael@0 | 220 | //"hostless schemes should be parseable." |
michael@0 | 221 | var aUri = NetUtil.newURI("javascript:alert('foo');"); |
michael@0 | 222 | do_check_true(src.permits(aUri)); |
michael@0 | 223 | //"src should reject other hosts" |
michael@0 | 224 | do_check_false(src.permits("https://a.com")); |
michael@0 | 225 | //"nothing else should be allowed" |
michael@0 | 226 | do_check_false(src.permits("https://foobar.com")); |
michael@0 | 227 | |
michael@0 | 228 | src = CSPSource.create("{app-host-is-uid}", undefined, "app://{app-host-is-uid}"); |
michael@0 | 229 | //"src should inherit and require 'app' scheme" |
michael@0 | 230 | do_check_false(src.permits("https://{app-host-is-uid}")); |
michael@0 | 231 | //"src should inherit scheme 'app'" |
michael@0 | 232 | do_check_true(src.permits("app://{app-host-is-uid}")); |
michael@0 | 233 | |
michael@0 | 234 | }); |
michael@0 | 235 | |
michael@0 | 236 | ///////////////////// Test the source list ////////////////////// |
michael@0 | 237 | |
michael@0 | 238 | test( |
michael@0 | 239 | function test_CSPSourceList_fromString() { |
michael@0 | 240 | var sd = CSPSourceList.fromString("'none'"); |
michael@0 | 241 | //"'none' -- should parse" |
michael@0 | 242 | do_check_neq(null,sd); |
michael@0 | 243 | // "'none' should be a zero-length list" |
michael@0 | 244 | do_check_eq(0, sd._sources.length); |
michael@0 | 245 | do_check_true(sd.isNone()); |
michael@0 | 246 | |
michael@0 | 247 | sd = CSPSourceList.fromString("*"); |
michael@0 | 248 | //"'*' should be a zero-length list" |
michael@0 | 249 | do_check_eq(0, sd._sources.length); |
michael@0 | 250 | |
michael@0 | 251 | //print(" --- Ignore the following three errors if they print ---"); |
michael@0 | 252 | //"funny char in host" |
michael@0 | 253 | do_check_true(CSPSourceList.fromString("f!oo.bar").isNone()); |
michael@0 | 254 | //"funny char in scheme" |
michael@0 | 255 | do_check_true(CSPSourceList.fromString("ht!ps://f-oo.bar").isNone()); |
michael@0 | 256 | //"funny char in port" |
michael@0 | 257 | do_check_true(CSPSourceList.fromString("https://f-oo.bar:3f").isNone()); |
michael@0 | 258 | //print(" --- Stop ignoring errors that print ---\n"); |
michael@0 | 259 | }); |
michael@0 | 260 | |
michael@0 | 261 | test( |
michael@0 | 262 | function test_CSPSourceList_fromString_twohost() { |
michael@0 | 263 | var str = "foo.bar:21 https://ras.bar"; |
michael@0 | 264 | var parsed = "http://foo.bar:21 https://ras.bar:443"; |
michael@0 | 265 | var sd = CSPSourceList.fromString(str, undefined, URI("http://self.com:80")); |
michael@0 | 266 | //"two-host list should parse" |
michael@0 | 267 | do_check_neq(null,sd); |
michael@0 | 268 | //"two-host list should parse to two hosts" |
michael@0 | 269 | do_check_eq(2, sd._sources.length); |
michael@0 | 270 | //"two-host list should contain original data" |
michael@0 | 271 | do_check_eq(parsed, sd.toString()); |
michael@0 | 272 | }); |
michael@0 | 273 | |
michael@0 | 274 | test( |
michael@0 | 275 | function test_CSPSourceList_permits() { |
michael@0 | 276 | var nullSourceList = CSPSourceList.fromString("'none'"); |
michael@0 | 277 | var simpleSourceList = CSPSourceList.fromString("a.com", undefined, URI("http://self.com")); |
michael@0 | 278 | var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88", |
michael@0 | 279 | undefined, |
michael@0 | 280 | URI("http://self.com:88")); |
michael@0 | 281 | var allSourceList = CSPSourceList.fromString("*"); |
michael@0 | 282 | var allAndMoreSourceList = CSPSourceList.fromString("* https://bar.com 'none'"); |
michael@0 | 283 | var wildcardHostSourceList = CSPSourceList.fromString("*.foo.com", |
michael@0 | 284 | undefined, URI("http://self.com")); |
michael@0 | 285 | var allDoubledHostSourceList = CSPSourceList.fromString("**"); |
michael@0 | 286 | var allGarbageHostSourceList = CSPSourceList.fromString("*a"); |
michael@0 | 287 | |
michael@0 | 288 | //'none' should permit none." |
michael@0 | 289 | do_check_false( nullSourceList.permits("http://a.com")); |
michael@0 | 290 | //a.com should permit a.com" |
michael@0 | 291 | do_check_true( simpleSourceList.permits("http://a.com")); |
michael@0 | 292 | //wrong host" |
michael@0 | 293 | do_check_false( simpleSourceList.permits("http://b.com")); |
michael@0 | 294 | //double list permits http://bar.com:88" |
michael@0 | 295 | do_check_true( doubleSourceList.permits("http://bar.com:88")); |
michael@0 | 296 | //double list permits https://bar.com:88" |
michael@0 | 297 | do_check_false( doubleSourceList.permits("https://bar.com:88")); |
michael@0 | 298 | //double list does not permit http://bar.com:443" |
michael@0 | 299 | do_check_false( doubleSourceList.permits("http://bar.com:443")); |
michael@0 | 300 | //"double list permits https://foo.com:88" (should not inherit port) |
michael@0 | 301 | do_check_false( doubleSourceList.permits("https://foo.com:88")); |
michael@0 | 302 | //"double list does not permit foo.com on http" |
michael@0 | 303 | do_check_false( doubleSourceList.permits("http://foo.com")); |
michael@0 | 304 | |
michael@0 | 305 | //"* does not permit specific host" |
michael@0 | 306 | do_check_true( allSourceList.permits("http://x.com:23")); |
michael@0 | 307 | //"* does not permit a long host with no port" |
michael@0 | 308 | do_check_true( allSourceList.permits("http://a.b.c.d.e.f.g.h.i.j.k.l.x.com")); |
michael@0 | 309 | |
michael@0 | 310 | //* short circuts parsing |
michael@0 | 311 | do_check_true(allAndMoreSourceList.permits("http://a.com")); |
michael@0 | 312 | |
michael@0 | 313 | //"** permits all" |
michael@0 | 314 | do_check_false(allDoubledHostSourceList.permits("http://barbaz.com")); |
michael@0 | 315 | //"*a permits all" |
michael@0 | 316 | do_check_false(allGarbageHostSourceList.permits("http://barbaz.com")); |
michael@0 | 317 | |
michael@0 | 318 | //"*.foo.com does not permit somerandom.foo.com" |
michael@0 | 319 | do_check_true(wildcardHostSourceList.permits("http://somerandom.foo.com")); |
michael@0 | 320 | //"*.foo.com permits all" |
michael@0 | 321 | do_check_false(wildcardHostSourceList.permits("http://barbaz.com")); |
michael@0 | 322 | }); |
michael@0 | 323 | |
michael@0 | 324 | ///////////////////// Test the Whole CSP rep object ////////////////////// |
michael@0 | 325 | |
michael@0 | 326 | test( |
michael@0 | 327 | function test_CSPRep_fromString() { |
michael@0 | 328 | |
michael@0 | 329 | // check default init |
michael@0 | 330 | //ASSERT(!(new CSPRep())._isInitialized, "Uninitialized rep thinks it is.") |
michael@0 | 331 | |
michael@0 | 332 | var cspr; |
michael@0 | 333 | var cspr_allowval; |
michael@0 | 334 | var SD = CSPRep.SRC_DIRECTIVES_OLD; |
michael@0 | 335 | |
michael@0 | 336 | // check default policy "allow *" |
michael@0 | 337 | cspr = CSPRep.fromString("allow *", URI("http://self.com:80")); |
michael@0 | 338 | // "DEFAULT_SRC directive is missing when specified in fromString" |
michael@0 | 339 | do_check_has_key(cspr._directives, SD.DEFAULT_SRC); |
michael@0 | 340 | |
michael@0 | 341 | }); |
michael@0 | 342 | |
michael@0 | 343 | |
michael@0 | 344 | test( |
michael@0 | 345 | function test_CSPRep_defaultSrc() { |
michael@0 | 346 | var cspr, cspr_default_val, cspr_allow; |
michael@0 | 347 | var SD = CSPRep.SRC_DIRECTIVES_OLD; |
michael@0 | 348 | |
michael@0 | 349 | // apply policy of "default-src *" (e.g. "allow *") |
michael@0 | 350 | cspr = CSPRep.fromString("default-src *", URI("http://self.com:80")); |
michael@0 | 351 | // "DEFAULT_SRC directive is missing when specified in fromString" |
michael@0 | 352 | do_check_has_key(cspr._directives, SD.DEFAULT_SRC); |
michael@0 | 353 | |
michael@0 | 354 | // check that |allow *| and |default-src *| are parsed equivalently and |
michael@0 | 355 | // result in the same set of explicit policy directives |
michael@0 | 356 | cspr = CSPRep.fromString("default-src *", URI("http://self.com:80")); |
michael@0 | 357 | cspr_allow = CSPRep.fromString("allow *", URI("http://self.com:80")); |
michael@0 | 358 | |
michael@0 | 359 | do_check_equivalent(cspr._directives['default-src'], |
michael@0 | 360 | cspr_allow._directives['default-src']); |
michael@0 | 361 | }); |
michael@0 | 362 | |
michael@0 | 363 | |
michael@0 | 364 | test( |
michael@0 | 365 | function test_CSPRep_fromString_oneDir() { |
michael@0 | 366 | |
michael@0 | 367 | var cspr; |
michael@0 | 368 | var SD = CSPRep.SRC_DIRECTIVES_OLD; |
michael@0 | 369 | var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, SD.FRAME_SRC]; |
michael@0 | 370 | |
michael@0 | 371 | // check one-directive policies |
michael@0 | 372 | cspr = CSPRep.fromString("allow bar.com; script-src https://foo.com", |
michael@0 | 373 | URI("http://self.com")); |
michael@0 | 374 | |
michael@0 | 375 | for(var x in DEFAULTS) { |
michael@0 | 376 | //DEFAULTS[x] + " does not use default rule." |
michael@0 | 377 | do_check_false(cspr.permits("http://bar.com:22", DEFAULTS[x])); |
michael@0 | 378 | //DEFAULTS[x] + " does not use default rule." |
michael@0 | 379 | do_check_true(cspr.permits("http://bar.com:80", DEFAULTS[x])); |
michael@0 | 380 | //DEFAULTS[x] + " does not use default rule." |
michael@0 | 381 | do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x])); |
michael@0 | 382 | //DEFAULTS[x] + " does not use default rule." |
michael@0 | 383 | do_check_false(cspr.permits("https://foo.com", DEFAULTS[x])); |
michael@0 | 384 | } |
michael@0 | 385 | //"script-src false positive in policy. |
michael@0 | 386 | do_check_false(cspr.permits("http://bar.com:22", SD.SCRIPT_SRC)); |
michael@0 | 387 | //"script-src false negative in policy. |
michael@0 | 388 | do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC)); |
michael@0 | 389 | }); |
michael@0 | 390 | |
michael@0 | 391 | test( |
michael@0 | 392 | function test_CSPRep_fromString_twodir() { |
michael@0 | 393 | var cspr; |
michael@0 | 394 | var SD = CSPRep.SRC_DIRECTIVES_OLD; |
michael@0 | 395 | var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_SRC]; |
michael@0 | 396 | |
michael@0 | 397 | // check two-directive policies |
michael@0 | 398 | var polstr = "allow allow.com; " |
michael@0 | 399 | + "script-src https://foo.com; " |
michael@0 | 400 | + "img-src bar.com:*"; |
michael@0 | 401 | cspr = CSPRep.fromString(polstr, URI("http://self.com")); |
michael@0 | 402 | |
michael@0 | 403 | for(var x in DEFAULTS) { |
michael@0 | 404 | do_check_true(cspr.permits("http://allow.com", DEFAULTS[x])); |
michael@0 | 405 | //DEFAULTS[x] + " does not use default rule. |
michael@0 | 406 | do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x])); |
michael@0 | 407 | //DEFAULTS[x] + " does not use default rule. |
michael@0 | 408 | do_check_false(cspr.permits("http://bar.com:400", DEFAULTS[x])); |
michael@0 | 409 | //DEFAULTS[x] + " does not use default rule. |
michael@0 | 410 | } |
michael@0 | 411 | //"img-src does not use default rule. |
michael@0 | 412 | do_check_false(cspr.permits("http://allow.com:22", SD.IMG_SRC)); |
michael@0 | 413 | //"img-src does not use default rule. |
michael@0 | 414 | do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC)); |
michael@0 | 415 | //"img-src does not use default rule. |
michael@0 | 416 | do_check_true(cspr.permits("http://bar.com:88", SD.IMG_SRC)); |
michael@0 | 417 | |
michael@0 | 418 | //"script-src does not use default rule. |
michael@0 | 419 | do_check_false(cspr.permits("http://allow.com:22", SD.SCRIPT_SRC)); |
michael@0 | 420 | //"script-src does not use default rule. |
michael@0 | 421 | do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC)); |
michael@0 | 422 | //"script-src does not use default rule. |
michael@0 | 423 | do_check_false(cspr.permits("http://bar.com:400", SD.SCRIPT_SRC)); |
michael@0 | 424 | }); |
michael@0 | 425 | |
michael@0 | 426 | test(function test_CSPRep_fromString_withself() { |
michael@0 | 427 | var cspr; |
michael@0 | 428 | var SD = CSPRep.SRC_DIRECTIVES_OLD; |
michael@0 | 429 | var self = "https://self.com:34"; |
michael@0 | 430 | |
michael@0 | 431 | // check one-directive policies |
michael@0 | 432 | cspr = CSPRep.fromString("allow 'self'; script-src 'self' https://*:*", |
michael@0 | 433 | URI(self)); |
michael@0 | 434 | //"img-src does not enforce default rule, 'self'. |
michael@0 | 435 | do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC)); |
michael@0 | 436 | //"img-src does not allow self |
michael@0 | 437 | do_check_true(cspr.permits(self, SD.IMG_SRC)); |
michael@0 | 438 | //"script-src is too relaxed |
michael@0 | 439 | do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC)); |
michael@0 | 440 | //"script-src should allow self |
michael@0 | 441 | do_check_true(cspr.permits(self, SD.SCRIPT_SRC)); |
michael@0 | 442 | //"script-src is too strict on host/port |
michael@0 | 443 | do_check_true(cspr.permits("https://evil.com:100", SD.SCRIPT_SRC)); |
michael@0 | 444 | }); |
michael@0 | 445 | |
michael@0 | 446 | |
michael@0 | 447 | //////////////// TEST CSP REP SPEC COMPLIANT PARSER //////////// |
michael@0 | 448 | test( |
michael@0 | 449 | function test_CSPRep_fromStringSpecCompliant() { |
michael@0 | 450 | |
michael@0 | 451 | var cspr; |
michael@0 | 452 | var cspr_allowval; |
michael@0 | 453 | var SD = CSPRep.SRC_DIRECTIVES_NEW; |
michael@0 | 454 | var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, SD.SCRIPT_SRC, SD.FONT_SRC, |
michael@0 | 455 | SD.OBJECT_SRC, SD.FRAME_SRC, SD.CONNECT_SRC]; |
michael@0 | 456 | |
michael@0 | 457 | // check default policy "default-src *" |
michael@0 | 458 | cspr = CSPRep.fromStringSpecCompliant("default-src *", URI("http://self.com:80")); |
michael@0 | 459 | // "DEFAULT_SRC directive is missing when specified in |
michael@0 | 460 | // fromStringSpecCompliant" |
michael@0 | 461 | do_check_has_key(cspr._directives, SD.DEFAULT_SRC); |
michael@0 | 462 | |
michael@0 | 463 | for(var x in DEFAULTS) { |
michael@0 | 464 | // each of these should be equivalent to DEFAULT_SRC |
michael@0 | 465 | //DEFAULTS[x] + " does not use default rule." |
michael@0 | 466 | do_check_true(cspr.permits("http://bar.com", DEFAULTS[x])); |
michael@0 | 467 | } |
michael@0 | 468 | }); |
michael@0 | 469 | |
michael@0 | 470 | |
michael@0 | 471 | test( |
michael@0 | 472 | function test_CSPRep_fromStringSpecCompliant_oneDir() { |
michael@0 | 473 | |
michael@0 | 474 | var cspr; |
michael@0 | 475 | var SD = CSPRep.SRC_DIRECTIVES_NEW; |
michael@0 | 476 | var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, |
michael@0 | 477 | SD.FRAME_SRC, SD.CONNECT_SRC]; |
michael@0 | 478 | |
michael@0 | 479 | // check one-directive policies |
michael@0 | 480 | cspr = CSPRep.fromStringSpecCompliant("default-src bar.com; script-src https://foo.com", |
michael@0 | 481 | URI("http://self.com")); |
michael@0 | 482 | |
michael@0 | 483 | for(var x in DEFAULTS) { |
michael@0 | 484 | //DEFAULTS[x] + " does not use default rule." |
michael@0 | 485 | do_check_false(cspr.permits("http://bar.com:22", DEFAULTS[x])); |
michael@0 | 486 | //DEFAULTS[x] + " does not use default rule." |
michael@0 | 487 | do_check_true(cspr.permits("http://bar.com:80", DEFAULTS[x])); |
michael@0 | 488 | //DEFAULTS[x] + " does not use default rule." |
michael@0 | 489 | do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x])); |
michael@0 | 490 | //DEFAULTS[x] + " does not use default rule." |
michael@0 | 491 | do_check_false(cspr.permits("https://foo.com", DEFAULTS[x])); |
michael@0 | 492 | } |
michael@0 | 493 | //"script-src false positive in policy. |
michael@0 | 494 | do_check_false(cspr.permits("http://bar.com:22", SD.SCRIPT_SRC)); |
michael@0 | 495 | //"script-src false negative in policy. |
michael@0 | 496 | do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC)); |
michael@0 | 497 | }); |
michael@0 | 498 | |
michael@0 | 499 | test( |
michael@0 | 500 | function test_CSPRep_fromStringSpecCompliant_twodir() { |
michael@0 | 501 | var cspr; |
michael@0 | 502 | |
michael@0 | 503 | var SD = CSPRep.SRC_DIRECTIVES_NEW; |
michael@0 | 504 | |
michael@0 | 505 | var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_SRC, |
michael@0 | 506 | SD.CONNECT_SRC]; |
michael@0 | 507 | |
michael@0 | 508 | // check two-directive policies |
michael@0 | 509 | var polstr = "default-src allow.com; " + |
michael@0 | 510 | "script-src https://foo.com; " + |
michael@0 | 511 | "img-src bar.com:*"; |
michael@0 | 512 | cspr = CSPRep.fromStringSpecCompliant(polstr, URI("http://self.com")); |
michael@0 | 513 | |
michael@0 | 514 | for(var x in DEFAULTS) { |
michael@0 | 515 | do_check_true(cspr.permits("http://allow.com", DEFAULTS[x])); |
michael@0 | 516 | //DEFAULTS[x] + " does not use default rule. |
michael@0 | 517 | do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x])); |
michael@0 | 518 | //DEFAULTS[x] + " does not use default rule. |
michael@0 | 519 | do_check_false(cspr.permits("http://bar.com:400", DEFAULTS[x])); |
michael@0 | 520 | //DEFAULTS[x] + " does not use default rule. |
michael@0 | 521 | } |
michael@0 | 522 | //"img-src does not use default rule. |
michael@0 | 523 | do_check_false(cspr.permits("http://allow.com:22", SD.IMG_SRC)); |
michael@0 | 524 | //"img-src does not use default rule. |
michael@0 | 525 | do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC)); |
michael@0 | 526 | //"img-src does not use default rule. |
michael@0 | 527 | do_check_true(cspr.permits("http://bar.com:88", SD.IMG_SRC)); |
michael@0 | 528 | |
michael@0 | 529 | //"script-src does not use default rule. |
michael@0 | 530 | do_check_false(cspr.permits("http://allow.com:22", SD.SCRIPT_SRC)); |
michael@0 | 531 | //"script-src does not use default rule. |
michael@0 | 532 | do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC)); |
michael@0 | 533 | //"script-src does not use default rule. |
michael@0 | 534 | do_check_false(cspr.permits("http://bar.com:400", SD.SCRIPT_SRC)); |
michael@0 | 535 | }); |
michael@0 | 536 | |
michael@0 | 537 | test(function test_CSPRep_fromStringSpecCompliant_withself() { |
michael@0 | 538 | var cspr; |
michael@0 | 539 | var self = "https://self.com:34"; |
michael@0 | 540 | var SD = CSPRep.SRC_DIRECTIVES_NEW; |
michael@0 | 541 | |
michael@0 | 542 | // check one-directive policies |
michael@0 | 543 | cspr = CSPRep.fromStringSpecCompliant("default-src 'self'; script-src 'self' https://*:*", |
michael@0 | 544 | URI(self)); |
michael@0 | 545 | //"img-src does not enforce default rule, 'self'. |
michael@0 | 546 | do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC)); |
michael@0 | 547 | //"img-src does not allow self |
michael@0 | 548 | do_check_true(cspr.permits(self, SD.IMG_SRC)); |
michael@0 | 549 | //"script-src is too relaxed |
michael@0 | 550 | do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC)); |
michael@0 | 551 | //"script-src should allow self |
michael@0 | 552 | do_check_true(cspr.permits(self, SD.SCRIPT_SRC)); |
michael@0 | 553 | //"script-src is too strict on host/port |
michael@0 | 554 | do_check_true(cspr.permits("https://evil.com:100", SD.SCRIPT_SRC)); |
michael@0 | 555 | }); |
michael@0 | 556 | |
michael@0 | 557 | |
michael@0 | 558 | //////////////// TEST FRAME ANCESTOR DEFAULTS ///////////////// |
michael@0 | 559 | // (see bug 555068) |
michael@0 | 560 | test(function test_FrameAncestor_defaults() { |
michael@0 | 561 | var cspr; |
michael@0 | 562 | var SD = CSPRep.SRC_DIRECTIVES_OLD; |
michael@0 | 563 | var self = "http://self.com:34"; |
michael@0 | 564 | |
michael@0 | 565 | cspr = CSPRep.fromString("allow 'none'", URI(self)); |
michael@0 | 566 | |
michael@0 | 567 | //"frame-ancestors should default to * not 'allow' value" |
michael@0 | 568 | do_check_true(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS)); |
michael@0 | 569 | do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 570 | do_check_true(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 571 | do_check_true(cspr.permits("http://self.com", SD.FRAME_ANCESTORS)); |
michael@0 | 572 | do_check_true(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 573 | |
michael@0 | 574 | cspr = CSPRep.fromString("allow 'none'; frame-ancestors 'self'", URI(self)); |
michael@0 | 575 | |
michael@0 | 576 | //"frame-ancestors should only allow self" |
michael@0 | 577 | do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 578 | do_check_false(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS)); |
michael@0 | 579 | do_check_false(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 580 | do_check_false(cspr.permits("http://self.com", SD.FRAME_ANCESTORS)); |
michael@0 | 581 | do_check_false(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 582 | }); |
michael@0 | 583 | |
michael@0 | 584 | test(function test_FrameAncestor_defaults_specCompliant() { |
michael@0 | 585 | var cspr; |
michael@0 | 586 | var self = "http://self.com:34"; |
michael@0 | 587 | var SD = CSPRep.SRC_DIRECTIVES_NEW; |
michael@0 | 588 | |
michael@0 | 589 | cspr = CSPRep.fromStringSpecCompliant("default-src 'none'", URI(self)); |
michael@0 | 590 | |
michael@0 | 591 | //"frame-ancestors should default to * not 'default-src' value" |
michael@0 | 592 | do_check_true(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS)); |
michael@0 | 593 | do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 594 | do_check_true(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 595 | do_check_true(cspr.permits("http://self.com", SD.FRAME_ANCESTORS)); |
michael@0 | 596 | do_check_true(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 597 | |
michael@0 | 598 | cspr = CSPRep.fromStringSpecCompliant("default-src 'none'; frame-ancestors 'self'", URI(self)); |
michael@0 | 599 | |
michael@0 | 600 | //"frame-ancestors should only allow self" |
michael@0 | 601 | do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 602 | do_check_false(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS)); |
michael@0 | 603 | do_check_false(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 604 | do_check_false(cspr.permits("http://self.com", SD.FRAME_ANCESTORS)); |
michael@0 | 605 | do_check_false(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS)); |
michael@0 | 606 | }); |
michael@0 | 607 | |
michael@0 | 608 | |
michael@0 | 609 | test(function test_FrameAncestor_TLD_defaultPorts() { |
michael@0 | 610 | var cspr; |
michael@0 | 611 | var SD = CSPRep.SRC_DIRECTIVES_OLD; |
michael@0 | 612 | var self = "http://self"; //TLD only, no .com or anything. |
michael@0 | 613 | |
michael@0 | 614 | cspr = CSPRep.fromString("allow 'self'; frame-ancestors 'self' http://foo:80 bar:80 http://three", URI(self)); |
michael@0 | 615 | |
michael@0 | 616 | //"frame-ancestors should default to * not 'allow' value" |
michael@0 | 617 | do_check_true(cspr.permits("http://self", SD.FRAME_ANCESTORS)); |
michael@0 | 618 | do_check_true(cspr.permits("http://self:80", SD.FRAME_ANCESTORS)); |
michael@0 | 619 | do_check_true(cspr.permits("http://foo", SD.FRAME_ANCESTORS)); |
michael@0 | 620 | do_check_true(cspr.permits("http://foo:80", SD.FRAME_ANCESTORS)); |
michael@0 | 621 | do_check_true(cspr.permits("http://bar", SD.FRAME_ANCESTORS)); |
michael@0 | 622 | do_check_true(cspr.permits("http://three:80", SD.FRAME_ANCESTORS)); |
michael@0 | 623 | |
michael@0 | 624 | do_check_false(cspr.permits("https://foo:400", SD.FRAME_ANCESTORS)); |
michael@0 | 625 | do_check_false(cspr.permits("https://self:34", SD.FRAME_ANCESTORS)); |
michael@0 | 626 | do_check_false(cspr.permits("https://bar", SD.FRAME_ANCESTORS)); |
michael@0 | 627 | do_check_false(cspr.permits("http://three:81", SD.FRAME_ANCESTORS)); |
michael@0 | 628 | do_check_false(cspr.permits("https://three:81", SD.FRAME_ANCESTORS)); |
michael@0 | 629 | }); |
michael@0 | 630 | |
michael@0 | 631 | test(function test_FrameAncestor_ignores_userpass_bug779918() { |
michael@0 | 632 | var cspr; |
michael@0 | 633 | var SD = CSPRep.SRC_DIRECTIVES_OLD; |
michael@0 | 634 | var self = "http://self.com/bar"; |
michael@0 | 635 | var testPolicy = "default-src 'self'; frame-ancestors 'self'"; |
michael@0 | 636 | |
michael@0 | 637 | cspr = CSPRep.fromString(testPolicy, URI(self)); |
michael@0 | 638 | |
michael@0 | 639 | // wrapped in URI() because of source parsing |
michael@0 | 640 | do_check_true(cspr.permits(URI("http://username:password@self.com/foo"), SD.FRAME_ANCESTORS)); |
michael@0 | 641 | do_check_true(cspr.permits(URI("http://other:pass1@self.com/foo"), SD.FRAME_ANCESTORS)); |
michael@0 | 642 | do_check_true(cspr.permits(URI("http://self.com:80/foo"), SD.FRAME_ANCESTORS)); |
michael@0 | 643 | do_check_true(cspr.permits(URI("http://self.com/foo"), SD.FRAME_ANCESTORS)); |
michael@0 | 644 | |
michael@0 | 645 | // construct fake ancestry with CSP applied to the child. |
michael@0 | 646 | // [aChildUri] -> [aParentUri] -> (root/top) |
michael@0 | 647 | // and then test "permitsAncestry" on the child/self docshell. |
michael@0 | 648 | function testPermits(aChildUri, aParentUri, aContentType) { |
michael@0 | 649 | let cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"] |
michael@0 | 650 | .createInstance(Ci.nsIContentSecurityPolicy); |
michael@0 | 651 | cspObj.appendPolicy(testPolicy, aChildUri, false, false); |
michael@0 | 652 | let docshellparent = Cc["@mozilla.org/docshell;1"] |
michael@0 | 653 | .createInstance(Ci.nsIDocShell); |
michael@0 | 654 | let docshellchild = Cc["@mozilla.org/docshell;1"] |
michael@0 | 655 | .createInstance(Ci.nsIDocShell); |
michael@0 | 656 | docshellparent.setCurrentURI(aParentUri); |
michael@0 | 657 | docshellchild.setCurrentURI(aChildUri); |
michael@0 | 658 | docshellparent.addChild(docshellchild); |
michael@0 | 659 | return cspObj.permitsAncestry(docshellchild); |
michael@0 | 660 | }; |
michael@0 | 661 | |
michael@0 | 662 | // check parent without userpass |
michael@0 | 663 | do_check_true(testPermits(URI("http://username:password@self.com/foo"), |
michael@0 | 664 | URI("http://self.com/bar"))); |
michael@0 | 665 | do_check_true(testPermits(URI("http://user1:pass1@self.com/foo"), |
michael@0 | 666 | URI("http://self.com/bar"))); |
michael@0 | 667 | do_check_true(testPermits(URI("http://self.com/foo"), |
michael@0 | 668 | URI("http://self.com/bar"))); |
michael@0 | 669 | |
michael@0 | 670 | // check parent with userpass |
michael@0 | 671 | do_check_true(testPermits(URI("http://username:password@self.com/foo"), |
michael@0 | 672 | URI("http://username:password@self.com/bar"))); |
michael@0 | 673 | do_check_true(testPermits(URI("http://user1:pass1@self.com/foo"), |
michael@0 | 674 | URI("http://username:password@self.com/bar"))); |
michael@0 | 675 | do_check_true(testPermits(URI("http://self.com/foo"), |
michael@0 | 676 | URI("http://username:password@self.com/bar"))); |
michael@0 | 677 | }); |
michael@0 | 678 | |
michael@0 | 679 | test(function test_CSP_ReportURI_parsing() { |
michael@0 | 680 | var cspr; |
michael@0 | 681 | var SD = CSPRep.SRC_DIRECTIVES_NEW; |
michael@0 | 682 | var self = "http://self.com:34"; |
michael@0 | 683 | var parsedURIs = []; |
michael@0 | 684 | |
michael@0 | 685 | var uri_valid_absolute = self + "/report.py"; |
michael@0 | 686 | var uri_other_host_absolute = "http://foo.org:34/report.py"; |
michael@0 | 687 | var uri_valid_relative = "/report.py"; |
michael@0 | 688 | var uri_valid_relative_expanded = self + uri_valid_relative; |
michael@0 | 689 | var uri_valid_relative2 = "foo/bar/report.py"; |
michael@0 | 690 | var uri_valid_relative2_expanded = self + "/" + uri_valid_relative2; |
michael@0 | 691 | var uri_invalid_relative = "javascript:alert(1)"; |
michael@0 | 692 | var uri_other_scheme_absolute = "https://self.com/report.py"; |
michael@0 | 693 | var uri_other_scheme_and_host_absolute = "https://foo.com/report.py"; |
michael@0 | 694 | |
michael@0 | 695 | cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_valid_absolute, URI(self)); |
michael@0 | 696 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 697 | do_check_in_array(parsedURIs, uri_valid_absolute); |
michael@0 | 698 | do_check_eq(parsedURIs.length, 1); |
michael@0 | 699 | |
michael@0 | 700 | cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_other_host_absolute, URI(self)); |
michael@0 | 701 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 702 | do_check_in_array(parsedURIs, uri_other_host_absolute); |
michael@0 | 703 | do_check_eq(parsedURIs.length, 1); // the empty string is in there. |
michael@0 | 704 | |
michael@0 | 705 | cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_invalid_relative, URI(self)); |
michael@0 | 706 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 707 | do_check_in_array(parsedURIs, ""); |
michael@0 | 708 | do_check_eq(parsedURIs.length, 1); |
michael@0 | 709 | |
michael@0 | 710 | cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_valid_relative, URI(self)); |
michael@0 | 711 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 712 | do_check_in_array(parsedURIs, uri_valid_relative_expanded); |
michael@0 | 713 | do_check_eq(parsedURIs.length, 1); |
michael@0 | 714 | |
michael@0 | 715 | cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_valid_relative2, URI(self)); |
michael@0 | 716 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 717 | dump(parsedURIs.length); |
michael@0 | 718 | do_check_in_array(parsedURIs, uri_valid_relative2_expanded); |
michael@0 | 719 | do_check_eq(parsedURIs.length, 1); |
michael@0 | 720 | |
michael@0 | 721 | // make sure cross-scheme reporting works |
michael@0 | 722 | cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_other_scheme_absolute, URI(self)); |
michael@0 | 723 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 724 | dump(parsedURIs.length); |
michael@0 | 725 | do_check_in_array(parsedURIs, uri_other_scheme_absolute); |
michael@0 | 726 | do_check_eq(parsedURIs.length, 1); |
michael@0 | 727 | |
michael@0 | 728 | // make sure cross-scheme, cross-host reporting works |
michael@0 | 729 | cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + uri_other_scheme_and_host_absolute, URI(self)); |
michael@0 | 730 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 731 | dump(parsedURIs.length); |
michael@0 | 732 | do_check_in_array(parsedURIs, uri_other_scheme_and_host_absolute); |
michael@0 | 733 | do_check_eq(parsedURIs.length, 1); |
michael@0 | 734 | |
michael@0 | 735 | // combination! |
michael@0 | 736 | cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + |
michael@0 | 737 | uri_valid_relative2 + " " + |
michael@0 | 738 | uri_valid_absolute, URI(self)); |
michael@0 | 739 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 740 | do_check_in_array(parsedURIs, uri_valid_relative2_expanded); |
michael@0 | 741 | do_check_in_array(parsedURIs, uri_valid_absolute); |
michael@0 | 742 | do_check_eq(parsedURIs.length, 2); |
michael@0 | 743 | |
michael@0 | 744 | cspr = CSPRep.fromStringSpecCompliant("default-src *; report-uri " + |
michael@0 | 745 | uri_valid_relative2 + " " + |
michael@0 | 746 | uri_other_host_absolute + " " + |
michael@0 | 747 | uri_valid_absolute, URI(self)); |
michael@0 | 748 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 749 | do_check_in_array(parsedURIs, uri_valid_relative2_expanded); |
michael@0 | 750 | do_check_in_array(parsedURIs, uri_other_host_absolute); |
michael@0 | 751 | do_check_in_array(parsedURIs, uri_valid_absolute); |
michael@0 | 752 | do_check_eq(parsedURIs.length, 3); |
michael@0 | 753 | }); |
michael@0 | 754 | |
michael@0 | 755 | test( |
michael@0 | 756 | function test_bug634778_duplicateDirective_Detection() { |
michael@0 | 757 | var cspr; |
michael@0 | 758 | var SD = CSPRep.SRC_DIRECTIVES_OLD; |
michael@0 | 759 | var self = "http://self.com:34"; |
michael@0 | 760 | var firstDomain = "http://first.com"; |
michael@0 | 761 | var secondDomain = "http://second.com"; |
michael@0 | 762 | var thirdDomain = "http://third.com"; |
michael@0 | 763 | |
michael@0 | 764 | // check for duplicate "default-src" directives |
michael@0 | 765 | cspr = CSPRep.fromString("default-src " + self + "; default-src " + |
michael@0 | 766 | firstDomain, URI(self)); |
michael@0 | 767 | do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); |
michael@0 | 768 | do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC)); |
michael@0 | 769 | |
michael@0 | 770 | // check for duplicate "allow" directives |
michael@0 | 771 | cspr = CSPRep.fromString("allow " + self + "; allow " + firstDomain, |
michael@0 | 772 | URI(self)); |
michael@0 | 773 | do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); |
michael@0 | 774 | do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC)); |
michael@0 | 775 | |
michael@0 | 776 | // check for duplicate "allow" + "default-src" directives |
michael@0 | 777 | cspr = CSPRep.fromString("allow " + self + "; default-src " + firstDomain, |
michael@0 | 778 | URI(self)); |
michael@0 | 779 | do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); |
michael@0 | 780 | do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC)); |
michael@0 | 781 | |
michael@0 | 782 | // check for duplicate report-uri directives |
michael@0 | 783 | cspr = CSPRep.fromString("allow *; report-uri " + self + "/report.py; report-uri " |
michael@0 | 784 | + firstDomain + "/report.py", URI(self)); |
michael@0 | 785 | parsedURIs = cspr.getReportURIs().split(/\s+/); |
michael@0 | 786 | do_check_in_array(parsedURIs, self + "/report.py"); |
michael@0 | 787 | do_check_eq(parsedURIs.length, 1); |
michael@0 | 788 | |
michael@0 | 789 | // check for three directives with duplicates |
michael@0 | 790 | cspr = CSPRep.fromString("img-src " + firstDomain + "; default-src " + self |
michael@0 | 791 | + "; img-src " + secondDomain, URI(self)); |
michael@0 | 792 | do_check_true(cspr.permits(firstDomain, SD.IMG_SRC)); |
michael@0 | 793 | do_check_false(cspr.permits(secondDomain, SD.IMG_SRC)); |
michael@0 | 794 | do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); |
michael@0 | 795 | |
michael@0 | 796 | // check for three directives with duplicates |
michael@0 | 797 | cspr = CSPRep.fromString("img-src " + firstDomain + "; default-src " + self |
michael@0 | 798 | + "; img-src " + secondDomain, URI(self)); |
michael@0 | 799 | do_check_true(cspr.permits(firstDomain, SD.IMG_SRC)); |
michael@0 | 800 | do_check_false(cspr.permits(secondDomain, SD.IMG_SRC)); |
michael@0 | 801 | |
michael@0 | 802 | // check for three directives with duplicates |
michael@0 | 803 | cspr = CSPRep.fromString("default-src " + self + "; img-src " + firstDomain |
michael@0 | 804 | + "; img-src " + secondDomain, URI(self)); |
michael@0 | 805 | do_check_true(cspr.permits(firstDomain, SD.IMG_SRC)); |
michael@0 | 806 | do_check_false(cspr.permits(secondDomain, SD.IMG_SRC)); |
michael@0 | 807 | |
michael@0 | 808 | // check for four directives with duplicates |
michael@0 | 809 | cspr = CSPRep.fromString("default-src " + self + "; img-src " + firstDomain |
michael@0 | 810 | + "; img-src " + secondDomain + "; img-src " |
michael@0 | 811 | + thirdDomain, URI(self)); |
michael@0 | 812 | do_check_true(cspr.permits(firstDomain, SD.IMG_SRC)); |
michael@0 | 813 | do_check_false(cspr.permits(secondDomain, SD.IMG_SRC)); |
michael@0 | 814 | do_check_false(cspr.permits(thirdDomain, SD.IMG_SRC)); |
michael@0 | 815 | |
michael@0 | 816 | // check for four directives with two duplicates |
michael@0 | 817 | cspr = CSPRep.fromString("default-src " + self + "; style-src " |
michael@0 | 818 | + firstDomain + "; media-src " + firstDomain |
michael@0 | 819 | + "; media-src " + secondDomain + "; style-src " |
michael@0 | 820 | + thirdDomain, URI(self)); |
michael@0 | 821 | do_check_true(cspr.permits(self, SD.DEFAULT_SRC)); |
michael@0 | 822 | do_check_true(cspr.permits(firstDomain, SD.STYLE_SRC)); |
michael@0 | 823 | do_check_true(cspr.permits(firstDomain, SD.MEDIA_SRC)); |
michael@0 | 824 | do_check_false(cspr.permits(secondDomain, SD.MEDIA_SRC)); |
michael@0 | 825 | do_check_false(cspr.permits(thirdDomain, SD.STYLE_SRC)); |
michael@0 | 826 | }); |
michael@0 | 827 | |
michael@0 | 828 | test( |
michael@0 | 829 | function test_bug672961_withNonstandardSelfPort() { |
michael@0 | 830 | /** |
michael@0 | 831 | * When a protected document has a non-standard port, other host names |
michael@0 | 832 | * listed as sources should inherit the scheme of the protected document |
michael@0 | 833 | * but NOT the port. Other hosts should use the default port for the |
michael@0 | 834 | * inherited scheme. For example, since 443 is default for HTTPS: |
michael@0 | 835 | * |
michael@0 | 836 | * Document with CSP: https://foobar.com:4443 |
michael@0 | 837 | * Transmitted policy: |
michael@0 | 838 | * "allow 'self' a.com" |
michael@0 | 839 | * Explicit policy: |
michael@0 | 840 | * "allow https://foobar.com:4443 https://a.com:443" |
michael@0 | 841 | * |
michael@0 | 842 | * This test examines scheme and nonstandard port inheritance. |
michael@0 | 843 | */ |
michael@0 | 844 | |
michael@0 | 845 | var src; |
michael@0 | 846 | src = CSPSource.create("a.com", undefined, "https://foobar.com:4443"); |
michael@0 | 847 | //"src should inherit and require https scheme |
michael@0 | 848 | do_check_false(src.permits("http://a.com")); |
michael@0 | 849 | //"src should inherit scheme 'https'" |
michael@0 | 850 | do_check_true(src.permits("https://a.com")); |
michael@0 | 851 | //"src should get default port |
michael@0 | 852 | do_check_true(src.permits("https://a.com:443")); |
michael@0 | 853 | |
michael@0 | 854 | src = CSPSource.create("http://a.com", undefined, "https://foobar.com:4443"); |
michael@0 | 855 | //"src should require http scheme" |
michael@0 | 856 | do_check_false(src.permits("https://a.com")); |
michael@0 | 857 | //"src should keep scheme 'http'" |
michael@0 | 858 | do_check_true(src.permits("http://a.com")); |
michael@0 | 859 | //"src should inherit default port for 'http'" |
michael@0 | 860 | do_check_true(src.permits("http://a.com:80")); |
michael@0 | 861 | |
michael@0 | 862 | src = CSPSource.create("'self'", undefined, "https://foobar.com:4443"); |
michael@0 | 863 | //"src should inherit nonstandard port from self |
michael@0 | 864 | do_check_true(src.permits("https://foobar.com:4443")); |
michael@0 | 865 | do_check_false(src.permits("https://foobar.com")); |
michael@0 | 866 | do_check_false(src.permits("https://foobar.com:443")); |
michael@0 | 867 | |
michael@0 | 868 | //"src should inherit and require https scheme from self |
michael@0 | 869 | do_check_false(src.permits("http://foobar.com:4443")); |
michael@0 | 870 | do_check_false(src.permits("http://foobar.com")); |
michael@0 | 871 | |
michael@0 | 872 | }); |
michael@0 | 873 | |
michael@0 | 874 | test( |
michael@0 | 875 | function test_bug634773_noneAndStarAreDifferent() { |
michael@0 | 876 | /** |
michael@0 | 877 | * Bug 634773 is that allow * and allow 'none' end up "equal" via |
michael@0 | 878 | * CSPSourceList.prototype.equals(), which is wrong. This tests that |
michael@0 | 879 | * doesn't happen. |
michael@0 | 880 | */ |
michael@0 | 881 | |
michael@0 | 882 | var p_none = CSPSourceList.fromString("'none'", undefined, "http://foo.com", false); |
michael@0 | 883 | var p_all = CSPSourceList.fromString("*", undefined, "http://foo.com", false); |
michael@0 | 884 | var p_one = CSPSourceList.fromString("bar.com", undefined, "http://foo.com", false); |
michael@0 | 885 | |
michael@0 | 886 | do_check_false(p_none.equals(p_all)); |
michael@0 | 887 | do_check_false(p_none.equals(p_one)); |
michael@0 | 888 | do_check_false(p_all.equals(p_none)); |
michael@0 | 889 | do_check_false(p_all.equals(p_one)); |
michael@0 | 890 | |
michael@0 | 891 | do_check_true(p_all.permits("http://bar.com")); |
michael@0 | 892 | do_check_true(p_one.permits("http://bar.com")); |
michael@0 | 893 | do_check_false(p_none.permits("http://bar.com")); |
michael@0 | 894 | }); |
michael@0 | 895 | |
michael@0 | 896 | |
michael@0 | 897 | test( |
michael@0 | 898 | function test_bug764937_defaultSrcMissing() { |
michael@0 | 899 | var cspObjSpecCompliant = Cc["@mozilla.org/contentsecuritypolicy;1"] |
michael@0 | 900 | .createInstance(Ci.nsIContentSecurityPolicy); |
michael@0 | 901 | var cspObjOld = Cc["@mozilla.org/contentsecuritypolicy;1"] |
michael@0 | 902 | .createInstance(Ci.nsIContentSecurityPolicy); |
michael@0 | 903 | var selfURI = URI("http://self.com/"); |
michael@0 | 904 | |
michael@0 | 905 | function testPermits(cspObj, aUri, aContentType) { |
michael@0 | 906 | return cspObj.shouldLoad(aContentType, aUri, null, null, null, null) |
michael@0 | 907 | == Ci.nsIContentPolicy.ACCEPT; |
michael@0 | 908 | }; |
michael@0 | 909 | |
michael@0 | 910 | const policy = "script-src 'self'"; |
michael@0 | 911 | cspObjSpecCompliant.appendPolicy(policy, selfURI, false, true); |
michael@0 | 912 | |
michael@0 | 913 | // Spec-Compliant policy default-src defaults to *. |
michael@0 | 914 | // This means all images are allowed, and only 'self' |
michael@0 | 915 | // script is allowed. |
michael@0 | 916 | do_check_true(testPermits(cspObjSpecCompliant, |
michael@0 | 917 | URI("http://bar.com/foo.png"), |
michael@0 | 918 | Ci.nsIContentPolicy.TYPE_IMAGE)); |
michael@0 | 919 | do_check_true(testPermits(cspObjSpecCompliant, |
michael@0 | 920 | URI("http://self.com/foo.png"), |
michael@0 | 921 | Ci.nsIContentPolicy.TYPE_IMAGE)); |
michael@0 | 922 | do_check_true(testPermits(cspObjSpecCompliant, |
michael@0 | 923 | URI("http://self.com/foo.js"), |
michael@0 | 924 | Ci.nsIContentPolicy.TYPE_SCRIPT)); |
michael@0 | 925 | do_check_false(testPermits(cspObjSpecCompliant, |
michael@0 | 926 | URI("http://bar.com/foo.js"), |
michael@0 | 927 | Ci.nsIContentPolicy.TYPE_SCRIPT)); |
michael@0 | 928 | |
michael@0 | 929 | cspObjOld.appendPolicy(policy, selfURI, false, false); |
michael@0 | 930 | |
michael@0 | 931 | // non-Spec-Compliant policy default-src defaults to 'none' |
michael@0 | 932 | // This means all images are blocked, and so are all scripts (because the |
michael@0 | 933 | // policy is ignored and fails closed). |
michael@0 | 934 | do_check_false(testPermits(cspObjOld, |
michael@0 | 935 | URI("http://bar.com/foo.png"), |
michael@0 | 936 | Ci.nsIContentPolicy.TYPE_IMAGE)); |
michael@0 | 937 | do_check_false(testPermits(cspObjOld, |
michael@0 | 938 | URI("http://self.com/foo.png"), |
michael@0 | 939 | Ci.nsIContentPolicy.TYPE_IMAGE)); |
michael@0 | 940 | do_check_false(testPermits(cspObjOld, |
michael@0 | 941 | URI("http://self.com/foo.js"), |
michael@0 | 942 | Ci.nsIContentPolicy.TYPE_SCRIPT)); |
michael@0 | 943 | do_check_false(testPermits(cspObjOld, |
michael@0 | 944 | URI("http://bar.com/foo.js"), |
michael@0 | 945 | Ci.nsIContentPolicy.TYPE_SCRIPT)); |
michael@0 | 946 | |
michael@0 | 947 | }); |
michael@0 | 948 | |
michael@0 | 949 | test(function test_equals_does_case_insensitive_comparison() { |
michael@0 | 950 | // NOTE: For scheme, host and keyword-host: |
michael@0 | 951 | // (1) compare the same lower-case in two distinct objects |
michael@0 | 952 | // (2) compare upper-case with lower-case inputs |
michael@0 | 953 | // to test case insensitivity. |
michael@0 | 954 | |
michael@0 | 955 | // CSPSource equals ignores case |
michael@0 | 956 | var upperCaseHost = "http://FOO.COM"; |
michael@0 | 957 | var lowerCaseHost = "http://foo.com"; |
michael@0 | 958 | src1 = CSPSource.fromString(lowerCaseHost); |
michael@0 | 959 | src2 = CSPSource.fromString(lowerCaseHost); |
michael@0 | 960 | do_check_true(src1.equals(src2)) |
michael@0 | 961 | src3 = CSPSource.fromString(upperCaseHost); |
michael@0 | 962 | do_check_true(src1.equals(src3)) |
michael@0 | 963 | |
michael@0 | 964 | // CSPHost equals ignores case |
michael@0 | 965 | var upperCaseScheme = "HTTP"; |
michael@0 | 966 | var lowerCaseScheme = "http"; |
michael@0 | 967 | src1 = CSPHost.fromString(lowerCaseScheme); |
michael@0 | 968 | src2 = CSPHost.fromString(lowerCaseScheme); |
michael@0 | 969 | do_check_true(src1.equals(src2)); |
michael@0 | 970 | src3 = CSPHost.fromString(upperCaseScheme); |
michael@0 | 971 | do_check_true(src1.equals(src3)); |
michael@0 | 972 | |
michael@0 | 973 | // CSPSourceList equals (mainly for testing keywords) |
michael@0 | 974 | var upperCaseKeywords = "'SELF'"; |
michael@0 | 975 | var lowerCaseKeywords = "'self'"; |
michael@0 | 976 | src1 = CSPSourceList.fromString(lowerCaseKeywords); |
michael@0 | 977 | src2 = CSPSourceList.fromString(lowerCaseKeywords); |
michael@0 | 978 | do_check_true(src1.equals(src2)) |
michael@0 | 979 | src3 = CSPSourceList.fromString(upperCaseKeywords); |
michael@0 | 980 | do_check_true(src1.equals(src3)) |
michael@0 | 981 | |
michael@0 | 982 | }); |
michael@0 | 983 | |
michael@0 | 984 | test(function test_csp_permits_case_insensitive() { |
michael@0 | 985 | var cspr; |
michael@0 | 986 | var SD = CSPRep.SRC_DIRECTIVES_NEW; |
michael@0 | 987 | |
michael@0 | 988 | // checks directives can be case-insensitive |
michael@0 | 989 | var selfHost = "http://self.com"; |
michael@0 | 990 | var testPolicy1 = "DEFAULT-src 'self';"; |
michael@0 | 991 | cspr = CSPRep.fromString(testPolicy1, URI(selfHost)); |
michael@0 | 992 | do_check_true(cspr.permits(URI("http://self.com"), SD.DEFAULT_SRC)); |
michael@0 | 993 | |
michael@0 | 994 | // checks hosts can be case-insensitive |
michael@0 | 995 | var testPolicy2 = "default-src 'self' http://FOO.COM"; |
michael@0 | 996 | cspr = CSPRep.fromString(testPolicy2, URI(selfHost)); |
michael@0 | 997 | do_check_true(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC)); |
michael@0 | 998 | |
michael@0 | 999 | // checks schemes can be case-insensitive |
michael@0 | 1000 | var testPolicy3 = "default-src 'self' HTTP://foo.com"; |
michael@0 | 1001 | cspr = CSPRep.fromString(testPolicy3, URI(selfHost)); |
michael@0 | 1002 | do_check_true(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC)); |
michael@0 | 1003 | |
michael@0 | 1004 | // checks keywords can be case-insensitive |
michael@0 | 1005 | var testPolicy4 = "default-src 'NONE'"; |
michael@0 | 1006 | cspr = CSPRep.fromString(testPolicy4, URI(selfHost)); |
michael@0 | 1007 | do_check_false(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC)); |
michael@0 | 1008 | }); |
michael@0 | 1009 | /* |
michael@0 | 1010 | |
michael@0 | 1011 | test(function test_CSPRep_fromPolicyURI_failswhenmixed() { |
michael@0 | 1012 | var cspr; |
michael@0 | 1013 | var self = "http://localhost:" + POLICY_PORT; |
michael@0 | 1014 | var closed_policy = CSPRep.fromString("allow 'none'"); |
michael@0 | 1015 | var my_uri_policy = "policy-uri " + POLICY_URI; |
michael@0 | 1016 | |
michael@0 | 1017 | //print(" --- Ignore the following two errors if they print ---"); |
michael@0 | 1018 | cspr = CSPRep.fromString("allow *; " + my_uri_policy, URI(self)); |
michael@0 | 1019 | |
michael@0 | 1020 | //"Parsing should fail when 'policy-uri' is mixed with allow directive" |
michael@0 | 1021 | do_check_equivalent(cspr, closed_policy); |
michael@0 | 1022 | cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, URI(self)); |
michael@0 | 1023 | |
michael@0 | 1024 | //"Parsing should fail when 'policy-uri' is mixed with other directives" |
michael@0 | 1025 | do_check_equivalent(cspr, closed_policy); |
michael@0 | 1026 | //print(" --- Stop ignoring errors that print ---\n"); |
michael@0 | 1027 | |
michael@0 | 1028 | }); |
michael@0 | 1029 | */ |
michael@0 | 1030 | |
michael@0 | 1031 | // TODO: test reporting |
michael@0 | 1032 | // TODO: test refinements (?) |
michael@0 | 1033 | // TODO: test 'eval' and 'inline' keywords |
michael@0 | 1034 | |
michael@0 | 1035 | function run_test() { |
michael@0 | 1036 | function policyresponder(request,response) { |
michael@0 | 1037 | response.setStatusLine(request.httpVersion, 200, "OK"); |
michael@0 | 1038 | response.setHeader("Content-Type", "text/csp", false); |
michael@0 | 1039 | response.bodyOutputStream.write(POLICY_FROM_URI, POLICY_FROM_URI.length); |
michael@0 | 1040 | } |
michael@0 | 1041 | //server.registerDirectory("/", nsILocalFileForBasePath); |
michael@0 | 1042 | httpServer.registerPathHandler("/policy", policyresponder); |
michael@0 | 1043 | |
michael@0 | 1044 | for(let i in tests) { |
michael@0 | 1045 | tests[i](); |
michael@0 | 1046 | } |
michael@0 | 1047 | |
michael@0 | 1048 | //teardown |
michael@0 | 1049 | httpServer.stop(function() { }); |
michael@0 | 1050 | do_test_finished(); |
michael@0 | 1051 | } |
michael@0 | 1052 | |
michael@0 | 1053 | |
michael@0 | 1054 |