1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/test/unit/test_cspreports.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,186 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +const Cc = Components.classes; 1.9 +const Ci = Components.interfaces; 1.10 +const Cu = Components.utils; 1.11 +const Cr = Components.results; 1.12 + 1.13 +Cu.import('resource://gre/modules/CSPUtils.jsm'); 1.14 +Cu.import('resource://gre/modules/NetUtil.jsm'); 1.15 + 1.16 +var httpServer = new HttpServer(); 1.17 +httpServer.start(-1); 1.18 +var testsToFinish = 0; 1.19 + 1.20 +const REPORT_SERVER_PORT = httpServer.identity.primaryPort; 1.21 +const REPORT_SERVER_URI = "http://localhost"; 1.22 +const REPORT_SERVER_PATH = "/report"; 1.23 + 1.24 +/** 1.25 + * Construct a callback that listens to a report submission and either passes 1.26 + * or fails a test based on what it gets. 1.27 + */ 1.28 +function makeReportHandler(testpath, message, expectedJSON) { 1.29 + return function(request, response) { 1.30 + // we only like "POST" submissions for reports! 1.31 + if (request.method !== "POST") { 1.32 + do_throw("violation report should be a POST request"); 1.33 + return; 1.34 + } 1.35 + 1.36 + // obtain violation report 1.37 + var reportObj = JSON.parse( 1.38 + NetUtil.readInputStreamToString( 1.39 + request.bodyInputStream, 1.40 + request.bodyInputStream.available())); 1.41 + 1.42 + dump("GOT REPORT:\n" + JSON.stringify(reportObj) + "\n"); 1.43 + dump("TESTPATH: " + testpath + "\n"); 1.44 + dump("EXPECTED: \n" + JSON.stringify(expectedJSON) + "\n\n"); 1.45 + 1.46 + for (var i in expectedJSON) 1.47 + do_check_eq(expectedJSON[i], reportObj['csp-report'][i]); 1.48 + 1.49 + testsToFinish--; 1.50 + httpServer.registerPathHandler(testpath, null); 1.51 + if (testsToFinish < 1) 1.52 + httpServer.stop(do_test_finished); 1.53 + else 1.54 + do_test_finished(); 1.55 + }; 1.56 +} 1.57 + 1.58 +/** 1.59 + * Everything created by this assumes it will cause a report. If you want to 1.60 + * add a test here that will *not* cause a report to go out, you're gonna have 1.61 + * to make sure the test cleans up after itself. 1.62 + */ 1.63 +function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) { 1.64 + testsToFinish++; 1.65 + do_test_pending(); 1.66 + 1.67 + // set up a new CSP instance for each test. 1.68 + var csp = Cc["@mozilla.org/contentsecuritypolicy;1"] 1.69 + .createInstance(Ci.nsIContentSecurityPolicy); 1.70 + var policy = "allow 'none'; " + 1.71 + "report-uri " + REPORT_SERVER_URI + 1.72 + ":" + REPORT_SERVER_PORT + 1.73 + "/test" + id; 1.74 + var selfuri = NetUtil.newURI(REPORT_SERVER_URI + 1.75 + ":" + REPORT_SERVER_PORT + 1.76 + "/foo/self"); 1.77 + var selfchan = NetUtil.newChannel(selfuri); 1.78 + 1.79 + dump("Created test " + id + " : " + policy + "\n\n"); 1.80 + 1.81 + // make the reports seem authentic by "binding" them to a channel. 1.82 + csp.setRequestContext(selfuri, null, null, selfchan); 1.83 + 1.84 + // Load up the policy 1.85 + // set as report-only if that's the case 1.86 + csp.appendPolicy(policy, selfuri, useReportOnlyPolicy, false); 1.87 + 1.88 + // prime the report server 1.89 + var handler = makeReportHandler("/test" + id, "Test " + id, expectedJSON); 1.90 + httpServer.registerPathHandler("/test" + id, handler); 1.91 + 1.92 + //trigger the violation 1.93 + callback(csp); 1.94 +} 1.95 + 1.96 +function run_test() { 1.97 + var selfuri = NetUtil.newURI(REPORT_SERVER_URI + 1.98 + ":" + REPORT_SERVER_PORT + 1.99 + "/foo/self"); 1.100 + 1.101 + // test that inline script violations cause a report. 1.102 + makeTest(0, {"blocked-uri": "self"}, false, 1.103 + function(csp) { 1.104 + let inlineOK = true, oReportViolation = {'value': false}; 1.105 + inlineOK = csp.getAllowsInlineScript(oReportViolation); 1.106 + 1.107 + // this is not a report only policy, so it better block inline scripts 1.108 + do_check_false(inlineOK); 1.109 + // ... and cause reports to go out 1.110 + do_check_true(oReportViolation.value); 1.111 + 1.112 + if (oReportViolation.value) { 1.113 + // force the logging, since the getter doesn't. 1.114 + csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT, 1.115 + selfuri.asciiSpec, 1.116 + "script sample", 1.117 + 0); 1.118 + } 1.119 + }); 1.120 + 1.121 + // test that eval violations cause a report. 1.122 + makeTest(1, {"blocked-uri": "self"}, false, 1.123 + function(csp) { 1.124 + let evalOK = true, oReportViolation = {'value': false}; 1.125 + evalOK = csp.getAllowsEval(oReportViolation); 1.126 + 1.127 + // this is not a report only policy, so it better block eval 1.128 + do_check_false(evalOK); 1.129 + // ... and cause reports to go out 1.130 + do_check_true(oReportViolation.value); 1.131 + 1.132 + if (oReportViolation.value) { 1.133 + // force the logging, since the getter doesn't. 1.134 + csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_EVAL, 1.135 + selfuri.asciiSpec, 1.136 + "script sample", 1.137 + 1); 1.138 + } 1.139 + }); 1.140 + 1.141 + makeTest(2, {"blocked-uri": "http://blocked.test/foo.js"}, false, 1.142 + function(csp) { 1.143 + // shouldLoad creates and sends out the report here. 1.144 + csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT, 1.145 + NetUtil.newURI("http://blocked.test/foo.js"), 1.146 + null, null, null, null); 1.147 + }); 1.148 + 1.149 + // test that inline script violations cause a report in report-only policy 1.150 + makeTest(3, {"blocked-uri": "self"}, true, 1.151 + function(csp) { 1.152 + let inlineOK = true, oReportViolation = {'value': false}; 1.153 + inlineOK = csp.getAllowsInlineScript(oReportViolation); 1.154 + 1.155 + // this is a report only policy, so it better allow inline scripts 1.156 + do_check_true(inlineOK); 1.157 + 1.158 + // ... and cause reports to go out 1.159 + do_check_true(oReportViolation.value); 1.160 + 1.161 + if (oReportViolation.value) { 1.162 + // force the logging, since the getter doesn't. 1.163 + csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT, 1.164 + selfuri.asciiSpec, 1.165 + "script sample", 1.166 + 3); 1.167 + } 1.168 + }); 1.169 + 1.170 + // test that eval violations cause a report in report-only policy 1.171 + makeTest(4, {"blocked-uri": "self"}, true, 1.172 + function(csp) { 1.173 + let evalOK = true, oReportViolation = {'value': false}; 1.174 + evalOK = csp.getAllowsEval(oReportViolation); 1.175 + 1.176 + // this is a report only policy, so it better allow eval 1.177 + do_check_true(evalOK); 1.178 + // ... but still cause reports to go out 1.179 + do_check_true(oReportViolation.value); 1.180 + 1.181 + if (oReportViolation.value) { 1.182 + // force the logging, since the getter doesn't. 1.183 + csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT, 1.184 + selfuri.asciiSpec, 1.185 + "script sample", 1.186 + 4); 1.187 + } 1.188 + }); 1.189 +}