summaryrefslogtreecommitdiff
path: root/test/unit/test_policy_deciding.py
blob: a3605376e3013cbeff9246b6fcc52558f1030d1f (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# SPDX-License-Identifier: CC0-1.0

"""
Haketilo unit tests - determining what to do on a given web page
"""

# This file is part of Haketilo
#
# Copyright (C) 2021, Wojtek Kosior <koszko@koszko.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the CC0 1.0 Universal License as published by
# the Creative Commons Corporation.
#
# 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
# CC0 1.0 Universal License for more details.

import re
from hashlib import sha256
import pytest

from ..script_loader import load_script

csp_re = re.compile(r'^\S+\s+\S+;(?:\s+\S+\s+\S+;)*$')
rule_re = re.compile(r'^\s*(?P<src_kind>\S+)\s+(?P<allowed_origins>\S+)$')
def parse_csp(csp):
    '''
    Parsing of CSP string into a dict. A simplified format of CSP is assumed.
    '''
    assert csp_re.match(csp)

    result = {}

    for rule in csp.split(';')[:-1]:
        match = rule_re.match(rule)
        result[match.group('src_kind')] = match.group('allowed_origins')

    return result

@pytest.mark.get_page('https://gotmyowndoma.in')
def test_decide_policy(execute_in_page):
    """
    policy.js contains code that, using a Pattern Query Tree instance and a URL,
    decides what Haketilo should do on a page opened at that URL, i.e. whether
    it should block or allow script execution and whether it should inject its
    own scripts and which ones. Test that the policy object gets constructed
    properly.
    """
    execute_in_page(load_script('common/policy.js'))

    policy = execute_in_page(
        '''
        returnval(decide_policy(pqt.make(), "http://unkno.wn/", true, "abcd"));
        ''')
    assert policy['allow'] == True
    for prop in ('mapping', 'payload', 'nonce', 'csp'):
        assert prop not in policy

    policy = execute_in_page(
        '''{
        const tree = pqt.make();
        pqt.register(tree, "http://kno.wn", "allowed", {allow: true});
        returnval(decide_policy(tree, "http://kno.wn/", false, "abcd"));
        }''')
    assert policy['allow'] == True
    assert policy['mapping'] == 'allowed'
    for prop in ('payload', 'nonce', 'csp'):
        assert prop not in policy

    policy = execute_in_page(
        '''
        returnval(decide_policy(pqt.make(), "http://unkno.wn/", false, "abcd"));
        '''
        )
    assert policy['allow'] == False
    for prop in ('mapping', 'payload', 'nonce'):
        assert prop not in policy
    assert parse_csp(policy['csp']) == {
        'prefetch-src':    "'none'",
        'script-src-attr': "'none'",
        'script-src':      "'none'",
        'script-src-elem': "'none'"
    }

    policy = execute_in_page(
        '''{
        const tree = pqt.make();
        pqt.register(tree, "http://kno.wn", "disallowed", {allow: false});
        returnval(decide_policy(tree, "http://kno.wn/", true, "abcd"));
        }''')
    assert policy['allow'] == False
    assert policy['mapping'] == 'disallowed'
    for prop in ('payload', 'nonce'):
        assert prop not in policy
    assert parse_csp(policy['csp']) == {
        'prefetch-src':    "'none'",
        'script-src-attr': "'none'",
        'script-src':      "'none'",
        'script-src-elem': "'none'"
    }

    policy = execute_in_page(
        '''{
        const tree = pqt.make();
        pqt.register(tree, "http://kno.wn", "m1", {identifier: "res1"});
        returnval(decide_policy(tree, "http://kno.wn/", true, "abcd"));
        }''')
    assert policy['allow'] == False
    assert policy['mapping'] == 'm1'
    assert policy['payload'] == {'identifier': 'res1'}

    assert policy['nonce'] == \
        sha256('m1:res1:http://kno.wn/:abcd'.encode()).digest().hex()
    assert parse_csp(policy['csp']) == {
        'prefetch-src':    f"'none'",
        'script-src-attr': f"'none'",
        'script-src':      f"'nonce-{policy['nonce']}'",
        'script-src-elem': f"'nonce-{policy['nonce']}'"
    }
sg-avail'>...Ludovic Courtès 2016-04-18system: Add (gnu system mapped-devices)....Ludovic Courtès 2016-02-08Add (guix build bournish) and use it in the initrd....Ludovic Courtès 2016-02-03linux-initrd: Add serpent_generic and wp512 to the default set of modules....Mark H Weaver 2016-02-03linux-initrd: Add hid-generic and hid-apple to the default set of modules....Mark H Weaver 2016-01-17linux-initrd: Remove "usbkbd" from the default set of modules....Ludovic Courtès 2015-10-27linux-initrd: Use pata_acpi, pata_atiixp, and isci modules only on Intel....Mark H Weaver 2015-09-20linux-initrd: Add LUKS/dm-crypt modules to the initrd....Ludovic Courtès 2015-07-10gnu: Include (guix build syscalls) module in initrd/VM derivations....David Thompson 2015-07-07gnu: system: Move file-system->spec to (gnu system file-systems)....David Thompson