mercurial/sslutil.py
changeset 29113 5b9577edf745
parent 29112 5edc5acecc83
child 29115 ef316c653b7f
equal deleted inserted replaced
29112:5edc5acecc83 29113:5b9577edf745
   153             return ui.getpass(_('passphrase for %s: ') % f, '')
   153             return ui.getpass(_('passphrase for %s: ') % f, '')
   154         sslcontext.load_cert_chain(certfile, keyfile, password)
   154         sslcontext.load_cert_chain(certfile, keyfile, password)
   155 
   155 
   156     if ca_certs is not None:
   156     if ca_certs is not None:
   157         sslcontext.load_verify_locations(cafile=ca_certs)
   157         sslcontext.load_verify_locations(cafile=ca_certs)
       
   158         caloaded = True
   158     else:
   159     else:
   159         # This is a no-op on old Python.
   160         # This is a no-op on old Python.
   160         sslcontext.load_default_certs()
   161         sslcontext.load_default_certs()
       
   162         caloaded = _canloaddefaultcerts
   161 
   163 
   162     sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname)
   164     sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname)
   163     # check if wrap_socket failed silently because socket had been
   165     # check if wrap_socket failed silently because socket had been
   164     # closed
   166     # closed
   165     # - see http://bugs.python.org/issue13721
   167     # - see http://bugs.python.org/issue13721
   166     if not sslsocket.cipher():
   168     if not sslsocket.cipher():
   167         raise error.Abort(_('ssl connection failed'))
   169         raise error.Abort(_('ssl connection failed'))
       
   170 
       
   171     sslsocket._hgcaloaded = caloaded
       
   172 
   168     return sslsocket
   173     return sslsocket
   169 
   174 
   170 def _verifycert(cert, hostname):
   175 def _verifycert(cert, hostname):
   171     '''Verify that cert (in socket.getpeercert() format) matches hostname.
   176     '''Verify that cert (in socket.getpeercert() format) matches hostname.
   172     CRLs is not handled.
   177     CRLs is not handled.
   278     # FUTURE this can disappear once wrapsocket() is secure by default.
   283     # FUTURE this can disappear once wrapsocket() is secure by default.
   279     if _canloaddefaultcerts:
   284     if _canloaddefaultcerts:
   280         kws['cert_reqs'] = ssl.CERT_REQUIRED
   285         kws['cert_reqs'] = ssl.CERT_REQUIRED
   281         return kws
   286         return kws
   282 
   287 
   283     # This is effectively indicating that no CAs can be loaded because
       
   284     # we can't get here if web.cacerts is set or if we can find
       
   285     # CA certs elsewhere. Using a config option (which is later
       
   286     # consulted by validator.__call__ is not very obvious).
       
   287     # FUTURE fix this
       
   288     ui.setconfig('web', 'cacerts', '!', 'defaultcacerts')
       
   289     return kws
   288     return kws
   290 
   289 
   291 class validator(object):
   290 class validator(object):
   292     def __init__(self, ui, host):
   291     def __init__(self, ui, host):
   293         self.ui = ui
   292         self.ui = ui
   340                            'verified (check hostfingerprints or web.cacerts '
   339                            'verified (check hostfingerprints or web.cacerts '
   341                            'config setting)\n') %
   340                            'config setting)\n') %
   342                          (host, nicefingerprint))
   341                          (host, nicefingerprint))
   343             return
   342             return
   344 
   343 
   345         # No pinned fingerprint. Establish trust by looking at the CAs.
   344         if not sock._hgcaloaded:
   346         cacerts = self.ui.config('web', 'cacerts')
   345             if strict:
   347         if cacerts != '!':
   346                 raise error.Abort(_('%s certificate with fingerprint %s not '
   348             msg = _verifycert(peercert2, host)
   347                                     'verified') % (host, nicefingerprint),
   349             if msg:
   348                                   hint=_('check hostfingerprints or '
   350                 raise error.Abort(_('%s certificate error: %s') % (host, msg),
   349                                          'web.cacerts config setting'))
   351                                  hint=_('configure hostfingerprint %s or use '
   350             else:
   352                                         '--insecure to connect insecurely') %
   351                 self.ui.warn(_('warning: %s certificate with fingerprint %s '
   353                                       nicefingerprint)
   352                                'not verified (check hostfingerprints or '
   354             self.ui.debug('%s certificate successfully verified\n' % host)
   353                                'web.cacerts config setting)\n') %
   355         elif strict:
   354                              (host, nicefingerprint))
   356             raise error.Abort(_('%s certificate with fingerprint %s not '
   355 
   357                                'verified') % (host, nicefingerprint),
   356             return
   358                              hint=_('check hostfingerprints or web.cacerts '
   357 
   359                                      'config setting'))
   358         msg = _verifycert(peercert2, host)
   360         else:
   359         if msg:
   361             self.ui.warn(_('warning: %s certificate with fingerprint %s not '
   360             raise error.Abort(_('%s certificate error: %s') % (host, msg),
   362                            'verified (check hostfingerprints or web.cacerts '
   361                              hint=_('configure hostfingerprint %s or use '
   363                            'config setting)\n') %
   362                                     '--insecure to connect insecurely') %
   364                          (host, nicefingerprint))
   363                                   nicefingerprint)