* 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
parent
4fbcae3a81
commit
ba21262b81
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
1222
src/audit_offsets.cc
1222
src/audit_offsets.cc
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue