зеркало из https://github.com/mozilla/gecko-dev.git
Bug 965273 - CSP: Fix serialization and deserialization and add support for the {} characters on the host name. r=sstamm
This commit is contained in:
Родитель
409cb7fe8e
Коммит
fe9ff58e54
|
@ -45,7 +45,16 @@ const R_GETSCHEME = new RegExp ("^" + R_SCHEME.source + "(?=\\:)", 'i');
|
|||
const R_SCHEMESRC = new RegExp ("^" + R_SCHEME.source + "\\:$", 'i');
|
||||
|
||||
// host-char = ALPHA / DIGIT / "-"
|
||||
const R_HOSTCHAR = new RegExp ("[a-zA-Z0-9\\-]", 'i');
|
||||
// For the app: protocol, we need to add {} to the valid character set
|
||||
const HOSTCHAR = "{}a-zA-Z0-9\\-";
|
||||
const R_HOSTCHAR = new RegExp ("[" + HOSTCHAR + "]", 'i');
|
||||
|
||||
// Complementary character set of HOSTCHAR (characters that can't appear)
|
||||
const R_COMP_HCHAR = new RegExp ("[^" + HOSTCHAR + "]", "i");
|
||||
|
||||
// Invalid character set for host strings (which can include dots and star)
|
||||
const R_INV_HCHAR = new RegExp ("[^" + HOSTCHAR + "\\.\\*]", 'i');
|
||||
|
||||
|
||||
// host = "*" / [ "*." ] 1*host-char *( "." 1*host-char )
|
||||
const R_HOST = new RegExp ("\\*|(((\\*\\.)?" + R_HOSTCHAR.source +
|
||||
|
@ -284,10 +293,14 @@ CSPRep.ALLOW_DIRECTIVE = "allow";
|
|||
* while the policy-uri is asynchronously fetched
|
||||
* @param csp (optional)
|
||||
* the CSP object to update once the policy has been fetched
|
||||
* @param enforceSelfChecks (optional)
|
||||
* if present, and "true", will check to be sure "self" has the
|
||||
* appropriate values to inherit when they are omitted from the source.
|
||||
* @returns
|
||||
* an instance of CSPRep
|
||||
*/
|
||||
CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp) {
|
||||
CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp,
|
||||
enforceSelfChecks) {
|
||||
var SD = CSPRep.SRC_DIRECTIVES_OLD;
|
||||
var UD = CSPRep.URI_DIRECTIVES;
|
||||
var aCSPR = new CSPRep();
|
||||
|
@ -361,7 +374,8 @@ CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp) {
|
|||
CSPdebug("Skipping duplicate directive: \"" + dir + "\"");
|
||||
continue directive;
|
||||
}
|
||||
var dv = CSPSourceList.fromString(dirvalue, aCSPR, selfUri, true);
|
||||
var dv = CSPSourceList.fromString(dirvalue, aCSPR, selfUri,
|
||||
enforceSelfChecks);
|
||||
if (dv) {
|
||||
aCSPR._directives[SD.DEFAULT_SRC] = dv;
|
||||
continue directive;
|
||||
|
@ -372,7 +386,8 @@ CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp) {
|
|||
for each(var sdi in SD) {
|
||||
if (dirname === sdi) {
|
||||
// process dirs, and enforce that 'self' is defined.
|
||||
var dv = CSPSourceList.fromString(dirvalue, aCSPR, selfUri, true);
|
||||
var dv = CSPSourceList.fromString(dirvalue, aCSPR, selfUri,
|
||||
enforceSelfChecks);
|
||||
if (dv) {
|
||||
aCSPR._directives[sdi] = dv;
|
||||
continue directive;
|
||||
|
@ -526,12 +541,16 @@ CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp) {
|
|||
* while the policy-uri is asynchronously fetched
|
||||
* @param csp (optional)
|
||||
* the CSP object to update once the policy has been fetched
|
||||
* @param enforceSelfChecks (optional)
|
||||
* if present, and "true", will check to be sure "self" has the
|
||||
* appropriate values to inherit when they are omitted from the source.
|
||||
* @returns
|
||||
* an instance of CSPRep
|
||||
*/
|
||||
// When we deprecate our original CSP implementation, we rename this to
|
||||
// CSPRep.fromString and remove the existing CSPRep.fromString above.
|
||||
CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, csp) {
|
||||
CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, csp,
|
||||
enforceSelfChecks) {
|
||||
var SD = CSPRep.SRC_DIRECTIVES_NEW;
|
||||
var UD = CSPRep.URI_DIRECTIVES;
|
||||
var aCSPR = new CSPRep(true);
|
||||
|
@ -607,7 +626,8 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, cs
|
|||
for each(var sdi in SD) {
|
||||
if (dirname === sdi) {
|
||||
// process dirs, and enforce that 'self' is defined.
|
||||
var dv = CSPSourceList.fromString(dirvalue, aCSPR, self, true);
|
||||
var dv = CSPSourceList.fromString(dirvalue, aCSPR, self,
|
||||
enforceSelfChecks);
|
||||
if (dv) {
|
||||
// Check for unsafe-inline in style-src
|
||||
if (sdi === "style-src" && dv._allowUnsafeInline) {
|
||||
|
@ -1321,6 +1341,18 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
|
|||
self = CSPSource.create(self, aCSPRep, undefined, false);
|
||||
}
|
||||
|
||||
// check for 'unsafe-inline' (case insensitive)
|
||||
if (aStr.toLowerCase() === "'unsafe-inline'"){
|
||||
sObj._allowUnsafeInline = true;
|
||||
return sObj;
|
||||
}
|
||||
|
||||
// check for 'unsafe-eval' (case insensitive)
|
||||
if (aStr.toLowerCase() === "'unsafe-eval'"){
|
||||
sObj._allowUnsafeEval = true;
|
||||
return sObj;
|
||||
}
|
||||
|
||||
// Check for scheme-source match - this only matches if the source
|
||||
// string is just a scheme with no host.
|
||||
if (R_SCHEMESRC.test(aStr)) {
|
||||
|
@ -1409,18 +1441,6 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
|
|||
return sObj;
|
||||
}
|
||||
|
||||
// check for 'unsafe-inline' (case insensitive)
|
||||
if (aStr.toLowerCase() === "'unsafe-inline'"){
|
||||
sObj._allowUnsafeInline = true;
|
||||
return sObj;
|
||||
}
|
||||
|
||||
// check for 'unsafe-eval' (case insensitive)
|
||||
if (aStr.toLowerCase() === "'unsafe-eval'"){
|
||||
sObj._allowUnsafeEval = true;
|
||||
return sObj;
|
||||
}
|
||||
|
||||
cspError(aCSPRep, CSPLocalizer.getFormatStr("couldntParseInvalidSource",
|
||||
[aStr]));
|
||||
return null;
|
||||
|
@ -1490,10 +1510,10 @@ CSPSource.prototype = {
|
|||
return this._self.toString();
|
||||
|
||||
if (this._allowUnsafeInline)
|
||||
return "unsafe-inline";
|
||||
return "'unsafe-inline'";
|
||||
|
||||
if (this._allowUnsafeEval)
|
||||
return "unsafe-eval";
|
||||
return "'unsafe-eval'";
|
||||
|
||||
var s = "";
|
||||
if (this.scheme)
|
||||
|
@ -1607,7 +1627,7 @@ CSPHost.fromString = function(aStr) {
|
|||
if (!aStr) return null;
|
||||
|
||||
// host string must be LDH with dots and stars.
|
||||
var invalidChar = aStr.match(/[^a-zA-Z0-9\-\.\*]/);
|
||||
var invalidChar = aStr.match(R_INV_HCHAR);
|
||||
if (invalidChar) {
|
||||
CSPdebug("Invalid character '" + invalidChar + "' in host " + aStr);
|
||||
return null;
|
||||
|
@ -1628,7 +1648,7 @@ CSPHost.fromString = function(aStr) {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
else if (seg.match(/[^a-zA-Z0-9\-]/)) {
|
||||
else if (seg.match(R_COMP_HCHAR)) {
|
||||
// Non-wildcard segment must be LDH string
|
||||
CSPdebug("Invalid segment '" + seg + "' in host value");
|
||||
return null;
|
||||
|
|
|
@ -411,6 +411,18 @@ ContentSecurityPolicy.prototype = {
|
|||
*/
|
||||
appendPolicy:
|
||||
function csp_appendPolicy(aPolicy, selfURI, aReportOnly, aSpecCompliant) {
|
||||
return this._appendPolicyInternal(aPolicy, selfURI, aReportOnly,
|
||||
aSpecCompliant, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a new policy to our list of policies for this CSP context.
|
||||
* Only to be called from this module (not exported)
|
||||
* @returns the count of policies.
|
||||
*/
|
||||
_appendPolicyInternal:
|
||||
function csp_appendPolicy(aPolicy, selfURI, aReportOnly, aSpecCompliant,
|
||||
aEnforceSelfChecks) {
|
||||
#ifndef MOZ_B2G
|
||||
CSPdebug("APPENDING POLICY: " + aPolicy);
|
||||
CSPdebug(" SELF: " + (selfURI ? selfURI.asciiSpec : " null"));
|
||||
|
@ -443,13 +455,15 @@ ContentSecurityPolicy.prototype = {
|
|||
selfURI,
|
||||
aReportOnly,
|
||||
this._weakDocRequest.get(),
|
||||
this);
|
||||
this,
|
||||
aEnforceSelfChecks);
|
||||
} else {
|
||||
newpolicy = CSPRep.fromString(aPolicy,
|
||||
selfURI,
|
||||
aReportOnly,
|
||||
this._weakDocRequest.get(),
|
||||
this);
|
||||
this,
|
||||
aEnforceSelfChecks);
|
||||
}
|
||||
|
||||
newpolicy._specCompliant = !!aSpecCompliant;
|
||||
|
@ -950,7 +964,8 @@ ContentSecurityPolicy.prototype = {
|
|||
let specCompliant = aStream.readBoolean();
|
||||
// don't need self info because when the policy is turned back into a
|
||||
// string, 'self' is replaced with the explicit source expression.
|
||||
this.appendPolicy(polStr, null, reportOnly, specCompliant);
|
||||
this._appendPolicyInternal(polStr, null, reportOnly, specCompliant,
|
||||
false);
|
||||
}
|
||||
|
||||
// NOTE: the document instance that's deserializing this object (via its
|
||||
|
|
|
@ -114,8 +114,12 @@ test(
|
|||
h = CSPHost.fromString("foo-bar.com");
|
||||
do_check_neq(null, h); // "dashes in hosts should work"
|
||||
|
||||
|
||||
h = CSPHost.fromString("foo!bar.com");
|
||||
do_check_eq(null, h); // "special chars in hosts should fail"
|
||||
|
||||
h = CSPHost.fromString("{app-url-is-uid}");
|
||||
do_check_neq(null, h); // "Packaged apps URLs failed"
|
||||
});
|
||||
|
||||
test(
|
||||
|
@ -177,6 +181,9 @@ test(
|
|||
//Port parsing should work for all schemes
|
||||
do_check_neq(null, CSPSource.create("data:"));
|
||||
do_check_neq(null, CSPSource.create("javascript:"));
|
||||
|
||||
//"app:// URLs should work, including the {} characters.");
|
||||
do_check_neq(null, CSPSource.fromString("{app-host-is-uid}", undefined, "app://{app-host-is-uid}"));
|
||||
});
|
||||
|
||||
test(
|
||||
|
@ -218,6 +225,12 @@ test(
|
|||
//"nothing else should be allowed"
|
||||
do_check_false(src.permits("https://foobar.com"));
|
||||
|
||||
src = CSPSource.create("{app-host-is-uid}", undefined, "app://{app-host-is-uid}");
|
||||
//"src should inherit and require 'app' scheme"
|
||||
do_check_false(src.permits("https://{app-host-is-uid}"));
|
||||
//"src should inherit scheme 'app'"
|
||||
do_check_true(src.permits("app://{app-host-is-uid}"));
|
||||
|
||||
});
|
||||
|
||||
///////////////////// Test the source list //////////////////////
|
||||
|
|
Загрузка…
Ссылка в новой задаче