summaryrefslogtreecommitdiff
path: root/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py')
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py341
1 files changed, 341 insertions, 0 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py
new file mode 100644
index 0000000..c11dff2
--- /dev/null
+++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py
@@ -0,0 +1,341 @@
1from __future__ import absolute_import
2import errno
3import warnings
4import hmac
5
6from binascii import hexlify, unhexlify
7from hashlib import md5, sha1, sha256
8
9from ..exceptions import SSLError, InsecurePlatformWarning, SNIMissingWarning
10
11
12SSLContext = None
13HAS_SNI = False
14IS_PYOPENSSL = False
15IS_SECURETRANSPORT = False
16
17# Maps the length of a digest to a possible hash function producing this digest
18HASHFUNC_MAP = {
19 32: md5,
20 40: sha1,
21 64: sha256,
22}
23
24
25def _const_compare_digest_backport(a, b):
26 """
27 Compare two digests of equal length in constant time.
28
29 The digests must be of type str/bytes.
30 Returns True if the digests match, and False otherwise.
31 """
32 result = abs(len(a) - len(b))
33 for l, r in zip(bytearray(a), bytearray(b)):
34 result |= l ^ r
35 return result == 0
36
37
38_const_compare_digest = getattr(hmac, 'compare_digest',
39 _const_compare_digest_backport)
40
41
42try: # Test for SSL features
43 import ssl
44 from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23
45 from ssl import HAS_SNI # Has SNI?
46except ImportError:
47 pass
48
49
50try:
51 from ssl import OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION
52except ImportError:
53 OP_NO_SSLv2, OP_NO_SSLv3 = 0x1000000, 0x2000000
54 OP_NO_COMPRESSION = 0x20000
55
56# A secure default.
57# Sources for more information on TLS ciphers:
58#
59# - https://wiki.mozilla.org/Security/Server_Side_TLS
60# - https://www.ssllabs.com/projects/best-practices/index.html
61# - https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
62#
63# The general intent is:
64# - Prefer TLS 1.3 cipher suites
65# - prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE),
66# - prefer ECDHE over DHE for better performance,
67# - prefer any AES-GCM and ChaCha20 over any AES-CBC for better performance and
68# security,
69# - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common,
70# - disable NULL authentication, MD5 MACs and DSS for security reasons.
71DEFAULT_CIPHERS = ':'.join([
72 'TLS13-AES-256-GCM-SHA384',
73 'TLS13-CHACHA20-POLY1305-SHA256',
74 'TLS13-AES-128-GCM-SHA256',
75 'ECDH+AESGCM',
76 'ECDH+CHACHA20',
77 'DH+AESGCM',
78 'DH+CHACHA20',
79 'ECDH+AES256',
80 'DH+AES256',
81 'ECDH+AES128',
82 'DH+AES',
83 'RSA+AESGCM',
84 'RSA+AES',
85 '!aNULL',
86 '!eNULL',
87 '!MD5',
88])
89
90try:
91 from ssl import SSLContext # Modern SSL?
92except ImportError:
93 import sys
94
95 class SSLContext(object): # Platform-specific: Python 2 & 3.1
96 supports_set_ciphers = ((2, 7) <= sys.version_info < (3,) or
97 (3, 2) <= sys.version_info)
98
99 def __init__(self, protocol_version):
100 self.protocol = protocol_version
101 # Use default values from a real SSLContext
102 self.check_hostname = False
103 self.verify_mode = ssl.CERT_NONE
104 self.ca_certs = None
105 self.options = 0
106 self.certfile = None
107 self.keyfile = None
108 self.ciphers = None
109
110 def load_cert_chain(self, certfile, keyfile):
111 self.certfile = certfile
112 self.keyfile = keyfile
113
114 def load_verify_locations(self, cafile=None, capath=None):
115 self.ca_certs = cafile
116
117 if capath is not None:
118 raise SSLError("CA directories not supported in older Pythons")
119
120 def set_ciphers(self, cipher_suite):
121 if not self.supports_set_ciphers:
122 raise TypeError(
123 'Your version of Python does not support setting '
124 'a custom cipher suite. Please upgrade to Python '
125 '2.7, 3.2, or later if you need this functionality.'
126 )
127 self.ciphers = cipher_suite
128
129 def wrap_socket(self, socket, server_hostname=None, server_side=False):
130 warnings.warn(
131 'A true SSLContext object is not available. This prevents '
132 'urllib3 from configuring SSL appropriately and may cause '
133 'certain SSL connections to fail. You can upgrade to a newer '
134 'version of Python to solve this. For more information, see '
135 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html'
136 '#ssl-warnings',
137 InsecurePlatformWarning
138 )
139 kwargs = {
140 'keyfile': self.keyfile,
141 'certfile': self.certfile,
142 'ca_certs': self.ca_certs,
143 'cert_reqs': self.verify_mode,
144 'ssl_version': self.protocol,
145 'server_side': server_side,
146 }
147 if self.supports_set_ciphers: # Platform-specific: Python 2.7+
148 return wrap_socket(socket, ciphers=self.ciphers, **kwargs)
149 else: # Platform-specific: Python 2.6
150 return wrap_socket(socket, **kwargs)
151
152
153def assert_fingerprint(cert, fingerprint):
154 """
155 Checks if given fingerprint matches the supplied certificate.
156
157 :param cert:
158 Certificate as bytes object.
159 :param fingerprint:
160 Fingerprint as string of hexdigits, can be interspersed by colons.
161 """
162
163 fingerprint = fingerprint.replace(':', '').lower()
164 digest_length = len(fingerprint)
165 hashfunc = HASHFUNC_MAP.get(digest_length)
166 if not hashfunc:
167 raise SSLError(
168 'Fingerprint of invalid length: {0}'.format(fingerprint))
169
170 # We need encode() here for py32; works on py2 and p33.
171 fingerprint_bytes = unhexlify(fingerprint.encode())
172
173 cert_digest = hashfunc(cert).digest()
174
175 if not _const_compare_digest(cert_digest, fingerprint_bytes):
176 raise SSLError('Fingerprints did not match. Expected "{0}", got "{1}".'
177 .format(fingerprint, hexlify(cert_digest)))
178
179
180def resolve_cert_reqs(candidate):
181 """
182 Resolves the argument to a numeric constant, which can be passed to
183 the wrap_socket function/method from the ssl module.
184 Defaults to :data:`ssl.CERT_NONE`.
185 If given a string it is assumed to be the name of the constant in the
186 :mod:`ssl` module or its abbrevation.
187 (So you can specify `REQUIRED` instead of `CERT_REQUIRED`.
188 If it's neither `None` nor a string we assume it is already the numeric
189 constant which can directly be passed to wrap_socket.
190 """
191 if candidate is None:
192 return CERT_NONE
193
194 if isinstance(candidate, str):
195 res = getattr(ssl, candidate, None)
196 if res is None:
197 res = getattr(ssl, 'CERT_' + candidate)
198 return res
199
200 return candidate
201
202
203def resolve_ssl_version(candidate):
204 """
205 like resolve_cert_reqs
206 """
207 if candidate is None:
208 return PROTOCOL_SSLv23
209
210 if isinstance(candidate, str):
211 res = getattr(ssl, candidate, None)
212 if res is None:
213 res = getattr(ssl, 'PROTOCOL_' + candidate)
214 return res
215
216 return candidate
217
218
219def create_urllib3_context(ssl_version=None, cert_reqs=None,
220 options=None, ciphers=None):
221 """All arguments have the same meaning as ``ssl_wrap_socket``.
222
223 By default, this function does a lot of the same work that
224 ``ssl.create_default_context`` does on Python 3.4+. It:
225
226 - Disables SSLv2, SSLv3, and compression
227 - Sets a restricted set of server ciphers
228
229 If you wish to enable SSLv3, you can do::
230
231 from pip._vendor.urllib3.util import ssl_
232 context = ssl_.create_urllib3_context()
233 context.options &= ~ssl_.OP_NO_SSLv3
234
235 You can do the same to enable compression (substituting ``COMPRESSION``
236 for ``SSLv3`` in the last line above).
237
238 :param ssl_version:
239 The desired protocol version to use. This will default to
240 PROTOCOL_SSLv23 which will negotiate the highest protocol that both
241 the server and your installation of OpenSSL support.
242 :param cert_reqs:
243 Whether to require the certificate verification. This defaults to
244 ``ssl.CERT_REQUIRED``.
245 :param options:
246 Specific OpenSSL options. These default to ``ssl.OP_NO_SSLv2``,
247 ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``.
248 :param ciphers:
249 Which cipher suites to allow the server to select.
250 :returns:
251 Constructed SSLContext object with specified options
252 :rtype: SSLContext
253 """
254 context = SSLContext(ssl_version or ssl.PROTOCOL_SSLv23)
255
256 # Setting the default here, as we may have no ssl module on import
257 cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs
258
259 if options is None:
260 options = 0
261 # SSLv2 is easily broken and is considered harmful and dangerous
262 options |= OP_NO_SSLv2
263 # SSLv3 has several problems and is now dangerous
264 options |= OP_NO_SSLv3
265 # Disable compression to prevent CRIME attacks for OpenSSL 1.0+
266 # (issue #309)
267 options |= OP_NO_COMPRESSION
268
269 context.options |= options
270
271 if getattr(context, 'supports_set_ciphers', True): # Platform-specific: Python 2.6
272 context.set_ciphers(ciphers or DEFAULT_CIPHERS)
273
274 context.verify_mode = cert_reqs
275 if getattr(context, 'check_hostname', None) is not None: # Platform-specific: Python 3.2
276 # We do our own verification, including fingerprints and alternative
277 # hostnames. So disable it here
278 context.check_hostname = False
279 return context
280
281
282def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
283 ca_certs=None, server_hostname=None,
284 ssl_version=None, ciphers=None, ssl_context=None,
285 ca_cert_dir=None):
286 """
287 All arguments except for server_hostname, ssl_context, and ca_cert_dir have
288 the same meaning as they do when using :func:`ssl.wrap_socket`.
289
290 :param server_hostname:
291 When SNI is supported, the expected hostname of the certificate
292 :param ssl_context:
293 A pre-made :class:`SSLContext` object. If none is provided, one will
294 be created using :func:`create_urllib3_context`.
295 :param ciphers:
296 A string of ciphers we wish the client to support. This is not
297 supported on Python 2.6 as the ssl module does not support it.
298 :param ca_cert_dir:
299 A directory containing CA certificates in multiple separate files, as
300 supported by OpenSSL's -CApath flag or the capath argument to
301 SSLContext.load_verify_locations().
302 """
303 context = ssl_context
304 if context is None:
305 # Note: This branch of code and all the variables in it are no longer
306 # used by urllib3 itself. We should consider deprecating and removing
307 # this code.
308 context = create_urllib3_context(ssl_version, cert_reqs,
309 ciphers=ciphers)
310
311 if ca_certs or ca_cert_dir:
312 try:
313 context.load_verify_locations(ca_certs, ca_cert_dir)
314 except IOError as e: # Platform-specific: Python 2.6, 2.7, 3.2
315 raise SSLError(e)
316 # Py33 raises FileNotFoundError which subclasses OSError
317 # These are not equivalent unless we check the errno attribute
318 except OSError as e: # Platform-specific: Python 3.3 and beyond
319 if e.errno == errno.ENOENT:
320 raise SSLError(e)
321 raise
322 elif getattr(context, 'load_default_certs', None) is not None:
323 # try to load OS default certs; works well on Windows (require Python3.4+)
324 context.load_default_certs()
325
326 if certfile:
327 context.load_cert_chain(certfile, keyfile)
328 if HAS_SNI: # Platform-specific: OpenSSL with enabled SNI
329 return context.wrap_socket(sock, server_hostname=server_hostname)
330
331 warnings.warn(
332 'An HTTPS request has been made, but the SNI (Subject Name '
333 'Indication) extension to TLS is not available on this platform. '
334 'This may cause the server to present an incorrect TLS '
335 'certificate, which can cause validation failures. You can upgrade to '
336 'a newer version of Python to solve this. For more information, see '
337 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html'
338 '#ssl-warnings',
339 SNIMissingWarning
340 )
341 return context.wrap_socket(sock)