You've already forked mysql-audit
mirror of
https://github.com/trellix-enterprise/mysql-audit.git
synced 2025-12-14 18:14:01 +08:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edbed38f42 | ||
|
|
72af9c00f4 | ||
|
|
637d30a568 | ||
|
|
a52594c59c | ||
|
|
cb2cbc605c | ||
|
|
52c611cef8 | ||
|
|
6ea0b6bd15 | ||
|
|
2d0a23c73d | ||
|
|
bca3715fb5 | ||
|
|
d9786405af | ||
|
|
286197fe6d | ||
|
|
40dc1e7ff7 | ||
|
|
969d0b481a | ||
|
|
e7d07fc1fe | ||
|
|
e6fd9d8b6f | ||
|
|
8e56548468 | ||
|
|
e03dcc1cec | ||
|
|
8370847e9b | ||
|
|
4b78009cb3 | ||
|
|
f4a3411ccd |
@@ -42,7 +42,7 @@ Source code is available at: https://github.com/mcafee/mysql-audit
|
||||
|
||||
License
|
||||
-------------------------------
|
||||
Copyright (C) 2016 McAfee, Inc.
|
||||
Copyright (C) 2011-2018 McAfee, LLC.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
||||
General Public License as published by the Free Software Foundation; version 2 of the License.
|
||||
|
||||
@@ -52,6 +52,8 @@ first (see www.boost.org). In such a case, use:
|
||||
|
||||
Note: For MariaDB use: cmake . -DBUILD_CONFIG=mysql_release
|
||||
|
||||
Note: For Percona`s MySQL use: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_CONFIG=mysql_release -DWITH_BOOST=boost_1_59_0 .
|
||||
|
||||
Note: to speed things up it is possible to build just the following directories:
|
||||
libservices
|
||||
extra
|
||||
@@ -63,6 +65,8 @@ chmod +x bootstrap.sh
|
||||
CXX='gcc -static-libgcc' CC='gcc -static-libgcc' ./configure --with-mysql=mysql-5.x.x --with-mysql-libservices=mysql-5.x.x/libservices/libmysqlservices.a
|
||||
make
|
||||
|
||||
Note: For Percona`s MySQL define also PERCONA_BUILD=true variable, like "PERCONA_BUILD=true ./configure..."
|
||||
|
||||
==== Compiling with make =====
|
||||
|
||||
Go to top source dir and run:
|
||||
|
||||
@@ -128,6 +128,10 @@ CPPFLAGS="$CPPFLAGS -DMYSQL_AUDIT_PLUGIN_VERSION='\"$MYSQL_AUDIT_PLUGIN_VERSION\
|
||||
CPPFLAGS="$CPPFLAGS -DMYSQL_AUDIT_PLUGIN_REVISION='\"$MYSQL_AUDIT_PLUGIN_REVISION\"'"
|
||||
CPPFLAGS="$CPPFLAGS '-DMYSQL_AUDIT_PLUGIN_SYMBOL_VERSION()=extern const char audit_plugin_version_$MYSQL_AUDIT_PLUGIN_SYMBOL_VERSION'"
|
||||
|
||||
# Percona`s MySQL macro
|
||||
if [[ "$PERCONA_BUILD" = "true" ]]; then
|
||||
CPPFLAGS="$CPPFLAGS -DPERCONA_BUILD" # Percona`s build macro, used to distinguish between MySQL/MariaDB build VS Percona build
|
||||
fi
|
||||
|
||||
#subst the relevant variables
|
||||
AC_SUBST(CPPFLAGS)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#define AUDIT_LOG_PREFIX "Audit Plugin:"
|
||||
#define AUDIT_LOG_PREFIX "McAfee Audit Plugin:"
|
||||
#define AUDIT_PROTOCOL_VERSION "1.0"
|
||||
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
|
||||
@@ -101,6 +101,9 @@ typedef struct ThdOffsets {
|
||||
OFFSET found_rows;
|
||||
OFFSET sent_row_count;
|
||||
OFFSET row_count_func;
|
||||
OFFSET stmt_da;
|
||||
OFFSET da_status;
|
||||
OFFSET da_sql_errno;
|
||||
} ThdOffsets;
|
||||
|
||||
/*
|
||||
@@ -145,6 +148,9 @@ public:
|
||||
const char *getOsUser() const;
|
||||
const int getPort() const { return m_port; }
|
||||
const StatementSource getStatementSource() const { return m_source; }
|
||||
void storeErrorCode();
|
||||
void setErrorCode(uint code) { m_errorCode = code; m_setErrorCode = true; }
|
||||
bool getErrorCode(uint & code) const { code = m_errorCode; return m_setErrorCode; }
|
||||
/**
|
||||
* Start fetching objects. Return true if there are objects available.
|
||||
*/
|
||||
@@ -178,6 +184,9 @@ private:
|
||||
|
||||
int m_port; // TCP port of remote side
|
||||
|
||||
uint m_errorCode;
|
||||
bool m_setErrorCode;
|
||||
|
||||
protected:
|
||||
ThdSesData(const ThdSesData&);
|
||||
ThdSesData &operator =(const ThdSesData&);
|
||||
@@ -218,6 +227,8 @@ public:
|
||||
static QueryTableInf *getQueryCacheTableList1(THD *thd);
|
||||
|
||||
// utility functions for fetching thd stuff
|
||||
static int thd_client_port(THD *thd);
|
||||
|
||||
static inline my_thread_id thd_inst_thread_id(THD *thd)
|
||||
{
|
||||
return *(my_thread_id *) (((unsigned char *) thd)
|
||||
@@ -276,7 +287,9 @@ public:
|
||||
static inline const char *thd_inst_main_security_ctx_host(THD *thd)
|
||||
{
|
||||
Security_context *sctx = thd_inst_main_security_ctx(thd);
|
||||
if (! Audit_formatter::thd_offsets.sec_ctx_ip) // check ip to understand if set as host is first and may actually be set to 0
|
||||
// check ip to understand if set, as host is first in the struct and may actually be set to 0
|
||||
// we expect to have offsets for both ip and host or for neither of them
|
||||
if (! Audit_formatter::thd_offsets.sec_ctx_ip)
|
||||
{
|
||||
// interface changed in 5.5.34 and 5.6.14 and up host changed to get_host()
|
||||
// see: http://bazaar.launchpad.net/~mysql/mysql-server/5.5/revision/4407.1.1/sql/sql_class.h
|
||||
@@ -335,15 +348,9 @@ public:
|
||||
return sctx->priv_user().str;
|
||||
#endif
|
||||
}
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
// in 5.1.x priv_user is a pointer
|
||||
return *(const char **) (((unsigned char *) sctx)
|
||||
+ Audit_formatter::thd_offsets.sec_ctx_priv_user);
|
||||
#else
|
||||
// in 5.5 and up priv_user is an array (char priv_user[USERNAME_LENGTH])
|
||||
return (const char *) (((unsigned char *) sctx)
|
||||
+ Audit_formatter::thd_offsets.sec_ctx_priv_user);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int thd_inst_command(THD *thd)
|
||||
@@ -387,23 +394,19 @@ public:
|
||||
|
||||
static inline const char * pfs_connect_attrs(void * pfs)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs)
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs || pfs == NULL)
|
||||
{
|
||||
//no offsets - return null
|
||||
return NULL;
|
||||
}
|
||||
const char **pfs_pointer = (const char **) (((unsigned char *) pfs) + Audit_formatter::thd_offsets.pfs_connect_attrs);
|
||||
if (pfs_pointer == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return *pfs_pointer;
|
||||
}
|
||||
|
||||
static inline uint pfs_connect_attrs_length(void * pfs)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_length)
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_length || pfs == NULL)
|
||||
{
|
||||
//no offsets - return 0
|
||||
return 0;
|
||||
@@ -413,7 +416,7 @@ public:
|
||||
|
||||
static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_cs)
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_cs || pfs == NULL)
|
||||
{
|
||||
//no offsets - return null
|
||||
return NULL;
|
||||
@@ -475,29 +478,6 @@ static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
|
||||
return sock;
|
||||
}
|
||||
|
||||
static inline int thd_client_port(THD *thd)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.net)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
NET *net = ((NET *) (((unsigned char *) thd)
|
||||
+ Audit_formatter::thd_offsets.net));
|
||||
|
||||
// get the port for the remote end
|
||||
int port = -1;
|
||||
|
||||
if (net->vio != NULL) // MySQL 5.7.17 - this can happen. :-(
|
||||
{
|
||||
struct sockaddr_in *in;
|
||||
|
||||
in = (struct sockaddr_in *) & net->vio->remote;
|
||||
port = in->sin_port;
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
static inline ulonglong thd_found_rows(THD *thd)
|
||||
{
|
||||
if (Audit_formatter::thd_offsets.found_rows == 0)
|
||||
@@ -537,6 +517,47 @@ static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
|
||||
return *rows;
|
||||
}
|
||||
|
||||
static inline bool thd_error_code(THD *thd, uint & code)
|
||||
{
|
||||
#if MYSQL_VERSION_ID >= 50534
|
||||
|
||||
if ( Audit_formatter::thd_offsets.stmt_da == 0 ||
|
||||
Audit_formatter::thd_offsets.da_status == 0 ||
|
||||
Audit_formatter::thd_offsets.da_sql_errno == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Diagnostics_area **stmt_da = ((Diagnostics_area **) (((unsigned char *) thd)
|
||||
+ Audit_formatter::thd_offsets.stmt_da));
|
||||
|
||||
enum Diagnostics_area::enum_diagnostics_status *status =
|
||||
((enum Diagnostics_area::enum_diagnostics_status *) (((unsigned char *) (*stmt_da))
|
||||
+ Audit_formatter::thd_offsets.da_status));
|
||||
|
||||
uint *sql_errno = ((uint *) (((unsigned char *) (*stmt_da))
|
||||
+ Audit_formatter::thd_offsets.da_sql_errno));
|
||||
|
||||
if (*status == Diagnostics_area::DA_OK ||
|
||||
*status == Diagnostics_area::DA_EOF )
|
||||
{
|
||||
code = 0;
|
||||
return true;
|
||||
}
|
||||
else if (*status == Diagnostics_area::DA_ERROR)
|
||||
{
|
||||
code = *sql_errno;
|
||||
return true;
|
||||
}
|
||||
else // DA_EMPTY, DA_DISABLE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
|
||||
static inline Sql_cmd_uninstall_plugin* lex_sql_cmd(LEX *lex)
|
||||
{
|
||||
@@ -899,7 +920,8 @@ class Audit_socket_handler: public Audit_io_handler {
|
||||
public:
|
||||
|
||||
Audit_socket_handler() :
|
||||
m_vio(NULL), m_connect_timeout(1)
|
||||
m_vio(NULL), m_connect_timeout(1), m_write_timeout(0),
|
||||
m_log_with_error_severity(false)
|
||||
{
|
||||
m_io_type = "socket";
|
||||
}
|
||||
@@ -922,6 +944,8 @@ public:
|
||||
void close();
|
||||
|
||||
int open(const char *io_dest, bool log_errors);
|
||||
|
||||
unsigned long m_write_timeout; // write timeout in microseconds
|
||||
protected:
|
||||
// override default assignment and copy to protect against creating additional instances
|
||||
Audit_socket_handler & operator=(const Audit_socket_handler&);
|
||||
@@ -930,6 +954,9 @@ protected:
|
||||
// Vio we write to
|
||||
// define as void* so we don't access members directly
|
||||
void *m_vio;
|
||||
|
||||
// log using error severity only the second time same issue occurs
|
||||
bool m_log_with_error_severity;
|
||||
};
|
||||
|
||||
#endif /* AUDIT_HANDLER_H_ */
|
||||
|
||||
@@ -17,12 +17,6 @@
|
||||
#include <my_config.h>
|
||||
#include <mysql_version.h>
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
#include <mysql_priv.h>
|
||||
#else
|
||||
|
||||
// version 5.5.x doesn't contain mysql_priv.h . We need to add the includes provided by it.
|
||||
#if MYSQL_VERSION_ID >= 50505
|
||||
|
||||
// These two are not present in 5.7.9
|
||||
#if MYSQL_VERSION_ID < 50709
|
||||
@@ -44,6 +38,7 @@
|
||||
#include <sql/sql_base.h>
|
||||
#include <sql/sql_table.h>
|
||||
#include <sql/sql_view.h>
|
||||
#include <sql/sql_error.h>
|
||||
|
||||
// TODO: use mysql mutex instead of pthread
|
||||
/*
|
||||
@@ -53,8 +48,6 @@
|
||||
#define pthread_mutex_destroy mysql_mutex_destroy
|
||||
#define pthread_mutex_t mysql_mutex_t
|
||||
*/
|
||||
#endif /* ! if MYSQL_VERSION_ID >= 50505 */
|
||||
#endif /* ! if MYSQL_VERSION_ID < 50505 */
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50709
|
||||
#include <sql/log.h>
|
||||
|
||||
@@ -59,7 +59,7 @@ 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
|
||||
if echo $MYVER | grep -P '^(5\.7|10\.[1-2]|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
|
||||
@@ -110,6 +110,26 @@ else
|
||||
LEX_SQL='printf ", 0, 0"'
|
||||
fi
|
||||
|
||||
# Exit status info 5.5, 5.6, 5.7
|
||||
DA_STATUS="print_offset Diagnostics_area m_status" # 5.5, 5.6, 5.7, mariadb 10.0, 10.1, 10.2
|
||||
DA_SQL_ERRNO="print_offset Diagnostics_area m_sql_errno" # 5.5, 5.6, mariadb 10.0, 10.1, 10.2
|
||||
STMT_DA="print_offset THD m_stmt_da" # 5.6, 5.7, mariadb 10.0, 10.1, 10.2
|
||||
|
||||
if echo $MYVER | grep -P '^(5\.7)' > /dev/null
|
||||
then
|
||||
DA_SQL_ERRNO="print_offset Diagnostics_area m_mysql_errno"
|
||||
elif echo $MYVER | grep -P '^(5\.6|10\.)' > /dev/null
|
||||
then
|
||||
: place holder
|
||||
elif echo $MYVER | grep -P '^(5\.5)' > /dev/null
|
||||
then
|
||||
STMT_DA="print_offset THD stmt_da"
|
||||
else
|
||||
STMT_DA='printf ", 0"'
|
||||
DA_STATUS='printf ", 0"'
|
||||
DA_SQL_ERRNO='printf ", 0"'
|
||||
fi
|
||||
|
||||
cat <<EOF > offsets.gdb
|
||||
set logging on
|
||||
set width 0
|
||||
@@ -136,6 +156,9 @@ $LEX_SQL
|
||||
$FOUND_ROWS
|
||||
$SENT_ROW_COUNT
|
||||
$ROW_COUNT_FUNC
|
||||
$STMT_DA
|
||||
$DA_STATUS
|
||||
$DA_SQL_ERRNO
|
||||
printf "}"
|
||||
EOF
|
||||
|
||||
|
||||
54
plugin-name.txt
Normal file
54
plugin-name.txt
Normal file
@@ -0,0 +1,54 @@
|
||||
Tue, Jun 27, 2017 10:48:38 AM
|
||||
=============================
|
||||
|
||||
By default, the McAfee AUDIT plugin for MySQL* is named "AUDIT" and
|
||||
that is the name you should use when installing the plugin with the SQL
|
||||
"INSTALL PLUGIN" command.
|
||||
|
||||
It is the "AUDIT" name that provides the "audit_" prefix to the plugin's
|
||||
various configuration variables.
|
||||
|
||||
In order to avoid conflict with other vendors' auditing plugins whose
|
||||
names may start with "audit" (such as MySQL's "audit_log" plugin) it
|
||||
is possible to change the name of the McAfee plugin. The steps are
|
||||
as follows:
|
||||
|
||||
1. If you're currently using the McAfee plugin, unload it.
|
||||
|
||||
2. Edit the /usr/bin/mysqld_safe shell script (using the correct location
|
||||
for your system). For MySQL 5.7.9, look for the eval_log_error() function.
|
||||
Before the line that says:
|
||||
|
||||
eval "$cmd"
|
||||
|
||||
add a line like this:
|
||||
|
||||
export MCAFEE_AUDIT_PLUGIN_NAME=MCAFEE # use any name you want
|
||||
|
||||
You can use any name you like, "MCAFEE" is just an example.
|
||||
|
||||
For other MySQL versions, determine where the mysqld daemon is actually
|
||||
started, and set the environment variable right before that.
|
||||
|
||||
3. After restarting MySQL, you will need to load the plugin using the
|
||||
new name. From the MySQL client:
|
||||
|
||||
install plugin MCAFEE soname 'libaudit_plugin.so';
|
||||
|
||||
and/or from /etc/my.cnf:
|
||||
|
||||
[mysqld]
|
||||
plugin-load=MCAFEE=libaudit_plugin.so
|
||||
|
||||
Once you've done that, you must remember that the names of ALL the
|
||||
configuration variables will start with the lowercase version of the
|
||||
name you've chosen. For example, "mcafee_json_log_file" instead of
|
||||
"audit_json_log_file".
|
||||
|
||||
If you previously had various "audit_XXX" variables set in your
|
||||
/etc/my.cnf file, you will need to rename them! Otherwise MySQL will
|
||||
fail to start, with an error about unknown variables.
|
||||
|
||||
That's it! Good luck.
|
||||
|
||||
* Other trademarks and brands may be claimed as the property of others.
|
||||
0
src/MySQLPlugin.map
Executable file → Normal file
0
src/MySQLPlugin.map
Executable file → Normal file
@@ -27,6 +27,11 @@
|
||||
#include <unistd.h>
|
||||
#include "static_assert.h"
|
||||
|
||||
#if MYSQL_VERSION_ID < 50600
|
||||
// for 5.5 and 5.1
|
||||
extern "C" void vio_timeout(Vio *vio,uint which, uint timeout);
|
||||
#endif
|
||||
|
||||
// utility macro to log also with a date as a prefix
|
||||
// FIXME: This is no longer used. Remove?
|
||||
#define log_with_date(f, ...) do {\
|
||||
@@ -111,6 +116,49 @@ const char *Audit_formatter::retrieve_object_type(TABLE_LIST *pObj)
|
||||
return "TABLE";
|
||||
}
|
||||
|
||||
// This routine used to pull the client port out of the thd->net->vio->remote
|
||||
// object, but on MySQL 5.7 the port is zero. So we resort to getting the
|
||||
// underlying fd and using getpeername(2) on it.
|
||||
|
||||
int Audit_formatter::thd_client_port(THD *thd)
|
||||
{
|
||||
int port = -1;
|
||||
int sock = thd_client_fd(thd);
|
||||
|
||||
if (sock < 0)
|
||||
{
|
||||
return port; // shouldn't happen
|
||||
}
|
||||
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
|
||||
// get port of the guy on the other end of our connection
|
||||
if (getpeername(sock, (struct sockaddr *) & addr, & len) < 0)
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
if (addr.ss_family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) & addr;
|
||||
port = ntohs(sin->sin_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in6 *sin = (struct sockaddr_in6 *) & addr;
|
||||
port = ntohs(sin->sin6_port);
|
||||
}
|
||||
|
||||
if (port == 0) // shouldn't happen
|
||||
{
|
||||
port = -1;
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
void Audit_handler::stop_all()
|
||||
{
|
||||
for (size_t i = 0; i < MAX_AUDIT_HANDLERS_NUM; ++i)
|
||||
@@ -465,14 +513,46 @@ int Audit_socket_handler::open(const char *io_dest, bool log_errors)
|
||||
#endif
|
||||
{
|
||||
if (log_errors)
|
||||
{
|
||||
sql_print_warning(
|
||||
"%s unable to connect to socket: %s. err: %s.",
|
||||
AUDIT_LOG_PREFIX, m_io_dest, strerror(errno));
|
||||
|
||||
// The next time this occurs, log as an error
|
||||
m_log_with_error_severity = true;
|
||||
}
|
||||
// Only if issue persist also in second retry, report it by using 'error' severity.
|
||||
else if (m_log_with_error_severity)
|
||||
{
|
||||
sql_print_error(
|
||||
"%s unable to connect to socket: %s. err: %s.",
|
||||
AUDIT_LOG_PREFIX, m_io_dest, strerror(errno));
|
||||
|
||||
m_log_with_error_severity = false;
|
||||
}
|
||||
|
||||
close();
|
||||
return -2;
|
||||
}
|
||||
|
||||
// At this point, connected successfully.
|
||||
// Ensure same behavior in case first time failed but second retry was successful
|
||||
m_log_with_error_severity = false;
|
||||
|
||||
if (m_write_timeout > 0)
|
||||
{
|
||||
int timeout = m_write_timeout / 1000; // milliseconds to seconds, integer dvision
|
||||
if (timeout == 0)
|
||||
{
|
||||
timeout = 1; // round up to 1 second
|
||||
}
|
||||
// we don't check the result of this call since in earlier
|
||||
// versions it returns void
|
||||
//
|
||||
// 1 as the 2nd argument means write timeout
|
||||
vio_timeout((Vio*)m_vio, 1, timeout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -616,7 +696,7 @@ ssize_t Audit_json_formatter::start_msg_format(IWriter *writer)
|
||||
yajl_add_string_val(gen, "msg-type", "header");
|
||||
uint64 ts = my_getsystime() / (10000);
|
||||
yajl_add_uint64(gen, "date", ts);
|
||||
yajl_add_string_val(gen, "audit-version", MYSQL_AUDIT_PLUGIN_VERSION"-"MYSQL_AUDIT_PLUGIN_REVISION);
|
||||
yajl_add_string_val(gen, "audit-version", MYSQL_AUDIT_PLUGIN_VERSION "-" MYSQL_AUDIT_PLUGIN_REVISION);
|
||||
yajl_add_string_val(gen, "audit-protocol-version", AUDIT_PROTOCOL_VERSION);
|
||||
yajl_add_string_val(gen, "hostname", glob_hostname);
|
||||
yajl_add_string_val(gen, "mysql-version", server_version);
|
||||
@@ -848,7 +928,12 @@ ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer
|
||||
(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);
|
||||
// thd_row_count_func() returns signed valiue. Don't assign it to rows directly.
|
||||
longlong row_count = thd_row_count_func(thd);
|
||||
if (row_count > 0)
|
||||
{
|
||||
rows = row_count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -860,6 +945,12 @@ ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer
|
||||
yajl_add_uint64(gen, "rows", rows);
|
||||
}
|
||||
|
||||
uint code;
|
||||
if (pThdData->getErrorCode(code))
|
||||
{
|
||||
yajl_add_uint64(gen, "status", code); // 0 - success, otherwise reports specific errno
|
||||
}
|
||||
|
||||
yajl_add_string_val(gen, "cmd", cmd);
|
||||
|
||||
// get objects
|
||||
@@ -989,7 +1080,7 @@ 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_source(source)
|
||||
m_port(-1), m_source(source), m_errorCode(0), m_setErrorCode(false)
|
||||
{
|
||||
m_CmdName = retrieve_command (m_pThd, m_isSqlCmd);
|
||||
m_UserName = retrieve_user (m_pThd);
|
||||
@@ -1002,6 +1093,15 @@ ThdSesData::ThdSesData(THD *pTHD, StatementSource source)
|
||||
}
|
||||
}
|
||||
|
||||
void ThdSesData::storeErrorCode()
|
||||
{
|
||||
uint code = 0;
|
||||
if (Audit_formatter::thd_error_code(m_pThd, code))
|
||||
{
|
||||
setErrorCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
bool ThdSesData::startGetObjects()
|
||||
{
|
||||
// reset vars as this may be called multiple times
|
||||
|
||||
1931
src/audit_offsets.cc
1931
src/audit_offsets.cc
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@
|
||||
#include "md5.h"
|
||||
#endif
|
||||
|
||||
static const char *PLUGIN_NAME = "AUDIT";
|
||||
|
||||
|
||||
/*
|
||||
@@ -103,12 +104,12 @@ static char password_masking_regex_buff[4096] = {0};
|
||||
|
||||
static const char default_pw_masking_regex[] =
|
||||
// identified by [password] '***'
|
||||
"identified"_COMMENT_SPACE_"by"_COMMENT_SPACE_"(?:password)?"_COMMENT_SPACE_ _QUOTED_PSW_
|
||||
"identified" _COMMENT_SPACE_ "by" _COMMENT_SPACE_ "(?:password)?" _COMMENT_SPACE_ _QUOTED_PSW_
|
||||
// password function
|
||||
"|password"_COMMENT_SPACE_"\\("_COMMENT_SPACE_ _QUOTED_PSW_ _COMMENT_SPACE_"\\)"
|
||||
"|password" _COMMENT_SPACE_ "\\(" _COMMENT_SPACE_ _QUOTED_PSW_ _COMMENT_SPACE_ "\\)"
|
||||
// Used at: CHANGE MASTER TO MASTER_PASSWORD='new3cret', SET PASSWORD [FOR user] = 'hash', password 'user_pass';
|
||||
"|password"_COMMENT_SPACE_"(?:for"_COMMENT_SPACE_"\\S+?)?"_COMMENT_SPACE_"="_COMMENT_SPACE_ _QUOTED_PSW_
|
||||
"|password"_COMMENT_SPACE_ _QUOTED_PSW_
|
||||
"|password" _COMMENT_SPACE_ "(?:for" _COMMENT_SPACE_ "\\S+?)?" _COMMENT_SPACE_ "=" _COMMENT_SPACE_ _QUOTED_PSW_
|
||||
"|password" _COMMENT_SPACE_ _QUOTED_PSW_
|
||||
// federated engine create table with connection. See: http://dev.mysql.com/doc/refman/5.5/en/federated-create-connection.html
|
||||
// commented out as federated engine is disabled by default
|
||||
// "|ENGINE"_COMMENT_SPACE_"="_COMMENT_SPACE_"FEDERATED"_COMMENT_SPACE_".*CONNECTION"_COMMENT_SPACE_"="_COMMENT_SPACE_"[\'|\"]\\S+?://\\S+?:(?<psw>.*)@\\S+[\'|\"]"
|
||||
@@ -120,6 +121,9 @@ static char json_socket_name_buff[1024] = {0};
|
||||
// Define default port in case user configured out port and socket in my.cnf (bug 1151389)
|
||||
#define MYSQL_DEFAULT_PORT 3306
|
||||
|
||||
// Default value for write timeout in microseconds
|
||||
#define DEFAULT_WRITE_TIMEOUT 1000 // milliseconds --> 1 second - MySQL API uses seconds
|
||||
|
||||
/**
|
||||
* The trampoline functions we use. Will be set to point to allocated mem.
|
||||
*/
|
||||
@@ -129,12 +133,6 @@ static unsigned int trampoline_mysql_execute_size = 0;
|
||||
#if MYSQL_VERSION_ID < 50600
|
||||
static void (*trampoline_log_slow_statement)(THD *thd) = NULL;
|
||||
static unsigned int trampoline_log_slow_statement_size = 0;
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
static int (*trampoline_check_user)(THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, bool check_count) = NULL;
|
||||
static unsigned int trampoline_check_user_size = 0;
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
static bool (*trampoline_acl_authenticate)(THD *thd, uint connect_errors, uint com_change_user_pkt_len) = NULL;
|
||||
static unsigned int trampoline_acl_authenticate_size = 0;
|
||||
#endif
|
||||
@@ -260,7 +258,7 @@ static void initializePeerCredentials(THD *pThd)
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Is it a Unix Domain socket?
|
||||
// Is it a socket?
|
||||
if (fstat(sock, &sbuf) < 0)
|
||||
{
|
||||
goto done;
|
||||
@@ -271,17 +269,9 @@ static void initializePeerCredentials(THD *pThd)
|
||||
goto done;
|
||||
}
|
||||
|
||||
// At this point, we know we have a Unix domain socket.
|
||||
if (! json_formatter.m_write_socket_creds)
|
||||
{
|
||||
// We need to set this, so that we don't send the
|
||||
// client port, but we don't bother getting the command
|
||||
// name and user name, since they won't be sent.
|
||||
THDVAR(pThd, peer_is_uds) = TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Do a SO_PEERCRED
|
||||
// Note, this seems to work on any socket, but won't bring valid
|
||||
// info except for a Unix Domain Socket. Sigh.
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) < 0)
|
||||
{
|
||||
goto done;
|
||||
@@ -292,6 +282,21 @@ static void initializePeerCredentials(THD *pThd)
|
||||
goto done;
|
||||
}
|
||||
|
||||
// At this point, we know we have a socket but we don't know what type.
|
||||
if (! json_formatter.m_write_socket_creds)
|
||||
{
|
||||
// We need to set this, so that we don't send the
|
||||
// client port, but we don't bother getting the command
|
||||
// name and user name, since they won't be sent.
|
||||
THDVAR(pThd, peer_is_uds) = (cred.pid != 0);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (cred.pid == 0)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (peer == NULL)
|
||||
{
|
||||
goto done;
|
||||
@@ -305,7 +310,14 @@ static void initializePeerCredentials(THD *pThd)
|
||||
if (pwbuf == NULL)
|
||||
{
|
||||
// no name, send UID
|
||||
snprintf(buf, sizeof(buf) - 1, "%lu", (unsigned long) cred.uid);
|
||||
if (cred.uid >= 0)
|
||||
{
|
||||
snprintf(buf, sizeof(buf) - 1, "%lu", (unsigned long) cred.uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(buf, "[unknown]");
|
||||
}
|
||||
username = buf;
|
||||
}
|
||||
else
|
||||
@@ -370,7 +382,7 @@ PeerInfo *retrieve_peerinfo(THD *thd)
|
||||
{
|
||||
PeerInfo *peer = (PeerInfo *) THDVAR(thd, peer_info);
|
||||
|
||||
if (THDVAR(thd, peer_is_uds) && peer != NULL);
|
||||
if (THDVAR(thd, peer_is_uds) && peer != NULL)
|
||||
{
|
||||
return peer;
|
||||
}
|
||||
@@ -379,20 +391,25 @@ PeerInfo *retrieve_peerinfo(THD *thd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int check_array(const char *cmds[],const char *array, int length)
|
||||
// cmds[] is a list of "commands" (names, commands, whatever) to
|
||||
// check against the list stored in `array'. Although declared
|
||||
// here as simple `char *', the `array' is actually a two-dimensional
|
||||
// array where each element is `length' bytes long. (An array of
|
||||
// strings.)
|
||||
//
|
||||
// We loop over the array and for each element see if it's also
|
||||
// in `cmds'. If so, we return 1, otherwise we return 0.
|
||||
//
|
||||
// This should really be of type bool and return true/false.
|
||||
static int check_array(const char *cmds[], const char *array, int length)
|
||||
{
|
||||
for (int k = 0; array[k * length] !='\0';k++)
|
||||
{
|
||||
const char *elem = array + (k * length);
|
||||
for (int q = 0; cmds[q] != NULL; q++)
|
||||
{
|
||||
const char *cmd = cmds[q];
|
||||
int j = 0;
|
||||
while (array[k * length + j] != '\0' && cmd[j] != '\0'
|
||||
&& array[k * length + j] == tolower(cmd[j]))
|
||||
{
|
||||
j++;
|
||||
}
|
||||
if (array[k * length + j] == '\0' && j != 0)
|
||||
if (strcasecmp(cmd, elem) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -579,22 +596,16 @@ QueryTableInf *Audit_formatter::getQueryCacheTableList1(THD *thd)
|
||||
}
|
||||
|
||||
static bool (*trampoline_check_table_access)(THD *thd, ulong want_access,TABLE_LIST *tables,
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID >= 50505
|
||||
bool any_combination_of_privileges_will_do,
|
||||
#endif
|
||||
uint number, bool no_errors) = NULL;
|
||||
|
||||
static bool audit_check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID >= 50505
|
||||
bool any_combination_of_privileges_will_do,
|
||||
#endif
|
||||
uint number, bool no_errors)
|
||||
{
|
||||
TABLE_LIST *pTables;
|
||||
bool res = trampoline_check_table_access(thd, want_access, tables,
|
||||
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID >= 50505
|
||||
any_combination_of_privileges_will_do,
|
||||
#endif
|
||||
number, no_errors);
|
||||
if (!res && tables)
|
||||
{
|
||||
@@ -647,8 +658,9 @@ static int audit_send_result_to_client(Query_cache *pthis, THD *thd, const LEX_
|
||||
#endif
|
||||
if (res)
|
||||
{
|
||||
ThdSesData thd_data(thd, ThdSesData::SOURCE_QUERY_CACHE);
|
||||
audit(&thd_data);
|
||||
ThdSesData thdData(thd, ThdSesData::SOURCE_QUERY_CACHE);
|
||||
thdData.storeErrorCode();
|
||||
audit(&thdData);
|
||||
}
|
||||
THDVAR(thd, query_cache_table_list) = 0;
|
||||
return res;
|
||||
@@ -679,7 +691,8 @@ static int audit_open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint f
|
||||
&& (Audit_formatter::thd_inst_thread_id(thd)
|
||||
|| Audit_formatter::thd_inst_query_id(thd)))
|
||||
{
|
||||
ThdSesData thd_data (thd);
|
||||
ThdSesData thd_data(thd);
|
||||
// This is before something is run, so no need to set exit status
|
||||
audit(&thd_data);
|
||||
}
|
||||
return res;
|
||||
@@ -694,10 +707,11 @@ 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);
|
||||
if (strcasestr(ThdData.getCmdName(), "show_fields") == NULL)
|
||||
ThdSesData thdData(thd);
|
||||
if (strcasestr(thdData.getCmdName(), "show_fields") == NULL)
|
||||
{
|
||||
audit(&ThdData);
|
||||
thdData.storeErrorCode();
|
||||
audit(&thdData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -761,6 +775,7 @@ static int audit_notify(THD *thd, mysql_event_class_t event_class,
|
||||
case ER_ACCOUNT_HAS_BEEN_LOCKED:
|
||||
#endif
|
||||
ThdData.setCmdName("Failed Login");
|
||||
ThdData.setErrorCode(event_general->general_error_code);
|
||||
audit(&ThdData);
|
||||
break;
|
||||
default:
|
||||
@@ -827,12 +842,6 @@ 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
|
||||
#endif
|
||||
extern struct st_mysql_plugin *mysqld_builtins[];
|
||||
|
||||
void remove_hot_functions()
|
||||
{
|
||||
void * target_function = NULL;
|
||||
@@ -842,14 +851,6 @@ void remove_hot_functions()
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_log_slow_statement, trampoline_log_slow_statement_size, true);
|
||||
trampoline_log_slow_statement_size = 0;
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
target_function = (void *) check_user;
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_check_user, trampoline_check_user_size, true);
|
||||
trampoline_check_user_size = 0;
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
target_function = (void *) acl_authenticate;
|
||||
remove_hot_patch_function(target_function,
|
||||
(void*) trampoline_acl_authenticate, trampoline_acl_authenticate_size, true);
|
||||
@@ -919,11 +920,13 @@ int is_remove_patches(ThdSesData *pThdData)
|
||||
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 (strncasecmp(Lex_comment.str, PLUGIN_NAME, strlen(PLUGIN_NAME)) == 0)
|
||||
{
|
||||
char msgBuffer[200];
|
||||
if (! uninstall_plugin_enable)
|
||||
{
|
||||
my_message(ER_NOT_ALLOWED_COMMAND, "Uninstall AUDIT plugin disabled", MYF(0));
|
||||
sprintf(msgBuffer, "Uninstall %s plugin disabled", PLUGIN_NAME);
|
||||
my_message(ER_NOT_ALLOWED_COMMAND, msgBuffer, MYF(0));
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -933,7 +936,8 @@ int is_remove_patches(ThdSesData *pThdData)
|
||||
if (! called_once)
|
||||
{
|
||||
called_once = true;
|
||||
my_message(WARN_PLUGIN_BUSY, "Uninstall AUDIT plugin must be called again to complete", MYF(0));
|
||||
sprintf(msgBuffer, "Uninstall %s plugin must be called again to complete", PLUGIN_NAME);
|
||||
my_message(WARN_PLUGIN_BUSY, msgBuffer, MYF(0));
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
@@ -971,10 +975,10 @@ static int audit_mysql_execute_command(THD *thd)
|
||||
}
|
||||
}
|
||||
|
||||
ThdSesData thd_data(thd);
|
||||
const char *cmd = thd_data.getCmdName();
|
||||
ThdSesData thdData(thd);
|
||||
const char *cmd = thdData.getCmdName();
|
||||
|
||||
do_delay(& thd_data);
|
||||
do_delay(& thdData);
|
||||
|
||||
if (before_after_mode == AUDIT_BEFORE || before_after_mode == AUDIT_BOTH)
|
||||
{
|
||||
@@ -984,7 +988,7 @@ static int audit_mysql_execute_command(THD *thd)
|
||||
strcasestr(cmd, "truncate") != NULL ||
|
||||
strcasestr(cmd, "rename") != NULL)
|
||||
{
|
||||
audit(&thd_data);
|
||||
audit(&thdData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -999,7 +1003,7 @@ static int audit_mysql_execute_command(THD *thd)
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (is_remove_patches(&thd_data))
|
||||
switch (is_remove_patches(&thdData))
|
||||
{
|
||||
case 1:
|
||||
// hot patch function were removed and we call the real execute (restored)
|
||||
@@ -1019,10 +1023,11 @@ static int audit_mysql_execute_command(THD *thd)
|
||||
}
|
||||
}
|
||||
|
||||
thdData.storeErrorCode();
|
||||
|
||||
if (before_after_mode == AUDIT_AFTER || before_after_mode == AUDIT_BOTH)
|
||||
{
|
||||
audit(&thd_data);
|
||||
audit(&thdData);
|
||||
}
|
||||
|
||||
if (pThdPrintedList && pThdPrintedList->cur_index > 0)
|
||||
@@ -1044,29 +1049,15 @@ static void audit_log_slow_statement(THD *thd)
|
||||
trampoline_log_slow_statement(thd);
|
||||
audit_post_execute(thd);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
static int audit_check_user(THD *thd, enum enum_server_command command,
|
||||
const char *passwd, uint passwd_len, const char *db,
|
||||
bool check_count)
|
||||
{
|
||||
int res = trampoline_check_user(thd, command, passwd, passwd_len, db, check_count);
|
||||
ThdSesData ThdData(thd);
|
||||
|
||||
audit(&ThdData);
|
||||
|
||||
return (res);
|
||||
}
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
// only for 5.5
|
||||
// in 5.6: we use audit plugin event to get the login event
|
||||
static bool audit_acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len)
|
||||
{
|
||||
bool res = trampoline_acl_authenticate(thd, connect_errors, com_change_user_pkt_len);
|
||||
ThdSesData ThdData(thd);
|
||||
|
||||
audit(&ThdData);
|
||||
ThdSesData thdData(thd);
|
||||
thdData.storeErrorCode();
|
||||
audit(&thdData);
|
||||
|
||||
return (res);
|
||||
}
|
||||
@@ -1239,9 +1230,17 @@ static bool calc_file_md5(const char *file_name, char *digest_str)
|
||||
|
||||
if ((fd = my_open(file_name, O_RDONLY, MYF(MY_WME))) < 0)
|
||||
{
|
||||
sql_print_error("%s Failed file open: [%s], errno: %d.",
|
||||
log_prefix, file_name, errno);
|
||||
return false;
|
||||
sql_print_error("%s Failed file open: [%s], errno: %d. Retrying with /proc/%d/exe.",
|
||||
log_prefix, file_name, errno, getpid());
|
||||
|
||||
char pidFilename[100];
|
||||
sprintf(pidFilename, "/proc/%d/exe", getpid());
|
||||
if ((fd = my_open(pidFilename, O_RDONLY, MYF(MY_WME))) < 0)
|
||||
{
|
||||
sql_print_error("%s Failed file open: [%s], errno: %d.",
|
||||
log_prefix, pidFilename, errno);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
my_MD5Context context;
|
||||
@@ -1330,7 +1329,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 %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 %zu %zu %zu", log_prefix,
|
||||
Audit_formatter::thd_offsets.query_id,
|
||||
Audit_formatter::thd_offsets.thread_id,
|
||||
Audit_formatter::thd_offsets.main_security_ctx,
|
||||
@@ -1352,7 +1351,10 @@ static int setup_offsets()
|
||||
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
|
||||
Audit_formatter::thd_offsets.row_count_func,
|
||||
Audit_formatter::thd_offsets.stmt_da,
|
||||
Audit_formatter::thd_offsets.da_status,
|
||||
Audit_formatter::thd_offsets.da_sql_errno
|
||||
);
|
||||
|
||||
if (! validate_offsets(&Audit_formatter::thd_offsets))
|
||||
@@ -1467,11 +1469,23 @@ static int setup_offsets()
|
||||
{
|
||||
decoffsets.row_count_func -= dec;
|
||||
}
|
||||
if (decoffsets.stmt_da)
|
||||
{
|
||||
decoffsets.stmt_da -= dec;
|
||||
}
|
||||
if (decoffsets.da_status)
|
||||
{
|
||||
decoffsets.da_status -= dec;
|
||||
}
|
||||
if (decoffsets.da_sql_errno)
|
||||
{
|
||||
decoffsets.da_sql_errno -= 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 %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 %zu %zu %zu",
|
||||
log_prefix, dec, offset->version, offset->md5digest,
|
||||
Audit_formatter::thd_offsets.query_id,
|
||||
Audit_formatter::thd_offsets.thread_id,
|
||||
@@ -1493,7 +1507,10 @@ static int setup_offsets()
|
||||
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
|
||||
Audit_formatter::thd_offsets.row_count_func,
|
||||
Audit_formatter::thd_offsets.stmt_da,
|
||||
Audit_formatter::thd_offsets.da_status,
|
||||
Audit_formatter::thd_offsets.da_sql_errno
|
||||
);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
@@ -1511,7 +1528,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 %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 %zu %zu %zu",
|
||||
log_prefix, inc, offset->version, offset->md5digest,
|
||||
Audit_formatter::thd_offsets.query_id,
|
||||
Audit_formatter::thd_offsets.thread_id,
|
||||
@@ -1533,7 +1550,10 @@ static int setup_offsets()
|
||||
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
|
||||
Audit_formatter::thd_offsets.row_count_func,
|
||||
Audit_formatter::thd_offsets.stmt_da,
|
||||
Audit_formatter::thd_offsets.da_status,
|
||||
Audit_formatter::thd_offsets.da_sql_errno
|
||||
);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@@ -1958,7 +1978,7 @@ static int audit_plugin_init(void *p)
|
||||
interface_ver = interface_ver >> 8;
|
||||
#endif
|
||||
sql_print_information(
|
||||
"%s starting up. Version: %s , Revision: %s (%s). AUDIT plugin interface version: %d (0x%x). MySQL Server version: %s.",
|
||||
"%s starting up. Version: %s , Revision: %s (%s). MySQL AUDIT plugin interface version: %d (0x%x). MySQL Server version: %s.",
|
||||
log_prefix, MYSQL_AUDIT_PLUGIN_VERSION,
|
||||
MYSQL_AUDIT_PLUGIN_REVISION, arch, interface_ver, interface_ver,
|
||||
server_version);
|
||||
@@ -2134,15 +2154,7 @@ static int audit_plugin_init(void *p)
|
||||
log_prefix);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
if (do_hot_patch((void **)&trampoline_check_user, &trampoline_check_user_size,
|
||||
(void *)check_user, (void *)audit_check_user, "check_user"))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
if (do_hot_patch((void **)&trampoline_acl_authenticate, &trampoline_acl_authenticate_size,
|
||||
(void *)acl_authenticate, (void *)audit_acl_authenticate, "acl_authenticate"))
|
||||
{
|
||||
@@ -2343,6 +2355,12 @@ static MYSQL_SYSVAR_STR(json_socket_name, json_socket_handler.m_io_dest,
|
||||
"AUDIT plugin json log unix socket name",
|
||||
NULL, json_socket_name_update, "");
|
||||
|
||||
static MYSQL_SYSVAR_ULONG(json_socket_write_timeout, json_socket_handler.m_write_timeout,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"AUDIT plugin json socket write timeout, in milliseconds (currently must be at least 1000)",
|
||||
NULL, NULL, DEFAULT_WRITE_TIMEOUT,
|
||||
0, UINT_MAX32, 0);
|
||||
|
||||
static MYSQL_SYSVAR_STR(offsets, offsets_string,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
|
||||
"AUDIT plugin offsets. Comma separated list of offsets to use for extracting data",
|
||||
@@ -2476,6 +2494,7 @@ static struct st_mysql_sys_var* audit_system_variables[] =
|
||||
MYSQL_SYSVAR(peer_is_uds),
|
||||
MYSQL_SYSVAR(peer_info),
|
||||
MYSQL_SYSVAR(before_after),
|
||||
MYSQL_SYSVAR(json_socket_write_timeout),
|
||||
|
||||
NULL
|
||||
};
|
||||
@@ -2485,7 +2504,7 @@ mysql_declare_plugin(audit_plugin)
|
||||
{
|
||||
plugin_type,
|
||||
&audit_plugin,
|
||||
"AUDIT",
|
||||
PLUGIN_NAME,
|
||||
"McAfee Inc",
|
||||
"AUDIT plugin, creates a file mysql-audit.log to log activity",
|
||||
PLUGIN_LICENSE_GPL,
|
||||
@@ -2498,32 +2517,26 @@ mysql_declare_plugin(audit_plugin)
|
||||
}
|
||||
mysql_declare_plugin_end;
|
||||
|
||||
#if MYSQL_VERSION_ID < 50505
|
||||
/**
|
||||
* DLL constructor method.
|
||||
* We set here the audit plugin version to the same as the first built in plugin.
|
||||
* This is so we can have a single lib for all versions (needed in 5.1)
|
||||
*/
|
||||
extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
|
||||
static inline void init_peer_info()
|
||||
{
|
||||
if (mysqld_builtins && mysqld_builtins[0])
|
||||
{
|
||||
audit_plugin.interface_version = *(int *) mysqld_builtins[0]->info;
|
||||
sql_print_information("%s Set interface version to: %d (%d)",
|
||||
log_prefix, audit_plugin.interface_version,
|
||||
audit_plugin.interface_version >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_error(
|
||||
"%s mysqld_builtins are null. Plugin will not load unless the mysql version is: %d. \n",
|
||||
log_prefix, audit_plugin.interface_version >> 8);
|
||||
}
|
||||
|
||||
memset(peer_info_init_value, '0', sizeof(peer_info_init_value)-1);
|
||||
peer_info_init_value[sizeof(peer_info_init_value) - 1] = '\0';
|
||||
}
|
||||
#elif MYSQL_VERSION_ID < 50600
|
||||
|
||||
static inline void set_plugin_name_from_env()
|
||||
{
|
||||
char *plugin_name = getenv("MCAFEE_AUDIT_PLUGIN_NAME");
|
||||
|
||||
if (plugin_name != NULL)
|
||||
{
|
||||
PLUGIN_NAME = plugin_name;
|
||||
_mysql_plugin_declarations_[0].name = plugin_name;
|
||||
sql_print_information(
|
||||
"%s using plugin name %s from environtment", log_prefix, plugin_name);
|
||||
}
|
||||
}
|
||||
|
||||
#if MYSQL_VERSION_ID < 50600
|
||||
extern struct st_mysql_plugin *mysql_mandatory_plugins[];
|
||||
extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
|
||||
{
|
||||
@@ -2532,8 +2545,8 @@ extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
|
||||
log_prefix, audit_plugin.interface_version,
|
||||
audit_plugin.interface_version >> 8);
|
||||
|
||||
memset(peer_info_init_value, '0', sizeof(peer_info_init_value)-1);
|
||||
peer_info_init_value[sizeof(peer_info_init_value) - 1] = '\0';
|
||||
init_peer_info();
|
||||
set_plugin_name_from_env();
|
||||
}
|
||||
#elif !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID < 50709
|
||||
// Interface version for MySQL 5.6 changed in 5.6.14.
|
||||
@@ -2550,15 +2563,15 @@ extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
|
||||
audit_plugin.interface_version = 0x0301;
|
||||
}
|
||||
|
||||
memset(peer_info_init_value, '0', sizeof(peer_info_init_value)-1);
|
||||
peer_info_init_value[sizeof(peer_info_init_value) - 1] = '\0';
|
||||
init_peer_info();
|
||||
set_plugin_name_from_env();
|
||||
}
|
||||
#else
|
||||
// 5.7
|
||||
extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
|
||||
{
|
||||
memset(peer_info_init_value, '0', sizeof(peer_info_init_value)-1);
|
||||
peer_info_init_value[sizeof(peer_info_init_value) - 1] = '\0';
|
||||
init_peer_info();
|
||||
set_plugin_name_from_env();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user