Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | const Cc = Components.classes; |
michael@0 | 6 | const Ci = Components.interfaces; |
michael@0 | 7 | const Cu = Components.utils; |
michael@0 | 8 | const Cr = Components.results; |
michael@0 | 9 | |
michael@0 | 10 | Cu.import('resource://gre/modules/CSPUtils.jsm'); |
michael@0 | 11 | Cu.import('resource://gre/modules/NetUtil.jsm'); |
michael@0 | 12 | |
michael@0 | 13 | var httpServer = new HttpServer(); |
michael@0 | 14 | httpServer.start(-1); |
michael@0 | 15 | var testsToFinish = 0; |
michael@0 | 16 | |
michael@0 | 17 | const REPORT_SERVER_PORT = httpServer.identity.primaryPort; |
michael@0 | 18 | const REPORT_SERVER_URI = "http://localhost"; |
michael@0 | 19 | const REPORT_SERVER_PATH = "/report"; |
michael@0 | 20 | |
michael@0 | 21 | /** |
michael@0 | 22 | * Construct a callback that listens to a report submission and either passes |
michael@0 | 23 | * or fails a test based on what it gets. |
michael@0 | 24 | */ |
michael@0 | 25 | function makeReportHandler(testpath, message, expectedJSON) { |
michael@0 | 26 | return function(request, response) { |
michael@0 | 27 | // we only like "POST" submissions for reports! |
michael@0 | 28 | if (request.method !== "POST") { |
michael@0 | 29 | do_throw("violation report should be a POST request"); |
michael@0 | 30 | return; |
michael@0 | 31 | } |
michael@0 | 32 | |
michael@0 | 33 | // obtain violation report |
michael@0 | 34 | var reportObj = JSON.parse( |
michael@0 | 35 | NetUtil.readInputStreamToString( |
michael@0 | 36 | request.bodyInputStream, |
michael@0 | 37 | request.bodyInputStream.available())); |
michael@0 | 38 | |
michael@0 | 39 | dump("GOT REPORT:\n" + JSON.stringify(reportObj) + "\n"); |
michael@0 | 40 | dump("TESTPATH: " + testpath + "\n"); |
michael@0 | 41 | dump("EXPECTED: \n" + JSON.stringify(expectedJSON) + "\n\n"); |
michael@0 | 42 | |
michael@0 | 43 | for (var i in expectedJSON) |
michael@0 | 44 | do_check_eq(expectedJSON[i], reportObj['csp-report'][i]); |
michael@0 | 45 | |
michael@0 | 46 | testsToFinish--; |
michael@0 | 47 | httpServer.registerPathHandler(testpath, null); |
michael@0 | 48 | if (testsToFinish < 1) |
michael@0 | 49 | httpServer.stop(do_test_finished); |
michael@0 | 50 | else |
michael@0 | 51 | do_test_finished(); |
michael@0 | 52 | }; |
michael@0 | 53 | } |
michael@0 | 54 | |
michael@0 | 55 | /** |
michael@0 | 56 | * Everything created by this assumes it will cause a report. If you want to |
michael@0 | 57 | * add a test here that will *not* cause a report to go out, you're gonna have |
michael@0 | 58 | * to make sure the test cleans up after itself. |
michael@0 | 59 | */ |
michael@0 | 60 | function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) { |
michael@0 | 61 | testsToFinish++; |
michael@0 | 62 | do_test_pending(); |
michael@0 | 63 | |
michael@0 | 64 | // set up a new CSP instance for each test. |
michael@0 | 65 | var csp = Cc["@mozilla.org/contentsecuritypolicy;1"] |
michael@0 | 66 | .createInstance(Ci.nsIContentSecurityPolicy); |
michael@0 | 67 | var policy = "allow 'none'; " + |
michael@0 | 68 | "report-uri " + REPORT_SERVER_URI + |
michael@0 | 69 | ":" + REPORT_SERVER_PORT + |
michael@0 | 70 | "/test" + id; |
michael@0 | 71 | var selfuri = NetUtil.newURI(REPORT_SERVER_URI + |
michael@0 | 72 | ":" + REPORT_SERVER_PORT + |
michael@0 | 73 | "/foo/self"); |
michael@0 | 74 | var selfchan = NetUtil.newChannel(selfuri); |
michael@0 | 75 | |
michael@0 | 76 | dump("Created test " + id + " : " + policy + "\n\n"); |
michael@0 | 77 | |
michael@0 | 78 | // make the reports seem authentic by "binding" them to a channel. |
michael@0 | 79 | csp.setRequestContext(selfuri, null, null, selfchan); |
michael@0 | 80 | |
michael@0 | 81 | // Load up the policy |
michael@0 | 82 | // set as report-only if that's the case |
michael@0 | 83 | csp.appendPolicy(policy, selfuri, useReportOnlyPolicy, false); |
michael@0 | 84 | |
michael@0 | 85 | // prime the report server |
michael@0 | 86 | var handler = makeReportHandler("/test" + id, "Test " + id, expectedJSON); |
michael@0 | 87 | httpServer.registerPathHandler("/test" + id, handler); |
michael@0 | 88 | |
michael@0 | 89 | //trigger the violation |
michael@0 | 90 | callback(csp); |
michael@0 | 91 | } |
michael@0 | 92 | |
michael@0 | 93 | function run_test() { |
michael@0 | 94 | var selfuri = NetUtil.newURI(REPORT_SERVER_URI + |
michael@0 | 95 | ":" + REPORT_SERVER_PORT + |
michael@0 | 96 | "/foo/self"); |
michael@0 | 97 | |
michael@0 | 98 | // test that inline script violations cause a report. |
michael@0 | 99 | makeTest(0, {"blocked-uri": "self"}, false, |
michael@0 | 100 | function(csp) { |
michael@0 | 101 | let inlineOK = true, oReportViolation = {'value': false}; |
michael@0 | 102 | inlineOK = csp.getAllowsInlineScript(oReportViolation); |
michael@0 | 103 | |
michael@0 | 104 | // this is not a report only policy, so it better block inline scripts |
michael@0 | 105 | do_check_false(inlineOK); |
michael@0 | 106 | // ... and cause reports to go out |
michael@0 | 107 | do_check_true(oReportViolation.value); |
michael@0 | 108 | |
michael@0 | 109 | if (oReportViolation.value) { |
michael@0 | 110 | // force the logging, since the getter doesn't. |
michael@0 | 111 | csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT, |
michael@0 | 112 | selfuri.asciiSpec, |
michael@0 | 113 | "script sample", |
michael@0 | 114 | 0); |
michael@0 | 115 | } |
michael@0 | 116 | }); |
michael@0 | 117 | |
michael@0 | 118 | // test that eval violations cause a report. |
michael@0 | 119 | makeTest(1, {"blocked-uri": "self"}, false, |
michael@0 | 120 | function(csp) { |
michael@0 | 121 | let evalOK = true, oReportViolation = {'value': false}; |
michael@0 | 122 | evalOK = csp.getAllowsEval(oReportViolation); |
michael@0 | 123 | |
michael@0 | 124 | // this is not a report only policy, so it better block eval |
michael@0 | 125 | do_check_false(evalOK); |
michael@0 | 126 | // ... and cause reports to go out |
michael@0 | 127 | do_check_true(oReportViolation.value); |
michael@0 | 128 | |
michael@0 | 129 | if (oReportViolation.value) { |
michael@0 | 130 | // force the logging, since the getter doesn't. |
michael@0 | 131 | csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_EVAL, |
michael@0 | 132 | selfuri.asciiSpec, |
michael@0 | 133 | "script sample", |
michael@0 | 134 | 1); |
michael@0 | 135 | } |
michael@0 | 136 | }); |
michael@0 | 137 | |
michael@0 | 138 | makeTest(2, {"blocked-uri": "http://blocked.test/foo.js"}, false, |
michael@0 | 139 | function(csp) { |
michael@0 | 140 | // shouldLoad creates and sends out the report here. |
michael@0 | 141 | csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT, |
michael@0 | 142 | NetUtil.newURI("http://blocked.test/foo.js"), |
michael@0 | 143 | null, null, null, null); |
michael@0 | 144 | }); |
michael@0 | 145 | |
michael@0 | 146 | // test that inline script violations cause a report in report-only policy |
michael@0 | 147 | makeTest(3, {"blocked-uri": "self"}, true, |
michael@0 | 148 | function(csp) { |
michael@0 | 149 | let inlineOK = true, oReportViolation = {'value': false}; |
michael@0 | 150 | inlineOK = csp.getAllowsInlineScript(oReportViolation); |
michael@0 | 151 | |
michael@0 | 152 | // this is a report only policy, so it better allow inline scripts |
michael@0 | 153 | do_check_true(inlineOK); |
michael@0 | 154 | |
michael@0 | 155 | // ... and cause reports to go out |
michael@0 | 156 | do_check_true(oReportViolation.value); |
michael@0 | 157 | |
michael@0 | 158 | if (oReportViolation.value) { |
michael@0 | 159 | // force the logging, since the getter doesn't. |
michael@0 | 160 | csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT, |
michael@0 | 161 | selfuri.asciiSpec, |
michael@0 | 162 | "script sample", |
michael@0 | 163 | 3); |
michael@0 | 164 | } |
michael@0 | 165 | }); |
michael@0 | 166 | |
michael@0 | 167 | // test that eval violations cause a report in report-only policy |
michael@0 | 168 | makeTest(4, {"blocked-uri": "self"}, true, |
michael@0 | 169 | function(csp) { |
michael@0 | 170 | let evalOK = true, oReportViolation = {'value': false}; |
michael@0 | 171 | evalOK = csp.getAllowsEval(oReportViolation); |
michael@0 | 172 | |
michael@0 | 173 | // this is a report only policy, so it better allow eval |
michael@0 | 174 | do_check_true(evalOK); |
michael@0 | 175 | // ... but still cause reports to go out |
michael@0 | 176 | do_check_true(oReportViolation.value); |
michael@0 | 177 | |
michael@0 | 178 | if (oReportViolation.value) { |
michael@0 | 179 | // force the logging, since the getter doesn't. |
michael@0 | 180 | csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT, |
michael@0 | 181 | selfuri.asciiSpec, |
michael@0 | 182 | "script sample", |
michael@0 | 183 | 4); |
michael@0 | 184 | } |
michael@0 | 185 | }); |
michael@0 | 186 | } |