summaryrefslogtreecommitdiffstats
path: root/deluge/tests/test_security.py
blob: 6154d32d850d831fc030916cbcb6f652c989c67d (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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# -*- coding: utf-8 -*-
#
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#

import os

import pytest
from twisted.internet.utils import getProcessOutputAndValue

import deluge.component as component
import deluge.ui.web.server
from deluge import configmanager
from deluge.common import windows_check
from deluge.ui.web.server import DelugeWeb

from .basetest import BaseTestCase
from .common import get_test_data_file
from .common_web import WebServerTestBase
from .daemon_base import DaemonBase

SECURITY_TESTS = bool(os.getenv('SECURITY_TESTS', False))


class SecurityBaseTestCase(object):
    if windows_check():
        skip = 'windows cannot run .sh files'
    elif not SECURITY_TESTS:
        skip = 'Skipping security tests'

    http_err = 'cannot run http tests on daemon'

    def __init__(self):
        self.home_dir = os.path.expanduser('~')
        self.port = 8112

    def _run_test(self, test):
        d = getProcessOutputAndValue(
            'bash',
            [
                get_test_data_file('testssl.sh'),
                '--quiet',
                '--nodns',
                'none',
                '--color',
                '0',
                test,
                '127.0.0.1:%d' % self.port,
            ],
        )

        def on_result(results):

            if test == '-e':
                results = results[0].split(b'\n')[7:-6]
                self.assertTrue(len(results) > 3)
            else:
                self.assertIn(b'OK', results[0])
                self.assertNotIn(b'NOT ok', results[0])

        d.addCallback(on_result)
        return d

    def test_secured_webserver_protocol(self):
        return self._run_test('-p')

    def test_secured_webserver_standard_ciphers(self):
        return self._run_test('-s')

    def test_secured_webserver_heartbleed_vulnerability(self):
        return self._run_test('-H')

    def test_secured_webserver_css_injection_vulnerability(self):
        return self._run_test('-I')

    def test_secured_webserver_ticketbleed_vulnerability(self):
        return self._run_test('-T')

    def test_secured_webserver_renegotiation_vulnerabilities(self):
        return self._run_test('-R')

    def test_secured_webserver_crime_vulnerability(self):
        return self._run_test('-C')

    def test_secured_webserver_breach_vulnerability(self):
        return self._run_test('-B')

    def test_secured_webserver_poodle_vulnerability(self):
        return self._run_test('-O')

    def test_secured_webserver_tls_fallback_scsv_mitigation_vulnerability(self):
        return self._run_test('-Z')

    def test_secured_webserver_sweet32_vulnerability(self):
        return self._run_test('-W')

    def test_secured_webserver_beast_vulnerability(self):
        return self._run_test('-A')

    def test_secured_webserver_lucky13_vulnerability(self):
        return self._run_test('-L')

    def test_secured_webserver_freak_vulnerability(self):
        return self._run_test('-F')

    def test_secured_webserver_logjam_vulnerability(self):
        return self._run_test('-J')

    def test_secured_webserver_drown_vulnerability(self):
        return self._run_test('-D')

    def test_secured_webserver_forward_secrecy_settings(self):
        return self._run_test('-f')

    def test_secured_webserver_rc4_ciphers(self):
        return self._run_test('-4')

    def test_secured_webserver_preference(self):
        return self._run_test('-P')

    def test_secured_webserver_headers(self):
        return self._run_test('-h')

    def test_secured_webserver_ciphers(self):
        return self._run_test('-e')


@pytest.mark.security
class DaemonSecurityTestCase(BaseTestCase, DaemonBase, SecurityBaseTestCase):

    if windows_check():
        skip = 'windows cannot start_core not enough arguments for format string'

    def __init__(self, testname):
        super(DaemonSecurityTestCase, self).__init__(testname)
        DaemonBase.__init__(self)
        SecurityBaseTestCase.__init__(self)

    def setUp(self):
        skip = False
        for not_http_test in ('breach', 'headers', 'ticketbleed'):
            if not_http_test in self.id().split('.')[-1]:
                self.skipTest(SecurityBaseTestCase.http_err)
                skip = True
        if not skip:
            super(DaemonSecurityTestCase, self).setUp()

    def set_up(self):
        d = self.common_set_up()
        self.port = self.listen_port
        d.addCallback(self.start_core)
        d.addErrback(self.terminate_core)
        return d

    def tear_down(self):
        d = component.shutdown()
        d.addCallback(self.terminate_core)
        return d


@pytest.mark.security
class WebUISecurityTestBase(WebServerTestBase, SecurityBaseTestCase):
    def __init__(self, testname):
        super(WebUISecurityTestBase, self).__init__(testname)
        SecurityBaseTestCase.__init__(self)

    def start_webapi(self, arg):
        self.port = self.webserver_listen_port = 8999

        config_defaults = deluge.ui.web.server.CONFIG_DEFAULTS.copy()
        config_defaults['port'] = self.webserver_listen_port
        config_defaults['https'] = True
        self.config = configmanager.ConfigManager('web.conf', config_defaults)

        self.deluge_web = DelugeWeb(daemon=False)

        host = list(self.deluge_web.web_api.hostlist.config['hosts'][0])
        host[2] = self.listen_port
        self.deluge_web.web_api.hostlist.config['hosts'][0] = tuple(host)
        self.host_id = host[0]
        self.deluge_web.start()