* Add 'UPDATE' to list of commands checked for password masking.

* Fix 'uninstall plugin' to work on MySQL 5.7.
* Add ability to send rows affected by each command, includes new
  'audit_before_after' configuration variable.
* More offsets for more released versions.
pull/179/head
Arnold Robbins 2017-02-13 16:22:15 +02:00
parent 4fbcae3a81
commit ba21262b81
6 changed files with 1005 additions and 696 deletions

View File

@ -96,6 +96,11 @@ typedef struct ThdOffsets {
OFFSET pfs_connect_attrs_length;
OFFSET pfs_connect_attrs_cs;
OFFSET net;
OFFSET lex_m_sql_command;
OFFSET uninstall_cmd_comment;
OFFSET found_rows;
OFFSET sent_row_count;
OFFSET row_count_func;
} ThdOffsets;
/*
@ -128,7 +133,9 @@ class ThdSesData {
public:
// enum indicating from where the object list came from
enum ObjectIterType { OBJ_NONE, OBJ_DB, OBJ_QUERY_CACHE, OBJ_TABLE_LIST };
ThdSesData(THD *pTHD);
// enum indicating source of statement
typedef enum { SOURCE_GENERAL, SOURCE_QUERY_CACHE } StatementSource;
ThdSesData(THD *pTHD, StatementSource source = SOURCE_GENERAL);
THD *getTHD() const { return m_pThd;}
const char *getCmdName() const { return m_CmdName; }
void setCmdName(const char *cmd) { m_CmdName = cmd; }
@ -137,6 +144,7 @@ public:
const char *getAppName() const;
const char *getOsUser() const;
const int getPort() const { return m_port; }
const StatementSource getStatementSource() const { return m_source; }
/**
* Start fetching objects. Return true if there are objects available.
*/
@ -163,6 +171,9 @@ private:
QueryTableInf *m_tableInf;
int m_index;
// Statement source
StatementSource m_source;
PeerInfo *m_peerInfo;
int m_port; // TCP port of remote side
@ -374,8 +385,6 @@ public:
}
#endif
static inline const char * pfs_connect_attrs(void * pfs)
{
if (! Audit_formatter::thd_offsets.pfs_connect_attrs)
@ -437,6 +446,7 @@ static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
return *(const CHARSET_INFO **) (((unsigned char *) pfs) + Audit_formatter::thd_offsets.pfs_connect_attrs_cs);
}
}
static inline int thd_client_fd(THD *thd)
{
if (! Audit_formatter::thd_offsets.net)
@ -482,6 +492,52 @@ static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
return port;
}
static inline ulonglong thd_found_rows(THD *thd)
{
if (Audit_formatter::thd_offsets.found_rows == 0)
{
return 0;
}
ulonglong *rows = ((ulonglong *) (((unsigned char *) thd)
+ Audit_formatter::thd_offsets.found_rows));
return *rows;
}
static inline unsigned long thd_sent_row_count(THD *thd)
{
if (Audit_formatter::thd_offsets.sent_row_count == 0)
{
return 0;
}
ha_rows *rows = ((ha_rows *) (((unsigned char *) thd)
+ Audit_formatter::thd_offsets.sent_row_count));
return (unsigned long) *rows;
}
static inline longlong thd_row_count_func(THD *thd)
{
if (Audit_formatter::thd_offsets.row_count_func == 0)
{
return -1;
}
longlong *rows = ((longlong *) (((unsigned char *) thd)
+ Audit_formatter::thd_offsets.row_count_func));
return *rows;
}
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
static inline Sql_cmd_uninstall_plugin* lex_sql_cmd(LEX *lex)
{
return *(Sql_cmd_uninstall_plugin **) (((unsigned char *) lex) + Audit_formatter::thd_offsets.lex_m_sql_command);
}
#endif
// we don't use get_db_name() as when we call it view may be not null
// and it may return an invalid value for view_db
static inline const char *table_get_db_name(TABLE_LIST *table)

View File

@ -59,6 +59,7 @@
#if MYSQL_VERSION_ID >= 50709
#include <sql/log.h>
#if ! defined(MARIADB_BASE_VERSION)
#include <sql/sql_plugin.h>
#include <sql/auth/auth_common.h>
#endif
#endif

View File

@ -1,25 +1,24 @@
#!/bin/sh
if [ $# = 0 ]; then
if [ $# = 0 ]
then
echo "Usage: $0 <mysqld executable> [optional mysqld symbols]"
echo "Will extract offsets from mysqld. Requires gdb, md5sum and mysqld symbols."
exit 1
fi
#extract the version of mysqld
# Extract the version of mysqld
FULL_MYVER=`$1 --version | grep -P -o 'Ver\s+[\w\.-]+'| awk '{print $2}'`
FULL_MYVER=`$1 --version | grep -P -o 'Ver\s+[\w\.-]+'| awk '{ print $2 }'`
#extract the md5 digest
# Extract the md5 digest
MYMD5=`md5sum -b $1 | awk -v Field=1 '{print $1}'`
MYMD5=`md5sum -b $1 | awk -v Field=1 '{ print $1 }'`
MYVER="$FULL_MYVER"
echo $FULL_MYVER | grep 'log' > /dev/null
if [ $? = 0 ]; then
MYVER=`echo "$MYVER" | grep -P -o '.+(?=-log)'`
if echo $FULL_MYVER | grep 'log' > /dev/null
then
MYVER=`echo "$MYVER" | grep -P -o '.+(?=-log)'`
fi
COMMAND_MEMBER=command
@ -32,43 +31,83 @@ PRIV_USER=priv_user
DB=db
CLIENT_CAPS="print_offset THD client_capabilities"
#in 5.6 command member is named m_command
echo $MYVER | grep -P '^(5\.6|5\.7|10\.)' > /dev/null
if [ $? = 0 ]; then
# In 5.6 command member is named m_command
if echo $MYVER | grep -P '^(5\.6|5\.7|10\.)' > /dev/null
then
COMMAND_MEMBER=m_command
HAS_CONNECT_ATTRS=yes
fi
CONNECT_ATTRS_CS=m_session_connect_attrs_cs
#in 5.7 thread_id changed to m_thread_id. main_security_ctx changed to m_main_security_ctx
echo $MYVER | grep -P '^(5\.7)' > /dev/null
if [ $? = 0 ]; then
THREAD_ID=m_thread_id
SEC_CONTEXT=m_main_security_ctx
USER=m_user
HOST=m_host
IP=m_ip
PRIV_USER=m_priv_user
DB=m_db
#client capabilities has moved out THD in 5.7. Set to 0
CLIENT_CAPS='print_offset THD m_protocol'
HAS_CONNECT_ATTRS=yes
fi
#in 5.6.15 and up, 5.7 and mariabdb 10.0.11 and up, mariadb 10.1
#m_session_connect_attrs_cs changed to m_session_connect_attrs_cs_number
echo $MYVER | grep -P '^(5\.7|10\.1|5\.6\.(1[5-9]|[2-9][0-9])|10.0.(1[1-9]|[2-9][0-9]))' > /dev/null
if [ $? = 0 ]; then
CONNECT_ATTRS_CS=m_session_connect_attrs_cs_number
CONNECT_ATTRS_CS=m_session_connect_attrs_cs
# In 5.7 thread_id changed to m_thread_id. main_security_ctx changed to m_main_security_ctx
if echo $MYVER | grep -P '^(5\.7)' > /dev/null
then
THREAD_ID=m_thread_id
SEC_CONTEXT=m_main_security_ctx
USER=m_user
HOST=m_host
IP=m_ip
PRIV_USER=m_priv_user
DB=m_db
# client capabilities has moved out THD in 5.7. Set to 0
CLIENT_CAPS='print_offset THD m_protocol'
# comment which holds plugin name for uninstall moved into
# a separate object
HAS_LEX_SQL_CMD=yes
fi
# In 5.6.15 and up, 5.7 and mariabdb 10.0.11 and up, mariadb 10.1
# m_session_connect_attrs_cs changed to m_session_connect_attrs_cs_number
if echo $MYVER | grep -P '^(5\.7|10\.1|5\.6\.(1[5-9]|[2-9][0-9])|10.0.(1[1-9]|[2-9][0-9]))' > /dev/null
then
CONNECT_ATTRS_CS=m_session_connect_attrs_cs_number
fi
CONNECT_ATTRS=""
if [ -n "$HAS_CONNECT_ATTRS" ]; then
CONNECT_ATTRS="print_offset PFS_thread m_session_connect_attrs
if [ -n "$HAS_CONNECT_ATTRS" ]
then
CONNECT_ATTRS="print_offset PFS_thread m_session_connect_attrs
print_offset PFS_thread m_session_connect_attrs_length
print_offset PFS_thread $CONNECT_ATTRS_CS
"
else
CONNECT_ATTRS='printf ", 0, 0, 0"'
CONNECT_ATTRS='printf ", 0, 0, 0"'
fi
if echo $MYVER | grep -P '^5\.7' > /dev/null
then
if echo $MYVER | grep -P '^5\.7\.8' > /dev/null
then
FOUND_ROWS="print_offset THD limit_found_rows"
else
FOUND_ROWS="print_offset THD previous_found_rows"
fi
else
FOUND_ROWS="print_offset THD limit_found_rows"
fi
if echo $MYVER | grep -P '^5\.[15]' > /dev/null
then
SENT_ROW_COUNT='print_offset THD sent_row_count'
else
SENT_ROW_COUNT="print_offset THD m_sent_row_count"
fi
if echo $MYVER | grep -P '^5\.1' > /dev/null
then
ROW_COUNT_FUNC='print_offset THD row_count_func'
else
ROW_COUNT_FUNC='print_offset THD m_row_count_func'
fi
LEX_SQL=""
if [ -n "$HAS_LEX_SQL_CMD" ]
then
LEX_SQL="print_offset LEX m_sql_cmd
print_offset Sql_cmd_uninstall_plugin m_comment"
else
LEX_SQL='printf ", 0, 0"'
fi
cat <<EOF > offsets.gdb
@ -93,23 +132,31 @@ print_offset THD killed
$CLIENT_CAPS
$CONNECT_ATTRS
print_offset THD net
$LEX_SQL
$FOUND_ROWS
$SENT_ROW_COUNT
$ROW_COUNT_FUNC
printf "}"
EOF
SYMPARAM=""
if [ -n "$2" ]; then
if [ -n "$2" ]
then
SYMPARAM="-s $2 -e"
fi
which gdb > /dev/null 2>&1
if [ $? != 0 ]; then
if which gdb > /dev/null 2>&1
then
:
else
echo "ERROR: gdb not found. Make sure gdb is installed and on the path."
exit 3;
exit 3
fi
gdb -n -q -batch -x offsets.gdb $SYMPARAM $1 > /dev/null 2>&1
if [ $? != 0 ]; then
if gdb -n -q -batch -x offsets.gdb $SYMPARAM $1 > /dev/null 2>&1
then
:
else
echo "GDB failed!!!" > /dev/stderr
exit 2
fi
@ -118,7 +165,6 @@ OFFSETS=`cat gdb.txt`
echo "//offsets for: $1 ($FULL_MYVER)"
echo "$OFFSETS,"
#clean up
# clean up
rm gdb.txt
rm offsets.gdb

View File

@ -835,6 +835,31 @@ ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer
}
const char *cmd = pThdData->getCmdName();
ulonglong rows = 0;
if (pThdData->getStatementSource() == ThdSesData::SOURCE_QUERY_CACHE)
{
// from the query cache
rows = thd_found_rows(thd);
}
else if (strcasestr(cmd, "insert") != NULL ||
strcasestr(cmd, "update") != NULL ||
strcasestr(cmd, "delete") != NULL ||
(strcasestr(cmd, "select") != NULL && thd_row_count_func(thd) > 0))
{
// m_row_count_func will be -1 for most selects but can be > 0, e.g. select into file
rows = thd_row_count_func(thd);
}
else
{
rows = thd_sent_row_count(thd);
}
if (rows != 0UL)
{
yajl_add_uint64(gen, "rows", rows);
}
yajl_add_string_val(gen, "cmd", cmd);
// get objects
@ -960,11 +985,11 @@ ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer
return res;
}
ThdSesData::ThdSesData(THD *pTHD)
ThdSesData::ThdSesData(THD *pTHD, StatementSource source)
: m_pThd (pTHD), m_CmdName(NULL), m_UserName(NULL),
m_objIterType(OBJ_NONE), m_tables(NULL), m_firstTable(true),
m_tableInf(NULL), m_index(0), m_isSqlCmd(false),
m_port(-1)
m_port(-1), m_source(source)
{
m_CmdName = retrieve_command (m_pThd, m_isSqlCmd);
m_UserName = retrieve_user (m_pThd);

File diff suppressed because it is too large Load Diff

View File

@ -85,6 +85,14 @@ static int num_record_objs = 0;
static int num_whitelist_users = 0;
static SHOW_VAR com_status_vars_array [MAX_COM_STATUS_VARS_RECORDS] = {{0}};
enum before_after_enum {
AUDIT_AFTER = 0, // default
AUDIT_BEFORE,
AUDIT_BOTH
};
static ulong before_after_mode = AUDIT_AFTER;
// regex stuff
static char password_masking_regex_check_buff[4096] = {0};
static char * password_masking_regex_string = NULL;
@ -173,10 +181,24 @@ static MYSQL_THDVAR_BOOL(peer_is_uds,
// terminated by a final '\0'.
char peer_info_init_value[sizeof(struct PeerInfo) + 4];
#if defined(MARIADB_BASE_VERSION)
static MYSQL_THDVAR_ULONG(peer_info,
PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT,
"Pointer to peer info data",
NULL, NULL, 0, 0,
#ifdef __x86_64__
0xffffffffffffff,
#else
0xffffffff,
#endif
1);
#else // NOT mariadb
static MYSQL_THDVAR_STR(peer_info,
PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_READONLY | /* PLUGIN_VAR_NOCMDOPT | */ PLUGIN_VAR_MEMALLOC,
PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_READONLY |
PLUGIN_VAR_MEMALLOC,
"Info related to client process",
NULL, NULL, peer_info_init_value);
#endif
THDPRINTED *GetThdPrintedList(THD *thd)
@ -202,12 +224,32 @@ static void initializePeerCredentials(THD *pThd)
int fd;
PeerInfo *peer;
#if defined(MARIADB_BASE_VERSION)
if (THDVAR(pThd, peer_info) == 0)
{
peer = (PeerInfo *) malloc(sizeof(PeerInfo));
if (peer)
{
memset(peer, 0, sizeof(PeerInfo));
THDVAR(pThd, peer_info) = (ulong) peer;
}
else
{
goto done;
}
}
else
{
peer = (PeerInfo *) THDVAR(pThd, peer_info);
}
#else
// zero out thread local copy of PeerInfo
peer = (PeerInfo *) THDVAR(pThd, peer_info);
if (peer != NULL)
{
memset(peer, 0, sizeof(PeerInfo));
}
#endif
// get the NET structure
sock = Audit_formatter::thd_client_fd(pThd);
@ -398,6 +440,23 @@ static my_bool check_do_password_masking(const char * cmd)
return false;
}
static void do_delay(ThdSesData *pThdData)
{
if (delay_ms_val > 0)
{
const char *cmd = pThdData->getCmdName();
const char *cmds[2];
cmds[0] = cmd;
cmds[1] = NULL;
int delay = check_array(cmds, (char *) delay_cmds_array, MAX_COMMAND_CHAR_NUMBERS);
if (delay)
{
// Audit_file_handler::print_sleep(thd,delay_ms_val);
my_sleep(delay_ms_val *1000);
}
}
}
static void audit(ThdSesData *pThdData)
{
THDPRINTED *pThdPrintedList = GetThdPrintedList(pThdData->getTHD());
@ -476,7 +535,7 @@ static void audit(ThdSesData *pThdData)
}
}
if (pThdPrintedList && pThdPrintedList->cur_index < MAX_NUM_QUEUE_ELEM)
if (before_after_mode != AUDIT_BOTH && pThdPrintedList && pThdPrintedList->cur_index < MAX_NUM_QUEUE_ELEM)
{
// audit the event if we haven't done so yet or in the case of prepare_sql
// we audit as the test "test select" doesn't go through mysql_execute_command
@ -494,20 +553,6 @@ static void audit(ThdSesData *pThdData)
{
Audit_handler::log_audit_all(pThdData);
}
if (delay_ms_val > 0)
{
const char * cmd = pThdData->getCmdName();
const char *cmds[2];
cmds[0] = cmd;
cmds[1] = NULL;
int delay = check_array(cmds, (char *) delay_cmds_array, MAX_COMMAND_CHAR_NUMBERS);
if (delay)
{
// Audit_file_handler::print_sleep(thd,delay_ms_val);
my_sleep (delay_ms_val *1000);
}
}
}
@ -596,13 +641,13 @@ static int audit_send_result_to_client(Query_cache *pthis, THD *thd, const LEX_
}
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
res = trampoline_send_result_to_client (pthis,thd, sql, query_length);
res = trampoline_send_result_to_client(pthis,thd, sql, query_length);
#else
res = trampoline_send_result_to_client (pthis, thd, sql_query);
res = trampoline_send_result_to_client(pthis, thd, sql_query);
#endif
if (res)
{
ThdSesData thd_data(thd);
ThdSesData thd_data(thd, ThdSesData::SOURCE_QUERY_CACHE);
audit(&thd_data);
}
THDVAR(thd, query_cache_table_list) = 0;
@ -630,7 +675,9 @@ static int audit_open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint f
res = trampoline_open_tables (thd, start, counter, flags);
#endif
// only log if thread id or query id is non 0 (otherwise this is comming from startup activity)
if (Audit_formatter::thd_inst_thread_id(thd) || Audit_formatter::thd_inst_query_id(thd))
if ( (before_after_mode == AUDIT_BEFORE || before_after_mode == AUDIT_BOTH)
&& (Audit_formatter::thd_inst_thread_id(thd)
|| Audit_formatter::thd_inst_query_id(thd)))
{
ThdSesData thd_data (thd);
audit(&thd_data);
@ -647,7 +694,7 @@ static void audit_post_execute(THD * thd)
// query events are audited by mysql execute command
if (Audit_formatter::thd_inst_command(thd) != COM_QUERY)
{
ThdSesData ThdData (thd);
ThdSesData ThdData(thd);
if (strcasestr(ThdData.getCmdName(), "show_fields") == NULL)
{
audit(&ThdData);
@ -656,7 +703,6 @@ static void audit_post_execute(THD * thd)
}
/*
Plugin descriptor
*/
@ -723,7 +769,7 @@ static int audit_notify(THD *thd, mysql_event_class_t event_class,
// in pre-authenticate, user info etc is empty. don't log it
&& event_connection->event_subclass != MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE
#endif
)
)
{
ThdSesData ThdData(thd);
audit(&ThdData);
@ -765,6 +811,13 @@ static struct st_mysql_audit audit_plugin =
// some extern definitions which are not in include files
extern void log_slow_statement(THD *thd);
extern int mysql_execute_command(THD *thd);
#if defined(MARIADB_BASE_VERSION)
extern void end_connection(THD *thd);
static int (*trampoline_end_connection)(THD *thd) = NULL;
static unsigned int trampoline_end_connection_size = 0;
#endif
#if MYSQL_VERSION_ID >= 50505
// in 5.5 builtins is named differently
#define mysqld_builtins mysql_mandatory_plugins
@ -828,6 +881,15 @@ void remove_hot_functions()
target_function = (void*)
(int (*)(THD *thd, bool first_level)) &mysql_execute_command;
#endif
#if defined(MARIADB_BASE_VERSION)
target_function = (void*) end_connection;
remove_hot_patch_function(target_function,
(void*) trampoline_end_connection,
trampoline_end_connection_size, true);
trampoline_end_connection_size = 0;
#endif
remove_hot_patch_function(target_function,
(void*) trampoline_mysql_execute_command,
trampoline_mysql_execute_size, true);
@ -842,7 +904,12 @@ int is_remove_patches(ThdSesData *pThdData)
LEX *pLex = Audit_formatter::thd_lex(pThdData->getTHD());
if (pThdData->getTHD() && pLex != NULL && strncasecmp(cmd, sUninstallPlugin, strlen(sUninstallPlugin)) == 0)
{
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
LEX_STRING Lex_comment = *(LEX_STRING*)(((unsigned char *) pLex) + Audit_formatter::thd_offsets.lex_comment);
#else
Sql_cmd_uninstall_plugin *up = Audit_formatter::lex_sql_cmd(pLex);
LEX_STRING Lex_comment = *(LEX_STRING*)(((unsigned char *) up) + Audit_formatter::thd_offsets.uninstall_cmd_comment);
#endif
if (strncasecmp(Lex_comment.str, "AUDIT", 5) == 0)
{
if (! uninstall_plugin_enable)
@ -898,13 +965,18 @@ static int audit_mysql_execute_command(THD *thd)
ThdSesData thd_data(thd);
const char *cmd = thd_data.getCmdName();
if (strcasestr(cmd, "alter") != NULL ||
strcasestr(cmd, "drop") != NULL ||
strcasestr(cmd, "create") != NULL ||
strcasestr(cmd, "truncate") != NULL ||
strcasestr(cmd, "rename") != NULL)
do_delay(& thd_data);
if (before_after_mode == AUDIT_BEFORE || before_after_mode == AUDIT_BOTH)
{
audit(&thd_data);
if (strcasestr(cmd, "alter") != NULL ||
strcasestr(cmd, "drop") != NULL ||
strcasestr(cmd, "create") != NULL ||
strcasestr(cmd, "truncate") != NULL ||
strcasestr(cmd, "rename") != NULL)
{
audit(&thd_data);
}
}
int res;
@ -938,7 +1010,11 @@ static int audit_mysql_execute_command(THD *thd)
}
}
audit(&thd_data);
if (before_after_mode == AUDIT_AFTER || before_after_mode == AUDIT_BOTH)
{
audit(&thd_data);
}
if (pThdPrintedList && pThdPrintedList->cur_index > 0)
{
@ -987,6 +1063,24 @@ static bool audit_acl_authenticate(THD *thd, uint connect_errors, uint com_chang
}
#endif
#if defined(MARIADB_BASE_VERSION)
static void audit_end_connection(THD *thd)
{
#if MYSQL_VERSION_ID < 50600
ThdSesData thd_data(thd);
thd_data.setCmdName("Quit");
audit(&thd_data);
#endif
PeerInfo *peer = (PeerInfo *) THDVAR(thd, peer_info);
if (peer)
{
free(peer);
THDVAR(thd, peer_info) = 0;
}
trampoline_end_connection(thd);
}
#endif
static bool parse_thd_offsets_string (char *poffsets_string)
{
char offset_str[2048] = {0};
@ -1053,6 +1147,14 @@ static bool parse_thd_offsets_string (char *poffsets_string)
static bool validate_offsets(const ThdOffsets *offset)
{
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
if (offset->lex_m_sql_command == 0 || offset->uninstall_cmd_comment == 0)
{
sql_print_error("%s Offsets: missing offsets for checking 'uninstall plugin'", log_prefix);
return false;
}
#endif
// check that offsets are actually correct. We use a buff of memory as a dummy THD (32K is high enough)
char buf[32*1024] = {0};
THD *thd = (THD *)buf;
@ -1219,7 +1321,7 @@ static int setup_offsets()
if (parse_thd_offsets_string(offsets_string))
{
sql_print_information ("%s setup_offsets Audit_formatter::thd_offsets values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu", log_prefix,
sql_print_information ("%s setup_offsets Audit_formatter::thd_offsets values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu", log_prefix,
Audit_formatter::thd_offsets.query_id,
Audit_formatter::thd_offsets.thread_id,
Audit_formatter::thd_offsets.main_security_ctx,
@ -1236,7 +1338,12 @@ static int setup_offsets()
Audit_formatter::thd_offsets.pfs_connect_attrs,
Audit_formatter::thd_offsets.pfs_connect_attrs_length,
Audit_formatter::thd_offsets.pfs_connect_attrs_cs,
Audit_formatter::thd_offsets.net
Audit_formatter::thd_offsets.net,
Audit_formatter::thd_offsets.lex_m_sql_command,
Audit_formatter::thd_offsets.uninstall_cmd_comment,
Audit_formatter::thd_offsets.found_rows,
Audit_formatter::thd_offsets.sent_row_count,
Audit_formatter::thd_offsets.row_count_func
);
if (! validate_offsets(&Audit_formatter::thd_offsets))
@ -1331,10 +1438,31 @@ static int setup_offsets()
{
decoffsets.net -= dec;
}
if (decoffsets.lex_m_sql_command)
{
decoffsets.lex_m_sql_command -= dec;
}
if (decoffsets.uninstall_cmd_comment)
{
decoffsets.uninstall_cmd_comment -= dec;
}
if (decoffsets.found_rows)
{
decoffsets.found_rows -= dec;
}
if (decoffsets.sent_row_count)
{
decoffsets.sent_row_count -= dec;
}
if (decoffsets.row_count_func)
{
decoffsets.row_count_func -= dec;
}
if (validate_offsets(&decoffsets))
{
Audit_formatter::thd_offsets = decoffsets;
sql_print_information("%s Using decrement (%zu) offsets from offset version: %s (%s) values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu",
sql_print_information("%s Using decrement (%zu) offsets from offset version: %s (%s) values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu",
log_prefix, dec, offset->version, offset->md5digest,
Audit_formatter::thd_offsets.query_id,
Audit_formatter::thd_offsets.thread_id,
@ -1351,7 +1479,13 @@ static int setup_offsets()
Audit_formatter::thd_offsets.pfs_connect_attrs,
Audit_formatter::thd_offsets.pfs_connect_attrs_length,
Audit_formatter::thd_offsets.pfs_connect_attrs_cs,
Audit_formatter::thd_offsets.net);
Audit_formatter::thd_offsets.net,
Audit_formatter::thd_offsets.lex_m_sql_command,
Audit_formatter::thd_offsets.uninstall_cmd_comment,
Audit_formatter::thd_offsets.found_rows,
Audit_formatter::thd_offsets.sent_row_count,
Audit_formatter::thd_offsets.row_count_func
);
DBUG_RETURN(0);
}
@ -1368,7 +1502,7 @@ static int setup_offsets()
if (validate_offsets(&incoffsets))
{
Audit_formatter::thd_offsets = incoffsets;
sql_print_information("%s Using increment (%zu) offsets from offset version: %s (%s) values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu",
sql_print_information("%s Using increment (%zu) offsets from offset version: %s (%s) values: %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu",
log_prefix, inc, offset->version, offset->md5digest,
Audit_formatter::thd_offsets.query_id,
Audit_formatter::thd_offsets.thread_id,
@ -1385,7 +1519,13 @@ static int setup_offsets()
Audit_formatter::thd_offsets.pfs_connect_attrs,
Audit_formatter::thd_offsets.pfs_connect_attrs_length,
Audit_formatter::thd_offsets.pfs_connect_attrs_cs,
Audit_formatter::thd_offsets.net);
Audit_formatter::thd_offsets.net,
Audit_formatter::thd_offsets.lex_m_sql_command,
Audit_formatter::thd_offsets.uninstall_cmd_comment,
Audit_formatter::thd_offsets.found_rows,
Audit_formatter::thd_offsets.sent_row_count,
Audit_formatter::thd_offsets.row_count_func
);
DBUG_RETURN(0);
}
}
@ -1862,11 +2002,11 @@ static int audit_plugin_init(void *p)
{
record_objs_string_update_extended(NULL, NULL, NULL, &record_objs_string);
}
if (NULL != password_masking_cmds_string)
if (password_masking_cmds_string != NULL)
{
password_masking_cmds_string_update(NULL, NULL, NULL, &password_masking_cmds_string);
}
if (NULL != password_masking_regex_string)
if (password_masking_regex_string != NULL)
{
password_masking_regex_string_update(NULL, NULL, NULL, &password_masking_regex_string);
}
@ -2035,6 +2175,15 @@ static int audit_plugin_init(void *p)
DBUG_RETURN(1);
}
#if defined(MARIADB_BASE_VERSION)
target_function = (void*) end_connection;
if (do_hot_patch((void **)&trampoline_end_connection, &trampoline_end_connection_size,
(void *)target_function, (void *)audit_end_connection, "end_connection"))
{
DBUG_RETURN(1);
}
#endif
if (set_com_status_vars_array () != 0)
{
DBUG_RETURN(1);
@ -2150,6 +2299,7 @@ static MYSQL_SYSVAR_STR(json_log_file, json_file_handler.m_io_dest,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
"AUDIT plugin json log file name",
NULL, NULL, "mysql-audit.json");
static MYSQL_SYSVAR_LONG(json_file_bufsize, json_file_handler.m_bufsize,
PLUGIN_VAR_RQCMDARG,
"AUDIT plugin json log file buffer size. Buffer size in bytes (larger size may improve performance). 0 = use default size, 1 = no buffering. If changed during runtime need to perform a flush for the new value to take affect.",
@ -2245,7 +2395,7 @@ static MYSQL_SYSVAR_STR(password_masking_cmds, password_masking_cmds_string,
"AUDIT plugin commands to apply password masking regex to, comma separated",
NULL, password_masking_cmds_string_update,
// set password is recorded as set_option
"CREATE_USER,GRANT,SET_OPTION,SLAVE_START,CREATE_SERVER,ALTER_SERVER,CHANGE_MASTER");
"CREATE_USER,GRANT,SET_OPTION,SLAVE_START,CREATE_SERVER,ALTER_SERVER,CHANGE_MASTER,UPDATE");
static MYSQL_SYSVAR_STR(whitelist_users, whitelist_users_string,
PLUGIN_VAR_RQCMDARG,
"AUDIT plugin whitelisted users whose queries are not recorded, comma separated",
@ -2256,6 +2406,26 @@ static MYSQL_SYSVAR_STR(record_objs, record_objs_string,
"AUDIT plugin objects to record, comma separated. If set then only queries containing these objects will be recorded.",
NULL, record_objs_string_update_extended, NULL);
static const char *before_after_names[] =
{
"after", "before", "both", NullS
};
TYPELIB before_after_typelib =
{
array_elements(before_after_names) - 1,
"before_after_typelib",
before_after_names,
NULL
};
static MYSQL_SYSVAR_ENUM(before_after, before_after_mode,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
"AUDIT plugin log statements before execution, after, or both. Default is 'after'",
NULL, NULL, 0,
& before_after_typelib);
/*
* Plugin system vars
*/
@ -2296,6 +2466,7 @@ static struct st_mysql_sys_var* audit_system_variables[] =
MYSQL_SYSVAR(set_peer_cred),
MYSQL_SYSVAR(peer_is_uds),
MYSQL_SYSVAR(peer_info),
MYSQL_SYSVAR(before_after),
NULL
};