mercurial/sslutil.py
changeset 29577 9654ef41f7cc
parent 29561 1a782fabf80d
child 29578 4a4b8d3b4e43
--- a/mercurial/sslutil.py	Sun Jul 17 10:50:51 2016 -0700
+++ b/mercurial/sslutil.py	Sun Jul 17 10:59:32 2016 -0700
@@ -84,7 +84,11 @@
 
         def set_ciphers(self, ciphers):
             if not self._supportsciphers:
-                raise error.Abort(_('setting ciphers not supported'))
+                raise error.Abort(_('setting ciphers in [hostsecurity] is not '
+                                    'supported by this version of Python'),
+                                  hint=_('remove the config option or run '
+                                         'Mercurial with a modern Python '
+                                         'version (preferred)'))
 
             self._ciphers = ciphers
 
@@ -131,6 +135,8 @@
         'verifymode': None,
         # Defines extra ssl.OP* bitwise options to set.
         'ctxoptions': None,
+        # OpenSSL Cipher List to use (instead of default).
+        'ciphers': None,
     }
 
     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
@@ -183,6 +189,10 @@
 
     s['protocol'], s['ctxoptions'] = 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,
@@ -347,6 +357,14 @@
     # This still works on our fake SSLContext.
     sslcontext.verify_mode = settings['verifymode']
 
+    if settings['ciphers']:
+        try:
+            sslcontext.set_ciphers(settings['ciphers'])
+        except ssl.SSLError as e:
+            raise error.Abort(_('could not set ciphers: %s') % e.args[0],
+                              hint=_('change cipher string (%s) in config') %
+                                   settings['ciphers'])
+
     if certfile is not None:
         def password():
             f = keyfile or certfile