Skip to content

Commit

Permalink
Merge pull request #140 from rethinkdb/feature/wildcard-certs-hostname
Browse files Browse the repository at this point in the history
Feature/wildcard certs hostname
  • Loading branch information
gabor-boros authored Sep 13, 2019
2 parents 9d85d0b + b5dfb95 commit 95e96de
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 3 deletions.
6 changes: 5 additions & 1 deletion rethinkdb/gevent_net/net_gevent.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand Down Expand Up @@ -103,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=self.host)
ssl.match_hostname(
self._socket.getpeercert(),
hostname=get_hostname_for_ssl_match(self.host)
)
except ssl.CertificateError:
self._socket.close()
raise
Expand Down
12 changes: 12 additions & 0 deletions rethinkdb/helpers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
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):
parts = hostname.split('.')

if len(parts) < 3:
return hostname

parts[0] = '*'
return '.'.join(parts)
6 changes: 5 additions & 1 deletion rethinkdb/net.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand Down Expand Up @@ -352,7 +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=self.host)
ssl.match_hostname(
self._socket.getpeercert(),
hostname=get_hostname_for_ssl_match(self.host)
)
except CertificateError:
self._socket.close()
raise
Expand Down
33 changes: 32 additions & 1 deletion tests/test_helpers.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -42,3 +42,34 @@ 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_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(expected_string)

assert result == expected_string

def test_no_tld(self):
expected_string = 'localhost'

result = get_hostname_for_ssl_match(expected_string)

assert result == expected_string

0 comments on commit 95e96de

Please sign in to comment.