Skip to content

Commit 8c9b493

Browse files
committed
WL#15154 patch #5 Establish TLS
On the client side, in Transporter::connect_client(), check the TLS negotiation result, initiate the TLS handshake, and perform certificate authorization checks. On the server side, in TransporterService::newSession(), check the TLS negotiation result and complete the TLS handshake. Then in TransporterRegistry::connect_server(), after receiving the client's hello message, perform certificate authorization checks. The connect and disconnect impls in TCP_Transporter are responsible for maintaining the m_encrypted flag and the certificate table. In TCP_Transporter::connect_common(), locking is enabled around the SSL object; the lock must be acquired in order to send data, receive data, or close the socket. Change-Id: I9758adc88e8f152760bab3df1485556681e88d07
1 parent 6576ab9 commit 8c9b493

File tree

4 files changed

+92
-9
lines changed

4 files changed

+92
-9
lines changed

storage/ndb/src/common/transporter/TCP_Transporter.cpp

+14-4
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,15 @@ bool TCP_Transporter::connect_client_impl(NdbSocket & socket)
220220

221221
bool TCP_Transporter::connect_common(NdbSocket & socket)
222222
{
223+
struct x509_st * cert = socket.peer_certificate();
224+
if(cert)
225+
{
226+
m_encrypted = true;
227+
m_transporter_registry.getTlsKeyManager()->cert_table_set(remoteNodeId,
228+
cert);
229+
socket.enable_locking();
230+
}
231+
223232
setSocketOptions(socket.ndb_socket());
224233
socket.set_nonblocking(true);
225234

@@ -532,15 +541,13 @@ TCP_Transporter::shutdown()
532541
{
533542
if (theSocket.is_valid())
534543
{
535-
DEB_MULTI_TRP(("Close socket for trp %u",
536-
getTransporterIndex()));
544+
DEB_MULTI_TRP(("Close socket for trp %u", getTransporterIndex()));
537545
theSocket.close();
538546
theSocket.invalidate();
539547
}
540548
else
541549
{
542-
DEB_MULTI_TRP(("Socket already closed for trp %u",
543-
getTransporterIndex()));
550+
DEB_MULTI_TRP(("Socket already closed for trp %u", getTransporterIndex()));
544551
}
545552
m_connected = false;
546553
}
@@ -694,4 +701,7 @@ TCP_Transporter::disconnectImpl()
694701
report_error(TE_ERROR_CLOSING_SOCKET);
695702
}
696703
}
704+
705+
m_encrypted = false;
706+
m_transporter_registry.getTlsKeyManager()->cert_table_clear(remoteNodeId);
697707
}

storage/ndb/src/common/transporter/Transporter.cpp

+36-1
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,11 @@ Transporter::connect_server(NdbSocket & sockfd,
271271
DBUG_RETURN(true);
272272
}
273273

274+
inline static void
275+
tls_error(int code)
276+
{
277+
g_eventLogger->error("TLS error %d '%s'", code, TlsKeyError::message(code));
278+
}
274279

275280
bool
276281
Transporter::connect_client()
@@ -351,11 +356,41 @@ Transporter::connect_client()
351356
int auth = m_socket_client->authenticate(secureSocket);
352357
if(auth < SocketAuthenticator::AuthOk)
353358
{
354-
DEBUG_FPRINTF((stderr, "Socket Authenticator failed\n"));
355359
DBUG_RETURN(false);
356360
}
357361
g_eventLogger->debug("Transporter client auth result: %d [%s]", auth,
358362
SocketAuthenticator::error(auth));
363+
364+
if(auth == SocketAuthTls::negotiate_tls_ok) // Initiate TLS
365+
{
366+
struct ssl_ctx_st * ctx = m_transporter_registry.m_tls_keys.ctx();
367+
struct ssl_st * ssl = NdbSocket::get_client_ssl(ctx);
368+
if(ssl == nullptr)
369+
{
370+
tls_error(TlsKeyError::no_local_cert);
371+
DBUG_RETURN(false);
372+
}
373+
if(! secureSocket.associate(ssl))
374+
{
375+
tls_error(TlsKeyError::openssl_error);
376+
NdbSocket::free_ssl(ssl);
377+
DBUG_RETURN(false);
378+
}
379+
if(! secureSocket.do_tls_handshake())
380+
{
381+
tls_error(TlsKeyError::authentication_failure);
382+
DBUG_RETURN(false);
383+
}
384+
385+
/* Certificate Authorization */
386+
auth = TlsKeyManager::check_server_host_auth(secureSocket,
387+
remoteHostName);
388+
if(auth)
389+
{
390+
tls_error(auth);
391+
DBUG_RETURN(false);
392+
}
393+
}
359394
}
360395

361396
DBUG_RETURN(connect_client(secureSocket));

storage/ndb/src/common/transporter/Transporter.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ class Transporter {
295295
// Sending/Receiving socket used by both client and server
296296
NdbSocket theSocket;
297297
private:
298-
SocketClient *m_socket_client;
298+
SocketClient *m_socket_client {nullptr};
299299
ndb_sockaddr m_connect_address;
300300

301301
virtual bool send_is_possible(int timeout_millisec) const = 0;

storage/ndb/src/common/transporter/TransporterRegistry.cpp

+41-3
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,33 @@ SocketServer::Session * TransporterService::newSession(ndb_socket_t sockfd)
126126
DEBUG_FPRINTF((stderr, "New session created\n"));
127127
if(m_auth)
128128
{
129-
int r = m_auth->server_authenticate(secureSocket);
130-
if(r < SocketAuthenticator::AuthOk)
129+
int auth_result = m_auth->server_authenticate(secureSocket);
130+
g_eventLogger->debug("Transporter server auth result: %d [%s]",
131+
auth_result, SocketAuthenticator::error(auth_result));
132+
if(auth_result < SocketAuthenticator::AuthOk)
131133
{
132134
DEBUG_FPRINTF((stderr, "Failed to authenticate new session\n"));
133135
secureSocket.close_with_reset(true); // Close with reset
134-
DBUG_RETURN(0);
136+
DBUG_RETURN(nullptr);
137+
}
138+
139+
if(auth_result == SocketAuthTls::negotiate_tls_ok) // Intitate TLS
140+
{
141+
struct ssl_ctx_st * ctx = m_transporter_registry->m_tls_keys.ctx();
142+
struct ssl_st * ssl = NdbSocket::get_server_ssl(ctx);
143+
if(ssl == nullptr)
144+
{
145+
DBUG_RETURN(nullptr);
146+
}
147+
if(! secureSocket.associate(ssl))
148+
{
149+
NdbSocket::free_ssl(ssl);
150+
DBUG_RETURN(nullptr);
151+
}
152+
if(! secureSocket.do_tls_handshake())
153+
{
154+
DBUG_RETURN(nullptr);
155+
}
135156
}
136157
}
137158

@@ -794,6 +815,23 @@ TransporterRegistry::connect_server(NdbSocket & socket,
794815
DBUG_RETURN(false);
795816
}
796817

818+
/* Client Certificate Authorization.
819+
*/
820+
ClientAuthorization * clientAuth;
821+
int authResult = TlsKeyManager::check_socket_for_auth(socket, & clientAuth);
822+
823+
if((authResult == 0) && clientAuth) {
824+
// This check may block, waiting for a DNS lookup
825+
authResult = TlsKeyManager::perform_client_host_auth(clientAuth);
826+
}
827+
828+
if(authResult)
829+
{
830+
msg.assfmt("TLS %s (for node %d [%s])",
831+
TlsKeyError::message(authResult), nodeId, t->remoteHostName);
832+
DBUG_RETURN(false);
833+
}
834+
797835
// Send reply to client
798836
SecureSocketOutputStream s_output(socket);
799837
if (s_output.println("%d %d", t->getLocalNodeId(), t->m_type) < 0)

0 commit comments

Comments
 (0)