Merge pull request #4236 from sysown/v2.x_ssl_keylog_support

Added support for SSLKEYLOGFILE
pull/4247/head
René Cannaò 3 years ago committed by GitHub
commit 0acf5bd94f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

4
deps/Makefile vendored

@ -280,6 +280,10 @@ endif
# patches for x509 cache . See https://github.com/sysown/proxysql/issues/4117 (Slow connection time with SSL and large CA file , relevant on Aurora)
cd mariadb-client-library/mariadb_client && patch libmariadb/mariadb_lib.c < ../mariadb_lib.c.x509cache.patch
cd mariadb-client-library/mariadb_client && patch libmariadb/secure/openssl.c < ../openssl.c.x509cache.patch
cd mariadb-client-library/mariadb_client && patch include/mysql.h < ../mysql.h.sslkeylogfile.patch
cd mariadb-client-library/mariadb_client && patch include/ma_common.h < ../ma_common.h.sslkeylogfile.patch
cd mariadb-client-library/mariadb_client && patch libmariadb/mariadb_lib.c < ../mariadb_lib.c.sslkeylogfile.patch
cd mariadb-client-library/mariadb_client && patch libmariadb/secure/openssl.c < ../openssl.c.sslkeylogfile.patch
cd mariadb-client-library/mariadb_client && CC=${CC} CXX=${CXX} ${MAKE} mariadbclient
# cd mariadb-client-library/mariadb_client/include && make my_config.h

@ -0,0 +1,14 @@
@@ -78,12 +78,13 @@
my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);
HASH userdata;
char *server_public_key;
char *proxy_header;
size_t proxy_header_len;
int (*io_wait)(my_socket handle, my_bool is_read, int timeout);
+ void (*ssl_keylog_callback)(const void *ssl, const char *line);
};
typedef struct st_connection_handler
{
struct st_ma_connection_plugin *plugin;
void *data;

@ -0,0 +1,32 @@
@@ -3277,12 +3277,15 @@
case MYSQL_OPT_SSL_CRL:
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_crl, (char *)arg1);
break;
case MYSQL_OPT_SSL_CRLPATH:
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_crlpath, (char *)arg1);
break;
+ case MARIADB_OPT_SSL_KEYLOG_CALLBACK:
+ OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_keylog_callback, arg1);
+ break;
case MYSQL_OPT_CONNECT_ATTR_DELETE:
{
uchar *h;
CHECK_OPT_EXTENSION_SET(&mysql->options);
if (hash_inited(&mysql->options.extension->connect_attrs) &&
(h= (uchar *)hash_search(&mysql->options.extension->connect_attrs, (uchar *)arg1,
@@ -3614,12 +3617,15 @@
case MYSQL_OPT_SSL_CRL:
*((char **)arg)= mysql->options.extension ? mysql->options.ssl_cipher : NULL;
break;
case MYSQL_OPT_SSL_CRLPATH:
*((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_crlpath : NULL;
break;
+ case MARIADB_OPT_SSL_KEYLOG_CALLBACK:
+ *((void(**)(const void *, const char *))arg)= mysql->options.extension ? mysql->options.extension->ssl_keylog_callback : NULL;
+ break;
case MYSQL_OPT_CONNECT_ATTRS:
/* mysql_get_optionsv(mysql, MYSQL_OPT_CONNECT_ATTRS, keys, vals, elements) */
{
unsigned int i, *elements;
char **key= NULL;
void *arg1;

@ -0,0 +1,16 @@
@@ -242,13 +242,14 @@
MARIADB_OPT_DEBUG,
MARIADB_OPT_FOUND_ROWS,
MARIADB_OPT_MULTI_RESULTS,
MARIADB_OPT_MULTI_STATEMENTS,
MARIADB_OPT_INTERACTIVE,
MARIADB_OPT_PROXY_HEADER,
- MARIADB_OPT_IO_WAIT
+ MARIADB_OPT_IO_WAIT,
+ MARIADB_OPT_SSL_KEYLOG_CALLBACK
};
enum mariadb_value {
MARIADB_CHARSET_ID,
MARIADB_CHARSET_NAME,
MARIADB_CLIENT_ERRORS,

@ -0,0 +1,34 @@
@@ -526,12 +526,19 @@
memset(buf, 0, size);
if (userdata)
strncpy(buf, (char *)userdata, size);
return (int)strlen(buf);
}
+static void ma_tls_set_sslkeylog_callback(MYSQL *mysql, SSL_CTX *ssl_ctx)
+{
+ if (mysql->options.extension && mysql->options.extension->ssl_keylog_callback)
+ {
+ SSL_CTX_set_keylog_callback(ssl_ctx, (void(*)(const SSL*, const char*))mysql->options.extension->ssl_keylog_callback);
+ }
+}
static int ma_tls_set_certs(MYSQL *mysql, SSL *ssl)
{
char *certfile= mysql->options.ssl_cert,
*keyfile= mysql->options.ssl_key;
char *pw= (mysql->options.extension) ?
@@ -653,12 +660,13 @@
if (!(ctx= SSL_CTX_new(SSLv23_client_method())))
#endif
goto error;
if (mysql->options.extension)
options|= ma_tls_version_options(mysql->options.extension->tls_version);
SSL_CTX_set_options(ctx, options);
+ ma_tls_set_sslkeylog_callback(mysql, ctx);
#ifdef HAVE_TLS_SESSION_CACHE
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT);
ma_tls_sessions= (MA_SSL_SESSION *)calloc(1, sizeof(struct st_ma_tls_session) * ma_tls_session_cache_size);
SSL_CTX_sess_set_new_cb(ctx, ma_tls_session_cb);
SSL_CTX_sess_set_remove_cb(ctx, ma_tls_remove_session_cb);
#endif

@ -59,6 +59,7 @@
#include "proxysql_debug.h"
#include "proxysql_macros.h"
#include "proxysql_coredump.h"
#include "proxysql_sslkeylog.h"
#include "jemalloc.h"
#ifndef NOJEM

@ -215,6 +215,7 @@ class ProxySQL_Admin {
#endif /* DEBUG */
int coredump_generation_interval_ms;
int coredump_generation_threshold;
char* ssl_keylog_file;
} variables;
unsigned long long last_p_memory_metrics_ts;

@ -88,7 +88,8 @@ class ProxySQL_GlobalVariables {
char * sqlite3_plugin;
char * web_interface_plugin;
char * ldap_auth_plugin;
SSL * get_SSL_ctx();
SSL_CTX *get_SSL_ctx();
SSL *get_SSL_new();
void get_SSL_pem_mem(char **key, char **cert);
std::shared_ptr<prometheus::Registry> prometheus_registry { nullptr };
struct {
@ -126,6 +127,8 @@ class ProxySQL_GlobalVariables {
bool clickhouse_server;
#endif /* PROXYSQLCLICKHOUSE */
pthread_mutex_t ext_glomth_mutex;
bool ssl_keylog_enabled;
} global;
struct mysql {
char *server_version;

@ -0,0 +1,11 @@
#ifndef __PROXYSQL_SSLKEYLOG_H
#define __PROXYSQL_SSLKEYLOG_H
#include "proxysql.h"
void proxysql_keylog_init();
bool proxysql_keylog_open(const char* keylog_file);
void proxysql_keylog_close(bool lock = true);
void proxysql_keylog_attach_callback(SSL_CTX* ssl_ctx);
void proxysql_keylog_write_line_callback(const SSL* ssl, const char* line);
#endif // __PROXYSQL_SSLKEYLOG_H

@ -144,7 +144,7 @@ MYCXXFLAGS=-std=c++11 $(MYCFLAGS) $(PSQLCH) $(ENABLE_EPOLL)
default: libproxysql.a
.PHONY: default
_OBJ_CXX = ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo SpookyV2.oo MySQL_Authentication.oo gen_utils.oo sqlite3db.oo mysql_connection.oo MySQL_HostGroups_Manager.oo mysql_data_stream.oo MySQL_Thread.oo MySQL_Session.oo MySQL_Protocol.oo mysql_backend.oo Query_Processor.oo ProxySQL_Admin.oo ProxySQL_Config.oo ProxySQL_Restapi.oo MySQL_Monitor.oo MySQL_Logger.oo thread.oo MySQL_PreparedStatement.oo ProxySQL_Cluster.oo ClickHouse_Authentication.oo ClickHouse_Server.oo ProxySQL_Statistics.oo Chart_bundle_js.oo ProxySQL_HTTP_Server.oo ProxySQL_RESTAPI_Server.oo font-awesome.min.css.oo main-bundle.min.css.oo set_parser.oo MySQL_Variables.oo c_tokenizer.oo proxysql_utils.oo proxysql_coredump.oo
_OBJ_CXX = ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo SpookyV2.oo MySQL_Authentication.oo gen_utils.oo sqlite3db.oo mysql_connection.oo MySQL_HostGroups_Manager.oo mysql_data_stream.oo MySQL_Thread.oo MySQL_Session.oo MySQL_Protocol.oo mysql_backend.oo Query_Processor.oo ProxySQL_Admin.oo ProxySQL_Config.oo ProxySQL_Restapi.oo MySQL_Monitor.oo MySQL_Logger.oo thread.oo MySQL_PreparedStatement.oo ProxySQL_Cluster.oo ClickHouse_Authentication.oo ClickHouse_Server.oo ProxySQL_Statistics.oo Chart_bundle_js.oo ProxySQL_HTTP_Server.oo ProxySQL_RESTAPI_Server.oo font-awesome.min.css.oo main-bundle.min.css.oo set_parser.oo MySQL_Variables.oo c_tokenizer.oo proxysql_utils.oo proxysql_coredump.oo proxysql_sslkeylog.oo
OBJ_CXX = $(patsubst %,$(ODIR)/%,$(_OBJ_CXX))
HEADERS = ../include/*.h ../include/*.hpp

@ -1510,6 +1510,7 @@ bool MySQL_Monitor_State_Data::create_new_connection() {
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);
mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback);
}
unsigned int timeout=mysql_thread___monitor_connect_timeout/1000;
if (timeout==0) timeout=1;

@ -224,6 +224,7 @@ void * kill_query_thread(void *arg) {
mysql=mysql_init(NULL);
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "proxysql_killer");
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_server_host", ka->hostname);
//mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback);
if (!mysql) {
goto __exit_kill_query_thread;
}
@ -5360,11 +5361,12 @@ void MySQL_Session::handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE(
client_myds->DSS=STATE_SSL_INIT;
client_myds->rbio_ssl = BIO_new(BIO_s_mem());
client_myds->wbio_ssl = BIO_new(BIO_s_mem());
client_myds->ssl = GloVars.get_SSL_ctx();
client_myds->ssl = GloVars.get_SSL_new();
SSL_set_fd(client_myds->ssl, client_myds->fd);
SSL_set_accept_state(client_myds->ssl);
SSL_set_bio(client_myds->ssl, client_myds->rbio_ssl, client_myds->wbio_ssl);
l_free(pkt->size,pkt->ptr);
proxysql_keylog_attach_callback(GloVars.get_SSL_ctx());
return;
}

@ -28,7 +28,6 @@
#include "ProxySQL_Statistics.hpp"
#include "MySQL_Logger.hpp"
#include "SQLite3_Server.h"
#include "Web_Interface.hpp"
#include <dirent.h>
@ -684,6 +683,7 @@ static char * admin_variables_names[]= {
#endif /* DEBUG */
(char *)"coredump_generation_interval_ms",
(char *)"coredump_generation_threshold",
(char *)"ssl_keylog_file",
NULL
};
@ -1803,6 +1803,18 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_
GloMyLogger->flush_log();
}
SPA->flush_error_log();
proxysql_keylog_close();
char* ssl_keylog_file = SPA->get_variable((char*)"ssl_keylog_file");
if (ssl_keylog_file != NULL) {
if (strlen(ssl_keylog_file) > 0) {
if (proxysql_keylog_open(ssl_keylog_file) == false) {
// re-opening file failed, setting ssl_keylog_enabled to false
GloVars.global.ssl_keylog_enabled = false;
proxy_warning("Cannot open SSLKEYLOGFILE '%s' for writing.\n", ssl_keylog_file);
}
}
free(ssl_keylog_file);
}
SPA->send_MySQL_OK(&sess->client_myds->myprot, NULL);
return false;
}
@ -5933,6 +5945,7 @@ ProxySQL_Admin::ProxySQL_Admin() :
#endif /* DEBUG */
variables.coredump_generation_interval_ms = 30000;
variables.coredump_generation_threshold = 10;
variables.ssl_keylog_file = strdup("");
last_p_memory_metrics_ts = 0;
// create the scheduler
scheduler=new ProxySQL_External_Scheduler();
@ -6436,6 +6449,9 @@ void ProxySQL_Admin::admin_shutdown() {
if (variables.telnet_stats_ifaces) {
free(variables.telnet_stats_ifaces);
}
if (variables.ssl_keylog_file) {
free(variables.ssl_keylog_file);
}
};
ProxySQL_Admin::~ProxySQL_Admin() {
@ -8082,6 +8098,7 @@ char * ProxySQL_Admin::get_variable(char *name) {
sprintf(intbuf,"%d",variables.coredump_generation_threshold);
return strdup(intbuf);
}
if (!strcasecmp(name,"ssl_keylog_file")) return s_strdup(variables.ssl_keylog_file);
return NULL;
}
@ -8773,6 +8790,35 @@ bool ProxySQL_Admin::set_variable(char *name, char *value, bool lock) { // this
return false;
}
}
if (!strcasecmp(name, "ssl_keylog_file")) {
if (strcmp(variables.ssl_keylog_file, value)) {
if (vallen == 0 || strcmp(value, "(null)") == 0) {
proxysql_keylog_close();
free(variables.ssl_keylog_file);
variables.ssl_keylog_file = strdup("");
GloVars.global.ssl_keylog_enabled = false;
} else {
char* sslkeylogfile = NULL;
if (value[0] == '/') { // absolute path
sslkeylogfile = strdup(value);
} else { // relative path
sslkeylogfile = (char*)malloc(strlen(GloVars.datadir) + strlen(value) + 2);
sprintf(sslkeylogfile, "%s/%s", GloVars.datadir, value);
}
if (proxysql_keylog_open(sslkeylogfile) == false) {
free(sslkeylogfile);
proxy_warning("Cannot open SSLKEYLOGFILE '%s' for writing.\n", value);
return false;
}
//free(sslkeylogfile);
free(variables.ssl_keylog_file);
variables.ssl_keylog_file = sslkeylogfile; //strdup(value);
GloVars.global.ssl_keylog_enabled = true;
}
}
return true;
}
return false;
}

@ -93,7 +93,10 @@ void * ProxySQL_Cluster_Monitor_thread(void *args) {
mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
//mysql_options(conn, MYSQL_OPT_READ_TIMEOUT, &timeout_long);
//mysql_options(conn, MYSQL_OPT_WRITE_TIMEOUT, &timeout);
{ unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val); }
{
unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val);
mysql_options(conn, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback);
}
//rc_conn = mysql_real_connect(conn, node->hostname, username, password, NULL, node->port, NULL, CLIENT_COMPRESS); // FIXME: add optional support for compression
rc_conn = mysql_real_connect(conn, node->get_host_address(), username, password, NULL, node->port, NULL, 0);
// if (rc_conn) {
@ -1037,7 +1040,10 @@ void ProxySQL_Cluster::pull_mysql_query_rules_from_peer(const string& expected_c
mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
//mysql_options(conn, MYSQL_OPT_READ_TIMEOUT, &timeout_long);
//mysql_options(conn, MYSQL_OPT_WRITE_TIMEOUT, &timeout);
{ unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val); }
{
unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val);
mysql_options(conn, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback);
}
proxy_info("Cluster: Fetching MySQL Query Rules from peer %s:%d started. Expected checksum: %s\n", hostname, port, expected_checksum.c_str());
rc_conn = mysql_real_connect(conn, ip_address ? ip_address : hostname, username, password, NULL, port, NULL, 0);
if (rc_conn) {
@ -1308,7 +1314,10 @@ void ProxySQL_Cluster::pull_mysql_users_from_peer(const string& expected_checksu
mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
//mysql_options(conn, MYSQL_OPT_READ_TIMEOUT, &timeout_long);
//mysql_options(conn, MYSQL_OPT_WRITE_TIMEOUT, &timeout);
{ unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val); }
{
unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val);
mysql_options(conn, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback);
}
proxy_info("Cluster: Fetching MySQL Users from peer %s:%d started. Expected checksum: %s\n", hostname, port, expected_checksum.c_str());
rc_conn = mysql_real_connect(conn, ip_address ? ip_address : hostname, username, password, NULL, port, NULL, 0);
@ -1631,7 +1640,10 @@ void ProxySQL_Cluster::pull_mysql_servers_from_peer(const std::string& checksum,
mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
//mysql_options(conn, MYSQL_OPT_READ_TIMEOUT, &timeout_long);
//mysql_options(conn, MYSQL_OPT_WRITE_TIMEOUT, &timeout);
{ unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val); }
{
unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val);
mysql_options(conn, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback);
}
proxy_info("Cluster: Fetching MySQL Servers from peer %s:%d started. Expected checksum %s\n", hostname, port, peer_checksum);
rc_conn = mysql_real_connect(conn, ip_address ? ip_address : hostname, username, password, NULL, port, NULL, 0);
if (rc_conn) {
@ -2049,7 +2061,10 @@ void ProxySQL_Cluster::pull_global_variables_from_peer(const string& var_type, c
mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
//mysql_options(conn, MYSQL_OPT_READ_TIMEOUT, &timeout_long);
//mysql_options(conn, MYSQL_OPT_WRITE_TIMEOUT, &timeout);
{ unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val); }
{
unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val);
mysql_options(conn, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback);
}
proxy_info("Cluster: Fetching %s variables from peer %s:%d started\n", vars_type_str, hostname, port);
rc_conn = mysql_real_connect(conn, ip_address ? ip_address : hostname, username, password, NULL, port, NULL, 0);
@ -2201,7 +2216,10 @@ void ProxySQL_Cluster::pull_proxysql_servers_from_peer(const std::string& expect
mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
//mysql_options(conn, MYSQL_OPT_READ_TIMEOUT, &timeout_long);
//mysql_options(conn, MYSQL_OPT_WRITE_TIMEOUT, &timeout);
{ unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val); }
{
unsigned char val = 1; mysql_options(conn, MYSQL_OPT_SSL_ENFORCE, &val);
mysql_options(conn, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback);
}
proxy_info(
"Cluster: Fetching ProxySQL Servers from peer %s:%d started. Expected checksum: %s\n",
hostname, port, expected_checksum.c_str()

@ -148,6 +148,7 @@ ProxySQL_GlobalVariables::ProxySQL_GlobalVariables() :
#ifdef PROXYSQLCLICKHOUSE
global.clickhouse_server=false;
#endif /* PROXYSQLCLICKHOUSE */
global.ssl_keylog_enabled = false;
opt=new ez::ezOptionParser();
opt->overview="High Performance Advanced Proxy for MySQL";
opt->syntax="proxysql [OPTIONS]";
@ -296,6 +297,8 @@ void ProxySQL_GlobalVariables::process_opts_pre() {
init_debug_struct();
#endif
init_coredump_struct();
proxysql_keylog_init();
};
void ProxySQL_GlobalVariables::process_opts_post() {

@ -9,7 +9,6 @@
#include "MySQL_Data_Stream.h"
#include "query_processor.h"
#include "MySQL_Variables.h"
#include <atomic>
// some of the code that follows is from mariadb client library memory allocator
@ -719,6 +718,7 @@ void MySQL_Connection::connect_start() {
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);
mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback);
}
unsigned int timeout= 1;
const char *csname = NULL;

@ -0,0 +1,102 @@
#include "proxysql_sslkeylog.h"
// http://udn.realityripple.com/docs/Mozilla/Projects/NSS/Key_Log_Format
#define KEYLOG_LABEL_MAXLEN (sizeof("CLIENT_HANDSHAKE_TRAFFIC_SECRET") - 1)
#define CLIENT_RANDOM_SIZE 32
/*
* The master secret in TLS 1.2 and before is always 48 bytes. In TLS 1.3, the
* secret size depends on the cipher suite's hash function which is 32 bytes
* for SHA-256 and 48 bytes for SHA-384.
*/
#define SECRET_MAXLEN 48
static pthread_rwlock_t keylog_file_rwlock;
/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
static FILE *keylog_file_fp = NULL;
FILE* proxysql_open_file(const char* file) {
FILE *file_tmp = fopen(file, "a+");
if (file_tmp) {
if (setvbuf(file_tmp, NULL, _IOLBF, 4096)) {
fclose(file_tmp);
file_tmp = NULL;
goto __exit;
}
}
__exit:
return file_tmp;
}
void proxysql_keylog_init() {
pthread_rwlock_init(&keylog_file_rwlock, nullptr);
keylog_file_fp = NULL;
}
bool proxysql_keylog_open(const char* keylog_file)
{
assert(keylog_file);
FILE* keylog_file_tmp = proxysql_open_file(keylog_file);
if (!keylog_file_tmp) return false;
pthread_rwlock_wrlock(&keylog_file_rwlock);
proxysql_keylog_close(false);
keylog_file_fp = keylog_file_tmp;
pthread_rwlock_unlock(&keylog_file_rwlock);
return true;
}
void proxysql_keylog_close(bool lock)
{
if (lock)
pthread_rwlock_wrlock(&keylog_file_rwlock);
if(keylog_file_fp) {
fclose(keylog_file_fp);
keylog_file_fp = NULL;
}
if (lock)
pthread_rwlock_unlock(&keylog_file_rwlock);
}
void proxysql_keylog_write_line_callback(const SSL *ssl, const char *line)
{
(void)ssl; // to fix warning
// checking keylog_file_fp without acquiring a lock is safe, as it is checked again after acquring lock
if (!keylog_file_fp) return;
/* The current maximum valid keylog line length LF and NUL is 195. */
size_t linelen;
char buf[256];
pthread_rwlock_rdlock(&keylog_file_rwlock);
if(!keylog_file_fp || !line) {
goto __exit;
}
linelen = strlen(line);
if(linelen == 0 || linelen > sizeof(buf) - 2) {
/* Empty line or too big to fit in a LF and NUL. */
goto __exit;
}
memcpy(buf, line, linelen);
if(line[linelen - 1] != '\n') {
buf[linelen++] = '\n';
}
buf[linelen] = '\0';
/* as we are using rwlock, using fputs as it's thread-safe*/
fputs(buf, keylog_file_fp);
__exit:
pthread_rwlock_unlock(&keylog_file_rwlock);
}
void proxysql_keylog_attach_callback(SSL_CTX* ssl_ctx) {
if (ssl_ctx && (SSL_CTX_get_keylog_callback(ssl_ctx) == (SSL_CTX_keylog_cb_func)NULL)) {
SSL_CTX_set_keylog_callback(ssl_ctx, proxysql_keylog_write_line_callback);
}
}

@ -4,7 +4,13 @@
#include "cpp.h"
//ProxySQL_GlobalVariables GloVars;
SSL * ProxySQL_GlobalVariables::get_SSL_ctx() {
SSL_CTX * ProxySQL_GlobalVariables::get_SSL_ctx() {
// take the mutex
std::lock_guard<std::mutex> lock(global.ssl_mutex);
return GloVars.global.ssl_ctx;
}
SSL * ProxySQL_GlobalVariables::get_SSL_new() {
// take the mutex
std::lock_guard<std::mutex> lock(global.ssl_mutex);
return SSL_new(GloVars.global.ssl_ctx);

Loading…
Cancel
Save