sslutil: move protocol determination to _hostsettings
authorGregory Szorc <gregory.szorc@gmail.com>
Wed, 06 Jul 2016 22:47:24 -0700
changeset 29507 97dcdcf75f4f
parent 29506 2550604f5ec7
child 29508 d65ec41b6384
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.
mercurial/sslutil.py
--- a/mercurial/sslutil.py	Mon Jul 11 13:40:02 2016 -0700
+++ b/mercurial/sslutil.py	Wed Jul 06 22:47:24 2016 -0700
@@ -126,10 +126,28 @@
         '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,
@@ -215,6 +233,7 @@
             # user).
             s['verifymode'] = ssl.CERT_NONE
 
+    assert s['protocol'] is not None
     assert s['verifymode'] is not None
 
     return s
@@ -237,27 +256,10 @@
 
     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