sslutil: document and slightly refactor validation logic
authorGregory Szorc <gregory.szorc@gmail.com>
Sun, 10 Apr 2016 11:02:58 -0700
changeset 28850 3819c349b194
parent 28849 1fde84d42f9c
child 28851 584e0716c7af
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.
mercurial/sslutil.py
--- 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),