mercurial/sslutil.py
changeset 49054 5144d3579a9c
parent 48875 6000f5b25c9b
child 49055 50bd2910d162
equal deleted inserted replaced
49053:7d1daa1ef286 49054:5144d3579a9c
    10 
    10 
    11 import hashlib
    11 import hashlib
    12 import os
    12 import os
    13 import re
    13 import re
    14 import ssl
    14 import ssl
       
    15 import warnings
    15 
    16 
    16 from .i18n import _
    17 from .i18n import _
    17 from .pycompat import getattr
    18 from .pycompat import getattr
    18 from .node import hex
    19 from .node import hex
    19 from . import (
    20 from . import (
   306     # have explicit control over CA loading because implicitly loading
   307     # have explicit control over CA loading because implicitly loading
   307     # CAs may undermine the user's intent. For example, a user may define a CA
   308     # CAs may undermine the user's intent. For example, a user may define a CA
   308     # bundle with a specific CA cert removed. If the system/default CA bundle
   309     # bundle with a specific CA cert removed. If the system/default CA bundle
   309     # is loaded and contains that removed CA, you've just undone the user's
   310     # is loaded and contains that removed CA, you've just undone the user's
   310     # choice.
   311     # choice.
   311     #
   312 
   312     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol that both
   313     if util.safehasattr(ssl, 'PROTOCOL_TLS_CLIENT'):
   313     # ends support, including TLS protocols. commonssloptions() restricts the
   314         # python 3.7+
   314     # set of allowed protocols.
   315         sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
   315     sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
   316         minimumprotocol = settings[b'minimumprotocol']
   316     sslcontext.options |= commonssloptions(settings[b'minimumprotocol'])
   317         if minimumprotocol == b'tls1.0':
       
   318             with warnings.catch_warnings():
       
   319                 warnings.filterwarnings(
       
   320                     'ignore',
       
   321                     'ssl.TLSVersion.TLSv1 is deprecated',
       
   322                     DeprecationWarning,
       
   323                 )
       
   324                 sslcontext.minimum_version = ssl.TLSVersion.TLSv1
       
   325         elif minimumprotocol == b'tls1.1':
       
   326             with warnings.catch_warnings():
       
   327                 warnings.filterwarnings(
       
   328                     'ignore',
       
   329                     'ssl.TLSVersion.TLSv1_1 is deprecated',
       
   330                     DeprecationWarning,
       
   331                 )
       
   332                 sslcontext.minimum_version = ssl.TLSVersion.TLSv1_1
       
   333         elif minimumprotocol == b'tls1.2':
       
   334             sslcontext.minimum_version = ssl.TLSVersion.TLSv1_2
       
   335         else:
       
   336             raise error.Abort(_(b'this should not happen'))
       
   337         # Prevent CRIME.
       
   338         # There is no guarantee this attribute is defined on the module.
       
   339         sslcontext.options |= getattr(ssl, 'OP_NO_COMPRESSION', 0)
       
   340     else:
       
   341         # Despite its name, PROTOCOL_SSLv23 selects the highest protocol that both
       
   342         # ends support, including TLS protocols. commonssloptions() restricts the
       
   343         # set of allowed protocols.
       
   344         sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
       
   345         sslcontext.options |= commonssloptions(settings[b'minimumprotocol'])
       
   346 
       
   347     # We check the hostname ourselves in _verifycert
       
   348     sslcontext.check_hostname = False
   317     sslcontext.verify_mode = settings[b'verifymode']
   349     sslcontext.verify_mode = settings[b'verifymode']
   318 
   350 
   319     if settings[b'ciphers']:
   351     if settings[b'ciphers']:
   320         try:
   352         try:
   321             sslcontext.set_ciphers(pycompat.sysstr(settings[b'ciphers']))
   353             sslcontext.set_ciphers(pycompat.sysstr(settings[b'ciphers']))
   507         if f and not os.path.exists(f):
   539         if f and not os.path.exists(f):
   508             raise error.Abort(
   540             raise error.Abort(
   509                 _(b'referenced certificate file (%s) does not exist') % f
   541                 _(b'referenced certificate file (%s) does not exist') % f
   510             )
   542             )
   511 
   543 
   512     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol that both
   544     if util.safehasattr(ssl, 'PROTOCOL_TLS_SERVER'):
   513     # ends support, including TLS protocols. commonssloptions() restricts the
   545         # python 3.7+
   514     # set of allowed protocols.
   546         sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
   515     protocol = ssl.PROTOCOL_SSLv23
   547         sslcontext.options |= getattr(ssl, 'OP_NO_COMPRESSION', 0)
   516     options = commonssloptions(b'tls1.0')
   548 
   517 
   549         # This config option is intended for use in tests only. It is a giant
   518     # This config option is intended for use in tests only. It is a giant
   550         # footgun to kill security. Don't define it.
   519     # footgun to kill security. Don't define it.
   551         exactprotocol = ui.config(b'devel', b'serverexactprotocol')
   520     exactprotocol = ui.config(b'devel', b'serverexactprotocol')
   552         if exactprotocol == b'tls1.0':
   521     if exactprotocol == b'tls1.0':
   553             if b'tls1.0' not in supportedprotocols:
   522         if b'tls1.0' not in supportedprotocols:
   554                 raise error.Abort(_(b'TLS 1.0 not supported by this Python'))
   523             raise error.Abort(_(b'TLS 1.0 not supported by this Python'))
   555             with warnings.catch_warnings():
   524         protocol = ssl.PROTOCOL_TLSv1
   556                 warnings.filterwarnings(
   525     elif exactprotocol == b'tls1.1':
   557                     'ignore',
   526         if b'tls1.1' not in supportedprotocols:
   558                     'ssl.TLSVersion.TLSv1 is deprecated',
   527             raise error.Abort(_(b'TLS 1.1 not supported by this Python'))
   559                     DeprecationWarning,
   528         protocol = ssl.PROTOCOL_TLSv1_1
   560                 )
   529     elif exactprotocol == b'tls1.2':
   561                 sslcontext.minimum_version = ssl.TLSVersion.TLSv1
   530         if b'tls1.2' not in supportedprotocols:
   562                 sslcontext.maximum_version = ssl.TLSVersion.TLSv1
   531             raise error.Abort(_(b'TLS 1.2 not supported by this Python'))
   563         elif exactprotocol == b'tls1.1':
   532         protocol = ssl.PROTOCOL_TLSv1_2
   564             if b'tls1.1' not in supportedprotocols:
   533     elif exactprotocol:
   565                 raise error.Abort(_(b'TLS 1.1 not supported by this Python'))
   534         raise error.Abort(
   566             with warnings.catch_warnings():
   535             _(b'invalid value for serverexactprotocol: %s') % exactprotocol
   567                 warnings.filterwarnings(
   536         )
   568                     'ignore',
   537 
   569                     'ssl.TLSVersion.TLSv1_1 is deprecated',
   538     # We /could/ use create_default_context() here since it doesn't load
   570                     DeprecationWarning,
   539     # CAs when configured for client auth. However, it is hard-coded to
   571                 )
   540     # use ssl.PROTOCOL_SSLv23 which may not be appropriate here.
   572                 sslcontext.minimum_version = ssl.TLSVersion.TLSv1_1
   541     sslcontext = ssl.SSLContext(protocol)
   573                 sslcontext.maximum_version = ssl.TLSVersion.TLSv1_1
   542     sslcontext.options |= options
   574         elif exactprotocol == b'tls1.2':
       
   575             if b'tls1.2' not in supportedprotocols:
       
   576                 raise error.Abort(_(b'TLS 1.2 not supported by this Python'))
       
   577             sslcontext.minimum_version = ssl.TLSVersion.TLSv1_2
       
   578             sslcontext.maximum_version = ssl.TLSVersion.TLSv1_2
       
   579         elif exactprotocol:
       
   580             raise error.Abort(
       
   581                 _(b'invalid value for serverexactprotocol: %s') % exactprotocol
       
   582             )
       
   583     else:
       
   584         # Despite its name, PROTOCOL_SSLv23 selects the highest protocol that both
       
   585         # ends support, including TLS protocols. commonssloptions() restricts the
       
   586         # set of allowed protocols.
       
   587         protocol = ssl.PROTOCOL_SSLv23
       
   588         options = commonssloptions(b'tls1.0')
       
   589 
       
   590         # This config option is intended for use in tests only. It is a giant
       
   591         # footgun to kill security. Don't define it.
       
   592         exactprotocol = ui.config(b'devel', b'serverexactprotocol')
       
   593         if exactprotocol == b'tls1.0':
       
   594             if b'tls1.0' not in supportedprotocols:
       
   595                 raise error.Abort(_(b'TLS 1.0 not supported by this Python'))
       
   596             protocol = ssl.PROTOCOL_TLSv1
       
   597         elif exactprotocol == b'tls1.1':
       
   598             if b'tls1.1' not in supportedprotocols:
       
   599                 raise error.Abort(_(b'TLS 1.1 not supported by this Python'))
       
   600             protocol = ssl.PROTOCOL_TLSv1_1
       
   601         elif exactprotocol == b'tls1.2':
       
   602             if b'tls1.2' not in supportedprotocols:
       
   603                 raise error.Abort(_(b'TLS 1.2 not supported by this Python'))
       
   604             protocol = ssl.PROTOCOL_TLSv1_2
       
   605         elif exactprotocol:
       
   606             raise error.Abort(
       
   607                 _(b'invalid value for serverexactprotocol: %s') % exactprotocol
       
   608             )
       
   609 
       
   610         # We /could/ use create_default_context() here since it doesn't load
       
   611         # CAs when configured for client auth. However, it is hard-coded to
       
   612         # use ssl.PROTOCOL_SSLv23 which may not be appropriate here.
       
   613         sslcontext = ssl.SSLContext(protocol)
       
   614         sslcontext.options |= options
   543 
   615 
   544     # Improve forward secrecy.
   616     # Improve forward secrecy.
   545     sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0)
   617     sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0)
   546     sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0)
   618     sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0)
   547 
   619