added the ability to limit auditing output to specific commands and objects(tables/views)
parent
60f1b8e6d7
commit
ed048a30bb
|
@ -35,6 +35,9 @@ typedef size_t OFFSET;
|
|||
|
||||
#define MAX_COM_STATUS_VARS_RECORDS 512
|
||||
|
||||
#define MAX_OBJECT_CHAR_NUMBERS 130
|
||||
#define MAX_NUM_OBJECT_ELEM 256
|
||||
|
||||
/**
|
||||
* The struct usd to hold offsets. We should have one per version.
|
||||
*/
|
||||
|
|
|
@ -29,259 +29,259 @@
|
|||
* Will write into buff the date prefix for txt formatter. Return the number of bytes written
|
||||
* (not including null terminate).
|
||||
*/
|
||||
static int log_date_prefix(char * buff, size_t buff_size)
|
||||
{
|
||||
struct tm tm_tmp;
|
||||
time_t result= time(NULL);
|
||||
localtime_r(&result, &tm_tmp);
|
||||
//my_snprintf is limited regarding formatting but sufficient for this
|
||||
return my_snprintf(buff, buff_size, "%02d%02d%02d %2d:%02d:%02d: ",
|
||||
tm_tmp.tm_year % 100,
|
||||
tm_tmp.tm_mon+1,
|
||||
tm_tmp.tm_mday,
|
||||
tm_tmp.tm_hour,
|
||||
tm_tmp.tm_min,
|
||||
tm_tmp.tm_sec);
|
||||
}
|
||||
static int log_date_prefix(char * buff, size_t buff_size)
|
||||
{
|
||||
struct tm tm_tmp;
|
||||
time_t result= time(NULL);
|
||||
localtime_r(&result, &tm_tmp);
|
||||
//my_snprintf is limited regarding formatting but sufficient for this
|
||||
return my_snprintf(buff, buff_size, "%02d%02d%02d %2d:%02d:%02d: ",
|
||||
tm_tmp.tm_year % 100,
|
||||
tm_tmp.tm_mon+1,
|
||||
tm_tmp.tm_mday,
|
||||
tm_tmp.tm_hour,
|
||||
tm_tmp.tm_min,
|
||||
tm_tmp.tm_sec);
|
||||
}
|
||||
|
||||
|
||||
//utility macro to log also with a date as a prefix
|
||||
#define log_with_date(f, ...) do{\
|
||||
struct tm tm_tmp;\
|
||||
time_t result= time(NULL);\
|
||||
localtime_r(&result, &tm_tmp);\
|
||||
fprintf(f, "%02d%02d%02d %2d:%02d:%02d: ",\
|
||||
tm_tmp.tm_year % 100,\
|
||||
tm_tmp.tm_mon+1,\
|
||||
tm_tmp.tm_mday,\
|
||||
tm_tmp.tm_hour,\
|
||||
tm_tmp.tm_min,\
|
||||
tm_tmp.tm_sec);\
|
||||
fprintf(f, __VA_ARGS__);\
|
||||
}while(0)
|
||||
//utility macro to log also with a date as a prefix
|
||||
#define log_with_date(f, ...) do{ \
|
||||
struct tm tm_tmp; \
|
||||
time_t result= time(NULL); \
|
||||
localtime_r(&result, &tm_tmp); \
|
||||
fprintf(f, "%02d%02d%02d %2d:%02d:%02d: ", \
|
||||
tm_tmp.tm_year % 100, \
|
||||
tm_tmp.tm_mon+1, \
|
||||
tm_tmp.tm_mday, \
|
||||
tm_tmp.tm_hour, \
|
||||
tm_tmp.tm_min, \
|
||||
tm_tmp.tm_sec); \
|
||||
fprintf(f, __VA_ARGS__); \
|
||||
}while(0)
|
||||
|
||||
|
||||
//initialize static stuff
|
||||
ThdOffsets Audit_formatter::thd_offsets = { 0 };
|
||||
Audit_handler * Audit_handler::m_audit_handler_list[Audit_handler::MAX_AUDIT_HANDLERS_NUM];
|
||||
const char * Audit_json_formatter::DEF_MSG_DELIMITER = "\\n";
|
||||
//initialize static stuff
|
||||
ThdOffsets Audit_formatter::thd_offsets = { 0 };
|
||||
Audit_handler * Audit_handler::m_audit_handler_list[Audit_handler::MAX_AUDIT_HANDLERS_NUM];
|
||||
const char * Audit_json_formatter::DEF_MSG_DELIMITER = "\\n";
|
||||
|
||||
#define C_STRING_WITH_LEN(X) ((char *) (X)), ((size_t) (sizeof(X) - 1))
|
||||
|
||||
|
||||
const char * Audit_formatter::retrive_object_type (TABLE_LIST *pObj)
|
||||
{
|
||||
if (pObj->view)
|
||||
{
|
||||
return "VIEW";
|
||||
}
|
||||
return "TABLE";
|
||||
}
|
||||
const char * Audit_formatter::retrive_object_type (TABLE_LIST *pObj)
|
||||
{
|
||||
if (pObj->view)
|
||||
{
|
||||
return "VIEW";
|
||||
}
|
||||
return "TABLE";
|
||||
}
|
||||
|
||||
|
||||
void Audit_handler::stop_all()
|
||||
{
|
||||
for (int i = 0; i < MAX_AUDIT_HANDLERS_NUM; ++i)
|
||||
{
|
||||
if (m_audit_handler_list[i] != NULL)
|
||||
{
|
||||
m_audit_handler_list[i]->set_enable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Audit_handler::stop_all()
|
||||
{
|
||||
for (int i = 0; i < MAX_AUDIT_HANDLERS_NUM; ++i)
|
||||
{
|
||||
if (m_audit_handler_list[i] != NULL)
|
||||
{
|
||||
m_audit_handler_list[i]->set_enable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Audit_handler::log_audit_all(ThdSesData *pThdData)
|
||||
{
|
||||
for (int i = 0; i < MAX_AUDIT_HANDLERS_NUM; ++i)
|
||||
{
|
||||
if (m_audit_handler_list[i] != NULL)
|
||||
{
|
||||
m_audit_handler_list[i]->log_audit(pThdData);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Audit_handler::log_audit_all(ThdSesData *pThdData)
|
||||
{
|
||||
for (int i = 0; i < MAX_AUDIT_HANDLERS_NUM; ++i)
|
||||
{
|
||||
if (m_audit_handler_list[i] != NULL)
|
||||
{
|
||||
m_audit_handler_list[i]->log_audit(pThdData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Audit_handler::set_enable(bool val)
|
||||
{
|
||||
lock_exclusive();
|
||||
if (m_enabled == val) //we are already enabled simply return
|
||||
{
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
m_enabled = val;
|
||||
if (m_enabled)
|
||||
{
|
||||
//call the startup of the handler
|
||||
handler_start();
|
||||
}
|
||||
else
|
||||
{
|
||||
//call the cleanup of the handler
|
||||
handler_stop();
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
void Audit_handler::set_enable(bool val)
|
||||
{
|
||||
lock_exclusive();
|
||||
if (m_enabled == val) //we are already enabled simply return
|
||||
{
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
m_enabled = val;
|
||||
if (m_enabled)
|
||||
{
|
||||
//call the startup of the handler
|
||||
handler_start();
|
||||
}
|
||||
else
|
||||
{
|
||||
//call the cleanup of the handler
|
||||
handler_stop();
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void Audit_handler::log_audit(ThdSesData *pThdData)
|
||||
{
|
||||
lock_shared();
|
||||
if (!m_enabled)
|
||||
{
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
//sanity check that offsets match
|
||||
//we can also consider using secutiry context function to do some sanity checks
|
||||
// char buffer[2048];
|
||||
// thd_security_context(thd, buffer, 2048, 2000);
|
||||
// fprintf(log_file, "info from security context: %s\n", buffer);
|
||||
unsigned long inst_thread_id = Audit_formatter::thd_inst_thread_id(pThdData->getTHD());
|
||||
unsigned long plug_thread_id = thd_get_thread_id(pThdData->getTHD());
|
||||
if (inst_thread_id != plug_thread_id)
|
||||
{
|
||||
if (m_print_offset_err)
|
||||
{
|
||||
m_print_offset_err = false;
|
||||
sql_print_error(
|
||||
"%s Thread id from thd_get_thread_id doesn't match calculated value from offset %lu <> %lu. Aborting!",
|
||||
AUDIT_LOG_PREFIX, inst_thread_id, plug_thread_id);
|
||||
void Audit_handler::log_audit(ThdSesData *pThdData)
|
||||
{
|
||||
lock_shared();
|
||||
if (!m_enabled)
|
||||
{
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
//sanity check that offsets match
|
||||
//we can also consider using secutiry context function to do some sanity checks
|
||||
// char buffer[2048];
|
||||
// thd_security_context(thd, buffer, 2048, 2000);
|
||||
// fprintf(log_file, "info from security context: %s\n", buffer);
|
||||
unsigned long inst_thread_id = Audit_formatter::thd_inst_thread_id(pThdData->getTHD());
|
||||
unsigned long plug_thread_id = thd_get_thread_id(pThdData->getTHD());
|
||||
if (inst_thread_id != plug_thread_id)
|
||||
{
|
||||
if (m_print_offset_err)
|
||||
{
|
||||
m_print_offset_err = false;
|
||||
sql_print_error(
|
||||
"%s Thread id from thd_get_thread_id doesn't match calculated value from offset %lu <> %lu. Aborting!",
|
||||
AUDIT_LOG_PREFIX, inst_thread_id, plug_thread_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{//offsets are good
|
||||
m_print_offset_err = true; //mark to print offset err to log incase we encounter in the future
|
||||
handler_log_audit(pThdData);
|
||||
m_print_offset_err = true; //mark to print offset err to log incase we encounter in the future
|
||||
handler_log_audit(pThdData);
|
||||
}
|
||||
unlock();
|
||||
unlock();
|
||||
}
|
||||
|
||||
ssize_t Audit_file_handler::write(const char * data, size_t size)
|
||||
{
|
||||
return my_fwrite(m_log_file, (uchar *) data, size, MYF(0));
|
||||
return my_fwrite(m_log_file, (uchar *) data, size, MYF(0));
|
||||
}
|
||||
|
||||
void Audit_file_handler::handler_start()
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
char format_name[FN_REFLEN];
|
||||
fn_format(format_name, m_filename, "", "", MY_UNPACK_FILENAME);
|
||||
m_log_file = my_fopen(format_name, O_RDWR | O_APPEND, MYF(0));
|
||||
if (!m_log_file)
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
char format_name[FN_REFLEN];
|
||||
fn_format(format_name, m_filename, "", "", MY_UNPACK_FILENAME);
|
||||
m_log_file = my_fopen(format_name, O_RDWR | O_APPEND, MYF(0));
|
||||
if (!m_log_file)
|
||||
{
|
||||
sql_print_error(
|
||||
"%s unable to create %s: %s. audit file handler disabled!!",
|
||||
AUDIT_LOG_PREFIX, m_filename, strerror(errno));
|
||||
m_enabled = false;
|
||||
sql_print_error(
|
||||
"%s unable to create %s: %s. audit file handler disabled!!",
|
||||
AUDIT_LOG_PREFIX, m_filename, strerror(errno));
|
||||
m_enabled = false;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
ssize_t res = m_formatter->start_msg_format(this);
|
||||
/*
|
||||
sanity check of writing to the log. If we fail. We will print an erorr and disable this handler.
|
||||
*/
|
||||
if (res < 0 || fflush(m_log_file) != 0)
|
||||
ssize_t res = m_formatter->start_msg_format(this);
|
||||
/*
|
||||
sanity check of writing to the log. If we fail. We will print an erorr and disable this handler.
|
||||
*/
|
||||
if (res < 0 || fflush(m_log_file) != 0)
|
||||
{
|
||||
sql_print_error(
|
||||
"%s unable to write to %s: %s. Disabling audit handler.",
|
||||
AUDIT_LOG_PREFIX, m_log_file, strerror(errno));
|
||||
close_file();
|
||||
m_enabled = false;
|
||||
sql_print_error(
|
||||
"%s unable to write to %s: %s. Disabling audit handler.",
|
||||
AUDIT_LOG_PREFIX, m_log_file, strerror(errno));
|
||||
close_file();
|
||||
m_enabled = false;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
}
|
||||
void Audit_file_handler::handler_stop()
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
m_formatter->stop_msg_format(this);
|
||||
close_file();
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
m_formatter->stop_msg_format(this);
|
||||
close_file();
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
}
|
||||
|
||||
void Audit_file_handler::handler_log_audit(ThdSesData *pThdData)
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
m_formatter->event_format(pThdData, this);
|
||||
if (++m_sync_counter >= m_sync_period && m_sync_period)
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
m_formatter->event_format(pThdData, this);
|
||||
if (++m_sync_counter >= m_sync_period && m_sync_period)
|
||||
{
|
||||
m_sync_counter = 0;
|
||||
//Note fflush() only flushes the user space buffers provided by the C library.
|
||||
//To ensure that the data is physically stored on disk the kernel buffers must be flushed too,
|
||||
//e.g. with sync(2) or fsync(2).
|
||||
fflush(m_log_file);
|
||||
int fd = fileno(m_log_file);
|
||||
my_sync(fd, MYF(MY_WME));
|
||||
m_sync_counter = 0;
|
||||
//Note fflush() only flushes the user space buffers provided by the C library.
|
||||
//To ensure that the data is physically stored on disk the kernel buffers must be flushed too,
|
||||
//e.g. with sync(2) or fsync(2).
|
||||
fflush(m_log_file);
|
||||
int fd = fileno(m_log_file);
|
||||
my_sync(fd, MYF(MY_WME));
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
}
|
||||
|
||||
/////////////////// Audit_socket_handler //////////////////////////////////
|
||||
|
||||
ssize_t Audit_socket_handler::write(const char * data, size_t size)
|
||||
{
|
||||
return vio_write(m_vio, (const uchar *) data, size);
|
||||
return vio_write(m_vio, (const uchar *) data, size);
|
||||
}
|
||||
|
||||
void Audit_socket_handler::handler_start()
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
//open the socket
|
||||
int sock = socket(AF_UNIX,SOCK_STREAM,0);
|
||||
if (sock < 0)
|
||||
{
|
||||
sql_print_error(
|
||||
"%s unable to create socket: %s. audit socket handler disabled!!",
|
||||
AUDIT_LOG_PREFIX, strerror(errno));
|
||||
m_enabled = false;
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
return;
|
||||
}
|
||||
|
||||
//connect the socket
|
||||
m_vio= vio_new(sock, VIO_TYPE_SOCKET, VIO_LOCALHOST);
|
||||
struct sockaddr_un UNIXaddr;
|
||||
UNIXaddr.sun_family = AF_UNIX;
|
||||
strmake(UNIXaddr.sun_path, m_sockname, sizeof(UNIXaddr.sun_path)-1);
|
||||
if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
|
||||
m_connect_timeout))
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
//open the socket
|
||||
int sock = socket(AF_UNIX,SOCK_STREAM,0);
|
||||
if (sock < 0)
|
||||
{
|
||||
sql_print_error(
|
||||
"%s unable to connect to socket: %s. err: %s. audit socket handler disabled!!",
|
||||
AUDIT_LOG_PREFIX, m_sockname, strerror(errno));
|
||||
"%s unable to create socket: %s. audit socket handler disabled!!",
|
||||
AUDIT_LOG_PREFIX, strerror(errno));
|
||||
m_enabled = false;
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
return;
|
||||
}
|
||||
|
||||
//connect the socket
|
||||
m_vio= vio_new(sock, VIO_TYPE_SOCKET, VIO_LOCALHOST);
|
||||
struct sockaddr_un UNIXaddr;
|
||||
UNIXaddr.sun_family = AF_UNIX;
|
||||
strmake(UNIXaddr.sun_path, m_sockname, sizeof(UNIXaddr.sun_path)-1);
|
||||
if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
|
||||
m_connect_timeout))
|
||||
{
|
||||
sql_print_error(
|
||||
"%s unable to connect to socket: %s. err: %s. audit socket handler disabled!!",
|
||||
AUDIT_LOG_PREFIX, m_sockname, strerror(errno));
|
||||
close_vio();
|
||||
m_enabled = false;
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
return;
|
||||
|
||||
}
|
||||
ssize_t res = m_formatter->start_msg_format(this);
|
||||
/*
|
||||
sanity check of writing to the log. If we fail. We will print an erorr and disable this handler.
|
||||
*/
|
||||
if (res < 0)
|
||||
ssize_t res = m_formatter->start_msg_format(this);
|
||||
/*
|
||||
sanity check of writing to the log. If we fail. We will print an erorr and disable this handler.
|
||||
*/
|
||||
if (res < 0)
|
||||
{
|
||||
sql_print_error(
|
||||
"%s unable to write to %s: %s. Disabling audit handler.",
|
||||
AUDIT_LOG_PREFIX, m_sockname, strerror(errno));
|
||||
close_vio();
|
||||
m_enabled = false;
|
||||
sql_print_error(
|
||||
"%s unable to write to %s: %s. Disabling audit handler.",
|
||||
AUDIT_LOG_PREFIX, m_sockname, strerror(errno));
|
||||
close_vio();
|
||||
m_enabled = false;
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
}
|
||||
void Audit_socket_handler::handler_stop()
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
m_formatter->stop_msg_format(this);
|
||||
close_vio();
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
m_formatter->stop_msg_format(this);
|
||||
close_vio();
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
}
|
||||
|
||||
void Audit_socket_handler::handler_log_audit(ThdSesData *pThdData)
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
m_formatter->event_format(pThdData, this);
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
pthread_mutex_lock(&LOCK_io);
|
||||
m_formatter->event_format(pThdData, this);
|
||||
pthread_mutex_unlock(&LOCK_io);
|
||||
}
|
||||
|
||||
//////////////////////// Audit Socket handler end ///////////////////////////////////////////
|
||||
|
@ -291,40 +291,40 @@ void Audit_socket_handler::handler_log_audit(ThdSesData *pThdData)
|
|||
|
||||
static inline yajl_gen_status yajl_add_string(yajl_gen hand, const char * str)
|
||||
{
|
||||
return yajl_gen_string(hand, (const unsigned char*)str, strlen(str));
|
||||
return yajl_gen_string(hand, (const unsigned char*)str, strlen(str));
|
||||
}
|
||||
|
||||
static inline void yajl_add_string_val(yajl_gen hand, const char * name, const char* val)
|
||||
{
|
||||
if(0 == val)
|
||||
{
|
||||
return; //we don't add NULL values to json
|
||||
}
|
||||
yajl_add_string(hand, name);
|
||||
yajl_add_string(hand, val);
|
||||
if(0 == val)
|
||||
{
|
||||
return; //we don't add NULL values to json
|
||||
}
|
||||
yajl_add_string(hand, name);
|
||||
yajl_add_string(hand, val);
|
||||
}
|
||||
|
||||
static inline void yajl_add_string_val(yajl_gen hand, const char * name, const char* val, size_t val_len)
|
||||
{
|
||||
yajl_add_string(hand, name);
|
||||
yajl_gen_string(hand, (const unsigned char*)val, val_len);
|
||||
yajl_add_string(hand, name);
|
||||
yajl_gen_string(hand, (const unsigned char*)val, val_len);
|
||||
}
|
||||
|
||||
static inline void yajl_add_uint64(yajl_gen gen, const char * name, uint64 num)
|
||||
{
|
||||
const size_t max_int64_str_len = 21;
|
||||
char buf[max_int64_str_len];
|
||||
snprintf(buf, max_int64_str_len, "%llu", num);
|
||||
yajl_add_string_val(gen, name, buf);
|
||||
const size_t max_int64_str_len = 21;
|
||||
char buf[max_int64_str_len];
|
||||
snprintf(buf, max_int64_str_len, "%llu", num);
|
||||
yajl_add_string_val(gen, name, buf);
|
||||
}
|
||||
static inline void yajl_add_obj( yajl_gen gen, const char *db,const char* ptype,const char * name =NULL)
|
||||
{
|
||||
yajl_add_string_val(gen, "db", db);
|
||||
if (name)
|
||||
yajl_add_string_val(gen, "db", db);
|
||||
if (name)
|
||||
{
|
||||
yajl_add_string_val(gen, "name", name);
|
||||
yajl_add_string_val(gen, "name", name);
|
||||
}
|
||||
yajl_add_string_val(gen, "obj_type",ptype);
|
||||
yajl_add_string_val(gen, "obj_type",ptype);
|
||||
}
|
||||
|
||||
//void Audit_file_handler::print_sleep (THD *thd, int delay_ms)
|
||||
|
@ -334,152 +334,151 @@ static inline void yajl_add_obj( yajl_gen gen, const char *db,const char* ptype
|
|||
// yajl_gen gen = yajl_gen_alloc(&config, NULL);
|
||||
// yajl_gen_array_open(gen);
|
||||
// yajl_gen_map_open(gen);
|
||||
// yajl_add_string_val(gen, "msg-type", "activity");
|
||||
// yajl_add_string_val(gen, "msg-type", "activity");
|
||||
// uint64 ts = my_getsystime() / (10000);
|
||||
// yajl_add_uint64(gen, "date", ts);
|
||||
// yajl_add_uint64(gen, "thread-id", thdid);
|
||||
// yajl_add_uint64(gen, "audit is going to sleep for ", delay_ms);
|
||||
// yajl_gen_map_close(gen);
|
||||
// yajl_gen_array_close(gen);
|
||||
// yajl_add_uint64(gen, "thread-id", thdid);
|
||||
// yajl_add_uint64(gen, "audit is going to sleep for ", delay_ms);
|
||||
// yajl_gen_map_close(gen);
|
||||
// yajl_gen_array_close(gen);
|
||||
// fflush(m_log_file);
|
||||
// int fd = fileno(m_log_file);
|
||||
// my_sync(fd, MYF(MY_WME));
|
||||
// my_sync(fd, MYF(MY_WME));
|
||||
//
|
||||
//}
|
||||
ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * writer)
|
||||
{
|
||||
unsigned long thdid = thd_get_thread_id(pThdData->getTHD());
|
||||
query_id_t qid = thd_inst_query_id(pThdData->getTHD());
|
||||
int command = thd_inst_command(pThdData->getTHD());
|
||||
unsigned long thdid = thd_get_thread_id(pThdData->getTHD());
|
||||
query_id_t qid = thd_inst_query_id(pThdData->getTHD());
|
||||
int command = thd_inst_command(pThdData->getTHD());
|
||||
|
||||
|
||||
Security_context * sctx = thd_inst_main_security_ctx(pThdData->getTHD());
|
||||
Security_context * sctx = thd_inst_main_security_ctx(pThdData->getTHD());
|
||||
|
||||
//initialize yajl
|
||||
yajl_gen gen = yajl_gen_alloc(&config, NULL);
|
||||
yajl_gen_map_open(gen);
|
||||
yajl_add_string_val(gen, "msg-type", "activity");
|
||||
//TODO: get the start date from THD (but it is not in millis. Need to think about how we handle this)
|
||||
//for now simply use the current time.
|
||||
//my_getsystime() time since epoc in 100 nanosec units. Need to devide by 1000*(1000/100) to reach millis
|
||||
uint64 ts = my_getsystime() / (10000);
|
||||
yajl_add_uint64(gen, "date", ts);
|
||||
yajl_add_uint64(gen, "thread-id", thdid);
|
||||
yajl_add_uint64(gen, "query-id", qid);
|
||||
yajl_add_string_val(gen, "user", sctx->user);
|
||||
yajl_add_string_val(gen, "priv_user", sctx->priv_user);
|
||||
yajl_add_string_val(gen, "host", sctx->host);
|
||||
yajl_add_string_val(gen, "ip", sctx->ip);
|
||||
const char *cmd = pThdData->getCmdName();
|
||||
//only print tables if lex is not null and it is not a quit command
|
||||
LEX * pLex = Audit_formatter::thd_lex(pThdData->getTHD());
|
||||
QueryTableInf *pQuery_cache_table_list = getQueryCacheTableList1 (pThdData->getTHD());
|
||||
if (pLex && command != COM_QUIT && pLex->query_tables == NULL && pQuery_cache_table_list)
|
||||
//initialize yajl
|
||||
yajl_gen gen = yajl_gen_alloc(&config, NULL);
|
||||
yajl_gen_map_open(gen);
|
||||
yajl_add_string_val(gen, "msg-type", "activity");
|
||||
//TODO: get the start date from THD (but it is not in millis. Need to think about how we handle this)
|
||||
//for now simply use the current time.
|
||||
//my_getsystime() time since epoc in 100 nanosec units. Need to devide by 1000*(1000/100) to reach millis
|
||||
uint64 ts = my_getsystime() / (10000);
|
||||
yajl_add_uint64(gen, "date", ts);
|
||||
yajl_add_uint64(gen, "thread-id", thdid);
|
||||
yajl_add_uint64(gen, "query-id", qid);
|
||||
yajl_add_string_val(gen, "user", sctx->user);
|
||||
yajl_add_string_val(gen, "priv_user", sctx->priv_user);
|
||||
yajl_add_string_val(gen, "host", sctx->host);
|
||||
yajl_add_string_val(gen, "ip", sctx->ip);
|
||||
const char *cmd = pThdData->getCmdName();
|
||||
//only print tables if lex is not null and it is not a quit command
|
||||
LEX * pLex = Audit_formatter::thd_lex(pThdData->getTHD());
|
||||
QueryTableInf *pQuery_cache_table_list = getQueryCacheTableList1 (pThdData->getTHD());
|
||||
if (pLex && command != COM_QUIT && pLex->query_tables == NULL && pQuery_cache_table_list)
|
||||
{
|
||||
yajl_add_string_val(gen, "cmd", "select");
|
||||
yajl_add_string(gen, "objects");
|
||||
yajl_gen_array_open(gen);
|
||||
for (int i=0;i<pQuery_cache_table_list->num_of_elem && i < MAX_NUM_QUERY_TABLE_ELEM && pQuery_cache_table_list->num_of_elem >=0;i++)
|
||||
yajl_add_string_val(gen, "cmd", "select");
|
||||
yajl_add_string(gen, "objects");
|
||||
yajl_gen_array_open(gen);
|
||||
for (int i=0;i<pQuery_cache_table_list->num_of_elem && i < MAX_NUM_QUERY_TABLE_ELEM && pQuery_cache_table_list->num_of_elem >=0;i++)
|
||||
{
|
||||
yajl_gen_map_open(gen);
|
||||
yajl_add_obj (gen, pQuery_cache_table_list->db[i],pQuery_cache_table_list->object_type[i],pQuery_cache_table_list->table_name[i] );
|
||||
yajl_gen_map_close(gen);
|
||||
yajl_gen_map_open(gen);
|
||||
yajl_add_obj (gen, pQuery_cache_table_list->db[i],pQuery_cache_table_list->object_type[i],pQuery_cache_table_list->table_name[i] );
|
||||
yajl_gen_map_close(gen);
|
||||
|
||||
}
|
||||
yajl_gen_array_close(gen);
|
||||
yajl_gen_array_close(gen);
|
||||
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
|
||||
yajl_add_string_val(gen, "cmd", cmd);
|
||||
yajl_add_string_val(gen, "cmd", cmd);
|
||||
}
|
||||
|
||||
|
||||
if (strcmp (cmd,"Init DB") ==0 || strcmp (cmd, "SHOW TABLES")== 0 || strcmp (cmd, "SHOW TABLE")==0)
|
||||
{
|
||||
if ((pThdData->getTHD())->db !=0)
|
||||
{
|
||||
yajl_add_string(gen, "objects");
|
||||
yajl_gen_array_open(gen);
|
||||
yajl_add_obj (gen,(pThdData->getTHD())->db,"database", NULL);
|
||||
yajl_gen_array_close(gen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pLex && command != COM_QUIT && pLex->query_tables)
|
||||
if (strcmp (cmd,"Init DB") ==0 || strcmp (cmd, "SHOW TABLES")== 0 || strcmp (cmd, "SHOW TABLE")==0)
|
||||
{
|
||||
yajl_add_string(gen, "objects");
|
||||
yajl_gen_array_open(gen);
|
||||
TABLE_LIST * table = pLex->query_tables;
|
||||
bool isFirstElementInView = true;
|
||||
|
||||
while (table)
|
||||
{
|
||||
yajl_gen_map_open(gen);
|
||||
if (isFirstElementInView && strstr (cmd,"_view")!=NULL )
|
||||
{
|
||||
yajl_add_obj (gen,table->get_db_name(), "view",table->get_table_name());
|
||||
isFirstElementInView = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
yajl_add_obj (gen,table->get_db_name(), retrive_object_type(table),table->get_table_name());
|
||||
}
|
||||
yajl_gen_map_close(gen);
|
||||
table = table->next_global;
|
||||
}
|
||||
yajl_gen_array_close(gen);
|
||||
if ((pThdData->getTHD())->db !=0)
|
||||
{
|
||||
yajl_add_string(gen, "objects");
|
||||
yajl_gen_array_open(gen);
|
||||
yajl_add_obj (gen,(pThdData->getTHD())->db,"database", NULL);
|
||||
yajl_gen_array_close(gen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t qlen = 0;
|
||||
|
||||
const char * query = thd_query(pThdData->getTHD(), &qlen);
|
||||
if (query && qlen > 0)
|
||||
if (pLex && command != COM_QUIT && pLex->query_tables)
|
||||
{
|
||||
CHARSET_INFO *col_connection = Item::default_charset();
|
||||
if (strcmp (col_connection->csname,"utf8")!=0) {
|
||||
String sQuery (query,col_connection) ;
|
||||
pThdData->getTHD()->convert_string (&sQuery,col_connection,&my_charset_utf8_general_ci);
|
||||
yajl_add_string_val(gen, "query", sQuery.c_ptr_safe(), sQuery.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
yajl_add_string_val(gen, "query",query, qlen);
|
||||
}
|
||||
yajl_add_string(gen, "objects");
|
||||
yajl_gen_array_open(gen);
|
||||
TABLE_LIST * table = pLex->query_tables;
|
||||
bool isFirstElementInView = true;
|
||||
|
||||
while (table)
|
||||
{
|
||||
yajl_gen_map_open(gen);
|
||||
if (isFirstElementInView && strstr (cmd,"_view")!=NULL )
|
||||
{
|
||||
yajl_add_obj (gen,table->get_db_name(), "view",table->get_table_name());
|
||||
isFirstElementInView = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
yajl_add_obj (gen,table->get_db_name(), retrive_object_type(table),table->get_table_name());
|
||||
}
|
||||
yajl_gen_map_close(gen);
|
||||
table = table->next_global;
|
||||
}
|
||||
yajl_gen_array_close(gen);
|
||||
}
|
||||
|
||||
|
||||
size_t qlen = 0;
|
||||
|
||||
const char * query = thd_query(pThdData->getTHD(), &qlen);
|
||||
if (query && qlen > 0)
|
||||
{
|
||||
CHARSET_INFO *col_connection = Item::default_charset();
|
||||
if (strcmp (col_connection->csname,"utf8")!=0) {
|
||||
String sQuery (query,col_connection) ;
|
||||
pThdData->getTHD()->convert_string (&sQuery,col_connection,&my_charset_utf8_general_ci);
|
||||
yajl_add_string_val(gen, "query", sQuery.c_ptr_safe(), sQuery.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
yajl_add_string_val(gen, "query",query, qlen);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if (cmd!=NULL && strlen (cmd)!=0)
|
||||
if (cmd!=NULL && strlen (cmd)!=0)
|
||||
{
|
||||
yajl_add_string_val(gen, "query",cmd, strlen (cmd));
|
||||
yajl_add_string_val(gen, "query",cmd, strlen (cmd));
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
yajl_add_string_val(gen, "query","n/a", strlen ("n/a" ));
|
||||
yajl_add_string_val(gen, "query","n/a", strlen ("n/a" ));
|
||||
}
|
||||
}
|
||||
ssize_t res = -2;
|
||||
yajl_gen_status stat = yajl_gen_map_close(gen); //close the object
|
||||
if(stat == yajl_gen_status_ok) //all is good write the buffer out
|
||||
ssize_t res = -2;
|
||||
yajl_gen_status stat = yajl_gen_map_close(gen); //close the object
|
||||
if(stat == yajl_gen_status_ok) //all is good write the buffer out
|
||||
{
|
||||
const unsigned char * text = NULL;
|
||||
unsigned int len = 0;
|
||||
yajl_gen_get_buf(gen, &text, &len);
|
||||
//print the json
|
||||
res = writer->write((const char *)text, len);
|
||||
if(res >= 0)
|
||||
const unsigned char * text = NULL;
|
||||
unsigned int len = 0;
|
||||
yajl_gen_get_buf(gen, &text, &len);
|
||||
//print the json
|
||||
res = writer->write((const char *)text, len);
|
||||
if(res >= 0)
|
||||
{
|
||||
//TODO: use the msg_delimiter
|
||||
res = writer->write("\n", 1);
|
||||
//TODO: use the msg_delimiter
|
||||
res = writer->write("\n", 1);
|
||||
}
|
||||
//my_fwrite(log_file, (uchar *) b.data, json_size(&b), MYF(0));
|
||||
//my_fwrite(log_file, (uchar *) b.data, json_size(&b), MYF(0));
|
||||
}
|
||||
yajl_gen_free(gen); //free the generator
|
||||
return res;
|
||||
yajl_gen_free(gen); //free the generator
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -487,5 +486,5 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
|
|||
|
||||
ThdSesData::ThdSesData (THD *pTHD) : m_pThd (pTHD), m_CmdName(NULL)
|
||||
{
|
||||
m_CmdName = retrieve_command (m_pThd);
|
||||
m_CmdName = retrieve_command (m_pThd);
|
||||
}
|
||||
|
|
|
@ -104,6 +104,8 @@ static const ThdOffsets thd_offsets_arr[] =
|
|||
{"5.1.60-community","d9497964e8983a348538c0d05eaee7f0", 6328, 6392, 3688, 3960, 88, 2048},
|
||||
//offsets for: /mysqlrpm/5.1.61/usr/sbin/mysqld (5.1.61-community)
|
||||
{"5.1.61-community","bda6030d35e7fafa5b1e57154a53b804", 6328, 6392, 3688, 3960, 88, 2048},
|
||||
//offsets for:
|
||||
{"5.1.63","2a6d7c81179baf6bc6bbb807b8b54967", 6336, 6400, 3696, 3968, 88, 2048},
|
||||
//offsets for: mysqlrpm/5.5.8/usr/sbin/mysqld (5.5.8)
|
||||
{"5.5.8","70a882693d54df8ab7c7d9f256e317bb", 6032, 6080, 3776, 4200, 88, 2560},
|
||||
//offsets for: mysqlrpm/5.5.9/usr/sbin/mysqld (5.5.9)
|
||||
|
@ -454,8 +456,16 @@ static my_bool validate_checksum_enable = FALSE;
|
|||
static char * offsets_string = NULL;
|
||||
static int delay_ms_val =0;
|
||||
static char *delay_cmds_string = NULL;
|
||||
static char *record_cmds_string = NULL;
|
||||
static char *record_objs_string = NULL;
|
||||
|
||||
static char delay_cmds_array [SQLCOM_END + 2][MAX_COMMAND_CHAR_NUMBERS];
|
||||
static char record_cmds_array [SQLCOM_END + 2][MAX_COMMAND_CHAR_NUMBERS];
|
||||
static char record_objs_array [MAX_NUM_OBJECT_ELEM + 2][MAX_OBJECT_CHAR_NUMBERS];
|
||||
static int num_delay_cmds = 0;
|
||||
static int num_record_cmds = 0;
|
||||
static int num_record_objs = 0;
|
||||
|
||||
static SHOW_VAR com_status_vars_array [MAX_COM_STATUS_VARS_RECORDS] = {0};
|
||||
/**
|
||||
* The trampoline function we use. Define it via a macro which simply fills it with nops.
|
||||
|
@ -506,9 +516,49 @@ THDPRINTED * GetThdPrintedList (THD *thd)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int check_array(const char *cmd, char *array, int length) {
|
||||
for (int k=0; array[k * length + 0] !='\0';k++) {
|
||||
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) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void audit(ThdSesData *pThdData)
|
||||
{
|
||||
THDPRINTED *pThdPrintedList = GetThdPrintedList (pThdData->getTHD());
|
||||
if (num_record_cmds > 0) {
|
||||
const char * cmd = pThdData->getCmdName();
|
||||
if (!check_array(cmd, (char *) record_cmds_array, MAX_COMMAND_CHAR_NUMBERS)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_record_objs > 0) {
|
||||
LEX *pLex = Audit_formatter::thd_lex(pThdData->getTHD());
|
||||
TABLE_LIST * table = pLex->query_tables;
|
||||
int matched = 0;
|
||||
while (table && !matched) {
|
||||
char *name = table->get_table_name();
|
||||
char *db = table->get_db_name();
|
||||
char obj[MAX_OBJECT_CHAR_NUMBERS];
|
||||
strcpy(obj, db);
|
||||
strcat(obj, ":");
|
||||
strcat(obj, name);
|
||||
matched = check_array(obj, (char *) record_objs_array, MAX_OBJECT_CHAR_NUMBERS);
|
||||
table = table->next_global;
|
||||
}
|
||||
if (!matched) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pThdPrintedList && pThdPrintedList->cur_index < MAX_NUM_QUEUE_ELEM)
|
||||
{
|
||||
if (pThdPrintedList->is_thd_printed_queue[pThdPrintedList->cur_index] == 0)
|
||||
|
@ -528,21 +578,11 @@ static void audit(ThdSesData *pThdData)
|
|||
if (delay_ms_val > 0)
|
||||
{
|
||||
const char * cmd = pThdData->getCmdName();
|
||||
for (int k=0; delay_cmds_array[k][0] !='\0';k++)
|
||||
{
|
||||
int j=0;
|
||||
for (;delay_cmds_array[k][j] !='\0'
|
||||
&& cmd[j] !='\0'
|
||||
&& delay_cmds_array[k][j] == tolower (cmd[j]);j++)
|
||||
{
|
||||
|
||||
}
|
||||
if (delay_cmds_array[k][j] == '\0' && j !=0)
|
||||
{
|
||||
//Audit_file_handler::print_sleep(thd,delay_ms_val);
|
||||
my_sleep (delay_ms_val *1000);
|
||||
break;
|
||||
}
|
||||
int delay = check_array(cmd, (char *) delay_cmds_array, MAX_COMMAND_CHAR_NUMBERS);
|
||||
if (delay)
|
||||
{
|
||||
//Audit_file_handler::print_sleep(thd,delay_ms_val);
|
||||
my_sleep (delay_ms_val *1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -887,47 +927,47 @@ static bool parse_thd_offsets_string (char *poffsets_string)
|
|||
{
|
||||
|
||||
char offset_str [2048] = {0};
|
||||
char *poffset_str = offset_str;
|
||||
strncpy (poffset_str,poffsets_string,2048);
|
||||
char * comma_delimiter = strchr (poffset_str,',');
|
||||
int i =0;
|
||||
OFFSET *pOffset;
|
||||
size_t len = strlen (poffset_str);
|
||||
|
||||
for (int j=0;j<len;j++)
|
||||
{
|
||||
if (!((poffset_str[j] >= '0' && poffset_str[j] <='9') || poffset_str[j] == ' ' || poffset_str[j] == ','))
|
||||
return false;
|
||||
}
|
||||
while (comma_delimiter !=NULL)
|
||||
{
|
||||
*comma_delimiter = '\0';
|
||||
pOffset = (OFFSET*)&Audit_formatter::thd_offsets.query_id + i;
|
||||
if ((size_t)pOffset- (size_t)&Audit_formatter::thd_offsets < sizeof (Audit_formatter::thd_offsets))
|
||||
{
|
||||
sscanf (poffset_str, "%d", pOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
poffset_str = comma_delimiter + 1;
|
||||
comma_delimiter = strchr (poffset_str,',');
|
||||
}
|
||||
if (poffset_str !=NULL)
|
||||
{
|
||||
pOffset = &Audit_formatter::thd_offsets.query_id + i;
|
||||
if ((size_t)pOffset- (size_t)&Audit_formatter::thd_offsets < sizeof (Audit_formatter::thd_offsets))
|
||||
{
|
||||
sscanf (poffset_str, "%d", pOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
char *poffset_str = offset_str;
|
||||
strncpy (poffset_str,poffsets_string,2048);
|
||||
char * comma_delimiter = strchr (poffset_str,',');
|
||||
int i =0;
|
||||
OFFSET *pOffset;
|
||||
size_t len = strlen (poffset_str);
|
||||
|
||||
for (int j=0;j<len;j++)
|
||||
{
|
||||
if (!((poffset_str[j] >= '0' && poffset_str[j] <='9') || poffset_str[j] == ' ' || poffset_str[j] == ','))
|
||||
return false;
|
||||
}
|
||||
while (comma_delimiter !=NULL)
|
||||
{
|
||||
*comma_delimiter = '\0';
|
||||
pOffset = (OFFSET*)&Audit_formatter::thd_offsets.query_id + i;
|
||||
if ((size_t)pOffset- (size_t)&Audit_formatter::thd_offsets < sizeof (Audit_formatter::thd_offsets))
|
||||
{
|
||||
sscanf (poffset_str, "%d", pOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
poffset_str = comma_delimiter + 1;
|
||||
comma_delimiter = strchr (poffset_str,',');
|
||||
}
|
||||
if (poffset_str !=NULL)
|
||||
{
|
||||
pOffset = &Audit_formatter::thd_offsets.query_id + i;
|
||||
if ((size_t)pOffset- (size_t)&Audit_formatter::thd_offsets < sizeof (Audit_formatter::thd_offsets))
|
||||
{
|
||||
sscanf (poffset_str, "%d", pOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1097,69 +1137,69 @@ static int setup_offsets()
|
|||
const char * retrieve_command (THD * thd)
|
||||
{
|
||||
const char *cmd = NULL;
|
||||
|
||||
int command = Audit_formatter::thd_inst_command(thd);
|
||||
if (command < 0 || command > COM_END)
|
||||
{
|
||||
command = COM_END;
|
||||
}
|
||||
const int sql_command = thd_sql_command(thd);
|
||||
if (sql_command >=0 && sql_command <= (MAX_COM_STATUS_VARS_RECORDS -1) )
|
||||
{
|
||||
cmd = com_status_vars_array[sql_command + 1].name;
|
||||
}
|
||||
if(!cmd)
|
||||
{
|
||||
cmd = command_name[command].str;
|
||||
}
|
||||
Security_context * sctx = Audit_formatter::thd_inst_main_security_ctx(thd);
|
||||
if (strcmp (cmd, "Connect") ==0 && (sctx->priv_user == NULL || *sctx->priv_user == 0x0))
|
||||
{
|
||||
cmd = "Failed Login";
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
int command = Audit_formatter::thd_inst_command(thd);
|
||||
if (command < 0 || command > COM_END)
|
||||
{
|
||||
command = COM_END;
|
||||
}
|
||||
const int sql_command = thd_sql_command(thd);
|
||||
if (sql_command >=0 && sql_command <= (MAX_COM_STATUS_VARS_RECORDS -1) )
|
||||
{
|
||||
cmd = com_status_vars_array[sql_command + 1].name;
|
||||
}
|
||||
if(!cmd)
|
||||
{
|
||||
cmd = command_name[command].str;
|
||||
}
|
||||
Security_context * sctx = Audit_formatter::thd_inst_main_security_ctx(thd);
|
||||
if (strcmp (cmd, "Connect") ==0 && (sctx->priv_user == NULL || *sctx->priv_user == 0x0))
|
||||
{
|
||||
cmd = "Failed Login";
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static int set_com_status_vars_array ()
|
||||
{
|
||||
DBUG_ENTER("set_com_status_vars_array");
|
||||
SHOW_VAR *com_status_vars;
|
||||
int sv_idx =0;
|
||||
while (strcmp (status_vars[sv_idx].name,"Com") !=0 && status_vars[sv_idx].name != NullS)
|
||||
{
|
||||
sv_idx ++;
|
||||
}
|
||||
if (strcmp (status_vars[sv_idx].name,"Com")==0)
|
||||
{
|
||||
int status_vars_index =0;
|
||||
com_status_vars = (SHOW_VAR*)status_vars[sv_idx].value;
|
||||
size_t initial_offset = (size_t) com_status_vars[0].value;
|
||||
while (com_status_vars[status_vars_index].name != NullS)
|
||||
{
|
||||
int sql_command_idx = (com_status_vars[status_vars_index].value - (char*) (initial_offset)) / sizeof (ulong);
|
||||
if (sql_command_idx >=0 && sql_command_idx < MAX_COM_STATUS_VARS_RECORDS)
|
||||
{
|
||||
com_status_vars_array [sql_command_idx].name = com_status_vars[status_vars_index].name;
|
||||
com_status_vars_array [sql_command_idx].type = com_status_vars[status_vars_index].type;
|
||||
com_status_vars_array [sql_command_idx].value = com_status_vars[status_vars_index].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_error("%s Failed sql_command_idx [%d] is out of bounds. Plugin Init failed.",
|
||||
log_prefix, sql_command_idx);
|
||||
DBUG_RETURN (1);
|
||||
}
|
||||
status_vars_index ++;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_error("%s Failed looking up 'Com' entry in status_vars. Plugin Init failed.",
|
||||
log_prefix);
|
||||
DBUG_RETURN (1);
|
||||
}
|
||||
DBUG_RETURN (0);
|
||||
int sv_idx =0;
|
||||
while (strcmp (status_vars[sv_idx].name,"Com") !=0 && status_vars[sv_idx].name != NullS)
|
||||
{
|
||||
sv_idx ++;
|
||||
}
|
||||
if (strcmp (status_vars[sv_idx].name,"Com")==0)
|
||||
{
|
||||
int status_vars_index =0;
|
||||
com_status_vars = (SHOW_VAR*)status_vars[sv_idx].value;
|
||||
size_t initial_offset = (size_t) com_status_vars[0].value;
|
||||
while (com_status_vars[status_vars_index].name != NullS)
|
||||
{
|
||||
int sql_command_idx = (com_status_vars[status_vars_index].value - (char*) (initial_offset)) / sizeof (ulong);
|
||||
if (sql_command_idx >=0 && sql_command_idx < MAX_COM_STATUS_VARS_RECORDS)
|
||||
{
|
||||
com_status_vars_array [sql_command_idx].name = com_status_vars[status_vars_index].name;
|
||||
com_status_vars_array [sql_command_idx].type = com_status_vars[status_vars_index].type;
|
||||
com_status_vars_array [sql_command_idx].value = com_status_vars[status_vars_index].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_error("%s Failed sql_command_idx [%d] is out of bounds. Plugin Init failed.",
|
||||
log_prefix, sql_command_idx);
|
||||
DBUG_RETURN (1);
|
||||
}
|
||||
status_vars_index ++;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_error("%s Failed looking up 'Com' entry in status_vars. Plugin Init failed.",
|
||||
log_prefix);
|
||||
DBUG_RETURN (1);
|
||||
}
|
||||
DBUG_RETURN (0);
|
||||
}
|
||||
/*
|
||||
Initialize the daemon plugin installation.
|
||||
|
@ -1414,8 +1454,9 @@ static void json_log_socket_enable(THD *thd, struct st_mysql_sys_var *var,
|
|||
}
|
||||
}
|
||||
|
||||
static void delay_cmds_string_handler (THD *thd, struct st_mysql_sys_var *var,
|
||||
void *tgt, const void *save)
|
||||
static int string_handler (THD *thd, struct st_mysql_sys_var *var,
|
||||
void *tgt, const void *save,
|
||||
char *string_array, int rows, int length)
|
||||
{
|
||||
|
||||
char *old= *(char **) tgt;
|
||||
|
@ -1429,41 +1470,60 @@ static void delay_cmds_string_handler (THD *thd, struct st_mysql_sys_var *var,
|
|||
const char* save_string;
|
||||
save_string = *static_cast<const char*const*>(save);
|
||||
|
||||
int k =0;
|
||||
if (save_string !=NULL)
|
||||
{
|
||||
int r =0;
|
||||
if (save_string !=NULL) {
|
||||
int p = 0;
|
||||
for (int i = 0; save_string[i] != '\0'; i++) {
|
||||
// consider space and tab and comma to be separators
|
||||
// strings of multiple of them will be only a single separator
|
||||
if (save_string[i] == ' ' || save_string[i] == '\t' || save_string[i] == ',') {
|
||||
if (p > 0) {
|
||||
string_array[r * length + p ] = '\0';
|
||||
p = 0;
|
||||
r++;
|
||||
if (r == (rows - 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// otherwise copy the character over
|
||||
else {
|
||||
string_array[r * length + p] = tolower(save_string[i]);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
// if we have copied chars to the current row, then terminate the string and
|
||||
// go to the next row.
|
||||
if (p > 0) {
|
||||
string_array[r * length + p] = '\0';
|
||||
r++;
|
||||
}
|
||||
// now terminate the list
|
||||
string_array[r * length + 0] = '\0';
|
||||
}
|
||||
|
||||
int j =0;
|
||||
for (int i=0; save_string[i] !='\0'; i++,j++)
|
||||
{
|
||||
while (save_string[i] ==' ' || save_string[i] == '\t' || save_string[i] == ',' )
|
||||
{
|
||||
if (save_string[i] == ',')
|
||||
{
|
||||
if (j+1 < MAX_COMMAND_CHAR_NUMBERS)
|
||||
{
|
||||
delay_cmds_array[k][j] = '\0';
|
||||
}
|
||||
k++;
|
||||
j=0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (k < SQLCOM_END && j < MAX_COMMAND_CHAR_NUMBERS)
|
||||
{
|
||||
delay_cmds_array[k][j] = tolower (save_string[i]);
|
||||
}
|
||||
}
|
||||
if (k < SQLCOM_END && j < MAX_COMMAND_CHAR_NUMBERS)
|
||||
{
|
||||
delay_cmds_array[k][j] = '\0';
|
||||
}
|
||||
|
||||
}
|
||||
if (k < SQLCOM_END)
|
||||
{
|
||||
delay_cmds_array[k+1][0]='\0';
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void delay_cmds_string_handler (THD *thd, struct st_mysql_sys_var *var,
|
||||
void *tgt, const void *save)
|
||||
{
|
||||
num_delay_cmds = string_handler(thd, var, tgt, save, (char *) delay_cmds_array, SQLCOM_END + 2, MAX_COMMAND_CHAR_NUMBERS);
|
||||
sql_print_information("%s Set num_delay_cmds: %d", log_prefix, num_delay_cmds);
|
||||
}
|
||||
|
||||
static void record_cmds_string_handler (THD *thd, struct st_mysql_sys_var *var,
|
||||
void *tgt, const void *save)
|
||||
{
|
||||
num_record_cmds = string_handler(thd, var, tgt, save, (char *) record_cmds_array, SQLCOM_END + 2, MAX_COMMAND_CHAR_NUMBERS);
|
||||
sql_print_information("%s Set num_record_cmds: %d", log_prefix, num_record_cmds);
|
||||
}
|
||||
|
||||
static void record_objs_string_handler (THD *thd, struct st_mysql_sys_var *var,
|
||||
void *tgt, const void *save)
|
||||
{
|
||||
num_record_objs = string_handler(thd, var, tgt, save, (char *) record_objs_array, MAX_NUM_OBJECT_ELEM + 2, MAX_OBJECT_CHAR_NUMBERS);
|
||||
sql_print_information("%s Set num_record_objs: %d", log_prefix, num_record_objs);
|
||||
}
|
||||
|
||||
//setup sysvars which update directly the relevant plugins
|
||||
|
@ -1517,6 +1577,16 @@ static MYSQL_SYSVAR_STR(delay_cmds, delay_cmds_string,
|
|||
"AUDIT plugin delay commands to match against comma separated. If empty then delay is disabled.",
|
||||
NULL, delay_cmds_string_handler, NULL);
|
||||
|
||||
static MYSQL_SYSVAR_STR(record_cmds, record_cmds_string,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"AUDIT plugin commands to record, comma separated",
|
||||
NULL, record_cmds_string_handler, NULL);
|
||||
|
||||
static MYSQL_SYSVAR_STR(record_objs, record_objs_string,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"AUDIT plugin objects to record, comma separated",
|
||||
NULL, record_objs_string_handler, NULL);
|
||||
|
||||
/*
|
||||
* Plugin system vars
|
||||
*/
|
||||
|
@ -1534,6 +1604,8 @@ static struct st_mysql_sys_var* audit_system_variables[] =
|
|||
MYSQL_SYSVAR(is_thd_printed_list),
|
||||
MYSQL_SYSVAR(delay_ms),
|
||||
MYSQL_SYSVAR(delay_cmds),
|
||||
MYSQL_SYSVAR(record_cmds),
|
||||
MYSQL_SYSVAR(record_objs),
|
||||
NULL };
|
||||
|
||||
//declare our plugin
|
||||
|
|
Loading…
Reference in New Issue