mirror of
https://github.com/codex-storage/deluge.git
synced 2025-01-11 03:55:43 +00:00
[Servers] Moved check_ssl_keys and generate_ssl_keys to crypto_utils.py
With this change, we drop a core dependency from the UI. This will help group together all related functionality in one place, i.e. all security related functions. Also updated testssl.sh version to 3.0.6 (SECURITY_TEST) Closes: deluge-torrent/deluge#288
This commit is contained in:
parent
6a10e57f7e
commit
88ffd1b843
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
@ -41,12 +41,25 @@ jobs:
|
|||||||
key-server: keyserver.ubuntu.com
|
key-server: keyserver.ubuntu.com
|
||||||
install: python3-libtorrent-dbg
|
install: python3-libtorrent-dbg
|
||||||
|
|
||||||
|
- name: Sets env var for security
|
||||||
|
if: (github.event_name == 'pull_request' && contains(github.event.pull_request.body, 'security_test')) || (github.event_name == 'push' && contains(github.event.head_commit.message, 'security_test'))
|
||||||
|
run: echo "SECURITY_TESTS=True" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
pip install --upgrade pip wheel
|
pip install --upgrade pip wheel
|
||||||
pip install -r requirements.txt -r requirements-tests.txt
|
pip install -r requirements.txt -r requirements-tests.txt
|
||||||
pip install -e .
|
pip install -e .
|
||||||
|
|
||||||
|
- name: Install security dependencies
|
||||||
|
if: contains(env.SECURITY_TESTS, 'True')
|
||||||
|
run: |
|
||||||
|
wget -O- $TESTSSL_URL$TESTSSL_VER | tar xz
|
||||||
|
mv -t deluge/tests/data testssl.sh-$TESTSSL_VER/testssl.sh testssl.sh-$TESTSSL_VER/etc/;
|
||||||
|
env:
|
||||||
|
TESTSSL_VER: 3.0.6
|
||||||
|
TESTSSL_URL: https://codeload.github.com/drwetter/testssl.sh/tar.gz/refs/tags/v
|
||||||
|
|
||||||
- name: Setup core dump directory
|
- name: Setup core dump directory
|
||||||
run: |
|
run: |
|
||||||
sudo mkdir /cores/ && sudo chmod 777 /cores/
|
sudo mkdir /cores/ && sudo chmod 777 /cores/
|
||||||
@ -57,7 +70,7 @@ jobs:
|
|||||||
ulimit -c unlimited # Enable core dumps to be captured
|
ulimit -c unlimited # Enable core dumps to be captured
|
||||||
cp /usr/lib/python3/dist-packages/libtorrent*.so $GITHUB_WORKSPACE/deluge
|
cp /usr/lib/python3/dist-packages/libtorrent*.so $GITHUB_WORKSPACE/deluge
|
||||||
python -c 'from deluge._libtorrent import lt; print(lt.__version__)';
|
python -c 'from deluge._libtorrent import lt; print(lt.__version__)';
|
||||||
catchsegv python -X dev -m pytest -v -m "not (todo or gtkui or security)" deluge
|
catchsegv python -X dev -m pytest -v -m "not (todo or gtkui)" deluge
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
# capture all crashes as build artifacts
|
# capture all crashes as build artifacts
|
||||||
|
@ -12,13 +12,11 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import stat
|
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
|
|
||||||
from OpenSSL import crypto
|
|
||||||
from twisted.internet import defer, reactor
|
from twisted.internet import defer, reactor
|
||||||
from twisted.internet.protocol import Factory, connectionDone
|
from twisted.internet.protocol import Factory, connectionDone
|
||||||
|
|
||||||
@ -29,7 +27,7 @@ from deluge.core.authmanager import (
|
|||||||
AUTH_LEVEL_DEFAULT,
|
AUTH_LEVEL_DEFAULT,
|
||||||
AUTH_LEVEL_NONE,
|
AUTH_LEVEL_NONE,
|
||||||
)
|
)
|
||||||
from deluge.crypto_utils import get_context_factory
|
from deluge.crypto_utils import check_ssl_keys, get_context_factory
|
||||||
from deluge.error import (
|
from deluge.error import (
|
||||||
DelugeError,
|
DelugeError,
|
||||||
IncompatibleClient,
|
IncompatibleClient,
|
||||||
@ -588,59 +586,3 @@ class RPCServer(component.Component):
|
|||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.factory.state = 'stopping'
|
self.factory.state = 'stopping'
|
||||||
|
|
||||||
|
|
||||||
def check_ssl_keys():
|
|
||||||
"""
|
|
||||||
Check for SSL cert/key and create them if necessary
|
|
||||||
"""
|
|
||||||
ssl_dir = deluge.configmanager.get_config_dir('ssl')
|
|
||||||
if not os.path.exists(ssl_dir):
|
|
||||||
# The ssl folder doesn't exist so we need to create it
|
|
||||||
os.makedirs(ssl_dir)
|
|
||||||
generate_ssl_keys()
|
|
||||||
else:
|
|
||||||
for f in ('daemon.pkey', 'daemon.cert'):
|
|
||||||
if not os.path.exists(os.path.join(ssl_dir, f)):
|
|
||||||
generate_ssl_keys()
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def generate_ssl_keys():
|
|
||||||
"""
|
|
||||||
This method generates a new SSL key/cert.
|
|
||||||
"""
|
|
||||||
from deluge.common import PY2
|
|
||||||
|
|
||||||
digest = 'sha256' if not PY2 else b'sha256'
|
|
||||||
|
|
||||||
# Generate key pair
|
|
||||||
pkey = crypto.PKey()
|
|
||||||
pkey.generate_key(crypto.TYPE_RSA, 2048)
|
|
||||||
|
|
||||||
# Generate cert request
|
|
||||||
req = crypto.X509Req()
|
|
||||||
subj = req.get_subject()
|
|
||||||
setattr(subj, 'CN', 'Deluge Daemon')
|
|
||||||
req.set_pubkey(pkey)
|
|
||||||
req.sign(pkey, digest)
|
|
||||||
|
|
||||||
# Generate certificate
|
|
||||||
cert = crypto.X509()
|
|
||||||
cert.set_serial_number(0)
|
|
||||||
cert.gmtime_adj_notBefore(0)
|
|
||||||
cert.gmtime_adj_notAfter(60 * 60 * 24 * 365 * 3) # Three Years
|
|
||||||
cert.set_issuer(req.get_subject())
|
|
||||||
cert.set_subject(req.get_subject())
|
|
||||||
cert.set_pubkey(req.get_pubkey())
|
|
||||||
cert.sign(pkey, digest)
|
|
||||||
|
|
||||||
# Write out files
|
|
||||||
ssl_dir = deluge.configmanager.get_config_dir('ssl')
|
|
||||||
with open(os.path.join(ssl_dir, 'daemon.pkey'), 'wb') as _file:
|
|
||||||
_file.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
|
|
||||||
with open(os.path.join(ssl_dir, 'daemon.cert'), 'wb') as _file:
|
|
||||||
_file.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
|
|
||||||
# Make the files only readable by this user
|
|
||||||
for f in ('daemon.pkey', 'daemon.cert'):
|
|
||||||
os.chmod(os.path.join(ssl_dir, f), stat.S_IREAD | stat.S_IWRITE)
|
|
||||||
|
@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
from __future__ import division, print_function, unicode_literals
|
from __future__ import division, print_function, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import stat
|
||||||
|
|
||||||
|
from OpenSSL import crypto
|
||||||
from OpenSSL.crypto import FILETYPE_PEM
|
from OpenSSL.crypto import FILETYPE_PEM
|
||||||
from twisted.internet.ssl import (
|
from twisted.internet.ssl import (
|
||||||
AcceptableCiphers,
|
AcceptableCiphers,
|
||||||
@ -18,6 +22,8 @@ from twisted.internet.ssl import (
|
|||||||
TLSVersion,
|
TLSVersion,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import deluge.configmanager
|
||||||
|
|
||||||
# A TLS ciphers list.
|
# A TLS ciphers list.
|
||||||
# Sources for more information on TLS ciphers:
|
# Sources for more information on TLS ciphers:
|
||||||
# - https://wiki.mozilla.org/Security/Server_Side_TLS
|
# - https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||||
@ -77,3 +83,59 @@ def get_context_factory(cert_path, pkey_path):
|
|||||||
ctx.set_options(SSL_OP_NO_RENEGOTIATION)
|
ctx.set_options(SSL_OP_NO_RENEGOTIATION)
|
||||||
|
|
||||||
return cert_options
|
return cert_options
|
||||||
|
|
||||||
|
|
||||||
|
def check_ssl_keys():
|
||||||
|
"""
|
||||||
|
Check for SSL cert/key and create them if necessary
|
||||||
|
"""
|
||||||
|
ssl_dir = deluge.configmanager.get_config_dir('ssl')
|
||||||
|
if not os.path.exists(ssl_dir):
|
||||||
|
# The ssl folder doesn't exist so we need to create it
|
||||||
|
os.makedirs(ssl_dir)
|
||||||
|
generate_ssl_keys()
|
||||||
|
else:
|
||||||
|
for f in ('daemon.pkey', 'daemon.cert'):
|
||||||
|
if not os.path.exists(os.path.join(ssl_dir, f)):
|
||||||
|
generate_ssl_keys()
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
def generate_ssl_keys():
|
||||||
|
"""
|
||||||
|
This method generates a new SSL key/cert.
|
||||||
|
"""
|
||||||
|
from deluge.common import PY2
|
||||||
|
|
||||||
|
digest = 'sha256' if not PY2 else b'sha256'
|
||||||
|
|
||||||
|
# Generate key pair
|
||||||
|
pkey = crypto.PKey()
|
||||||
|
pkey.generate_key(crypto.TYPE_RSA, 2048)
|
||||||
|
|
||||||
|
# Generate cert request
|
||||||
|
req = crypto.X509Req()
|
||||||
|
subj = req.get_subject()
|
||||||
|
setattr(subj, 'CN', 'Deluge Daemon')
|
||||||
|
req.set_pubkey(pkey)
|
||||||
|
req.sign(pkey, digest)
|
||||||
|
|
||||||
|
# Generate certificate
|
||||||
|
cert = crypto.X509()
|
||||||
|
cert.set_serial_number(0)
|
||||||
|
cert.gmtime_adj_notBefore(0)
|
||||||
|
cert.gmtime_adj_notAfter(60 * 60 * 24 * 365 * 3) # Three Years
|
||||||
|
cert.set_issuer(req.get_subject())
|
||||||
|
cert.set_subject(req.get_subject())
|
||||||
|
cert.set_pubkey(req.get_pubkey())
|
||||||
|
cert.sign(pkey, digest)
|
||||||
|
|
||||||
|
# Write out files
|
||||||
|
ssl_dir = deluge.configmanager.get_config_dir('ssl')
|
||||||
|
with open(os.path.join(ssl_dir, 'daemon.pkey'), 'wb') as _file:
|
||||||
|
_file.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
|
||||||
|
with open(os.path.join(ssl_dir, 'daemon.cert'), 'wb') as _file:
|
||||||
|
_file.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
|
||||||
|
# Make the files only readable by this user
|
||||||
|
for f in ('daemon.pkey', 'daemon.cert'):
|
||||||
|
os.chmod(os.path.join(ssl_dir, f), stat.S_IREAD | stat.S_IWRITE)
|
||||||
|
@ -45,6 +45,7 @@ class SecurityBaseTestCase(object):
|
|||||||
get_test_data_file('testssl.sh'),
|
get_test_data_file('testssl.sh'),
|
||||||
'--quiet',
|
'--quiet',
|
||||||
'--nodns',
|
'--nodns',
|
||||||
|
'none',
|
||||||
'--color',
|
'--color',
|
||||||
'0',
|
'0',
|
||||||
test,
|
test,
|
||||||
@ -55,11 +56,11 @@ class SecurityBaseTestCase(object):
|
|||||||
def on_result(results):
|
def on_result(results):
|
||||||
|
|
||||||
if test == '-e':
|
if test == '-e':
|
||||||
results = results[0].split('\n')[7:-6]
|
results = results[0].split(b'\n')[7:-6]
|
||||||
self.assertTrue(len(results) > 3)
|
self.assertTrue(len(results) > 3)
|
||||||
else:
|
else:
|
||||||
self.assertIn('OK', results[0])
|
self.assertIn(b'OK', results[0])
|
||||||
self.assertNotIn('NOT ok', results[0])
|
self.assertNotIn(b'NOT ok', results[0])
|
||||||
|
|
||||||
d.addCallback(on_result)
|
d.addCallback(on_result)
|
||||||
return d
|
return d
|
||||||
|
@ -23,8 +23,7 @@ from twisted.web.resource import EncodingResourceWrapper
|
|||||||
|
|
||||||
from deluge import common, component, configmanager
|
from deluge import common, component, configmanager
|
||||||
from deluge.common import is_ipv6
|
from deluge.common import is_ipv6
|
||||||
from deluge.core.rpcserver import check_ssl_keys
|
from deluge.crypto_utils import check_ssl_keys, get_context_factory
|
||||||
from deluge.crypto_utils import get_context_factory
|
|
||||||
from deluge.i18n import set_language, setup_translation
|
from deluge.i18n import set_language, setup_translation
|
||||||
from deluge.ui.tracker_icons import TrackerIcons
|
from deluge.ui.tracker_icons import TrackerIcons
|
||||||
from deluge.ui.web.auth import Auth
|
from deluge.ui.web.auth import Auth
|
||||||
|
Loading…
x
Reference in New Issue
Block a user