aboutsummaryrefslogtreecommitdiff
path: root/common/misc.js
diff options
context:
space:
mode:
Diffstat (limited to 'common/misc.js')
-rw-r--r--common/misc.js84
1 files changed, 17 insertions, 67 deletions
diff --git a/common/misc.js b/common/misc.js
index 3c7dc46..39c696f 100644
--- a/common/misc.js
+++ b/common/misc.js
@@ -45,11 +45,6 @@ function gen_nonce(length) // Default 16
return Uint8toHex(randomData);
}
-function gen_unique(url)
-{
- return sha256(get_secure_salt() + url);
-}
-
function get_secure_salt()
{
if (is_chrome)
@@ -58,72 +53,29 @@ function get_secure_salt()
return browser.runtime.getURL("dummy");
}
-/*
- * stripping url from query and target (everything after `#' or `?'
- * gets removed)
- */
-function url_item(url)
-{
- let url_re = /^([^?#]*).*$/;
- let match = url_re.exec(url);
- return match[1];
-}
-
-/*
- * Assume a url like:
- * https://example.com/green?illuminati=confirmed#<injected-policy>#winky
- * This function will make it into an object like:
- * {
- * "base_url": "https://example.com/green?illuminati=confirmed",
- * "target": "#<injected-policy>",
- * "target2": "#winky",
- * "policy": <injected-policy-as-js-object>,
- * "current": <boolean-indicating-whether-policy-url-matches>
- * }
- * In case url doesn't have 2 #'s, target2 and target can be set to undefined.
- */
-function url_extract_target(url)
+function extract_signed(signature, data, times)
{
- const url_re = /^([^#]*)((#[^#]*)(#.*)?)?$/;
- const match = url_re.exec(url);
- const targets = {
- base_url: match[1],
- target: match[3] || "",
- target2: match[4] || ""
- };
- if (!targets.target)
- return targets;
-
- /* %7B -> { */
- const index = targets.target.indexOf('%7B');
- if (index === -1)
- return targets;
-
const now = new Date();
- const sig = targets.target.substring(1, index);
- const policy = targets.target.substring(index);
- if (sig !== sign_policy(policy, now) &&
- sig !== sign_policy(policy, now, -1))
- return targets;
+ times ||= [[now], [now, -1]];
+
+ const reductor =
+ (ok, time) => ok || signature === sign_data(data, ...time);
+ if (!times.reduce(reductor, false))
+ return undefined;
try {
- targets.policy = JSON.parse(decodeURIComponent(policy));
- targets.current = targets.policy.base_url === targets.base_url;
+ return JSON.parse(decodeURIComponent(data));
} catch (e) {
/* This should not be reached - it's our self-produced valid JSON. */
console.log("Unexpected internal error - invalid JSON smuggled!", e);
}
-
- return targets;
}
/* csp rule that blocks all scripts except for those injected by us */
function csp_rule(nonce)
{
- let rule = `script-src 'nonce-${nonce}';`;
- if (is_chrome)
- rule += `script-src-elem 'nonce-${nonce}';`;
- return rule;
+ const rule = `'nonce-${nonce}'`;
+ return `script-src ${rule}; script-src-elem ${rule}; script-src-attr 'none'; prefetch-src 'none';`;
}
/*
@@ -149,10 +101,10 @@ function is_privileged_url(url)
return !!/^(chrome(-extension)?|moz-extension):\/\/|^about:/i.exec(url);
}
-/* Sign a given policy for a given time */
-function sign_policy(policy, now, hours_offset) {
+/* Sign a given string for a given time */
+function sign_data(data, now, hours_offset) {
let time = Math.floor(now / 3600000) + (hours_offset || 0);
- return gen_unique(time + policy);
+ return sha256(get_secure_salt() + time + data);
}
/* Parse a CSP header */
@@ -175,11 +127,11 @@ function parse_csp(csp) {
}
/* Make CSP headers do our bidding, not interfere */
-function sanitize_csp_header(header, rule, block)
+function sanitize_csp_header(header, rule, allow)
{
const csp = parse_csp(header.value);
- if (block) {
+ if (!allow) {
/* No snitching */
delete csp['report-to'];
delete csp['report-uri'];
@@ -223,10 +175,8 @@ const matchers = {
/*
* EXPORTS_START
* EXPORT gen_nonce
- * EXPORT gen_unique
- * EXPORT url_item
- * EXPORT url_extract_target
- * EXPORT sign_policy
+ * EXPORT extract_signed
+ * EXPORT sign_data
* EXPORT csp_rule
* EXPORT nice_name
* EXPORT open_in_settings