[PATCH 3 of 4 STABLE] sslutil: capture string string representation of protocol

Gregory Szorc gregory.szorc at gmail.com
Wed Jul 20 00:31:55 EDT 2016


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1468985429 25200
#      Tue Jul 19 20:30:29 2016 -0700
# Branch stable
# Node ID 925cb3b2baebcbf8f0498f2a7e7cbd6610732cbb
# Parent  c575dafbff39b743957fc39af4f107fba04ee467
sslutil: capture string string representation of protocol

This will be used in a subsequent patch to improve messaging.

diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -134,16 +134,19 @@ def _hostsettings(ui, hostname):
         # 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,
+        # String representation of minimum protocol to be used for UI
+        # presentation.
+        'protocolui': None,
         # ssl.CERT_* constant used by SSLContext.verify_mode.
         'verifymode': None,
         # Defines extra ssl.OP* bitwise options to set.
         'ctxoptions': None,
         # OpenSSL Cipher List to use (instead of default).
         'ciphers': None,
     }
 
@@ -182,17 +185,17 @@ def _hostsettings(ui, hostname):
     validateprotocol(protocol, key)
 
     # If --insecure is used, we allow the use of TLS 1.0 despite config options.
     # We always print a "connection security to %s is disabled..." message when
     # --insecure is used. So no need to print anything more here.
     if ui.insecureconnections:
         protocol = 'tls1.0'
 
-    s['protocol'], s['ctxoptions'] = protocolsettings(protocol)
+    s['protocol'], s['ctxoptions'], s['protocolui'] = protocolsettings(protocol)
 
     ciphers = ui.config('hostsecurity', 'ciphers')
     ciphers = ui.config('hostsecurity', '%s:ciphers' % hostname, ciphers)
     s['ciphers'] = ciphers
 
     # Look for fingerprints in [hostsecurity] section. Value is a list
     # of <alg>:<fingerprint> strings.
     fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname,
@@ -280,17 +283,22 @@ def _hostsettings(ui, hostname):
 
     assert s['protocol'] is not None
     assert s['ctxoptions'] is not None
     assert s['verifymode'] is not None
 
     return s
 
 def protocolsettings(protocol):
-    """Resolve the protocol and context options for a config value."""
+    """Resolve the protocol for a config value.
+
+    Returns a 3-tuple of (protocol, options, ui value) where the first
+    2 items are values used by SSLContext and the last is a string value
+    of the ``minimumprotocol`` config option equivalent.
+    """
     if protocol not in configprotocols:
         raise ValueError('protocol value not supported: %s' % protocol)
 
     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
     # that both ends support, including TLS protocols. On legacy stacks,
     # the highest it likely goes is TLS 1.0. On modern stacks, it can
     # support TLS 1.2.
     #
@@ -302,17 +310,17 @@ def protocolsettings(protocol):
     # full/real SSLContext available to us.
     if supportedprotocols == set(['tls1.0']):
         if protocol != 'tls1.0':
             raise error.Abort(_('current Python does not support protocol '
                                 'setting %s') % protocol,
                               hint=_('upgrade Python or disable setting since '
                                      'only TLS 1.0 is supported'))
 
-        return ssl.PROTOCOL_TLSv1, 0
+        return ssl.PROTOCOL_TLSv1, 0, 'tls1.0'
 
     # WARNING: returned options don't work unless the modern ssl module
     # is available. Be careful when adding options here.
 
     # SSLv2 and SSLv3 are broken. We ban them outright.
     options = ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
 
     if protocol == 'tls1.0':
@@ -324,17 +332,17 @@ def protocolsettings(protocol):
         options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
     else:
         raise error.Abort(_('this should not happen'))
 
     # Prevent CRIME.
     # There is no guarantee this attribute is defined on the module.
     options |= getattr(ssl, 'OP_NO_COMPRESSION', 0)
 
-    return ssl.PROTOCOL_SSLv23, options
+    return ssl.PROTOCOL_SSLv23, options, protocol
 
 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
     choices based on what security options are available.
 
     In addition to the arguments supported by ``ssl.wrap_socket``, we allow
@@ -440,17 +448,17 @@ def wrapserversocket(sock, ui, certfile=
     file via ``certfile`` (the private key must come first in the file).
 
     ``cafile`` defines the path to certificate authorities.
 
     ``requireclientcert`` specifies whether to require client certificates.
 
     Typically ``cafile`` is only defined if ``requireclientcert`` is true.
     """
-    protocol, options = protocolsettings('tls1.0')
+    protocol, options, _protocolui = protocolsettings('tls1.0')
 
     # This config option is intended for use in tests only. It is a giant
     # footgun to kill security. Don't define it.
     exactprotocol = ui.config('devel', 'serverexactprotocol')
     if exactprotocol == 'tls1.0':
         protocol = ssl.PROTOCOL_TLSv1
     elif exactprotocol == 'tls1.1':
         if 'tls1.1' not in supportedprotocols:


More information about the Mercurial-devel mailing list