From 8ab51c65e7a008f7be3b931df6e8b98aef1f9652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Fri, 8 Mar 2024 20:46:36 +0000 Subject: [PATCH 1/6] ssl_params: use NULL instead of empty string #4466 If values in mysql_servers_ssl_params are empty strings, they needs to be passed as NULL arguments in mysql_ssl_set() and mysql_options() Closes #4466 --- lib/mysql_connection.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index e3430b02a7..e58d36c1c4 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -761,14 +761,16 @@ void MySQL_Connection::connect_start() { mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, mysql_thread___ssl_p2s_crlpath); } else { mysql_ssl_set(mysql, - ssl_params->ssl_key.c_str(), - ssl_params->ssl_cert.c_str(), - ssl_params->ssl_ca.c_str(), - ssl_params->ssl_capath.c_str(), - ssl_params->ssl_cipher.c_str() + ( ssl_params->ssl_key.length() > 0 ? ssl_params->ssl_key.c_str() : NULL ) , + ( ssl_params->ssl_cert.length() > 0 ? ssl_params->ssl_cert.c_str() : NULL ) , + ( ssl_params->ssl_ca.length() > 0 ? ssl_params->ssl_ca.c_str() : NULL ) , + ( ssl_params->ssl_capath.length() > 0 ? ssl_params->ssl_capath.c_str() : NULL ) , + ( ssl_params->ssl_cipher.length() > 0 ? ssl_params->ssl_cipher.c_str() : NULL ) ); - mysql_options(mysql, MYSQL_OPT_SSL_CRL, ssl_params->ssl_crl.c_str()); - mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, ssl_params->ssl_crlpath.c_str()); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, + ( ssl_params->ssl_crl.length() > 0 ? ssl_params->ssl_crl.c_str() : NULL ) ); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, + ( ssl_params->ssl_crlpath.length() > 0 ? ssl_params->ssl_crlpath.c_str() : NULL ) ); } mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback); } From d92c2d2e297357f9faa194c647b31d0f3e11f2ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Sat, 16 Mar 2024 21:26:14 +0000 Subject: [PATCH 2/6] Implementation of MySQL_Connection::set_ssl_params --- include/mysql_connection.h | 1 + lib/mysql_connection.cpp | 48 +++++++++++++++++++++----------------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/include/mysql_connection.h b/include/mysql_connection.h index ae7dbeffe6..350a8940ca 100644 --- a/include/mysql_connection.h +++ b/include/mysql_connection.h @@ -253,5 +253,6 @@ class MySQL_Connection { bool requires_CHANGE_USER(const MySQL_Connection *client_conn); unsigned int number_of_matching_session_variables(const MySQL_Connection *client_conn, unsigned int& not_matching); unsigned long get_mysql_thread_id() { return mysql ? mysql->thread_id : 0; } + static void set_ssl_params(MYSQL *mysql, MySQLServers_SslParams *ssl_params); }; #endif /* __CLASS_MYSQL_CONNECTION_H */ diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index e58d36c1c4..37e8b58b2e 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -750,28 +750,7 @@ void MySQL_Connection::connect_start() { ssl_params = NULL; } ssl_params = MyHGM->get_Server_SSL_Params(parent->address, parent->port, userinfo->username); - if (ssl_params == NULL) { - mysql_ssl_set(mysql, - mysql_thread___ssl_p2s_key, - mysql_thread___ssl_p2s_cert, - mysql_thread___ssl_p2s_ca, - mysql_thread___ssl_p2s_capath, - mysql_thread___ssl_p2s_cipher); - mysql_options(mysql, MYSQL_OPT_SSL_CRL, mysql_thread___ssl_p2s_crl); - mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, mysql_thread___ssl_p2s_crlpath); - } else { - mysql_ssl_set(mysql, - ( ssl_params->ssl_key.length() > 0 ? ssl_params->ssl_key.c_str() : NULL ) , - ( ssl_params->ssl_cert.length() > 0 ? ssl_params->ssl_cert.c_str() : NULL ) , - ( ssl_params->ssl_ca.length() > 0 ? ssl_params->ssl_ca.c_str() : NULL ) , - ( ssl_params->ssl_capath.length() > 0 ? ssl_params->ssl_capath.c_str() : NULL ) , - ( ssl_params->ssl_cipher.length() > 0 ? ssl_params->ssl_cipher.c_str() : NULL ) - ); - mysql_options(mysql, MYSQL_OPT_SSL_CRL, - ( ssl_params->ssl_crl.length() > 0 ? ssl_params->ssl_crl.c_str() : NULL ) ); - mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, - ( ssl_params->ssl_crlpath.length() > 0 ? ssl_params->ssl_crlpath.c_str() : NULL ) ); - } + MySQL_Connection::set_ssl_params(mysql, ssl_params); mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback); } unsigned int timeout= 1; @@ -2978,3 +2957,28 @@ bool MySQL_Connection::get_gtid(char *buff, uint64_t *trx_id) { } return ret; } + +void MySQL_Connection::set_ssl_params(MYSQL *mysql, MySQLServers_SslParams *ssl_params) { + if (ssl_params == NULL) { + mysql_ssl_set(mysql, + mysql_thread___ssl_p2s_key, + mysql_thread___ssl_p2s_cert, + mysql_thread___ssl_p2s_ca, + mysql_thread___ssl_p2s_capath, + mysql_thread___ssl_p2s_cipher); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, mysql_thread___ssl_p2s_crl); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, mysql_thread___ssl_p2s_crlpath); + } else { + mysql_ssl_set(mysql, + ( ssl_params->ssl_key.length() > 0 ? ssl_params->ssl_key.c_str() : NULL ) , + ( ssl_params->ssl_cert.length() > 0 ? ssl_params->ssl_cert.c_str() : NULL ) , + ( ssl_params->ssl_ca.length() > 0 ? ssl_params->ssl_ca.c_str() : NULL ) , + ( ssl_params->ssl_capath.length() > 0 ? ssl_params->ssl_capath.c_str() : NULL ) , + ( ssl_params->ssl_cipher.length() > 0 ? ssl_params->ssl_cipher.c_str() : NULL ) + ); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, + ( ssl_params->ssl_crl.length() > 0 ? ssl_params->ssl_crl.c_str() : NULL ) ); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, + ( ssl_params->ssl_crlpath.length() > 0 ? ssl_params->ssl_crlpath.c_str() : NULL ) ); + } +} From b1e998ba71608543bf3c07adb6ec5eda302a34e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Sat, 16 Mar 2024 21:26:57 +0000 Subject: [PATCH 3/6] Fix incorrect error handling in kill_query_thread --- lib/MySQL_Session.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index ac9d00fc7a..4de71503d6 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -223,6 +223,10 @@ void* kill_query_thread(void *arg) { mysql_thr->curtime=monotonic_time(); mysql_thr->refresh_variables(); MYSQL *mysql=mysql_init(NULL); + if (!mysql) { + goto __exit_kill_query_thread; + } + mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "proxysql_killer"); mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_server_host", ka->hostname); @@ -238,9 +242,6 @@ void* kill_query_thread(void *arg) { mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback); } - if (!mysql) { - goto __exit_kill_query_thread; - } MYSQL *ret; if (ka->port) { switch (ka->kill_type) { From c971d401a4b0589029cc7f13ae3698fd2968a4f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Sat, 16 Mar 2024 21:41:27 +0000 Subject: [PATCH 4/6] Use of ssl_params in kill_query_thread() --- lib/MySQL_Session.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 4de71503d6..7d466f6288 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -222,6 +222,9 @@ void* kill_query_thread(void *arg) { std::unique_ptr mysql_thr(new MySQL_Thread()); mysql_thr->curtime=monotonic_time(); mysql_thr->refresh_variables(); + + MySQLServers_SslParams * ssl_params = NULL; + MYSQL *mysql=mysql_init(NULL); if (!mysql) { goto __exit_kill_query_thread; @@ -230,15 +233,10 @@ void* kill_query_thread(void *arg) { mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "proxysql_killer"); mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_server_host", ka->hostname); + if (ka->use_ssl && ka->port) { - mysql_ssl_set(mysql, - mysql_thread___ssl_p2s_key, - mysql_thread___ssl_p2s_cert, - mysql_thread___ssl_p2s_ca, - mysql_thread___ssl_p2s_capath, - mysql_thread___ssl_p2s_cipher); - mysql_options(mysql, MYSQL_OPT_SSL_CRL, mysql_thread___ssl_p2s_crl); - mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, mysql_thread___ssl_p2s_crlpath); + ssl_params = MyHGM->get_Server_SSL_Params(ka->hostname, ka->port, ka->username); + MySQL_Connection::set_ssl_params(mysql,ssl_params); mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback); } @@ -275,7 +273,16 @@ void* kill_query_thread(void *arg) { ret=mysql_real_connect(mysql,"localhost",ka->username,ka->password,NULL,0,ka->hostname,0); } if (!ret) { - proxy_error("Failed to connect to server %s:%d to run KILL %s %lu: Error: %s\n" , ka->hostname, ka->port, ( ka->kill_type==KILL_QUERY ? "QUERY" : "CONNECTION" ) , ka->id, mysql_error(mysql)); + int myerr = mysql_errno(mysql); + if (ssl_params != NULL && myerr == 2026) { + proxy_error("Failed to connect to server %s:%d to run KILL %s %lu. SSL Params: %s , %s , %s , %s , %s , %s , %s , %s\n", + ka->hostname, ka->port, ( ka->kill_type==KILL_QUERY ? "QUERY" : "CONNECTION" ) , ka->id, + ssl_params->ssl_ca.c_str() , ssl_params->ssl_cert.c_str() , ssl_params->ssl_key.c_str() , ssl_params->ssl_capath.c_str() , + ssl_params->ssl_crl.c_str() , ssl_params->ssl_crlpath.c_str() , ssl_params->ssl_cipher.c_str() , ssl_params->tls_version.c_str() + ); + } else { + proxy_error("Failed to connect to server %s:%d to run KILL %s %lu: Error: %s\n" , ka->hostname, ka->port, ( ka->kill_type==KILL_QUERY ? "QUERY" : "CONNECTION" ) , ka->id, mysql_error(mysql)); + } MyHGM->p_update_mysql_error_counter(p_mysql_error_type::mysql, ka->hid, ka->hostname, ka->port, mysql_errno(mysql)); goto __exit_kill_query_thread; } @@ -300,6 +307,10 @@ void* kill_query_thread(void *arg) { if (mysql) mysql_close(mysql); delete ka; + if (ssl_params != NULL) { + delete ssl_params; + ssl_params = NULL; + } return NULL; } From 68da6dd29df7f61c26bdad28c9233a2fac63f970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 18 Mar 2024 21:23:40 +0000 Subject: [PATCH 5/6] Use of ssl_params in MySQL_Monitor --- lib/MySQL_Monitor.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/MySQL_Monitor.cpp b/lib/MySQL_Monitor.cpp index 747c8e2488..c58e0ccd55 100644 --- a/lib/MySQL_Monitor.cpp +++ b/lib/MySQL_Monitor.cpp @@ -1525,15 +1525,10 @@ bool MySQL_Monitor_State_Data::set_wait_timeout() { bool MySQL_Monitor_State_Data::create_new_connection() { mysql=mysql_init(NULL); assert(mysql); - if (use_ssl) { - mysql_ssl_set(mysql, - mysql_thread___ssl_p2s_key, - mysql_thread___ssl_p2s_cert, - mysql_thread___ssl_p2s_ca, - mysql_thread___ssl_p2s_capath, - mysql_thread___ssl_p2s_cipher); - mysql_options(mysql, MYSQL_OPT_SSL_CRL, mysql_thread___ssl_p2s_crl); - mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, mysql_thread___ssl_p2s_crlpath); + MySQLServers_SslParams * ssl_params = NULL; + if (use_ssl && port) { + ssl_params = MyHGM->get_Server_SSL_Params(hostname, port, mysql_thread___monitor_username); + MySQL_Connection::set_ssl_params(mysql,ssl_params); mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback); } unsigned int timeout=mysql_thread___monitor_connect_timeout/1000; @@ -1551,6 +1546,13 @@ bool MySQL_Monitor_State_Data::create_new_connection() { mysql_error_msg=strdup(mysql_error(mysql)); int myerrno=mysql_errno(mysql); MyHGM->p_update_mysql_error_counter(p_mysql_error_type::proxysql, hostgroup_id, hostname, port, myerrno); + if (ssl_params != NULL && myerrno == 2026) { + proxy_error("Failed to connect to server %s:%d . SSL Params: %s , %s , %s , %s , %s , %s , %s , %s\n", + ( port ? hostname : "localhost" ) , port , + ssl_params->ssl_ca.c_str() , ssl_params->ssl_cert.c_str() , ssl_params->ssl_key.c_str() , ssl_params->ssl_capath.c_str() , + ssl_params->ssl_crl.c_str() , ssl_params->ssl_crlpath.c_str() , ssl_params->ssl_cipher.c_str() , ssl_params->tls_version.c_str() + ); + } if (myerrno < 2000) { mysql_close(mysql); } else { From f7fbf2b17f520725621324052a465b35cfd2d6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 18 Mar 2024 22:52:47 +0000 Subject: [PATCH 6/6] Read mysql_servers_ssl_params from config file --- lib/ProxySQL_Config.cpp | 53 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/lib/ProxySQL_Config.cpp b/lib/ProxySQL_Config.cpp index 79dee6c1ea..dc7360471a 100644 --- a/lib/ProxySQL_Config.cpp +++ b/lib/ProxySQL_Config.cpp @@ -1087,6 +1087,59 @@ int ProxySQL_Config::Read_MySQL_Servers_from_configfile() { rows++; } } + if (root.exists("mysql_servers_ssl_params")==true) { // mysql_servers_ssl_params + const Setting &mysql_servers_ssl_params = root["mysql_servers_ssl_params"]; + int count = mysql_servers_ssl_params.getLength(); + char *q=(char *)"INSERT OR REPLACE INTO mysql_servers_ssl_params (hostname, port, username, ssl_ca, ssl_cert, ssl_key, ssl_capath, ssl_crl, ssl_crlpath, ssl_cipher, tls_version, comment) VALUES ('%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')"; + for (i=0; i< count; i++) { + const Setting &line = mysql_servers_ssl_params[i]; + string hostname = ""; + int port = 3306; + string username = ""; + string ssl_ca = ""; + string ssl_cert = ""; + string ssl_key = ""; + string ssl_capath = ""; + string ssl_crl = ""; + string ssl_crlpath = ""; + string ssl_cipher = ""; + string tls_version = ""; + std::string comment=""; + if (line.lookupValue("hostname", hostname)==false) { + proxy_error("Admin: detected a mysql_servers_ssl_params in config file without a mandatory hostname\n"); + continue; + } + line.lookupValue("port", port); + line.lookupValue("username", username); + line.lookupValue("ssl_ca", ssl_ca); + line.lookupValue("ssl_cert", ssl_cert); + line.lookupValue("ssl_key", ssl_key); + line.lookupValue("ssl_capath", ssl_capath); + line.lookupValue("ssl_crl", ssl_crl); + line.lookupValue("ssl_crlpath", ssl_crlpath); + line.lookupValue("ssl_cipher", ssl_cipher); + line.lookupValue("tls_version", tls_version); + line.lookupValue("comment", comment); + char *o1=strdup(comment.c_str()); + char *o=escape_string_single_quotes(o1, false); + char *query=(char *)malloc( + strlen(q) + + hostname.length() + username.length() + + ssl_ca.length() + ssl_cert.length() + ssl_key.length() + ssl_capath.length() + + ssl_crl.length() + ssl_crlpath.length() + ssl_cipher.length() + tls_version.length() + + strlen(o) + 32); + sprintf(query, q, + hostname.c_str() , port , username.c_str() , + ssl_ca.c_str() , ssl_cert.c_str() , ssl_key.c_str() , ssl_capath.c_str() , + ssl_crl.c_str() , ssl_crlpath.c_str() , ssl_cipher.c_str() , tls_version.c_str() , + o); + admindb->execute(query); + if (o!=o1) free(o); + free(o1); + free(query); + rows++; + } + } if (root.exists("mysql_group_replication_hostgroups")==true) { const Setting &mysql_group_replication_hostgroups = root["mysql_group_replication_hostgroups"]; int count = mysql_group_replication_hostgroups.getLength();