aboutsummaryrefslogtreecommitdiff
path: root/background
diff options
context:
space:
mode:
Diffstat (limited to 'background')
-rw-r--r--background/cookie_filter.js17
-rw-r--r--background/main.js4
-rw-r--r--background/page_actions_server.js18
-rw-r--r--background/policy_injector.js76
-rw-r--r--background/storage.js4
-rw-r--r--background/storage_server.js4
-rw-r--r--background/stream_filter.js11
7 files changed, 99 insertions, 35 deletions
diff --git a/background/cookie_filter.js b/background/cookie_filter.js
index fea2d23..64d18b2 100644
--- a/background/cookie_filter.js
+++ b/background/cookie_filter.js
@@ -1,7 +1,8 @@
/**
- * part of Hachette
- * Filtering request headers to remove hachette cookies that might have slipped
- * through.
+ * This file is part of Haketilo.
+ *
+ * Function: Filtering request headers to remove haketilo cookies that might
+ * have slipped through.
*
* Copyright (C) 2021 Wojtek Kosior
* Redistribution terms are gathered in the `copyright' file.
@@ -13,29 +14,29 @@
* IMPORTS_END
*/
-function is_valid_hachette_cookie(cookie)
+function is_valid_haketilo_cookie(cookie)
{
- const match = /^hachette-(\w*)=(.*)$/.exec(cookie);
+ const match = /^haketilo-(\w*)=(.*)$/.exec(cookie);
if (!match)
return false;
return !extract_signed(match.slice(1, 3)).fail;
}
-function remove_hachette_cookies(header)
+function remove_haketilo_cookies(header)
{
if (header.name !== "Cookie")
return header;
const cookies = header.value.split("; ");
- const value = cookies.filter(c => !is_valid_hachette_cookie(c)).join("; ");
+ const value = cookies.filter(c => !is_valid_haketilo_cookie(c)).join("; ");
return value ? {name: "Cookie", value} : null;
}
function filter_cookie_headers(headers)
{
- return headers.map(remove_hachette_cookies).filter(h => h);
+ return headers.map(remove_haketilo_cookies).filter(h => h);
}
/*
diff --git a/background/main.js b/background/main.js
index 03cd5d7..40b3a9e 100644
--- a/background/main.js
+++ b/background/main.js
@@ -1,5 +1,7 @@
/**
- * Hachette main background script
+ * This file is part of Haketilo.
+ *
+ * Function: Main background script.
*
* Copyright (C) 2021 Wojtek Kosior
* Redistribution terms are gathered in the `copyright' file.
diff --git a/background/page_actions_server.js b/background/page_actions_server.js
index b0db5f5..156a79f 100644
--- a/background/page_actions_server.js
+++ b/background/page_actions_server.js
@@ -1,5 +1,7 @@
/**
- * Hachette serving of page actions to content scripts
+ * This file is part of Haketilo.
+ *
+ * Function: Serving page actions to content scripts.
*
* Copyright (C) 2021 Wojtek Kosior
* Redistribution terms are gathered in the `copyright' file.
@@ -25,15 +27,19 @@ let policy_observable;
function send_actions(url, port)
{
- let [pattern, settings] = query_best(storage, url);
- if (!settings)
- settings = {allow: policy_observable && policy_observable.value};
+ const [pattern, queried_settings] = query_best(storage, url);
+
+ const settings = {allow: policy_observable && policy_observable.value};
+ Object.assign(settings, queried_settings);
+ if (settings.components)
+ settings.allow = false;
+
const repos = storage.get_all(TYPE_PREFIX.REPO);
port.postMessage(["settings", [pattern, settings, repos]]);
- let components = settings.components;
- let processed_bags = new Set();
+ const components = settings.components;
+ const processed_bags = new Set();
if (components !== undefined)
send_scripts([components], port, processed_bags);
diff --git a/background/policy_injector.js b/background/policy_injector.js
index 318190b..881595b 100644
--- a/background/policy_injector.js
+++ b/background/policy_injector.js
@@ -1,5 +1,7 @@
/**
- * Hachette injecting policy to page using webRequest
+ * This file is part of Haketilo.
+ *
+ * Function: Injecting policy to page by modifying HTTP headers.
*
* Copyright (C) 2021 Wojtek Kosior
* Copyright (C) 2021 jahoti
@@ -10,33 +12,81 @@
* IMPORTS_START
* IMPORT sign_data
* IMPORT extract_signed
- * IMPORT sanitize_csp_header
* IMPORT make_csp_rule
- * IMPORT is_csp_header_name
+ * IMPORT csp_header_regex
* IMPORTS_END
*/
function inject_csp_headers(headers, policy)
{
- if (!policy.allow || policy.has_payload) {
- /* Remove report-only CSP headers that snitch on us. */
- headers = headers.filter(h => !is_csp_header_name(h.name, true));
+ let csp_headers;
+ let old_signature;
+ let haketilo_header;
- /* Add our own CSP header */
- headers.push({
- name: "content-security-policy",
- value: make_csp_rule(policy)
- });
+ for (const header of headers.filter(h => h.name === "x-haketilo")) {
+ /* x-haketilo header has format: <signature>_0_<data> */
+ const match = /^([^_]+)_(0_.*)$/.exec(header.value);
+ if (!match)
+ continue;
+
+ const result = extract_signed(...match.slice(1, 3));
+ if (result.fail)
+ continue;
+
+ /* This should succeed - it's our self-produced valid JSON. */
+ const old_data = JSON.parse(decodeURIComponent(result.data));
+
+ /* Confirmed- it's the originals, smuggled in! */
+ csp_headers = old_data.csp_headers;
+ old_signature = old_data.policy_sig;
+
+ haketilo_header = header;
+ break;
+ }
+
+ if (policy.has_payload) {
+ csp_headers = [];
+ const non_csp_headers = [];
+ const header_list =
+ h => csp_header_regex.test(h) ? csp_headers : non_csp_headers;
+ headers.forEach(h => header_list(h.name).push(h));
+ headers = non_csp_headers;
+ } else {
+ headers.push(...csp_headers || []);
}
-
+
+ if (!haketilo_header) {
+ haketilo_header = {name: "x-haketilo"};
+ headers.push(haketilo_header);
+ }
+
+ if (old_signature)
+ headers = headers.filter(h => h.value.search(old_signature) === -1);
+
const policy_str = encodeURIComponent(JSON.stringify(policy));
const signed_policy = sign_data(policy_str, new Date().getTime());
const later_30sec = new Date(new Date().getTime() + 30000).toGMTString();
headers.push({
name: "Set-Cookie",
- value: `hachette-${signed_policy.join("=")}; Expires=${later_30sec};`
+ value: `haketilo-${signed_policy.join("=")}; Expires=${later_30sec};`
});
+ /*
+ * Smuggle in the signature and the original CSP headers for future use.
+ * These are signed with a time of 0, as it's not clear there is a limit on
+ * how long Firefox might retain headers in the cache.
+ */
+ let haketilo_data = {csp_headers, policy_sig: signed_policy[0]};
+ haketilo_data = encodeURIComponent(JSON.stringify(haketilo_data));
+ haketilo_header.value = sign_data(haketilo_data, 0).join("_");
+
+ if (!policy.allow) {
+ headers.push({
+ name: "content-security-policy",
+ value: make_csp_rule(policy)
+ });
+ }
+
return headers;
}
diff --git a/background/storage.js b/background/storage.js
index 12c0c61..a4e626a 100644
--- a/background/storage.js
+++ b/background/storage.js
@@ -1,5 +1,7 @@
/**
- * Hachette storage manager
+ * This file is part of Haketilo.
+ *
+ * Function: Storage manager.
*
* Copyright (C) 2021 Wojtek Kosior
* Redistribution terms are gathered in the `copyright' file.
diff --git a/background/storage_server.js b/background/storage_server.js
index 2252eb5..73126d4 100644
--- a/background/storage_server.js
+++ b/background/storage_server.js
@@ -1,5 +1,7 @@
/**
- * Hachette storage through connection (server side)
+ * This file is part of Haketilo.
+ *
+ * Function: Storage through messages (server side).
*
* Copyright (C) 2021 Wojtek Kosior
* Redistribution terms are gathered in the `copyright' file.
diff --git a/background/stream_filter.js b/background/stream_filter.js
index 96b6132..e5e0827 100644
--- a/background/stream_filter.js
+++ b/background/stream_filter.js
@@ -1,5 +1,7 @@
/**
- * Hachette modifying a web page using the StreamFilter API
+ * This file is part of Haketilo.
+ *
+ * Function: Modifying a web page using the StreamFilter API.
*
* Copyright (C) 2018 Giorgio Maone <giorgio@maone.net>
* Copyright (C) 2021 Wojtek Kosior
@@ -12,7 +14,7 @@
/*
* IMPORTS_START
* IMPORT browser
- * IMPORT is_csp_header_name
+ * IMPORT csp_header_regex
* IMPORTS_END
*/
@@ -116,8 +118,7 @@ function may_define_csp_rules(html)
const doc = new DOMParser().parseFromString(html, "text/html");
for (const meta of doc.querySelectorAll("head>meta[http-equiv]")) {
- if (is_csp_header_name(meta.getAttribute("http-equiv"), true) &&
- meta.content)
+ if (csp_header_regex.test(meta.httpEquiv) && meta.content)
return true;
}
@@ -174,7 +175,7 @@ function filter_data(properties, event)
*/
const dummy_script =
- `<script data-hachette-deleteme="${properties.policy.nonce}" nonce="${properties.policy.nonce}">null</script>`;
+ `<script data-haketilo-deleteme="${properties.policy.nonce}" nonce="${properties.policy.nonce}">null</script>`;
const doctype_decl = /^(\s*<!doctype[^<>"']*>)?/i.exec(decoded)[0];
decoded = doctype_decl + dummy_script +
decoded.substring(doctype_decl.length);