27
27
#include " openssl/err.h"
28
28
29
29
#include " debugger/EventLogger.hpp"
30
+ #include " portlib/ndb_openssl_version.h"
30
31
#include " portlib/NdbTick.h"
31
-
32
- #include " util/require.h"
32
+ #include " util/ndb_openssl3_compat.h"
33
33
#include " util/NdbSocket.h"
34
+ #include " util/require.h"
34
35
#include " util/socket_io.h"
35
36
36
- #include " portlib/ndb_openssl_version.h"
37
-
38
37
static constexpr bool openssl_version_ok =
39
38
(OPENSSL_VERSION_NUMBER >= NDB_TLS_MINIMUM_OPENSSL);
40
39
@@ -134,31 +133,24 @@ int NdbSocket::set_nonblocking(int on) const {
134
133
135
134
static void log_ssl_error (const char * fn_name)
136
135
{
137
- char buffer[512 ];
138
- int code;
139
- while ((code = ERR_get_error ()) != 0 ) {
140
- ERR_error_string_n (code, buffer, sizeof (buffer));
141
- g_eventLogger->error (" NDB TLS %s: %s" , fn_name, buffer);
136
+ const int code = ERR_peek_last_error ();
137
+ if (ERR_GET_REASON (code) == SSL_R_UNEXPECTED_EOF_WHILE_READING) {
138
+ /*
139
+ * "unexpected eof while reading" are in general expected to happen now and
140
+ * then when network or peer breaks - logging is suppressed to limit
141
+ * harmless noise.
142
+ */
143
+ while (ERR_get_error () != 0 ) /* clear queued errors */ ;
144
+ return ;
142
145
}
143
- }
144
-
145
- bool NdbSocket::ssl_handshake () {
146
- /* Check for non-blocking socket (see set_nonblocking): */
147
- if (SSL_get_mode (ssl) & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) return false ;
148
- assert (SSL_get_mode (ssl) & SSL_MODE_AUTO_RETRY);
149
-
150
- int r = SSL_do_handshake (ssl);
151
- if (r == 1 ) return true ;
152
-
153
- int err = SSL_get_error (ssl, r);
154
- require (err != SSL_ERROR_WANT_READ); // always use blocking I/O for handshake
155
- require (err != SSL_ERROR_WANT_WRITE);
156
- const char * desc = SSL_is_server (ssl) ?
157
- " handshake failed in server" : " handshake failed in client" ;
158
-
159
- log_ssl_error (desc);
160
- close ();
161
- return false ;
146
+ char buffer[512 ];
147
+ ERR_error_string_n (code, buffer, sizeof (buffer));
148
+ g_eventLogger->error (" NDB TLS %s: %s" , fn_name, buffer);
149
+ #if defined(VM_TRACE) || !defined(NDEBUG) || defined(ERROR_INSERT)
150
+ /* Check that there is at least one error in queue. */
151
+ require (ERR_get_error () != 0 );
152
+ #endif
153
+ while (ERR_get_error () != 0 ) /* clear queued errors */ ;
162
154
}
163
155
164
156
/* This is only used by read & write routines */
@@ -188,22 +180,43 @@ static ssize_t handle_ssl_error(int err, const char * fn) {
188
180
}
189
181
}
190
182
183
+ bool NdbSocket::ssl_handshake () {
184
+ /* Check for non-blocking socket (see set_nonblocking): */
185
+ if (SSL_get_mode (ssl) & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) return false ;
186
+ assert (SSL_get_mode (ssl) & SSL_MODE_AUTO_RETRY);
187
+
188
+ int r = SSL_do_handshake (ssl);
189
+ if (r == 1 ) return true ;
190
+
191
+ int err = SSL_get_error (ssl, r);
192
+ require (err != SSL_ERROR_WANT_READ); // always use blocking I/O for handshake
193
+ require (err != SSL_ERROR_WANT_WRITE);
194
+ const char * desc = SSL_is_server (ssl) ?
195
+ " handshake failed in server" : " handshake failed in client" ;
196
+
197
+ handle_ssl_error (err, desc);
198
+ close ();
199
+ return false ;
200
+ }
201
+
191
202
// ssl_close
192
203
void NdbSocket::ssl_close () {
193
204
Guard guard (mutex);
194
- const int mode = SSL_get_shutdown (ssl);
195
- if (!(mode & SSL_SENT_SHUTDOWN)) {
196
- /*
197
- * Do not call SSL_shutdown again if it already been called in
198
- * NdbSocket::shutdown. In that case it could block waiting on
199
- * SSL_RECEIVED_SHUTDOWN.
200
- */
201
- int r = SSL_shutdown (ssl);
202
- if (r < 0 ) {
203
- // Clear errors
204
- int err = SSL_get_error (ssl, r);
205
- Debug_Log (" SSL_shutdown(): ERR %d" , err);
206
- handle_ssl_error (err, " SSL_close" );
205
+ if (SSL_is_init_finished (ssl)) {
206
+ const int mode = SSL_get_shutdown (ssl);
207
+ if (!(mode & SSL_SENT_SHUTDOWN)) {
208
+ /*
209
+ * Do not call SSL_shutdown again if it already been called in
210
+ * NdbSocket::shutdown. In that case it could block waiting on
211
+ * SSL_RECEIVED_SHUTDOWN.
212
+ */
213
+ int r = SSL_shutdown (ssl);
214
+ if (r < 0 ) {
215
+ // Clear errors
216
+ int err = SSL_get_error (ssl, r);
217
+ Debug_Log (" SSL_shutdown(): ERR %d" , err);
218
+ handle_ssl_error (err, " SSL_close" );
219
+ }
207
220
}
208
221
}
209
222
SSL_free (ssl);
@@ -237,6 +250,11 @@ int NdbSocket::ssl_shutdown() const {
237
250
int err;
238
251
{
239
252
Guard guard (mutex);
253
+ /*
254
+ * SSL_is_init_finished may return false if either TLS handshake have not
255
+ * finished, or an unexpected eof was seen.
256
+ */
257
+ if (!SSL_is_init_finished (ssl)) return 0 ;
240
258
const int mode = SSL_get_shutdown (ssl);
241
259
assert (!(mode & SSL_SENT_SHUTDOWN));
242
260
if (unlikely (mode & SSL_SENT_SHUTDOWN)) return 0 ;
@@ -255,7 +273,7 @@ ssize_t NdbSocket::ssl_recv(char *buf, size_t len) const
255
273
int err;
256
274
{
257
275
Guard guard (mutex);
258
- if (unlikely (ssl == nullptr || SSL_get_shutdown (ssl)))
276
+ if (unlikely (ssl == nullptr || SSL_get_shutdown (ssl) & SSL_RECEIVED_SHUTDOWN ))
259
277
return 0 ;
260
278
261
279
r = SSL_read_ex (ssl, buf, len, &nread);
@@ -274,7 +292,7 @@ ssize_t NdbSocket::ssl_peek(char *buf, size_t len) const
274
292
int err;
275
293
{
276
294
Guard guard (mutex);
277
- if (unlikely (ssl == nullptr || SSL_get_shutdown (ssl)))
295
+ if (unlikely (ssl == nullptr || SSL_get_shutdown (ssl) & SSL_RECEIVED_SHUTDOWN ))
278
296
return 0 ;
279
297
280
298
r = SSL_peek_ex (ssl, buf, len, &nread);
@@ -294,7 +312,7 @@ ssize_t NdbSocket::ssl_send(const char * buf, size_t len) const
294
312
/* Locked section */
295
313
{
296
314
Guard guard (mutex);
297
- if (unlikely (ssl == nullptr || SSL_get_shutdown (ssl)))
315
+ if (unlikely (ssl == nullptr || SSL_get_shutdown (ssl) & SSL_SENT_SHUTDOWN ))
298
316
return -1 ;
299
317
300
318
if (SSL_write_ex (ssl, buf, len, &nwrite))
0 commit comments