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

mail settings
Submitter Gregory Szorc
Date July 20, 2016, 4:31 a.m.
Message ID <925cb3b2baebcbf8f049.1468989115@ubuntu-vm-main>
Download mbox | patch
Permalink /patch/15963/
State Accepted
Headers show


Gregory Szorc - July 20, 2016, 4:31 a.m.
# HG changeset patch
# User Gregory Szorc <>
# 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/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -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
         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: