From cdb6e90c357421053ed76fa07cfa1685bb55ad4f Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Thu, 21 Jul 2022 09:11:29 +0200 Subject: [PATCH 1/5] Fix for CONC-608: Replace server error codes Since Connector/C is not able to retrieve error strings for server error codes, the following error codes were replaced: - ER_NET_PACKET_TOO_LARFE by CR_NET_PACKET_TOO_LARGE - ER_OUT_OF_RESOURCES by CR_OUT_OF_MEMORY - ER_NET_WRITE_ERROR by CR_ERR_NET_WRITE (new constant) - ER_NET_UNCOMPRESS_ERROR by CR_ERR_NET_UNCOMPRESS (new constant) --- include/errmsg.h | 6 +++++- libmariadb/ma_errmsg.c | 7 +++++++ libmariadb/ma_net.c | 16 ++++++++++------ libmariadb/mariadb_stmt.c | 3 ++- unittest/libmariadb/connection.c | 2 +- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/include/errmsg.h b/include/errmsg.h index 7ca3238a..8a7a718c 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -101,7 +101,11 @@ extern const char *mariadb_client_errors[]; /* Error messages */ #define CR_BULK_WITHOUT_PARAMETERS 5006 #define CR_INVALID_STMT 5007 #define CR_VERSION_MISMATCH 5008 +#define CR_ERR_NET_READ 5013 +#define CR_ERR_NET_WRITE 5014 +#define CR_ERR_NET_UNCOMPRESS 5015 + /* Always last, if you add new error codes please update the value for CR_MARIADB_LAST_ERROR */ -#define CR_MARIADB_LAST_ERROR CR_VERSION_MISMATCH +#define CR_MARIADB_LAST_ERROR CR_ERR_NET_UNCOMPRESS #endif diff --git a/libmariadb/ma_errmsg.c b/libmariadb/ma_errmsg.c index 6f11f7cc..fe8eea9e 100644 --- a/libmariadb/ma_errmsg.c +++ b/libmariadb/ma_errmsg.c @@ -159,6 +159,13 @@ const char *mariadb_client_errors[] = /* 5006 */ "Bulk operation without parameters is not supported", /* 5007 */ "Invalid statement handle", /* 5008 */ "Unsupported version %d. Supported versions are in the range %d - %d", + /* 5009 */ "", + /* 5010 */ "", + /* 5011 */ "", + /* 5012 */ "", + /* 5013 */ "Read error: %s (%d)", + /* 5014 */ "Write error: %s (%d)", + /* 5015 */ "Error while uncompressing packet", "" }; diff --git a/libmariadb/ma_net.c b/libmariadb/ma_net.c index 680369b3..3451bf70 100644 --- a/libmariadb/ma_net.c +++ b/libmariadb/ma_net.c @@ -29,7 +29,7 @@ #include #include #include "mysql.h" -#include "ma_server_error.h" +#include "errmsg.h" #include #include #include @@ -125,7 +125,7 @@ static my_bool net_realloc(NET *net, size_t length) if (length >= net->max_packet_size) { net->error=1; - net->last_errno=ER_NET_PACKET_TOO_LARGE; + net->pvio->set_error(net->pvio->mysql, CR_NET_PACKET_TOO_LARGE, SQLSTATE_UNKNOWN, 0); return(1); } pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); @@ -313,7 +313,7 @@ int ma_net_real_write(NET *net, const char *packet, size_t len) uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE; if (!(b=(uchar*) malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1))) { - net->last_errno=ER_OUT_OF_RESOURCES; + net->pvio->set_error(net->pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); net->error=2; net->reading_or_writing=0; return(1); @@ -337,8 +337,13 @@ int ma_net_real_write(NET *net, const char *packet, size_t len) { if ((length=ma_pvio_write(net->pvio,(uchar *)pos,(size_t) (end-pos))) <= 0) { + int save_errno= errno; + char errmsg[100]; + net->error=2; /* Close socket */ - net->last_errno= ER_NET_ERROR_ON_WRITE; + strerror_r(save_errno, errmsg, 100); + net->pvio->set_error(net->pvio->mysql, CR_ERR_NET_WRITE, SQLSTATE_UNKNOWN, 0, + errmsg, save_errno); net->reading_or_writing=0; #ifdef HAVE_COMPRESS if (net->compress) @@ -557,8 +562,7 @@ ulong ma_net_read(NET *net) if (_mariadb_uncompress((unsigned char*) net->buff + net->where_b, &packet_length, &complen)) { net->error=2; /* caller will close socket */ - net->last_errno=ER_NET_UNCOMPRESS_ERROR; - break; + net->pvio->set_error(net->pvio->mysql, CR_ERR_NET_UNCOMPRESS, SQLSTATE_UNKNOWN, 0); return packet_error; } buffer_length+= complen; diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index fe24af5e..fe8d35e6 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -1680,7 +1680,8 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon goto fail; if (!is_multi && mysql->net.extension->multi_status == COM_MULTI_ENABLED) - ma_multi_command(mysql, COM_MULTI_END); + if (ma_multi_command(mysql, COM_MULTI_END)) + goto fail; if (mysql->net.extension->multi_status > COM_MULTI_OFF) return 0; diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index a7631dc8..624c5945 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -685,7 +685,7 @@ int test_connection_timeout2(MYSQL *unused __attribute__((unused))) SKIP_SKYSQL; SKIP_MAXSCALE; -// SKIP_TLS; + SKIP_TLS; mysql= mysql_init(NULL); mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout); From 6700ee4a7c0388b356c17f22e6d60701268b8af9 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Thu, 21 Jul 2022 09:47:23 +0200 Subject: [PATCH 2/5] Make TLS/SSL more verbose: Added TLS/SSL prefixes for error strings Report Error string for errno --- libmariadb/ma_errmsg.c | 2 +- libmariadb/secure/gnutls.c | 10 ++++++---- libmariadb/secure/openssl.c | 14 ++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libmariadb/ma_errmsg.c b/libmariadb/ma_errmsg.c index fe8eea9e..9143dcfe 100644 --- a/libmariadb/ma_errmsg.c +++ b/libmariadb/ma_errmsg.c @@ -108,7 +108,7 @@ const char *client_errors[]= /* 2023 */ "", /* 2024 */ "", /* 2025 */ "", -/* 2026 */ "SSL connection error: %-.100s", +/* 2026 */ "TLS/SSL connection error: %-.100s", /* 2027 */ "received malformed packet", /* 2028 */ "", /* 2029 */ "", diff --git a/libmariadb/secure/gnutls.c b/libmariadb/secure/gnutls.c index f7e81bf7..8aa35686 100644 --- a/libmariadb/secure/gnutls.c +++ b/libmariadb/secure/gnutls.c @@ -878,6 +878,7 @@ static void ma_tls_set_error(MYSQL *mysql, void *ssl, int ssl_errno) char ssl_error[MAX_SSL_ERR_LEN]; const char *ssl_error_reason; MARIADB_PVIO *pvio= mysql->net.pvio; + int save_errno= errno; if (!ssl_errno) { @@ -898,15 +899,16 @@ static void ma_tls_set_error(MYSQL *mysql, void *ssl, int ssl_errno) return; } - if ((ssl_error_reason= gnutls_strerror(ssl_errno))) + if (ssl_errno && (ssl_error_reason= gnutls_strerror(ssl_errno))) { pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ssl_error_reason); return; } - snprintf(ssl_error, MAX_SSL_ERR_LEN, "SSL errno=%d", ssl_errno); - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, - ssl_error); + + strerror_r(save_errno, ssl_error, MAX_SSL_ERR_LEN); + pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "TLS/SSL error: %s (%d)", + ssl_error, save_errno); } diff --git a/libmariadb/secure/openssl.c b/libmariadb/secure/openssl.c index d0b9d0ea..75b50892 100644 --- a/libmariadb/secure/openssl.c +++ b/libmariadb/secure/openssl.c @@ -125,20 +125,18 @@ static void ma_tls_set_error(MYSQL *mysql) char ssl_error[MAX_SSL_ERR_LEN]; const char *ssl_error_reason; MARIADB_PVIO *pvio= mysql->net.pvio; + int save_errno= errno; - if (!ssl_errno) - { - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error"); - return; - } - if ((ssl_error_reason= ERR_reason_error_string(ssl_errno))) + if (ssl_errno && (ssl_error_reason= ERR_reason_error_string(ssl_errno))) { pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, ssl_error_reason); return; } - snprintf(ssl_error, MAX_SSL_ERR_LEN, "SSL errno=%lu", ssl_errno); - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, ssl_error); + + strerror_r(save_errno, ssl_error, MAX_SSL_ERR_LEN); + pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "TLS/SSL error: %s (%d)", + ssl_error, save_errno); return; } From 6a67ed631d1f9ad1206dbee18f41c1ba94392620 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Thu, 21 Jul 2022 11:26:32 +0200 Subject: [PATCH 3/5] Don't prefix error message 2026 (SSL connection error) with TLS Removed prefix, since there are too many error test failing now, which check the error string and not the error number --- libmariadb/ma_errmsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb/ma_errmsg.c b/libmariadb/ma_errmsg.c index 9143dcfe..fe8eea9e 100644 --- a/libmariadb/ma_errmsg.c +++ b/libmariadb/ma_errmsg.c @@ -108,7 +108,7 @@ const char *client_errors[]= /* 2023 */ "", /* 2024 */ "", /* 2025 */ "", -/* 2026 */ "TLS/SSL connection error: %-.100s", +/* 2026 */ "SSL connection error: %-.100s", /* 2027 */ "received malformed packet", /* 2028 */ "", /* 2029 */ "", From 4830ed83790f7b0947fbb11f6e3c1272edc506f9 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Thu, 21 Jul 2022 12:15:16 +0200 Subject: [PATCH 4/5] Windows build fixes --- include/ma_global.h | 1 + libmariadb/ma_tls.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/ma_global.h b/include/ma_global.h index 1b7d6837..3a6003ea 100644 --- a/include/ma_global.h +++ b/include/ma_global.h @@ -32,6 +32,7 @@ #if _MSC_VER < 1900 #define snprintf _snprintf #endif +#define strerror_r(errno,buf,len) strerror_s(buf,len,errno) #endif #define STDCALL __stdcall #endif diff --git a/libmariadb/ma_tls.c b/libmariadb/ma_tls.c index a5401f95..3f48ad8b 100644 --- a/libmariadb/ma_tls.c +++ b/libmariadb/ma_tls.c @@ -232,6 +232,6 @@ end: void ma_pvio_tls_set_connection(MYSQL *mysql) { - return ma_tls_set_connection(mysql); + ma_tls_set_connection(mysql); } #endif /* HAVE_TLS */ From 8e8d175a64bf56076825a64a9a82718763fe345d Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Fri, 22 Jul 2022 08:16:25 +0200 Subject: [PATCH 5/5] Fix gnutls error message: When using default error string (2026), a zero ptr for error message needs to be specified. --- libmariadb/secure/gnutls.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libmariadb/secure/gnutls.c b/libmariadb/secure/gnutls.c index 8aa35686..dd462752 100644 --- a/libmariadb/secure/gnutls.c +++ b/libmariadb/secure/gnutls.c @@ -880,12 +880,6 @@ static void ma_tls_set_error(MYSQL *mysql, void *ssl, int ssl_errno) MARIADB_PVIO *pvio= mysql->net.pvio; int save_errno= errno; - if (!ssl_errno) - { - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error"); - return; - } - /* give a more descriptive error message for alerts */ if (ssl_errno == GNUTLS_E_FATAL_ALERT_RECEIVED) { @@ -901,7 +895,7 @@ static void ma_tls_set_error(MYSQL *mysql, void *ssl, int ssl_errno) if (ssl_errno && (ssl_error_reason= gnutls_strerror(ssl_errno))) { - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, + pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, ssl_error_reason); return; }