Show More
@@ -12,61 +12,54 b' from mercurial import util' | |||||
12 | from mercurial.i18n import _ |
|
12 | from mercurial.i18n import _ | |
13 |
|
13 | |||
14 | _canloaddefaultcerts = False |
|
14 | _canloaddefaultcerts = False | |
|
15 | CERT_REQUIRED = ssl.CERT_REQUIRED | |||
15 | try: |
|
16 | try: | |
16 | CERT_REQUIRED = ssl.CERT_REQUIRED |
|
17 | ssl_context = ssl.SSLContext | |
17 | try: |
|
18 | _canloaddefaultcerts = util.safehasattr(ssl_context, 'load_default_certs') | |
18 | ssl_context = ssl.SSLContext |
|
|||
19 | _canloaddefaultcerts = util.safehasattr(ssl_context, |
|
|||
20 | 'load_default_certs') |
|
|||
21 |
|
19 | |||
22 |
|
|
20 | def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE, | |
23 | cert_reqs=ssl.CERT_NONE, |
|
21 | ca_certs=None, serverhostname=None): | |
24 | ca_certs=None, serverhostname=None): |
|
22 | # Allow any version of SSL starting with TLSv1 and | |
25 | # Allow any version of SSL starting with TLSv1 and |
|
23 | # up. Note that specifying TLSv1 here prohibits use of | |
26 | # up. Note that specifying TLSv1 here prohibits use of |
|
24 | # newer standards (like TLSv1_2), so this is the right way | |
27 | # newer standards (like TLSv1_2), so this is the right way |
|
25 | # to do this. Note that in the future it'd be better to | |
28 | # to do this. Note that in the future it'd be better to |
|
26 | # support using ssl.create_default_context(), which sets | |
29 | # support using ssl.create_default_context(), which sets |
|
27 | # up a bunch of things in smart ways (strong ciphers, | |
30 | # up a bunch of things in smart ways (strong ciphers, |
|
28 | # protocol versions, etc) and is upgraded by Python | |
31 | # protocol versions, etc) and is upgraded by Python |
|
29 | # maintainers for us, but that breaks too many things to | |
32 | # maintainers for us, but that breaks too many things to |
|
30 | # do it in a hurry. | |
33 | # do it in a hurry. |
|
31 | sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) | |
34 | sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) |
|
32 | sslcontext.options &= ssl.OP_NO_SSLv2 & ssl.OP_NO_SSLv3 | |
35 | sslcontext.options &= ssl.OP_NO_SSLv2 & ssl.OP_NO_SSLv3 |
|
33 | if certfile is not None: | |
36 | if certfile is not None: |
|
34 | def password(): | |
37 | def password(): |
|
35 | f = keyfile or certfile | |
38 | f = keyfile or certfile |
|
36 | return ui.getpass(_('passphrase for %s: ') % f, '') | |
39 | return ui.getpass(_('passphrase for %s: ') % f, '') |
|
37 | sslcontext.load_cert_chain(certfile, keyfile, password) | |
40 | sslcontext.load_cert_chain(certfile, keyfile, password) |
|
38 | sslcontext.verify_mode = cert_reqs | |
41 | sslcontext.verify_mode = cert_reqs |
|
39 | if ca_certs is not None: | |
42 | if ca_certs is not None: |
|
40 | sslcontext.load_verify_locations(cafile=ca_certs) | |
43 | sslcontext.load_verify_locations(cafile=ca_certs) |
|
41 | elif _canloaddefaultcerts: | |
44 |
|
|
42 | sslcontext.load_default_certs() | |
45 | sslcontext.load_default_certs() |
|
|||
46 |
|
43 | |||
47 |
|
|
44 | sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname) | |
48 | server_hostname=serverhostname) |
|
45 | # check if wrap_socket failed silently because socket had been | |
49 | # check if wrap_socket failed silently because socket had been |
|
46 | # closed | |
50 | # closed |
|
47 | # - see http://bugs.python.org/issue13721 | |
51 | # - see http://bugs.python.org/issue13721 |
|
48 | if not sslsocket.cipher(): | |
52 | if not sslsocket.cipher(): |
|
49 | raise util.Abort(_('ssl connection failed')) | |
53 | raise util.Abort(_('ssl connection failed')) |
|
50 | return sslsocket | |
54 | return sslsocket |
|
51 | except AttributeError: | |
55 | except AttributeError: |
|
52 | def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE, | |
56 | def wrapsocket(sock, keyfile, certfile, ui, |
|
53 | ca_certs=None, serverhostname=None): | |
57 | cert_reqs=ssl.CERT_NONE, |
|
54 | sslsocket = ssl.wrap_socket(sock, keyfile, certfile, | |
58 | ca_certs=None, serverhostname=None): |
|
55 | cert_reqs=cert_reqs, ca_certs=ca_certs, | |
59 | sslsocket = ssl.wrap_socket(sock, keyfile, certfile, |
|
56 | ssl_version=ssl.PROTOCOL_TLSv1) | |
60 | cert_reqs=cert_reqs, ca_certs=ca_certs, |
|
57 | # check if wrap_socket failed silently because socket had been | |
61 | ssl_version=ssl.PROTOCOL_TLSv1) |
|
58 | # closed | |
62 | # check if wrap_socket failed silently because socket had been |
|
59 | # - see http://bugs.python.org/issue13721 | |
63 | # closed |
|
60 | if not sslsocket.cipher(): | |
64 | # - see http://bugs.python.org/issue13721 |
|
61 | raise util.Abort(_('ssl connection failed')) | |
65 |
|
|
62 | return sslsocket | |
66 | raise util.Abort(_('ssl connection failed')) |
|
|||
67 | return sslsocket |
|
|||
68 | except ImportError: |
|
|||
69 | raise |
|
|||
70 |
|
63 | |||
71 | def _verifycert(cert, hostname): |
|
64 | def _verifycert(cert, hostname): | |
72 | '''Verify that cert (in socket.getpeercert() format) matches hostname. |
|
65 | '''Verify that cert (in socket.getpeercert() format) matches hostname. |
General Comments 0
You need to be logged in to leave comments.
Login now