Skip to content

Commit 7c83065

Browse files
committed
WL#15154 patch #3 TLS negotiation
Negotiate TLS in SocketAuthTls SocketAuthenticator. On the server side, TransporterRegistry always instantiates a SocketAuthTls authenticator. Change-Id: I826390b545ef96ec4224ff25bc66d9fdb7a5cf7a
1 parent bde5956 commit 7c83065

File tree

3 files changed

+170
-13
lines changed

3 files changed

+170
-13
lines changed

storage/ndb/include/util/SocketAuthenticator.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ class SocketAuthenticator
4242

4343
static constexpr int AuthOk = 0;
4444
static const char * error(int); // returns error message for code
45+
46+
static constexpr int
47+
negotiation_failed = -4,
48+
unexpected_response = -3,
49+
peer_requires_cleartext = -2,
50+
peer_requires_tls = -1,
51+
negotiate_cleartext_ok = 0, /* AuthOk */
52+
negotiate_tls_ok = 1;
4553
};
4654

4755

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

65+
class SocketAuthTls : public SocketAuthenticator
66+
{
67+
public:
68+
SocketAuthTls(const class TlsKeyManager * km, bool requireTls) :
69+
m_tls_keys(km), tls_required(requireTls) {}
70+
~SocketAuthTls() override {}
71+
int client_authenticate(NdbSocket &) override;
72+
int server_authenticate(NdbSocket &) override;
73+
74+
private:
75+
const class TlsKeyManager * m_tls_keys;
76+
const bool tls_required;
77+
};
5778

5879
#endif // SOCKET_AUTHENTICATOR_HPP

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3597,8 +3597,9 @@ TransporterRegistry::start_service(SocketServer& socket_server)
35973597
unsigned short port= (unsigned short)t.m_s_service_port;
35983598
if(t.m_s_service_port<0)
35993599
port= -t.m_s_service_port; // is a dynamic port
3600-
TransporterService *transporter_service =
3601-
new TransporterService(new SocketAuthSimple());
3600+
// FIXME, use t.m_require_tls in patch#4:
3601+
SocketAuthTls * auth = new SocketAuthTls(& m_tls_keys, false);
3602+
TransporterService *transporter_service = new TransporterService(auth);
36023603
ndb_sockaddr addr;
36033604
if (t.m_interface && Ndb_getAddr(&addr, t.m_interface))
36043605
{

storage/ndb/src/common/util/SocketAuthenticator.cpp

Lines changed: 146 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,32 @@
2222
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2323
*/
2424

25-
#include <ndb_global.h>
26-
#include <SocketAuthenticator.hpp>
27-
#include <InputStream.hpp>
28-
#include <OutputStream.hpp>
25+
#include "ndb_global.h"
26+
#include "mgmapi/mgmapi_config_parameters.h"
27+
#include "util/InputStream.hpp"
28+
#include "util/OutputStream.hpp"
29+
#include "util/TlsKeyManager.hpp"
30+
31+
#include "util/SocketAuthenticator.hpp"
2932

3033
const char * SocketAuthenticator::error(int result)
3134
{
32-
return (result < AuthOk) ? "Socket Auth failure" : "Success";
35+
switch(result) {
36+
case negotiate_tls_ok:
37+
return "success (negotiated TLS)";
38+
case negotiate_cleartext_ok:
39+
return "success (negotiated cleartext)";
40+
case peer_requires_tls:
41+
return "peer requires TLS";
42+
case peer_requires_cleartext:
43+
return "peer requires cleartext";
44+
case unexpected_response:
45+
return "unexpected response from peer";
46+
case negotiation_failed:
47+
return "negotiation failed";
48+
default:
49+
return "[unexpected error code]";
50+
}
3351
}
3452

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

4664
// Read authentication result
4765
if (s_input.gets(buf, sizeof(buf)) == nullptr)
48-
return -1;
66+
return negotiation_failed;
4967
buf[sizeof(buf)-1]= 0;
5068

5169
// Verify authentication result
5270
if (strncmp("ok", buf, 2) == 0)
53-
return 0;
71+
return AuthOk;
5472

55-
return -1;
73+
return unexpected_response;
5674
}
5775

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

6583
// Read username
6684
if (s_input.gets(buf, sizeof(buf)) == nullptr)
67-
return -1;
85+
return negotiation_failed;
6886
buf[sizeof(buf)-1]= 0;
6987

7088
// Read password
7189
if (s_input.gets(buf, sizeof(buf)) == nullptr)
72-
return -1;
90+
return negotiation_failed;
7391
buf[sizeof(buf)-1]= 0;
7492

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

78-
return 0;
96+
return AuthOk;
97+
}
98+
99+
100+
/*
101+
* SocketAuthTls
102+
*/
103+
104+
int SocketAuthTls::client_authenticate(NdbSocket & sockfd)
105+
{
106+
SecureSocketOutputStream s_output(sockfd);
107+
SecureSocketInputStream s_input(sockfd);
108+
char buf[32];
109+
const bool tls_enabled = m_tls_keys->ctx();
110+
111+
// Write first line
112+
if(tls_required)
113+
s_output.println("ndbd TLS required");
114+
else if(tls_enabled)
115+
s_output.println("ndbd TLS enabled");
116+
else
117+
s_output.println("ndbd TLS disabled");
118+
119+
// Write second line
120+
s_output.println("%s", "");
121+
122+
// Read authentication result
123+
if (s_input.gets(buf, sizeof(buf)) == nullptr)
124+
return negotiation_failed;
125+
126+
// Check authentication result
127+
buf[sizeof(buf)-1]= '\0';
128+
if (strcmp("ok\n", buf) == 0) /* SocketAuthSimple responds "ok" */
129+
return tls_required ? peer_requires_cleartext : negotiate_cleartext_ok;
130+
131+
if (strcmp("TLS ok\n", buf) == 0)
132+
return tls_enabled ? negotiate_tls_ok : unexpected_response;
133+
134+
if (strcmp("TLS required\n", buf) == 0)
135+
return peer_requires_tls;
136+
137+
if (strcmp("Cleartext ok\n", buf) == 0)
138+
return tls_required ? unexpected_response : negotiate_cleartext_ok;
139+
140+
if (strcmp("Cleartext required\n", buf) == 0)
141+
return peer_requires_cleartext;
142+
143+
return negotiation_failed;
144+
}
145+
146+
int SocketAuthTls::server_authenticate(NdbSocket & sockfd)
147+
{
148+
SecureSocketOutputStream s_output(sockfd);
149+
SecureSocketInputStream s_input(sockfd);
150+
char buf[256];
151+
const bool tls_enabled = m_tls_keys->ctx();
152+
153+
enum { unknown, too_old, tls_off, tls_on, tls_mandatory } client_status;
154+
155+
/* Read first line */
156+
if (s_input.gets(buf, sizeof(buf)) == nullptr)
157+
return negotiation_failed;
158+
159+
/* Parse first line */
160+
buf[sizeof(buf)-1]= '\0';
161+
if(strcmp("ndbd TLS disabled\n", buf) == 0)
162+
client_status = tls_off;
163+
else if(strcmp("ndbd TLS enabled\n", buf) == 0)
164+
client_status = tls_on;
165+
else if(strcmp("ndbd TLS required\n", buf) == 0)
166+
client_status = tls_mandatory;
167+
else if(strcmp("ndbd\n", buf) == 0)
168+
client_status = too_old;
169+
else
170+
client_status = unknown;
171+
172+
/* Read the second line */
173+
if (s_input.gets(buf, sizeof(buf)) == nullptr)
174+
return negotiation_failed;
175+
176+
int result = 0;
177+
switch(client_status) {
178+
case unknown:
179+
result = unexpected_response;
180+
break;
181+
case tls_off:
182+
case too_old:
183+
result = tls_required ? peer_requires_cleartext : negotiate_cleartext_ok;
184+
break;
185+
case tls_on:
186+
result = tls_required ? negotiate_tls_ok : negotiate_cleartext_ok;
187+
break;
188+
case tls_mandatory:
189+
result = tls_enabled ? negotiate_tls_ok : peer_requires_tls;
190+
break;
191+
}
192+
193+
switch(result) {
194+
case negotiate_cleartext_ok:
195+
if(client_status == too_old)
196+
s_output.println("ok");
197+
else
198+
s_output.println("Cleartext ok");
199+
break;
200+
case negotiate_tls_ok:
201+
s_output.println("TLS ok");
202+
break;
203+
case peer_requires_tls:
204+
s_output.println("Cleartext required");
205+
break;
206+
case peer_requires_cleartext:
207+
s_output.println("TLS required");
208+
break;
209+
default:
210+
s_output.println("Error");
211+
}
212+
213+
return result;
79214
}
80215

0 commit comments

Comments
 (0)