diff -r d5067913f97b -r 9654ef41f7cc mercurial/sslutil.py --- 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 : 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