Patchwork [1,of,4,force-tls] sslutil: add a config knob to support TLS (default) or SSLv23 (bc) (issue4038)

login
register
mail settings
Submitter Augie Fackler
Date Sept. 20, 2013, 2:29 p.m.
Message ID <069ad53af06879c9809e.1379687398@arthedain.pit.corp.google.com>
Download mbox | patch
Permalink /patch/2562/
State Accepted
Commit 47ff9d1abfa92c996757a5c4109c4bc93724b325
Headers show

Comments

Augie Fackler - Sept. 20, 2013, 2:29 p.m.
# HG changeset patch
# User Augie Fackler <raf@durin42.com>
# Date 1379622540 14400
#      Thu Sep 19 16:29:00 2013 -0400
# Node ID 069ad53af06879c9809ea71ab00138d02839a3d5
# Parent  d4ed26beae0e41c86c413c69c1e6f13c32eb3d33
sslutil: add a config knob to support TLS (default) or SSLv23 (bc) (issue4038)

Prior to this change, we default to SSLv23, which is insecure because
it allows use of SSLv2. Unfortunately, there's no constant for OpenSSL
to let us use SSLv3 or TLS - we have to pick one or the other. We
expose a knob to revert to pre-TLS SSL for the user that has an
ancient server that lacks proper TLS support.

Patch

diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -14,10 +14,13 @@ 
     # avoid using deprecated/broken FakeSocket in python 2.6
     import ssl
     CERT_REQUIRED = ssl.CERT_REQUIRED
-    def ssl_wrap_socket(sock, keyfile, certfile,
+    PROTOCOL_SSLv23 = ssl.PROTOCOL_SSLv23
+    PROTOCOL_TLSv1 = ssl.PROTOCOL_TLSv1
+    def ssl_wrap_socket(sock, keyfile, certfile, ssl_version=PROTOCOL_TLSv1,
                 cert_reqs=ssl.CERT_NONE, ca_certs=None):
         sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
-                cert_reqs=cert_reqs, ca_certs=ca_certs)
+                                    cert_reqs=cert_reqs, ca_certs=ca_certs,
+                                    ssl_version=ssl_version)
         # check if wrap_socket failed silently because socket had been closed
         # - see http://bugs.python.org/issue13721
         if not sslsocket.cipher():
@@ -26,9 +29,12 @@ 
 except ImportError:
     CERT_REQUIRED = 2
 
+    PROTOCOL_SSLv23 = 2
+    PROTOCOL_TLSv1 = 3
+
     import socket, httplib
 
-    def ssl_wrap_socket(sock, key_file, cert_file,
+    def ssl_wrap_socket(sock, key_file, cert_file, ssl_version=PROTOCOL_TLSv1,
                         cert_reqs=CERT_REQUIRED, ca_certs=None):
         if not util.safehasattr(socket, 'ssl'):
             raise util.Abort(_('Python SSL support not found'))
@@ -84,15 +90,22 @@ 
 
 def sslkwargs(ui, host):
     cacerts = ui.config('web', 'cacerts')
+    forcetls = ui.configbool('ui', 'tls', default=True)
+    if forcetls:
+        ssl_version = PROTOCOL_TLSv1
+    else:
+        ssl_version = PROTOCOL_SSLv23
     hostfingerprint = ui.config('hostfingerprints', host)
+    kws = {'ssl_version': ssl_version,
+           }
     if cacerts and not hostfingerprint:
         cacerts = util.expandpath(cacerts)
         if not os.path.exists(cacerts):
             raise util.Abort(_('could not find web.cacerts: %s') % cacerts)
-        return {'ca_certs': cacerts,
-                'cert_reqs': CERT_REQUIRED,
-                }
-    return {}
+        kws.update({'ca_certs': cacerts,
+                    'cert_reqs': CERT_REQUIRED,
+                    })
+    return kws
 
 class validator(object):
     def __init__(self, ui, host):