Skip to content

Commit 141ef03

Browse files
committed
Bug#35833719 Consume PEM and SSL errors after failed function call
To prevent errors from failed OpenSSL library function piling up always consume error directly after failing function call. The piled up old errors caused confusion when checking the errors for later function calls. An example was errors like: NDB TLS SSL_read: error:0480006C:PEM routines::no start line When SSL_read was called all certificate handling have already completed and there should be no reasone for PEM function errors. But this was due to old errors reported, errors that should have been consumed earlier during certificate handling. In Certificate::read there certificates are read in a loop from a file an explicit check that "no start line" error aborted the loop and not some other error. Change-Id: Icfabe1f06d362489551e6ec7b8d42a829f65878c
1 parent 1445212 commit 141ef03

File tree

4 files changed

+77
-29
lines changed

4 files changed

+77
-29
lines changed

storage/ndb/include/util/NodeCertificate.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ class Certificate {
173173
static bool remove(const char * dir, const char * file);
174174

175175
/* Read from file */
176-
static void read(struct stack_st_X509 *, FILE *);
176+
static bool read(struct stack_st_X509 *, FILE *);
177177
static struct stack_st_X509 * open(const char * path);
178178
static struct stack_st_X509 * open(const PkiFile::PathName &);
179179
static struct x509_st * open_one(const char * path); // first cert in file

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

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -130,22 +130,6 @@ int NdbSocket::set_nonblocking(int on) const {
130130

131131
/* NdbSocket private instance methods */
132132

133-
// ssl_close
134-
void NdbSocket::ssl_close() {
135-
Guard guard(mutex);
136-
const int mode = SSL_get_shutdown(ssl);
137-
if (!(mode & SSL_SENT_SHUTDOWN)) {
138-
/*
139-
* Do not call SSL_shutdown again if it already been called in
140-
* NdbSocket::shutdown. In that case it could block waiting on
141-
* SSL_RECEIVED_SHUTDOWN.
142-
*/
143-
SSL_shutdown(ssl);
144-
}
145-
SSL_free(ssl);
146-
ssl = nullptr;
147-
}
148-
149133
#if OPENSSL_VERSION_NUMBER >= NDB_TLS_MINIMUM_OPENSSL
150134

151135
static void log_ssl_error(const char * fn_name)
@@ -204,6 +188,28 @@ static ssize_t handle_ssl_error(int err, const char * fn) {
204188
}
205189
}
206190

191+
// ssl_close
192+
void NdbSocket::ssl_close() {
193+
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");
207+
}
208+
}
209+
SSL_free(ssl);
210+
ssl = nullptr;
211+
}
212+
207213
bool NdbSocket::update_keys(bool req_peer) const {
208214
if(ssl && (SSL_version(ssl) == TLS1_3_VERSION)) {
209215
Guard guard(mutex);
@@ -310,6 +316,7 @@ bool NdbSocket::key_update_pending() const { return false; }
310316
ssize_t NdbSocket::ssl_recv(char *, size_t) const { return too_old; }
311317
ssize_t NdbSocket::ssl_peek(char *, size_t) const { return too_old; }
312318
ssize_t NdbSocket::ssl_send(const char *, size_t) const { return too_old; }
319+
void NdbSocket::ssl_close() { }
313320
int NdbSocket::ssl_shutdown() const { return -1; }
314321
#endif
315322

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

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "ndb_global.h" // DIR_SEPARATOR, access()
3838
#include "ndb_limits.h"
3939

40+
#include "debugger/EventLogger.hpp"
4041
#include "portlib/ndb_localtime.h"
4142
#include "util/File.hpp"
4243
#include "util/ndb_openssl3_compat.h"
@@ -57,6 +58,30 @@ inline void _putenv(const char *a) { putenv(const_cast<char *>(a)); }
5758
*/
5859
static constexpr size_t CN_max_length = 65;
5960

61+
static void handle_pem_error(const char fn_name[])
62+
{
63+
int err = ERR_peek_last_error();
64+
if (err != 0)
65+
{
66+
char buffer[256];
67+
ERR_error_string_n(err, buffer, 256);
68+
g_eventLogger->error("NDB TLS %s: %s", fn_name, buffer);
69+
}
70+
else
71+
{
72+
// Expected some error
73+
g_eventLogger->error("NDB TLS %s: Expected error but found none.", fn_name);
74+
}
75+
/*
76+
* Check that this function are called for every failed function call that
77+
* have set an error.
78+
*/
79+
#if defined(VM_TRACE) || !defined(NDEBUG) || defined(ERROR_INSERT)
80+
require(ERR_get_error() != 0); // At least one error
81+
#endif
82+
while (ERR_get_error() != 0) /* clear SSL error stack without checks */ ;
83+
}
84+
6085
/*
6186
* Implementation of certificate and key file naming conventions
6287
*/
@@ -299,6 +324,7 @@ EVP_PKEY * PrivateKey::open(const char * path, char * passphrase) {
299324
FILE * fp = fopen(path, "r");
300325
if(fp != nullptr) {
301326
PEM_read_PrivateKey(fp, &key, nullptr, passphrase);
327+
if(!key) handle_pem_error("PEM_read_PrivateKey");
302328
fclose(fp);
303329
}
304330
return key;
@@ -319,6 +345,7 @@ bool PrivateKey::store(EVP_PKEY * key, const PkiFile::PathName & path,
319345
return true;
320346
}
321347
else {
348+
handle_pem_error("PEM_write_PKCS8PrivateKey");
322349
fclose(fp);
323350
PkiFile::remove(path);
324351
return false;
@@ -488,6 +515,7 @@ SigningRequest * SigningRequest::open(const char * file) {
488515
SigningRequest * SigningRequest::read(FILE * fp) {
489516
X509_REQ * req = nullptr;
490517
PEM_read_X509_REQ(fp, &req, nullptr, nullptr);
518+
if (req == nullptr) handle_pem_error("PEM_read_X509_REQ");
491519
return req ? new SigningRequest(req) : nullptr;
492520
}
493521

@@ -514,7 +542,9 @@ bool SigningRequest::store(const char * dir) const {
514542
}
515543

516544
bool SigningRequest::write(FILE * fp) const {
517-
return PEM_write_X509_REQ(fp, m_req);
545+
bool ok = PEM_write_X509_REQ(fp, m_req);
546+
if (!ok) handle_pem_error("PEM_write_X509_REQ");
547+
return ok;
518548
}
519549

520550
bool SigningRequest::verify() const {
@@ -621,6 +651,7 @@ bool Certificate::write(STACK_OF(X509) * certs, FILE * fp) {
621651
int r = 1;
622652
for(int i = 0 ; i < sk_X509_num(certs) && r == 1 ; i++)
623653
r = PEM_write_X509(fp, sk_X509_value(certs, i));
654+
if (r != 1) handle_pem_error("PEM_writeX509");
624655
return r;
625656
}
626657

@@ -669,22 +700,30 @@ STACK_OF(X509) * Certificate::open(const char * path) {
669700

670701
if(fp) {
671702
certs = sk_X509_new_null();
672-
Certificate::read(certs, fp);
703+
bool ok = Certificate::read(certs, fp);
673704
fclose(fp);
674-
}
675705

676-
if(sk_X509_num(certs) == 0) {
677-
sk_X509_free(certs);
678-
certs = nullptr;
706+
if(!ok || sk_X509_num(certs) == 0) {
707+
sk_X509_pop_free(certs, X509_free);
708+
certs = nullptr;
709+
}
679710
}
680711

681712
return certs;
682713
}
683714

684-
void Certificate::read(STACK_OF(X509) * certs, FILE * fp) {
715+
bool Certificate::read(STACK_OF(X509) * certs, FILE * fp) {
685716
X509 * cert;
686717
while((cert = PEM_read_X509(fp, nullptr, nullptr, nullptr)) != nullptr)
687718
sk_X509_push(certs, cert);
719+
// Expect PEM_R_NO_START_LINE error
720+
int err = ERR_peek_last_error();
721+
if (ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
722+
while (ERR_get_error() != 0) /* clear ssl errors */ ;
723+
return true;
724+
}
725+
handle_pem_error("PEM_read_X509");
726+
return false;
688727
}
689728

690729
X509 * Certificate::open_one(const char * path) {
@@ -1277,10 +1316,7 @@ int NodeCertificate::stderr_callback(int result, X509_STORE_CTX * ctx) {
12771316
bool NodeCertificate::verify_signature(EVP_PKEY * CA_key) const {
12781317
int r0 = X509_verify(m_x509, CA_key);
12791318
if (r0 != 1) {
1280-
char error_buf[256];
1281-
int er = ERR_get_error();
1282-
ERR_error_string_n(er, error_buf, 256);
1283-
fprintf(stderr, "X509_verify: %d (err %d: %s)\n", r0, er, error_buf);
1319+
handle_pem_error("X509_verify");
12841320
return false;
12851321
}
12861322

storage/ndb/tools/sign_keys.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1202,14 +1202,18 @@ int remote_key_signing(const SigningRequest * csr, EVP_PKEY * key,
12021202
fclose(wfp);
12031203

12041204
/* Read certificate chain file from coprocess */
1205-
Certificate::read(all_certs, rfp);
1205+
bool read_certs_ok = Certificate::read(all_certs, rfp);
12061206
fclose(rfp);
12071207

12081208
/* Wait up to 10 seconds for coprocess to exit.
12091209
Return value 137 will indicate that wait() has failed. */
12101210
int r1 = 137;
12111211
proc->wait(r1, 10000);
12121212

1213+
/* Check if any failure when certs were read */
1214+
if (!read_certs_ok)
1215+
return 138;
1216+
12131217
/* Check if any certs were read */
12141218
int ncerts = sk_X509_num(all_certs);
12151219
if(ncerts == 0)
@@ -1247,6 +1251,7 @@ const NodeCertificate * sign_remote(const SigningRequest * csr,
12471251
int rs = remote_key_signing(csr, csr->key(), cluster_certs, all_certs);
12481252
if(rs == 0)
12491253
return NodeCertificate::from_credentials(all_certs, csr->key());
1254+
sk_X509_pop_free(all_certs, X509_free);
12501255
fprintf(stderr, "Remote key signing error: %d\n", rs);
12511256
return nullptr;
12521257
}

0 commit comments

Comments
 (0)