From 4d510742c8328a423d67ddec37bae957d972a63b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Boros?= Date: Sat, 7 Sep 2019 09:46:38 +0200 Subject: [PATCH 1/6] Add helper to get the hostname for ssl matching --- rethinkdb/helpers.py | 9 +++++++++ tests/test_helpers.py | 23 ++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/rethinkdb/helpers.py b/rethinkdb/helpers.py index 4a161286..c9def7bc 100644 --- a/rethinkdb/helpers.py +++ b/rethinkdb/helpers.py @@ -1,10 +1,19 @@ +import re import six + def decode_utf8(string, encoding='utf-8'): if hasattr(string, 'decode'): return string.decode(encoding) return string + def chain_to_bytes(*strings): return b''.join([six.b(string) if isinstance(string, six.string_types) else string for string in strings]) + + +def get_hostname_for_ssl_match(hostname): + match = re.match(r'^((?P[^\.]+)\.)?(?P[^\./]+\.[^/]+)/?.*$', hostname) + domain = match.group('domain') + return '*.{domain}'.format(domain=domain) if match.group('subdomain') else domain \ No newline at end of file diff --git a/tests/test_helpers.py b/tests/test_helpers.py index ca868de6..88a093c4 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -1,6 +1,6 @@ import pytest from mock import Mock -from rethinkdb.helpers import decode_utf8, chain_to_bytes +from rethinkdb.helpers import decode_utf8, chain_to_bytes, get_hostname_for_ssl_match @pytest.mark.unit class TestDecodeUTF8Helper(object): @@ -42,3 +42,24 @@ def test_mixed_chaining(self): result = chain_to_bytes('iron', ' ', b'man') assert result == expected_string + + +@pytest.mark.unit +class TestSSLMatchHostHostnameHelper(object): + def test_subdomain_replaced_to_star(self): + expected_string = '*.example.com' + + result = get_hostname_for_ssl_match('test.example.com') + + assert result == expected_string + + def test_no_subdomain_to_replace(self): + expected_string = 'example.com' + + result = get_hostname_for_ssl_match('example.com') + + assert result == expected_string + + def test_no_match(self): + with pytest.raises(AttributeError) as exc: + get_hostname_for_ssl_match('') \ No newline at end of file From 0c7608706a427fceb8fec30d27af8f716fc75709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Boros?= Date: Sat, 7 Sep 2019 09:46:55 +0200 Subject: [PATCH 2/6] Extend net and net_gevent to use the new helper --- rethinkdb/gevent_net/net_gevent.py | 3 ++- rethinkdb/net.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/rethinkdb/gevent_net/net_gevent.py b/rethinkdb/gevent_net/net_gevent.py index a151ba5c..52e87727 100644 --- a/rethinkdb/gevent_net/net_gevent.py +++ b/rethinkdb/gevent_net/net_gevent.py @@ -26,6 +26,7 @@ from rethinkdb import net, ql2_pb2 from rethinkdb.errors import ReqlAuthError, ReqlCursorEmpty, ReqlDriverError, ReqlTimeoutError, RqlDriverError, \ RqlTimeoutError +from rethinkdb.helpers import get_hostname_for_ssl_match from rethinkdb.logger import default_logger __all__ = ['Connection'] @@ -103,7 +104,7 @@ def __init__(self, parent): self._socket.close() raise ReqlDriverError("SSL handshake failed (see server log for more information): %s" % str(exc)) try: - ssl.match_hostname(self._socket.getpeercert(), hostname=self.host) + ssl.match_hostname(self._socket.getpeercert(), hostname=get_hostname_for_ssl_match(self.host)) except ssl.CertificateError: self._socket.close() raise diff --git a/rethinkdb/net.py b/rethinkdb/net.py index 5a4c8ddc..e314ac23 100644 --- a/rethinkdb/net.py +++ b/rethinkdb/net.py @@ -44,6 +44,7 @@ ReqlTimeoutError, ReqlUserError) from rethinkdb.handshake import HandshakeV1_0 +from rethinkdb.helpers import get_hostname_for_ssl_match from rethinkdb.logger import default_logger __all__ = ['Connection', 'Cursor', 'DEFAULT_PORT', 'DefaultConnection', 'make_connection'] @@ -352,7 +353,8 @@ def __init__(self, parent, timeout): "SSL handshake failed (see server log for more information): %s" % str(err)) try: - match_hostname(self._socket.getpeercert(), hostname=self.host) + + match_hostname(self._socket.getpeercert(), hostname=get_hostname_for_ssl_match(self.host)) except CertificateError: self._socket.close() raise From 6e14dc76e97fa3b1aab0137b35fb499e54dc4603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Boros?= Date: Sat, 7 Sep 2019 09:52:21 +0200 Subject: [PATCH 3/6] New line at the end of helpers --- rethinkdb/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rethinkdb/helpers.py b/rethinkdb/helpers.py index c9def7bc..e70264c5 100644 --- a/rethinkdb/helpers.py +++ b/rethinkdb/helpers.py @@ -16,4 +16,4 @@ def chain_to_bytes(*strings): def get_hostname_for_ssl_match(hostname): match = re.match(r'^((?P[^\.]+)\.)?(?P[^\./]+\.[^/]+)/?.*$', hostname) domain = match.group('domain') - return '*.{domain}'.format(domain=domain) if match.group('subdomain') else domain \ No newline at end of file + return '*.{domain}'.format(domain=domain) if match.group('subdomain') else domain From af04a2cdbace8326adc843f8d81c457e10557363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Boros?= Date: Sat, 7 Sep 2019 09:58:21 +0200 Subject: [PATCH 4/6] Fix codacy issues --- rethinkdb/gevent_net/net_gevent.py | 5 ++++- rethinkdb/net.py | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/rethinkdb/gevent_net/net_gevent.py b/rethinkdb/gevent_net/net_gevent.py index 52e87727..2969922e 100644 --- a/rethinkdb/gevent_net/net_gevent.py +++ b/rethinkdb/gevent_net/net_gevent.py @@ -104,7 +104,10 @@ def __init__(self, parent): self._socket.close() raise ReqlDriverError("SSL handshake failed (see server log for more information): %s" % str(exc)) try: - ssl.match_hostname(self._socket.getpeercert(), hostname=get_hostname_for_ssl_match(self.host)) + ssl.match_hostname( + self._socket.getpeercert(), + hostname=get_hostname_for_ssl_match(self.host) + ) except ssl.CertificateError: self._socket.close() raise diff --git a/rethinkdb/net.py b/rethinkdb/net.py index e314ac23..155e038d 100644 --- a/rethinkdb/net.py +++ b/rethinkdb/net.py @@ -353,8 +353,10 @@ def __init__(self, parent, timeout): "SSL handshake failed (see server log for more information): %s" % str(err)) try: - - match_hostname(self._socket.getpeercert(), hostname=get_hostname_for_ssl_match(self.host)) + ssl.match_hostname( + self._socket.getpeercert(), + hostname=get_hostname_for_ssl_match(self.host) + ) except CertificateError: self._socket.close() raise From aa62ff26614a2a9a0788c0ad64ce8420a77d1d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Boros?= Date: Fri, 13 Sep 2019 10:18:46 +0200 Subject: [PATCH 5/6] Removing the regexp. It can not handle localhost and special TLDs --- rethinkdb/helpers.py | 10 +++++++--- tests/test_helpers.py | 18 ++++++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/rethinkdb/helpers.py b/rethinkdb/helpers.py index e70264c5..bbd0e82a 100644 --- a/rethinkdb/helpers.py +++ b/rethinkdb/helpers.py @@ -14,6 +14,10 @@ def chain_to_bytes(*strings): def get_hostname_for_ssl_match(hostname): - match = re.match(r'^((?P[^\.]+)\.)?(?P[^\./]+\.[^/]+)/?.*$', hostname) - domain = match.group('domain') - return '*.{domain}'.format(domain=domain) if match.group('subdomain') else domain + parts = hostname.split('.') + + if len(parts) < 3: + return hostname + + parts[0] = '*' + return '.'.join(parts) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 88a093c4..68e5fefb 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -53,13 +53,23 @@ def test_subdomain_replaced_to_star(self): assert result == expected_string + def test_subdomain_replaced_to_star_special_tld(self): + expected_string = '*.example.co.uk' + + result = get_hostname_for_ssl_match('test.example.co.uk') + + assert result == expected_string + def test_no_subdomain_to_replace(self): expected_string = 'example.com' - result = get_hostname_for_ssl_match('example.com') + result = get_hostname_for_ssl_match(expected_string) assert result == expected_string - def test_no_match(self): - with pytest.raises(AttributeError) as exc: - get_hostname_for_ssl_match('') \ No newline at end of file + def test_no_tld(self): + expected_string = 'localhost' + + result = get_hostname_for_ssl_match(expected_string) + + assert result == expected_string From b5dfb9504483b5e26ca6da03c97a948ed6ecea54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Boros?= Date: Fri, 13 Sep 2019 10:20:17 +0200 Subject: [PATCH 6/6] Remove unused imports --- rethinkdb/helpers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/rethinkdb/helpers.py b/rethinkdb/helpers.py index bbd0e82a..46152e49 100644 --- a/rethinkdb/helpers.py +++ b/rethinkdb/helpers.py @@ -1,4 +1,3 @@ -import re import six