Bug 971341: Fix infinite tab loading due to missing characters in CSP's path regexes r=sstamm

This commit is contained in:
Garrett Robinson 2014-04-02 10:57:35 -07:00
parent 36d8723d7c
commit 3a7bbfce46
3 changed files with 65 additions and 36 deletions

View File

@ -63,22 +63,21 @@ const R_HOST = new RegExp ("\\*|(((\\*\\.)?" + R_HOSTCHAR.source +
// port = ":" ( 1*DIGIT / "*" )
const R_PORT = new RegExp ("(\\:([0-9]+|\\*))", 'i');
// path
const R_PATH = new RegExp("(\\/(([a-zA-Z0-9\\-\\_]+)\\/?)*)", 'i');
// file
const R_FILE = new RegExp("(\\/([a-zA-Z0-9\\-\\_]+)\\.([a-zA-Z]+))", 'i');
// host-source = [ scheme "://" ] host [ port path file ]
const R_HOSTSRC = new RegExp ("^((((" + R_SCHEME.source + "\\:\\/\\/)?("
const R_HOSTSRC = new RegExp ("^((" + R_SCHEME.source + "\\:\\/\\/)?("
+ R_HOST.source + ")"
+ R_PORT.source + "?)"
+ R_PATH.source + "?)"
+ R_FILE.source + "?)$", 'i');
+ R_PORT.source + "?)$", 'i');
function STRIP_INPUTDELIM(re) {
return re.replace(/(^\^)|(\$$)/g, "");
}
// ext-host-source = host-source "/" *( <VCHAR except ";" and ","> )
// ; ext-host-source is reserved for future use.
const R_EXTHOSTSRC = new RegExp ("^" + R_HOSTSRC.source + "\\/[:print:]+$", 'i');
const R_VCHAR_EXCEPT = new RegExp("[!-+--:<-~]"); // ranges exclude , and ;
const R_EXTHOSTSRC = new RegExp ("^" + STRIP_INPUTDELIM(R_HOSTSRC.source)
+ "\\/"
+ R_VCHAR_EXCEPT.source + "*$", 'i');
// keyword-source = "'self'" / "'unsafe-inline'" / "'unsafe-eval'"
const R_KEYWORDSRC = new RegExp ("^('self'|'unsafe-inline'|'unsafe-eval')$", 'i');
@ -99,6 +98,7 @@ const R_HASHSRC = new RegExp ("^'" + R_HASH_ALGOS.source + "-" + R_BASE64.sou
// source-exp = scheme-source / host-source / keyword-source
const R_SOURCEEXP = new RegExp (R_SCHEMESRC.source + "|" +
R_HOSTSRC.source + "|" +
R_EXTHOSTSRC.source + "|" +
R_KEYWORDSRC.source + "|" +
R_NONCESRC.source + "|" +
R_HASHSRC.source, 'i');
@ -1392,7 +1392,13 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
sObj._scheme = schemeMatch[0];
}
// get array of matches to the R_HOST regular expression
// Bug 916054: in CSP 1.0, source-expressions that are paths should have
// the path after the origin ignored and only the origin enforced.
if (R_EXTHOSTSRC.test(aStr)) {
var extHostMatch = R_EXTHOSTSRC.exec(aStr);
aStr = extHostMatch[1];
}
var hostMatch = R_HOSTSRC.exec(aStr);
if (!hostMatch) {
cspError(aCSPRep, CSPLocalizer.getFormatStr("couldntParseInvalidSource",
@ -1400,24 +1406,20 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
return null;
}
// Host regex gets scheme, so remove scheme from aStr. Add 3 for '://'
if (schemeMatch)
if (schemeMatch) {
hostMatch = R_HOSTSRC.exec(aStr.substring(schemeMatch[0].length + 3));
// Bug 916054: in CSP 1.0, source-expressions that are paths should have
// the path after the origin ignored and only the origin enforced.
hostMatch[0] = hostMatch[0].replace(R_FILE, "");
hostMatch[0] = hostMatch[0].replace(R_PATH, "");
}
var portMatch = R_PORT.exec(hostMatch);
// Host regex also gets port, so remove the port here.
if (portMatch)
if (portMatch) {
hostMatch = R_HOSTSRC.exec(hostMatch[0].substring(0, hostMatch[0].length - portMatch[0].length));
}
sObj._host = CSPHost.fromString(hostMatch[0]);
if (!portMatch) {
// gets the default port for the given scheme
defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
var defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
if (!defPort) {
cspError(aCSPRep,
CSPLocalizer.getFormatStr("couldntParseInvalidSource",
@ -1440,12 +1442,14 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
}
// check for a nonce-source match
if (R_NONCESRC.test(aStr))
if (R_NONCESRC.test(aStr)) {
return CSPNonceSource.fromString(aStr, aCSPRep);
}
// check for a hash-source match
if (R_HASHSRC.test(aStr))
if (R_HASHSRC.test(aStr)) {
return CSPHashSource.fromString(aStr, aCSPRep);
}
// check for 'self' (case insensitive)
if (aStr.toLowerCase() === "'self'") {

View File

@ -27,6 +27,7 @@ var policies = [
["allowed", "test1.example.com/path-1/path_2/file_1.js"],
["allowed", "test1.example.com/path-1/path_2/file-2.js"],
["allowed", "test1.example.com/path-1/path_2/f.js"],
["allowed", "test1.example.com/path-1/path_2/f.oo.js"],
["allowed", "*.example.com"],
["allowed", "*.example.com/"],
["allowed", "*.example.com/path-1"],
@ -36,6 +37,7 @@ var policies = [
["allowed", "*.example.com/path-1/path_2/file_1.js"],
["allowed", "*.example.com/path-1/path_2/file-2.js"],
["allowed", "*.example.com/path-1/path_2/f.js"],
["allowed", "*.example.com/path-1/path_2/f.oo.js"],
["allowed", "test1.example.com:80"],
["allowed", "test1.example.com:80/"],
["allowed", "test1.example.com:80/path-1"],
@ -43,6 +45,7 @@ var policies = [
["allowed", "test1.example.com:80/path-1/path_2"],
["allowed", "test1.example.com:80/path-1/path_2/"],
["allowed", "test1.example.com:80/path-1/path_2/file.js"],
["allowed", "test1.example.com:80/path-1/path_2/f.ile.js"],
["allowed", "test1.example.com:*"],
["allowed", "test1.example.com:*/"],
["allowed", "test1.example.com:*/path-1"],
@ -50,13 +53,9 @@ var policies = [
["allowed", "test1.example.com:*/path-1/path_2"],
["allowed", "test1.example.com:*/path-1/path_2/"],
["allowed", "test1.example.com:*/path-1/path_2/file.js"],
["allowed", "test1.example.com:*/path-1/path_2/f.ile.js"],
// the following tests should fail
["blocked", "test1.example.com/path-1//path_2"],
["blocked", "test1.example.com/path-1/file.js.cpp"],
["blocked", "test1.example.com:88path-1/"],
["blocked", "test1.example.com:80//"],
["blocked", "test1.example.com:80//path-1"],
["blocked", "test1.example.com:80/.js"],
["blocked", "test1.example.com:80.js"],
["blocked", "test1.example.com:*.js"],
["blocked", "test1.example.com:*."]

View File

@ -12,6 +12,32 @@ var ioService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var self = ioService.newURI("http://test1.example.com:80", null, null);
function testValidSRCsHostSourceWithSchemeAndPath() {
var csps = [
"http://test1.example.com",
"http://test1.example.com/",
"http://test1.example.com/path-1",
"http://test1.example.com/path-1/",
"http://test1.example.com/path-1/path_2/",
"http://test1.example.com/path-1/path_2/file.js",
"http://test1.example.com/path-1/path_2/file_1.js",
"http://test1.example.com/path-1/path_2/file-2.js",
"http://test1.example.com/path-1/path_2/f.js",
"http://test1.example.com/path-1/path_2/f.oo.js"
]
var obj;
var expected = "http://test1.example.com:80";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
dump("expected: " + expected + "\n");
dump("got: " + obj._sources[0] + "\n");
do_check_eq(1, obj._sources.length);
do_check_eq(obj._sources[0], expected);
}
}
function testValidSRCsRegularHost() {
var csps = [
"test1.example.com",
@ -22,7 +48,8 @@ function testValidSRCsRegularHost() {
"test1.example.com/path-1/path_2/file.js",
"test1.example.com/path-1/path_2/file_1.js",
"test1.example.com/path-1/path_2/file-2.js",
"test1.example.com/path-1/path_2/f.js"
"test1.example.com/path-1/path_2/f.js",
"test1.example.com/path-1/path_2/f.oo.js"
]
var obj;
@ -46,6 +73,7 @@ function testValidSRCsWildCardHost() {
"*.example.com/path-1/path_2/file_1.js",
"*.example.com/path-1/path_2/file-2.js",
"*.example.com/path-1/path_2/f.js",
"*.example.com/path-1/path_2/f.oo.js"
]
var obj;
@ -66,7 +94,8 @@ function testValidSRCsRegularPort() {
"test1.example.com:80/path-1/",
"test1.example.com:80/path-1/path_2",
"test1.example.com:80/path-1/path_2/",
"test1.example.com:80/path-1/path_2/file.js"
"test1.example.com:80/path-1/path_2/file.js",
"test1.example.com:80/path-1/path_2/f.ile.js"
]
var obj;
@ -87,7 +116,8 @@ function testValidSRCsWildCardPort() {
"test1.example.com:*/path-1/",
"test1.example.com:*/path-1/path_2",
"test1.example.com:*/path-1/path_2/",
"test1.example.com:*/path-1/path_2/file.js"
"test1.example.com:*/path-1/path_2/file.js",
"test1.example.com:*/path-1/path_2/f.ile.js"
]
var obj;
@ -103,12 +133,7 @@ function testValidSRCsWildCardPort() {
function testInvalidSRCs() {
var csps = [
"test1.example.com/path-1//path_2",
"test1.example.com/path-1/file.js.cpp",
"test1.example.com:88path-1/",
"test1.example.com:80//",
"test1.example.com:80//path-1",
"test1.example.com:80/.js",
"test1.example.com:80.js",
"test1.example.com:*.js",
"test1.example.com:*."
@ -124,6 +149,7 @@ function testInvalidSRCs() {
}
function run_test() {
testValidSRCsHostSourceWithSchemeAndPath();
testValidSRCsRegularHost();
testValidSRCsWildCardHost();
testValidSRCsRegularPort();