Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/sslutil.py @ 19806:47ff9d1abfa9
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.
author | Augie Fackler <raf@durin42.com> |
---|---|
date | Thu, 19 Sep 2013 16:29:00 -0400 |
parents | f2871c30e6a7 |
children | 3b82d412e9e8 |
comparison
equal
deleted
inserted
replaced
19805:9b088e9c2690 | 19806:47ff9d1abfa9 |
---|---|
12 from mercurial.i18n import _ | 12 from mercurial.i18n import _ |
13 try: | 13 try: |
14 # avoid using deprecated/broken FakeSocket in python 2.6 | 14 # avoid using deprecated/broken FakeSocket in python 2.6 |
15 import ssl | 15 import ssl |
16 CERT_REQUIRED = ssl.CERT_REQUIRED | 16 CERT_REQUIRED = ssl.CERT_REQUIRED |
17 def ssl_wrap_socket(sock, keyfile, certfile, | 17 PROTOCOL_SSLv23 = ssl.PROTOCOL_SSLv23 |
18 PROTOCOL_TLSv1 = ssl.PROTOCOL_TLSv1 | |
19 def ssl_wrap_socket(sock, keyfile, certfile, ssl_version=PROTOCOL_TLSv1, | |
18 cert_reqs=ssl.CERT_NONE, ca_certs=None): | 20 cert_reqs=ssl.CERT_NONE, ca_certs=None): |
19 sslsocket = ssl.wrap_socket(sock, keyfile, certfile, | 21 sslsocket = ssl.wrap_socket(sock, keyfile, certfile, |
20 cert_reqs=cert_reqs, ca_certs=ca_certs) | 22 cert_reqs=cert_reqs, ca_certs=ca_certs, |
23 ssl_version=ssl_version) | |
21 # check if wrap_socket failed silently because socket had been closed | 24 # check if wrap_socket failed silently because socket had been closed |
22 # - see http://bugs.python.org/issue13721 | 25 # - see http://bugs.python.org/issue13721 |
23 if not sslsocket.cipher(): | 26 if not sslsocket.cipher(): |
24 raise util.Abort(_('ssl connection failed')) | 27 raise util.Abort(_('ssl connection failed')) |
25 return sslsocket | 28 return sslsocket |
26 except ImportError: | 29 except ImportError: |
27 CERT_REQUIRED = 2 | 30 CERT_REQUIRED = 2 |
28 | 31 |
32 PROTOCOL_SSLv23 = 2 | |
33 PROTOCOL_TLSv1 = 3 | |
34 | |
29 import socket, httplib | 35 import socket, httplib |
30 | 36 |
31 def ssl_wrap_socket(sock, key_file, cert_file, | 37 def ssl_wrap_socket(sock, key_file, cert_file, ssl_version=PROTOCOL_TLSv1, |
32 cert_reqs=CERT_REQUIRED, ca_certs=None): | 38 cert_reqs=CERT_REQUIRED, ca_certs=None): |
33 if not util.safehasattr(socket, 'ssl'): | 39 if not util.safehasattr(socket, 'ssl'): |
34 raise util.Abort(_('Python SSL support not found')) | 40 raise util.Abort(_('Python SSL support not found')) |
35 if ca_certs: | 41 if ca_certs: |
36 raise util.Abort(_( | 42 raise util.Abort(_( |
82 # We COMPLETELY ignore CERT_REQUIRED on Python <= 2.5, as it's totally | 88 # We COMPLETELY ignore CERT_REQUIRED on Python <= 2.5, as it's totally |
83 # busted on those versions. | 89 # busted on those versions. |
84 | 90 |
85 def sslkwargs(ui, host): | 91 def sslkwargs(ui, host): |
86 cacerts = ui.config('web', 'cacerts') | 92 cacerts = ui.config('web', 'cacerts') |
93 forcetls = ui.configbool('ui', 'tls', default=True) | |
94 if forcetls: | |
95 ssl_version = PROTOCOL_TLSv1 | |
96 else: | |
97 ssl_version = PROTOCOL_SSLv23 | |
87 hostfingerprint = ui.config('hostfingerprints', host) | 98 hostfingerprint = ui.config('hostfingerprints', host) |
99 kws = {'ssl_version': ssl_version, | |
100 } | |
88 if cacerts and not hostfingerprint: | 101 if cacerts and not hostfingerprint: |
89 cacerts = util.expandpath(cacerts) | 102 cacerts = util.expandpath(cacerts) |
90 if not os.path.exists(cacerts): | 103 if not os.path.exists(cacerts): |
91 raise util.Abort(_('could not find web.cacerts: %s') % cacerts) | 104 raise util.Abort(_('could not find web.cacerts: %s') % cacerts) |
92 return {'ca_certs': cacerts, | 105 kws.update({'ca_certs': cacerts, |
93 'cert_reqs': CERT_REQUIRED, | 106 'cert_reqs': CERT_REQUIRED, |
94 } | 107 }) |
95 return {} | 108 return kws |
96 | 109 |
97 class validator(object): | 110 class validator(object): |
98 def __init__(self, ui, host): | 111 def __init__(self, ui, host): |
99 self.ui = ui | 112 self.ui = ui |
100 self.host = host | 113 self.host = host |