changeset 29227:dffe78d80a6c

sslutil: convert socket validation from a class to a function (API) Now that the socket validator doesn't have any instance state, we can make it a generic function. The "validator" class has been converted into the "validatesocket" function and all consumers have been updated.
author Gregory Szorc <gregory.szorc@gmail.com>
date Sun, 15 May 2016 11:38:38 -0700
parents 33006bd6a1d7
children 9b07017ba528
files mercurial/httpconnection.py mercurial/mail.py mercurial/sslutil.py mercurial/url.py
diffstat 4 files changed, 69 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/httpconnection.py	Sun May 15 11:32:11 2016 -0700
+++ b/mercurial/httpconnection.py	Sun May 15 11:38:38 2016 -0700
@@ -284,6 +284,6 @@
 
         con = HTTPConnection(host, port, use_ssl=True,
                              ssl_wrap_socket=sslutil.wrapsocket,
-                             ssl_validator=sslutil.validator(self.ui, host),
+                             ssl_validator=sslutil.validatesocket,
                              **kwargs)
         return con
--- a/mercurial/mail.py	Sun May 15 11:32:11 2016 -0700
+++ b/mercurial/mail.py	Sun May 15 11:38:38 2016 -0700
@@ -139,7 +139,7 @@
         s.ehlo()
     if (starttls or smtps) and verifycert:
         ui.note(_('(verifying remote certificate)\n'))
-        sslutil.validator(ui, mailhost)(s.sock, verifycert == 'strict')
+        sslutil.validatesocket(s.sock, verifycert == 'strict')
     username = ui.config('smtp', 'username')
     password = ui.config('smtp', 'password')
     if username and not password:
--- a/mercurial/sslutil.py	Sun May 15 11:32:11 2016 -0700
+++ b/mercurial/sslutil.py	Sun May 15 11:38:38 2016 -0700
@@ -291,77 +291,77 @@
 
     return kws
 
-class validator(object):
-    def __init__(self, ui=None, host=None):
-        pass
+def validatesocket(sock, strict=False):
+    """Validate a socket meets security requiremnets.
 
-    def __call__(self, sock, strict=False):
-        host = sock._hgstate['hostname']
-        ui = sock._hgstate['ui']
+    The passed socket must have been created with ``wrapsocket()``.
+    """
+    host = sock._hgstate['hostname']
+    ui = sock._hgstate['ui']
 
-        if not sock.cipher(): # work around http://bugs.python.org/issue13721
-            raise error.Abort(_('%s ssl connection error') % host)
-        try:
-            peercert = sock.getpeercert(True)
-            peercert2 = sock.getpeercert()
-        except AttributeError:
-            raise error.Abort(_('%s ssl connection error') % host)
+    if not sock.cipher(): # work around http://bugs.python.org/issue13721
+        raise error.Abort(_('%s ssl connection error') % host)
+    try:
+        peercert = sock.getpeercert(True)
+        peercert2 = sock.getpeercert()
+    except AttributeError:
+        raise error.Abort(_('%s ssl connection error') % host)
 
-        if not peercert:
-            raise error.Abort(_('%s certificate error: '
-                               'no certificate received') % 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.
-        hostfingerprints = ui.configlist('hostfingerprints', host)
-        peerfingerprint = util.sha1(peercert).hexdigest()
-        nicefingerprint = ":".join([peerfingerprint[x:x + 2]
-            for x in xrange(0, len(peerfingerprint), 2)])
-        if hostfingerprints:
-            fingerprintmatch = False
-            for hostfingerprint in hostfingerprints:
-                if peerfingerprint.lower() == \
-                        hostfingerprint.replace(':', '').lower():
-                    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))
-            return
+    # If a certificate fingerprint is pinned, use it and only it to
+    # validate the remote cert.
+    hostfingerprints = ui.configlist('hostfingerprints', host)
+    peerfingerprint = util.sha1(peercert).hexdigest()
+    nicefingerprint = ":".join([peerfingerprint[x:x + 2]
+        for x in xrange(0, len(peerfingerprint), 2)])
+    if hostfingerprints:
+        fingerprintmatch = False
+        for hostfingerprint in hostfingerprints:
+            if peerfingerprint.lower() == \
+                    hostfingerprint.replace(':', '').lower():
+                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))
+        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 '
-                      'config setting)\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 '
+                  'config setting)\n') %
+                (host, nicefingerprint))
+        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'))
-            else:
-                ui.warn(_('warning: %s certificate with fingerprint %s '
-                          'not verified (check hostfingerprints or '
-                          'web.cacerts config setting)\n') %
-                        (host, nicefingerprint))
+    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'))
+        else:
+            ui.warn(_('warning: %s certificate with fingerprint %s '
+                      'not verified (check hostfingerprints or '
+                      'web.cacerts config setting)\n') %
+                    (host, nicefingerprint))
 
-            return
+        return
 
-        msg = _verifycert(peercert2, host)
-        if msg:
-            raise error.Abort(_('%s certificate error: %s') % (host, msg),
-                             hint=_('configure hostfingerprint %s or use '
-                                    '--insecure to connect insecurely') %
-                                  nicefingerprint)
+    msg = _verifycert(peercert2, host)
+    if msg:
+        raise error.Abort(_('%s certificate error: %s') % (host, msg),
+                         hint=_('configure hostfingerprint %s or use '
+                                '--insecure to connect insecurely') %
+                              nicefingerprint)
--- a/mercurial/url.py	Sun May 15 11:32:11 2016 -0700
+++ b/mercurial/url.py	Sun May 15 11:38:38 2016 -0700
@@ -356,7 +356,7 @@
             self.sock = sslutil.wrapsocket(
                 self.sock, self.key_file, self.cert_file, serverhostname=host,
                 **sslutil.sslkwargs(self.ui, host))
-            sslutil.validator(self.ui, host)(self.sock)
+            sslutil.validatesocket(self.sock)
 
     class httpshandler(keepalive.KeepAliveHandler, urlreq.httpshandler):
         def __init__(self, ui):