Don't emit SNIMissingWarning when using IP address
MODIFY
test/test_ssl.py
test/test_ssl.py
+import mock
import pytest
from six import b
from urllib3.util import ssl_
+from urllib3.exceptions import SNIMissingWarning
@pytest.mark.parametrize('addr', [
@@ -20,3 +22,45 @@ def test_is_ipaddress_true(addr):
])
def test_is_ipaddress_false(addr):
assert not ssl_.is_ipaddress(addr)
+
+
+@pytest.mark.parametrize(
+ ['has_sni', 'server_hostname', 'uses_sni'],
+ [(True, '127.0.0.1', False),
+ (False, 'www.python.org', False),
+ (False, '0.0.0.0', False),
+ (True, 'www.google.com', True)]
+)
+def test_context_sni_with_ip_address(monkeypatch, has_sni, server_hostname, uses_sni):
+ monkeypatch.setattr(ssl_, 'HAS_SNI', has_sni)
+
+ sock = mock.Mock()
+ context = mock.Mock()
+
+ ssl_.ssl_wrap_socket(sock, server_hostname=server_hostname, ssl_context=context)
+
+ if uses_sni:
+ context.wrap_socket.assert_called_with(sock, server_hostname=server_hostname)
+ else:
+ context.wrap_socket.assert_called_with(sock)
+
+
+@pytest.mark.parametrize(
+ ['has_sni', 'server_hostname', 'should_warn'],
+ [(True, 'www.google.com', False),
+ (True, '127.0.0.1', False),
+ (False, '127.0.0.1', False),
+ (False, 'www.google.com', True)]
+)
+def test_sni_missing_warning_with_ip_addresses(monkeypatch, has_sni, server_hostname, should_warn):
+ monkeypatch.setattr(ssl_, 'HAS_SNI', has_sni)
+
+ sock = mock.Mock()
+ context = mock.Mock()
+
+ with pytest.warns(None) as record:
+ ssl_.ssl_wrap_socket(sock, server_hostname=server_hostname, ssl_context=context)
+
+ assert len(record) == int(should_warn)
+ if should_warn:
+ assert isinstance(record[0].message, SNIMissingWarning)

MODIFY
urllib3/util/ssl_.py
urllib3/util/ssl_.py
@@ -327,13 +327,19 @@ def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
if certfile:
context.load_cert_chain(certfile, keyfile)
- if HAS_SNI:
+
+ if server_hostname is not None:
+ is_ip = is_ipaddress(server_hostname)
+ else:
+ is_ip = False
+
# If we detect server_hostname is an IP address then the SNI
# extension should not be used according to RFC3546 Section 3.1
- if server_hostname is not None and not is_ipaddress(server_hostname):
+ # We shouldn't warn the user if SNI isn't available but we would
+ # not be using SNI anyways due to IP address for server_hostname.
+ if not is_ip:
+ if HAS_SNI:
return context.wrap_socket(sock, server_hostname=server_hostname)
- else:
- return context.wrap_socket(sock)
warnings.warn(
'An HTTPS request has been made, but the SNI (Server Name '
@@ -345,6 +351,7 @@ def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
'#ssl-warnings',
SNIMissingWarning
)
+
return context.wrap_socket(sock)

Don't emit SNIMissingWarning when using IP address