sslutil: move SSLContext.verify_mode value into _hostsettings
authorGregory Szorc <gregory.szorc@gmail.com>
Sat, 28 May 2016 11:41:21 -0700
changeset 29259 ec247e8595f9
parent 29258 6315c1e14f75
child 29260 70bc9912d83d
sslutil: move SSLContext.verify_mode value into _hostsettings _determinecertoptions() and _hostsettings() are redundant with each other. _hostsettings() is used the flexible API we want. We start the process of removing _determinecertoptions() by moving some of the logic for the verify_mode value into _hostsettings(). As part of this, _determinecertoptions() now takes a settings dict as its argument. This is technically API incompatible. But since _determinecertoptions() came into existence a few days ago as part of this release, I'm not flagging it as such.
mercurial/sslutil.py
--- a/mercurial/sslutil.py	Sat May 28 11:12:02 2016 -0700
+++ b/mercurial/sslutil.py	Sat May 28 11:41:21 2016 -0700
@@ -114,6 +114,8 @@
     s = {
         # List of 2-tuple of (hash algorithm, hash).
         'certfingerprints': [],
+        # ssl.CERT_* constant used by SSLContext.verify_mode.
+        'verifymode': None,
     }
 
     # Fingerprints from [hostfingerprints] are always SHA-1.
@@ -121,22 +123,26 @@
         fingerprint = fingerprint.replace(':', '').lower()
         s['certfingerprints'].append(('sha1', fingerprint))
 
+    # 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:
+        s['verifymode'] = ssl.CERT_NONE
+
+    # TODO assert verifymode is not None once we integrate cacert
+    # checking in this function.
+
     return s
 
-def _determinecertoptions(ui, host):
+def _determinecertoptions(ui, settings):
     """Determine certificate options for a connections.
 
     Returns a tuple of (cert_reqs, ca_certs).
     """
-    # If a host key fingerprint is on file, it is the only thing that matters
-    # and CA certs don't come into play.
-    hostfingerprint = ui.config('hostfingerprints', host)
-    if hostfingerprint:
-        return ssl.CERT_NONE, None
-
-    # The code below sets up CA verification arguments. If --insecure is
-    # used, we don't take CAs into consideration, so return early.
-    if ui.insecureconnections:
+    if settings['verifymode'] == ssl.CERT_NONE:
         return ssl.CERT_NONE, None
 
     cacerts = ui.config('web', 'cacerts')
@@ -181,7 +187,8 @@
     if not serverhostname:
         raise error.Abort('serverhostname argument is required')
 
-    cert_reqs, ca_certs = _determinecertoptions(ui, serverhostname)
+    settings = _hostsettings(ui, serverhostname)
+    cert_reqs, ca_certs = _determinecertoptions(ui, settings)
 
     # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
     # that both ends support, including TLS protocols. On legacy stacks,
@@ -234,7 +241,7 @@
     sslsocket._hgstate = {
         'caloaded': caloaded,
         'hostname': serverhostname,
-        'settings': _hostsettings(ui, serverhostname),
+        'settings': settings,
         'ui': ui,
     }