mercurial/url.py
changeset 13315 0d1dca7d2a04
parent 13250 1a4330e30017
parent 13314 8dc488dfcdb4
child 13329 4e92ad05fe18
--- a/mercurial/url.py	Thu Jan 27 17:22:37 2011 -0600
+++ b/mercurial/url.py	Fri Jan 28 03:09:22 2011 +0100
@@ -551,7 +551,8 @@
             else:
                 cacerts = None
 
-            if cacerts:
+            hostfingerprint = self.ui.config('hostfingerprints', self.host)
+            if cacerts and not hostfingerprint:
                 sock = _create_connection((self.host, self.port))
                 self.sock = _ssl_wrap_socket(sock, self.key_file,
                         self.cert_file, cert_reqs=CERT_REQUIRED,
@@ -563,10 +564,33 @@
                 self.ui.debug('%s certificate successfully verified\n' %
                               self.host)
             else:
-                self.ui.warn(_("warning: %s certificate not verified "
-                               "(check web.cacerts config setting)\n") %
-                             self.host)
                 httplib.HTTPSConnection.connect(self)
+                if hasattr(self.sock, 'getpeercert'):
+                    peercert = self.sock.getpeercert(True)
+                    peerfingerprint = util.sha1(peercert).hexdigest()
+                    nicefingerprint = ":".join([peerfingerprint[x:x + 2]
+                        for x in xrange(0, len(peerfingerprint), 2)])
+                    if hostfingerprint:
+                        if peerfingerprint.lower() != \
+                                hostfingerprint.replace(':', '').lower():
+                            raise util.Abort(_('invalid certificate for %s '
+                                               'with fingerprint %s') %
+                                             (self.host, nicefingerprint))
+                        self.ui.debug('%s certificate matched fingerprint %s\n' %
+                                      (self.host, nicefingerprint))
+                    else:
+                        self.ui.warn(_('warning: %s certificate '
+                                       'with fingerprint %s not verified '
+                                       '(check hostfingerprints or web.cacerts '
+                                       'config setting)\n') %
+                                     (self.host, nicefingerprint))
+                else: # python 2.5 ?
+                    if hostfingerprint:
+                        raise util.Abort(_('no certificate for %s '
+                                           'with fingerprint') % self.host)
+                    self.ui.warn(_('warning: %s certificate not verified '
+                                   '(check web.cacerts config setting)\n') %
+                                 self.host)
 
     class httpsconnection(BetterHTTPS):
         response_class = keepalive.HTTPResponse