| |
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 |