diff options
author | Ruben Rodriguez <ruben@gnu.org> | 2015-07-13 22:53:00 -0500 |
---|---|---|
committer | Ruben Rodriguez <ruben@gnu.org> | 2015-07-13 22:53:00 -0500 |
commit | 23103d7773e24fdf15b79ed69c67089b593fb31a (patch) | |
tree | ee1b744a80dd192e62fefc72ff1f0bf978d0d24c /data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js | |
parent | 9cb91f8a48f9467e448f88984c20b3429e8a2510 (diff) |
HTTPS-Everywhere updated to 5.0.5
Diffstat (limited to 'data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js')
-rw-r--r-- | data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js | 152 |
1 files changed, 110 insertions, 42 deletions
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js index ecbaf76..fc91385 100644 --- a/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js +++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js @@ -30,6 +30,7 @@ function RuleSet(id, name, xmlName, match_rule, default_off, platform) { this.name = name; this.xmlName = xmlName; this.notes = ""; + if (match_rule) this.ruleset_match_c = new RegExp(match_rule); else this.ruleset_match_c = null; if (default_off) { @@ -108,7 +109,11 @@ RuleSet.prototype = { for (i = 0; i < this.rules.length; ++i) { // This is just for displaying inactive rules returl = urispec.replace(this.rules[i].from_c, this.rules[i].to); - if (returl != urispec) return returl; + if (returl != urispec) { + // we rewrote the uri + this.log(DBUG, "Rewrote " + urispec + " -> " + returl + " using " + this.xmlName + ": " + this.rules[i].from_c + " -> " + this.rules[i].to); + return returl; + } } return null; @@ -241,11 +246,9 @@ const RuleWriter = { return rv; }, - read: function(file, rule_store, ruleset_id) { + read: function(file) { if (!file.exists()) return null; - if ((rule_store.targets == null) && (rule_store.targets != {})) - this.log(WARN, "TARGETS IS NULL"); var data = ""; var fstream = CC["@mozilla.org/network/file-input-stream;1"] .createInstance(CI.nsIFileInputStream); @@ -262,6 +265,28 @@ const RuleWriter = { sstream.close(); fstream.close(); + return data; + }, + + write: function(file, data) { + //if (!file.exists()) + // return null; + this.log(DBUG, "Opening " + file.path + " for writing"); + var fstream = CC["@mozilla.org/network/file-output-stream;1"] + .createInstance(CI.nsIFileOutputStream); + fstream.init(file, -1, -1, 0); + + var retval = fstream.write(data, data.length); + this.log(DBUG, "Got retval " + retval); + fstream.close(); + return data; + }, + + rulesetFromFile: function(file, rule_store, ruleset_id) { + if ((rule_store.targets == null) && (rule_store.targets != {})) + this.log(WARN, "TARGETS IS NULL"); + var data = this.read(file); + if (!data) return null; return this.readFromString(data, rule_store, ruleset_id); }, @@ -442,7 +467,7 @@ const HTTPSRules = { try { this.log(DBUG,"Loading ruleset file: "+rulefiles[i].path); var ruleset_id = "custom_" + i; - RuleWriter.read(rulefiles[i], this, ruleset_id); + RuleWriter.rulesetFromFile(rulefiles[i], this, ruleset_id); } catch(e) { this.log(WARN, "Error in ruleset file: " + e); if (e.lineNumber) @@ -459,6 +484,7 @@ const HTTPSRules = { } }, + rewrittenURI: function(alist, input_uri) { // This function oversees the task of working out if a uri should be // rewritten, what it should be rewritten to, and recordkeeping of which @@ -471,7 +497,7 @@ const HTTPSRules = { // Why does JS have no tuples, again? var blob = {}; blob.newuri = null; if (!alist) this.log(DBUG, "No applicable list rewriting " + input_uri.spec); - this.log(NOTE, "Processing " + input_uri.spec); + this.log(DBUG, "Processing " + input_uri.spec); var uri = this.sanitiseURI(input_uri); @@ -493,8 +519,6 @@ const HTTPSRules = { } blob.newuri = rs[i].transformURI(uri); if (blob.newuri) { - // we rewrote the uri - this.log(DBUG, "Rewrote "+input_uri.spec); if (alist) { if (uri.spec in https_everywhere_blacklist) alist.breaking_rule(rs[i]); @@ -581,12 +605,10 @@ const HTTPSRules = { // flow? Perhaps we can preload all targets from the DB into memory at startup // so we only hit the DB when we know there is something to be had. loadRulesetById: function(ruleset_id) { - this.log(DBUG, "Querying DB for ruleset id " + ruleset_id); this.queryForRuleset.params.id = ruleset_id; try { if (this.queryForRuleset.executeStep()) { - this.log(INFO, "Found ruleset in DB for id " + ruleset_id); RuleWriter.readFromString(this.queryForRuleset.row.contents, this, ruleset_id); } else { this.log(WARN,"Couldn't find ruleset for id " + ruleset_id); @@ -613,13 +635,20 @@ const HTTPSRules = { } } } else { - this.log(INFO, "For target " + target + ", found no ids in DB"); + this.log(DBUG, "For target " + target + ", found no ids in DB"); } return output; }, + /** + * Return a list of rulesets that declare targets matching a given hostname. + * The returned rulesets include those that are disabled for various reasons. + * This function is only defined for fully-qualified hostnames. Wildcards and + * cookie-style domain attributes with a leading dot are not permitted. + * @param host {string} + * @return {Array.<RuleSet>} + */ potentiallyApplicableRulesets: function(host) { - // Return a list of rulesets that declare targets matching this host var i, tmp, t; var results = []; @@ -633,6 +662,10 @@ const HTTPSRules = { var segmented = host.split("."); for (i = 0; i < segmented.length; ++i) { tmp = segmented[i]; + if (tmp.length === 0) { + this.log(WARN,"Malformed host passed to potentiallyApplicableRulesets: " + host); + return null; + } segmented[i] = "*"; t = segmented.join("."); segmented[i] = tmp; @@ -656,7 +689,7 @@ const HTTPSRules = { // implementations, etc. var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Ci.nsIXMLHttpRequest); - req.open("GET", "https://eff.org/files/alexa-top-10000-global.txt", false); + req.open("GET", "https://www.eff.org/files/alexa-top-10000-global.txt", false); req.send(); var domains = req.response.split("\n"); var domains_l = domains.length - 1; // The last entry in this thing is bogus @@ -680,23 +713,48 @@ const HTTPSRules = { this.log(NOTE, count + " hits: average subsequent call to potentiallyApplicableRulesets took " + (t2 - t1) / domains_l + " milliseconds"); }, - shouldSecureCookie: function(applicable_list, c, known_https) { - // Check to see if the Cookie object c meets any of our cookierule citeria - // for being marked as secure. - // @applicable_list : an ApplicableList or record keeping - // @c : an nsICookie2 - // @known_https : true if we know the page setting the cookie is https + /** + * If a cookie's domain attribute has a leading dot to indicate it should be + * sent for all subdomains (".example.com"), return the actual host part (the + * part after the dot). + * + * @param cookieDomain {string} A cookie domain to strip a leading dot from. + * @return {string} a fully qualified hostname. + */ + hostFromCookieDomain: function(cookieDomain) { + if (cookieDomain.length > 0 && cookieDomain[0] == ".") { + return cookieDomain.slice(1); + } else { + return cookieDomain; + } + }, - this.log(DBUG," rawhost: " + c.rawHost + "\n name: " + c.name + "\n host" + c.host); + /** + * Check to see if the Cookie object c meets any of our cookierule citeria + * for being marked as secure. + * + * @param applicable_list {ApplicableList} an ApplicableList for record keeping + * @param c {nsICookie2} The cookie we might secure. + * @param known_https {boolean} True if the cookie appeared in an HTTPS request and + * so we know it is okay to mark it secure (assuming a cookierule matches it. + * TODO(jsha): Double-check that the code calling this actually does that. + * @return {boolean} True if the cookie in question should have the 'secure' + * flag set to true. + */ + shouldSecureCookie: function(applicable_list, c, known_https) { + this.log(DBUG," rawhost: " + c.rawHost + " name: " + c.name + " host" + c.host); var i,j; - var rs = this.potentiallyApplicableRulesets(c.host); + // potentiallyApplicableRulesets is defined on hostnames not cookie-style + // "domain" attributes, so we strip a leading dot before calling. + var rs = this.potentiallyApplicableRulesets(this.hostFromCookieDomain(c.host)); for (i = 0; i < rs.length; ++i) { var ruleset = rs[i]; if (ruleset.active) { ruleset.ensureCompiled(); // Never secure a cookie if this page might be HTTP - if (!known_https && !this.safeToSecureCookie(c.rawHost)) + if (!(known_https || this.safeToSecureCookie(c.rawHost))) { continue; + } for (j = 0; j < ruleset.cookierules.length; j++) { var cr = ruleset.cookierules[j]; if (cr.host_c.test(c.host) && cr.name_c.test(c.name)) { @@ -705,29 +763,38 @@ const HTTPSRules = { return true; } } - if (ruleset.cookierules.length > 0) - if (applicable_list) applicable_list.moot_rule(ruleset); + if (ruleset.cookierules.length > 0 && applicable_list) { + applicable_list.moot_rule(ruleset); + } } else if (ruleset.cookierules.length > 0) { - if (applicable_list) applicable_list.inactive_rule(ruleset); + if (applicable_list) { + applicable_list.inactive_rule(ruleset); + } this.log(INFO,"Inactive cookie rule " + ruleset.name); } } return false; }, + /** + * Check if the domain might be being served over HTTP. If so, it isn't + * safe to secure a cookie! We can't always know this for sure because + * observing cookie-changed doesn't give us enough context to know the + * full origin URI. In particular, if cookies are set from Javascript (as + * opposed to HTTP/HTTPS responses), we don't know what page context that + * Javascript ran in. + + * First, if there are any redirect loops on this domain, don't secure + * cookies. XXX This is not a very satisfactory heuristic. Sometimes we + * would want to secure the cookie anyway, because the URLs that loop are + * not authenticated or not important. Also by the time the loop has been + * observed and the domain blacklisted, a cookie might already have been + * flagged as secure. + * + * @param domain {string} The cookie's 'domain' attribute. + * @return {boolean} True if it's safe to secure a cookie on that domain. + */ safeToSecureCookie: function(domain) { - // Check if the domain might be being served over HTTP. If so, it isn't - // safe to secure a cookie! We can't always know this for sure because - // observing cookie-changed doesn't give us enough context to know the - // full origin URI. - - // First, if there are any redirect loops on this domain, don't secure - // cookies. XXX This is not a very satisfactory heuristic. Sometimes we - // would want to secure the cookie anyway, because the URLs that loop are - // not authenticated or not important. Also by the time the loop has been - // observed and the domain blacklisted, a cookie might already have been - // flagged as secure. - if (domain in https_blacklist_domains) { this.log(INFO, "cookies for " + domain + "blacklisted"); return false; @@ -735,7 +802,6 @@ const HTTPSRules = { // If we passed that test, make up a random URL on the domain, and see if // we would HTTPSify that. - try { var nonce_path = "/" + Math.random().toString(); nonce_path = nonce_path + nonce_path; @@ -746,17 +812,19 @@ const HTTPSRules = { return false; } - this.log(INFO, "Testing securecookie applicability with " + test_uri); - var rs = this.potentiallyApplicableRulesets(domain); + this.log(DBUG, "Testing securecookie applicability with " + test_uri); + // potentiallyApplicableRulesets is defined on hostnames not cookie-style + // "domain" attributes, so we strip a leading dot before calling. + var rs = this.potentiallyApplicableRulesets(this.hostFromCookieDomain(domain)); for (var i = 0; i < rs.length; ++i) { if (!rs[i].active) continue; var rewrite = rs[i].apply(test_uri); if (rewrite) { - this.log(INFO, "Yes: " + rewrite); + this.log(DBUG, "Safe to secure cookie for " + test_uri + ": " + rewrite); return true; } } - this.log(INFO, "(NO)"); + this.log(DBUG, "Unsafe to secure cookie for " + test_uri); return false; } }; |