force tls for https mercurial hooks, see issue #704

This commit is contained in:
Sebastian Sdorra
2015-04-18 20:07:09 +02:00
parent 518bf3fdab
commit 714f5224ad

View File

@@ -36,7 +36,43 @@
# changegroup.scm = python:scmhooks.callback
#
import os, urllib, urllib2
import os, urllib, urllib2, httplib, socket, ssl
# Python 2's urllib2 does not allow you to select the TLS dialect,
# and by default uses a SSLv23 compatibility negotiation implementation.
# Besides being vulnerable to POODLE, the OSX implementation doesn't
# work correctly, failing to connect to servers that respond only to
# TLS1.0+. These classes help set up TLS support for urllib2.
# source: https://gist.github.com/flandr/74be22d1c3d7c1dfefdd
class TLS1Connection(httplib.HTTPSConnection):
"""Like HTTPSConnection but more specific"""
def __init__(self, host, **kwargs):
httplib.HTTPSConnection.__init__(self, host, **kwargs)
def connect(self):
"""Overrides HTTPSConnection.connect to specify TLS version"""
# Standard implementation from HTTPSConnection, which is not
# designed for extension, unfortunately
sock = socket.create_connection((self.host, self.port),
self.timeout, self.source_address)
if getattr(self, '_tunnel_host', None):
self.sock = sock
self._tunnel()
# This is the only difference; default wrap_socket uses SSLv23
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
ssl_version=ssl.PROTOCOL_TLSv1)
class TLS1Handler(urllib2.HTTPSHandler):
"""Like HTTPSHandler but more specific"""
def __init__(self):
urllib2.HTTPSHandler.__init__(self)
def https_open(self, req):
return self.do_open(TLS1Connection, req)
# hook begin
baseUrl = os.environ['SCM_URL']
challenge = os.environ['SCM_CHALLENGE']
@@ -56,7 +92,11 @@ def callHookUrl(ui, repo, hooktype, node):
data = urllib.urlencode({'node': node, 'challenge': challenge, 'credentials': credentials, 'repositoryPath': repo.root})
# open url but ignore proxy settings
proxy_handler = urllib2.ProxyHandler({})
opener = urllib2.build_opener(proxy_handler)
# use tls for https connections
if url.startswith("https"):
opener = urllib2.build_opener(proxy_handler, TLS1Handler())
else:
opener = urllib2.build_opener(proxy_handler)
req = urllib2.Request(url, data)
conn = opener.open(req)
if conn.code >= 200 and conn.code < 300: