mercurial/sslutil.py
changeset 28651 4827d07073e6
parent 28650 737863b01d9f
child 28652 c617614aefd2
equal deleted inserted replaced
28650:737863b01d9f 28651:4827d07073e6
   105                 args['ciphers'] = self._ciphers
   105                 args['ciphers'] = self._ciphers
   106 
   106 
   107             return ssl.wrap_socket(socket, **args)
   107             return ssl.wrap_socket(socket, **args)
   108 
   108 
   109 try:
   109 try:
   110     # ssl.SSLContext was added in 2.7.9 and presence indicates modern
       
   111     # SSL/TLS features are available.
       
   112     ssl_context = ssl.SSLContext
       
   113 
       
   114     def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE,
   110     def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE,
   115                    ca_certs=None, serverhostname=None):
   111                    ca_certs=None, serverhostname=None):
   116         # Allow any version of SSL starting with TLSv1 and
   112         # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
   117         # up. Note that specifying TLSv1 here prohibits use of
   113         # that both ends support, including TLS protocols. On legacy stacks,
   118         # newer standards (like TLSv1_2), so this is the right way
   114         # the highest it likely goes in TLS 1.0. On modern stacks, it can
   119         # to do this. Note that in the future it'd be better to
   115         # support TLS 1.2.
   120         # support using ssl.create_default_context(), which sets
   116         #
   121         # up a bunch of things in smart ways (strong ciphers,
   117         # The PROTOCOL_TLSv* constants select a specific TLS version
   122         # protocol versions, etc) and is upgraded by Python
   118         # only (as opposed to multiple versions). So the method for
   123         # maintainers for us, but that breaks too many things to
   119         # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
   124         # do it in a hurry.
   120         # disable protocols via SSLContext.options and OP_NO_* constants.
   125         sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
   121         # However, SSLContext.options doesn't work unless we have the
       
   122         # full/real SSLContext available to us.
       
   123         #
       
   124         # SSLv2 and SSLv3 are broken. We ban them outright.
       
   125         if modernssl:
       
   126             protocol = ssl.PROTOCOL_SSLv23
       
   127         else:
       
   128             protocol = ssl.PROTOCOL_TLSv1
       
   129 
       
   130         # TODO use ssl.create_default_context() on modernssl.
       
   131         sslcontext = SSLContext(protocol)
       
   132 
       
   133         # This is a no-op on old Python.
   126         sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3
   134         sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3
       
   135 
   127         if certfile is not None:
   136         if certfile is not None:
   128             def password():
   137             def password():
   129                 f = keyfile or certfile
   138                 f = keyfile or certfile
   130                 return ui.getpass(_('passphrase for %s: ') % f, '')
   139                 return ui.getpass(_('passphrase for %s: ') % f, '')
   131             sslcontext.load_cert_chain(certfile, keyfile, password)
   140             sslcontext.load_cert_chain(certfile, keyfile, password)
   132         sslcontext.verify_mode = cert_reqs
   141         sslcontext.verify_mode = cert_reqs
   133         if ca_certs is not None:
   142         if ca_certs is not None:
   134             sslcontext.load_verify_locations(cafile=ca_certs)
   143             sslcontext.load_verify_locations(cafile=ca_certs)
   135         elif _canloaddefaultcerts:
   144         else:
       
   145             # This is a no-op on old Python.
   136             sslcontext.load_default_certs()
   146             sslcontext.load_default_certs()
   137 
   147 
   138         sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname)
   148         sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname)
   139         # check if wrap_socket failed silently because socket had been
   149         # check if wrap_socket failed silently because socket had been
   140         # closed
   150         # closed
   141         # - see http://bugs.python.org/issue13721
   151         # - see http://bugs.python.org/issue13721
   142         if not sslsocket.cipher():
   152         if not sslsocket.cipher():
   143             raise error.Abort(_('ssl connection failed'))
   153             raise error.Abort(_('ssl connection failed'))
   144         return sslsocket
   154         return sslsocket
   145 except AttributeError:
   155 except AttributeError:
   146     # We don't have a modern version of the "ssl" module and are running
   156     raise util.Abort('this should not happen')
   147     # Python <2.7.9.
       
   148     def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE,
       
   149                    ca_certs=None, serverhostname=None):
       
   150         sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
       
   151                                     cert_reqs=cert_reqs, ca_certs=ca_certs,
       
   152                                     ssl_version=ssl.PROTOCOL_TLSv1)
       
   153         # check if wrap_socket failed silently because socket had been
       
   154         # closed
       
   155         # - see http://bugs.python.org/issue13721
       
   156         if not sslsocket.cipher():
       
   157             raise error.Abort(_('ssl connection failed'))
       
   158         return sslsocket
       
   159 
   157 
   160 def _verifycert(cert, hostname):
   158 def _verifycert(cert, hostname):
   161     '''Verify that cert (in socket.getpeercert() format) matches hostname.
   159     '''Verify that cert (in socket.getpeercert() format) matches hostname.
   162     CRLs is not handled.
   160     CRLs is not handled.
   163 
   161