]> jfr.im git - dlqueue.git/blobdiff - venv/lib/python3.11/site-packages/pip/_vendor/urllib3/contrib/securetransport.py
hello world
[dlqueue.git] / venv / lib / python3.11 / site-packages / pip / _vendor / urllib3 / contrib / securetransport.py
diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/contrib/securetransport.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/contrib/securetransport.py
deleted file mode 100644 (file)
index 4a06bc6..0000000
+++ /dev/null
@@ -1,921 +0,0 @@
-"""
-SecureTranport support for urllib3 via ctypes.
-
-This makes platform-native TLS available to urllib3 users on macOS without the
-use of a compiler. This is an important feature because the Python Package
-Index is moving to become a TLSv1.2-or-higher server, and the default OpenSSL
-that ships with macOS is not capable of doing TLSv1.2. The only way to resolve
-this is to give macOS users an alternative solution to the problem, and that
-solution is to use SecureTransport.
-
-We use ctypes here because this solution must not require a compiler. That's
-because pip is not allowed to require a compiler either.
-
-This is not intended to be a seriously long-term solution to this problem.
-The hope is that PEP 543 will eventually solve this issue for us, at which
-point we can retire this contrib module. But in the short term, we need to
-solve the impending tire fire that is Python on Mac without this kind of
-contrib module. So...here we are.
-
-To use this module, simply import and inject it::
-
-    import pip._vendor.urllib3.contrib.securetransport as securetransport
-    securetransport.inject_into_urllib3()
-
-Happy TLSing!
-
-This code is a bastardised version of the code found in Will Bond's oscrypto
-library. An enormous debt is owed to him for blazing this trail for us. For
-that reason, this code should be considered to be covered both by urllib3's
-license and by oscrypto's:
-
-.. code-block::
-
-    Copyright (c) 2015-2016 Will Bond <will@wbond.net>
-
-    Permission is hereby granted, free of charge, to any person obtaining a
-    copy of this software and associated documentation files (the "Software"),
-    to deal in the Software without restriction, including without limitation
-    the rights to use, copy, modify, merge, publish, distribute, sublicense,
-    and/or sell copies of the Software, and to permit persons to whom the
-    Software is furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be included in
-    all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-    DEALINGS IN THE SOFTWARE.
-"""
-from __future__ import absolute_import
-
-import contextlib
-import ctypes
-import errno
-import os.path
-import shutil
-import socket
-import ssl
-import struct
-import threading
-import weakref
-
-from pip._vendor import six
-
-from .. import util
-from ..util.ssl_ import PROTOCOL_TLS_CLIENT
-from ._securetransport.bindings import CoreFoundation, Security, SecurityConst
-from ._securetransport.low_level import (
-    _assert_no_error,
-    _build_tls_unknown_ca_alert,
-    _cert_array_from_pem,
-    _create_cfstring_array,
-    _load_client_cert_chain,
-    _temporary_keychain,
-)
-
-try:  # Platform-specific: Python 2
-    from socket import _fileobject
-except ImportError:  # Platform-specific: Python 3
-    _fileobject = None
-    from ..packages.backports.makefile import backport_makefile
-
-__all__ = ["inject_into_urllib3", "extract_from_urllib3"]
-
-# SNI always works
-HAS_SNI = True
-
-orig_util_HAS_SNI = util.HAS_SNI
-orig_util_SSLContext = util.ssl_.SSLContext
-
-# This dictionary is used by the read callback to obtain a handle to the
-# calling wrapped socket. This is a pretty silly approach, but for now it'll
-# do. I feel like I should be able to smuggle a handle to the wrapped socket
-# directly in the SSLConnectionRef, but for now this approach will work I
-# guess.
-#
-# We need to lock around this structure for inserts, but we don't do it for
-# reads/writes in the callbacks. The reasoning here goes as follows:
-#
-#    1. It is not possible to call into the callbacks before the dictionary is
-#       populated, so once in the callback the id must be in the dictionary.
-#    2. The callbacks don't mutate the dictionary, they only read from it, and
-#       so cannot conflict with any of the insertions.
-#
-# This is good: if we had to lock in the callbacks we'd drastically slow down
-# the performance of this code.
-_connection_refs = weakref.WeakValueDictionary()
-_connection_ref_lock = threading.Lock()
-
-# Limit writes to 16kB. This is OpenSSL's limit, but we'll cargo-cult it over
-# for no better reason than we need *a* limit, and this one is right there.
-SSL_WRITE_BLOCKSIZE = 16384
-
-# This is our equivalent of util.ssl_.DEFAULT_CIPHERS, but expanded out to
-# individual cipher suites. We need to do this because this is how
-# SecureTransport wants them.
-CIPHER_SUITES = [
-    SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-    SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-    SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-    SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-    SecurityConst.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
-    SecurityConst.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-    SecurityConst.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
-    SecurityConst.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
-    SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
-    SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-    SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
-    SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-    SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
-    SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-    SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
-    SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-    SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
-    SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
-    SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
-    SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
-    SecurityConst.TLS_AES_256_GCM_SHA384,
-    SecurityConst.TLS_AES_128_GCM_SHA256,
-    SecurityConst.TLS_RSA_WITH_AES_256_GCM_SHA384,
-    SecurityConst.TLS_RSA_WITH_AES_128_GCM_SHA256,
-    SecurityConst.TLS_AES_128_CCM_8_SHA256,
-    SecurityConst.TLS_AES_128_CCM_SHA256,
-    SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA256,
-    SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA256,
-    SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA,
-    SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA,
-]
-
-# Basically this is simple: for PROTOCOL_SSLv23 we turn it into a low of
-# TLSv1 and a high of TLSv1.2. For everything else, we pin to that version.
-# TLSv1 to 1.2 are supported on macOS 10.8+
-_protocol_to_min_max = {
-    util.PROTOCOL_TLS: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12),
-    PROTOCOL_TLS_CLIENT: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12),
-}
-
-if hasattr(ssl, "PROTOCOL_SSLv2"):
-    _protocol_to_min_max[ssl.PROTOCOL_SSLv2] = (
-        SecurityConst.kSSLProtocol2,
-        SecurityConst.kSSLProtocol2,
-    )
-if hasattr(ssl, "PROTOCOL_SSLv3"):
-    _protocol_to_min_max[ssl.PROTOCOL_SSLv3] = (
-        SecurityConst.kSSLProtocol3,
-        SecurityConst.kSSLProtocol3,
-    )
-if hasattr(ssl, "PROTOCOL_TLSv1"):
-    _protocol_to_min_max[ssl.PROTOCOL_TLSv1] = (
-        SecurityConst.kTLSProtocol1,
-        SecurityConst.kTLSProtocol1,
-    )
-if hasattr(ssl, "PROTOCOL_TLSv1_1"):
-    _protocol_to_min_max[ssl.PROTOCOL_TLSv1_1] = (
-        SecurityConst.kTLSProtocol11,
-        SecurityConst.kTLSProtocol11,
-    )
-if hasattr(ssl, "PROTOCOL_TLSv1_2"):
-    _protocol_to_min_max[ssl.PROTOCOL_TLSv1_2] = (
-        SecurityConst.kTLSProtocol12,
-        SecurityConst.kTLSProtocol12,
-    )
-
-
-def inject_into_urllib3():
-    """
-    Monkey-patch urllib3 with SecureTransport-backed SSL-support.
-    """
-    util.SSLContext = SecureTransportContext
-    util.ssl_.SSLContext = SecureTransportContext
-    util.HAS_SNI = HAS_SNI
-    util.ssl_.HAS_SNI = HAS_SNI
-    util.IS_SECURETRANSPORT = True
-    util.ssl_.IS_SECURETRANSPORT = True
-
-
-def extract_from_urllib3():
-    """
-    Undo monkey-patching by :func:`inject_into_urllib3`.
-    """
-    util.SSLContext = orig_util_SSLContext
-    util.ssl_.SSLContext = orig_util_SSLContext
-    util.HAS_SNI = orig_util_HAS_SNI
-    util.ssl_.HAS_SNI = orig_util_HAS_SNI
-    util.IS_SECURETRANSPORT = False
-    util.ssl_.IS_SECURETRANSPORT = False
-
-
-def _read_callback(connection_id, data_buffer, data_length_pointer):
-    """
-    SecureTransport read callback. This is called by ST to request that data
-    be returned from the socket.
-    """
-    wrapped_socket = None
-    try:
-        wrapped_socket = _connection_refs.get(connection_id)
-        if wrapped_socket is None:
-            return SecurityConst.errSSLInternal
-        base_socket = wrapped_socket.socket
-
-        requested_length = data_length_pointer[0]
-
-        timeout = wrapped_socket.gettimeout()
-        error = None
-        read_count = 0
-
-        try:
-            while read_count < requested_length:
-                if timeout is None or timeout >= 0:
-                    if not util.wait_for_read(base_socket, timeout):
-                        raise socket.error(errno.EAGAIN, "timed out")
-
-                remaining = requested_length - read_count
-                buffer = (ctypes.c_char * remaining).from_address(
-                    data_buffer + read_count
-                )
-                chunk_size = base_socket.recv_into(buffer, remaining)
-                read_count += chunk_size
-                if not chunk_size:
-                    if not read_count:
-                        return SecurityConst.errSSLClosedGraceful
-                    break
-        except (socket.error) as e:
-            error = e.errno
-
-            if error is not None and error != errno.EAGAIN:
-                data_length_pointer[0] = read_count
-                if error == errno.ECONNRESET or error == errno.EPIPE:
-                    return SecurityConst.errSSLClosedAbort
-                raise
-
-        data_length_pointer[0] = read_count
-
-        if read_count != requested_length:
-            return SecurityConst.errSSLWouldBlock
-
-        return 0
-    except Exception as e:
-        if wrapped_socket is not None:
-            wrapped_socket._exception = e
-        return SecurityConst.errSSLInternal
-
-
-def _write_callback(connection_id, data_buffer, data_length_pointer):
-    """
-    SecureTransport write callback. This is called by ST to request that data
-    actually be sent on the network.
-    """
-    wrapped_socket = None
-    try:
-        wrapped_socket = _connection_refs.get(connection_id)
-        if wrapped_socket is None:
-            return SecurityConst.errSSLInternal
-        base_socket = wrapped_socket.socket
-
-        bytes_to_write = data_length_pointer[0]
-        data = ctypes.string_at(data_buffer, bytes_to_write)
-
-        timeout = wrapped_socket.gettimeout()
-        error = None
-        sent = 0
-
-        try:
-            while sent < bytes_to_write:
-                if timeout is None or timeout >= 0:
-                    if not util.wait_for_write(base_socket, timeout):
-                        raise socket.error(errno.EAGAIN, "timed out")
-                chunk_sent = base_socket.send(data)
-                sent += chunk_sent
-
-                # This has some needless copying here, but I'm not sure there's
-                # much value in optimising this data path.
-                data = data[chunk_sent:]
-        except (socket.error) as e:
-            error = e.errno
-
-            if error is not None and error != errno.EAGAIN:
-                data_length_pointer[0] = sent
-                if error == errno.ECONNRESET or error == errno.EPIPE:
-                    return SecurityConst.errSSLClosedAbort
-                raise
-
-        data_length_pointer[0] = sent
-
-        if sent != bytes_to_write:
-            return SecurityConst.errSSLWouldBlock
-
-        return 0
-    except Exception as e:
-        if wrapped_socket is not None:
-            wrapped_socket._exception = e
-        return SecurityConst.errSSLInternal
-
-
-# We need to keep these two objects references alive: if they get GC'd while
-# in use then SecureTransport could attempt to call a function that is in freed
-# memory. That would be...uh...bad. Yeah, that's the word. Bad.
-_read_callback_pointer = Security.SSLReadFunc(_read_callback)
-_write_callback_pointer = Security.SSLWriteFunc(_write_callback)
-
-
-class WrappedSocket(object):
-    """
-    API-compatibility wrapper for Python's OpenSSL wrapped socket object.
-
-    Note: _makefile_refs, _drop(), and _reuse() are needed for the garbage
-    collector of PyPy.
-    """
-
-    def __init__(self, socket):
-        self.socket = socket
-        self.context = None
-        self._makefile_refs = 0
-        self._closed = False
-        self._exception = None
-        self._keychain = None
-        self._keychain_dir = None
-        self._client_cert_chain = None
-
-        # We save off the previously-configured timeout and then set it to
-        # zero. This is done because we use select and friends to handle the
-        # timeouts, but if we leave the timeout set on the lower socket then
-        # Python will "kindly" call select on that socket again for us. Avoid
-        # that by forcing the timeout to zero.
-        self._timeout = self.socket.gettimeout()
-        self.socket.settimeout(0)
-
-    @contextlib.contextmanager
-    def _raise_on_error(self):
-        """
-        A context manager that can be used to wrap calls that do I/O from
-        SecureTransport. If any of the I/O callbacks hit an exception, this
-        context manager will correctly propagate the exception after the fact.
-        This avoids silently swallowing those exceptions.
-
-        It also correctly forces the socket closed.
-        """
-        self._exception = None
-
-        # We explicitly don't catch around this yield because in the unlikely
-        # event that an exception was hit in the block we don't want to swallow
-        # it.
-        yield
-        if self._exception is not None:
-            exception, self._exception = self._exception, None
-            self.close()
-            raise exception
-
-    def _set_ciphers(self):
-        """
-        Sets up the allowed ciphers. By default this matches the set in
-        util.ssl_.DEFAULT_CIPHERS, at least as supported by macOS. This is done
-        custom and doesn't allow changing at this time, mostly because parsing
-        OpenSSL cipher strings is going to be a freaking nightmare.
-        """
-        ciphers = (Security.SSLCipherSuite * len(CIPHER_SUITES))(*CIPHER_SUITES)
-        result = Security.SSLSetEnabledCiphers(
-            self.context, ciphers, len(CIPHER_SUITES)
-        )
-        _assert_no_error(result)
-
-    def _set_alpn_protocols(self, protocols):
-        """
-        Sets up the ALPN protocols on the context.
-        """
-        if not protocols:
-            return
-        protocols_arr = _create_cfstring_array(protocols)
-        try:
-            result = Security.SSLSetALPNProtocols(self.context, protocols_arr)
-            _assert_no_error(result)
-        finally:
-            CoreFoundation.CFRelease(protocols_arr)
-
-    def _custom_validate(self, verify, trust_bundle):
-        """
-        Called when we have set custom validation. We do this in two cases:
-        first, when cert validation is entirely disabled; and second, when
-        using a custom trust DB.
-        Raises an SSLError if the connection is not trusted.
-        """
-        # If we disabled cert validation, just say: cool.
-        if not verify:
-            return
-
-        successes = (
-            SecurityConst.kSecTrustResultUnspecified,
-            SecurityConst.kSecTrustResultProceed,
-        )
-        try:
-            trust_result = self._evaluate_trust(trust_bundle)
-            if trust_result in successes:
-                return
-            reason = "error code: %d" % (trust_result,)
-        except Exception as e:
-            # Do not trust on error
-            reason = "exception: %r" % (e,)
-
-        # SecureTransport does not send an alert nor shuts down the connection.
-        rec = _build_tls_unknown_ca_alert(self.version())
-        self.socket.sendall(rec)
-        # close the connection immediately
-        # l_onoff = 1, activate linger
-        # l_linger = 0, linger for 0 seoncds
-        opts = struct.pack("ii", 1, 0)
-        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, opts)
-        self.close()
-        raise ssl.SSLError("certificate verify failed, %s" % reason)
-
-    def _evaluate_trust(self, trust_bundle):
-        # We want data in memory, so load it up.
-        if os.path.isfile(trust_bundle):
-            with open(trust_bundle, "rb") as f:
-                trust_bundle = f.read()
-
-        cert_array = None
-        trust = Security.SecTrustRef()
-
-        try:
-            # Get a CFArray that contains the certs we want.
-            cert_array = _cert_array_from_pem(trust_bundle)
-
-            # Ok, now the hard part. We want to get the SecTrustRef that ST has
-            # created for this connection, shove our CAs into it, tell ST to
-            # ignore everything else it knows, and then ask if it can build a
-            # chain. This is a buuuunch of code.
-            result = Security.SSLCopyPeerTrust(self.context, ctypes.byref(trust))
-            _assert_no_error(result)
-            if not trust:
-                raise ssl.SSLError("Failed to copy trust reference")
-
-            result = Security.SecTrustSetAnchorCertificates(trust, cert_array)
-            _assert_no_error(result)
-
-            result = Security.SecTrustSetAnchorCertificatesOnly(trust, True)
-            _assert_no_error(result)
-
-            trust_result = Security.SecTrustResultType()
-            result = Security.SecTrustEvaluate(trust, ctypes.byref(trust_result))
-            _assert_no_error(result)
-        finally:
-            if trust:
-                CoreFoundation.CFRelease(trust)
-
-            if cert_array is not None:
-                CoreFoundation.CFRelease(cert_array)
-
-        return trust_result.value
-
-    def handshake(
-        self,
-        server_hostname,
-        verify,
-        trust_bundle,
-        min_version,
-        max_version,
-        client_cert,
-        client_key,
-        client_key_passphrase,
-        alpn_protocols,
-    ):
-        """
-        Actually performs the TLS handshake. This is run automatically by
-        wrapped socket, and shouldn't be needed in user code.
-        """
-        # First, we do the initial bits of connection setup. We need to create
-        # a context, set its I/O funcs, and set the connection reference.
-        self.context = Security.SSLCreateContext(
-            None, SecurityConst.kSSLClientSide, SecurityConst.kSSLStreamType
-        )
-        result = Security.SSLSetIOFuncs(
-            self.context, _read_callback_pointer, _write_callback_pointer
-        )
-        _assert_no_error(result)
-
-        # Here we need to compute the handle to use. We do this by taking the
-        # id of self modulo 2**31 - 1. If this is already in the dictionary, we
-        # just keep incrementing by one until we find a free space.
-        with _connection_ref_lock:
-            handle = id(self) % 2147483647
-            while handle in _connection_refs:
-                handle = (handle + 1) % 2147483647
-            _connection_refs[handle] = self
-
-        result = Security.SSLSetConnection(self.context, handle)
-        _assert_no_error(result)
-
-        # If we have a server hostname, we should set that too.
-        if server_hostname:
-            if not isinstance(server_hostname, bytes):
-                server_hostname = server_hostname.encode("utf-8")
-
-            result = Security.SSLSetPeerDomainName(
-                self.context, server_hostname, len(server_hostname)
-            )
-            _assert_no_error(result)
-
-        # Setup the ciphers.
-        self._set_ciphers()
-
-        # Setup the ALPN protocols.
-        self._set_alpn_protocols(alpn_protocols)
-
-        # Set the minimum and maximum TLS versions.
-        result = Security.SSLSetProtocolVersionMin(self.context, min_version)
-        _assert_no_error(result)
-
-        result = Security.SSLSetProtocolVersionMax(self.context, max_version)
-        _assert_no_error(result)
-
-        # If there's a trust DB, we need to use it. We do that by telling
-        # SecureTransport to break on server auth. We also do that if we don't
-        # want to validate the certs at all: we just won't actually do any
-        # authing in that case.
-        if not verify or trust_bundle is not None:
-            result = Security.SSLSetSessionOption(
-                self.context, SecurityConst.kSSLSessionOptionBreakOnServerAuth, True
-            )
-            _assert_no_error(result)
-
-        # If there's a client cert, we need to use it.
-        if client_cert:
-            self._keychain, self._keychain_dir = _temporary_keychain()
-            self._client_cert_chain = _load_client_cert_chain(
-                self._keychain, client_cert, client_key
-            )
-            result = Security.SSLSetCertificate(self.context, self._client_cert_chain)
-            _assert_no_error(result)
-
-        while True:
-            with self._raise_on_error():
-                result = Security.SSLHandshake(self.context)
-
-                if result == SecurityConst.errSSLWouldBlock:
-                    raise socket.timeout("handshake timed out")
-                elif result == SecurityConst.errSSLServerAuthCompleted:
-                    self._custom_validate(verify, trust_bundle)
-                    continue
-                else:
-                    _assert_no_error(result)
-                    break
-
-    def fileno(self):
-        return self.socket.fileno()
-
-    # Copy-pasted from Python 3.5 source code
-    def _decref_socketios(self):
-        if self._makefile_refs > 0:
-            self._makefile_refs -= 1
-        if self._closed:
-            self.close()
-
-    def recv(self, bufsiz):
-        buffer = ctypes.create_string_buffer(bufsiz)
-        bytes_read = self.recv_into(buffer, bufsiz)
-        data = buffer[:bytes_read]
-        return data
-
-    def recv_into(self, buffer, nbytes=None):
-        # Read short on EOF.
-        if self._closed:
-            return 0
-
-        if nbytes is None:
-            nbytes = len(buffer)
-
-        buffer = (ctypes.c_char * nbytes).from_buffer(buffer)
-        processed_bytes = ctypes.c_size_t(0)
-
-        with self._raise_on_error():
-            result = Security.SSLRead(
-                self.context, buffer, nbytes, ctypes.byref(processed_bytes)
-            )
-
-        # There are some result codes that we want to treat as "not always
-        # errors". Specifically, those are errSSLWouldBlock,
-        # errSSLClosedGraceful, and errSSLClosedNoNotify.
-        if result == SecurityConst.errSSLWouldBlock:
-            # If we didn't process any bytes, then this was just a time out.
-            # However, we can get errSSLWouldBlock in situations when we *did*
-            # read some data, and in those cases we should just read "short"
-            # and return.
-            if processed_bytes.value == 0:
-                # Timed out, no data read.
-                raise socket.timeout("recv timed out")
-        elif result in (
-            SecurityConst.errSSLClosedGraceful,
-            SecurityConst.errSSLClosedNoNotify,
-        ):
-            # The remote peer has closed this connection. We should do so as
-            # well. Note that we don't actually return here because in
-            # principle this could actually be fired along with return data.
-            # It's unlikely though.
-            self.close()
-        else:
-            _assert_no_error(result)
-
-        # Ok, we read and probably succeeded. We should return whatever data
-        # was actually read.
-        return processed_bytes.value
-
-    def settimeout(self, timeout):
-        self._timeout = timeout
-
-    def gettimeout(self):
-        return self._timeout
-
-    def send(self, data):
-        processed_bytes = ctypes.c_size_t(0)
-
-        with self._raise_on_error():
-            result = Security.SSLWrite(
-                self.context, data, len(data), ctypes.byref(processed_bytes)
-            )
-
-        if result == SecurityConst.errSSLWouldBlock and processed_bytes.value == 0:
-            # Timed out
-            raise socket.timeout("send timed out")
-        else:
-            _assert_no_error(result)
-
-        # We sent, and probably succeeded. Tell them how much we sent.
-        return processed_bytes.value
-
-    def sendall(self, data):
-        total_sent = 0
-        while total_sent < len(data):
-            sent = self.send(data[total_sent : total_sent + SSL_WRITE_BLOCKSIZE])
-            total_sent += sent
-
-    def shutdown(self):
-        with self._raise_on_error():
-            Security.SSLClose(self.context)
-
-    def close(self):
-        # TODO: should I do clean shutdown here? Do I have to?
-        if self._makefile_refs < 1:
-            self._closed = True
-            if self.context:
-                CoreFoundation.CFRelease(self.context)
-                self.context = None
-            if self._client_cert_chain:
-                CoreFoundation.CFRelease(self._client_cert_chain)
-                self._client_cert_chain = None
-            if self._keychain:
-                Security.SecKeychainDelete(self._keychain)
-                CoreFoundation.CFRelease(self._keychain)
-                shutil.rmtree(self._keychain_dir)
-                self._keychain = self._keychain_dir = None
-            return self.socket.close()
-        else:
-            self._makefile_refs -= 1
-
-    def getpeercert(self, binary_form=False):
-        # Urgh, annoying.
-        #
-        # Here's how we do this:
-        #
-        # 1. Call SSLCopyPeerTrust to get hold of the trust object for this
-        #    connection.
-        # 2. Call SecTrustGetCertificateAtIndex for index 0 to get the leaf.
-        # 3. To get the CN, call SecCertificateCopyCommonName and process that
-        #    string so that it's of the appropriate type.
-        # 4. To get the SAN, we need to do something a bit more complex:
-        #    a. Call SecCertificateCopyValues to get the data, requesting
-        #       kSecOIDSubjectAltName.
-        #    b. Mess about with this dictionary to try to get the SANs out.
-        #
-        # This is gross. Really gross. It's going to be a few hundred LoC extra
-        # just to repeat something that SecureTransport can *already do*. So my
-        # operating assumption at this time is that what we want to do is
-        # instead to just flag to urllib3 that it shouldn't do its own hostname
-        # validation when using SecureTransport.
-        if not binary_form:
-            raise ValueError("SecureTransport only supports dumping binary certs")
-        trust = Security.SecTrustRef()
-        certdata = None
-        der_bytes = None
-
-        try:
-            # Grab the trust store.
-            result = Security.SSLCopyPeerTrust(self.context, ctypes.byref(trust))
-            _assert_no_error(result)
-            if not trust:
-                # Probably we haven't done the handshake yet. No biggie.
-                return None
-
-            cert_count = Security.SecTrustGetCertificateCount(trust)
-            if not cert_count:
-                # Also a case that might happen if we haven't handshaked.
-                # Handshook? Handshaken?
-                return None
-
-            leaf = Security.SecTrustGetCertificateAtIndex(trust, 0)
-            assert leaf
-
-            # Ok, now we want the DER bytes.
-            certdata = Security.SecCertificateCopyData(leaf)
-            assert certdata
-
-            data_length = CoreFoundation.CFDataGetLength(certdata)
-            data_buffer = CoreFoundation.CFDataGetBytePtr(certdata)
-            der_bytes = ctypes.string_at(data_buffer, data_length)
-        finally:
-            if certdata:
-                CoreFoundation.CFRelease(certdata)
-            if trust:
-                CoreFoundation.CFRelease(trust)
-
-        return der_bytes
-
-    def version(self):
-        protocol = Security.SSLProtocol()
-        result = Security.SSLGetNegotiatedProtocolVersion(
-            self.context, ctypes.byref(protocol)
-        )
-        _assert_no_error(result)
-        if protocol.value == SecurityConst.kTLSProtocol13:
-            raise ssl.SSLError("SecureTransport does not support TLS 1.3")
-        elif protocol.value == SecurityConst.kTLSProtocol12:
-            return "TLSv1.2"
-        elif protocol.value == SecurityConst.kTLSProtocol11:
-            return "TLSv1.1"
-        elif protocol.value == SecurityConst.kTLSProtocol1:
-            return "TLSv1"
-        elif protocol.value == SecurityConst.kSSLProtocol3:
-            return "SSLv3"
-        elif protocol.value == SecurityConst.kSSLProtocol2:
-            return "SSLv2"
-        else:
-            raise ssl.SSLError("Unknown TLS version: %r" % protocol)
-
-    def _reuse(self):
-        self._makefile_refs += 1
-
-    def _drop(self):
-        if self._makefile_refs < 1:
-            self.close()
-        else:
-            self._makefile_refs -= 1
-
-
-if _fileobject:  # Platform-specific: Python 2
-
-    def makefile(self, mode, bufsize=-1):
-        self._makefile_refs += 1
-        return _fileobject(self, mode, bufsize, close=True)
-
-else:  # Platform-specific: Python 3
-
-    def makefile(self, mode="r", buffering=None, *args, **kwargs):
-        # We disable buffering with SecureTransport because it conflicts with
-        # the buffering that ST does internally (see issue #1153 for more).
-        buffering = 0
-        return backport_makefile(self, mode, buffering, *args, **kwargs)
-
-
-WrappedSocket.makefile = makefile
-
-
-class SecureTransportContext(object):
-    """
-    I am a wrapper class for the SecureTransport library, to translate the
-    interface of the standard library ``SSLContext`` object to calls into
-    SecureTransport.
-    """
-
-    def __init__(self, protocol):
-        self._min_version, self._max_version = _protocol_to_min_max[protocol]
-        self._options = 0
-        self._verify = False
-        self._trust_bundle = None
-        self._client_cert = None
-        self._client_key = None
-        self._client_key_passphrase = None
-        self._alpn_protocols = None
-
-    @property
-    def check_hostname(self):
-        """
-        SecureTransport cannot have its hostname checking disabled. For more,
-        see the comment on getpeercert() in this file.
-        """
-        return True
-
-    @check_hostname.setter
-    def check_hostname(self, value):
-        """
-        SecureTransport cannot have its hostname checking disabled. For more,
-        see the comment on getpeercert() in this file.
-        """
-        pass
-
-    @property
-    def options(self):
-        # TODO: Well, crap.
-        #
-        # So this is the bit of the code that is the most likely to cause us
-        # trouble. Essentially we need to enumerate all of the SSL options that
-        # users might want to use and try to see if we can sensibly translate
-        # them, or whether we should just ignore them.
-        return self._options
-
-    @options.setter
-    def options(self, value):
-        # TODO: Update in line with above.
-        self._options = value
-
-    @property
-    def verify_mode(self):
-        return ssl.CERT_REQUIRED if self._verify else ssl.CERT_NONE
-
-    @verify_mode.setter
-    def verify_mode(self, value):
-        self._verify = True if value == ssl.CERT_REQUIRED else False
-
-    def set_default_verify_paths(self):
-        # So, this has to do something a bit weird. Specifically, what it does
-        # is nothing.
-        #
-        # This means that, if we had previously had load_verify_locations
-        # called, this does not undo that. We need to do that because it turns
-        # out that the rest of the urllib3 code will attempt to load the
-        # default verify paths if it hasn't been told about any paths, even if
-        # the context itself was sometime earlier. We resolve that by just
-        # ignoring it.
-        pass
-
-    def load_default_certs(self):
-        return self.set_default_verify_paths()
-
-    def set_ciphers(self, ciphers):
-        # For now, we just require the default cipher string.
-        if ciphers != util.ssl_.DEFAULT_CIPHERS:
-            raise ValueError("SecureTransport doesn't support custom cipher strings")
-
-    def load_verify_locations(self, cafile=None, capath=None, cadata=None):
-        # OK, we only really support cadata and cafile.
-        if capath is not None:
-            raise ValueError("SecureTransport does not support cert directories")
-
-        # Raise if cafile does not exist.
-        if cafile is not None:
-            with open(cafile):
-                pass
-
-        self._trust_bundle = cafile or cadata
-
-    def load_cert_chain(self, certfile, keyfile=None, password=None):
-        self._client_cert = certfile
-        self._client_key = keyfile
-        self._client_cert_passphrase = password
-
-    def set_alpn_protocols(self, protocols):
-        """
-        Sets the ALPN protocols that will later be set on the context.
-
-        Raises a NotImplementedError if ALPN is not supported.
-        """
-        if not hasattr(Security, "SSLSetALPNProtocols"):
-            raise NotImplementedError(
-                "SecureTransport supports ALPN only in macOS 10.12+"
-            )
-        self._alpn_protocols = [six.ensure_binary(p) for p in protocols]
-
-    def wrap_socket(
-        self,
-        sock,
-        server_side=False,
-        do_handshake_on_connect=True,
-        suppress_ragged_eofs=True,
-        server_hostname=None,
-    ):
-        # So, what do we do here? Firstly, we assert some properties. This is a
-        # stripped down shim, so there is some functionality we don't support.
-        # See PEP 543 for the real deal.
-        assert not server_side
-        assert do_handshake_on_connect
-        assert suppress_ragged_eofs
-
-        # Ok, we're good to go. Now we want to create the wrapped socket object
-        # and store it in the appropriate place.
-        wrapped_socket = WrappedSocket(sock)
-
-        # Now we can handshake
-        wrapped_socket.handshake(
-            server_hostname,
-            self._verify,
-            self._trust_bundle,
-            self._min_version,
-            self._max_version,
-            self._client_cert,
-            self._client_key,
-            self._client_key_passphrase,
-            self._alpn_protocols,
-        )
-        return wrapped_socket