feat(mysqlx): add descriptive TLS error messages with failure detection

Adds SSL handshake failure detection and descriptive error messages
for both client-side and backend TLS failures.

Changes to MysqlxDataStream:
- Added ssl_failed_ flag to distinguish WANT_IO (in progress) from
  actual SSL failure
- ssl_handshake_failed() accessor for session to check failure state
- ssl_failed_ is set to true in do_ssl_handshake() when
  get_ssl_status() returns MYSQLX_SSL_FAIL
- ssl_failed_ is initialized to false in constructor, init_ssl(),
  and init_ssl_connect()

Changes to MysqlxSession handler_tls_accept_init():
- After do_ssl_handshake() returns false, checks ssl_handshake_failed()
- On failure: sends error 3151 ("TLS handshake failed") to client
  with OpenSSL error details retrieved via ERR_get_error()/
  ERR_error_string_n(), then closes session
- On WANT_IO: continues waiting (existing behavior)
- Error 3150: TLS not configured on server (unchanged)
- Error 3151: TLS handshake failed (new)
- Error 3152: Reserved for backend TLS failures (Task 3)
chore/retire-dead-mysqlx-worker
Rene Cannao 2 months ago
parent dc35119813
commit d50e48a971

@ -78,6 +78,7 @@ public:
bool do_ssl_handshake();
bool ssl_init_done() const { return ssl_ != nullptr; }
bool ssl_handshake_complete() const { return ssl_handshake_done_; }
bool ssl_handshake_failed() const { return ssl_failed_; }
bool has_ssl_pending_write() const;
ssize_t flush_ssl_write_buf();
@ -113,6 +114,7 @@ private:
std::vector<uint8_t> ssl_write_buf_;
size_t ssl_write_offset_;
bool ssl_handshake_done_;
bool ssl_failed_;
bool try_parse_frame();
static constexpr size_t X_FRAME_HEADER_SIZE = 5;

@ -11,7 +11,7 @@ MysqlxDataStream::MysqlxDataStream()
poll_events_(0), revents_(0), read_offset_(0), write_offset_(0),
parse_error_(false), encrypted_(false), poll_fds_idx(-1),
ssl_(nullptr), rbio_ssl_(nullptr), wbio_ssl_(nullptr),
ssl_write_offset_(0), ssl_handshake_done_(false) {}
ssl_write_offset_(0), ssl_handshake_done_(false), ssl_failed_(false) {}
MysqlxDataStream::~MysqlxDataStream() {
if (ssl_) {
@ -116,6 +116,7 @@ void MysqlxDataStream::init_ssl(SSL_CTX* ctx) {
SSL_set_bio(ssl_, rbio_ssl_, wbio_ssl_);
SSL_set_accept_state(ssl_);
ssl_handshake_done_ = false;
ssl_failed_ = false;
encrypted_ = false;
}
@ -127,6 +128,7 @@ void MysqlxDataStream::init_ssl_connect(SSL_CTX* ctx) {
SSL_set_bio(ssl_, rbio_ssl_, wbio_ssl_);
SSL_set_connect_state(ssl_);
ssl_handshake_done_ = false;
ssl_failed_ = false;
encrypted_ = false;
}
@ -170,6 +172,8 @@ bool MysqlxDataStream::do_ssl_handshake() {
mysqlx_ssl_status status = get_ssl_status(ssl_, n);
if (status == MYSQLX_SSL_WANT_IO) {
queue_encrypted_output();
} else {
ssl_failed_ = true;
}
return false;
}

@ -612,6 +612,18 @@ void MysqlxSession::handler_tls_accept_init() {
client_ds_.init_ssl(ctx);
}
if (!client_ds_.do_ssl_handshake()) {
if (client_ds_.ssl_handshake_failed()) {
char err_buf[256];
unsigned long ssl_err = ERR_get_error();
if (ssl_err != 0) {
ERR_error_string_n(ssl_err, err_buf, sizeof(err_buf));
} else {
snprintf(err_buf, sizeof(err_buf), "Unknown TLS error");
}
send_error(3151, "TLS handshake failed");
healthy = false;
return;
}
return;
}
status_ = CONNECTING_CLIENT;

Loading…
Cancel
Save