Bug 672961 - CSP blocks domains incorrectly when on a site with non-standard port. r=mrbkap

This commit is contained in:
Sid Stamm 2012-03-21 19:52:24 -04:00
parent 2cefe6b3a9
commit f0191803f3
2 changed files with 71 additions and 24 deletions

View File

@ -886,20 +886,18 @@ CSPSource.fromURI = function(aURI, self, enforceSelfChecks) {
// for port. In fact, there's no way to represent "*" differently than
// a blank port in an nsURI, since "*" turns into -1, and so does an
// absence of port declaration.
// port is never inherited from self -- this gets too confusing.
// Instead, whatever scheme is used (an explicit one or the inherited
// one) dictates the port if no port is explicitly stated.
// Set it to undefined here and the default port will be resolved in the
// getter for .port.
sObj._port = undefined;
try {
// if there's no port, an exception will get thrown
// (NS_ERROR_FAILURE)
if (aURI.port > 0) {
sObj._port = aURI.port;
} else {
// port is never inherited from self -- this gets too confusing.
// Instead, whatever scheme is used (an explicit one or the inherited
// one) dictates the port if no port is explicitly stated.
if (sObj._scheme) {
sObj._port = gIoService.getProtocolHandler(sObj._scheme).defaultPort;
if (sObj._port < 1)
sObj._port = undefined;
}
}
} catch(e) {
sObj._port = undefined;
@ -948,8 +946,8 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
CSPError("self keyword used, but no self data specified");
return null;
}
sObj._isSelf = true;
sObj._self = self.clone();
sObj._isSelf = true;
return sObj;
}
@ -1079,35 +1077,39 @@ CSPSource.validSchemeName = function(aStr) {
CSPSource.prototype = {
get scheme () {
if (this._isSelf && this._self)
return this._self.scheme;
if (!this._scheme && this._self)
return this._self.scheme;
return this._scheme;
},
get host () {
if (this._isSelf && this._self)
return this._self.host;
if (!this._host && this._self)
return this._self.host;
return this._host;
},
/**
* If 'self' has port hard-defined, and this doesn't have a port
* hard-defined, use the self's port. Otherwise, if both are implicit,
* resolve default port for this scheme.
* If this doesn't have a nonstandard port (hard-defined), use the default
* port for this source's scheme. Should never inherit port from 'self'.
*/
get port () {
if (this._isSelf && this._self)
return this._self.port;
if (this._port) return this._port;
// if no port, get the default port for the scheme.
if (this._scheme) {
// if no port, get the default port for the scheme
// (which may be inherited from 'self')
if (this.scheme) {
try {
var port = gIoService.getProtocolHandler(this._scheme).defaultPort;
var port = gIoService.getProtocolHandler(this.scheme).defaultPort;
if (port > 0) return port;
} catch(e) {
// if any errors happen, fail gracefully.
}
}
// if there was no scheme (and thus no default scheme), return self.port
if (this._self && this._self.port) return this._self.port;
return undefined;
},
@ -1121,12 +1123,12 @@ CSPSource.prototype = {
return this._self.toString();
var s = "";
if (this._scheme)
s = s + this._scheme + "://";
if (this.scheme)
s = s + this.scheme + "://";
if (this._host)
s = s + this._host;
if (this._port)
s = s + ":" + this._port;
if (this.port)
s = s + ":" + this.port;
return s;
},

View File

@ -271,7 +271,7 @@ test(
test(
function test_CSPSourceList_fromString_twohost() {
var str = "foo.bar:21 https://ras.bar";
var parsed = "foo.bar:21 https://ras.bar";
var parsed = "http://foo.bar:21 https://ras.bar:443";
var sd = CSPSourceList.fromString(str, "http://self.com:80");
//"two-host list should parse"
do_check_neq(null,sd);
@ -482,7 +482,6 @@ test(function test_CSPRep_fromString_withself() {
//"img-src does not enforce default rule, 'self'.
do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
//"img-src does not allow self
CSPdebug(cspr);
do_check_true(cspr.permits(self, SD.IMG_SRC));
//"script-src is too relaxed
do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC));
@ -577,6 +576,52 @@ test(function test_CSP_ReportURI_parsing() {
do_check_eq(parsedURIs.length, 2);
});
test(
function test_bug672961_withNonstandardSelfPort() {
/**
* When a protected document has a non-standard port, other host names
* listed as sources should inherit the scheme of the protected document
* but NOT the port. Other hosts should use the default port for the
* inherited scheme. For example, since 443 is default for HTTPS:
*
* Document with CSP: https://foobar.com:4443
* Transmitted policy:
* "allow 'self' a.com"
* Explicit policy:
* "allow https://foobar.com:4443 https://a.com:443"
*
* This test examines scheme and nonstandard port inheritance.
*/
var src;
src = CSPSource.create("a.com", "https://foobar.com:4443");
//"src should inherit and require https scheme
do_check_false(src.permits("http://a.com"));
//"src should inherit scheme 'https'"
do_check_true(src.permits("https://a.com"));
//"src should get default port
do_check_true(src.permits("https://a.com:443"));
src = CSPSource.create("http://a.com", "https://foobar.com:4443");
//"src should require http scheme"
do_check_false(src.permits("https://a.com"));
//"src should keep scheme 'http'"
do_check_true(src.permits("http://a.com"));
//"src should inherit default port for 'http'"
do_check_true(src.permits("http://a.com:80"));
src = CSPSource.create("'self'", "https://foobar.com:4443");
//"src should inherit nonstandard port from self
do_check_true(src.permits("https://foobar.com:4443"));
do_check_false(src.permits("https://foobar.com"));
do_check_false(src.permits("https://foobar.com:443"));
//"src should inherit and require https scheme from self
do_check_false(src.permits("http://foobar.com:4443"));
do_check_false(src.permits("http://foobar.com"));
});
/*
test(function test_CSPRep_fromPolicyURI_failswhenmixed() {