changeset 28850:3819c349b194

sslutil: document and slightly refactor validation logic This main purpose of this patch is to make it clearer that fingerprint pinning takes precedence over CA verification. This will make subsequent refactoring to the validation code easier to read.
author Gregory Szorc <gregory.szorc@gmail.com>
date Sun, 10 Apr 2016 11:02:58 -0700
parents 1fde84d42f9c
children 584e0716c7af
files mercurial/sslutil.py
diffstat 1 files changed, 9 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/sslutil.py	Sun Apr 10 11:00:41 2016 -0700
+++ b/mercurial/sslutil.py	Sun Apr 10 11:02:58 2016 -0700
@@ -264,8 +264,6 @@
 
     def __call__(self, sock, strict=False):
         host = self.host
-        cacerts = self.ui.config('web', 'cacerts')
-        hostfingerprints = self.ui.configlist('hostfingerprints', host)
 
         if not sock.cipher(): # work around http://bugs.python.org/issue13721
             raise error.Abort(_('%s ssl connection error') % host)
@@ -278,6 +276,10 @@
         if not peercert:
             raise error.Abort(_('%s certificate error: '
                                'no certificate received') % host)
+
+        # If a certificate fingerprint is pinned, use it and only it to
+        # validate the remote cert.
+        hostfingerprints = self.ui.configlist('hostfingerprints', host)
         peerfingerprint = util.sha1(peercert).hexdigest()
         nicefingerprint = ":".join([peerfingerprint[x:x + 2]
             for x in xrange(0, len(peerfingerprint), 2)])
@@ -294,7 +296,11 @@
                                  hint=_('check hostfingerprint configuration'))
             self.ui.debug('%s certificate matched fingerprint %s\n' %
                           (host, nicefingerprint))
-        elif cacerts != '!':
+            return
+
+        # No pinned fingerprint. Establish trust by looking at the CAs.
+        cacerts = self.ui.config('web', 'cacerts')
+        if cacerts != '!':
             msg = _verifycert(peercert2, host)
             if msg:
                 raise error.Abort(_('%s certificate error: %s') % (host, msg),