[PATCH 8 of 8] sslutil: reference appropriate config section in messaging

Gregory Szorc gregory.szorc at gmail.com
Sat May 28 16:04:30 EDT 2016


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1464465526 25200
#      Sat May 28 12:58:46 2016 -0700
# Node ID 8a57327eb7ab175ce91abdc06dc8a60130575cf7
# Parent  969eddf5985326d5c4fd26da95fa19247339e6a0
sslutil: reference appropriate config section in messaging

Error messages reference the config section defining the host
fingerprint. Now that we have multiple sections where this config
setting could live, we need to point the user at the appropriate
one.

We default to the new "hostsecurity" section. But we will still
refer them to the "hostfingerprint" section if a value is defined
there.

There are some corner cases where the messaging might be off. e.g.
they could define a SHA-1 fingerprint in both sections. IMO the
messaging needs a massive overhaul. I plan to do this as part
of future refactoring to security settings.

diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -112,16 +112,18 @@ def _hostsettings(ui, hostname):
     Returns a dict of settings relevant to that hostname.
     """
     s = {
         # List of 2-tuple of (hash algorithm, hash).
         'certfingerprints': [],
         # Path to file containing concatenated CA certs. Used by
         # SSLContext.load_verify_locations().
         'cafile': None,
+        # Whether the legacy [hostfingerprints] section has data for this host.
+        'legacyfingerprint': False,
         # ssl.CERT_* constant used by SSLContext.verify_mode.
         'verifymode': None,
     }
 
     # Look for fingerprints in [hostsecurity] section. Value is a list
     # of <alg>:<fingerprint> strings.
     fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname,
                                  [])
@@ -135,16 +137,17 @@ def _hostsettings(ui, hostname):
         alg, fingerprint = fingerprint.split(':', 1)
         fingerprint = fingerprint.replace(':', '').lower()
         s['certfingerprints'].append((alg, fingerprint))
 
     # Fingerprints from [hostfingerprints] are always SHA-1.
     for fingerprint in ui.configlist('hostfingerprints', hostname, []):
         fingerprint = fingerprint.replace(':', '').lower()
         s['certfingerprints'].append(('sha1', fingerprint))
+        s['legacyfingerprint'] = True
 
     # If a host cert fingerprint is defined, it is the only thing that
     # matters. No need to validate CA certs.
     if s['certfingerprints']:
         s['verifymode'] = ssl.CERT_NONE
 
     # If --insecure is used, don't take CAs into consideration.
     elif ui.insecureconnections:
@@ -345,55 +348,60 @@ def validatesocket(sock, strict=False):
     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['legacyfingerprint']:
+        section = 'hostfingerprint'
+    else:
+        section = 'hostsecurity'
+
     if settings['certfingerprints']:
         fingerprintmatch = False
         for hash, fingerprint in settings['certfingerprints']:
             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'))
+                             hint=_('check %s configuration') % section)
         ui.debug('%s certificate matched fingerprint %s\n' %
                  (host, nicefingerprint))
         return
 
     # If insecure connections were explicitly requested via --insecure,
     # print a warning and do no verification.
     #
     # It may seem odd that this is checked *after* host fingerprint pinning.
     # This is for backwards compatibility (for now). The message is also
     # the same as below for BC.
     if ui.insecureconnections:
         ui.warn(_('warning: %s certificate with fingerprint %s not '
-                  'verified (check hostfingerprints or web.cacerts '
+                  'verified (check %s or web.cacerts '
                   'config setting)\n') %
-                (host, nicefingerprint))
+                (host, nicefingerprint, section))
         return
 
     if not sock._hgstate['caloaded']:
         if strict:
             raise error.Abort(_('%s certificate with fingerprint %s not '
                                 'verified') % (host, nicefingerprint),
-                              hint=_('check hostfingerprints or '
-                                     'web.cacerts config setting'))
+                              hint=_('check %s or web.cacerts config '
+                                     'setting') % section)
         else:
             ui.warn(_('warning: %s certificate with fingerprint %s '
-                      'not verified (check hostfingerprints or '
-                      'web.cacerts config setting)\n') %
-                    (host, nicefingerprint))
+                      'not verified (check %s or web.cacerts config '
+                      'setting)\n') %
+                    (host, nicefingerprint, section))
 
         return
 
     msg = _verifycert(peercert2, host)
     if msg:
         raise error.Abort(_('%s certificate error: %s') % (host, msg),
-                         hint=_('configure hostfingerprint %s or use '
+                         hint=_('configure %s %s or use '
                                 '--insecure to connect insecurely') %
-                              nicefingerprint)
+                              (section, nicefingerprint))
diff --git a/tests/test-https.t b/tests/test-https.t
--- a/tests/test-https.t
+++ b/tests/test-https.t
@@ -172,17 +172,17 @@ Apple's OpenSSL. This trick do not work 
   [255]
 
   $ DISABLEOSXDUMMYCERT="--insecure"
 #endif
 
 clone via pull
 
   $ hg clone https://localhost:$HGPORT/ copy-pull $DISABLEOSXDUMMYCERT
-  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting)
+  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostsecurity or web.cacerts config setting)
   requesting all changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 4 changes to 4 files
   updating to branch default
   4 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg verify -R copy-pull
@@ -199,17 +199,17 @@ clone via pull
 
 pull without cacert
 
   $ cd copy-pull
   $ echo '[hooks]' >> .hg/hgrc
   $ echo "changegroup = printenv.py changegroup" >> .hg/hgrc
   $ hg pull $DISABLEOSXDUMMYCERT
   pulling from https://localhost:$HGPORT/
-  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting)
+  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostsecurity or web.cacerts config setting)
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
   changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=https://localhost:$HGPORT/ (glob)
   (run 'hg update' to get a working copy)
   $ cd ..
@@ -231,39 +231,39 @@ variables in the filename
   $ echo "[web]" >> $HGRCPATH
   $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH
   $ P=`pwd` hg -R copy-pull pull
   pulling from https://localhost:$HGPORT/
   searching for changes
   no changes found
   $ P=`pwd` hg -R copy-pull pull --insecure
   pulling from https://localhost:$HGPORT/
-  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting)
+  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostsecurity or web.cacerts config setting)
   searching for changes
   no changes found
 
 cacert mismatch
 
   $ hg -R copy-pull pull --config web.cacerts=pub.pem https://127.0.0.1:$HGPORT/
   pulling from https://127.0.0.1:$HGPORT/
   abort: 127.0.0.1 certificate error: certificate is for localhost
-  (configure hostfingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca or use --insecure to connect insecurely)
+  (configure hostsecurity 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca or use --insecure to connect insecurely)
   [255]
   $ hg -R copy-pull pull --config web.cacerts=pub.pem https://127.0.0.1:$HGPORT/ --insecure
   pulling from https://127.0.0.1:$HGPORT/
-  warning: 127.0.0.1 certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting)
+  warning: 127.0.0.1 certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostsecurity or web.cacerts config setting)
   searching for changes
   no changes found
   $ hg -R copy-pull pull --config web.cacerts=pub-other.pem
   pulling from https://localhost:$HGPORT/
   abort: error: *certificate verify failed* (glob)
   [255]
   $ hg -R copy-pull pull --config web.cacerts=pub-other.pem --insecure
   pulling from https://localhost:$HGPORT/
-  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting)
+  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostsecurity or web.cacerts config setting)
   searching for changes
   no changes found
 
 Test server cert which isn't valid yet
 
   $ hg serve -R test -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem
   $ cat hg1.pid >> $DAEMON_PIDS
   $ hg -R copy-pull pull --config web.cacerts=pub-not-yet.pem https://localhost:$HGPORT1/
@@ -311,17 +311,17 @@ Fingerprints
 
   $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
   abort: certificate for localhost has unexpected fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca
   (check hostfingerprint configuration)
   [255]
 
   $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
   abort: certificate for localhost has unexpected fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca
-  (check hostfingerprint configuration)
+  (check hostsecurity configuration)
   [255]
 
 - fails when cert doesn't match hostname (port is ignored)
   $ hg -R copy-pull id https://localhost:$HGPORT1/ --config hostfingerprints.localhost=914f1aff87249c09b6859b88b1906d30756491ca
   abort: certificate for localhost has unexpected fingerprint 28:ff:71:bf:65:31:14:23:ad:62:92:b4:0e:31:99:18:fc:83:e3:9b
   (check hostfingerprint configuration)
   [255]
 
@@ -343,17 +343,17 @@ Prepare for connecting through proxy
   $ echo "always=True" >> copy-pull/.hg/hgrc
   $ echo "[hostfingerprints]" >> copy-pull/.hg/hgrc
   $ echo "localhost =" >> copy-pull/.hg/hgrc
 
 Test unvalidated https through proxy
 
   $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull --insecure --traceback
   pulling from https://localhost:$HGPORT/
-  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting)
+  warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostsecurity or web.cacerts config setting)
   searching for changes
   no changes found
 
 Test https with cacert and fingerprint through proxy
 
   $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull --config web.cacerts=pub.pem
   pulling from https://localhost:$HGPORT/
   searching for changes


More information about the Mercurial-devel mailing list