comparison mercurial/sslutil.py @ 29507:97dcdcf75f4f

sslutil: move protocol determination to _hostsettings Most of the logic for configuring TLS is now in this function. Let's move protocol determination code there as well.
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 06 Jul 2016 22:47:24 -0700
parents be68a4445041
children d65ec41b6384
comparison
equal deleted inserted replaced
29506:2550604f5ec7 29507:97dcdcf75f4f
124 'cafile': None, 124 'cafile': None,
125 # Whether certificate verification should be disabled. 125 # Whether certificate verification should be disabled.
126 'disablecertverification': False, 126 'disablecertverification': False,
127 # Whether the legacy [hostfingerprints] section has data for this host. 127 # Whether the legacy [hostfingerprints] section has data for this host.
128 'legacyfingerprint': False, 128 'legacyfingerprint': False,
129 # PROTOCOL_* constant to use for SSLContext.__init__.
130 'protocol': None,
129 # ssl.CERT_* constant used by SSLContext.verify_mode. 131 # ssl.CERT_* constant used by SSLContext.verify_mode.
130 'verifymode': None, 132 'verifymode': None,
131 } 133 }
134
135 # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
136 # that both ends support, including TLS protocols. On legacy stacks,
137 # the highest it likely goes in TLS 1.0. On modern stacks, it can
138 # support TLS 1.2.
139 #
140 # The PROTOCOL_TLSv* constants select a specific TLS version
141 # only (as opposed to multiple versions). So the method for
142 # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
143 # disable protocols via SSLContext.options and OP_NO_* constants.
144 # However, SSLContext.options doesn't work unless we have the
145 # full/real SSLContext available to us.
146 if modernssl:
147 s['protocol'] = ssl.PROTOCOL_SSLv23
148 else:
149 s['protocol'] = ssl.PROTOCOL_TLSv1
132 150
133 # Look for fingerprints in [hostsecurity] section. Value is a list 151 # Look for fingerprints in [hostsecurity] section. Value is a list
134 # of <alg>:<fingerprint> strings. 152 # of <alg>:<fingerprint> strings.
135 fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname, 153 fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname,
136 []) 154 [])
213 # is insecure. We allow the connection and abort during 231 # is insecure. We allow the connection and abort during
214 # validation (once we have the fingerprint to print to the 232 # validation (once we have the fingerprint to print to the
215 # user). 233 # user).
216 s['verifymode'] = ssl.CERT_NONE 234 s['verifymode'] = ssl.CERT_NONE
217 235
236 assert s['protocol'] is not None
218 assert s['verifymode'] is not None 237 assert s['verifymode'] is not None
219 238
220 return s 239 return s
221 240
222 def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None): 241 def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None):
235 if not serverhostname: 254 if not serverhostname:
236 raise error.Abort(_('serverhostname argument is required')) 255 raise error.Abort(_('serverhostname argument is required'))
237 256
238 settings = _hostsettings(ui, serverhostname) 257 settings = _hostsettings(ui, serverhostname)
239 258
240 # Despite its name, PROTOCOL_SSLv23 selects the highest protocol 259 # TODO use ssl.create_default_context() on modernssl.
241 # that both ends support, including TLS protocols. On legacy stacks, 260 sslcontext = SSLContext(settings['protocol'])
242 # the highest it likely goes in TLS 1.0. On modern stacks, it can 261
243 # support TLS 1.2.
244 #
245 # The PROTOCOL_TLSv* constants select a specific TLS version
246 # only (as opposed to multiple versions). So the method for
247 # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
248 # disable protocols via SSLContext.options and OP_NO_* constants.
249 # However, SSLContext.options doesn't work unless we have the
250 # full/real SSLContext available to us.
251 #
252 # SSLv2 and SSLv3 are broken. We ban them outright. 262 # SSLv2 and SSLv3 are broken. We ban them outright.
253 if modernssl:
254 protocol = ssl.PROTOCOL_SSLv23
255 else:
256 protocol = ssl.PROTOCOL_TLSv1
257
258 # TODO use ssl.create_default_context() on modernssl.
259 sslcontext = SSLContext(protocol)
260
261 # This is a no-op on old Python. 263 # This is a no-op on old Python.
262 sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3 264 sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3
263 265
264 # This still works on our fake SSLContext. 266 # This still works on our fake SSLContext.
265 sslcontext.verify_mode = settings['verifymode'] 267 sslcontext.verify_mode = settings['verifymode']