diff --git a/adafruit_connection_manager.py b/adafruit_connection_manager.py index cc70f3f..7c4d896 100644 --- a/adafruit_connection_manager.py +++ b/adafruit_connection_manager.py @@ -29,6 +29,8 @@ import errno import sys +WIZNET5K_SSL_SUPPORT_VERSION = (9, 1) + # typing @@ -128,8 +130,23 @@ def get_radio_socketpool(radio): elif class_name == "WIZNET5K": import adafruit_wiznet5k.adafruit_wiznet5k_socket as pool # pylint: disable=import-outside-toplevel - # Note: SSL/TLS connections are not supported by the Wiznet5k library at this time - ssl_context = create_fake_ssl_context(pool, radio) + # Note: At this time, SSL/TLS connections are not supported by older + # versions of the Wiznet5k library or on boards withouut the ssl module + # see https://docs.circuitpython.org/en/latest/shared-bindings/support_matrix.html + ssl_context = None + cp_version = sys.implementation[1] + if pool.SOCK_STREAM == 1 and cp_version >= WIZNET5K_SSL_SUPPORT_VERSION: + try: + import ssl # pylint: disable=import-outside-toplevel + + ssl_context = ssl.create_default_context() + pool.set_interface(radio) + except ImportError: + # if SSL not on board, default to fake_ssl_context + pass + + if ssl_context is None: + ssl_context = create_fake_ssl_context(pool, radio) else: raise AttributeError(f"Unsupported radio class: {class_name}") diff --git a/tests/conftest.py b/tests/conftest.py index 7947b1c..08d3914 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -49,6 +49,19 @@ def adafruit_wiznet5k_socket_module(): del sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socket"] +@pytest.fixture +def adafruit_wiznet5k_with_ssl_socket_module(): + wiznet5k_module = type(sys)("adafruit_wiznet5k") + wiznet5k_socket_module = type(sys)("adafruit_wiznet5k_socket") + wiznet5k_socket_module.set_interface = set_interface + wiznet5k_socket_module.SOCK_STREAM = 1 + sys.modules["adafruit_wiznet5k"] = wiznet5k_module + sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socket"] = wiznet5k_socket_module + yield + del sys.modules["adafruit_wiznet5k"] + del sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socket"] + + @pytest.fixture(autouse=True) def reset_connection_manager(monkeypatch): monkeypatch.setattr( diff --git a/tests/ssl_context_test.py b/tests/ssl_context_test.py index abc857f..de6d4f1 100644 --- a/tests/ssl_context_test.py +++ b/tests/ssl_context_test.py @@ -5,11 +5,13 @@ """ SLL Context Tests """ import ssl +from unittest import mock import mocket import pytest import adafruit_connection_manager +from adafruit_connection_manager import WIZNET5K_SSL_SUPPORT_VERSION def test_connect_esp32spi_https( # pylint: disable=unused-argument @@ -50,7 +52,9 @@ def test_connect_wiznet5k_https_not_supported( # pylint: disable=unused-argumen ): mock_pool = mocket.MocketPool() radio = mocket.MockRadio.WIZNET5K() - ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio) + old_version = (WIZNET5K_SSL_SUPPORT_VERSION[0] - 1, 0, 0) + with mock.patch("sys.implementation", (None, old_version)): + ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio) connection_manager = adafruit_connection_manager.ConnectionManager(mock_pool) # verify a HTTPS call for a board without built in WiFi and SSL support errors @@ -59,3 +63,12 @@ def test_connect_wiznet5k_https_not_supported( # pylint: disable=unused-argumen mocket.MOCK_HOST_1, 443, "https:", ssl_context=ssl_context ) assert "This radio does not support TLS/HTTPS" in str(context) + + +def test_connect_wiznet5k_https_supported( # pylint: disable=unused-argument + adafruit_wiznet5k_with_ssl_socket_module, +): + radio = mocket.MockRadio.WIZNET5K() + with mock.patch("sys.implementation", (None, WIZNET5K_SSL_SUPPORT_VERSION)): + ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio) + assert isinstance(ssl_context, ssl.SSLContext)