summaryrefslogtreecommitdiff
path: root/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/contrib/pyopenssl.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/contrib/pyopenssl.py')
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/contrib/pyopenssl.py455
1 files changed, 0 insertions, 455 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/contrib/pyopenssl.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/contrib/pyopenssl.py
deleted file mode 100644
index f13e2bc..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/urllib3/contrib/pyopenssl.py
+++ /dev/null
@@ -1,455 +0,0 @@
1"""
2SSL with SNI_-support for Python 2. Follow these instructions if you would
3like to verify SSL certificates in Python 2. Note, the default libraries do
4*not* do certificate checking; you need to do additional work to validate
5certificates yourself.
6
7This needs the following packages installed:
8
9* pyOpenSSL (tested with 16.0.0)
10* cryptography (minimum 1.3.4, from pyopenssl)
11* idna (minimum 2.0, from cryptography)
12
13However, pyopenssl depends on cryptography, which depends on idna, so while we
14use all three directly here we end up having relatively few packages required.
15
16You can install them with the following command:
17
18 pip install pyopenssl cryptography idna
19
20To activate certificate checking, call
21:func:`~urllib3.contrib.pyopenssl.inject_into_urllib3` from your Python code
22before you begin making HTTP requests. This can be done in a ``sitecustomize``
23module, or at any other time before your application begins using ``urllib3``,
24like this::
25
26 try:
27 import urllib3.contrib.pyopenssl
28 urllib3.contrib.pyopenssl.inject_into_urllib3()
29 except ImportError:
30 pass
31
32Now you can use :mod:`urllib3` as you normally would, and it will support SNI
33when the required modules are installed.
34
35Activating this module also has the positive side effect of disabling SSL/TLS
36compression in Python 2 (see `CRIME attack`_).
37
38If you want to configure the default list of supported cipher suites, you can
39set the ``urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST`` variable.
40
41.. _sni: https://en.wikipedia.org/wiki/Server_Name_Indication
42.. _crime attack: https://en.wikipedia.org/wiki/CRIME_(security_exploit)
43"""
44from __future__ import absolute_import
45
46import OpenSSL.SSL
47from cryptography import x509
48from cryptography.hazmat.backends.openssl import backend as openssl_backend
49from cryptography.hazmat.backends.openssl.x509 import _Certificate
50
51from socket import timeout, error as SocketError
52from io import BytesIO
53
54try: # Platform-specific: Python 2
55 from socket import _fileobject
56except ImportError: # Platform-specific: Python 3
57 _fileobject = None
58 from ..packages.backports.makefile import backport_makefile
59
60import logging
61import ssl
62from ..packages import six
63import sys
64
65from .. import util
66
67__all__ = ['inject_into_urllib3', 'extract_from_urllib3']
68
69# SNI always works.
70HAS_SNI = True
71
72# Map from urllib3 to PyOpenSSL compatible parameter-values.
73_openssl_versions = {
74 ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD,
75 ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD,
76}
77
78if hasattr(ssl, 'PROTOCOL_TLSv1_1') and hasattr(OpenSSL.SSL, 'TLSv1_1_METHOD'):
79 _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD
80
81if hasattr(ssl, 'PROTOCOL_TLSv1_2') and hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'):
82 _openssl_versions[ssl.PROTOCOL_TLSv1_2] = OpenSSL.SSL.TLSv1_2_METHOD
83
84try:
85 _openssl_versions.update({ssl.PROTOCOL_SSLv3: OpenSSL.SSL.SSLv3_METHOD})
86except AttributeError:
87 pass
88
89_stdlib_to_openssl_verify = {
90 ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE,
91 ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER,
92 ssl.CERT_REQUIRED:
93 OpenSSL.SSL.VERIFY_PEER + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
94}
95_openssl_to_stdlib_verify = dict(
96 (v, k) for k, v in _stdlib_to_openssl_verify.items()
97)
98
99# OpenSSL will only write 16K at a time
100SSL_WRITE_BLOCKSIZE = 16384
101
102orig_util_HAS_SNI = util.HAS_SNI
103orig_util_SSLContext = util.ssl_.SSLContext
104
105
106log = logging.getLogger(__name__)
107
108
109def inject_into_urllib3():
110 'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.'
111
112 _validate_dependencies_met()
113
114 util.ssl_.SSLContext = PyOpenSSLContext
115 util.HAS_SNI = HAS_SNI
116 util.ssl_.HAS_SNI = HAS_SNI
117 util.IS_PYOPENSSL = True
118 util.ssl_.IS_PYOPENSSL = True
119
120
121def extract_from_urllib3():
122 'Undo monkey-patching by :func:`inject_into_urllib3`.'
123
124 util.ssl_.SSLContext = orig_util_SSLContext
125 util.HAS_SNI = orig_util_HAS_SNI
126 util.ssl_.HAS_SNI = orig_util_HAS_SNI
127 util.IS_PYOPENSSL = False
128 util.ssl_.IS_PYOPENSSL = False
129
130
131def _validate_dependencies_met():
132 """
133 Verifies that PyOpenSSL's package-level dependencies have been met.
134 Throws `ImportError` if they are not met.
135 """
136 # Method added in `cryptography==1.1`; not available in older versions
137 from cryptography.x509.extensions import Extensions
138 if getattr(Extensions, "get_extension_for_class", None) is None:
139 raise ImportError("'cryptography' module missing required functionality. "
140 "Try upgrading to v1.3.4 or newer.")
141
142 # pyOpenSSL 0.14 and above use cryptography for OpenSSL bindings. The _x509
143 # attribute is only present on those versions.
144 from OpenSSL.crypto import X509
145 x509 = X509()
146 if getattr(x509, "_x509", None) is None:
147 raise ImportError("'pyOpenSSL' module missing required functionality. "
148 "Try upgrading to v0.14 or newer.")
149
150
151def _dnsname_to_stdlib(name):
152 """
153 Converts a dNSName SubjectAlternativeName field to the form used by the
154 standard library on the given Python version.
155
156 Cryptography produces a dNSName as a unicode string that was idna-decoded
157 from ASCII bytes. We need to idna-encode that string to get it back, and
158 then on Python 3 we also need to convert to unicode via UTF-8 (the stdlib
159 uses PyUnicode_FromStringAndSize on it, which decodes via UTF-8).
160 """
161 def idna_encode(name):
162 """
163 Borrowed wholesale from the Python Cryptography Project. It turns out
164 that we can't just safely call `idna.encode`: it can explode for
165 wildcard names. This avoids that problem.
166 """
167 from pip._vendor import idna
168
169 for prefix in [u'*.', u'.']:
170 if name.startswith(prefix):
171 name = name[len(prefix):]
172 return prefix.encode('ascii') + idna.encode(name)
173 return idna.encode(name)
174
175 name = idna_encode(name)
176 if sys.version_info >= (3, 0):
177 name = name.decode('utf-8')
178 return name
179
180
181def get_subj_alt_name(peer_cert):
182 """
183 Given an PyOpenSSL certificate, provides all the subject alternative names.
184 """
185 # Pass the cert to cryptography, which has much better APIs for this.
186 if hasattr(peer_cert, "to_cryptography"):
187 cert = peer_cert.to_cryptography()
188 else:
189 # This is technically using private APIs, but should work across all
190 # relevant versions before PyOpenSSL got a proper API for this.
191 cert = _Certificate(openssl_backend, peer_cert._x509)
192
193 # We want to find the SAN extension. Ask Cryptography to locate it (it's
194 # faster than looping in Python)
195 try:
196 ext = cert.extensions.get_extension_for_class(
197 x509.SubjectAlternativeName
198 ).value
199 except x509.ExtensionNotFound:
200 # No such extension, return the empty list.
201 return []
202 except (x509.DuplicateExtension, x509.UnsupportedExtension,
203 x509.UnsupportedGeneralNameType, UnicodeError) as e:
204 # A problem has been found with the quality of the certificate. Assume
205 # no SAN field is present.
206 log.warning(
207 "A problem was encountered with the certificate that prevented "
208 "urllib3 from finding the SubjectAlternativeName field. This can "
209 "affect certificate validation. The error was %s",
210 e,
211 )
212 return []
213
214 # We want to return dNSName and iPAddress fields. We need to cast the IPs
215 # back to strings because the match_hostname function wants them as
216 # strings.
217 # Sadly the DNS names need to be idna encoded and then, on Python 3, UTF-8
218 # decoded. This is pretty frustrating, but that's what the standard library
219 # does with certificates, and so we need to attempt to do the same.
220 names = [
221 ('DNS', _dnsname_to_stdlib(name))
222 for name in ext.get_values_for_type(x509.DNSName)
223 ]
224 names.extend(
225 ('IP Address', str(name))
226 for name in ext.get_values_for_type(x509.IPAddress)
227 )
228
229 return names
230
231
232class WrappedSocket(object):
233 '''API-compatibility wrapper for Python OpenSSL's Connection-class.
234
235 Note: _makefile_refs, _drop() and _reuse() are needed for the garbage
236 collector of pypy.
237 '''
238
239 def __init__(self, connection, socket, suppress_ragged_eofs=True):
240 self.connection = connection
241 self.socket = socket
242 self.suppress_ragged_eofs = suppress_ragged_eofs
243 self._makefile_refs = 0
244 self._closed = False
245
246 def fileno(self):
247 return self.socket.fileno()
248
249 # Copy-pasted from Python 3.5 source code
250 def _decref_socketios(self):
251 if self._makefile_refs > 0:
252 self._makefile_refs -= 1
253 if self._closed:
254 self.close()
255
256 def recv(self, *args, **kwargs):
257 try:
258 data = self.connection.recv(*args, **kwargs)
259 except OpenSSL.SSL.SysCallError as e:
260 if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'):
261 return b''
262 else:
263 raise SocketError(str(e))
264 except OpenSSL.SSL.ZeroReturnError as e:
265 if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN:
266 return b''
267 else:
268 raise
269 except OpenSSL.SSL.WantReadError:
270 rd = util.wait_for_read(self.socket, self.socket.gettimeout())
271 if not rd:
272 raise timeout('The read operation timed out')
273 else:
274 return self.recv(*args, **kwargs)
275 else:
276 return data
277
278 def recv_into(self, *args, **kwargs):
279 try:
280 return self.connection.recv_into(*args, **kwargs)
281 except OpenSSL.SSL.SysCallError as e:
282 if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'):
283 return 0
284 else:
285 raise SocketError(str(e))
286 except OpenSSL.SSL.ZeroReturnError as e:
287 if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN:
288 return 0
289 else:
290 raise
291 except OpenSSL.SSL.WantReadError:
292 rd = util.wait_for_read(self.socket, self.socket.gettimeout())
293 if not rd:
294 raise timeout('The read operation timed out')
295 else:
296 return self.recv_into(*args, **kwargs)
297
298 def settimeout(self, timeout):
299 return self.socket.settimeout(timeout)
300
301 def _send_until_done(self, data):
302 while True:
303 try:
304 return self.connection.send(data)
305 except OpenSSL.SSL.WantWriteError:
306 wr = util.wait_for_write(self.socket, self.socket.gettimeout())
307 if not wr:
308 raise timeout()
309 continue
310 except OpenSSL.SSL.SysCallError as e:
311 raise SocketError(str(e))
312
313 def sendall(self, data):
314 total_sent = 0
315 while total_sent < len(data):
316 sent = self._send_until_done(data[total_sent:total_sent + SSL_WRITE_BLOCKSIZE])
317 total_sent += sent
318
319 def shutdown(self):
320 # FIXME rethrow compatible exceptions should we ever use this
321 self.connection.shutdown()
322
323 def close(self):
324 if self._makefile_refs < 1:
325 try:
326 self._closed = True
327 return self.connection.close()
328 except OpenSSL.SSL.Error:
329 return
330 else:
331 self._makefile_refs -= 1
332
333 def getpeercert(self, binary_form=False):
334 x509 = self.connection.get_peer_certificate()
335
336 if not x509:
337 return x509
338
339 if binary_form:
340 return OpenSSL.crypto.dump_certificate(
341 OpenSSL.crypto.FILETYPE_ASN1,
342 x509)
343
344 return {
345 'subject': (
346 (('commonName', x509.get_subject().CN),),
347 ),
348 'subjectAltName': get_subj_alt_name(x509)
349 }
350
351 def _reuse(self):
352 self._makefile_refs += 1
353
354 def _drop(self):
355 if self._makefile_refs < 1:
356 self.close()
357 else:
358 self._makefile_refs -= 1
359
360
361if _fileobject: # Platform-specific: Python 2
362 def makefile(self, mode, bufsize=-1):
363 self._makefile_refs += 1
364 return _fileobject(self, mode, bufsize, close=True)
365else: # Platform-specific: Python 3
366 makefile = backport_makefile
367
368WrappedSocket.makefile = makefile
369
370
371class PyOpenSSLContext(object):
372 """
373 I am a wrapper class for the PyOpenSSL ``Context`` object. I am responsible
374 for translating the interface of the standard library ``SSLContext`` object
375 to calls into PyOpenSSL.
376 """
377 def __init__(self, protocol):
378 self.protocol = _openssl_versions[protocol]
379 self._ctx = OpenSSL.SSL.Context(self.protocol)
380 self._options = 0
381 self.check_hostname = False
382
383 @property
384 def options(self):
385 return self._options
386
387 @options.setter
388 def options(self, value):
389 self._options = value
390 self._ctx.set_options(value)
391
392 @property
393 def verify_mode(self):
394 return _openssl_to_stdlib_verify[self._ctx.get_verify_mode()]
395
396 @verify_mode.setter
397 def verify_mode(self, value):
398 self._ctx.set_verify(
399 _stdlib_to_openssl_verify[value],
400 _verify_callback
401 )
402
403 def set_default_verify_paths(self):
404 self._ctx.set_default_verify_paths()
405
406 def set_ciphers(self, ciphers):
407 if isinstance(ciphers, six.text_type):
408 ciphers = ciphers.encode('utf-8')
409 self._ctx.set_cipher_list(ciphers)
410
411 def load_verify_locations(self, cafile=None, capath=None, cadata=None):
412 if cafile is not None:
413 cafile = cafile.encode('utf-8')
414 if capath is not None:
415 capath = capath.encode('utf-8')
416 self._ctx.load_verify_locations(cafile, capath)
417 if cadata is not None:
418 self._ctx.load_verify_locations(BytesIO(cadata))
419
420 def load_cert_chain(self, certfile, keyfile=None, password=None):
421 self._ctx.use_certificate_file(certfile)
422 if password is not None:
423 self._ctx.set_passwd_cb(lambda max_length, prompt_twice, userdata: password)
424 self._ctx.use_privatekey_file(keyfile or certfile)
425
426 def wrap_socket(self, sock, server_side=False,
427 do_handshake_on_connect=True, suppress_ragged_eofs=True,
428 server_hostname=None):
429 cnx = OpenSSL.SSL.Connection(self._ctx, sock)
430
431 if isinstance(server_hostname, six.text_type): # Platform-specific: Python 3
432 server_hostname = server_hostname.encode('utf-8')
433
434 if server_hostname is not None:
435 cnx.set_tlsext_host_name(server_hostname)
436
437 cnx.set_connect_state()
438
439 while True:
440 try:
441 cnx.do_handshake()
442 except OpenSSL.SSL.WantReadError:
443 rd = util.wait_for_read(sock, sock.gettimeout())
444 if not rd:
445 raise timeout('select timed out')
446 continue
447 except OpenSSL.SSL.Error as e:
448 raise ssl.SSLError('bad handshake: %r' % e)
449 break
450
451 return WrappedSocket(cnx, sock)
452
453
454def _verify_callback(cnx, x509, err_no, err_depth, return_code):
455 return err_no == 0