Fix ssl deprecation warnings in Python 3.10
MODIFY
.github/workflows/ci.yml
.github/workflows/ci.yml
@@ -44,7 +44,7 @@ jobs:
os: ubuntu-latest
experimental: false
nox-session: test_brotlipy
- - python-version: 3.10.0-alpha.7
+ - python-version: 3.10.0-beta.2
os: ubuntu-latest
experimental: false
nox-session: test-3.10

MODIFY
dev-requirements.txt
dev-requirements.txt
coverage==5.5
tornado==6.1
PySocks==1.7.1
-pytest==6.2.3
+pytest==6.2.4
pytest-timeout==1.4.2
pytest-freezegun==0.4.2
flaky==3.7.0

MODIFY
src/urllib3/contrib/pyopenssl.py
src/urllib3/contrib/pyopenssl.py
@@ -66,7 +66,6 @@ from socket import socket as socket_cls
from socket import timeout
from .. import util
-from ..util.ssl_ import is_ipaddress
__all__ = ["inject_into_urllib3", "extract_from_urllib3"]
@@ -80,7 +79,8 @@ USE_DEFAULT_SSLCONTEXT_CIPHERS = util.ssl_._is_ge_openssl_v1_1_1(
# Map from urllib3 to PyOpenSSL compatible parameter-values.
_openssl_versions = {
- util.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD,
+ util.ssl_.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD,
+ util.ssl_.PROTOCOL_TLS_CLIENT: OpenSSL.SSL.SSLv23_METHOD,
ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD,
}
@@ -458,7 +458,7 @@ class PyOpenSSLContext:
cnx = OpenSSL.SSL.Connection(self._ctx, sock)
# If server_hostname is an IP, don't use it for SNI, per RFC6066 Section 3
- if server_hostname and not is_ipaddress(server_hostname):
+ if server_hostname and not util.ssl_.is_ipaddress(server_hostname):
if isinstance(server_hostname, str):
server_hostname = server_hostname.encode("utf-8")
cnx.set_tlsext_host_name(server_hostname)

MODIFY
src/urllib3/contrib/securetransport.py
src/urllib3/contrib/securetransport.py
@@ -111,7 +111,11 @@ SSL_WRITE_BLOCKSIZE = 16384
# 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)
+ util.ssl_.PROTOCOL_TLS: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12),
+ util.ssl_.PROTOCOL_TLS_CLIENT: (
+ SecurityConst.kTLSProtocol1,
+ SecurityConst.kTLSProtocol12,
+ ),
}
if hasattr(ssl, "PROTOCOL_SSLv2"):

MODIFY
src/urllib3/util/__init__.py
src/urllib3/util/__init__.py
@@ -8,7 +8,6 @@ from .ssl_ import (
HAS_SNI,
IS_PYOPENSSL,
IS_SECURETRANSPORT,
- PROTOCOL_TLS,
SSLContext,
assert_fingerprint,
resolve_cert_reqs,
@@ -24,7 +23,6 @@ __all__ = (
"IS_PYOPENSSL",
"IS_SECURETRANSPORT",
"SSLContext",
- "PROTOCOL_TLS",
"ALPN_PROTOCOLS",
"Retry",
"Timeout",

MODIFY
src/urllib3/util/ssl_.py
src/urllib3/util/ssl_.py
@@ -50,6 +50,7 @@ try: # Do we have ssl at all?
OPENSSL_VERSION,
OPENSSL_VERSION_NUMBER,
PROTOCOL_TLS,
+ PROTOCOL_TLS_CLIENT,
OP_NO_SSLv2,
OP_NO_SSLv3,
SSLContext,
@@ -66,6 +67,7 @@ except ImportError:
OP_NO_SSLv2 = 0x1000000 # type: ignore
OP_NO_SSLv3 = 0x2000000 # type: ignore
PROTOCOL_SSLv23 = PROTOCOL_TLS = 2
+ PROTOCOL_TLS_CLIENT = 16
_PCTRTT = Tuple[Tuple[str, str], ...]
@@ -223,7 +225,13 @@ def create_urllib3_context(
"""
if SSLContext is None:
raise TypeError("Can't create an SSLContext object without an ssl module")
- context = SSLContext(ssl_version or PROTOCOL_TLS)
+
+ # PROTOCOL_TLS is deprecated in Python 3.10 so we pass PROTOCOL_TLS_CLIENT instead.
+ if ssl_version in (None, PROTOCOL_TLS):
+ ssl_version = PROTOCOL_TLS_CLIENT
+
+ context = SSLContext(ssl_version)
+
# Unless we're given ciphers defer to either system ciphers in
# the case of OpenSSL 1.1.1+ or use our own secure default ciphers.
if ciphers is not None or not USE_DEFAULT_SSLCONTEXT_CIPHERS:
@@ -260,9 +268,16 @@ def create_urllib3_context(
) is not None:
context.post_handshake_auth = True
+ # The order of the below lines setting verify_mode and check_hostname
+ # matter due to safe-guards SSLContext has to prevent an SSLContext with
+ # check_hostname=True, verify_mode=NONE/OPTIONAL.
+ if cert_reqs == ssl.CERT_REQUIRED:
context.verify_mode = cert_reqs
- # We ask for verification here but it may be disabled in HTTPSConnection.connect
- context.check_hostname = cert_reqs == ssl.CERT_REQUIRED
+ context.check_hostname = True
+ else:
+ context.check_hostname = False
+ context.verify_mode = cert_reqs
+
if hasattr(context, "hostname_checks_common_name"):
context.hostname_checks_common_name = False

MODIFY
test/with_dummyserver/test_https.py
test/with_dummyserver/test_https.py
@@ -678,12 +678,13 @@ class TestHTTPS(HTTPSDummyServerTestCase):
else:
assert w == []
- def test_no_tls_version_deprecation_with_ssl_version(self):
+ @pytest.mark.parametrize("ssl_version", [ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_CLIENT])
+ def test_no_tls_version_deprecation_with_ssl_version(self, ssl_version):
if self.tls_protocol_name is None:
pytest.skip("Skipping base test class")
with HTTPSConnectionPool(
- self.host, self.port, ca_certs=DEFAULT_CA, ssl_version=util.PROTOCOL_TLS
+ self.host, self.port, ca_certs=DEFAULT_CA, ssl_version=ssl_version
) as https_pool:
conn = https_pool._get_conn()
try:

Fix ssl deprecation warnings in Python 3.10