content/base/test/unit/test_csputils.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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

mercurial