mercurial/sslutil.py
changeset 44901 53b3baaadb64
parent 44900 38e3df9ff1e7
child 44902 24d440e2fdbb
equal deleted inserted replaced
44900:38e3df9ff1e7 44901:53b3baaadb64
   224     assert s[b'verifymode'] is not None
   224     assert s[b'verifymode'] is not None
   225 
   225 
   226     return s
   226     return s
   227 
   227 
   228 
   228 
   229 def protocolsettings(minimumprotocol):
   229 def commonssloptions(minimumprotocol):
   230     """Resolve the protocol for a config value.
   230     """Return SSLContext options common to servers and clients.
   231 
       
   232     Returns a tuple of (protocol, options) which are values used by SSLContext.
       
   233     """
   231     """
   234     if minimumprotocol not in configprotocols:
   232     if minimumprotocol not in configprotocols:
   235         raise ValueError(b'protocol value not supported: %s' % minimumprotocol)
   233         raise ValueError(b'protocol value not supported: %s' % minimumprotocol)
   236 
       
   237     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
       
   238     # that both ends support, including TLS protocols.
       
   239     #
       
   240     # The PROTOCOL_TLSv* constants select a specific TLS version
       
   241     # only (as opposed to multiple versions). So the method for
       
   242     # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
       
   243     # disable protocols via SSLContext.options and OP_NO_* constants.
       
   244 
   234 
   245     # SSLv2 and SSLv3 are broken. We ban them outright.
   235     # SSLv2 and SSLv3 are broken. We ban them outright.
   246     options = ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
   236     options = ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
   247 
   237 
   248     if minimumprotocol == b'tls1.0':
   238     if minimumprotocol == b'tls1.0':
   257 
   247 
   258     # Prevent CRIME.
   248     # Prevent CRIME.
   259     # There is no guarantee this attribute is defined on the module.
   249     # There is no guarantee this attribute is defined on the module.
   260     options |= getattr(ssl, 'OP_NO_COMPRESSION', 0)
   250     options |= getattr(ssl, 'OP_NO_COMPRESSION', 0)
   261 
   251 
   262     return ssl.PROTOCOL_SSLv23, options
   252     return options
   263 
   253 
   264 
   254 
   265 def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None):
   255 def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None):
   266     """Add SSL/TLS to a socket.
   256     """Add SSL/TLS to a socket.
   267 
   257 
   312     # have explicit control over CA loading because implicitly loading
   302     # have explicit control over CA loading because implicitly loading
   313     # CAs may undermine the user's intent. For example, a user may define a CA
   303     # CAs may undermine the user's intent. For example, a user may define a CA
   314     # bundle with a specific CA cert removed. If the system/default CA bundle
   304     # bundle with a specific CA cert removed. If the system/default CA bundle
   315     # is loaded and contains that removed CA, you've just undone the user's
   305     # is loaded and contains that removed CA, you've just undone the user's
   316     # choice.
   306     # choice.
   317     protocol, options = protocolsettings(settings[b'minimumprotocol'])
   307     #
   318     sslcontext = ssl.SSLContext(protocol)
   308     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol that both
   319     sslcontext.options |= options
   309     # ends support, including TLS protocols. commonssloptions() restricts the
       
   310     # set of allowed protocols.
       
   311     sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
       
   312     sslcontext.options |= commonssloptions(settings[b'minimumprotocol'])
   320     sslcontext.verify_mode = settings[b'verifymode']
   313     sslcontext.verify_mode = settings[b'verifymode']
   321 
   314 
   322     if settings[b'ciphers']:
   315     if settings[b'ciphers']:
   323         try:
   316         try:
   324             sslcontext.set_ciphers(pycompat.sysstr(settings[b'ciphers']))
   317             sslcontext.set_ciphers(pycompat.sysstr(settings[b'ciphers']))
   510         if f and not os.path.exists(f):
   503         if f and not os.path.exists(f):
   511             raise error.Abort(
   504             raise error.Abort(
   512                 _(b'referenced certificate file (%s) does not exist') % f
   505                 _(b'referenced certificate file (%s) does not exist') % f
   513             )
   506             )
   514 
   507 
   515     protocol, options = protocolsettings(b'tls1.0')
   508     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol that both
       
   509     # ends support, including TLS protocols. commonssloptions() restricts the
       
   510     # set of allowed protocols.
       
   511     protocol = ssl.PROTOCOL_SSLv23
       
   512     options = commonssloptions(b'tls1.0')
   516 
   513 
   517     # This config option is intended for use in tests only. It is a giant
   514     # This config option is intended for use in tests only. It is a giant
   518     # footgun to kill security. Don't define it.
   515     # footgun to kill security. Don't define it.
   519     exactprotocol = ui.config(b'devel', b'serverexactprotocol')
   516     exactprotocol = ui.config(b'devel', b'serverexactprotocol')
   520     if exactprotocol == b'tls1.0':
   517     if exactprotocol == b'tls1.0':