Index: swarm_client/third_party/requests/packages/urllib3/contrib/pyopenssl.py |
=================================================================== |
--- swarm_client/third_party/requests/packages/urllib3/contrib/pyopenssl.py (revision 235167) |
+++ swarm_client/third_party/requests/packages/urllib3/contrib/pyopenssl.py (working copy) |
@@ -1,344 +0,0 @@ |
-'''SSL with SNI-support for Python 2. |
- |
-This needs the following packages installed: |
- |
-* pyOpenSSL (tested with 0.13) |
-* ndg-httpsclient (tested with 0.3.2) |
-* pyasn1 (tested with 0.1.6) |
- |
-To activate it call :func:`~urllib3.contrib.pyopenssl.inject_into_urllib3`. |
-This can be done in a ``sitecustomize`` module, or at any other time before |
-your application begins using ``urllib3``, like this:: |
- |
- try: |
- import urllib3.contrib.pyopenssl |
- urllib3.contrib.pyopenssl.inject_into_urllib3() |
- except ImportError: |
- pass |
- |
-Now you can use :mod:`urllib3` as you normally would, and it will support SNI |
-when the required modules are installed. |
-''' |
- |
-from ndg.httpsclient.ssl_peer_verification import SUBJ_ALT_NAME_SUPPORT |
-from ndg.httpsclient.subj_alt_name import SubjectAltName |
-import OpenSSL.SSL |
-from pyasn1.codec.der import decoder as der_decoder |
-from socket import _fileobject |
-import ssl |
-from cStringIO import StringIO |
- |
-from .. import connectionpool |
-from .. import util |
- |
-__all__ = ['inject_into_urllib3', 'extract_from_urllib3'] |
- |
-# SNI only *really* works if we can read the subjectAltName of certificates. |
-HAS_SNI = SUBJ_ALT_NAME_SUPPORT |
- |
-# Map from urllib3 to PyOpenSSL compatible parameter-values. |
-_openssl_versions = { |
- ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD, |
- ssl.PROTOCOL_SSLv3: OpenSSL.SSL.SSLv3_METHOD, |
- ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, |
-} |
-_openssl_verify = { |
- ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE, |
- ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER, |
- ssl.CERT_REQUIRED: OpenSSL.SSL.VERIFY_PEER |
- + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT, |
-} |
- |
- |
-orig_util_HAS_SNI = util.HAS_SNI |
-orig_connectionpool_ssl_wrap_socket = connectionpool.ssl_wrap_socket |
- |
- |
-def inject_into_urllib3(): |
- 'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.' |
- |
- connectionpool.ssl_wrap_socket = ssl_wrap_socket |
- util.HAS_SNI = HAS_SNI |
- |
- |
-def extract_from_urllib3(): |
- 'Undo monkey-patching by :func:`inject_into_urllib3`.' |
- |
- connectionpool.ssl_wrap_socket = orig_connectionpool_ssl_wrap_socket |
- util.HAS_SNI = orig_util_HAS_SNI |
- |
- |
-### Note: This is a slightly bug-fixed version of same from ndg-httpsclient. |
-def get_subj_alt_name(peer_cert): |
- # Search through extensions |
- dns_name = [] |
- if not SUBJ_ALT_NAME_SUPPORT: |
- return dns_name |
- |
- general_names = SubjectAltName() |
- for i in range(peer_cert.get_extension_count()): |
- ext = peer_cert.get_extension(i) |
- ext_name = ext.get_short_name() |
- if ext_name != 'subjectAltName': |
- continue |
- |
- # PyOpenSSL returns extension data in ASN.1 encoded form |
- ext_dat = ext.get_data() |
- decoded_dat = der_decoder.decode(ext_dat, |
- asn1Spec=general_names) |
- |
- for name in decoded_dat: |
- if not isinstance(name, SubjectAltName): |
- continue |
- for entry in range(len(name)): |
- component = name.getComponentByPosition(entry) |
- if component.getName() != 'dNSName': |
- continue |
- dns_name.append(str(component.getComponent())) |
- |
- return dns_name |
- |
- |
-class fileobject(_fileobject): |
- |
- def read(self, size=-1): |
- # Use max, disallow tiny reads in a loop as they are very inefficient. |
- # We never leave read() with any leftover data from a new recv() call |
- # in our internal buffer. |
- rbufsize = max(self._rbufsize, self.default_bufsize) |
- # Our use of StringIO rather than lists of string objects returned by |
- # recv() minimizes memory usage and fragmentation that occurs when |
- # rbufsize is large compared to the typical return value of recv(). |
- buf = self._rbuf |
- buf.seek(0, 2) # seek end |
- if size < 0: |
- # Read until EOF |
- self._rbuf = StringIO() # reset _rbuf. we consume it via buf. |
- while True: |
- try: |
- data = self._sock.recv(rbufsize) |
- except OpenSSL.SSL.WantReadError: |
- continue |
- if not data: |
- break |
- buf.write(data) |
- return buf.getvalue() |
- else: |
- # Read until size bytes or EOF seen, whichever comes first |
- buf_len = buf.tell() |
- if buf_len >= size: |
- # Already have size bytes in our buffer? Extract and return. |
- buf.seek(0) |
- rv = buf.read(size) |
- self._rbuf = StringIO() |
- self._rbuf.write(buf.read()) |
- return rv |
- |
- self._rbuf = StringIO() # reset _rbuf. we consume it via buf. |
- while True: |
- left = size - buf_len |
- # recv() will malloc the amount of memory given as its |
- # parameter even though it often returns much less data |
- # than that. The returned data string is short lived |
- # as we copy it into a StringIO and free it. This avoids |
- # fragmentation issues on many platforms. |
- try: |
- data = self._sock.recv(left) |
- except OpenSSL.SSL.WantReadError: |
- continue |
- if not data: |
- break |
- n = len(data) |
- if n == size and not buf_len: |
- # Shortcut. Avoid buffer data copies when: |
- # - We have no data in our buffer. |
- # AND |
- # - Our call to recv returned exactly the |
- # number of bytes we were asked to read. |
- return data |
- if n == left: |
- buf.write(data) |
- del data # explicit free |
- break |
- assert n <= left, "recv(%d) returned %d bytes" % (left, n) |
- buf.write(data) |
- buf_len += n |
- del data # explicit free |
- #assert buf_len == buf.tell() |
- return buf.getvalue() |
- |
- def readline(self, size=-1): |
- buf = self._rbuf |
- buf.seek(0, 2) # seek end |
- if buf.tell() > 0: |
- # check if we already have it in our buffer |
- buf.seek(0) |
- bline = buf.readline(size) |
- if bline.endswith('\n') or len(bline) == size: |
- self._rbuf = StringIO() |
- self._rbuf.write(buf.read()) |
- return bline |
- del bline |
- if size < 0: |
- # Read until \n or EOF, whichever comes first |
- if self._rbufsize <= 1: |
- # Speed up unbuffered case |
- buf.seek(0) |
- buffers = [buf.read()] |
- self._rbuf = StringIO() # reset _rbuf. we consume it via buf. |
- data = None |
- recv = self._sock.recv |
- while True: |
- try: |
- while data != "\n": |
- data = recv(1) |
- if not data: |
- break |
- buffers.append(data) |
- except OpenSSL.SSL.WantReadError: |
- continue |
- break |
- return "".join(buffers) |
- |
- buf.seek(0, 2) # seek end |
- self._rbuf = StringIO() # reset _rbuf. we consume it via buf. |
- while True: |
- try: |
- data = self._sock.recv(self._rbufsize) |
- except OpenSSL.SSL.WantReadError: |
- continue |
- if not data: |
- break |
- nl = data.find('\n') |
- if nl >= 0: |
- nl += 1 |
- buf.write(data[:nl]) |
- self._rbuf.write(data[nl:]) |
- del data |
- break |
- buf.write(data) |
- return buf.getvalue() |
- else: |
- # Read until size bytes or \n or EOF seen, whichever comes first |
- buf.seek(0, 2) # seek end |
- buf_len = buf.tell() |
- if buf_len >= size: |
- buf.seek(0) |
- rv = buf.read(size) |
- self._rbuf = StringIO() |
- self._rbuf.write(buf.read()) |
- return rv |
- self._rbuf = StringIO() # reset _rbuf. we consume it via buf. |
- while True: |
- try: |
- data = self._sock.recv(self._rbufsize) |
- except OpenSSL.SSL.WantReadError: |
- continue |
- if not data: |
- break |
- left = size - buf_len |
- # did we just receive a newline? |
- nl = data.find('\n', 0, left) |
- if nl >= 0: |
- nl += 1 |
- # save the excess data to _rbuf |
- self._rbuf.write(data[nl:]) |
- if buf_len: |
- buf.write(data[:nl]) |
- break |
- else: |
- # Shortcut. Avoid data copy through buf when returning |
- # a substring of our first recv(). |
- return data[:nl] |
- n = len(data) |
- if n == size and not buf_len: |
- # Shortcut. Avoid data copy through buf when |
- # returning exactly all of our first recv(). |
- return data |
- if n >= left: |
- buf.write(data[:left]) |
- self._rbuf.write(data[left:]) |
- break |
- buf.write(data) |
- buf_len += n |
- #assert buf_len == buf.tell() |
- return buf.getvalue() |
- |
- |
-class WrappedSocket(object): |
- '''API-compatibility wrapper for Python OpenSSL's Connection-class.''' |
- |
- def __init__(self, connection, socket): |
- self.connection = connection |
- self.socket = socket |
- |
- def fileno(self): |
- return self.socket.fileno() |
- |
- def makefile(self, mode, bufsize=-1): |
- return fileobject(self.connection, mode, bufsize) |
- |
- def settimeout(self, timeout): |
- return self.socket.settimeout(timeout) |
- |
- def sendall(self, data): |
- return self.connection.sendall(data) |
- |
- def close(self): |
- return self.connection.shutdown() |
- |
- def getpeercert(self, binary_form=False): |
- x509 = self.connection.get_peer_certificate() |
- |
- if not x509: |
- return x509 |
- |
- if binary_form: |
- return OpenSSL.crypto.dump_certificate( |
- OpenSSL.crypto.FILETYPE_ASN1, |
- x509) |
- |
- return { |
- 'subject': ( |
- (('commonName', x509.get_subject().CN),), |
- ), |
- 'subjectAltName': [ |
- ('DNS', value) |
- for value in get_subj_alt_name(x509) |
- ] |
- } |
- |
- |
-def _verify_callback(cnx, x509, err_no, err_depth, return_code): |
- return err_no == 0 |
- |
- |
-def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, |
- ca_certs=None, server_hostname=None, |
- ssl_version=None): |
- ctx = OpenSSL.SSL.Context(_openssl_versions[ssl_version]) |
- if certfile: |
- ctx.use_certificate_file(certfile) |
- if keyfile: |
- ctx.use_privatekey_file(keyfile) |
- if cert_reqs != ssl.CERT_NONE: |
- ctx.set_verify(_openssl_verify[cert_reqs], _verify_callback) |
- if ca_certs: |
- try: |
- ctx.load_verify_locations(ca_certs, None) |
- except OpenSSL.SSL.Error as e: |
- raise ssl.SSLError('bad ca_certs: %r' % ca_certs, e) |
- |
- cnx = OpenSSL.SSL.Connection(ctx, sock) |
- cnx.set_tlsext_host_name(server_hostname) |
- cnx.set_connect_state() |
- while True: |
- try: |
- cnx.do_handshake() |
- except OpenSSL.SSL.WantReadError: |
- continue |
- except OpenSSL.SSL.Error as e: |
- raise ssl.SSLError('bad handshake', e) |
- break |
- |
- return WrappedSocket(cnx, sock) |