Have openssl autonegotiate tls protocol on python < 2.7.9

This allows usage of tls-1.1 and tls-1.2 if the underlying openssl
library supports it.  Unfortunately it also allows sslv2 and sslv3 if
the server is only configured to support those.  In this day and age,
that's probably something that the server administrator should fix
anyhow.
pull/11603/head
Toshio Kuratomi 9 years ago
parent ba7243c5f9
commit 3d3e1c82a2

@ -106,6 +106,33 @@ try:
except ImportError: except ImportError:
HAS_SSLCONTEXT = False HAS_SSLCONTEXT = False
# Select a protocol that includes all secure tls protocols
# Exclude insecure ssl protocols if possible
# If we can't find extra tls methods, ssl.PROTOCOL_TLSv1 is sufficient
PROTOCOL = ssl.PROTOCOL_TLSv1
if not HAS_SSLCONTEXT and HAS_SSL:
try:
import ctypes, ctypes.util
except ImportError:
# python 2.4 (likely rhel5 which doesn't have tls1.1 support in its openssl)
pass
else:
libssl_name = ctypes.util.find_library('ssl')
libssl = ctypes.CDLL(libssl_name)
for method in ('TLSv1_1_method', 'TLSv1_2_method'):
try:
libssl[method]
# Found something - we'll let openssl autonegotiate and hope
# the server has disabled sslv2 and 3. best we can do.
PROTOCOL = ssl.PROTOCOL_SSLv23
break
except AttributeError:
pass
del libssl
HAS_MATCH_HOSTNAME = True HAS_MATCH_HOSTNAME = True
try: try:
from ssl import match_hostname, CertificateError from ssl import match_hostname, CertificateError
@ -304,7 +331,7 @@ class CustomHTTPSConnection(httplib.HTTPSConnection):
if HAS_SSLCONTEXT: if HAS_SSLCONTEXT:
self.sock = self.context.wrap_socket(sock, server_hostname=self.host) self.sock = self.context.wrap_socket(sock, server_hostname=self.host)
else: else:
self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=ssl.PROTOCOL_TLSv1) self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=PROTOCOL)
class CustomHTTPSHandler(urllib2.HTTPSHandler): class CustomHTTPSHandler(urllib2.HTTPSHandler):
@ -514,7 +541,7 @@ class SSLValidationHandler(urllib2.BaseHandler):
if context: if context:
ssl_s = context.wrap_socket(s, server_hostname=proxy_parts.get('hostname')) ssl_s = context.wrap_socket(s, server_hostname=proxy_parts.get('hostname'))
else: else:
ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1) ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL)
match_hostname(ssl_s.getpeercert(), self.hostname) match_hostname(ssl_s.getpeercert(), self.hostname)
else: else:
raise ProxyError('Unsupported proxy scheme: %s. Currently ansible only supports HTTP proxies.' % proxy_parts.get('scheme')) raise ProxyError('Unsupported proxy scheme: %s. Currently ansible only supports HTTP proxies.' % proxy_parts.get('scheme'))
@ -523,7 +550,7 @@ class SSLValidationHandler(urllib2.BaseHandler):
if context: if context:
ssl_s = context.wrap_socket(s, server_hostname=self.hostname) ssl_s = context.wrap_socket(s, server_hostname=self.hostname)
else: else:
ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1) ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL)
match_hostname(ssl_s.getpeercert(), self.hostname) match_hostname(ssl_s.getpeercert(), self.hostname)
# close the ssl connection # close the ssl connection
#ssl_s.unwrap() #ssl_s.unwrap()

Loading…
Cancel
Save