зеркало из https://github.com/mozilla/gecko-dev.git
Bug 780978 - remove makeExplicit() from CSPUtils.jsm. (r=imelven)
This commit is contained in:
Родитель
f59f7834c5
Коммит
6910532ccd
|
@ -472,12 +472,13 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
|||
|
||||
} // end directive: loop
|
||||
|
||||
// TODO : clean this up using patch in bug 780978
|
||||
// if makeExplicit fails for any reason, default to default-src 'none'. This
|
||||
// includes the case where "default-src" is not present.
|
||||
if (aCSPR.makeExplicit())
|
||||
return aCSPR;
|
||||
return CSPRep.fromString("default-src 'none'", selfUri);
|
||||
// the X-Content-Security-Policy syntax requires an allow or default-src
|
||||
// directive to be present.
|
||||
if (!aCSPR._directives[SD.DEFAULT_SRC]) {
|
||||
cspWarn(aCSPR, CSPLocalizer.getStr("allowOrDefaultSrcRequired"));
|
||||
return CSPRep.fromString("default-src 'none'", selfUri);
|
||||
}
|
||||
return aCSPR;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -690,12 +691,7 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, docRequest, csp) {
|
|||
|
||||
} // end directive: loop
|
||||
|
||||
// TODO : clean this up using patch in bug 780978
|
||||
// if makeExplicit fails for any reason, default to default-src 'none'. This
|
||||
// includes the case where "default-src" is not present.
|
||||
if (aCSPR.makeExplicit())
|
||||
return aCSPR;
|
||||
return CSPRep.fromStringSpecCompliant("default-src 'none'", self);
|
||||
return aCSPR;
|
||||
};
|
||||
|
||||
CSPRep.prototype = {
|
||||
|
@ -763,21 +759,53 @@ CSPRep.prototype = {
|
|||
if (aURI instanceof Ci.nsIURI && aURI.scheme === "about")
|
||||
return true;
|
||||
|
||||
// make sure the context is valid
|
||||
// make sure the right directive set is used
|
||||
let DIRS = this._specCompliant ? CSPRep.SRC_DIRECTIVES_NEW : CSPRep.SRC_DIRECTIVES_OLD;
|
||||
|
||||
let contextIsSrcDir = false;
|
||||
for (var i in DIRS) {
|
||||
if (DIRS[i] === aContext) {
|
||||
return this._directives[aContext].permits(aURI);
|
||||
// for catching calls with invalid contexts (below)
|
||||
contextIsSrcDir = true;
|
||||
if (this._directives.hasOwnProperty(aContext)) {
|
||||
return this._directives[aContext].permits(aURI);
|
||||
}
|
||||
//found matching dir, can stop looking
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
// frame-ancestors is a special case; it doesn't fall back to default-src.
|
||||
if (aContext === DIRS.FRAME_ANCESTORS)
|
||||
return true;
|
||||
|
||||
// All directives that don't fall back to default-src should have an escape
|
||||
// hatch above (like frame-ancestors).
|
||||
if (!contextIsSrcDir) {
|
||||
// if this code runs, there's probably something calling permits() that
|
||||
// shouldn't be calling permits().
|
||||
CSPdebug("permits called with invalid load type: " + aContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
// no directives specifically matched, fall back to default-src.
|
||||
// (default-src may not be present for CSP 1.0-compliant policies, and
|
||||
// indicates no relevant directives were present and the load should be
|
||||
// permitted).
|
||||
if (this._directives.hasOwnProperty(DIRS.DEFAULT_SRC)) {
|
||||
return this._directives[DIRS.DEFAULT_SRC].permits(aURI);
|
||||
}
|
||||
|
||||
// no relevant directives present -- this means for CSP 1.0 that the load
|
||||
// should be permitted (and for the old CSP, to block it).
|
||||
return this._specCompliant;
|
||||
},
|
||||
|
||||
/**
|
||||
* Intersects with another CSPRep, deciding the subset policy
|
||||
* that should be enforced, and returning a new instance.
|
||||
* This assumes that either both CSPReps are specCompliant or they are both
|
||||
* not.
|
||||
* @param aCSPRep
|
||||
* a CSPRep instance to use as "other" CSP
|
||||
* @returns
|
||||
|
@ -790,12 +818,71 @@ CSPRep.prototype = {
|
|||
let DIRS = aCSPRep._specCompliant ? CSPRep.SRC_DIRECTIVES_NEW :
|
||||
CSPRep.SRC_DIRECTIVES_OLD;
|
||||
|
||||
// one or more of the two CSPReps may not have any given directive. In
|
||||
// these cases, we need to pick "all" or "none" based on the type of CSPRep
|
||||
// (spec compliant or not).
|
||||
let thisHasDefault = this._directives.hasOwnProperty(DIRS.DEFAULT_SRC),
|
||||
thatHasDefault = aCSPRep._directives.hasOwnProperty(DIRS.DEFAULT_SRC);
|
||||
for (var dir in DIRS) {
|
||||
var dirv = DIRS[dir];
|
||||
if (this._directives.hasOwnProperty(dirv))
|
||||
newRep._directives[dirv] = this._directives[dirv].intersectWith(aCSPRep._directives[dirv]);
|
||||
else
|
||||
newRep._directives[dirv] = aCSPRep._directives[dirv];
|
||||
let dirv = DIRS[dir];
|
||||
let thisHasDir = this._directives.hasOwnProperty(dirv),
|
||||
thatHasDir = aCSPRep._directives.hasOwnProperty(dirv);
|
||||
|
||||
|
||||
// if both specific src directives are absent, skip this (new policy will
|
||||
// rely on default-src)
|
||||
if (!thisHasDir && !thatHasDir) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// frame-ancestors is a special case; it doesn't fall back to
|
||||
// default-src, so only add it to newRep if one or both of the policies
|
||||
// have it.
|
||||
if (dirv === DIRS.FRAME_ANCESTORS) {
|
||||
if (thisHasDir && thatHasDir) {
|
||||
// both have frame-ancestors, intersect them.
|
||||
newRep._directives[dirv] =
|
||||
aCSPRep._directives[dirv].intersectWith(this._directives[dirv]);
|
||||
} else if (thisHasDir || thatHasDir) {
|
||||
// one or the other has frame-ancestors, copy it.
|
||||
newRep._directives[dirv] =
|
||||
( thisHasDir ? this : aCSPRep )._directives[dirv].clone();
|
||||
}
|
||||
}
|
||||
else if (aCSPRep._specCompliant) {
|
||||
// CSP 1.0 doesn't require default-src, so an intersection only makes
|
||||
// sense if there is a default-src or both policies have the directive.
|
||||
|
||||
if (!thisHasDir && !thisHasDefault) {
|
||||
// only aCSPRep has a relevant directive
|
||||
newRep._directives[dirv] = aCSPRep._directives[dirv].clone();
|
||||
}
|
||||
else if (!thatHasDir && !thatHasDefault) {
|
||||
// only "this" has a relevant directive
|
||||
newRep._directives[dirv] = this._directives[dirv].clone();
|
||||
}
|
||||
else {
|
||||
// both policies have a relevant directive (may be default-src)
|
||||
var isect1 = thisHasDir ?
|
||||
this._directives[dirv] :
|
||||
this._directives[DIRS.DEFAULT_SRC];
|
||||
var isect2 = thatHasDir ?
|
||||
aCSPRep._directives[dirv] :
|
||||
aCSPRep._directives[DIRS.DEFAULT_SRC];
|
||||
newRep._directives[dirv] = isect1.intersectWith(isect2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// pre-1.0 CSP requires a default-src, so we can assume it's here
|
||||
// (since the parser created one).
|
||||
var isect1 = thisHasDir ?
|
||||
this._directives[dirv] :
|
||||
this._directives[DIRS.DEFAULT_SRC];
|
||||
var isect2 = thatHasDir ?
|
||||
aCSPRep._directives[dirv] :
|
||||
aCSPRep._directives[DIRS.DEFAULT_SRC];
|
||||
newRep._directives[dirv] = isect1.intersectWith(isect2);
|
||||
}
|
||||
}
|
||||
|
||||
// REPORT_URI
|
||||
|
@ -828,55 +915,6 @@ CSPRep.prototype = {
|
|||
return newRep;
|
||||
},
|
||||
|
||||
/**
|
||||
* Copies default source list to each unspecified directive.
|
||||
* @returns
|
||||
* true if the makeExplicit succeeds
|
||||
* false if it fails (for some weird reason)
|
||||
*/
|
||||
makeExplicit:
|
||||
function cspsd_makeExplicit() {
|
||||
let SD = this._specCompliant ? CSPRep.SRC_DIRECTIVES_NEW : CSPRep.SRC_DIRECTIVES_OLD;
|
||||
|
||||
// It's ok for a 1.0 spec compliant policy to not have a default source,
|
||||
// in this case it should use default-src *
|
||||
// However, our original CSP implementation required a default src
|
||||
// or an allow directive.
|
||||
if (!this._directives[SD.DEFAULT_SRC]) {
|
||||
if(!this._specCompliant) {
|
||||
this.warn(CSPLocalizer.getStr("allowOrDefaultSrcRequired"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// bug 780978 will remove these lines and needs to make sure that
|
||||
// CSPRep.permits() enforces this logic: prefixed headers default to
|
||||
// "disallowed" and unprefixed headers default to "allowed" when
|
||||
// neither specific -src nor default-src directive is provided.
|
||||
this._directives[SD.DEFAULT_SRC]
|
||||
= CSPSourceList.fromString("*", this, this._self, true);
|
||||
this._directives[SD.DEFAULT_SRC]._isImplicit = true;
|
||||
}
|
||||
|
||||
var defaultSrcDir = this._directives[SD.DEFAULT_SRC];
|
||||
|
||||
for (var dir in SD) {
|
||||
var dirv = SD[dir];
|
||||
if (dirv === SD.DEFAULT_SRC) continue;
|
||||
if (!this._directives[dirv]) {
|
||||
// implicit directive, make explicit.
|
||||
// All but frame-ancestors directive inherit from 'allow' (bug 555068)
|
||||
if (dirv === SD.FRAME_ANCESTORS)
|
||||
this._directives[dirv] = CSPSourceList.fromString("*",this);
|
||||
else
|
||||
this._directives[dirv] = defaultSrcDir.clone();
|
||||
this._directives[dirv]._isImplicit = true;
|
||||
}
|
||||
}
|
||||
|
||||
this._isInitialized = true;
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if "eval" is enabled through the "eval" keyword.
|
||||
*/
|
||||
|
@ -942,10 +980,6 @@ this.CSPSourceList = function CSPSourceList() {
|
|||
this._sources = [];
|
||||
this._permitAllSources = false;
|
||||
|
||||
// Set to true when this list is created using "makeExplicit()"
|
||||
// It's useful to know this when reporting the directive that was violated.
|
||||
this._isImplicit = false;
|
||||
|
||||
// When this is true, the source list contains 'unsafe-inline'.
|
||||
this._allowUnsafeInline = false;
|
||||
|
||||
|
@ -1175,9 +1209,6 @@ CSPSourceList.prototype = {
|
|||
newCSPSrcList._sources = isrcs;
|
||||
}
|
||||
|
||||
// if either was explicit, so is this.
|
||||
newCSPSrcList._isImplicit = this._isImplicit && that._isImplicit;
|
||||
|
||||
if ((!newCSPSrcList._CSPRep) && that._CSPRep) {
|
||||
newCSPSrcList._CSPRep = that._CSPRep;
|
||||
}
|
||||
|
|
|
@ -558,10 +558,24 @@ ContentSecurityPolicy.prototype = {
|
|||
if (res != Ci.nsIContentPolicy.ACCEPT) {
|
||||
CSPdebug("blocking request for " + aContentLocation.asciiSpec);
|
||||
try {
|
||||
let directive = this._policy._directives[cspContext];
|
||||
let violatedPolicy = (directive._isImplicit
|
||||
? 'default-src' : cspContext)
|
||||
+ ' ' + directive.toString();
|
||||
let directive = "unknown directive",
|
||||
violatedPolicy = "unknown policy";
|
||||
|
||||
// The policy might not explicitly declare each source directive (so
|
||||
// the cspContext may be implicit). If so, we have to report
|
||||
// violations as appropriate: specific or the default-src directive.
|
||||
if (this._policy._directives.hasOwnProperty(cspContext)) {
|
||||
directive = this._policy._directives[cspContext];
|
||||
violatedPolicy = cspContext + ' ' + directive.toString();
|
||||
} else if (this._policy._directives.hasOwnProperty("default-src")) {
|
||||
directive = this._policy._directives["default-src"];
|
||||
violatedPolicy = "default-src " + directive.toString();
|
||||
} else {
|
||||
violatedPolicy = "unknown directive";
|
||||
CSPdebug('ERROR in blocking content: ' +
|
||||
'CSP is not sure which part of the policy caused this block');
|
||||
}
|
||||
|
||||
this._asyncReportViolation(aContentLocation, aOriginalUri, violatedPolicy);
|
||||
} catch(e) {
|
||||
CSPdebug('---------------- ERROR: ' + e);
|
||||
|
|
|
@ -372,15 +372,6 @@ test(
|
|||
// "DEFAULT_SRC directive is missing when specified in fromString"
|
||||
do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
|
||||
|
||||
// ... and check that the other directives were auto-filled with the
|
||||
// DEFAULT_SRC one.
|
||||
cspr_allowval = cspr._directives[SD.DEFAULT_SRC];
|
||||
for(var d in SD) {
|
||||
//"Missing key " + d
|
||||
do_check_has_key(cspr._directives, SD[d]);
|
||||
//"Implicit directive " + d + " has non-allow value."
|
||||
do_check_eq(cspr._directives[SD[d]].toString(), cspr_allowval.toString());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
@ -394,24 +385,13 @@ test(
|
|||
// "DEFAULT_SRC directive is missing when specified in fromString"
|
||||
do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
|
||||
|
||||
// check that the other directives were auto-filled with the
|
||||
// DEFAULT_SRC one.
|
||||
cspr_default_val = cspr._directives[SD.DEFAULT_SRC];
|
||||
for (var d in SD) {
|
||||
do_check_has_key(cspr._directives, SD[d]);
|
||||
// "Implicit directive " + d + " has non-default-src value."
|
||||
do_check_eq(cspr._directives[SD[d]].toString(), cspr_default_val.toString());
|
||||
}
|
||||
|
||||
// check that |allow *| and |default-src *| are parsed equivalently and
|
||||
// result in the same set of explicit policy directives
|
||||
cspr = CSPRep.fromString("default-src *", URI("http://self.com:80"));
|
||||
cspr_allow = CSPRep.fromString("allow *", URI("http://self.com:80"));
|
||||
|
||||
for (var d in SD) {
|
||||
do_check_equivalent(cspr._directives[SD[d]],
|
||||
cspr_allow._directives[SD[d]]);
|
||||
}
|
||||
do_check_equivalent(cspr._directives['default-src'],
|
||||
cspr_allow._directives['default-src']);
|
||||
});
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче