summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorhodbn <hodbn@users.noreply.github.com>2020-08-23 17:19:37 -0700
committerGitHub <noreply@github.com>2020-08-23 19:19:37 -0500
commit16dc22b419e3958e0457bcfbc97d8a160d95208a (patch)
tree1d9469cdd38a764e8420db5eb10dd5766cf71a3e /test
parent0210ddb33c28249425ddeb7704c357d5b07c46f6 (diff)
downloadurllib3-16dc22b419e3958e0457bcfbc97d8a160d95208a.tar.gz
Don't raise SNI warning on SecureTransport with server_hostname=None
Diffstat (limited to 'test')
-rw-r--r--test/contrib/test_pyopenssl.py1
-rw-r--r--test/contrib/test_securetransport.py2
-rw-r--r--test/test_util.py210
3 files changed, 120 insertions, 93 deletions
diff --git a/test/contrib/test_pyopenssl.py b/test/contrib/test_pyopenssl.py
index 25b8deb1..7d1af312 100644
--- a/test/contrib/test_pyopenssl.py
+++ b/test/contrib/test_pyopenssl.py
@@ -30,6 +30,7 @@ def teardown_module():
pass
+from ..test_util import TestUtilSSL # noqa: E402, F401
from ..with_dummyserver.test_https import ( # noqa: E402, F401
TestHTTPS,
TestHTTPS_TLSv1,
diff --git a/test/contrib/test_securetransport.py b/test/contrib/test_securetransport.py
index 5fb8fbcf..41519436 100644
--- a/test/contrib/test_securetransport.py
+++ b/test/contrib/test_securetransport.py
@@ -29,6 +29,8 @@ def teardown_module():
pass
+from ..test_util import TestUtilSSL # noqa: E402, F401
+
# SecureTransport does not support TLSv1.3
# https://github.com/urllib3/urllib3/issues/1674
from ..with_dummyserver.test_https import ( # noqa: E402, F401
diff --git a/test/test_util.py b/test/test_util.py
index 838c7515..1630ece7 100644
--- a/test/test_util.py
+++ b/test/test_util.py
@@ -10,7 +10,7 @@ from itertools import chain
from mock import patch, Mock
import pytest
-from urllib3 import add_stderr_logger, disable_warnings
+from urllib3 import add_stderr_logger, disable_warnings, util
from urllib3.util.request import make_headers, rewind_body, _FAILEDTELL
from urllib3.util.response import assert_header_parsing
from urllib3.util.timeout import Timeout
@@ -29,7 +29,7 @@ from urllib3.exceptions import (
UnrewindableBodyError,
)
from urllib3.util.connection import allowed_gai_family, _has_ipv6
-from urllib3.util import is_fp_closed, ssl_
+from urllib3.util import is_fp_closed
from urllib3.packages import six
from . import clear_warnings
@@ -666,31 +666,6 @@ class TestUtil(object):
current_time.return_value = TIMEOUT_EPOCH + 37
assert timeout.get_connect_duration() == 37
- @pytest.mark.parametrize(
- "candidate, requirements",
- [
- (None, ssl.CERT_REQUIRED),
- (ssl.CERT_NONE, ssl.CERT_NONE),
- (ssl.CERT_REQUIRED, ssl.CERT_REQUIRED),
- ("REQUIRED", ssl.CERT_REQUIRED),
- ("CERT_REQUIRED", ssl.CERT_REQUIRED),
- ],
- )
- def test_resolve_cert_reqs(self, candidate, requirements):
- assert resolve_cert_reqs(candidate) == requirements
-
- @pytest.mark.parametrize(
- "candidate, version",
- [
- (ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1),
- ("PROTOCOL_TLSv1", ssl.PROTOCOL_TLSv1),
- ("TLSv1", ssl.PROTOCOL_TLSv1),
- (ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23),
- ],
- )
- def test_resolve_ssl_version(self, candidate, version):
- assert resolve_ssl_version(candidate) == version
-
def test_is_fp_closed_object_supports_closed(self):
class ClosedFile(object):
@property
@@ -722,72 +697,6 @@ class TestUtil(object):
with pytest.raises(ValueError):
is_fp_closed(NotReallyAFile())
- def test_ssl_wrap_socket_loads_the_cert_chain(self):
- socket = object()
- mock_context = Mock()
- ssl_wrap_socket(
- ssl_context=mock_context, sock=socket, certfile="/path/to/certfile"
- )
-
- mock_context.load_cert_chain.assert_called_once_with("/path/to/certfile", None)
-
- @patch("urllib3.util.ssl_.create_urllib3_context")
- def test_ssl_wrap_socket_creates_new_context(self, create_urllib3_context):
- socket = object()
- ssl_wrap_socket(sock=socket, cert_reqs="CERT_REQUIRED")
-
- create_urllib3_context.assert_called_once_with(
- None, "CERT_REQUIRED", ciphers=None
- )
-
- def test_ssl_wrap_socket_loads_verify_locations(self):
- socket = object()
- mock_context = Mock()
- ssl_wrap_socket(ssl_context=mock_context, ca_certs="/path/to/pem", sock=socket)
- mock_context.load_verify_locations.assert_called_once_with(
- "/path/to/pem", None, None
- )
-
- def test_ssl_wrap_socket_loads_certificate_directories(self):
- socket = object()
- mock_context = Mock()
- ssl_wrap_socket(
- ssl_context=mock_context, ca_cert_dir="/path/to/pems", sock=socket
- )
- mock_context.load_verify_locations.assert_called_once_with(
- None, "/path/to/pems", None
- )
-
- def test_ssl_wrap_socket_loads_certificate_data(self):
- socket = object()
- mock_context = Mock()
- ssl_wrap_socket(
- ssl_context=mock_context, ca_cert_data="TOTALLY PEM DATA", sock=socket
- )
- mock_context.load_verify_locations.assert_called_once_with(
- None, None, "TOTALLY PEM DATA"
- )
-
- def test_ssl_wrap_socket_with_no_sni_warns(self):
- socket = object()
- mock_context = Mock()
- # Ugly preservation of original value
- HAS_SNI = ssl_.HAS_SNI
- ssl_.HAS_SNI = False
- try:
- with patch("warnings.warn") as warn:
- ssl_wrap_socket(
- ssl_context=mock_context,
- sock=socket,
- server_hostname="www.google.com",
- )
- mock_context.wrap_socket.assert_called_once_with(socket)
- assert warn.call_count >= 1
- warnings = [call[0][1] for call in warn.call_args_list]
- assert SNIMissingWarning in warnings
- finally:
- ssl_.HAS_SNI = HAS_SNI
-
def test_const_compare_digest_fallback(self):
target = hashlib.sha256(b"abcdef").digest()
assert _const_compare_digest_backport(target, target)
@@ -838,3 +747,118 @@ class TestUtil(object):
def test_assert_header_parsing_throws_typeerror_with_non_headers(self, headers):
with pytest.raises(TypeError):
assert_header_parsing(headers)
+
+
+class TestUtilSSL(object):
+ """Test utils that use an SSL backend."""
+
+ @pytest.mark.parametrize(
+ "candidate, requirements",
+ [
+ (None, ssl.CERT_REQUIRED),
+ (ssl.CERT_NONE, ssl.CERT_NONE),
+ (ssl.CERT_REQUIRED, ssl.CERT_REQUIRED),
+ ("REQUIRED", ssl.CERT_REQUIRED),
+ ("CERT_REQUIRED", ssl.CERT_REQUIRED),
+ ],
+ )
+ def test_resolve_cert_reqs(self, candidate, requirements):
+ assert resolve_cert_reqs(candidate) == requirements
+
+ @pytest.mark.parametrize(
+ "candidate, version",
+ [
+ (ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1),
+ ("PROTOCOL_TLSv1", ssl.PROTOCOL_TLSv1),
+ ("TLSv1", ssl.PROTOCOL_TLSv1),
+ (ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23),
+ ],
+ )
+ def test_resolve_ssl_version(self, candidate, version):
+ assert resolve_ssl_version(candidate) == version
+
+ def test_ssl_wrap_socket_loads_the_cert_chain(self):
+ socket = object()
+ mock_context = Mock()
+ ssl_wrap_socket(
+ ssl_context=mock_context, sock=socket, certfile="/path/to/certfile"
+ )
+
+ mock_context.load_cert_chain.assert_called_once_with("/path/to/certfile", None)
+
+ @patch("urllib3.util.ssl_.create_urllib3_context")
+ def test_ssl_wrap_socket_creates_new_context(self, create_urllib3_context):
+ socket = object()
+ ssl_wrap_socket(sock=socket, cert_reqs="CERT_REQUIRED")
+
+ create_urllib3_context.assert_called_once_with(
+ None, "CERT_REQUIRED", ciphers=None
+ )
+
+ def test_ssl_wrap_socket_loads_verify_locations(self):
+ socket = object()
+ mock_context = Mock()
+ ssl_wrap_socket(ssl_context=mock_context, ca_certs="/path/to/pem", sock=socket)
+ mock_context.load_verify_locations.assert_called_once_with(
+ "/path/to/pem", None, None
+ )
+
+ def test_ssl_wrap_socket_loads_certificate_directories(self):
+ socket = object()
+ mock_context = Mock()
+ ssl_wrap_socket(
+ ssl_context=mock_context, ca_cert_dir="/path/to/pems", sock=socket
+ )
+ mock_context.load_verify_locations.assert_called_once_with(
+ None, "/path/to/pems", None
+ )
+
+ def test_ssl_wrap_socket_loads_certificate_data(self):
+ socket = object()
+ mock_context = Mock()
+ ssl_wrap_socket(
+ ssl_context=mock_context, ca_cert_data="TOTALLY PEM DATA", sock=socket
+ )
+ mock_context.load_verify_locations.assert_called_once_with(
+ None, None, "TOTALLY PEM DATA"
+ )
+
+ def _wrap_socket_and_mock_warn(self, sock, server_hostname):
+ mock_context = Mock()
+ with patch("warnings.warn") as warn:
+ ssl_wrap_socket(
+ ssl_context=mock_context, sock=sock, server_hostname=server_hostname,
+ )
+ return mock_context, warn
+
+ def test_ssl_wrap_socket_sni_hostname_use_or_warn(self):
+ """Test that either an SNI hostname is used or a warning is made."""
+ sock = object()
+ context, warn = self._wrap_socket_and_mock_warn(sock, "www.google.com")
+ if util.HAS_SNI:
+ warn.assert_not_called()
+ context.wrap_socket.assert_called_once_with(
+ sock, server_hostname="www.google.com"
+ )
+ else:
+ assert warn.call_count >= 1
+ warnings = [call[0][1] for call in warn.call_args_list]
+ assert SNIMissingWarning in warnings
+ context.wrap_socket.assert_called_once_with(sock)
+
+ def test_ssl_wrap_socket_sni_ip_address_no_warn(self):
+ """Test that a warning is not made if server_hostname is an IP address."""
+ sock = object()
+ context, warn = self._wrap_socket_and_mock_warn(sock, "8.8.8.8")
+ if util.IS_SECURETRANSPORT:
+ context.wrap_socket.assert_called_once_with(sock, server_hostname="8.8.8.8")
+ else:
+ context.wrap_socket.assert_called_once_with(sock)
+ warn.assert_not_called()
+
+ def test_ssl_wrap_socket_sni_none_no_warn(self):
+ """Test that a warning is not made if server_hostname is not given."""
+ sock = object()
+ context, warn = self._wrap_socket_and_mock_warn(sock, None)
+ context.wrap_socket.assert_called_once_with(sock)
+ warn.assert_not_called()