diff options
Diffstat (limited to 'common/misc.js')
-rw-r--r-- | common/misc.js | 85 |
1 files changed, 15 insertions, 70 deletions
diff --git a/common/misc.js b/common/misc.js index 97fc2dc..9ffb7ff 100644 --- a/common/misc.js +++ b/common/misc.js @@ -1,5 +1,7 @@ /** - * Hachette miscellaneous operations refactored to a separate file + * This file is part of Haketilo. + * + * Function: Miscellaneous operations refactored to a separate file. * * Copyright (C) 2021 Wojtek Kosior * Copyright (C) 2021 jahoti @@ -36,36 +38,26 @@ function Uint8toHex(data) return returnValue; } -function gen_nonce(length) // Default 16 +function gen_nonce(length=16) { - let randomData = new Uint8Array(length || 16); + let randomData = new Uint8Array(length); crypto.getRandomValues(randomData); return Uint8toHex(randomData); } -/* csp rule that blocks all scripts except for those injected by us */ -function csp_rule(nonce) +/* CSP rule that blocks scripts according to policy's needs. */ +function make_csp_rule(policy) { - const rule = `'nonce-${nonce}'`; - return `script-src ${rule}; script-src-elem ${rule}; script-src-attr 'none'; prefetch-src 'none';`; + let rule = "prefetch-src 'none'; script-src-attr 'none';"; + const script_src = policy.has_payload ? + `'nonce-${policy.nonce}'` : "'none'"; + rule += ` script-src ${script_src}; script-src-elem ${script_src};`; + return rule; } /* Check if some HTTP header might define CSP rules. */ -const csp_header_names = new Set([ - "content-security-policy", - "x-webkit-csp", - "x-content-security-policy" -]); - -const report_only_header_name = "content-security-policy-report-only"; - -function is_csp_header_name(string, include_report_only) -{ - string = string && string.toLowerCase().trim() || ""; - - return (include_report_only && string === report_only_header_name) || - csp_header_names.has(string); -} +const csp_header_regex = + /^\s*(content-security-policy|x-webkit-csp|x-content-security-policy)/i; /* * Print item together with type, e.g. @@ -111,52 +103,6 @@ function parse_csp(csp) { return directives; } -/* Make CSP headers do our bidding, not interfere */ -function sanitize_csp_header(header, policy) -{ - const rule = `'nonce-${policy.nonce}'`; - const csp = parse_csp(header.value); - - if (!policy.allow) { - /* No snitching */ - delete csp['report-to']; - delete csp['report-uri']; - - delete csp['script-src']; - delete csp['script-src-elem']; - - csp['script-src-attr'] = ["'none'"]; - csp['prefetch-src'] = ["'none'"]; - } - - if ('script-src' in csp) - csp['script-src'].push(rule); - else - csp['script-src'] = [rule]; - - if ('script-src-elem' in csp) - csp['script-src-elem'].push(rule); - else - csp['script-src-elem'] = [rule]; - - const new_csp = Object.entries(csp).map( - i => `${i[0]} ${i[1].join(' ')};` - ); - - return {name: header.name, value: new_csp.join('')}; -} - -/* csp rule that blocks all scripts except for those injected by us */ -function make_csp_rule(policy) -{ - let rule = "prefetch-src 'none'; ", nonce = `'nonce-${policy.nonce}'`; - if (!policy.allow) { - rule += `script-src ${nonce}; script-src-elem ${nonce}; ` + - "script-src-attr 'none'; "; - } - return rule; -} - /* Regexes and objects to use as/in schemas for parse_json_with_schema(). */ const nonempty_string_matcher = /.+/; @@ -173,11 +119,10 @@ const matchers = { * EXPORTS_START * EXPORT gen_nonce * EXPORT make_csp_rule - * EXPORT is_csp_header_name + * EXPORT csp_header_regex * EXPORT nice_name * EXPORT open_in_settings * EXPORT is_privileged_url - * EXPORT sanitize_csp_header * EXPORT matchers * EXPORTS_END */ |