Mercurial > hg
comparison mercurial/sslutil.py @ 28649:7acab42ef184
sslutil: implement SSLContext class
Python <2.7.9 doesn't have a ssl.SSLContext class. In this patch,
we implement the interface to the class so we can have a unified
code path for all supported versions of Python.
This is similar to the approach that urllib3 takes.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sun, 27 Mar 2016 13:50:34 -0700 |
parents | 7fc787e5d8ec |
children | 737863b01d9f |
comparison
equal
deleted
inserted
replaced
28648:7fc787e5d8ec | 28649:7acab42ef184 |
---|---|
33 OP_NO_SSLv2 = ssl.OP_NO_SSLv2 | 33 OP_NO_SSLv2 = ssl.OP_NO_SSLv2 |
34 OP_NO_SSLv3 = ssl.OP_NO_SSLv3 | 34 OP_NO_SSLv3 = ssl.OP_NO_SSLv3 |
35 except AttributeError: | 35 except AttributeError: |
36 OP_NO_SSLv2 = 0x1000000 | 36 OP_NO_SSLv2 = 0x1000000 |
37 OP_NO_SSLv3 = 0x2000000 | 37 OP_NO_SSLv3 = 0x2000000 |
38 | |
39 try: | |
40 # ssl.SSLContext was added in 2.7.9 and presence indicates modern | |
41 # SSL/TLS features are available. | |
42 SSLContext = ssl.SSLContext | |
43 modernssl = True | |
44 except AttributeError: | |
45 modernssl = False | |
46 | |
47 # We implement SSLContext using the interface from the standard library. | |
48 class SSLContext(object): | |
49 # ssl.wrap_socket gained the "ciphers" named argument in 2.7. | |
50 _supportsciphers = sys.version_info >= (2, 7) | |
51 | |
52 def __init__(self, protocol): | |
53 # From the public interface of SSLContext | |
54 self.protocol = protocol | |
55 self.check_hostname = False | |
56 self.options = 0 | |
57 self.verify_mode = ssl.CERT_NONE | |
58 | |
59 # Used by our implementation. | |
60 self._certfile = None | |
61 self._keyfile = None | |
62 self._certpassword = None | |
63 self._cacerts = None | |
64 self._ciphers = None | |
65 | |
66 def load_cert_chain(self, certfile, keyfile=None, password=None): | |
67 self._certfile = certfile | |
68 self._keyfile = keyfile | |
69 self._certpassword = password | |
70 | |
71 def load_default_certs(self, purpose=None): | |
72 pass | |
73 | |
74 def load_verify_locations(self, cafile=None, capath=None, cadata=None): | |
75 if capath: | |
76 raise error.Abort('capath not supported') | |
77 if cadata: | |
78 raise error.Abort('cadata not supported') | |
79 | |
80 self._cacerts = cafile | |
81 | |
82 def set_ciphers(self, ciphers): | |
83 if not self._supportsciphers: | |
84 raise error.Abort('setting ciphers not supported') | |
85 | |
86 self._ciphers = ciphers | |
87 | |
88 def wrap_socket(self, socket, server_hostname=None, server_side=False): | |
89 # server_hostname is unique to SSLContext.wrap_socket and is used | |
90 # for SNI in that context. So there's nothing for us to do with it | |
91 # in this legacy code since we don't support SNI. | |
92 | |
93 args = { | |
94 'keyfile': self._keyfile, | |
95 'certfile': self._certfile, | |
96 'server_side': server_side, | |
97 'cert_reqs': self.verify_mode, | |
98 'ssl_version': self.protocol, | |
99 'ca_certs': self._cacerts, | |
100 } | |
101 | |
102 if self._supportsciphers: | |
103 args['ciphers'] = self._ciphers | |
104 | |
105 return ssl.wrap_socket(socket, **args) | |
38 | 106 |
39 _canloaddefaultcerts = False | 107 _canloaddefaultcerts = False |
40 try: | 108 try: |
41 # ssl.SSLContext was added in 2.7.9 and presence indicates modern | 109 # ssl.SSLContext was added in 2.7.9 and presence indicates modern |
42 # SSL/TLS features are available. | 110 # SSL/TLS features are available. |