Bug 938652 - CSP directives and source expressions should do case-insensitive matching and comparison. r=geekboy

This commit is contained in:
Yeuk Hon Wong 2014-01-22 13:18:55 -08:00
Родитель 1ac93c7ad5
Коммит 618394c4a6
2 изменённых файлов: 80 добавлений и 15 удалений

Просмотреть файл

@ -306,7 +306,7 @@ CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp) {
dir = dir.trim();
if (dir.length < 1) continue;
var dirname = dir.split(/\s+/)[0];
var dirname = dir.split(/\s+/)[0].toLowerCase();
var dirvalue = dir.substring(dirname.length).trim();
if (aCSPR._directives.hasOwnProperty(dirname)) {
@ -564,7 +564,7 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, cs
dir = dir.trim();
if (dir.length < 1) continue;
var dirname = dir.split(/\s+/)[0];
var dirname = dir.split(/\s+/)[0].toLowerCase();
var dirvalue = dir.substring(dirname.length).trim();
dirs[dirname] = dirvalue;
}
@ -1003,7 +1003,7 @@ CSPSourceList.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
slObj._CSPRep = aCSPRep;
aStr = aStr.trim();
// w3 specifies case insensitive equality
if (aStr.toUpperCase() === "'NONE'") {
if (aStr.toLowerCase() === "'none'") {
slObj._permitAllSources = false;
return slObj;
}
@ -1071,7 +1071,7 @@ CSPSourceList.prototype = {
// sort both arrays and compare like a zipper
// XXX (sid): I think we can make this more efficient
var sortfn = function(a,b) {
return a.toString() > b.toString();
return a.toString.toLowerCase() > b.toString.toLowerCase();
};
var a_sorted = this._sources.sort(sortfn);
var b_sorted = that._sources.sort(sortfn);
@ -1418,7 +1418,7 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
return CSPHashSource.fromString(aStr, aCSPRep);
// check for 'self' (case insensitive)
if (aStr.toUpperCase() === "'SELF'") {
if (aStr.toLowerCase() === "'self'") {
if (!self) {
cspError(aCSPRep, CSPLocalizer.getStr("selfKeywordNoSelfData"));
return null;
@ -1429,13 +1429,13 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
}
// check for 'unsafe-inline' (case insensitive)
if (aStr.toUpperCase() === "'UNSAFE-INLINE'"){
if (aStr.toLowerCase() === "'unsafe-inline'"){
sObj._allowUnsafeInline = true;
return sObj;
}
// check for 'unsafe-eval' (case insensitive)
if (aStr.toUpperCase() === "'UNSAFE-EVAL'"){
if (aStr.toLowerCase() === "'unsafe-eval'"){
sObj._allowUnsafeEval = true;
return sObj;
}
@ -1556,7 +1556,7 @@ CSPSource.prototype = {
aSource = CSPSource.create(aSource, this._CSPRep);
// verify scheme
if (this.scheme != aSource.scheme)
if (this.scheme.toLowerCase() != aSource.scheme.toLowerCase())
return false;
// port is defined in 'this' (undefined means it may not be relevant
@ -1592,14 +1592,14 @@ CSPSource.prototype = {
// 2. ports match
// 3. either both hosts are undefined, or one equals the other.
if (resolveSelf)
return this.scheme === that.scheme
&& this.port === that.port
return this.scheme.toLowerCase() === that.scheme.toLowerCase()
&& this.port === that.port
&& (!(this.host || that.host) ||
(this.host && this.host.equals(that.host)));
// otherwise, compare raw (non-self-resolved values)
return this._scheme === that._scheme
&& this._port === that._port
return this._scheme.toLowerCase() === that._scheme.toLowerCase()
&& this._port === that._port
&& (!(this._host || that._host) ||
(this._host && this._host.equals(that._host)));
},
@ -1688,7 +1688,9 @@ CSPHost.prototype = {
*/
permits:
function(aHost) {
if (!aHost) aHost = CSPHost.fromString("*");
if (!aHost) {
aHost = CSPHost.fromString("*");
}
if (!(aHost instanceof CSPHost)) {
// -- compare CSPHost to String
@ -1714,7 +1716,8 @@ CSPHost.prototype = {
// * Compare from right to left.
for (var i=1; i <= thislen; i++) {
if (this._segments[thislen-i] != "*" &&
(this._segments[thislen-i] != aHost._segments[thatlen-i])) {
(this._segments[thislen-i].toLowerCase() !=
aHost._segments[thatlen-i].toLowerCase())) {
return false;
}
}
@ -1737,8 +1740,10 @@ CSPHost.prototype = {
return false;
for (var i=0; i<this._segments.length; i++) {
if (this._segments[i] != that._segments[i])
if (this._segments[i].toLowerCase() !=
that._segments[i].toLowerCase()) {
return false;
}
}
return true;
}

Просмотреть файл

@ -916,6 +916,66 @@ test(
});
test(function test_equals_does_case_insensitive_comparison() {
// NOTE: For scheme, host and keyword-host:
// (1) compare the same lower-case in two distinct objects
// (2) compare upper-case with lower-case inputs
// to test case insensitivity.
// CSPSource equals ignores case
var upperCaseHost = "http://FOO.COM";
var lowerCaseHost = "http://foo.com";
src1 = CSPSource.fromString(lowerCaseHost);
src2 = CSPSource.fromString(lowerCaseHost);
do_check_true(src1.equals(src2))
src3 = CSPSource.fromString(upperCaseHost);
do_check_true(src1.equals(src3))
// CSPHost equals ignores case
var upperCaseScheme = "HTTP";
var lowerCaseScheme = "http";
src1 = CSPHost.fromString(lowerCaseScheme);
src2 = CSPHost.fromString(lowerCaseScheme);
do_check_true(src1.equals(src2));
src3 = CSPHost.fromString(upperCaseScheme);
do_check_true(src1.equals(src3));
// CSPSourceList equals (mainly for testing keywords)
var upperCaseKeywords = "'SELF'";
var lowerCaseKeywords = "'self'";
src1 = CSPSourceList.fromString(lowerCaseKeywords);
src2 = CSPSourceList.fromString(lowerCaseKeywords);
do_check_true(src1.equals(src2))
src3 = CSPSourceList.fromString(upperCaseKeywords);
do_check_true(src1.equals(src3))
});
test(function test_csp_permits_case_insensitive() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES_NEW;
// checks directives can be case-insensitive
var selfHost = "http://self.com";
var testPolicy1 = "DEFAULT-src 'self';";
cspr = CSPRep.fromString(testPolicy1, URI(selfHost));
do_check_true(cspr.permits(URI("http://self.com"), SD.DEFAULT_SRC));
// checks hosts can be case-insensitive
var testPolicy2 = "default-src 'self' http://FOO.COM";
cspr = CSPRep.fromString(testPolicy2, URI(selfHost));
do_check_true(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC));
// checks schemes can be case-insensitive
var testPolicy3 = "default-src 'self' HTTP://foo.com";
cspr = CSPRep.fromString(testPolicy3, URI(selfHost));
do_check_true(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC));
// checks keywords can be case-insensitive
var testPolicy4 = "default-src 'NONE'";
cspr = CSPRep.fromString(testPolicy4, URI(selfHost));
do_check_false(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC));
});
/*
test(function test_CSPRep_fromPolicyURI_failswhenmixed() {