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'] |