Bug 783497 - Fix CSPSource expression intersection to resolve "self" data. (r=jst)

This commit is contained in:
Sid Stamm 2012-08-17 15:03:24 -07:00
parent a70ab36c9b
commit 7ab0ecade7
2 changed files with 83 additions and 34 deletions

View File

@ -515,8 +515,10 @@ CSPRep.prototype = {
for (var dir in CSPRep.SRC_DIRECTIVES) {
var dirv = CSPRep.SRC_DIRECTIVES[dir];
newRep._directives[dirv] = this._directives[dirv]
.intersectWith(aCSPRep._directives[dirv]);
if (this._directives.hasOwnProperty(dirv))
newRep._directives[dirv] = this._directives[dirv].intersectWith(aCSPRep._directives[dirv]);
else
newRep._directives[dirv] = aCSPRep._directives[dirv];
}
// REPORT_URI
@ -534,12 +536,6 @@ CSPRep.prototype = {
newRep._directives[reportURIDir] = aCSPRep._directives[reportURIDir].concat();
}
for (var dir in CSPRep.SRC_DIRECTIVES) {
var dirv = CSPRep.SRC_DIRECTIVES[dir];
newRep._directives[dirv] = this._directives[dirv]
.intersectWith(aCSPRep._directives[dirv]);
}
newRep._allowEval = this.allowsEvalInScripts
&& aCSPRep.allowsEvalInScripts;
@ -779,6 +775,8 @@ CSPSourceList.prototype = {
var newCSPSrcList = null;
if (!that) return this.clone();
if (this.isNone() || that.isNone())
newCSPSrcList = CSPSourceList.fromString("'none'");
@ -1187,32 +1185,32 @@ CSPSource.prototype = {
// when a scheme, host or port is undefined.)
// port
if (!this._port)
newSource._port = that._port;
else if (!that._port)
newSource._port = this._port;
else if (this._port === "*")
newSource._port = that._port;
else if (that._port === "*")
newSource._port = this._port;
else if (that._port === this._port)
newSource._port = this._port;
if (!this.port)
newSource._port = that.port;
else if (!that.port)
newSource._port = this.port;
else if (this.port === "*")
newSource._port = that.port;
else if (that.port === "*")
newSource._port = this.port;
else if (that.port === this.port)
newSource._port = this.port;
else {
CSPError(CSPLocalizer.getFormatStr("notIntersectPort", [this.toString(), that.toString()]));
return null;
}
// scheme
if (!this._scheme)
newSource._scheme = that._scheme;
else if (!that._scheme)
newSource._scheme = this._scheme;
if (this._scheme === "*")
newSource._scheme = that._scheme;
else if (that._scheme === "*")
newSource._scheme = this._scheme;
else if (that._scheme === this._scheme)
newSource._scheme = this._scheme;
if (!this.scheme)
newSource._scheme = that.scheme;
else if (!that.scheme)
newSource._scheme = this.scheme;
if (this.scheme === "*")
newSource._scheme = that.scheme;
else if (that.scheme === "*")
newSource._scheme = this.scheme;
else if (that.scheme === this.scheme)
newSource._scheme = this.scheme;
else {
CSPError(CSPLocalizer.getFormatStr("notIntersectScheme", [this.toString(), that.toString()]));
return null;
@ -1227,14 +1225,14 @@ CSPSource.prototype = {
// error should still be reported.
// host
if (this._host && that._host) {
newSource._host = this._host.intersectWith(that._host);
} else if (this._host) {
if (this.host && that.host) {
newSource._host = this.host.intersectWith(that.host);
} else if (this.host) {
CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [that.toString()]));
newSource._host = this._host.clone();
} else if (that._host) {
newSource._host = this.host.clone();
} else if (that.host) {
CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [this.toString()]));
newSource._host = that._host.clone();
newSource._host = that.host.clone();
} else {
CSPError(CSPLocalizer.getFormatStr("intersectingSourcesWithUndefinedHosts", [this.toString(), that.toString()]));
newSource._host = CSPHost.fromString("*");

View File

@ -635,6 +635,57 @@ test(
do_check_false(p_none.permits("http://bar.com"));
});
test(
function test_bug783497_refinePolicyIssues() {
const firstPolicy = "allow 'self'; img-src 'self'; script-src 'self'; options 'bogus-option'";
const secondPolicy = "default-src 'none'; script-src 'self'";
var cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"]
.createInstance(Ci.nsIContentSecurityPolicy);
var selfURI = URI("http://self.com/");
function testPermits(aUri, aContext) {
return cspObj.shouldLoad(aContext, aUri, null, null, null, null)
== Ci.nsIContentPolicy.ACCEPT;
};
// everything is allowed by the default policy
do_check_true(testPermits(URI("http://self.com/foo.js"),
Ci.nsIContentPolicy.TYPE_SCRIPT));
do_check_true(testPermits(URI("http://other.com/foo.js"),
Ci.nsIContentPolicy.TYPE_SCRIPT));
do_check_true(testPermits(URI("http://self.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
do_check_true(testPermits(URI("http://other.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
// fold in the first policy
cspObj.refinePolicy(firstPolicy, selfURI);
// script-src and img-src are limited to self after the first policy
do_check_true(testPermits(URI("http://self.com/foo.js"),
Ci.nsIContentPolicy.TYPE_SCRIPT));
do_check_false(testPermits(URI("http://other.com/foo.js"),
Ci.nsIContentPolicy.TYPE_SCRIPT));
do_check_true(testPermits(URI("http://self.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
do_check_false(testPermits(URI("http://other.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
// fold in the second policy
cspObj.refinePolicy(secondPolicy, selfURI);
// script-src is self and img-src is none after the merge
do_check_true(testPermits(URI("http://self.com/foo.js"),
Ci.nsIContentPolicy.TYPE_SCRIPT));
do_check_false(testPermits(URI("http://other.com/foo.js"),
Ci.nsIContentPolicy.TYPE_SCRIPT));
do_check_false(testPermits(URI("http://self.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
do_check_false(testPermits(URI("http://other.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
});
/*