From a610cf12209326fba5e6660c1644cbff55b7c07d Mon Sep 17 00:00:00 2001 From: jake-jake-jake Date: Thu, 27 Oct 2016 11:45:43 -0400 Subject: [PATCH] Connection warnings (#1341) * Add warning.warn on MD5 and SHA1 hashes * Add SHA256 only suggestion to docs * PyFlakes fix * changelog * Added name to list * Reorder fingerprint param info * Add tests for deprecation warning --- CHANGES.rst | 3 ++- CONTRIBUTORS.txt | 1 + aiohttp/connector.py | 5 +++++ docs/client_reference.rst | 9 +++++---- tests/test_client_functional.py | 11 +++++++++-- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index cfe718f2ac8..12909101498 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -66,7 +66,8 @@ CHANGES - Document deployment without `Gunicorn` #1120 -- +- Add deprecation warning for MD5 and SHA1 digests when used for fingerprint + of site certs in TCPConnector. #1186 1.0.5 (2016-10-11) ------------------ diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 5c8c7750ff4..6b8042ccf26 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -65,6 +65,7 @@ Igor Pavlov Ingmar Steen Jacob Champion Jaesung Lee +Jake Davis Jakub Wilk Jashandeep Sohi Jeroen van der Heijden diff --git a/aiohttp/connector.py b/aiohttp/connector.py index 783e5a309c1..f24354f2969 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -441,6 +441,11 @@ def __init__(self, *, verify_ssl=True, fingerprint=None, hashfunc = HASHFUNC_BY_DIGESTLEN.get(digestlen) if not hashfunc: raise ValueError('fingerprint has invalid length') + elif hashfunc is md5 or hashfunc is sha1: + warnings.simplefilter('always') + warnings.warn('md5 and sha1 are insecure and deprecated. ' + 'Use sha256.', + DeprecationWarning, stacklevel=2) self._hashfunc = hashfunc self._fingerprint = fingerprint diff --git a/docs/client_reference.rst b/docs/client_reference.rst index a84ecb3a27a..6f24f0ea987 100644 --- a/docs/client_reference.rst +++ b/docs/client_reference.rst @@ -886,12 +886,13 @@ TCPConnector *HTTPS* requests (enabled by default). May be disabled to skip validation for sites with invalid certificates. - :param bytes fingerprint: Pass the binary MD5, SHA1, or SHA256 - digest of the expected certificate in DER format to verify - that the certificate the server presents matches. Useful - for `certificate pinning + :param bytes fingerprint: Pass the SHA256 digest of the expected + certificate in DER format to verify that the certificate the + server presents matches. Useful for `certificate pinning `_. + Note: use of MD5 or SHA1 digests is insecure and deprecated. + .. versionadded:: 0.16 :param bool use_dns_cache: use internal cache for DNS lookups, ``True`` diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py index 5061c5b761d..5750c0978cf 100644 --- a/tests/test_client_functional.py +++ b/tests/test_client_functional.py @@ -266,8 +266,15 @@ def test_tcp_connector_fingerprint_ok(test_server, test_client, def handler(request): return web.HTTPOk(text='Test message') - connector = aiohttp.TCPConnector(loop=loop, verify_ssl=False, - fingerprint=fingerprint) + # Test for deprecation warning on md5 and sha1 len digests. + if len(fingerprint) == 16 or len(fingerprint) == 20: + with pytest.warns(DeprecationWarning) as cm: + connector = aiohttp.TCPConnector(loop=loop, verify_ssl=False, + fingerprint=fingerprint) + assert 'Use sha256.' in str(cm[0].message) + else: + connector = aiohttp.TCPConnector(loop=loop, verify_ssl=False, + fingerprint=fingerprint) app = web.Application(loop=loop) app.router.add_route('GET', '/', handler) server = yield from test_server(app, ssl=ssl_ctx)