/** * This file is part of Haketilo. * * Function: Determining what to do on a given web page. * * Copyright (C) 2021 Wojtek Kosior * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * As additional permission under GNU GPL version 3 section 7, you * may distribute forms of that code without the copy of the GNU * GPL normally required by section 4, provided you include this * license notice and, in case of non-source distribution, a URL * through which recipients can access the Corresponding Source. * If you modify file(s) with this exception, you may extend this * exception to your version of the file(s), but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. * * As a special exception to the GPL, any HTML file which merely * makes function calls to this code, and for that purpose * includes it by reference shall be deemed a separate work for * copyright law purposes. If you modify this code, you may extend * this exception to your version of the code, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * I, Wojtek Kosior, thereby promise not to sue for violation of this file's * license. Although I request that you do not make use of this code in a * proprietary program, I am not going to enforce this in court. */ #IMPORT common/patterns_query_tree.js AS pqt #FROM common/sha256.js IMPORT sha256 /* * CSP rule that either blocks all scripts or only allows scripts with specified * nonce attached. */ function make_csp(nonce) { const rule = nonce ? `nonce-${nonce}` : "none"; const csp_dict = {"prefetch-src": "none", "script-src-attr": "none"}; Object.assign(csp_dict, {"script-src": rule, "script-src-elem": rule}); return Object.entries(csp_dict).map(([a, b]) => `${a} '${b}';`).join(" "); } function decide_policy(patterns_tree, url, default_allow, secret) { const policy = {allow: default_allow}; try { var payloads = pqt.search(patterns_tree, url).next().value; } catch (e) { console.error("Haketilo:", e); policy.allow = false; policy.error = {haketilo_error_type: "deciding_policy"}; } if (payloads !== undefined) { /* * mapping will be either the actual mapping identifier or "~allow" if * we matched a simple script block/allow rule. */ policy.mapping = Object.keys(payloads).sort()[0]; const payload = payloads[policy.mapping]; if (policy.mapping === "~allow") { /* Convert 0/1 back to false/true. */ policy.allow = !!payload; } else /* if (payload.identifier) */ { policy.allow = false; policy.payload = payload; /* * Hash a secret and other values into a string that's unpredictable * to someone who does not know these values. What we produce here * is not a true "nonce" because it might get produced multiple * times given the same url and mapping choice. Nevertheless, this * is reasonably good given the limitations WebExtension APIs and * environments give us. If we were using a true nonce, we'd have no * reliable way of passing it to our content scripts. */ const nonce_source = [ policy.mapping, policy.payload.identifier, url, secret ]; policy.nonce = sha256(nonce_source.join(":")); } } if (!policy.allow) policy.csp = make_csp(policy.nonce); return policy; } #EXPORT decide_policy #EXPORT () => ({allow: false, csp: make_csp()}) AS fallback_policy