Skip to content

Commit c11c98e

Browse files
committed
RDBC-788 Server certificate validation
1 parent 8a817f7 commit c11c98e

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

ravendb/changes/database_changes.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import base64
12
import ssl
23
from threading import Lock
3-
from typing import TYPE_CHECKING, Dict
4+
from typing import TYPE_CHECKING, Dict, Optional
45

56
from websocket import WebSocket
67

@@ -13,6 +14,7 @@
1314
OperationStatusChange,
1415
TopologyChange,
1516
)
17+
from ravendb.serverwide.commands import GetTcpInfoCommand
1618
from ravendb.tools.parsers import IncrementalJsonParser
1719
import websocket
1820
from ravendb.exceptions.exceptions import NotSupportedException
@@ -57,6 +59,11 @@ def __init__(self, request_executor: "RequestExecutor", database_name, on_close,
5759
self._logger.addHandler(handler)
5860
self._logger.setLevel(logging.DEBUG)
5961

62+
def _get_server_certificate(self) -> Optional[str]:
63+
cmd = GetTcpInfoCommand(self._request_executor.url)
64+
self._request_executor.execute_command(cmd)
65+
return cmd.result.certificate
66+
6067
def do_work(self):
6168
preferred_node = self._request_executor.preferred_node.current_node # todo: refactor, protected access
6269
url = (
@@ -69,13 +76,22 @@ def do_work(self):
6976
while not self._closed:
7077
try:
7178
if not self.client_websocket.connected:
72-
# Get certificate and wrap socket into secured socket
7379
if self._request_executor.certificate_path:
80+
# Get server certificate via HTTPS and prepare SSL context
81+
server_certificate = base64.b64decode(self._get_server_certificate())
7482
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
7583
ssl_context.load_cert_chain(self._request_executor.certificate_path)
76-
self.client_websocket = WebSocket(sslopt={"context": ssl_context})
7784

85+
# Connect WebSocket providing SSL
86+
self.client_websocket = WebSocket(sslopt={"context": ssl_context})
7887
self.client_websocket.connect(url, suppress_origin=True)
88+
89+
# Server certificate authentication
90+
server_certificate_from_tls = self.client_websocket.sock.getpeercert(True)
91+
if server_certificate != server_certificate_from_tls:
92+
raise ValueError("Certificates don't match")
93+
94+
pass
7995
else:
8096
self.client_websocket.connect(url)
8197

0 commit comments

Comments
 (0)