summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gear/__init__.py42
1 files changed, 40 insertions, 2 deletions
diff --git a/gear/__init__.py b/gear/__init__.py
index 6287281..6e0f1c8 100644
--- a/gear/__init__.py
+++ b/gear/__init__.py
@@ -91,6 +91,44 @@ def convert_to_bytes(data):
return data
+def best_tls_version():
+ if hasattr(ssl, 'PROTOCOL_TLS'):
+ return ssl.PROTOCOL_TLS
+ # Note there is some risk in selecting tls 1.2 if available
+ # as both the client and server may not support it and need 1.1
+ # or 1.0. However, a xenial installation with python 3.5 does
+ # support 1.2 which is probably as old a setup as we need to worry
+ # about.
+ elif hasattr(ssl, 'PROTOCOL_TLSv1_2'):
+ return ssl.PROTOCOL_TLSv1_2
+ elif hasattr(ssl, 'PROTOCOL_TLSv1_1'):
+ return ssl.PROTOCOL_TLSv1_1
+ elif hasattr(ssl, 'PROTOCOL_TLSv1'):
+ return ssl.PROTOCOL_TLSv1
+ else:
+ raise ConnectionError('No supported TLS version available.')
+
+
+def create_ssl_context():
+ tls_version = best_tls_version()
+ context = ssl.SSLContext(tls_version)
+
+ # Disable TLSv1.3
+ # According to https://bugs.python.org/issue43622#msg389497, an event on
+ # ssl socket can happen without data being available at application level.
+ # As gear is using a polling loop with multiple file descriptors and ssl
+ # socket used as a blocking one, a blocked state could happen.
+ # This is highlighted by Zuul SSL test: TestSchedulerSSL, where such
+ # blocked state appears consistently.
+ # note: gear tests and zuul tests are ok for TLSv1.2 but this behavior
+ # could also happen
+ if (hasattr(ssl, 'PROTOCOL_TLS') and
+ tls_version == ssl.PROTOCOL_TLS):
+ context.options |= ssl.OP_NO_TLSv1_3
+
+ return context
+
+
class Task(object):
def __init__(self):
self._wait_event = threading.Event()
@@ -209,7 +247,7 @@ class Connection(object):
if self.use_ssl:
self.log.debug("Using SSL")
- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+ context = create_ssl_context()
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = False
context.load_cert_chain(self.ssl_cert, self.ssl_key)
@@ -2862,7 +2900,7 @@ class Server(BaseClientServer):
self.log.debug("Accepting new connection")
c, addr = self.socket.accept()
if self.use_ssl:
- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+ context = create_ssl_context()
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(self.ssl_cert, self.ssl_key)
context.load_verify_locations(self.ssl_ca)