[PATCH] Allow fnmatch patterns in [hostfingerprint]

Steffen Daode Nurpmeso sdaoden at googlemail.com
Wed Sep 21 07:48:59 CDT 2011

Heya Mercurial,

i track multiple repos from *.googlecode.com and i had to update
multiple fingerprints once again.  [Censored.]
Anyway, here is a diff which supports fnmatch(3) patterns for
hostname matching, of course preferring full matches instead of
shell-style pattern matches.  Since this matches only against the
hostnames really used i fail to see any security problems.
Applies to current tip, too.

Ciao, sdaoden(*)(gmail.com)
ASCII ribbon campaign           ( ) More nuclear fission plants
  against HTML e-mail            X    can serve more coloured
    and proprietary attachments / \     and sounding animations
-- >8 --
diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -7,6 +7,7 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 import os
+import fnmatch
 from mercurial import util
 from mercurial.i18n import _
@@ -65,6 +66,19 @@
             return _('certificate is for %s') % certname
     return _('no commonName or subjectAltName found in certificate')
+def _getfingerprint(ui, host):
+    hfsi = ui.configitems('hostfingerprints')
+    if not len(hfsi):
+        return None
+    # Always favour direct match over glob
+    m = None
+    for k, v in hfsi:
+        if k == host:
+            return v
+        if m is None and fnmatch.fnmatch(host, k):
+            m = v
+    return m
 # CERT_REQUIRED means fetch the cert from the server all the time AND
 # validate it against the CA store provided in web.cacerts.
@@ -74,7 +88,7 @@
 def sslkwargs(ui, host):
     cacerts = ui.config('web', 'cacerts')
-    hostfingerprint = ui.config('hostfingerprints', host)
+    hostfingerprint = _getfingerprint(ui, host)
     if cacerts and not hostfingerprint:
         cacerts = util.expandpath(cacerts)
         if not os.path.exists(cacerts):
@@ -92,7 +106,7 @@
     def __call__(self, sock):
         host = self.host
         cacerts = self.ui.config('web', 'cacerts')
-        hostfingerprint = self.ui.config('hostfingerprints', host)
+        hostfingerprint = _getfingerprint(self.ui, host)
         if cacerts and not hostfingerprint:
             msg = _verifycert(sock.getpeercert(), host)
             if msg:

More information about the Mercurial-devel mailing list