Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 7 additions & 12 deletions mig/install/MiGserver-template.conf
Original file line number Diff line number Diff line change
Expand Up @@ -586,24 +586,15 @@ enable_sftp_subsys = __ENABLE_SFTP_SUBSYS__
# Pure Python WsgiDAV-based webdav(s) daemon
enable_davs = __ENABLE_DAVS__
# Allow sub-optimal but still relatively strong legacy TLS support in WebDAVS
# NOTE: Python-2.7.x ssl supports TLSv1.2+ with strong ciphers and all popular
# NOTE: Python-2.7+ ssl supports TLSv1.2+ with strong ciphers and all popular
# clients (including Windows 10+ native WebDAVS) also work with those.
# NOTE: Apparently Win 7 (+8.1?) native WebDAVS only works with semi-strong
# legacy ciphers and TLSv1.0+v1.1 unless updated and enabled
# NOTE: Win 7 went EoL in January 2020 and should no longer be needed
#enable_davs_legacy_tls = False
# Pure Python pyftpdlib-based ftp(s) daemon
enable_ftps = __ENABLE_FTPS__
# Allow sub-optimal but still relatively strong legacy TLS supports in FTPS
# NOTE: Recent PyOpenSSL supports TLSv1.2+ with strong ciphers and all popular
# NOTE: Modern PyOpenSSL supports TLSv1.2+ with strong ciphers and all popular
# clients also work with those.
# NOTE: CentOS 7 native pyOpenSSL 0.13 does NOT support elliptic curve ciphers
# and FileZilla fails on listdir with remaining strong DHE ciphers.
# Installing a recent pyopenssl e.g. from the centos-openstack-X repo
# allows disabling legacy tls support without breaking FileZilla support.
# TODO: disable as soon as a recent pyopenssl version is available - the one
# from pip breaks paramiko so do NOT go there.
enable_ftps_legacy_tls = True
#enable_ftps_legacy_tls = False
# Enable WSGI served web pages (faster than CGI) - requires apache wsgi module
enable_wsgi = __ENABLE_WSGI__
# Enable system notify helper used e.g. to warn about failed user logins
Expand Down Expand Up @@ -638,6 +629,10 @@ peers_explicit_fields = __PEERS_EXPLICIT_FIELDS__
peers_contact_hint = __PEERS_CONTACT_HINT__
# Enable OpenID daemon for web access with user/pw from local user DB
enable_openid = __ENABLE_OPENID__
# Allow sub-optimal but still relatively strong legacy TLS support in OpenID 2.0
# NOTE: Python-2.7+ ssl supports TLSv1.2+ with strong ciphers and all popular
# clients also work with those.
#enable_openid_legacy_tls = False
# Enable share links for easy external exchange of data with anyone
enable_sharelinks = __ENABLE_SHARELINKS__
# Enable storage quota
Expand Down
15 changes: 12 additions & 3 deletions mig/server/grid_ftps.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
from mig.shared.accountstate import check_account_accessible
from mig.shared.base import invisible_path, force_utf8, force_native_str
from mig.shared.conf import get_configuration_object
from mig.shared.defaults import STRONG_TLS_CIPHERS, STRONG_TLS_LEGACY_CIPHERS
from mig.shared.fileio import user_chroot_exceptions
from mig.shared.griddaemons.ftps import default_max_user_hits, \
default_user_abuse_hits, default_proto_abuse_hits, \
Expand Down Expand Up @@ -318,7 +319,7 @@
self.authenticated_user = username
return True
else:
# Must raise AuthenticationFailed exception since version 1.0.0 instead

Check warning on line 322 in mig/server/grid_ftps.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (83 > 80 characters)
# of returning bool
self.authenticated_user = None
raise AuthenticationFailed()
Expand Down Expand Up @@ -387,7 +388,7 @@
return [i for i in AbstractedFS.listdir(self, path) if not
invisible_path(i)]

### Force symlinks to look like real dirs to avoid client confusion ###

Check warning on line 391 in mig/server/grid_ftps.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

too many leading '#' for block comment
def lstat(self, path):
"""Modified to always return real stat to hide symlinks"""
return self.stat(path)
Expand Down Expand Up @@ -443,7 +444,7 @@
ftp_old_path = self.fs2ftp(old_path)
_ = self.fs2ftp(new_path)
# Prevent rename of special files
if in_vgrid_share(configuration, old_path) == ftp_old_path.lstrip(os.sep):

Check warning on line 447 in mig/server/grid_ftps.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (82 > 80 characters)
logger.error("rename on vgrid share root %s :: %s" %
(ftp_old_path, old_path))
raise FilesystemError("requested rename not allowed")
Expand Down Expand Up @@ -493,14 +494,22 @@
handler.tls_data_required = True
keyfile = certfile = conf.user_ftps_key
handler.certfile = certfile
# Mimic cipher setup from other daemons
ciphers = daemon_conf['ssl_ciphers'] = None
# Harden TLS/SSL if possible, requires recent pyftpdlib
if hasattr(handler, 'ssl_context'):
dhparamsfile = configuration.user_shared_dhparams
dhparams_path = configuration.user_shared_dhparams
legacy_tls = configuration.site_enable_ftps_legacy_tls
if ciphers is not None:
use_ciphers = ciphers
elif legacy_tls:
use_ciphers = STRONG_TLS_LEGACY_CIPHERS
else:
use_ciphers = STRONG_TLS_CIPHERS
ssl_ctx = hardened_openssl_context(conf, OpenSSL, keyfile,
certfile,
dhparamsfile=dhparamsfile,
allow_pre_tlsv12=legacy_tls)
dhparamsfile=dhparams_path,
ciphers=use_ciphers)
handler.ssl_context = ssl_ctx
else:
logger.warning("Unable to enforce explicit strong TLS connections")
Expand All @@ -513,7 +522,7 @@
handler.authorizer = authorizer
handler.abstracted_fs = MiGRestrictedFilesystem
# TODO: masqueraded ftps fails from fireftp - maybe this would help?
# if configuration.user_ftps_show_address != configuration.user_ftps_address:

Check warning on line 525 in mig/server/grid_ftps.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (81 > 80 characters)
# handler.masquerade_address = socket.gethostbyname(
# configuration.user_ftps_show_address)
handler.passive_ports = conf.user_ftps_pasv_ports
Expand Down
14 changes: 13 additions & 1 deletion mig/server/grid_openid.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@
from mig.shared.base import client_id_dir, cert_field_map, force_utf8, \
force_native_str
from mig.shared.conf import get_configuration_object
from mig.shared.defaults import STRONG_TLS_CIPHERS, \
STRONG_TLS_LEGACY_CIPHERS
from mig.shared.griddaemons.openid import default_max_user_hits, \
default_user_abuse_hits, default_proto_abuse_hits, \
default_username_validator, refresh_user_creds, update_login_map, \
Expand All @@ -116,7 +118,7 @@
from mig.shared.tlsserver import hardened_ssl_context
from mig.shared.url import urlparse, urlencode, check_local_site_url, \
parse_qsl
from mig.shared.useradm import get_openid_user_dn, check_password_scramble, \

Check warning on line 121 in mig/server/grid_openid.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (81 > 80 characters)
check_hash
from mig.shared.userdb import default_db_path
from mig.shared.validstring import possible_user_id
Expand All @@ -135,7 +137,7 @@

# NOTE: response may contain password on the form
# (<Symbol Bare namespace>, 'password'): 'S3cr3tP4ssw0rd'
pw_pattern = "\(<Symbol Bare namespace>, 'password'\): '(.+)'"

Check warning on line 140 in mig/server/grid_openid.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

invalid escape sequence '\)'

Check warning on line 140 in mig/server/grid_openid.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

invalid escape sequence '\('
pw_regexp = re.compile(pw_pattern)


Expand All @@ -158,7 +160,7 @@
def valid_cert_fields(arg):
"""Make sure only valid cert field names are allowed"""
valid_job_id(arg, extra_chars=',')
if [i for i in arg.split(',') if not i in cert_field_names]:

Check warning on line 163 in mig/server/grid_openid.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

test for membership should be 'not in'
invalid_argument(arg)


Expand Down Expand Up @@ -303,7 +305,7 @@

# Add our own SReg fields to list of valid fields from sreg 1.1 spec
for (key, val) in cert_field_map.items():
if not key in sreg.data_fields:

Check warning on line 308 in mig/server/grid_openid.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

test for membership should be 'not in'
sreg.data_fields[key] = key.replace('_', ' ').title()
# print "DEBUG: sreg fields: %s" % sreg.data_fields
for name in cert_field_names:
Expand Down Expand Up @@ -475,7 +477,7 @@
# Resolve retry url, strip password and err

retry_query = {key: val for (key, val) in self.query.items()
if not key in ['password', 'err']}

Check warning on line 480 in mig/server/grid_openid.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

test for membership should be 'not in'
self.retry_url = "%s?%s" \
% (self.parsed_uri[2], urlencode(retry_query))

Expand Down Expand Up @@ -1654,6 +1656,8 @@
data_path = configuration.openid_store
daemon_conf = configuration.daemon_conf
nossl = daemon_conf['nossl']
# Mimic cipher setup from other daemons
ciphers = daemon_conf['ssl_ciphers'] = None
addr = (host, port)
# TODO: is this threaded version robust enough (thread safety)?
# OpenIDServer = OpenIDHTTPServer
Expand All @@ -1675,12 +1679,20 @@
# Use best possible SSL/TLS args for this python version
key_path = cert_path = configuration.user_openid_key
dhparams_path = configuration.user_shared_dhparams
legacy_tls = configuration.site_enable_openid_legacy_tls
if ciphers is not None:
use_ciphers = ciphers
elif legacy_tls:
use_ciphers = STRONG_TLS_LEGACY_CIPHERS
else:
use_ciphers = STRONG_TLS_CIPHERS
if not os.path.isfile(cert_path):
logger.error('No such server key: %s' % cert_path)
sys.exit(1)
logger.info('Wrapping connections in SSL')
ssl_ctx = hardened_ssl_context(configuration, key_path, cert_path,
dhparams_path)
dhparamsfile=dhparams_path,
ciphers=use_ciphers)
httpserver.socket = ssl_ctx.wrap_socket(httpserver.socket,
server_side=True)
# Override default SSLSocket accept function to inject timeout support
Expand Down
11 changes: 5 additions & 6 deletions mig/server/grid_webdavs.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@

def is_native(x): return True
elif wsgidav_major >= 3:
from wsgidav.compat import is_native

Check failure on line 85 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Name "is_native" already defined on line 83 [no-redef]
from wsgidav.debug_filter import WsgiDavDebugFilter
# No Cors middelware here
Cors = None
Expand Down Expand Up @@ -335,8 +335,7 @@
context to use in all future connections in the wrap method.

If the optional legacy_tls arg is set the STRONG_TLS_LEGACY_CIPHERS
are used instead of the STRONG_TLS_CIPHERS, and the limitation to
TLSv1.2+ is left out to allow legacy TLSv1.0 and TLSv1.1 connections.
are used instead of the STRONG_TLS_CIPHERS.
This is required to support e.g. native Windows 7 WebDAVS access with
the weak ECDHE-RSA-AES128-SHA cipher.
"""
Expand All @@ -345,17 +344,17 @@
certificate_chain, ciphers)
# logger.debug("proceed with hardening of ssl contetx")
# Set up hardened SSL context once and for all
dhparams = configuration.user_shared_dhparams
dhparams_path = configuration.user_shared_dhparams
if ciphers is not None:
use_ciphers = ciphers
elif legacy_tls:
use_ciphers = STRONG_TLS_LEGACY_CIPHERS
else:
use_ciphers = STRONG_TLS_CIPHERS
self.context = hardened_ssl_context(configuration, self.private_key,
self.certificate, dhparams,
ciphers=use_ciphers,
allow_pre_tlsv12=legacy_tls)
self.certificate,
dhparamsfile=dhparams_path,
ciphers=use_ciphers)
# logger.debug("established hardened ssl contetx")

def __force_close(self, socket_list):
Expand Down Expand Up @@ -418,7 +417,7 @@
# NOTE: we extract error reason from sys here because SSLError
# only started exposing that info in python >=2.7.9
# https://docs.python.org/2.7/library/ssl.html#ssl.SSLError
exc = sys.exc_info()[1]

Check failure on line 420 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Assignment to variable "exc" outside except: block [misc]
if exc.errno == ssl.SSL_ERROR_EOF:
# This is almost certainly due to the cherrypy engine
# 'pinging' the socket to assert it's connectable;
Expand Down Expand Up @@ -1122,31 +1121,31 @@
return result
return _impl

@__allow_handle

Check failure on line 1124 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Argument 1 to "__gdp_log" has incompatible type "Callable[[MiGFileResource, Any, Any], Any]"; expected "MiGFileResource" [arg-type]
@__gdp_log
def handle_copy(self, dest_path, depth_infinity):
"""Handle a COPY request natively, but with our restrictions"""
return super(MiGFileResource, self).handle_copy(
dest_path, depth_infinity)

@__allow_handle

Check failure on line 1131 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Argument 1 to "__gdp_log" has incompatible type "Callable[[MiGFileResource, Any], Any]"; expected "MiGFileResource" [arg-type]
@__gdp_log
def handle_move(self, dest_path):
"""Handle a MOVE request natively, but with our restrictions"""
return super(MiGFileResource, self).handle_move(dest_path)

@__allow_handle

Check failure on line 1137 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Argument 1 to "__gdp_log" has incompatible type "Callable[[MiGFileResource], Any]"; expected "MiGFileResource" [arg-type]
@__gdp_log
def handle_delete(self):
"""Handle a DELETE request natively, but with our restrictions"""
return super(MiGFileResource, self).handle_delete()

@__gdp_log

Check failure on line 1143 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Argument 1 to "__gdp_log" has incompatible type "Callable[[MiGFileResource], Any]"; expected "MiGFileResource" [arg-type]
def get_content(self):
"""Handle a GET request natively and log for GDP"""
return super(MiGFileResource, self).get_content()

@__gdp_log

Check failure on line 1148 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Argument 1 to "__gdp_log" has incompatible type "Callable[[MiGFileResource, Any], Any]"; expected "MiGFileResource" [arg-type]
def begin_write(self, content_type=None):
"""Handle a PUT request natively and log for GDP"""
return super(MiGFileResource, self).begin_write()
Expand Down Expand Up @@ -1258,20 +1257,20 @@
return result
return _impl

@__allow_handle

Check failure on line 1260 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Argument 1 to "__gdp_log" has incompatible type "Callable[[MiGFolderResource, Any, Any], Any]"; expected "MiGFolderResource" [arg-type]
@__gdp_log
def handle_copy(self, dest_path, depth_infinity):
"""Handle a COPY request natively, but with our restrictions"""
return super(MiGFolderResource, self).handle_copy(
dest_path, depth_infinity)

@__allow_handle

Check failure on line 1267 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Argument 1 to "__gdp_log" has incompatible type "Callable[[MiGFolderResource, Any], Any]"; expected "MiGFolderResource" [arg-type]
@__gdp_log
def handle_move(self, dest_path):
"""Handle a MOVE request natively, but with our restrictions"""
return super(MiGFolderResource, self).handle_move(dest_path)

@__allow_handle

Check failure on line 1273 in mig/server/grid_webdavs.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

Argument 1 to "__gdp_log" has incompatible type "Callable[[MiGFolderResource], Any]"; expected "MiGFolderResource" [arg-type]
@__gdp_log
def handle_delete(self):
"""Handle a DELETE request natively, but with our restrictions"""
Expand Down
5 changes: 5 additions & 0 deletions mig/shared/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,11 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
'SITE', 'enable_openid')
else:
self.site_enable_openid = False
if config.has_option('SITE', 'enable_openid_legacy_tls'):
self.site_enable_openid_legacy_tls = config.getboolean(
'SITE', 'enable_openid_legacy_tls')
else:
self.site_enable_openid_legacy_tls = False
if config.has_option('GLOBAL', 'user_openid_address'):
self.user_openid_address = config.get('GLOBAL',
'user_openid_address')
Expand Down
43 changes: 14 additions & 29 deletions mig/shared/tlsserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
# -- END_HEADER ---
#
Expand All @@ -40,16 +41,15 @@
def hardened_ssl_context(configuration, keyfile, certfile, dhparamsfile=None,
ciphers=STRONG_TLS_CIPHERS,
curve_priority=STRONG_TLS_CURVES,
allow_pre_tlsv12=False,
allow_pre_tlsv13=True,
allow_renegotiation=False,
):
"""Build and return a hardened native SSL context to apply to a socket"""
_logger = configuration.logger
_logger.info("enforcing strong SSL/TLS connections")
_logger.debug("using SSL/TLS ciphers: %s" % ciphers)
ssl_protocol = ssl.PROTOCOL_SSLv23
ssl_ctx = ssl.SSLContext(ssl_protocol)
ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_ctx.minimum_version = ssl.TLSVersion.TLSv1_2
ssl_ctx.load_cert_chain(certfile, keyfile)
ssl_options = 0
# NOTE: Override a number of weak and insecure legacy configurations
Expand All @@ -58,11 +58,7 @@ def hardened_ssl_context(configuration, keyfile, certfile, dhparamsfile=None,
ssl_options |= getattr(ssl, 'OP_NO_SSLv2', 0x1000000)
ssl_options |= getattr(ssl, 'OP_NO_SSLv3', 0x2000000)
ssl_options |= getattr(ssl, 'OP_NO_TLSv1', 0x4000000)
ssl_ctx.minimum_version = ssl.TLSVersion.TLSv1_1
# NOTE: refuse weak TLS protocols unless allow_pre_tlsv12
if not allow_pre_tlsv12:
ssl_options |= getattr(ssl, 'OP_NO_TLSv1_1', 0x10000000)
ssl_ctx.minimum_version = ssl.TLSVersion.TLSv1_2
ssl_options |= getattr(ssl, 'OP_NO_TLSv1_1', 0x10000000)
# NOTE: refuse slightly dated TLS 1.2 protocol unless allow_pre_tlsv13
if not allow_pre_tlsv13:
if getattr(ssl, 'HAS_TLSv1_3', False):
Expand All @@ -78,17 +74,13 @@ def hardened_ssl_context(configuration, keyfile, certfile, dhparamsfile=None,
ssl_options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0x400000)
ssl_options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0x80000)
ssl_options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0x100000)
# Useful for debugging
# ssl_options |= getattr(ssl, 'OP_NO_TICKET', 0x0004000)
# ssl_options |= getattr(ssl, 'OP_NO_TLSv1_1', 0x10000000)
# ssl_options |= getattr(ssl, 'OP_NO_TLSv1_2', 0x8000000)
if sys.version_info[:2] >= (2, 7) and ssl_ctx:
if sys.version_info[:2] >= (3, 7) and ssl_ctx:
_logger.info("enforcing strong SSL/TLS options")
_logger.debug("SSL/TLS options: %s" % ssl_options)
ssl_ctx.options |= ssl_options
else:
_logger.info("can't enforce strong SSL/TLS options")
_logger.warning("Upgrade to python 2.7.9+ for maximum security")
_logger.warning("Upgrade to python 3.7+ for maximum security")

pfs_available = False
if dhparamsfile:
Expand Down Expand Up @@ -134,7 +126,6 @@ def hardened_openssl_context(configuration, OpenSSL, keyfile, certfile,
cacertfile=None, dhparamsfile=None,
ciphers=STRONG_TLS_CIPHERS,
curve_priority=STRONG_TLS_CURVES,
allow_pre_tlsv12=False,
allow_pre_tlsv13=True,
allow_renegotiation=False,
):
Expand All @@ -143,8 +134,10 @@ def hardened_openssl_context(configuration, OpenSSL, keyfile, certfile,
SSL, crypto = OpenSSL.SSL, OpenSSL.crypto
_logger.info("enforcing strong SSL/TLS connections")
_logger.debug("using SSL/TLS ciphers: %s" % ciphers)
ssl_protocol = SSL.SSLv23_METHOD
ssl_ctx = SSL.Context(ssl_protocol)
ssl_ctx = SSL.Context(SSL.TLS_SERVER_METHOD)
ssl_ctx.set_min_proto_version(SSL.TLS1_2_VERSION)
# Mimic native ssl exposure of options
ssl_ctx._minimum_version = SSL.TLS1_2_VERSION
ssl_ctx.use_certificate_chain_file(certfile)
ssl_ctx.use_privatekey_file(keyfile)
if cacertfile:
Expand All @@ -157,15 +150,7 @@ def hardened_openssl_context(configuration, OpenSSL, keyfile, certfile,
ssl_options |= getattr(SSL, 'OP_NO_SSLv2', 0x1000000)
ssl_options |= getattr(SSL, 'OP_NO_SSLv3', 0x2000000)
ssl_options |= getattr(SSL, 'OP_NO_TLSv1', 0x4000000)
ssl_ctx.set_min_proto_version(SSL.TLS1_1_VERSION)
# Mimic native ssl exposure of options
ssl_ctx._minimum_version = SSL.TLS1_1_VERSION
# NOTE: refuse weak TLS protocols unless allow_pre_tlsv12
if not allow_pre_tlsv12:
ssl_options |= getattr(SSL, 'OP_NO_TLSv1_1', 0x10000000)
ssl_ctx.set_min_proto_version(SSL.TLS1_2_VERSION)
# Mimic native ssl exposure of options
ssl_ctx._minimum_version = SSL.TLS1_2_VERSION
ssl_options |= getattr(SSL, 'OP_NO_TLSv1_1', 0x10000000)
# NOTE: refuse slightly dated TLS 1.2 protocol unless allow_pre_tlsv13
if not allow_pre_tlsv13:
# IMPORTANT: OpenSSL doesn't have TLSv1.3 support marker at the moment,
Expand All @@ -186,15 +171,15 @@ def hardened_openssl_context(configuration, OpenSSL, keyfile, certfile,
ssl_options |= getattr(SSL, 'OP_CIPHER_SERVER_PREFERENCE', 0x400000)
ssl_options |= getattr(SSL, 'OP_SINGLE_ECDH_USE', 0x80000)
ssl_options |= getattr(SSL, 'OP_SINGLE_DH_USE', 0x100000)
if sys.version_info[:2] >= (2, 7) and ssl_ctx:
if sys.version_info[:2] >= (3, 7) and ssl_ctx:
_logger.info("enforcing strong SSL/TLS options")
_logger.debug("SSL/TLS options: %s" % ssl_options)
ssl_ctx.set_options(ssl_options)
# Mimic native ssl exposure of options
ssl_ctx._options = ssl_options
else:
_logger.info("can't enforce strong SSL/TLS options")
_logger.warning("Upgrade to python 2.7.9+ for maximum security")
_logger.warning("Upgrade to python 3.7+ for maximum security")
# Mimic native ssl exposure of options
ssl_ctx._options = None

Expand Down
19 changes: 7 additions & 12 deletions tests/fixture/confs-stdlocal/MiGserver.conf
Original file line number Diff line number Diff line change
Expand Up @@ -586,24 +586,15 @@ enable_sftp_subsys = False
# Pure Python WsgiDAV-based webdav(s) daemon
enable_davs = False
# Allow sub-optimal but still relatively strong legacy TLS support in WebDAVS
# NOTE: Python-2.7.x ssl supports TLSv1.2+ with strong ciphers and all popular
# NOTE: Python-2.7+ ssl supports TLSv1.2+ with strong ciphers and all popular
# clients (including Windows 10+ native WebDAVS) also work with those.
# NOTE: Apparently Win 7 (+8.1?) native WebDAVS only works with semi-strong
# legacy ciphers and TLSv1.0+v1.1 unless updated and enabled
# NOTE: Win 7 went EoL in January 2020 and should no longer be needed
#enable_davs_legacy_tls = False
# Pure Python pyftpdlib-based ftp(s) daemon
enable_ftps = False
# Allow sub-optimal but still relatively strong legacy TLS supports in FTPS
# NOTE: Recent PyOpenSSL supports TLSv1.2+ with strong ciphers and all popular
# NOTE: Modern PyOpenSSL supports TLSv1.2+ with strong ciphers and all popular
# clients also work with those.
# NOTE: CentOS 7 native pyOpenSSL 0.13 does NOT support elliptic curve ciphers
# and FileZilla fails on listdir with remaining strong DHE ciphers.
# Installing a recent pyopenssl e.g. from the centos-openstack-X repo
# allows disabling legacy tls support without breaking FileZilla support.
# TODO: disable as soon as a recent pyopenssl version is available - the one
# from pip breaks paramiko so do NOT go there.
enable_ftps_legacy_tls = True
#enable_ftps_legacy_tls = False
# Enable WSGI served web pages (faster than CGI) - requires apache wsgi module
enable_wsgi = True
# Enable system notify helper used e.g. to warn about failed user logins
Expand Down Expand Up @@ -638,6 +629,10 @@ peers_explicit_fields =
peers_contact_hint = employed here and authorized to invite external users
# Enable OpenID daemon for web access with user/pw from local user DB
enable_openid = False
# Allow sub-optimal but still relatively strong legacy TLS support in OpenID 2.0
# NOTE: Python-2.7+ ssl supports TLSv1.2+ with strong ciphers and all popular
# clients also work with those.
#enable_openid_legacy_tls = False
# Enable share links for easy external exchange of data with anyone
enable_sharelinks = True
# Enable storage quota
Expand Down
Loading
Loading