mercurial/sslutil.py
changeset 28850 3819c349b194
parent 28849 1fde84d42f9c
child 29042 693b856a4d45
equal deleted inserted replaced
28849:1fde84d42f9c 28850:3819c349b194
   262         self.ui = ui
   262         self.ui = ui
   263         self.host = host
   263         self.host = host
   264 
   264 
   265     def __call__(self, sock, strict=False):
   265     def __call__(self, sock, strict=False):
   266         host = self.host
   266         host = self.host
   267         cacerts = self.ui.config('web', 'cacerts')
       
   268         hostfingerprints = self.ui.configlist('hostfingerprints', host)
       
   269 
   267 
   270         if not sock.cipher(): # work around http://bugs.python.org/issue13721
   268         if not sock.cipher(): # work around http://bugs.python.org/issue13721
   271             raise error.Abort(_('%s ssl connection error') % host)
   269             raise error.Abort(_('%s ssl connection error') % host)
   272         try:
   270         try:
   273             peercert = sock.getpeercert(True)
   271             peercert = sock.getpeercert(True)
   276             raise error.Abort(_('%s ssl connection error') % host)
   274             raise error.Abort(_('%s ssl connection error') % host)
   277 
   275 
   278         if not peercert:
   276         if not peercert:
   279             raise error.Abort(_('%s certificate error: '
   277             raise error.Abort(_('%s certificate error: '
   280                                'no certificate received') % host)
   278                                'no certificate received') % host)
       
   279 
       
   280         # If a certificate fingerprint is pinned, use it and only it to
       
   281         # validate the remote cert.
       
   282         hostfingerprints = self.ui.configlist('hostfingerprints', host)
   281         peerfingerprint = util.sha1(peercert).hexdigest()
   283         peerfingerprint = util.sha1(peercert).hexdigest()
   282         nicefingerprint = ":".join([peerfingerprint[x:x + 2]
   284         nicefingerprint = ":".join([peerfingerprint[x:x + 2]
   283             for x in xrange(0, len(peerfingerprint), 2)])
   285             for x in xrange(0, len(peerfingerprint), 2)])
   284         if hostfingerprints:
   286         if hostfingerprints:
   285             fingerprintmatch = False
   287             fingerprintmatch = False
   292                 raise error.Abort(_('certificate for %s has unexpected '
   294                 raise error.Abort(_('certificate for %s has unexpected '
   293                                    'fingerprint %s') % (host, nicefingerprint),
   295                                    'fingerprint %s') % (host, nicefingerprint),
   294                                  hint=_('check hostfingerprint configuration'))
   296                                  hint=_('check hostfingerprint configuration'))
   295             self.ui.debug('%s certificate matched fingerprint %s\n' %
   297             self.ui.debug('%s certificate matched fingerprint %s\n' %
   296                           (host, nicefingerprint))
   298                           (host, nicefingerprint))
   297         elif cacerts != '!':
   299             return
       
   300 
       
   301         # No pinned fingerprint. Establish trust by looking at the CAs.
       
   302         cacerts = self.ui.config('web', 'cacerts')
       
   303         if cacerts != '!':
   298             msg = _verifycert(peercert2, host)
   304             msg = _verifycert(peercert2, host)
   299             if msg:
   305             if msg:
   300                 raise error.Abort(_('%s certificate error: %s') % (host, msg),
   306                 raise error.Abort(_('%s certificate error: %s') % (host, msg),
   301                                  hint=_('configure hostfingerprint %s or use '
   307                                  hint=_('configure hostfingerprint %s or use '
   302                                         '--insecure to connect insecurely') %
   308                                         '--insecure to connect insecurely') %