aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/message_server.js37
-rw-r--r--common/misc.js97
2 files changed, 91 insertions, 43 deletions
diff --git a/common/message_server.js b/common/message_server.js
new file mode 100644
index 0000000..ea40487
--- /dev/null
+++ b/common/message_server.js
@@ -0,0 +1,37 @@
+/**
+ * Hachette message server
+ *
+ * Copyright (C) 2021 Wojtek Kosior
+ * Redistribution terms are gathered in the `copyright' file.
+ */
+
+/*
+ * IMPORTS_START
+ * IMPORT browser
+ * IMPORTS_END
+ */
+
+var listeners = {};
+
+/* magic should be one of the constants from /common/connection_types.js */
+
+function listen_for_connection(magic, cb)
+{
+ listeners[magic] = cb;
+}
+
+function raw_listen(port)
+{
+ if (listeners[port.name] === undefined)
+ return;
+
+ listeners[port.name](port);
+}
+
+browser.runtime.onConnect.addListener(raw_listen);
+
+/*
+ * EXPORTS_START
+ * EXPORT listen_for_connection
+ * EXPORTS_END
+ */
diff --git a/common/misc.js b/common/misc.js
index b78dbb9..a59ec14 100644
--- a/common/misc.js
+++ b/common/misc.js
@@ -27,6 +27,23 @@ function gen_nonce()
* generating unique, per-site value that can be computed synchronously
* and is impossible to guess for a malicious website
*/
+
+/* Uint8toHex is a separate function not exported as (a) it's useful and (b) it will be used in crypto.subtle-based digests */
+function Uint8toHex(data)
+{
+ let returnValue = '';
+ for (let byte of data)
+ returnValue += ('00' + byte.toString(16)).slice(-2);
+ return returnValue;
+}
+
+function gen_nonce(length) // Default 16
+{
+ let randomData = new Uint8Array(length || 16);
+ crypto.getRandomValues(randomData);
+ return Uint8toHex(randomData);
+}
+
function gen_unique(url)
{
return sha256(get_secure_salt() + url);
@@ -52,24 +69,51 @@ function url_item(url)
}
/*
- * Assume a url like: https://example.com/green?illuminati=confirmed#tinky#winky
+ * 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" : "#tinky",
- * "target2" : "#winky"
+ * "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)
{
- let url_re = /^([^#]*)((#[^#]*)(#.*)?)?$/;
- let match = url_re.exec(url);
- return {
- base_url : match[1],
- target : match[3],
- target2 : match[4]
+ 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;
+
+ try {
+ targets.policy = JSON.parse(decodeURIComponent(policy));
+ targets.current = targets.policy.base_url === targets.base_url;
+ } 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 */
@@ -110,45 +154,12 @@ function sign_policy(policy, now, hours_offset) {
return gen_unique(time + policy);
}
-/* Extract any policy present in the URL */
-function url_extract_policy(url)
-{
- const targets = url_extract_target(url);
- 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) &&
- sig !== sign_policy(policy, now, 1)
- )
- return targets;
-
- try {
- targets.policy = JSON.parse(decodeURIComponent(policy));
- targets.current = targets.policy.base_url === targets.base_url;
- } catch (e) {
- /* TODO what should happen here? */
- }
-
- return targets;
-}
-
/*
* EXPORTS_START
* EXPORT gen_nonce
* EXPORT gen_unique
* EXPORT url_item
* EXPORT url_extract_target
- * EXPORT url_extract_policy
* EXPORT sign_policy
* EXPORT csp_rule
* EXPORT nice_name