diff --git a/include/mysql/plugin_audit.h b/include/mysql/plugin_audit.h index bfa6621b007..9771f959fce 100644 --- a/include/mysql/plugin_audit.h +++ b/include/mysql/plugin_audit.h @@ -29,7 +29,7 @@ extern "C" { #define MYSQL_AUDIT_CLASS_MASK_SIZE 1 -#define MYSQL_AUDIT_INTERFACE_VERSION 0x0302 +#define MYSQL_AUDIT_INTERFACE_VERSION 0x0303 /************************************************************************* @@ -102,6 +102,8 @@ struct mysql_event_connection const char *ip; unsigned int ip_length; MYSQL_CONST_LEX_STRING database; + const char *tls_version; + unsigned int tls_version_length; }; /* diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index fca41a85db0..a746396f921 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -738,6 +738,8 @@ struct mysql_event_connection const char *ip; unsigned int ip_length; MYSQL_CONST_LEX_STRING database; + const char *tls_version; + unsigned int tls_version_length; }; struct mysql_event_table { diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result index 75cefc34074..fa62b4dd782 100644 --- a/mysql-test/suite/plugins/r/server_audit.result +++ b/mysql-test/suite/plugins/r/server_audit.result @@ -240,7 +240,7 @@ set global server_audit_logging= on; disconnect cn1; drop user user1@localhost; set global server_audit_events=''; -set global server_audit_incl_users='root, plug_dest'; +set global server_audit_incl_users='root, plug_dest, ssl_user1'; CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; connect(localhost,plug,plug_dest,test,MYSQL_PORT,MYSQL_SOCK); @@ -256,6 +256,14 @@ connection default; disconnect plug_con; DROP USER plug; DROP USER plug_dest; +CREATE USER ssl_user1@localhost require SSL; +connect conssl1,localhost,ssl_user1,,,,,SSL; +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher CIPHER_NAME +disconnect conssl1; +connection default; +DROP USER ssl_user1@localhost; set global server_audit_query_log_limit= 15; select (1), (2), (3), (4); 1 2 3 4 @@ -301,7 +309,7 @@ server_audit_file_path server_audit_file_rotate_now OFF server_audit_file_rotate_size 1000000 server_audit_file_rotations 9 -server_audit_incl_users root, plug_dest +server_audit_incl_users root, plug_dest, ssl_user1 server_audit_logging ON server_audit_mode 1 server_audit_output_type file @@ -318,10 +326,10 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_incl_user TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show variables like \'server_audit_incl_users\'',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_excl_users= repeat("\'root\',", 10000)',ID TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show variables like \'server_audit_excl_users\'',0 -TIME,HOSTNAME,root,localhost,ID,0,CONNECT,mysql,,0 -TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,mysql,,0 -TIME,HOSTNAME,no_such_user,localhost,ID,0,FAILED_CONNECT,,,ID -TIME,HOSTNAME,no_such_user,localhost,ID,0,DISCONNECT,,,0 +TIME,HOSTNAME,root,localhost,ID,0,CONNECT,mysql,,0, +TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,mysql,,0, +TIME,HOSTNAME,no_such_user,localhost,ID,0,FAILED_CONNECT,,,ID, +TIME,HOSTNAME,no_such_user,localhost,ID,0,DISCONNECT,,,0, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_incl_users=\'odin, dva, tri\'',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_incl_users=\'odin, root, dva, tri\'',0 TIME,HOSTNAME,root,localhost,ID,ID,CREATE,test,t2, @@ -360,7 +368,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show variables like \'server_audi TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_mode=1',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_events=\'\'',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0 -TIME,HOSTNAME,root,localhost,ID,0,CONNECT,test,,0 +TIME,HOSTNAME,root,localhost,ID,0,CONNECT,test,,0, TIME,HOSTNAME,root,localhost,ID,ID,CREATE,test,t1, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create table t1 (id2 int)',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,test,t1, @@ -392,7 +400,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 -TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0 +TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, @@ -461,7 +469,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_events=\'\'',0 -TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_incl_users=\'root, plug_dest\'',0 +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_incl_users=\'root, plug_dest, ssl_user1\'',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, @@ -478,15 +486,15 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER plug_dest IDENTIFIED BY *****',0 -TIME,HOSTNAME,plug,localhost,ID,0,FAILED_CONNECT,,,ID -TIME,HOSTNAME,plug,localhost,ID,0,DISCONNECT,,,0 +TIME,HOSTNAME,plug,localhost,ID,0,FAILED_CONNECT,,,ID, +TIME,HOSTNAME,plug,localhost,ID,0,DISCONNECT,,,0, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT PROXY ON plug_dest TO plug',0 -TIME,HOSTNAME,plug,localhost,ID,0,CONNECT,,,0 -TIME,HOSTNAME,plug,localhost,ID,0,PROXY_CONNECT,,`plug_dest`@`%`,0 +TIME,HOSTNAME,plug,localhost,ID,0,CONNECT,,,0, +TIME,HOSTNAME,plug,localhost,ID,0,PROXY_CONNECT,,`plug_dest`@`%`,0, TIME,HOSTNAME,plug,localhost,ID,ID,QUERY,,'select USER(),CURRENT_USER()',0 -TIME,HOSTNAME,plug,localhost,ID,0,DISCONNECT,,,0 +TIME,HOSTNAME,plug,localhost,ID,0,DISCONNECT,,,0, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, @@ -503,6 +511,26 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'DROP USER plug_dest',0 +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER ssl_user1@localhost require SSL',0 +TIME,HOSTNAME,ssl_user1,localhost,ID,0,CONNECT,,,0,TLS_VERSION +TIME,HOSTNAME,ssl_user1,localhost,ID,ID,QUERY,Access denied for user 'ssl_user1'@'localhost' to database 'test','SHOW STATUS LIKE \'Ssl_version\'',0 +TIME,HOSTNAME,ssl_user1,localhost,ID,ID,QUERY,Access denied for user 'ssl_user1'@'localhost' to database 'test','SHOW STATUS LIKE \'Ssl_cipher\'',0 +TIME,HOSTNAME,ssl_user1,localhost,ID,0,DISCONNECT,,,0,TLS_VERSION +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'DROP USER ssl_user1@localhost',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global serv',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select \'A\', ',0 diff --git a/mysql-test/suite/plugins/t/server_audit.test b/mysql-test/suite/plugins/t/server_audit.test index 0a1f6a2aa9b..906f635536f 100644 --- a/mysql-test/suite/plugins/t/server_audit.test +++ b/mysql-test/suite/plugins/t/server_audit.test @@ -1,5 +1,7 @@ --source include/have_plugin_auth.inc --source include/not_embedded.inc +--source include/have_ssl_communication.inc +--source include/have_tlsv13.inc if (!$SERVER_AUDIT_SO) { skip No SERVER_AUDIT plugin; @@ -190,7 +192,7 @@ source include/wait_until_count_sessions.inc; drop user user1@localhost; set global server_audit_events=''; -set global server_audit_incl_users='root, plug_dest'; +set global server_audit_incl_users='root, plug_dest, ssl_user1'; CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; @@ -211,6 +213,16 @@ disconnect plug_con; DROP USER plug; DROP USER plug_dest; +CREATE USER ssl_user1@localhost require SSL; +connect (conssl1,localhost,ssl_user1,,,,,SSL); +--let $ssl_version = query_get_value(SHOW STATUS LIKE 'Ssl_version', Value, 1) +--replace_column 2 CIPHER_NAME +SHOW STATUS LIKE 'Ssl_cipher'; +disconnect conssl1; +connection default; +--sleep 2 +DROP USER ssl_user1@localhost; + set global server_audit_query_log_limit= 15; select (1), (2), (3), (4); select 'A', 'B', 'C', 'D'; @@ -237,6 +249,8 @@ show status like 'server_audit_current_log'; show variables like 'server_audit%'; uninstall plugin server_audit; +# replace stored SSL verison with constant string "TLS_VERSION" +--replace_result $ssl_version TLS_VERSION # replace the timestamp and the hostname with constant values --replace_regex /[0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\,[^,]*\,/TIME,HOSTNAME,/ /\,[1-9][0-9]*\,/,1,/ /\,[1-9][0-9]*/,ID/ cat_file $MYSQLD_DATADIR/server_audit.log; diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 65e9f0a5314..53203c143c7 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -329,6 +329,8 @@ struct connection_info int host_length; char ip[64]; int ip_length; + char tls_version[64]; + int tls_version_length; const char *query; int query_length; char query_buffer[1024]; @@ -1011,6 +1013,7 @@ static struct connection_info *get_loc_info(MYSQL_THD thd) ci->user_length= 0; ci->host_length= 0; ci->ip_length= 0; + ci->tls_version_length= 0; } return ci; } @@ -1192,6 +1195,7 @@ static void setup_connection_simple(struct connection_info *ci) ci->user_length= 0; ci->host_length= 0; ci->ip_length= 0; + ci->tls_version_length= 0; ci->query_length= 0; ci->header= 0; ci->proxy_length= 0; @@ -1215,6 +1219,8 @@ static void setup_connection_connect(MYSQL_THD thd,struct connection_info *cn, event->host, event->host_length); get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip), event->ip, event->ip_length); + get_str_n(cn->tls_version, &cn->tls_version_length, sizeof(cn->tls_version), + event->tls_version, event->tls_version_length); cn->header= 0; if (event->proxy_user && event->proxy_user[0]) { @@ -1381,6 +1387,8 @@ static void change_connection(struct connection_info *cn, event->user, event->user_length); get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip), event->ip, event->ip_length); + get_str_n(cn->tls_version, &cn->tls_version_length, sizeof(cn->tls_version), + event->tls_version, event->tls_version_length); } /* @@ -1477,6 +1485,17 @@ static size_t log_header(char *message, size_t message_len, connection_id, query_id, operation); } +static size_t create_tls_obj(const struct mysql_event_connection *ev, char *obj_str, size_t len) { + size_t obj_len; + + obj_len= 0; + memset(obj_str, 0, len); + if (ev->tls_version_length > 0) { + obj_len= my_snprintf(obj_str, len, + "%.*s", ev->tls_version_length, ev->tls_version); + } + return obj_len; +} static int log_proxy(const struct connection_info *cn, const struct mysql_event_connection *event) @@ -1494,10 +1513,10 @@ static int log_proxy(const struct connection_info *cn, cn->ip, cn->ip_length, event->thread_id, 0, "PROXY_CONNECT"); csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, - ",%.*s,`%.*s`@`%.*s`,%d", cn->db_length, cn->db, + ",%.*s,`%.*s`@`%.*s`,%d,%.*s", cn->db_length, cn->db, cn->proxy_length, cn->proxy, cn->proxy_host_length, cn->proxy_host, - event->status); + event->status, cn->tls_version_length, cn->tls_version); message[csize]= '\n'; return write_log(message, csize + 1, 1); } @@ -1510,6 +1529,8 @@ static int log_connection(const struct connection_info *cn, time_t ctime; size_t csize; char message[1024]; + char tls_obj[32]; + size_t obj_len; (void) time(&ctime); csize= log_header(message, sizeof(message)-1, &ctime, @@ -1518,8 +1539,10 @@ static int log_connection(const struct connection_info *cn, cn->host, cn->host_length, cn->ip, cn->ip_length, event->thread_id, 0, type); + + obj_len= create_tls_obj(event, tls_obj, sizeof(tls_obj)); csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, - ",%.*s,,%d", cn->db_length, cn->db, event->status); + ",%.*s,,%d,%.*s", cn->db_length, cn->db, event->status, (int) obj_len, tls_obj); message[csize]= '\n'; return write_log(message, csize + 1, 1); } @@ -1531,6 +1554,8 @@ static int log_connection_event(const struct mysql_event_connection *event, time_t ctime; size_t csize; char message[1024]; + char tls_obj[32]; + size_t obj_len; (void) time(&ctime); csize= log_header(message, sizeof(message)-1, &ctime, @@ -1539,8 +1564,10 @@ static int log_connection_event(const struct mysql_event_connection *event, event->host, event->host_length, event->ip, event->ip_length, event->thread_id, 0, type); + obj_len= create_tls_obj(event, tls_obj, sizeof(tls_obj)); csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, - ",%.*s,,%d", (int) event->database.length, event->database.str, event->status); + ",%.*s,,%d,%.*s", (int) event->database.length,event->database.str, + event->status, (int) obj_len, tls_obj); message[csize]= '\n'; return write_log(message, csize + 1, 1); } diff --git a/sql/sql_audit.h b/sql/sql_audit.h index 64500067699..1078be9ca99 100644 --- a/sql/sql_audit.h +++ b/sql/sql_audit.h @@ -83,6 +83,22 @@ static inline uint make_user_name(THD *thd, char *buf) return (uint)(end-buf); } +static inline +void set_tls_version_of_event(THD *thd, mysql_event_connection *event) +{ + event->tls_version = ""; + event->tls_version_length = 0; +#ifdef HAVE_OPENSSL + Vio *vio= thd->net.vio; + SSL *ssl= (SSL *) vio->ssl_arg; + if (ssl) + { + event->tls_version = SSL_get_version(ssl); + event->tls_version_length = safe_strlen_uint(event->tls_version); + } +#endif +} + /** Call audit plugins of GENERAL audit class, MYSQL_AUDIT_GENERAL_LOG subtype. @@ -219,6 +235,7 @@ void mysql_audit_notify_connection_connect(THD *thd) event.ip= sctx->ip; event.ip_length= safe_strlen_uint(sctx->ip); event.database= thd->db; + set_tls_version_of_event(thd, &event); mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); } @@ -248,6 +265,7 @@ void mysql_audit_notify_connection_disconnect(THD *thd, int errcode) event.ip= sctx->ip; event.ip_length= safe_strlen_uint(sctx->ip) ; event.database= thd->db; + set_tls_version_of_event(thd, &event); mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); } @@ -278,6 +296,7 @@ void mysql_audit_notify_connection_change_user(THD *thd, event.ip= old_ctx->ip; event.ip_length= safe_strlen_uint(old_ctx->ip); event.database= thd->db; + set_tls_version_of_event(thd, &event); mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); }