Patchwork [5,of,8] sslutil: calculate host fingerprints from additional algorithms

login
register
mail settings
Submitter Gregory Szorc
Date May 28, 2016, 8:04 p.m.
Message ID <c23a1d255746fc29cc7b.1464465867@ubuntu-vm-main>
Download mbox | patch
Permalink /patch/15233/
State Accepted
Headers show

Comments

Gregory Szorc - May 28, 2016, 8:04 p.m.
# HG changeset patch
# User Gregory Szorc <gregory.szorc@gmail.com>
# Date 1464461908 25200
#      Sat May 28 11:58:28 2016 -0700
# Node ID c23a1d255746fc29cc7b4f2e5f9a9c0636ba4d45
# Parent  91e745e440f753fb6c04516dfb507cf9aba585fb
sslutil: calculate host fingerprints from additional algorithms

Currently, we only support defining host fingerprints with SHA-1.
A future patch will introduce support for defining fingerprints
using other hashing algorithms. In preparation for that, we
rewrite the fingerprint verification code to support multiple
fingerprints, namely SHA-256 and SHA-512 fingerprints.

We still only display the SHA-1 fingerprint. We'll have to rivisit
this code once we support defining fingerprints with other hash
functions.

As part of this, I snuck in a change to use range() instead of
xrange() because xrange() isn't necessary for such small values.

Patch

diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -322,23 +322,28 @@  def validatesocket(sock, strict=False):
         raise error.Abort(_('%s ssl connection error') % host)
 
     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.
-    peerfingerprint = util.sha1(peercert).hexdigest()
-    nicefingerprint = ":".join([peerfingerprint[x:x + 2]
-        for x in xrange(0, len(peerfingerprint), 2)])
+    peerfingerprints = {
+        'sha1': util.sha1(peercert).hexdigest(),
+        'sha256': util.sha256(peercert).hexdigest(),
+        'sha512': util.sha512(peercert).hexdigest(),
+    }
+    nicefingerprint = ':'.join([peerfingerprints['sha1'][x:x + 2]
+        for x in range(0, len(peerfingerprints['sha1']), 2)])
+
     if settings['certfingerprints']:
         fingerprintmatch = False
         for hash, fingerprint in settings['certfingerprints']:
-            if peerfingerprint.lower() == fingerprint:
+            if peerfingerprints[hash].lower() == fingerprint:
                 fingerprintmatch = True
                 break
         if not fingerprintmatch:
             raise error.Abort(_('certificate for %s has unexpected '
                                'fingerprint %s') % (host, nicefingerprint),
                              hint=_('check hostfingerprint configuration'))
         ui.debug('%s certificate matched fingerprint %s\n' %
                  (host, nicefingerprint))