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