1. Add support for MariaDB 10.2.0-6, 10.1.25.

2. Plugin can now be renamed.
3. Socket failed to connect message log as warning the first time.
4. Correctly retrieve the port for a remote connection.
5. Log negative user id number as [unknown] .
pull/179/head
Aharon Robbins 2017-07-06 15:29:30 +03:00
parent e03dcc1cec
commit 8e56548468
6 changed files with 211 additions and 48 deletions

View File

@ -17,7 +17,7 @@
#include <pcre.h> #include <pcre.h>
#define AUDIT_LOG_PREFIX "Audit Plugin:" #define AUDIT_LOG_PREFIX "McAfee Audit Plugin:"
#define AUDIT_PROTOCOL_VERSION "1.0" #define AUDIT_PROTOCOL_VERSION "1.0"
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709 #if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
@ -218,6 +218,8 @@ public:
static QueryTableInf *getQueryCacheTableList1(THD *thd); static QueryTableInf *getQueryCacheTableList1(THD *thd);
// utility functions for fetching thd stuff // utility functions for fetching thd stuff
static int thd_client_port(THD *thd);
static inline my_thread_id thd_inst_thread_id(THD *thd) static inline my_thread_id thd_inst_thread_id(THD *thd)
{ {
return *(my_thread_id *) (((unsigned char *) thd) return *(my_thread_id *) (((unsigned char *) thd)
@ -475,29 +477,6 @@ static inline const CHARSET_INFO * pfs_connect_attrs_cs(void * pfs)
return sock; 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) static inline ulonglong thd_found_rows(THD *thd)
{ {
if (Audit_formatter::thd_offsets.found_rows == 0) if (Audit_formatter::thd_offsets.found_rows == 0)
@ -899,7 +878,8 @@ class Audit_socket_handler: public Audit_io_handler {
public: public:
Audit_socket_handler() : Audit_socket_handler() :
m_vio(NULL), m_connect_timeout(1), m_write_timeout(0) m_vio(NULL), m_connect_timeout(1), m_write_timeout(0),
m_log_with_error_severity(false)
{ {
m_io_type = "socket"; m_io_type = "socket";
} }
@ -932,6 +912,9 @@ protected:
// Vio we write to // Vio we write to
// define as void* so we don't access members directly // define as void* so we don't access members directly
void *m_vio; void *m_vio;
// log using error severity only the second time same issue occurs
bool m_log_with_error_severity;
}; };
#endif /* AUDIT_HANDLER_H_ */ #endif /* AUDIT_HANDLER_H_ */

View File

@ -59,7 +59,7 @@ fi
# In 5.6.15 and up, 5.7 and mariabdb 10.0.11 and up, mariadb 10.1 # 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 # 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 then
CONNECT_ATTRS_CS=m_session_connect_attrs_cs_number CONNECT_ATTRS_CS=m_session_connect_attrs_cs_number
fi fi

54
plugin-name.txt Normal file
View 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.

View File

@ -116,6 +116,49 @@ const char *Audit_formatter::retrieve_object_type(TABLE_LIST *pObj)
return "TABLE"; 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() void Audit_handler::stop_all()
{ {
for (size_t i = 0; i < MAX_AUDIT_HANDLERS_NUM; ++i) for (size_t i = 0; i < MAX_AUDIT_HANDLERS_NUM; ++i)
@ -470,15 +513,32 @@ int Audit_socket_handler::open(const char *io_dest, bool log_errors)
#endif #endif
{ {
if (log_errors) 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( sql_print_error(
"%s unable to connect to socket: %s. err: %s.", "%s unable to connect to socket: %s. err: %s.",
AUDIT_LOG_PREFIX, m_io_dest, strerror(errno)); AUDIT_LOG_PREFIX, m_io_dest, strerror(errno));
m_log_with_error_severity = false;
} }
close(); close();
return -2; 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) if (m_write_timeout > 0)
{ {
int timeout = m_write_timeout / 1000; // milliseconds to seconds, integer dvision int timeout = m_write_timeout / 1000; // milliseconds to seconds, integer dvision

View File

@ -858,6 +858,22 @@ const ThdOffsets thd_offsets_arr[] =
const ThdOffsets thd_offsets_arr[] = const ThdOffsets thd_offsets_arr[] =
{ {
/* +++ MARIADB 64 OFFSETS GO HERE +++ */ /* +++ MARIADB 64 OFFSETS GO HERE +++ */
//offsets for: /mariadb/10.1.25/bin/mysqld (10.1.25-MariaDB)
{"10.1.25-MariaDB","4b9b78ae51081d0ebc0a74f18a9e0f75", 13648, 13712, 6424, 8032, 88, 3000, 8, 0, 16, 24, 152, 13804, 7800, 3136, 3144, 3148, 568, 0, 0, 13024, 13048, 13032},
//offsets for: /mariadb/10.2.0/bin/mysqld (10.2.0-MariaDB)
{"10.2.0-MariaDB","f41691936c84306b0028acbc5f898a85", 13648, 13712, 6424, 8032, 88, 3072, 8, 0, 16, 24, 152, 13804, 7800, 3136, 3144, 3148, 568, 0, 0, 13024, 13048, 13032},
//offsets for: /mariadb/10.2.1/bin/mysqld (10.2.1-MariaDB)
{"10.2.1-MariaDB","5733c708d9eced8125ffb7df3ff35ab4", 13648, 13712, 6424, 8032, 88, 3080, 8, 0, 16, 24, 152, 13812, 7800, 3136, 3144, 3148, 568, 0, 0, 13024, 13048, 13032},
//offsets for: /mariadb/10.2.2/bin/mysqld (10.2.2-MariaDB)
{"10.2.2-MariaDB","d34d768480e3354431b2889e6e327bd6", 13752, 13816, 6528, 8136, 88, 3152, 8, 0, 16, 24, 152, 13916, 7904, 3136, 3144, 3148, 568, 0, 0, 13128, 13152, 13136},
//offsets for: /mariadb/10.2.3/bin/mysqld (10.2.3-MariaDB)
{"10.2.3-MariaDB","55d62a7984de41e8473638d3fb028f6d", 13776, 13840, 6544, 8152, 88, 3120, 8, 0, 16, 24, 152, 13940, 7920, 3136, 3144, 3148, 568, 0, 0, 13152, 13176, 13160},
//offsets for: /mariadb/10.2.4/bin/mysqld (10.2.4-MariaDB)
{"10.2.4-MariaDB","185570d073f337b9efa5fdb5b4c48b3d", 13792, 13856, 6560, 8168, 88, 3120, 8, 0, 16, 24, 152, 13956, 7936, 3136, 3144, 3148, 576, 0, 0, 13168, 13192, 13176},
//offsets for: /mariadb/10.2.5/bin/mysqld (10.2.5-MariaDB)
{"10.2.5-MariaDB","d80fabd4b7432b28ac19491c28b7afe0", 13792, 13856, 6560, 8168, 88, 3120, 8, 0, 16, 24, 152, 13956, 7936, 3136, 3144, 3148, 576, 0, 0, 13168, 13192, 13176},
//offsets for: /mariadb/10.2.6/bin/mysqld (10.2.6-MariaDB)
{"10.2.6-MariaDB","fbded44a97a2141b8a054209b9b2588a", 13792, 13856, 6560, 8168, 88, 3128, 8, 0, 16, 24, 152, 13956, 7936, 3136, 3144, 3148, 576, 0, 0, 13168, 13192, 13176},
//offsets for: /mariadb/10.1.24/bin/mysqld (10.1.24-MariaDB) //offsets for: /mariadb/10.1.24/bin/mysqld (10.1.24-MariaDB)
{"10.1.24-MariaDB","2be795c560d6aca4e9d966523176a588", 13648, 13712, 6424, 8032, 88, 3000, 8, 0, 16, 24, 152, 13804, 7800, 3136, 3144, 3148, 568, 0, 0, 13024, 13048, 13032}, {"10.1.24-MariaDB","2be795c560d6aca4e9d966523176a588", 13648, 13712, 6424, 8032, 88, 3000, 8, 0, 16, 24, 152, 13804, 7800, 3136, 3144, 3148, 568, 0, 0, 13024, 13048, 13032},
//offsets for: /mariadb/10.0.31/bin/mysqld (10.0.31-MariaDB) //offsets for: /mariadb/10.0.31/bin/mysqld (10.0.31-MariaDB)
@ -1031,6 +1047,22 @@ const ThdOffsets thd_offsets_arr[] =
const ThdOffsets thd_offsets_arr[] = const ThdOffsets thd_offsets_arr[] =
{ {
/* +++ MARIADB 32 OFFSETS GO HERE +++ */ /* +++ MARIADB 32 OFFSETS GO HERE +++ */
//offsets for: /mariadb/10.1.25/bin/mysqld (10.1.25-MariaDB)
{"10.1.25-MariaDB","12b0ba38e1ded5daf3ac94eab792ae90", 8504, 8540, 3848, 5308, 44, 1908, 4, 0, 8, 12, 84, 8616, 5176, 2604, 2608, 2612, 356, 0, 0, 8028, 8052, 8036},
//offsets for: /mariadb/10.2.0/bin/mysqld (10.2.0-MariaDB)
{"10.2.0-MariaDB","48cf1c6fc41578d1de4875469748b36a", 8512, 8548, 3852, 5316, 44, 1944, 4, 0, 8, 12, 84, 8628, 5180, 2604, 2608, 2612, 356, 0, 0, 8036, 8060, 8044},
//offsets for: /mariadb/10.2.1/bin/mysqld (10.2.1-MariaDB)
{"10.2.1-MariaDB","03919f36347c9a784a8a346c019fb462", 8512, 8548, 3852, 5316, 44, 1948, 4, 0, 8, 12, 84, 8636, 5180, 2604, 2608, 2612, 356, 0, 0, 8036, 8060, 8044},
//offsets for: /mariadb/10.2.2/bin/mysqld (10.2.2-MariaDB)
{"10.2.2-MariaDB","4ff0d974abf58d6f9c315c03adc9f6e1", 8564, 8600, 3904, 5368, 44, 1996, 4, 0, 8, 12, 84, 8688, 5232, 2604, 2608, 2612, 356, 0, 0, 8088, 8112, 8096},
//offsets for: /mariadb/10.2.3/bin/mysqld (10.2.3-MariaDB)
{"10.2.3-MariaDB","f1a620e35280a2065862216a4d37604d", 8576, 8612, 3912, 5376, 44, 1980, 4, 0, 8, 12, 84, 8700, 5240, 2604, 2608, 2612, 356, 0, 0, 8100, 8124, 8108},
//offsets for: /mariadb/10.2.4/bin/mysqld (10.2.4-MariaDB)
{"10.2.4-MariaDB","400cd2fc15db447615f59c7f03662335", 8588, 8624, 3924, 5388, 44, 1980, 4, 0, 8, 12, 84, 8712, 5252, 2604, 2608, 2612, 360, 0, 0, 8112, 8136, 8120},
//offsets for: /mariadb/10.2.5/bin/mysqld (10.2.5-MariaDB)
{"10.2.5-MariaDB","8fb7c12d6792c047ae5baf2629665b07", 8588, 8624, 3924, 5388, 44, 1980, 4, 0, 8, 12, 84, 8712, 5252, 2604, 2608, 2612, 360, 0, 0, 8112, 8136, 8120},
//offsets for: /mariadb/10.2.6/bin/mysqld (10.2.6-MariaDB)
{"10.2.6-MariaDB","2f2029a9a9a9654cf25174fcfe86e609", 8588, 8624, 3924, 5388, 44, 1984, 4, 0, 8, 12, 84, 8712, 5252, 2604, 2608, 2612, 360, 0, 0, 8112, 8136, 8120},
//offsets for: /mariadb/10.1.24/bin/mysqld (10.1.24-MariaDB) //offsets for: /mariadb/10.1.24/bin/mysqld (10.1.24-MariaDB)
{"10.1.24-MariaDB","16198adda60a75e53b9b9fc5b312a827", 8504, 8540, 3848, 5308, 44, 1908, 4, 0, 8, 12, 84, 8616, 5176, 2604, 2608, 2612, 356, 0, 0, 8028, 8052, 8036}, {"10.1.24-MariaDB","16198adda60a75e53b9b9fc5b312a827", 8504, 8540, 3848, 5308, 44, 1908, 4, 0, 8, 12, 84, 8616, 5176, 2604, 2608, 2612, 356, 0, 0, 8028, 8052, 8036},
//offsets for: /mariadb/10.0.31/bin/mysqld (10.0.31-MariaDB) //offsets for: /mariadb/10.0.31/bin/mysqld (10.0.31-MariaDB)

View File

@ -26,6 +26,7 @@
#include "md5.h" #include "md5.h"
#endif #endif
static const char *PLUGIN_NAME = "AUDIT";
/* /*
@ -263,7 +264,7 @@ static void initializePeerCredentials(THD *pThd)
goto done; goto done;
} }
// Is it a Unix Domain socket? // Is it a socket?
if (fstat(sock, &sbuf) < 0) if (fstat(sock, &sbuf) < 0)
{ {
goto done; goto done;
@ -274,17 +275,9 @@ static void initializePeerCredentials(THD *pThd)
goto done; 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 // 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) if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) < 0)
{ {
goto done; goto done;
@ -295,6 +288,21 @@ static void initializePeerCredentials(THD *pThd)
goto done; 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) if (peer == NULL)
{ {
goto done; goto done;
@ -308,7 +316,14 @@ static void initializePeerCredentials(THD *pThd)
if (pwbuf == NULL) if (pwbuf == NULL)
{ {
// no name, send UID // no name, send UID
if (cred.uid >= 0)
{
snprintf(buf, sizeof(buf) - 1, "%lu", (unsigned long) cred.uid); snprintf(buf, sizeof(buf) - 1, "%lu", (unsigned long) cred.uid);
}
else
{
strcpy(buf, "[unknown]");
}
username = buf; username = buf;
} }
else else
@ -922,7 +937,7 @@ int is_remove_patches(ThdSesData *pThdData)
Sql_cmd_uninstall_plugin *up = Audit_formatter::lex_sql_cmd(pLex); 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); LEX_STRING Lex_comment = *(LEX_STRING*)(((unsigned char *) up) + Audit_formatter::thd_offsets.uninstall_cmd_comment);
#endif #endif
if (strncasecmp(Lex_comment.str, "AUDIT", 5) == 0) if (strncasecmp(Lex_comment.str, PLUGIN_NAME, strlen(PLUGIN_NAME)) == 0)
{ {
if (! uninstall_plugin_enable) if (! uninstall_plugin_enable)
{ {
@ -2495,7 +2510,7 @@ mysql_declare_plugin(audit_plugin)
{ {
plugin_type, plugin_type,
&audit_plugin, &audit_plugin,
"AUDIT", PLUGIN_NAME,
"McAfee Inc", "McAfee Inc",
"AUDIT plugin, creates a file mysql-audit.log to log activity", "AUDIT plugin, creates a file mysql-audit.log to log activity",
PLUGIN_LICENSE_GPL, PLUGIN_LICENSE_GPL,
@ -2508,6 +2523,25 @@ mysql_declare_plugin(audit_plugin)
} }
mysql_declare_plugin_end; mysql_declare_plugin_end;
static inline void init_peer_info()
{
memset(peer_info_init_value, '0', sizeof(peer_info_init_value)-1);
peer_info_init_value[sizeof(peer_info_init_value) - 1] = '\0';
}
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 < 50505 #if MYSQL_VERSION_ID < 50505
/** /**
* DLL constructor method. * DLL constructor method.
@ -2530,8 +2564,8 @@ extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
log_prefix, audit_plugin.interface_version >> 8); log_prefix, audit_plugin.interface_version >> 8);
} }
memset(peer_info_init_value, '0', sizeof(peer_info_init_value)-1); init_peer_info();
peer_info_init_value[sizeof(peer_info_init_value) - 1] = '\0'; set_plugin_name_from_env();
} }
#elif MYSQL_VERSION_ID < 50600 #elif MYSQL_VERSION_ID < 50600
extern struct st_mysql_plugin *mysql_mandatory_plugins[]; extern struct st_mysql_plugin *mysql_mandatory_plugins[];
@ -2542,8 +2576,8 @@ extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
log_prefix, audit_plugin.interface_version, log_prefix, audit_plugin.interface_version,
audit_plugin.interface_version >> 8); audit_plugin.interface_version >> 8);
memset(peer_info_init_value, '0', sizeof(peer_info_init_value)-1); init_peer_info();
peer_info_init_value[sizeof(peer_info_init_value) - 1] = '\0'; set_plugin_name_from_env();
} }
#elif !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID < 50709 #elif !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID < 50709
// Interface version for MySQL 5.6 changed in 5.6.14. // Interface version for MySQL 5.6 changed in 5.6.14.
@ -2560,15 +2594,15 @@ extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
audit_plugin.interface_version = 0x0301; audit_plugin.interface_version = 0x0301;
} }
memset(peer_info_init_value, '0', sizeof(peer_info_init_value)-1); init_peer_info();
peer_info_init_value[sizeof(peer_info_init_value) - 1] = '\0'; set_plugin_name_from_env();
} }
#else #else
// 5.7 // 5.7
extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void) extern "C" void __attribute__ ((constructor)) audit_plugin_so_init(void)
{ {
memset(peer_info_init_value, '0', sizeof(peer_info_init_value)-1); init_peer_info();
peer_info_init_value[sizeof(peer_info_init_value) - 1] = '\0'; set_plugin_name_from_env();
} }
#endif #endif