summaryrefslogtreecommitdiff
path: root/background
diff options
context:
space:
mode:
Diffstat (limited to 'background')
-rw-r--r--background/nonce_store.js30
-rw-r--r--background/page_actions_server.js2
-rw-r--r--background/policy_injector.js93
3 files changed, 67 insertions, 58 deletions
diff --git a/background/nonce_store.js b/background/nonce_store.js
deleted file mode 100644
index e5a0e78..0000000
--- a/background/nonce_store.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * Central management of HTTP(S) nonces
- *
- * Copyright (C) 2021 jahoti
- * Redistribution terms are gathered in the `copyright' file.
- */
-
-/*
- * IMPORTS_START
- * IMPORT gen_nonce
- * IMPORTS_END
- */
-
-var nonces = {};
-
-function retrieve_nonce(tabId, frameId, update)
-{
- let code = tabId + '.' + frameId;
- console.log('Nonce for ' + code + ' ' + (update ? 'created/updated' : 'requested'));
- if (update)
- nonces[code] = gen_nonce();
-
- return nonces[code];
-}
-
-/*
- * EXPORTS_START
- * EXPORT retrieve_nonce
- * EXPORTS_END
- */
diff --git a/background/page_actions_server.js b/background/page_actions_server.js
index d92b870..2d9c333 100644
--- a/background/page_actions_server.js
+++ b/background/page_actions_server.js
@@ -11,7 +11,6 @@
* IMPORT TYPE_PREFIX
* IMPORT CONNECTION_TYPE
* IMPORT browser
- * IMPORT retrieve_nonce
* IMPORT listen_for_connection
* IMPORT sha256
* IMPORT get_query_best
@@ -138,7 +137,6 @@ function handle_message(port, message, handler)
function new_connection(port)
{
console.log("new page actions connection!");
- port.postMessage(['nonce', retrieve_nonce((port.sender.tab || '').id, port.sender.frameId)]);
let handler = [];
handler.push(m => handle_message(port, m, handler));
port.onMessage.addListener(handler[0]);
diff --git a/background/policy_injector.js b/background/policy_injector.js
index 9f79425..ee97333 100644
--- a/background/policy_injector.js
+++ b/background/policy_injector.js
@@ -2,6 +2,7 @@
* Myext injecting policy to page using webRequest
*
* Copyright (C) 2021 Wojtek Kosior
+ * Copyright (C) 2021 jahoti
* Redistribution terms are gathered in the `copyright' file.
*/
@@ -11,8 +12,13 @@
* IMPORT get_storage
* IMPORT browser
* IMPORT is_chrome
- * IMPORT retrieve_nonce
+ * IMPORT is_mozilla
+ * IMPORT gen_unique
+ * IMPORT gen_nonce
+ * IMPORT is_privileged_url
* IMPORT url_item
+ * IMPORT url_extract_target
+ * IMPORT sign_policy
* IMPORT get_query_best
* IMPORT csp_rule
* IMPORTS_END
@@ -34,34 +40,60 @@ function is_csp_header(header)
return !!csp_header_names[header.name.toLowerCase()];
}
-function is_our_header(header, rule)
+function url_inject(details)
{
- return header.value === rule
+ if (is_privileged_url(details.url))
+ return;
+
+ const targets = url_extract_target(details.url);
+ if (targets.current)
+ return;
+
+ /* Redirect; update policy */
+ if (targets.policy)
+ targets.target = "";
+
+ let [pattern, settings] = query_best(targets.base_url);
+ /* Defaults */
+ if (!pattern)
+ settings = {};
+
+ const policy = encodeURIComponent(
+ JSON.stringify({
+ allow: settings.allow,
+ nonce: gen_nonce(),
+ base_url: targets.base_url
+ })
+ );
+
+ return {
+ redirectUrl: [
+ targets.base_url,
+ '#', sign_policy(policy, new Date()), policy,
+ targets.target,
+ targets.target2
+ ].join("")
+ };
}
-function inject(details)
+function headers_inject(details)
{
- const url = url_item(details.url);
-
- const [pattern, settings] = query_best(url);
-
- const nonce = retrieve_nonce(details.tabId, details.frameId, true);
- const rule = csp_rule(nonce);
-
- var headers;
-
- if (settings !== undefined && settings.allow) {
- /*
- * Chrome doesn't have the buggy behavior of repeatedly injecting a
- * header we injected once. Firefox does and we have to remove it there.
- */
- if (is_chrome)
- return {cancel: false};
-
- headers = details.responseHeaders.filter(h => !is_our_header(h, rule));
- } else {
- headers = details.responseHeaders.filter(h => !is_csp_header(h));
-
+ const targets = url_extract_target(details.url);
+ /* Block mis-/unsigned requests */
+ if (!targets.current)
+ return {cancel: true};
+
+ const rule = csp_rule(targets.policy.nonce);
+ var headers = details.responseHeaders;
+
+ /*
+ * Chrome doesn't have the buggy behavior of caching headers
+ * we injected. Firefox does and we have to remove it there.
+ */
+ if (!targets.policy.allow || is_mozilla)
+ headers = headers.filter(h => !is_csp_header(h));
+
+ if (!targets.policy.allow) {
headers.push({
name : header_name,
value : rule
@@ -80,8 +112,17 @@ async function start_policy_injector()
if (is_chrome)
extra_opts.push("extraHeaders");
+ browser.webRequest.onBeforeRequest.addListener(
+ url_inject,
+ {
+ urls: ["<all_urls>"],
+ types: ["main_frame", "sub_frame"]
+ },
+ ["blocking"]
+ );
+
browser.webRequest.onHeadersReceived.addListener(
- inject,
+ headers_inject,
{
urls: ["<all_urls>"],
types: ["main_frame", "sub_frame"]