Skip to content

Commit

Permalink
WL#15154 patch #3 TLS negotiation
Browse files Browse the repository at this point in the history
Negotiate TLS in SocketAuthTls SocketAuthenticator.

On the server side, TransporterRegistry always instantiates
a SocketAuthTls authenticator.

Change-Id: I826390b545ef96ec4224ff25bc66d9fdb7a5cf7a
  • Loading branch information
jdduncan committed Jul 18, 2023
1 parent bde5956 commit 7c83065
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 13 deletions.
21 changes: 21 additions & 0 deletions storage/ndb/include/util/SocketAuthenticator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ class SocketAuthenticator

static constexpr int AuthOk = 0;
static const char * error(int); // returns error message for code

static constexpr int
negotiation_failed = -4,
unexpected_response = -3,
peer_requires_cleartext = -2,
peer_requires_tls = -1,
negotiate_cleartext_ok = 0, /* AuthOk */
negotiate_tls_ok = 1;
};


Expand All @@ -54,5 +62,18 @@ class SocketAuthSimple : public SocketAuthenticator
int server_authenticate(NdbSocket &) override;
};

class SocketAuthTls : public SocketAuthenticator
{
public:
SocketAuthTls(const class TlsKeyManager * km, bool requireTls) :
m_tls_keys(km), tls_required(requireTls) {}
~SocketAuthTls() override {}
int client_authenticate(NdbSocket &) override;
int server_authenticate(NdbSocket &) override;

private:
const class TlsKeyManager * m_tls_keys;
const bool tls_required;
};

#endif // SOCKET_AUTHENTICATOR_HPP
5 changes: 3 additions & 2 deletions storage/ndb/src/common/transporter/TransporterRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3597,8 +3597,9 @@ TransporterRegistry::start_service(SocketServer& socket_server)
unsigned short port= (unsigned short)t.m_s_service_port;
if(t.m_s_service_port<0)
port= -t.m_s_service_port; // is a dynamic port
TransporterService *transporter_service =
new TransporterService(new SocketAuthSimple());
// FIXME, use t.m_require_tls in patch#4:
SocketAuthTls * auth = new SocketAuthTls(& m_tls_keys, false);
TransporterService *transporter_service = new TransporterService(auth);
ndb_sockaddr addr;
if (t.m_interface && Ndb_getAddr(&addr, t.m_interface))
{
Expand Down
157 changes: 146 additions & 11 deletions storage/ndb/src/common/util/SocketAuthenticator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,32 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <ndb_global.h>
#include <SocketAuthenticator.hpp>
#include <InputStream.hpp>
#include <OutputStream.hpp>
#include "ndb_global.h"
#include "mgmapi/mgmapi_config_parameters.h"
#include "util/InputStream.hpp"
#include "util/OutputStream.hpp"
#include "util/TlsKeyManager.hpp"

#include "util/SocketAuthenticator.hpp"

const char * SocketAuthenticator::error(int result)
{
return (result < AuthOk) ? "Socket Auth failure" : "Success";
switch(result) {
case negotiate_tls_ok:
return "success (negotiated TLS)";
case negotiate_cleartext_ok:
return "success (negotiated cleartext)";
case peer_requires_tls:
return "peer requires TLS";
case peer_requires_cleartext:
return "peer requires cleartext";
case unexpected_response:
return "unexpected response from peer";
case negotiation_failed:
return "negotiation failed";
default:
return "[unexpected error code]";
}
}

int SocketAuthSimple::client_authenticate(NdbSocket & sockfd)
Expand All @@ -45,14 +63,14 @@ int SocketAuthSimple::client_authenticate(NdbSocket & sockfd)

// Read authentication result
if (s_input.gets(buf, sizeof(buf)) == nullptr)
return -1;
return negotiation_failed;
buf[sizeof(buf)-1]= 0;

// Verify authentication result
if (strncmp("ok", buf, 2) == 0)
return 0;
return AuthOk;

return -1;
return unexpected_response;
}

int SocketAuthSimple::server_authenticate(NdbSocket & sockfd)
Expand All @@ -64,17 +82,134 @@ int SocketAuthSimple::server_authenticate(NdbSocket & sockfd)

// Read username
if (s_input.gets(buf, sizeof(buf)) == nullptr)
return -1;
return negotiation_failed;
buf[sizeof(buf)-1]= 0;

// Read password
if (s_input.gets(buf, sizeof(buf)) == nullptr)
return -1;
return negotiation_failed;
buf[sizeof(buf)-1]= 0;

// Write authentication result
s_output.println("ok");

return 0;
return AuthOk;
}


/*
* SocketAuthTls
*/

int SocketAuthTls::client_authenticate(NdbSocket & sockfd)
{
SecureSocketOutputStream s_output(sockfd);
SecureSocketInputStream s_input(sockfd);
char buf[32];
const bool tls_enabled = m_tls_keys->ctx();

// Write first line
if(tls_required)
s_output.println("ndbd TLS required");
else if(tls_enabled)
s_output.println("ndbd TLS enabled");
else
s_output.println("ndbd TLS disabled");

// Write second line
s_output.println("%s", "");

// Read authentication result
if (s_input.gets(buf, sizeof(buf)) == nullptr)
return negotiation_failed;

// Check authentication result
buf[sizeof(buf)-1]= '\0';
if (strcmp("ok\n", buf) == 0) /* SocketAuthSimple responds "ok" */
return tls_required ? peer_requires_cleartext : negotiate_cleartext_ok;

if (strcmp("TLS ok\n", buf) == 0)
return tls_enabled ? negotiate_tls_ok : unexpected_response;

if (strcmp("TLS required\n", buf) == 0)
return peer_requires_tls;

if (strcmp("Cleartext ok\n", buf) == 0)
return tls_required ? unexpected_response : negotiate_cleartext_ok;

if (strcmp("Cleartext required\n", buf) == 0)
return peer_requires_cleartext;

return negotiation_failed;
}

int SocketAuthTls::server_authenticate(NdbSocket & sockfd)
{
SecureSocketOutputStream s_output(sockfd);
SecureSocketInputStream s_input(sockfd);
char buf[256];
const bool tls_enabled = m_tls_keys->ctx();

enum { unknown, too_old, tls_off, tls_on, tls_mandatory } client_status;

/* Read first line */
if (s_input.gets(buf, sizeof(buf)) == nullptr)
return negotiation_failed;

/* Parse first line */
buf[sizeof(buf)-1]= '\0';
if(strcmp("ndbd TLS disabled\n", buf) == 0)
client_status = tls_off;
else if(strcmp("ndbd TLS enabled\n", buf) == 0)
client_status = tls_on;
else if(strcmp("ndbd TLS required\n", buf) == 0)
client_status = tls_mandatory;
else if(strcmp("ndbd\n", buf) == 0)
client_status = too_old;
else
client_status = unknown;

/* Read the second line */
if (s_input.gets(buf, sizeof(buf)) == nullptr)
return negotiation_failed;

int result = 0;
switch(client_status) {
case unknown:
result = unexpected_response;
break;
case tls_off:
case too_old:
result = tls_required ? peer_requires_cleartext : negotiate_cleartext_ok;
break;
case tls_on:
result = tls_required ? negotiate_tls_ok : negotiate_cleartext_ok;
break;
case tls_mandatory:
result = tls_enabled ? negotiate_tls_ok : peer_requires_tls;
break;
}

switch(result) {
case negotiate_cleartext_ok:
if(client_status == too_old)
s_output.println("ok");
else
s_output.println("Cleartext ok");
break;
case negotiate_tls_ok:
s_output.println("TLS ok");
break;
case peer_requires_tls:
s_output.println("Cleartext required");
break;
case peer_requires_cleartext:
s_output.println("TLS required");
break;
default:
s_output.println("Error");
}

return result;
}

0 comments on commit 7c83065

Please sign in to comment.