mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge backout of changeset f0d3b958d38d (bug 552523) for causing 137-140 mochitest failures on the two mochitest runs (both Windows) that have completed so far.
This commit is contained in:
commit
e22a2a4669
@ -42,11 +42,11 @@ interface nsIHttpChannel;
|
||||
interface nsIDocShell;
|
||||
|
||||
/**
|
||||
* nsIContentSecurityPolicy
|
||||
* nsIContentSecurityPolicy
|
||||
* Describes an XPCOM component used to model an enforce CSPs.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(83F51E09-1C7B-41AC-A15F-D972DCC5205D)]
|
||||
[scriptable, uuid(AB36A2BF-CB32-4AA6-AB41-6B4E4444A221)]
|
||||
interface nsIContentSecurityPolicy : nsISupports
|
||||
{
|
||||
|
||||
@ -58,14 +58,15 @@ interface nsIContentSecurityPolicy : nsISupports
|
||||
attribute boolean isInitialized;
|
||||
|
||||
/**
|
||||
* A read-only string version of the enforced policy for debugging.
|
||||
* When set to true, content load-blocking and fail-closed are disabled: CSP
|
||||
* will ONLY send reports, and not modify behavior.
|
||||
*/
|
||||
readonly attribute AString enforcedPolicy;
|
||||
attribute boolean reportOnlyMode;
|
||||
|
||||
/**
|
||||
* A read-only string version of the report-only policy for debugging.
|
||||
* A read-only string version of the policy for debugging.
|
||||
*/
|
||||
readonly attribute AString reportOnlyPolicy;
|
||||
readonly attribute AString policy;
|
||||
|
||||
/**
|
||||
* Whether this policy allows in-page script.
|
||||
@ -84,6 +85,18 @@ interface nsIContentSecurityPolicy : nsISupports
|
||||
*/
|
||||
readonly attribute boolean allowsEval;
|
||||
|
||||
/**
|
||||
* Manually triggers violation report sending given a URI and reason.
|
||||
* The URI may be null, in which case "self" is sent.
|
||||
* @param blockedURI
|
||||
* the URI that violated the policy
|
||||
* @param violatedDirective
|
||||
* the directive that was violated.
|
||||
* @return
|
||||
* nothing.
|
||||
*/
|
||||
void sendReports(in AString blockedURI, in AString violatedDirective);
|
||||
|
||||
/**
|
||||
* Called after the CSP object is created to fill in the appropriate request
|
||||
* and request header information needed in case a report needs to be sent.
|
||||
@ -91,16 +104,10 @@ interface nsIContentSecurityPolicy : nsISupports
|
||||
void scanRequestData(in nsIHttpChannel aChannel);
|
||||
|
||||
/**
|
||||
* Updates the enforced policy currently stored in the CSP to be "refined" or
|
||||
* Updates the policy currently stored in the CSP to be "refined" or
|
||||
* tightened by the one specified in the string policyString.
|
||||
*/
|
||||
void refineEnforcedPolicy(in AString policyString, in nsIURI selfURI);
|
||||
|
||||
/**
|
||||
* Updates the report-only policy currently stored in the CSP to be "refined"
|
||||
* or tightened by the one specified in the string policyString.
|
||||
*/
|
||||
void refineReportOnlyPolicy(in AString policyString, in nsIURI selfURI);
|
||||
void refinePolicy(in AString policyString, in nsIURI selfURI);
|
||||
|
||||
/**
|
||||
* Verifies ancestry as permitted by the policy.
|
||||
|
@ -60,10 +60,16 @@ Cu.import("resource://gre/modules/CSPUtils.jsm");
|
||||
function ContentSecurityPolicy() {
|
||||
CSPdebug("CSP CREATED");
|
||||
this._isInitialized = false;
|
||||
this._enforcedPolicy = null;
|
||||
this._reportOnlyPolicy = null;
|
||||
this._requestHeaders = [];
|
||||
this._reportOnlyMode = false;
|
||||
this._policy = CSPRep.fromString("allow *");
|
||||
|
||||
// default options "wide open" since this policy will be intersected soon
|
||||
this._policy._allowInlineScripts = true;
|
||||
this._policy._allowEval = true;
|
||||
|
||||
this._requestHeaders = [];
|
||||
this._request = "";
|
||||
CSPdebug("CSP POLICY INITED TO 'allow *'");
|
||||
|
||||
this._observerService = Cc['@mozilla.org/observer-service;1']
|
||||
.getService(Ci.nsIObserverService);
|
||||
@ -122,76 +128,48 @@ ContentSecurityPolicy.prototype = {
|
||||
return this._policy.toString();
|
||||
},
|
||||
|
||||
/**
|
||||
* Decides whether or not inline scripts are allowed and sends out violation
|
||||
* reports if they're not. Also, if there's a report-only policy, violation
|
||||
* reports are sent when the policy disallows them, but this returns true.
|
||||
*/
|
||||
get allowsInlineScript() {
|
||||
// gotta wrap the violation string, since it's sent out to observers as
|
||||
// an nsISupports.
|
||||
var violation = Cc["@mozilla.org/supports-cstring;1"]
|
||||
// trigger automatic report to go out when inline scripts are disabled.
|
||||
if (!this._policy.allowsInlineScripts) {
|
||||
var violation = 'violated base restriction: Inline Scripts will not execute';
|
||||
// gotta wrap the violation string, since it's sent out to observers as
|
||||
// an nsISupports.
|
||||
let wrapper = Cc["@mozilla.org/supports-cstring;1"]
|
||||
.createInstance(Ci.nsISupportsCString);
|
||||
violation.data = 'base restriction: no inline scripts';
|
||||
|
||||
// first, trigger reports if the report-only policy disallows inline
|
||||
// scripts (but do not decide whether or not to block the script).
|
||||
if (this._reportOnlyPolicy && !this._reportOnlyPolicy.allowsInlineScripts) {
|
||||
wrapper.data = violation;
|
||||
this._observerService.notifyObservers(
|
||||
violation,
|
||||
wrapper,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
'inline script base restriction');
|
||||
this._sendReports(this._reportOnlyPolicy, 'self', violation.data);
|
||||
this.sendReports('self', violation);
|
||||
}
|
||||
|
||||
// second, verify with real policy and trigger automatic report to go out
|
||||
// when inline scripts are disabled.
|
||||
if (this._enforcedPolicy && !this._enforcedPolicy.allowsInlineScripts) {
|
||||
this._observerService.notifyObservers(
|
||||
violation,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
'inline script base restriction');
|
||||
this._sendReports(this._enforcedPolicy, 'self', violation.data);
|
||||
return false;
|
||||
}
|
||||
|
||||
// finally, if we get here, inline scripts should be allowed
|
||||
return true;
|
||||
return this._reportOnlyMode || this._policy.allowsInlineScripts;
|
||||
},
|
||||
|
||||
/**
|
||||
* Decides whether or not eval() is allowed and sends out violation
|
||||
* reports if not. Also, if there's a report-only policy, violation
|
||||
* reports are sent when the policy disallows eval, but this returns true.
|
||||
*/
|
||||
get allowsEval() {
|
||||
// gotta wrap the violation string, since it's sent out to observers as
|
||||
// an nsISupports.
|
||||
var violation = Cc["@mozilla.org/supports-cstring;1"]
|
||||
.createInstance(Ci.nsISupportsCString);
|
||||
violation.data = 'base restriction: no eval-like function calls';
|
||||
|
||||
// first, trigger reports if the report-only policy disallows eval
|
||||
// (but do not decide whether or not to block the script).
|
||||
if (this._reportOnlyPolicy && !this._reportOnlyPolicy.allowsEvalInScripts) {
|
||||
this._observerService.notifyObservers(
|
||||
violation,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
'eval script base restriction');
|
||||
this._sendReports(this._reportOnlyPolicy, 'self', violation.data);
|
||||
}
|
||||
|
||||
// trigger automatic report to go out when eval and friends are disabled.
|
||||
if (this._enforcedPolicy && !this._enforcedPolicy.allowsEvalInScripts) {
|
||||
if (!this._policy.allowsEvalInScripts) {
|
||||
var violation = 'violated base restriction: Code will not be created from strings';
|
||||
// gotta wrap the violation string, since it's sent out to observers as
|
||||
// an nsISupports.
|
||||
let wrapper = Cc["@mozilla.org/supports-cstring;1"]
|
||||
.createInstance(Ci.nsISupportsCString);
|
||||
wrapper.data = violation;
|
||||
this._observerService.notifyObservers(
|
||||
violation,
|
||||
wrapper,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
'eval script base restriction');
|
||||
this._sendReports(this._enforcedPolicy, 'self', violation.data);
|
||||
return false;
|
||||
this.sendReports('self', violation);
|
||||
}
|
||||
return this._reportOnlyMode || this._policy.allowsEvalInScripts;
|
||||
},
|
||||
|
||||
return true;
|
||||
set reportOnlyMode(val) {
|
||||
this._reportOnlyMode = val;
|
||||
},
|
||||
|
||||
get reportOnlyMode () {
|
||||
return this._reportOnlyMode;
|
||||
},
|
||||
|
||||
/*
|
||||
@ -228,8 +206,14 @@ ContentSecurityPolicy.prototype = {
|
||||
|
||||
/* ........ Methods .............. */
|
||||
|
||||
function csp_refinePolicyInternal(policyToRefine, aPolicy, selfURI) {
|
||||
CSPdebug(" REFINING: " + policyToRefine);
|
||||
/**
|
||||
* Given a new policy, intersects the currently enforced policy with the new
|
||||
* one and stores the result. The effect is a "tightening" or refinement of
|
||||
* an old policy. This is called any time a new policy is encountered and
|
||||
* the effective policy has to be refined.
|
||||
*/
|
||||
refinePolicy:
|
||||
function csp_refinePolicy(aPolicy, selfURI) {
|
||||
CSPdebug("REFINE POLICY: " + aPolicy);
|
||||
CSPdebug(" SELF: " + selfURI.asciiSpec);
|
||||
|
||||
@ -242,40 +226,19 @@ ContentSecurityPolicy.prototype = {
|
||||
selfURI.scheme + "://" + selfURI.hostPort);
|
||||
|
||||
// (2) Intersect the currently installed CSPRep object with the new one
|
||||
if (!this[policyToRefine])
|
||||
this[policyToRefine] = newpolicy;
|
||||
else
|
||||
this[policyToRefine] = this._policy.intersectWith(newpolicy);
|
||||
|
||||
// (3) Finished
|
||||
var intersect = this._policy.intersectWith(newpolicy);
|
||||
|
||||
// (3) Save the result
|
||||
this._policy = intersect;
|
||||
this._isInitialized = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a new policy, intersects the currently enforced policy with the new
|
||||
* one and stores the result. The effect is a "tightening" or refinement of
|
||||
* an old policy. This is called any time a new policy is encountered and
|
||||
* the effective policy has to be refined.
|
||||
*/
|
||||
refineEnforcedPolicy:
|
||||
function csp_refineEnforcedPolicy(aPolicy, selfURI) {
|
||||
return this._refinePolicyInternal("_enforcedPolicy", aPolicy, selfURI);
|
||||
},
|
||||
|
||||
/**
|
||||
* Same, but for report-only policy.
|
||||
*/
|
||||
refineReportOnlyPolicy:
|
||||
function csp_refineReportOnlyPolicy(aPolicy, selfURI) {
|
||||
return this._refinePolicyInternal("_reportOnlyPolicy", aPolicy, selfURI);
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates and sends a violation report to the specified report URIs.
|
||||
*/
|
||||
_sendReports:
|
||||
function(policyViolated, blockedUri, violatedDirective) {
|
||||
var uriString = policyViolated.getReportURIs();
|
||||
sendReports:
|
||||
function(blockedUri, violatedDirective) {
|
||||
var uriString = this._policy.getReportURIs();
|
||||
var uris = uriString.split(/\s+/);
|
||||
if (uris.length > 0) {
|
||||
// Generate report to send composed of
|
||||
@ -378,40 +341,22 @@ ContentSecurityPolicy.prototype = {
|
||||
let cspContext = CSPRep.SRC_DIRECTIVES.FRAME_ANCESTORS;
|
||||
for (let i in ancestors) {
|
||||
let ancestor = ancestors[i].prePath;
|
||||
|
||||
// first, check the report-only policy.
|
||||
if (this._reportOnlyPolicy) {
|
||||
let directive = this._reportOnlyPolicy._directives[cspContext];
|
||||
if (!this._policy.permits(ancestor, cspContext)) {
|
||||
// report the frame-ancestor violation
|
||||
let directive = this._policy._directives[cspContext];
|
||||
let violatedPolicy = (directive._isImplicit
|
||||
? 'allow' : 'frame-ancestors ')
|
||||
+ directive.toString();
|
||||
if (!this._reportOnlyPolicy.permits(ancestor, cspContext)) {
|
||||
this._observerService.notifyObservers(
|
||||
ancestors[i],
|
||||
CSP_VIOLATION_TOPIC,
|
||||
violatedPolicy);
|
||||
this._sendReports(this._enforcedPolicy, ancestors[i].asciiSpec, violatedPolicy);
|
||||
}
|
||||
}
|
||||
|
||||
// second, check the enforced policy.
|
||||
if (this._enforcedPolicy) {
|
||||
let directive = this._enforcedPolicy._directives[cspContext];
|
||||
let violatedPolicy = (directive._isImplicit
|
||||
? 'allow' : 'frame-ancestors ')
|
||||
+ directive.toString();
|
||||
if(!this._enforcedPolicy.permits(ancestor, cspContext)) {
|
||||
this._observerService.notifyObservers(
|
||||
ancestors[i],
|
||||
CSP_VIOLATION_TOPIC,
|
||||
violatedPolicy);
|
||||
this._sendReports(this._enforcedPolicy, ancestors[i].asciiSpec, violatedPolicy);
|
||||
return false;
|
||||
}
|
||||
? 'allow' : 'frame-ancestors ')
|
||||
+ directive.toString();
|
||||
// send an nsIURI object to the observers (more interesting than a string)
|
||||
this._observerService.notifyObservers(
|
||||
ancestors[i],
|
||||
CSP_VIOLATION_TOPIC,
|
||||
violatedPolicy);
|
||||
this.sendReports(ancestors[i].asciiSpec, violatedPolicy);
|
||||
// need to lie if we are testing in report-only mode
|
||||
return this._reportOnlyMode;
|
||||
}
|
||||
}
|
||||
|
||||
// all ancestors allowed (or only violated a report-only policy)
|
||||
return true;
|
||||
},
|
||||
|
||||
@ -444,60 +389,35 @@ ContentSecurityPolicy.prototype = {
|
||||
return Ci.nsIContentPolicy.ACCEPT;
|
||||
}
|
||||
|
||||
// frame-ancestors is already taken care of early on (as this document is
|
||||
// loaded)
|
||||
// otherwise, honor the translation
|
||||
// var source = aContentLocation.scheme + "://" + aContentLocation.hostPort;
|
||||
var res = this._policy.permits(aContentLocation, cspContext)
|
||||
? Ci.nsIContentPolicy.ACCEPT
|
||||
: Ci.nsIContentPolicy.REJECT_SERVER;
|
||||
|
||||
// first, run it by the report-only policy
|
||||
if (this._reportOnlyPolicy) {
|
||||
var ro_res = this._reportOnlyPolicy.permits(aContentLocation, cspContext)
|
||||
? Ci.nsIContentPolicy.ACCEPT
|
||||
: Ci.nsIContentPolicy.REJECT_SERVER;
|
||||
// frame-ancestors is taken care of early on (as this document is loaded)
|
||||
|
||||
if (ro_res != Ci.nsIContentPolicy.ACCEPT) {
|
||||
try {
|
||||
let directive = this._reportOnlyPolicy._directives[cspContext];
|
||||
let violatedPolicy = (directive._isImplicit
|
||||
? 'allow' : cspContext)
|
||||
+ ' ' + directive.toString();
|
||||
this._observerService.notifyObservers(
|
||||
aContentLocation,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
violatedPolicy);
|
||||
this._sendReports(this._reportOnlyPolicy, aContentLocation, violatedPolicy);
|
||||
} catch(e) {
|
||||
CSPdebug('---------------- ERROR: ' + e);
|
||||
}
|
||||
// If the result is *NOT* ACCEPT, then send report
|
||||
if (res != Ci.nsIContentPolicy.ACCEPT) {
|
||||
CSPdebug("blocking request for " + aContentLocation.asciiSpec);
|
||||
try {
|
||||
let directive = this._policy._directives[cspContext];
|
||||
let violatedPolicy = (directive._isImplicit
|
||||
? 'allow' : cspContext)
|
||||
+ ' ' + directive.toString();
|
||||
this._observerService.notifyObservers(
|
||||
aContentLocation,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
violatedPolicy);
|
||||
this.sendReports(aContentLocation, violatedPolicy);
|
||||
} catch(e) {
|
||||
CSPdebug('---------------- ERROR: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
// also run it by the enforced policy
|
||||
if (this._enforcedPolicy) {
|
||||
var en_res = this._enforcedPolicy.permits(aContentLocation, cspContext)
|
||||
? Ci.nsIContentPolicy.ACCEPT
|
||||
: Ci.nsIContentPolicy.REJECT_SERVER;
|
||||
|
||||
if (en_res != Ci.nsIContentPolicy.ACCEPT) {
|
||||
CSPdebug("blocking request for " + aContentLocation.asciiSpec);
|
||||
try {
|
||||
let directive = this._enforcedPolicy._directives[cspContext];
|
||||
let violatedPolicy = (directive._isImplicit
|
||||
? 'allow' : cspContext)
|
||||
+ ' ' + directive.toString();
|
||||
this._observerService.notifyObservers(
|
||||
aContentLocation,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
violatedPolicy);
|
||||
this._sendReports(this._enforcedPolicy, aContentLocation, violatedPolicy);
|
||||
} catch(e) {
|
||||
CSPdebug('---------------- ERROR: ' + e);
|
||||
}
|
||||
return en_res;
|
||||
}
|
||||
}
|
||||
|
||||
return Ci.nsIContentPolicy.ACCEPT;
|
||||
return (this._reportOnlyMode ? Ci.nsIContentPolicy.ACCEPT : res);
|
||||
},
|
||||
|
||||
|
||||
shouldProcess:
|
||||
function csp_shouldProcess(aContentType,
|
||||
aContentLocation,
|
||||
|
@ -117,18 +117,10 @@ CSPService::ShouldLoad(PRUint32 aContentType,
|
||||
if (csp) {
|
||||
#ifdef PR_LOGGING
|
||||
nsAutoString policy;
|
||||
csp->GetEnforcedPolicy(policy);
|
||||
if (policy.Length() > 0) {
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("Document CSP: %s",
|
||||
NS_ConvertUTF16toUTF8(policy).get()));
|
||||
}
|
||||
csp->GetReportOnlyPolicy(policy);
|
||||
if (policy.Length() > 0) {
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("Report-Only CSP: %s",
|
||||
NS_ConvertUTF16toUTF8(policy).get()));
|
||||
}
|
||||
csp->GetPolicy(policy);
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("Document has CSP: %s",
|
||||
NS_ConvertUTF16toUTF8(policy).get()));
|
||||
#endif
|
||||
// obtain the enforcement decision
|
||||
csp->ShouldLoad(aContentType,
|
||||
@ -183,18 +175,10 @@ CSPService::ShouldProcess(PRUint32 aContentType,
|
||||
if (csp) {
|
||||
#ifdef PR_LOGGING
|
||||
nsAutoString policy;
|
||||
csp->GetEnforcedPolicy(policy);
|
||||
if (policy.Length() > 0) {
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("shouldProcess - CSP: %s",
|
||||
NS_ConvertUTF16toUTF8(policy).get()));
|
||||
}
|
||||
csp->GetReportOnlyPolicy(policy);
|
||||
if (policy.Length() > 0) {
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("shouldProcess - Report-Only CSP: %s",
|
||||
NS_ConvertUTF16toUTF8(policy).get()));
|
||||
}
|
||||
csp->GetPolicy(policy);
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("shouldProcess - document has policy: %s",
|
||||
NS_ConvertUTF16toUTF8(policy).get()));
|
||||
#endif
|
||||
// obtain the enforcement decision
|
||||
csp->ShouldProcess(aContentType,
|
||||
|
@ -2222,23 +2222,29 @@ nsDocument::InitCSP()
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP Loaded"));
|
||||
#endif
|
||||
|
||||
if (!cspHeaderValue.IsEmpty()) {
|
||||
mCSP->RefineEnforcedPolicy(cspHeaderValue, chanURI);
|
||||
// ReportOnly mode is enabled *only* if there are no regular-strength CSP
|
||||
// headers present. If there are, then we ignore the ReportOnly mode and
|
||||
// toss a warning into the error console, proceeding with enforcing the
|
||||
// regular-strength CSP.
|
||||
if (cspHeaderValue.IsEmpty()) {
|
||||
mCSP->SetReportOnlyMode(true);
|
||||
mCSP->RefinePolicy(cspROHeaderValue, chanURI);
|
||||
#ifdef PR_LOGGING
|
||||
{
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("CSP refined with policy: \"%s\"",
|
||||
NS_ConvertUTF16toUTF8(cspHeaderValue).get()));
|
||||
("CSP (report only) refined, policy: \"%s\"",
|
||||
NS_ConvertUTF16toUTF8(cspROHeaderValue).get()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!cspROHeaderValue.IsEmpty()) {
|
||||
mCSP->RefineReportOnlyPolicy(cspROHeaderValue, chanURI);
|
||||
} else {
|
||||
//XXX(sstamm): maybe we should post a warning when both read only and regular
|
||||
// CSP headers are present.
|
||||
mCSP->RefinePolicy(cspHeaderValue, chanURI);
|
||||
#ifdef PR_LOGGING
|
||||
{
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("CSP (report-only) refined with policy: \"%s\"",
|
||||
NS_ConvertUTF16toUTF8(cspROHeaderValue).get()));
|
||||
("CSP refined, policy: \"%s\"",
|
||||
NS_ConvertUTF16toUTF8(cspHeaderValue).get()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -402,10 +402,6 @@ _TEST_FILES2 = \
|
||||
test_websocket.html \
|
||||
file_websocket_wsh.py \
|
||||
file_websocket_http_resource.txt \
|
||||
test_bug552523.html \
|
||||
file_bug552523.html \
|
||||
file_bug552523.html^headers^ \
|
||||
file_bug552523_violation.sjs \
|
||||
$(NULL)
|
||||
|
||||
# This test fails on the Mac for some reason
|
||||
|
@ -1,15 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css'
|
||||
href='/tests/content/base/test/file_CSP.sjs?testid=css_self&type=text/css' />
|
||||
<link rel='stylesheet' type='text/css'
|
||||
href='http://example.com/tests/content/base/test/file_CSP.sjs?testid=css_examplecom&type=text/css' />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<img src="/tests/content/base/test/file_CSP.sjs?testid=img_self&type=img/png"> </img>
|
||||
<img src="http://example.com/tests/content/base/test/file_CSP.sjs?testid=img_examplecom&type=img/png"> </img>
|
||||
<script src='/tests/content/base/test/file_CSP.sjs?testid=script_self&type=text/javascript'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,2 +0,0 @@
|
||||
x-content-security-policy: allow 'self'; img-src 'none'; report-uri http://mochi.test:8888/tests/content/base/test/file_bug552523_violation.sjs
|
||||
x-content-security-policy-report-only: allow *; img-src 'self'; script-src 'none'; report-uri http://mochi.test:8888/tests/content/base/test/file_bug552523_violation.sjs
|
@ -1,54 +0,0 @@
|
||||
// SJS file that receives violation reports and then responds with nothing.
|
||||
|
||||
const CC = Components.Constructor;
|
||||
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
||||
"nsIBinaryInputStream",
|
||||
"setInputStream");
|
||||
|
||||
const STATE = "bug552523_violations";
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var query = {};
|
||||
request.queryString.split('&').forEach(function (val) {
|
||||
var [name, value] = val.split('=');
|
||||
query[name] = unescape(value);
|
||||
});
|
||||
|
||||
|
||||
if ('results' in query) {
|
||||
// if asked for the received data, send it.
|
||||
response.setHeader("Content-Type", "text/javascript", false);
|
||||
response.write(getState(STATE));
|
||||
} else if ('reset' in query) {
|
||||
//clear state
|
||||
setState(STATE, JSON.stringify(null));
|
||||
} else {
|
||||
// ... otherwise, just respond "ok".
|
||||
response.write("'ok'");
|
||||
|
||||
var bodystream = new BinaryInputStream(request.bodyInputStream);
|
||||
var avail;
|
||||
var bytes = [];
|
||||
while ((avail = bodystream.available()) > 0)
|
||||
Array.prototype.push.apply(bytes, bodystream.readByteArray(avail));
|
||||
|
||||
var data = String.fromCharCode.apply(null, bytes);
|
||||
|
||||
// figure out which test was violating a policy
|
||||
var testpat = new RegExp("testid=([a-z0-9_]+)");
|
||||
var testid = testpat.exec(data)[1];
|
||||
|
||||
// store the violation in the persistent state
|
||||
var s = getState(STATE);
|
||||
if (!s) s = "{}";
|
||||
s = JSON.parse(s);
|
||||
if (!s) s = {};
|
||||
|
||||
if (!s[testid]) s[testid] = 0;
|
||||
s[testid]++;
|
||||
setState(STATE, JSON.stringify(s));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,12 +112,7 @@ window.testResult = function(testname, result, msg) {
|
||||
|
||||
// ... otherwise, finish
|
||||
window.examiner.remove();
|
||||
|
||||
// must call SimpleTest.finish() in the background because it modifies the
|
||||
// DOM (and this might be called during a reflow.)
|
||||
window.setTimeout(function () {
|
||||
SimpleTest.finish();
|
||||
}, 0);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
@ -1,158 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Content Security Policy and Report-Only mode</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
|
||||
<iframe style="width:200px;height:200px;" id='cspframe'></iframe>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var path = "/tests/content/base/test/";
|
||||
|
||||
// These are test results: -1 means it hasn't run,
|
||||
// true/false is the pass/fail result.
|
||||
window.loads = {
|
||||
css_self: {expected: true, verified: false},
|
||||
css_examplecom: {expected: false, verified: false},
|
||||
img_self: {expected: false, verified: false},
|
||||
img_examplecom: {expected: false, verified: false},
|
||||
script_self: {expected: true, verified: false},
|
||||
};
|
||||
|
||||
window.violation_reports = {
|
||||
css_self: {expected: 0, received: 0}, /* totally fine */
|
||||
css_examplecom: {expected: 1, received: 0}, /* violates enforced CSP */
|
||||
img_self: {expected: 1, received: 0}, /* violates enforced CSP */
|
||||
img_examplecom: {expected: 2, received: 0}, /* violates both CSPs */
|
||||
script_self: {expected: 1, received: 0}, /* violates report-only */
|
||||
};
|
||||
|
||||
// This is used to watch the blocked data bounce off CSP and allowed data
|
||||
// get sent out to the wire. This also watches for violation reports to go out.
|
||||
function examiner() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
var obsvc = Components.classes['@mozilla.org/observer-service;1']
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
obsvc.addObserver(this, "csp-on-violate-policy", false);
|
||||
obsvc.addObserver(this, "http-on-modify-request", false);
|
||||
}
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
// subject should be an nsURI, and should be either allowed or blocked.
|
||||
if(!subject.QueryInterface)
|
||||
return;
|
||||
|
||||
var testpat = new RegExp("testid=([a-z0-9_]+)");
|
||||
|
||||
if (topic === "http-on-modify-request") {
|
||||
var uri = subject.QueryInterface(Components.interfaces.nsIHttpChannel).URI;
|
||||
if (!testpat.test(uri.asciiSpec)) return;
|
||||
var testid = testpat.exec(uri.asciiSpec)[1];
|
||||
|
||||
//violation reports don't come through here, but the requested resources do
|
||||
// if the test has already finished, move on.
|
||||
if (window.loads[testid].verified) return;
|
||||
|
||||
//these are requests that were allowed by CSP
|
||||
var testid = testpat.exec(uri.asciiSpec)[1];
|
||||
window.testResult(testid, 'allowed', uri.asciiSpec + " allowed by csp");
|
||||
}
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
//these were NOT NECESSARILY blocked, but rather a policy was violated...
|
||||
var uri = subject.QueryInterface(Components.interfaces.nsIURI);
|
||||
if (!testpat.test(uri.asciiSpec)) return;
|
||||
var testid = testpat.exec(uri.asciiSpec)[1];
|
||||
|
||||
// if the test has already finished, move on.
|
||||
if (window.loads[testid].verified) return;
|
||||
|
||||
// record the ones that were supposed to be blocked, but don't use this
|
||||
// as an indicator for tests that are mistakenly blocked.
|
||||
if (!window.loads[testid].expected) {
|
||||
window.testResult(testid,
|
||||
'blocked',
|
||||
uri.asciiSpec + " blocked by \"" + data + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
// if any test is unverified, keep waiting
|
||||
for (var v in window.loads)
|
||||
if(!window.loads[v].verified)
|
||||
return;
|
||||
|
||||
// ... otherwise, finish.
|
||||
// Must call SimpleTest.finish() in the background because it modifies the
|
||||
// DOM (and this might be called during a reflow.)
|
||||
var self = window;
|
||||
window.examiner.remove();
|
||||
window.verifyReports();
|
||||
window.setTimeout(function () {
|
||||
SimpleTest.finish();
|
||||
}, 0);
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
var obsvc = Components.classes['@mozilla.org/observer-service;1']
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
obsvc.removeObserver(this, "csp-on-violate-policy");
|
||||
obsvc.removeObserver(this, "http-on-modify-request");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
window.testResult = function(testname, result, msg) {
|
||||
//otherwise, make sure the allowed ones are expected and blocked ones are not.
|
||||
if (window.loads[testname].expected) {
|
||||
is(result, 'allowed', ">> " + msg);
|
||||
} else {
|
||||
is(result, 'blocked', ">> " + msg);
|
||||
}
|
||||
window.loads[testname].verified = true;
|
||||
}
|
||||
|
||||
window.verifyReports = function() {
|
||||
//obtain from server
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "http://mochi.test:8888" + path + "file_bug552523_violation.sjs?results", false);
|
||||
xhr.send(null);
|
||||
|
||||
var received = JSON.parse(xhr.responseText);
|
||||
for (var r in received)
|
||||
window.violation_reports[r].received = received[r];
|
||||
|
||||
//make sure it all adds up
|
||||
for(var r in window.violation_reports) {
|
||||
var exp = window.violation_reports[r].expected;
|
||||
var rec = window.violation_reports[r].received;
|
||||
is(rec, exp, "Received wrong number of reports for " + r);
|
||||
}
|
||||
|
||||
//reset server
|
||||
xhr.open("GET", "http://mochi.test:8888" + path + "file_bug552523_violation.sjs?reset", false);
|
||||
xhr.send(null);
|
||||
};
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// save this for last so that our listeners are registered.
|
||||
// ... this loads the testbed of good and bad requests.
|
||||
|
||||
document.getElementById('cspframe').src = 'http://mochi.test:8888' + path + 'file_bug552523.html';
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user