[PATCH 1 of 3] sslutil: move protocol determination to _hostsettings
Gregory Szorc
gregory.szorc at gmail.com
Thu Jul 7 06:31:35 UTC 2016
# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1467870444 25200
# Wed Jul 06 22:47:24 2016 -0700
# Node ID f72b68901929352cd54e5d0c3b7e47b0d01c9313
# Parent 54ad81b0665f8b7191e6f049594db06b06d34e50
sslutil: move protocol determination to _hostsettings
Most of the logic for configuring TLS is now in this function.
Let's move protocol determination code there as well.
diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -121,20 +121,38 @@ def _hostsettings(ui, hostname):
'certfingerprints': [],
# Path to file containing concatenated CA certs. Used by
# SSLContext.load_verify_locations().
'cafile': None,
# Whether certificate verification should be disabled.
'disablecertverification': False,
# Whether the legacy [hostfingerprints] section has data for this host.
'legacyfingerprint': False,
+ # PROTOCOL_* constant to use for SSLContext.__init__.
+ 'protocol': None,
# ssl.CERT_* constant used by SSLContext.verify_mode.
'verifymode': None,
}
+ # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
+ # that both ends support, including TLS protocols. On legacy stacks,
+ # the highest it likely goes in TLS 1.0. On modern stacks, it can
+ # support TLS 1.2.
+ #
+ # The PROTOCOL_TLSv* constants select a specific TLS version
+ # only (as opposed to multiple versions). So the method for
+ # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
+ # disable protocols via SSLContext.options and OP_NO_* constants.
+ # However, SSLContext.options doesn't work unless we have the
+ # full/real SSLContext available to us.
+ if modernssl:
+ s['protocol'] = ssl.PROTOCOL_SSLv23
+ else:
+ s['protocol'] = ssl.PROTOCOL_TLSv1
+
# Look for fingerprints in [hostsecurity] section. Value is a list
# of <alg>:<fingerprint> strings.
fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname,
[])
for fingerprint in fingerprints:
if not (fingerprint.startswith(('sha1:', 'sha256:', 'sha512:'))):
raise error.Abort(_('invalid fingerprint for %s: %s') % (
hostname, fingerprint),
@@ -210,16 +228,17 @@ def _hostsettings(ui, hostname):
else:
# At this point we don't have a fingerprint, aren't being
# explicitly insecure, and can't load CA certs. Connecting
# is insecure. We allow the connection and abort during
# validation (once we have the fingerprint to print to the
# user).
s['verifymode'] = ssl.CERT_NONE
+ assert s['protocol'] is not None
assert s['verifymode'] is not None
return s
def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None):
"""Add SSL/TLS to a socket.
This is a glorified wrapper for ``ssl.wrap_socket()``. It makes sane
@@ -232,37 +251,20 @@ def wrapsocket(sock, keyfile, certfile,
server (and client) support SNI, this tells the server which certificate
to use.
"""
if not serverhostname:
raise error.Abort(_('serverhostname argument is required'))
settings = _hostsettings(ui, serverhostname)
- # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
- # that both ends support, including TLS protocols. On legacy stacks,
- # the highest it likely goes in TLS 1.0. On modern stacks, it can
- # support TLS 1.2.
- #
- # The PROTOCOL_TLSv* constants select a specific TLS version
- # only (as opposed to multiple versions). So the method for
- # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
- # disable protocols via SSLContext.options and OP_NO_* constants.
- # However, SSLContext.options doesn't work unless we have the
- # full/real SSLContext available to us.
- #
+ # TODO use ssl.create_default_context() on modernssl.
+ sslcontext = SSLContext(settings['protocol'])
+
# SSLv2 and SSLv3 are broken. We ban them outright.
- if modernssl:
- protocol = ssl.PROTOCOL_SSLv23
- else:
- protocol = ssl.PROTOCOL_TLSv1
-
- # TODO use ssl.create_default_context() on modernssl.
- sslcontext = SSLContext(protocol)
-
# This is a no-op on old Python.
sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3
# This still works on our fake SSLContext.
sslcontext.verify_mode = settings['verifymode']
if certfile is not None:
def password():
More information about the Mercurial-devel
mailing list