[PATCH] sslutil: python2.4 and 2.5 cannot verify certificates

Stephen Thorne stephen at thorne.id.au
Sun Jun 12 20:32:05 CDT 2011


# HG changeset patch
# User Stephen Thorne <stephen at thorne.id.au>
# Date 1307928723 -36000
# Node ID 131f3dcbb025b0f464f40f3cd9de52245d13a8e8
# Parent  b72cef1b8b26262f627423c16b5c09396721b220
sslutil: python2.4 and 2.5 cannot verify certificates

Two imports were omitted in the restructure of the code creating
sslutil.py, socket and httplib are required when the 'ssl' module
cannot be imported, restoring these imports allows mercurial to run
on python2.4+2.5 again.

Running mercurial on python2.4 or 2.5 with these import errors
fixed would result in a ui warning every time when accessing a https
respository telling the user there was not hostfingerprint set in the
configuration. If a hostfingerprint was added to the http configuration
then an Abort would happen every time because socket.getpeercert() is
not available and thus the fingerprint can't be verified.

The warning has been downgraded to an info on python2.4+2.5 and no longer
allows you to cause mercurial to simply Abort when you attempt to configure it
to verify the certificate.

diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -18,6 +18,8 @@ try:
 except ImportError:
     CERT_REQUIRED = 2
 
+    import socket, httplib
+
     def ssl_wrap_socket(sock, key_file, cert_file,
                         cert_reqs=CERT_REQUIRED, ca_certs=None):
         if ca_certs:
@@ -90,7 +92,10 @@ class validator(object):
         host = self.host
         cacerts = self.ui.config('web', 'cacerts')
         hostfingerprint = self.ui.config('hostfingerprints', host)
-        if cacerts and not hostfingerprint:
+        if not getattr(sock, 'getpeercert', False):
+            self.ui.debug(_('%s certificate cannot be verified due to lack of '
+                            'sock.getpeercert()\n') % (host,))
+        elif cacerts and not hostfingerprint:
             msg = _verifycert(sock.getpeercert(), host)
             if msg:
                 raise util.Abort(_('%s certificate error: %s '
@@ -98,29 +103,21 @@ class validator(object):
                                    'insecurely)') % (host, msg))
             self.ui.debug('%s certificate successfully verified\n' % host)
         else:
-            if getattr(sock, 'getpeercert', False):
-                peercert = sock.getpeercert(True)
-                peerfingerprint = util.sha1(peercert).hexdigest()
-                nicefingerprint = ":".join([peerfingerprint[x:x + 2]
-                    for x in xrange(0, len(peerfingerprint), 2)])
-                if hostfingerprint:
-                    if peerfingerprint.lower() != \
-                            hostfingerprint.replace(':', '').lower():
-                        raise util.Abort(_('invalid certificate for %s '
-                                           'with fingerprint %s') %
-                                         (host, nicefingerprint))
-                    self.ui.debug('%s certificate matched fingerprint %s\n' %
-                                  (host, nicefingerprint))
-                else:
-                    self.ui.warn(_('warning: %s certificate '
-                                   'with fingerprint %s not verified '
-                                   '(check hostfingerprints or web.cacerts '
-                                   'config setting)\n') %
-                                 (host, nicefingerprint))
-            else: # python 2.5 ?
-                if hostfingerprint:
-                    raise util.Abort(_('no certificate for %s with '
-                                       'configured hostfingerprint') % host)
-                self.ui.warn(_('warning: %s certificate not verified '
-                               '(check web.cacerts config setting)\n') %
-                             host)
+            peercert = sock.getpeercert(True)
+            peerfingerprint = util.sha1(peercert).hexdigest()
+            nicefingerprint = ":".join([peerfingerprint[x:x + 2]
+                for x in xrange(0, len(peerfingerprint), 2)])
+            if hostfingerprint:
+                if peerfingerprint.lower() != \
+                        hostfingerprint.replace(':', '').lower():
+                    raise util.Abort(_('invalid certificate for %s '
+                                       'with fingerprint %s') %
+                                     (host, nicefingerprint))
+                self.ui.debug('%s certificate matched fingerprint %s\n' %
+                              (host, nicefingerprint))
+            else:
+                self.ui.warn(_('warning: %s certificate '
+                               'with fingerprint %s not verified '
+                               '(check hostfingerprints or web.cacerts '
+                               'config setting)\n') %
+                             (host, nicefingerprint))


More information about the Mercurial-devel mailing list