You've already forked mysql-audit
mirror of
https://github.com/trellix-enterprise/mysql-audit.git
synced 2025-12-17 18:24:02 +08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ea0b6bd15 | ||
|
|
2d0a23c73d | ||
|
|
bca3715fb5 | ||
|
|
d9786405af | ||
|
|
286197fe6d | ||
|
|
40dc1e7ff7 | ||
|
|
969d0b481a | ||
|
|
e7d07fc1fe | ||
|
|
e6fd9d8b6f | ||
|
|
8e56548468 | ||
|
|
e03dcc1cec | ||
|
|
8370847e9b | ||
|
|
4b78009cb3 | ||
|
|
f4a3411ccd | ||
|
|
cd9400da0e | ||
|
|
0ff56ddfb4 | ||
|
|
570bfb0de6 | ||
|
|
ba21262b81 | ||
|
|
4fbcae3a81 |
@@ -42,7 +42,7 @@ Source code is available at: https://github.com/mcafee/mysql-audit
|
||||
|
||||
License
|
||||
-------------------------------
|
||||
Copyright (C) 2016 McAfee, Inc.
|
||||
Copyright (C) 2011-2017 McAfee, Inc.
|
||||
|
||||
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
|
||||
@@ -48,10 +48,23 @@ typedef struct _THDPRINTED {
|
||||
char is_thd_printed_queue[MAX_NUM_QUEUE_ELEM];
|
||||
} THDPRINTED;
|
||||
|
||||
#define MAX_COMMAND_CHAR_NUMBERS 40
|
||||
struct PeerInfo {
|
||||
unsigned long pid;
|
||||
enum { MAX_APP_NAME_LEN = 128, MAX_USER_NAME_LEN = 128 };
|
||||
char appName[MAX_APP_NAME_LEN + 1];
|
||||
char osUser[MAX_USER_NAME_LEN + 1]; // allow lots, in case from LDAP or some such
|
||||
PeerInfo() : pid(0) {
|
||||
memset(appName, 0, sizeof appName);
|
||||
memset(osUser, 0, sizeof osUser);
|
||||
}
|
||||
};
|
||||
|
||||
PeerInfo *retrieve_peerinfo(THD *thd);
|
||||
|
||||
const char *retrieve_command(THD *thd, bool& is_sql_cmd);
|
||||
typedef size_t OFFSET;
|
||||
|
||||
#define MAX_COMMAND_CHAR_NUMBERS 40
|
||||
#define MAX_COM_STATUS_VARS_RECORDS 512
|
||||
|
||||
// mysql max identifier is 64 so 2*64 + . and null
|
||||
@@ -82,6 +95,15 @@ typedef struct ThdOffsets {
|
||||
OFFSET pfs_connect_attrs;
|
||||
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;
|
||||
OFFSET stmt_da;
|
||||
OFFSET da_status;
|
||||
OFFSET da_sql_errno;
|
||||
} ThdOffsets;
|
||||
|
||||
/*
|
||||
@@ -114,11 +136,21 @@ 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);
|
||||
THD *getTHD() { return m_pThd;}
|
||||
const char *getCmdName() { return m_CmdName; }
|
||||
// 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; }
|
||||
const char *getUserName() { return m_UserName; }
|
||||
const unsigned long getPeerPid() const;
|
||||
const char *getAppName() const;
|
||||
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.
|
||||
*/
|
||||
@@ -145,6 +177,16 @@ private:
|
||||
QueryTableInf *m_tableInf;
|
||||
int m_index;
|
||||
|
||||
// Statement source
|
||||
StatementSource m_source;
|
||||
|
||||
PeerInfo *m_peerInfo;
|
||||
|
||||
int m_port; // TCP port of remote side
|
||||
|
||||
uint m_errorCode;
|
||||
bool m_setErrorCode;
|
||||
|
||||
protected:
|
||||
ThdSesData(const ThdSesData&);
|
||||
ThdSesData &operator =(const ThdSesData&);
|
||||
@@ -185,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)
|
||||
@@ -243,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
|
||||
@@ -302,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)
|
||||
@@ -322,61 +362,61 @@ public:
|
||||
{
|
||||
return *(LEX **) (((unsigned char *) thd) + Audit_formatter::thd_offsets.lex);
|
||||
}
|
||||
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
|
||||
//in mysql 5.7 capabilities flag moved to protocol. We use the capabilities offset to point to m_protocol
|
||||
//and get from protocol the capabilities flag
|
||||
static inline ulong thd_client_capabilities(THD *thd)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.client_capabilities)
|
||||
{
|
||||
//no offsets - return 0
|
||||
return 0;
|
||||
}
|
||||
Protocol * prot = *(Protocol **) (((unsigned char *) thd) + Audit_formatter::thd_offsets.client_capabilities);
|
||||
if(!prot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return prot->get_client_capabilities();
|
||||
}
|
||||
#else
|
||||
static inline ulong thd_client_capabilities(THD *thd)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.client_capabilities)
|
||||
{
|
||||
//no offsets - return 0
|
||||
return 0;
|
||||
}
|
||||
return *(ulong *) (((unsigned char *) thd) + Audit_formatter::thd_offsets.client_capabilities);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static inline const char * pfs_connect_attrs(void * pfs)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs)
|
||||
{
|
||||
//no offsets - return null
|
||||
return NULL;
|
||||
}
|
||||
return *(const char **) (((unsigned char *) pfs) + Audit_formatter::thd_offsets.pfs_connect_attrs);
|
||||
}
|
||||
|
||||
static inline uint pfs_connect_attrs_length(void * pfs)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_length)
|
||||
{
|
||||
//no offsets - return 0
|
||||
return 0;
|
||||
}
|
||||
return *(uint *) (((unsigned char *) pfs) + Audit_formatter::thd_offsets.pfs_connect_attrs_length);
|
||||
}
|
||||
|
||||
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
|
||||
//in mysql 5.7 capabilities flag moved to protocol. We use the capabilities offset to point to m_protocol
|
||||
//and get from protocol the capabilities flag
|
||||
static inline ulong thd_client_capabilities(THD *thd)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.client_capabilities)
|
||||
{
|
||||
//no offsets - return 0
|
||||
return 0;
|
||||
}
|
||||
Protocol * prot = *(Protocol **) (((unsigned char *) thd) + Audit_formatter::thd_offsets.client_capabilities);
|
||||
if(!prot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return prot->get_client_capabilities();
|
||||
}
|
||||
#else
|
||||
static inline ulong thd_client_capabilities(THD *thd)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.client_capabilities)
|
||||
{
|
||||
//no offsets - return 0
|
||||
return 0;
|
||||
}
|
||||
return *(ulong *) (((unsigned char *) thd) + Audit_formatter::thd_offsets.client_capabilities);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline const char * pfs_connect_attrs(void * pfs)
|
||||
{
|
||||
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);
|
||||
|
||||
return *pfs_pointer;
|
||||
}
|
||||
|
||||
static inline uint pfs_connect_attrs_length(void * pfs)
|
||||
{
|
||||
if (! Audit_formatter::thd_offsets.pfs_connect_attrs_length || pfs == NULL)
|
||||
{
|
||||
//no offsets - return 0
|
||||
return 0;
|
||||
}
|
||||
return *(uint *) (((unsigned char *) pfs) + Audit_formatter::thd_offsets.pfs_connect_attrs_length);
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -415,7 +455,116 @@ 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)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
NET *net = ((NET *) (((unsigned char *) thd)
|
||||
+ Audit_formatter::thd_offsets.net));
|
||||
// get the socket for the peer
|
||||
int sock = -1;
|
||||
if (net->vio != NULL) // MySQL 5.7.17 - this can happen. :-(
|
||||
{
|
||||
#if MYSQL_VERSION_ID < 50600
|
||||
sock = net->vio->sd;
|
||||
#else
|
||||
sock = net->vio->mysql_socket.fd;
|
||||
#endif
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
@@ -446,7 +595,8 @@ public:
|
||||
: m_msg_delimiter(NULL),
|
||||
m_write_start_msg(true),
|
||||
m_write_sess_connect_attrs(true),
|
||||
m_write_client_capabilities(true),
|
||||
m_write_client_capabilities(false),
|
||||
m_write_socket_creds(true),
|
||||
m_password_mask_regex_preg(NULL),
|
||||
m_password_mask_regex_compiled(false),
|
||||
m_perform_password_masking(NULL)
|
||||
@@ -491,13 +641,18 @@ public:
|
||||
* Public so sysvar can update
|
||||
*/
|
||||
my_bool m_write_sess_connect_attrs;
|
||||
|
||||
/**
|
||||
* include client capabilities
|
||||
* Public for sysvar
|
||||
*/
|
||||
my_bool m_write_client_capabilities;
|
||||
|
||||
/**
|
||||
* include client capabilities
|
||||
* Public for sysvar
|
||||
*/
|
||||
my_bool m_write_client_capabilities;
|
||||
|
||||
/**
|
||||
* include socket credentials from Unix Domain Socket
|
||||
* Public for sysvar
|
||||
*/
|
||||
my_bool m_write_socket_creds;
|
||||
|
||||
/**
|
||||
* Callback function to determine if password masking should be performed
|
||||
@@ -765,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";
|
||||
}
|
||||
@@ -788,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&);
|
||||
@@ -796,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,12 +48,11 @@
|
||||
#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>
|
||||
#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,103 @@ 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-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
|
||||
|
||||
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
|
||||
|
||||
# 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
|
||||
@@ -92,23 +151,35 @@ print_offset THD $DB
|
||||
print_offset THD killed
|
||||
$CLIENT_CAPS
|
||||
$CONNECT_ATTRS
|
||||
print_offset THD net
|
||||
$LEX_SQL
|
||||
$FOUND_ROWS
|
||||
$SENT_ROW_COUNT
|
||||
$ROW_COUNT_FUNC
|
||||
$STMT_DA
|
||||
$DA_STATUS
|
||||
$DA_SQL_ERRNO
|
||||
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
|
||||
@@ -117,7 +188,6 @@ OFFSETS=`cat gdb.txt`
|
||||
echo "//offsets for: $1 ($FULL_MYVER)"
|
||||
echo "$OFFSETS,"
|
||||
|
||||
#clean up
|
||||
# clean up
|
||||
rm gdb.txt
|
||||
rm offsets.gdb
|
||||
|
||||
|
||||
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.
|
||||
@@ -23,8 +23,15 @@
|
||||
// for definition of sockaddr_un
|
||||
#include <sys/un.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <limits.h>
|
||||
#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 {\
|
||||
@@ -109,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)
|
||||
@@ -463,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;
|
||||
}
|
||||
|
||||
@@ -558,7 +640,7 @@ static const char *thd_query_str(THD *thd, size_t *len)
|
||||
#elif defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID > 50140
|
||||
|
||||
extern "C" {
|
||||
MYSQL_LEX_STRING *thd_query_string(MYSQL_THD thd);
|
||||
MYSQL_LEX_STRING *thd_query_string(MYSQL_THD thd);
|
||||
}
|
||||
|
||||
static const char *thd_query_str(THD *thd, size_t *len)
|
||||
@@ -614,13 +696,14 @@ 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);
|
||||
yajl_add_string_val(gen, "mysql-program", my_progname);
|
||||
yajl_add_string_val(gen, "mysql-socket", mysqld_unix_port);
|
||||
yajl_add_uint64(gen, "mysql-port", mysqld_port);
|
||||
yajl_add_uint64(gen, "server_pid", getpid());
|
||||
ssize_t res = -2;
|
||||
|
||||
yajl_gen_status stat = yajl_gen_map_close(gen); // close the object
|
||||
@@ -677,12 +760,12 @@ static const char *replace_in_string(THD *thd,
|
||||
|
||||
//declare the function: parse_length_encoded_string from: storage/perfschema/table_session_connect.cc
|
||||
bool parse_length_encoded_string(const char **ptr,
|
||||
char *dest, uint dest_size,
|
||||
uint *copied_len,
|
||||
const char *start_ptr, uint input_length,
|
||||
bool copy_data,
|
||||
const CHARSET_INFO *from_cs,
|
||||
uint nchars_max);
|
||||
char *dest, uint dest_size,
|
||||
uint *copied_len,
|
||||
const char *start_ptr, uint input_length,
|
||||
bool copy_data,
|
||||
const CHARSET_INFO *from_cs,
|
||||
uint nchars_max);
|
||||
|
||||
/**
|
||||
* Code based upon read_nth_attribute of storage/perfschema/table_session_connect.cc
|
||||
@@ -690,76 +773,76 @@ bool parse_length_encoded_string(const char **ptr,
|
||||
*/
|
||||
static void log_session_connect_attrs(yajl_gen gen, THD *thd)
|
||||
{
|
||||
PFS_thread * pfs = PFS_thread::get_current_thread();
|
||||
const char * connect_attrs = Audit_formatter::pfs_connect_attrs(pfs);
|
||||
const uint connect_attrs_length = Audit_formatter::pfs_connect_attrs_length(pfs);
|
||||
const CHARSET_INFO *connect_attrs_cs = Audit_formatter::pfs_connect_attrs_cs(pfs);
|
||||
|
||||
//sanity max attributes
|
||||
const uint max_idx = 32;
|
||||
uint idx;
|
||||
const char *ptr;
|
||||
bool array_start = false;
|
||||
if(!connect_attrs || !connect_attrs_length || !connect_attrs_cs)
|
||||
{
|
||||
//either offsets are wrong or not set
|
||||
return;
|
||||
}
|
||||
for (ptr= connect_attrs, idx= 0;
|
||||
(uint)(ptr - connect_attrs) < connect_attrs_length && idx <= max_idx;
|
||||
idx++)
|
||||
{
|
||||
const uint MAX_COPY_CHARS_NAME = 32;
|
||||
const uint MAX_COPY_CHARS_VAL = 256;
|
||||
//time 6 (max udf8 char length)
|
||||
char attr_name[MAX_COPY_CHARS_NAME*6];
|
||||
char attr_value[MAX_COPY_CHARS_VAL *6];
|
||||
uint copy_length, attr_name_length, attr_value_length;
|
||||
/* always do copying */
|
||||
bool fill_in_attr_name= true;
|
||||
bool fill_in_attr_value= true;
|
||||
PFS_thread * pfs = PFS_thread::get_current_thread();
|
||||
const char * connect_attrs = Audit_formatter::pfs_connect_attrs(pfs);
|
||||
const uint connect_attrs_length = Audit_formatter::pfs_connect_attrs_length(pfs);
|
||||
const CHARSET_INFO *connect_attrs_cs = Audit_formatter::pfs_connect_attrs_cs(pfs);
|
||||
|
||||
/* read the key */
|
||||
copy_length = 0;
|
||||
if (parse_length_encoded_string(&ptr,
|
||||
attr_name, array_elements(attr_name), ©_length,
|
||||
connect_attrs,
|
||||
connect_attrs_length,
|
||||
fill_in_attr_name,
|
||||
connect_attrs_cs, MAX_COPY_CHARS_NAME) || !copy_length)
|
||||
{
|
||||
//something went wrong or we are done
|
||||
break;
|
||||
}
|
||||
|
||||
attr_name_length = copy_length;
|
||||
/* read the value */
|
||||
copy_length = 0;
|
||||
if (parse_length_encoded_string(&ptr,
|
||||
attr_value, array_elements(attr_value), ©_length,
|
||||
connect_attrs,
|
||||
connect_attrs_length,
|
||||
fill_in_attr_value,
|
||||
connect_attrs_cs, MAX_COPY_CHARS_VAL) || !copy_length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
attr_value_length= copy_length;
|
||||
if(!array_start)
|
||||
{
|
||||
yajl_add_string(gen, "connect_attrs");
|
||||
yajl_gen_map_open(gen);
|
||||
array_start = true;
|
||||
}
|
||||
yajl_gen_string(gen, (const unsigned char*)attr_name, attr_name_length);
|
||||
yajl_gen_string(gen, (const unsigned char*)attr_value, attr_value_length);
|
||||
|
||||
} //close for loop
|
||||
if(array_start)
|
||||
{
|
||||
yajl_gen_map_close(gen);
|
||||
}
|
||||
return;
|
||||
//sanity max attributes
|
||||
const uint max_idx = 32;
|
||||
uint idx;
|
||||
const char *ptr;
|
||||
bool array_start = false;
|
||||
if(!connect_attrs || !connect_attrs_length || !connect_attrs_cs)
|
||||
{
|
||||
//either offsets are wrong or not set
|
||||
return;
|
||||
}
|
||||
for (ptr= connect_attrs, idx= 0;
|
||||
(uint)(ptr - connect_attrs) < connect_attrs_length && idx <= max_idx;
|
||||
idx++)
|
||||
{
|
||||
const uint MAX_COPY_CHARS_NAME = 32;
|
||||
const uint MAX_COPY_CHARS_VAL = 256;
|
||||
//time 6 (max udf8 char length)
|
||||
char attr_name[MAX_COPY_CHARS_NAME*6];
|
||||
char attr_value[MAX_COPY_CHARS_VAL *6];
|
||||
uint copy_length, attr_name_length, attr_value_length;
|
||||
/* always do copying */
|
||||
bool fill_in_attr_name= true;
|
||||
bool fill_in_attr_value= true;
|
||||
|
||||
/* read the key */
|
||||
copy_length = 0;
|
||||
if (parse_length_encoded_string(&ptr,
|
||||
attr_name, array_elements(attr_name), ©_length,
|
||||
connect_attrs,
|
||||
connect_attrs_length,
|
||||
fill_in_attr_name,
|
||||
connect_attrs_cs, MAX_COPY_CHARS_NAME) || !copy_length)
|
||||
{
|
||||
//something went wrong or we are done
|
||||
break;
|
||||
}
|
||||
|
||||
attr_name_length = copy_length;
|
||||
/* read the value */
|
||||
copy_length = 0;
|
||||
if (parse_length_encoded_string(&ptr,
|
||||
attr_value, array_elements(attr_value), ©_length,
|
||||
connect_attrs,
|
||||
connect_attrs_length,
|
||||
fill_in_attr_value,
|
||||
connect_attrs_cs, MAX_COPY_CHARS_VAL) || !copy_length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
attr_value_length= copy_length;
|
||||
if(!array_start)
|
||||
{
|
||||
yajl_add_string(gen, "connect_attrs");
|
||||
yajl_gen_map_open(gen);
|
||||
array_start = true;
|
||||
}
|
||||
yajl_gen_string(gen, (const unsigned char*)attr_name, attr_name_length);
|
||||
yajl_gen_string(gen, (const unsigned char*)attr_value, attr_value_length);
|
||||
|
||||
} //close for loop
|
||||
if(array_start)
|
||||
{
|
||||
yajl_gen_map_close(gen);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -786,12 +869,14 @@ ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer
|
||||
yajl_add_string_val(gen, "priv_user", Audit_formatter::thd_inst_main_security_ctx_priv_user(thd));
|
||||
yajl_add_string_val(gen, "ip", Audit_formatter::thd_inst_main_security_ctx_ip(thd));
|
||||
|
||||
// Don't send host unless there's a real value
|
||||
// For backwards compatibility, we always send "host".
|
||||
// If there is no value, send the IP address
|
||||
const char *host = Audit_formatter::thd_inst_main_security_ctx_host(thd);
|
||||
if (host != NULL && *host != '\0')
|
||||
if (host == NULL || *host == '\0')
|
||||
{
|
||||
yajl_add_string_val(gen, "host", host);
|
||||
host = Audit_formatter::thd_inst_main_security_ctx_ip(thd);
|
||||
}
|
||||
yajl_add_string_val(gen, "host", host);
|
||||
|
||||
if (m_write_client_capabilities)
|
||||
{
|
||||
@@ -809,7 +894,63 @@ ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pThdData->getPeerPid() != 0) // Unix Domain Socket
|
||||
{
|
||||
if (m_write_socket_creds)
|
||||
{
|
||||
yajl_add_uint64(gen, "pid", pThdData->getPeerPid());
|
||||
if (pThdData->getOsUser() != NULL)
|
||||
{
|
||||
yajl_add_string_val(gen, "os_user", pThdData->getOsUser());
|
||||
}
|
||||
if (pThdData->getAppName() != NULL)
|
||||
{
|
||||
yajl_add_string_val(gen, "appname", pThdData->getAppName());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pThdData->getPort() > 0) // TCP socket
|
||||
{
|
||||
yajl_add_uint64(gen, "client_port", pThdData->getPort());
|
||||
}
|
||||
|
||||
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
|
||||
// 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
|
||||
{
|
||||
rows = thd_sent_row_count(thd);
|
||||
}
|
||||
|
||||
if (rows != 0UL)
|
||||
{
|
||||
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
|
||||
@@ -935,13 +1076,30 @@ 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_tableInf(NULL), m_index(0), m_isSqlCmd(false),
|
||||
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);
|
||||
|
||||
m_peerInfo = retrieve_peerinfo(m_pThd);
|
||||
if (m_peerInfo && m_peerInfo->pid == 0)
|
||||
{
|
||||
// not UDS, get remote port
|
||||
m_port = Audit_formatter::thd_client_port(m_pThd);
|
||||
}
|
||||
}
|
||||
|
||||
void ThdSesData::storeErrorCode()
|
||||
{
|
||||
uint code = 0;
|
||||
if (Audit_formatter::thd_error_code(m_pThd, code))
|
||||
{
|
||||
setErrorCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
bool ThdSesData::startGetObjects()
|
||||
@@ -1055,6 +1213,21 @@ bool ThdSesData::getNextObject(const char **db_name, const char **obj_name, cons
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned long ThdSesData::getPeerPid() const
|
||||
{
|
||||
return (m_peerInfo != NULL ? m_peerInfo->pid : 0L);
|
||||
}
|
||||
|
||||
const char *ThdSesData::getAppName() const
|
||||
{
|
||||
return (m_peerInfo != NULL ? m_peerInfo->appName : NULL);
|
||||
}
|
||||
|
||||
const char *ThdSesData::getOsUser() const
|
||||
{
|
||||
return (m_peerInfo != NULL ? m_peerInfo->osUser : NULL);
|
||||
}
|
||||
|
||||
pcre *Audit_json_formatter::regex_compile(const char *str)
|
||||
{
|
||||
const char *error;
|
||||
|
||||
2011
src/audit_offsets.cc
2011
src/audit_offsets.cc
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user