mercurial/sslutil.py
changeset 25431 96159068c506
parent 25430 19fa0cb71cd3
child 25432 bdc15b3c9bdb
equal deleted inserted replaced
25430:19fa0cb71cd3 25431:96159068c506
    10 
    10 
    11 from mercurial import util
    11 from mercurial import util
    12 from mercurial.i18n import _
    12 from mercurial.i18n import _
    13 
    13 
    14 _canloaddefaultcerts = False
    14 _canloaddefaultcerts = False
       
    15 CERT_REQUIRED = ssl.CERT_REQUIRED
    15 try:
    16 try:
    16     CERT_REQUIRED = ssl.CERT_REQUIRED
    17     ssl_context = ssl.SSLContext
    17     try:
    18     _canloaddefaultcerts = util.safehasattr(ssl_context, 'load_default_certs')
    18         ssl_context = ssl.SSLContext
    19 
    19         _canloaddefaultcerts = util.safehasattr(ssl_context,
    20     def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE,
    20                                                 'load_default_certs')
    21                    ca_certs=None, serverhostname=None):
    21 
    22         # Allow any version of SSL starting with TLSv1 and
    22         def wrapsocket(sock, keyfile, certfile, ui,
    23         # up. Note that specifying TLSv1 here prohibits use of
    23                        cert_reqs=ssl.CERT_NONE,
    24         # newer standards (like TLSv1_2), so this is the right way
    24                        ca_certs=None, serverhostname=None):
    25         # to do this. Note that in the future it'd be better to
    25             # Allow any version of SSL starting with TLSv1 and
    26         # support using ssl.create_default_context(), which sets
    26             # up. Note that specifying TLSv1 here prohibits use of
    27         # up a bunch of things in smart ways (strong ciphers,
    27             # newer standards (like TLSv1_2), so this is the right way
    28         # protocol versions, etc) and is upgraded by Python
    28             # to do this. Note that in the future it'd be better to
    29         # maintainers for us, but that breaks too many things to
    29             # support using ssl.create_default_context(), which sets
    30         # do it in a hurry.
    30             # up a bunch of things in smart ways (strong ciphers,
    31         sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    31             # protocol versions, etc) and is upgraded by Python
    32         sslcontext.options &= ssl.OP_NO_SSLv2 & ssl.OP_NO_SSLv3
    32             # maintainers for us, but that breaks too many things to
    33         if certfile is not None:
    33             # do it in a hurry.
    34             def password():
    34             sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    35                 f = keyfile or certfile
    35             sslcontext.options &= ssl.OP_NO_SSLv2 & ssl.OP_NO_SSLv3
    36                 return ui.getpass(_('passphrase for %s: ') % f, '')
    36             if certfile is not None:
    37             sslcontext.load_cert_chain(certfile, keyfile, password)
    37                 def password():
    38         sslcontext.verify_mode = cert_reqs
    38                     f = keyfile or certfile
    39         if ca_certs is not None:
    39                     return ui.getpass(_('passphrase for %s: ') % f, '')
    40             sslcontext.load_verify_locations(cafile=ca_certs)
    40                 sslcontext.load_cert_chain(certfile, keyfile, password)
    41         elif _canloaddefaultcerts:
    41             sslcontext.verify_mode = cert_reqs
    42             sslcontext.load_default_certs()
    42             if ca_certs is not None:
    43 
    43                 sslcontext.load_verify_locations(cafile=ca_certs)
    44         sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname)
    44             elif _canloaddefaultcerts:
    45         # check if wrap_socket failed silently because socket had been
    45                 sslcontext.load_default_certs()
    46         # closed
    46 
    47         # - see http://bugs.python.org/issue13721
    47             sslsocket = sslcontext.wrap_socket(sock,
    48         if not sslsocket.cipher():
    48                                                server_hostname=serverhostname)
    49             raise util.Abort(_('ssl connection failed'))
    49             # check if wrap_socket failed silently because socket had been
    50         return sslsocket
    50             # closed
    51 except AttributeError:
    51             # - see http://bugs.python.org/issue13721
    52     def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE,
    52             if not sslsocket.cipher():
    53                    ca_certs=None, serverhostname=None):
    53                 raise util.Abort(_('ssl connection failed'))
    54         sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
    54             return sslsocket
    55                                     cert_reqs=cert_reqs, ca_certs=ca_certs,
    55     except AttributeError:
    56                                     ssl_version=ssl.PROTOCOL_TLSv1)
    56         def wrapsocket(sock, keyfile, certfile, ui,
    57         # check if wrap_socket failed silently because socket had been
    57                        cert_reqs=ssl.CERT_NONE,
    58         # closed
    58                        ca_certs=None, serverhostname=None):
    59         # - see http://bugs.python.org/issue13721
    59             sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
    60         if not sslsocket.cipher():
    60                                         cert_reqs=cert_reqs, ca_certs=ca_certs,
    61             raise util.Abort(_('ssl connection failed'))
    61                                         ssl_version=ssl.PROTOCOL_TLSv1)
    62         return sslsocket
    62             # check if wrap_socket failed silently because socket had been
       
    63             # closed
       
    64             # - see http://bugs.python.org/issue13721
       
    65             if not sslsocket.cipher():
       
    66                 raise util.Abort(_('ssl connection failed'))
       
    67             return sslsocket
       
    68 except ImportError:
       
    69     raise
       
    70 
    63 
    71 def _verifycert(cert, hostname):
    64 def _verifycert(cert, hostname):
    72     '''Verify that cert (in socket.getpeercert() format) matches hostname.
    65     '''Verify that cert (in socket.getpeercert() format) matches hostname.
    73     CRLs is not handled.
    66     CRLs is not handled.
    74 
    67