Skip to content
This repository has been archived by the owner on Feb 19, 2020. It is now read-only.

xmltream.py: avoid using SSLv3 on unsupported systems. #470

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 18 additions & 5 deletions sleekxmpp/xmlstream/xmlstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,13 @@ def __init__(self, socket=None, host='', port=0, certfile=None,
#:
#: Most XMPP servers support TLSv1 or newer, however, if you really have to
#: connect to systems with insecure SSLv3, you may set :attr:`ssl_version`
#: as ``ssl.PROTOCOL_SSLv3``. Other values are ignored by current implementation.
#: as ``ssl.PROTOCOL_SSLv3``. Please note that many systems have removed,
#: SSLv3, it is not possible to use it anymore, specifying SSLv3 on these
#: system can trigger errors and exceptions. Other values are ignored by
#: current implementation.
#:
#: import ssl
#: # triggers AttributeError for systems that removed SSLv3
#: xmpp.ssl_version = ssl.PROTOCOL_SSLv3
self.ssl_version = ssl.PROTOCOL_SSLv23

Expand Down Expand Up @@ -430,6 +434,9 @@ def _create_secure_socket(self):
'!aNULL:!eNULL:!MD5:!3DES'
)

# Some systems have disabled SSLv3 completely at build time.
sslv3_available = hasattr(ssl, "PROTOCOL_SSLv3")

log.info(
"Using SSL/TLS version: %s",
ssl.get_protocol_name(self.ssl_version).replace('PROTOCOL_', '', 1)
Expand All @@ -440,6 +447,12 @@ def _create_secure_socket(self):
"supported versions, actually TLSv1.0+, since SSLv2 and "
"SSLv3 is disabled."
)
if not sslv3_available:
log.info(
"SSLv3 is removed by your system for good, because of its insecurity. "
"If you have legacy systems and compatibility issues, upgrading "
"them to TLS should be the right way to go."
)

if self.ca_certs is None:
cert_policy = ssl.CERT_NONE
Expand All @@ -459,7 +472,7 @@ def _create_secure_socket(self):
# Good, create_default_context() is supported, which consists
# recommended security settings by default.
ctx = ssl.create_default_context()
if self.ssl_version == ssl.PROTOCOL_SSLv3:
if sslv3_available and self.ssl_version == ssl.PROTOCOL_SSLv3:
# But if the user specifies insecure SSLv3, do a favor.
ctx.options &= ~ssl.OP_NO_SSLv3 # UNSET NO_SSLv3, or set SSLv3
ctx.set_ciphers(_CIPHERS_SSL) # _CIPHERS_SSL is weaker
Expand All @@ -473,7 +486,7 @@ def _create_secure_socket(self):
ctx.load_verify_locations(cafile=self.ca_certs)
else:
# Oops, create_default_context() is not supported.
if self.ssl_version == ssl.PROTOCOL_SSLv3:
if sslv3_available and self.ssl_version == ssl.PROTOCOL_SSLv3:
# First, if the user specifies insecure SSLv3, do a favor.
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
ctx.set_ciphers(_CIPHERS_SSL)
Expand All @@ -497,7 +510,7 @@ def _create_secure_socket(self):
elif sys.version_info >= (2, 7, 9):
# Good, create_default_context() is supported, do the same as Python 3.4.
ctx = ssl.create_default_context()
if self.ssl_version == ssl.PROTOCOL_SSLv3:
if sslv3_available and self.ssl_version == ssl.PROTOCOL_SSLv3:
# If the user specifies insecure SSLv3, do a favor.
ctx.options &= ~ssl.OP_NO_SSLv3
ctx.set_ciphers(_CIPHERS_SSL)
Expand All @@ -508,7 +521,7 @@ def _create_secure_socket(self):
elif cert_policy == ssl.CERT_REQUIRED:
ctx.load_verify_locations(cafile=self.ca_certs)
else:
if self.ssl_version == ssl.PROTOCOL_SSLv3:
if sslv3_available and self.ssl_version == ssl.PROTOCOL_SSLv3:
ssl_args['ssl_version'] = ssl.PROTOCOL_SSLv3
else:
ssl_args['ssl_version'] = ssl.PROTOCOL_TLSv1
Expand Down