Add MariaDB 10.1.13 offsets. Format the code.

pull/141/head
Arnold Robbins 2016-03-31 11:55:57 +03:00
parent 051b1fd67e
commit 80646620e9
9 changed files with 3683 additions and 3626 deletions

View File

@ -49,12 +49,12 @@ typedef struct _THDPRINTED {
} THDPRINTED;
#define MAX_COMMAND_CHAR_NUMBERS 40
const char * retrieve_command (THD * thd, bool & is_sql_cmd);
const char *retrieve_command(THD *thd, bool & is_sql_cmd);
typedef size_t OFFSET;
#define MAX_COM_STATUS_VARS_RECORDS 512
//mysql max identifier is 64 so 2*64 + . and null
// mysql max identifier is 64 so 2*64 + . and null
#define MAX_OBJECT_CHAR_NUMBERS 131
#define MAX_USER_CHAR_NUMBERS 20
#define MAX_NUM_OBJECT_ELEM 256
@ -63,10 +63,9 @@ typedef size_t OFFSET;
/**
* The struct used to hold offsets. We should have one per version.
*/
typedef struct ThdOffsets
{
const char * version;
const char * md5digest;
typedef struct ThdOffsets {
const char *version;
const char *md5digest;
OFFSET query_id;
OFFSET thread_id;
OFFSET main_security_ctx;
@ -96,30 +95,28 @@ typedef ssize_t (*audit_write_func)(const char *, size_t);
/**
* Interface for an io writer
*/
class IWriter
{
class IWriter {
public:
virtual ~IWriter() {}
//return negative on fail
virtual ssize_t write(const char * data, size_t size) = 0;
inline ssize_t write_str(const char * str)
// return negative on fail
virtual ssize_t write(const char *data, size_t size) = 0;
inline ssize_t write_str(const char *str)
{
return write(str, strlen(str));
}
//return 0 on success
virtual int open(const char * io_dest, bool log_errors) = 0;
// return 0 on success
virtual int open(const char *io_dest, bool log_errors) = 0;
virtual void close() = 0;
};
class ThdSesData {
public:
//enum indicating from where the object list came from
// 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; }
const char * getUserName () { return m_UserName; }
THD *getTHD() { return m_pThd;}
const char *getCmdName() { return m_CmdName; }
const char *getUserName() { return m_UserName; }
/**
* Start fetching objects. Return true if there are objects available.
*/
@ -129,32 +126,32 @@ public:
* Will point the passed pointers to point to db, name and type.
* obj_type is optional and may be null.
*/
bool getNextObject(const char ** db_name, const char ** obj_name, const char ** obj_type);
bool getNextObject(const char **db_name, const char **obj_name, const char **obj_type);
private:
THD *m_pThd;
const char *m_CmdName;
const char *m_UserName;
bool m_isSqlCmd;
enum ObjectIterType m_objIterType;
//pointer for iterating tables
TABLE_LIST * m_tables;
//indicator if we are at the first table
// pointer for iterating tables
TABLE_LIST *m_tables;
// indicator if we are at the first table
bool m_firstTable;
//used for query cache iter
QueryTableInf * m_tableInf;
// used for query cache iter
QueryTableInf *m_tableInf;
int m_index;
protected:
ThdSesData (const ThdSesData& );
ThdSesData &operator =(const ThdSesData& );
ThdSesData(const ThdSesData&);
ThdSesData &operator =(const ThdSesData&);
};
/**
* Base for audit formatter
*/
class Audit_formatter
{
class Audit_formatter {
public:
virtual ~Audit_formatter() {}
/**
@ -167,40 +164,40 @@ public:
*
* @return -1 on a failure
*/
virtual ssize_t event_format(ThdSesData *pThdData, IWriter * writer) =0;
virtual ssize_t event_format(ThdSesData *pThdData, IWriter *writer) =0;
/**
* format a message when handler is started
* @return -1 on a failure
*/
virtual ssize_t start_msg_format(IWriter * writer) { return 0; }
virtual ssize_t start_msg_format(IWriter *writer) { return 0; }
/**
* format a message when handler is stopped
* @return -1 on a failure
*/
virtual ssize_t stop_msg_format(IWriter * writer) { return 0; }
virtual ssize_t stop_msg_format(IWriter *writer) { return 0; }
static const char * retrieve_object_type (TABLE_LIST *pObj);
static QueryTableInf* getQueryCacheTableList1 (THD *thd);
//utility functions for fetching thd stuff
static inline my_thread_id thd_inst_thread_id(THD * thd)
static const char *retrieve_object_type(TABLE_LIST *pObj);
static QueryTableInf *getQueryCacheTableList1(THD *thd);
// utility functions for fetching thd stuff
static inline my_thread_id thd_inst_thread_id(THD *thd)
{
return *(my_thread_id *) (((unsigned char *) thd)
+ Audit_formatter::thd_offsets.thread_id);
}
static inline query_id_t thd_inst_query_id(THD * thd)
static inline query_id_t thd_inst_query_id(THD *thd)
{
return *(query_id_t *) (((unsigned char *) thd)
+ Audit_formatter::thd_offsets.query_id);
}
static inline Security_context * thd_inst_main_security_ctx(THD * thd)
static inline Security_context *thd_inst_main_security_ctx(THD *thd)
{
return (Security_context *) (((unsigned char *) thd)
+ Audit_formatter::thd_offsets.main_security_ctx);
}
static inline const char * thd_db(THD * thd)
static inline const char *thd_db(THD *thd)
{
if(!Audit_formatter::thd_offsets.db) //no offsets use compiled in header
if (! Audit_formatter::thd_offsets.db) // no offsets use compiled in header
{
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
return thd->db;
@ -212,9 +209,9 @@ public:
+ Audit_formatter::thd_offsets.db);
}
static inline int thd_killed(THD * thd)
static inline int thd_killed(THD *thd)
{
if(!Audit_formatter::thd_offsets.killed) //no offsets use thd_killed function
if (! Audit_formatter::thd_offsets.killed) // no offsets use thd_killed function
{
return ::thd_killed(thd);
}
@ -222,10 +219,10 @@ public:
+ Audit_formatter::thd_offsets.killed);
}
static inline const char * thd_inst_main_security_ctx_user(THD * thd)
static inline const char *thd_inst_main_security_ctx_user(THD *thd)
{
Security_context * sctx = thd_inst_main_security_ctx(thd);
if(!Audit_formatter::thd_offsets.sec_ctx_user) //no offsets use compiled in header
Security_context *sctx = thd_inst_main_security_ctx(thd);
if (! Audit_formatter::thd_offsets.sec_ctx_user) // no offsets use compiled in header
{
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
return sctx->user;
@ -237,13 +234,13 @@ public:
+ Audit_formatter::thd_offsets.sec_ctx_user);
}
static inline const char * thd_inst_main_security_ctx_host(THD * thd)
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
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
{
//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
// 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
#if defined(MARIADB_BASE_VERSION)
return sctx->host;
#else
@ -263,12 +260,12 @@ public:
+ Audit_formatter::thd_offsets.sec_ctx_host);
}
static inline const char * thd_inst_main_security_ctx_ip(THD * thd)
static inline const char *thd_inst_main_security_ctx_ip(THD *thd)
{
Security_context * sctx = thd_inst_main_security_ctx(thd);
if(!Audit_formatter::thd_offsets.sec_ctx_ip) //no offsets use compiled in header
Security_context *sctx = thd_inst_main_security_ctx(thd);
if (! Audit_formatter::thd_offsets.sec_ctx_ip) // no offsets use compiled in header
{
//interface changed in 5.5.34 and 5.6.14 and up host changed to get_ip()
// interface changed in 5.5.34 and 5.6.14 and up host changed to get_ip()
#if defined(MARIADB_BASE_VERSION)
return sctx->ip;
#else
@ -288,10 +285,10 @@ public:
+ Audit_formatter::thd_offsets.sec_ctx_ip);
}
static inline const char * thd_inst_main_security_ctx_priv_user(THD * thd)
static inline const char *thd_inst_main_security_ctx_priv_user(THD *thd)
{
Security_context * sctx = thd_inst_main_security_ctx(thd);
if(!Audit_formatter::thd_offsets.sec_ctx_priv_user) //no offsets use compiled in header
Security_context *sctx = thd_inst_main_security_ctx(thd);
if (! Audit_formatter::thd_offsets.sec_ctx_priv_user) // no offsets use compiled in header
{
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 50709
return sctx->priv_user;
@ -300,53 +297,50 @@ public:
#endif
}
#if MYSQL_VERSION_ID < 50505
//in 5.1.x priv_user is a pointer
// 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])
// 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)
static inline int thd_inst_command(THD *thd)
{
return *(int *) (((unsigned char *) thd) + Audit_formatter::thd_offsets.command);
}
static inline LEX* thd_lex(THD * thd)
static inline LEX *thd_lex(THD *thd)
{
return *(LEX**) (((unsigned char *) thd) + Audit_formatter::thd_offsets.lex);
return *(LEX **) (((unsigned char *) thd) + Audit_formatter::thd_offsets.lex);
}
//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)
// 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)
{
return table->db;
}
static inline const char * table_get_name(TABLE_LIST * table)
static inline const char *table_get_name(TABLE_LIST *table)
{
return table->table_name;
}
static inline bool table_is_view(TABLE_LIST * table)
static inline bool table_is_view(TABLE_LIST *table)
{
return table->view_tables != 0;
}
};
/**
* Format the audit even in json format
*/
class Audit_json_formatter: public Audit_formatter
{
class Audit_json_formatter: public Audit_formatter {
public:
static const char * DEF_MSG_DELIMITER;
static const char *DEF_MSG_DELIMITER;
Audit_json_formatter(): m_msg_delimiter(NULL), m_write_start_msg(true), m_password_mask_regex_preg(NULL),
m_password_mask_regex_compiled(false), m_perform_password_masking(NULL)
@ -354,9 +348,10 @@ public:
config.beautify = 0;
config.indentString = NULL;
}
virtual ~Audit_json_formatter()
{
if(m_password_mask_regex_preg)
if (m_password_mask_regex_preg)
{
m_password_mask_regex_compiled = false;
pcre_free(m_password_mask_regex_preg);
@ -364,20 +359,20 @@ public:
}
}
virtual ssize_t event_format(ThdSesData *pThdData, IWriter * writer);
virtual ssize_t start_msg_format(IWriter * writer);
virtual ssize_t event_format(ThdSesData *pThdData, IWriter *writer);
virtual ssize_t start_msg_format(IWriter *writer);
/**
* Utility method used to compile a regex program. Will compile and log errors if necessary.
* Return null if fails
*/
static pcre * regex_compile(const char * str);
static pcre *regex_compile(const char *str);
/**
* Compile password masking regex
* Return 0 on success
* Return true on success
*/
int compile_password_masking_regex(const char * str);
bool compile_password_masking_regex(const char *str);
/**
* Boolean indicating if to log start msg.
@ -389,7 +384,7 @@ public:
/**
* Callback function to determine if password masking should be performed
*/
my_bool (* m_perform_password_masking)(const char *cmd);
my_bool (*m_perform_password_masking)(const char *cmd);
/**
* Message delimiter. Should point to a valid json string (supporting the json escapping format).
@ -397,7 +392,7 @@ public:
*
* We only support a delimiter up to 32 chars
*/
char * m_msg_delimiter;
char *m_msg_delimiter;
/**
* Configuration of yajl. Leave public so sysvar can update this directly.
@ -417,24 +412,19 @@ protected:
/**
* Regex used for password masking
*/
pcre * m_password_mask_regex_preg;
pcre *m_password_mask_regex_preg;
};
/**
* Base class for audit handlers. Provides basic locking setup.
*/
class Audit_handler
{
class Audit_handler {
public:
static const size_t MAX_AUDIT_HANDLERS_NUM = 4;
static const size_t JSON_FILE_HANDLER = 1;
static const size_t JSON_SOCKET_HANDLER = 3;
static Audit_handler * m_audit_handler_list[];
static Audit_handler *m_audit_handler_list[];
/**
* Will iterate the handler list and log using each handler
@ -447,7 +437,8 @@ public:
static void stop_all();
Audit_handler() :
m_initialized(false), m_enabled(false), m_print_offset_err(true), m_formatter(NULL), m_failed(false), m_log_io_errors(true)
m_initialized(false), m_enabled(false), m_print_offset_err(true),
m_formatter(NULL), m_failed(false), m_log_io_errors(true)
{
}
@ -467,7 +458,7 @@ public:
* @frmt the formatter to use in this handler (does not manage distruction of this object)
* @return 0 on success
*/
int init(Audit_formatter * frmt)
int init(Audit_formatter *frmt)
{
m_formatter = frmt;
if (m_initialized)
@ -516,9 +507,9 @@ public:
unsigned int m_retry_interval;
protected:
Audit_formatter * m_formatter;
Audit_formatter *m_formatter;
virtual void handler_start();
//wiil call internal method and set failed as needed
// wiil call internal method and set failed as needed
bool handler_start_nolock();
virtual void handler_stop();
virtual bool handler_start_internal() = 0;
@ -540,15 +531,15 @@ protected:
return m_failed && (m_retry_interval < 0 ||
difftime(time(NULL), m_last_retry_sec_ts) > m_retry_interval);
}
//override default assignment and copy to protect against creating additional instances
// override default assignment and copy to protect against creating additional instances
Audit_handler & operator=(const Audit_handler&);
Audit_handler(const Audit_handler&);
private:
//bool indicating if to print offset errors to log or not
// bool indicating if to print offset errors to log or not
bool m_print_offset_err;
//lock io
// lock io
pthread_mutex_t LOCK_io;
//audit (enable) lock
// audit (enable) lock
rw_lock_t LOCK_audit;
inline void lock_shared()
{
@ -567,10 +558,10 @@ private:
/**
* Base class for handler which have io and need a lock
*/
class Audit_io_handler: public Audit_handler, public IWriter
{
class Audit_io_handler: public Audit_handler, public IWriter {
public:
Audit_io_handler() : m_io_dest(NULL), m_io_type(NULL)
Audit_io_handler()
: m_io_dest(NULL), m_io_type(NULL)
{
}
@ -582,17 +573,16 @@ public:
/**
* target we write to (socket/file). Public so we update via sysvar
*/
char * m_io_dest;
char *m_io_dest;
protected:
virtual bool handler_start_internal();
virtual void handler_stop_internal();
//used for logging messages
const char * m_io_type;
// used for logging messages
const char *m_io_type;
};
class Audit_file_handler: public Audit_io_handler
{
class Audit_file_handler: public Audit_io_handler {
public:
Audit_file_handler() :
@ -621,32 +611,27 @@ public:
/**
* Write function we pass to formatter
*/
ssize_t write(const char * data, size_t size);
ssize_t write(const char *data, size_t size);
void close();
int open(const char * io_dest, bool m_log_errors);
//static void print_sleep (THD *thd, int delay_ms);
int open(const char *io_dest, bool m_log_errors);
// static void print_sleep(THD *thd, int delay_ms);
protected:
//override default assignment and copy to protect against creating additional instances
// override default assignment and copy to protect against creating additional instances
Audit_file_handler & operator=(const Audit_file_handler&);
Audit_file_handler(const Audit_file_handler&);
/**
* Will acquire locks and call handler_write
*/
virtual bool handler_log_audit(ThdSesData *pThdData);
FILE * m_log_file;
//the period to use for syncing
FILE *m_log_file;
// the period to use for syncing
unsigned int m_sync_counter;
};
class Audit_socket_handler: public Audit_io_handler
{
class Audit_socket_handler: public Audit_io_handler {
public:
Audit_socket_handler() :
@ -668,13 +653,13 @@ public:
/**
* Write function we pass to formatter
*/
ssize_t write(const char * data, size_t size);
ssize_t write(const char *data, size_t size);
void close();
int open(const char * io_dest, bool log_errors);
int open(const char *io_dest, bool log_errors);
protected:
//override default assignment and copy to protect against creating additional instances
// override default assignment and copy to protect against creating additional instances
Audit_socket_handler & operator=(const Audit_socket_handler&);
Audit_socket_handler(const Audit_socket_handler&);
@ -682,10 +667,9 @@ protected:
* Will acquire locks and call handler_write
*/
virtual bool handler_log_audit(ThdSesData *pThdData);
//Vio we write to
//define as void* so we don't access members directly
void * m_vio;
// Vio we write to
// define as void* so we don't access members directly
void *m_vio;
};
#endif /* AUDIT_HANDLER_H_ */

4
include/md5.h Executable file → Normal file
View File

@ -43,13 +43,13 @@ extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
//define the my_MD5* functions
// define the my_MD5* functions
#define my_MD5Context MD5_CTX
#define my_MD5Init MD5_Init
#define my_MD5Update MD5_Update
#define my_MD5Final MD5_Final
#endif //#if MYSQL_VERSION_ID >= 50600
#endif // #if MYSQL_VERSION_ID >= 50600
#endif

View File

@ -8,8 +8,8 @@
#define MYSQL_DYNAMIC_PLUGIN 1
#define MYSQL_SERVER 1
//Fix for VIO. We don't want to using method mapping as then a change in the struct will cause the offsets compiled with to
//be wrong. As is the case with ndb which uses a version of Vio with support for ipv6 similar to 5.5 but different from 5.1
// Fix for VIO. We don't want to using method mapping as then a change in the struct will cause the offsets compiled with to
// be wrong. As is the case with ndb which uses a version of Vio with support for ipv6 similar to 5.5 but different from 5.1
#define DONT_MAP_VIO
#include <my_config.h>
@ -19,7 +19,7 @@
#include <mysql_priv.h>
#else
//version 5.5.x doesn't contain mysql_priv.h . We need to add the includes provided by it.
// 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
@ -43,7 +43,7 @@
#include <sql/sql_table.h>
#include <sql/sql_view.h>
//TODO: use mysql mutex instead of pthread
// TODO: use mysql mutex instead of pthread
/*
#define pthread_mutex_lock mysql_mutex_lock
#define pthread_mutex_unlock mysql_mutex_unlock
@ -67,8 +67,8 @@
#include <my_dir.h>
#include <my_sys.h>
//5.5 use my_free with a single param. 5.1 use with 2 params
//based on: http://bazaar.launchpad.net/~mysql/myodbc/5.1/view/head:/util/stringutil.h
// 5.5 use my_free with a single param. 5.1 use with 2 params
// based on: http://bazaar.launchpad.net/~mysql/myodbc/5.1/view/head:/util/stringutil.h
#ifndef x_free
# if MYSQL_VERSION_ID >= 50500
# define x_free(A) { void *tmp= (A); if (tmp) my_free((char *) tmp); }
@ -77,23 +77,19 @@
# endif
#endif
//MariaDB doesn't have my_getsystime (returns 100 nano seconds) function. They replaced with my_hrtime_t my_hrtime() which returns microseconds
// MariaDB doesn't have my_getsystime (returns 100 nano seconds) function. They replaced with my_hrtime_t my_hrtime() which returns microseconds
#if defined(MARIADB_BASE_VERSION)
#define my_getsystime() ((my_hrtime()).val * 10)
//MariaDB has a kill service that overrides thd_killed as a macro. It also has thd_killed function defined for backwards compatibility, so we redefine it.
// MariaDB has a kill service that overrides thd_killed as a macro. It also has thd_killed function defined for backwards compatibility, so we redefine it.
#undef thd_killed
extern "C" int thd_killed(const MYSQL_THD thd);
//MariadDB 10.0.10 removed the include for thd_security_context
// MariadDB 10.0.10 removed the include for thd_security_context
#if MYSQL_VERSION_ID >= 100010
extern "C" char *thd_security_context(MYSQL_THD thd, char *buffer, unsigned int length, unsigned int max_query_len);
#endif
#endif
#endif //MYSQL_INCL_H
#endif // MYSQL_INCL_H

View File

@ -18,16 +18,17 @@
* Created on: Feb 6, 2011
* Author: guyl
*/
#include "audit_handler.h"
//for definition of sockaddr_un
// for definition of sockaddr_un
#include <sys/un.h>
#include <stdio_ext.h>
#include "static_assert.h"
//utility macro to log also with a date as a prefix
#define log_with_date(f, ...) do{\
// 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);\
time_t result = time(NULL);\
localtime_r(&result, &tm_tmp);\
fprintf(f, "%02d%02d%02d %2d:%02d:%02d: ",\
tm_tmp.tm_year % 100,\
@ -37,23 +38,21 @@
tm_tmp.tm_min,\
tm_tmp.tm_sec);\
fprintf(f, __VA_ARGS__);\
}while(0)
} while (0)
//regex flags used in compilation
// regex flags used in compilation
static const int regex_flags = PCRE_DOTALL | PCRE_UTF8 | PCRE_CASELESS | PCRE_DUPNAMES;
//initialize static stuff
// initialize static stuff
ThdOffsets Audit_formatter::thd_offsets = { 0 };
Audit_handler * Audit_handler::m_audit_handler_list[Audit_handler::MAX_AUDIT_HANDLERS_NUM];
Audit_handler *Audit_handler::m_audit_handler_list[Audit_handler::MAX_AUDIT_HANDLERS_NUM];
const char * Audit_json_formatter::DEF_MSG_DELIMITER = "\\n";
#if MYSQL_VERSION_ID < 50709
#define C_STRING_WITH_LEN(X) ((char *) (X)), ((size_t) (sizeof(X) - 1))
#endif
const char * Audit_formatter::retrieve_object_type (TABLE_LIST *pObj)
const char *Audit_formatter::retrieve_object_type(TABLE_LIST *pObj)
{
if (table_is_view(pObj))
{
@ -62,7 +61,6 @@ const char * Audit_formatter::retrieve_object_type (TABLE_LIST *pObj)
return "TABLE";
}
void Audit_handler::stop_all()
{
for (size_t i = 0; i < MAX_AUDIT_HANDLERS_NUM; ++i)
@ -88,7 +86,7 @@ void Audit_handler::log_audit_all(ThdSesData *pThdData)
void Audit_handler::set_enable(bool val)
{
lock_exclusive();
if (m_enabled == val) //we are already enabled simply return
if (m_enabled == val) // we are already enabled simply return
{
unlock();
return;
@ -96,12 +94,12 @@ void Audit_handler::set_enable(bool val)
m_enabled = val;
if (m_enabled)
{
//call the startup of the handler
// call the startup of the handler
handler_start();
}
else
{
//call the cleanup of the handler
// call the cleanup of the handler
handler_stop();
}
unlock();
@ -110,14 +108,14 @@ void Audit_handler::set_enable(bool val)
void Audit_handler::flush()
{
lock_exclusive();
if (!m_enabled) //if not running we don't flush
if (! m_enabled) // if not running we don't flush
{
unlock();
return;
}
//call the cleanup of the handler
// call the cleanup of the handler
handler_stop();
//call the startup of the handler
// call the startup of the handler
handler_start();
sql_print_information("%s Log flush complete.", AUDIT_LOG_PREFIX);
unlock();
@ -126,13 +124,13 @@ void Audit_handler::flush()
void Audit_handler::log_audit(ThdSesData *pThdData)
{
lock_shared();
if (!m_enabled)
if (! m_enabled)
{
unlock();
return;
}
//sanity check that offsets match
//we can also consider using secutiry context function to do some sanity checks
// 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);
@ -149,24 +147,25 @@ void Audit_handler::log_audit(ThdSesData *pThdData)
}
}
else
{//offsets are good
m_print_offset_err = true; //mark to print offset err to log incase we encounter in the future
{
// offsets are good
m_print_offset_err = true; // mark to print offset err to log in case we encounter in the future
pthread_mutex_lock(&LOCK_io);
//check if failed
// check if failed
bool do_log = true;
if (m_failed)
{
do_log = false;
bool retry = m_retry_interval > 0 &&
difftime(time(NULL), m_last_retry_sec_ts) > m_retry_interval;
if(retry)
if (retry)
{
do_log = handler_start_nolock();
}
}
if(do_log)
if (do_log)
{
if(!handler_log_audit(pThdData))
if (! handler_log_audit(pThdData))
{
set_failed();
handler_stop_internal();
@ -186,10 +185,10 @@ void Audit_file_handler::close()
m_log_file = NULL;
}
ssize_t Audit_file_handler::write(const char * data, size_t size)
ssize_t Audit_file_handler::write(const char *data, size_t size)
{
ssize_t res = my_fwrite(m_log_file, (uchar *) data, size, MYF(0));
if(res < 0) // log the error
if (res < 0) // log the error
{
sql_print_error("%s failed writing to file: %s. Err: %s",
AUDIT_LOG_PREFIX, m_io_dest, strerror(errno));
@ -197,14 +196,15 @@ ssize_t Audit_file_handler::write(const char * data, size_t size)
return res;
}
int Audit_file_handler::open(const char * io_dest, bool log_errors)
int Audit_file_handler::open(const char *io_dest, bool log_errors)
{
char format_name[FN_REFLEN];
fn_format(format_name, io_dest, "", "", MY_UNPACK_FILENAME);
m_log_file = my_fopen(format_name, O_WRONLY | O_APPEND| O_CREAT, MYF(0));
if (!m_log_file)
if (! m_log_file)
{
if(log_errors)
if (log_errors)
{
sql_print_error(
"%s unable to open file %s: %s. audit file handler disabled!!",
@ -212,16 +212,18 @@ int Audit_file_handler::open(const char * io_dest, bool log_errors)
}
return -1;
}
ssize_t bufsize = BUFSIZ;
int res =0;
//0 -> use default, 1 or negative -> disabled
if(m_bufsize > 1)
int res = 0;
// 0 -> use default, 1 or negative -> disabled
if (m_bufsize > 1)
{
bufsize = m_bufsize;
}
if(1 == m_bufsize || m_bufsize < 0)
if (1 == m_bufsize || m_bufsize < 0)
{
//disabled
// disabled
res = setvbuf(m_log_file, NULL, _IONBF, 0);
}
else
@ -229,7 +231,8 @@ int Audit_file_handler::open(const char * io_dest, bool log_errors)
res = setvbuf(m_log_file, NULL, _IOFBF, bufsize);
}
if(res)
if (res)
{
sql_print_error(
"%s unable to set bufzie [%zd (%ld)] for file %s: %s.",
@ -240,12 +243,12 @@ int Audit_file_handler::open(const char * io_dest, bool log_errors)
return 0;
}
//no locks. called by handler_start and when it is time to retry
// no locks. called by handler_start and when it is time to retry
bool Audit_io_handler::handler_start_internal()
{
if(!m_io_dest || strlen(m_io_dest) == 0)
if (! m_io_dest || strlen(m_io_dest) == 0)
{
if(m_log_io_errors)
if (m_log_io_errors)
{
sql_print_error(
"%s %s: io destination not set. Not connecting.",
@ -255,16 +258,16 @@ bool Audit_io_handler::handler_start_internal()
}
if (open(m_io_dest, m_log_io_errors) != 0)
{
//open failed
// open failed
return false;
}
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.
* Sanity check of writing to the log. If we fail, we print an erorr and disable this handler.
*/
if (res < 0)
{
if(m_log_io_errors)
if (m_log_io_errors)
{
sql_print_error(
"%s unable to write header msg to %s: %s.",
@ -279,7 +282,7 @@ bool Audit_io_handler::handler_start_internal()
void Audit_io_handler::handler_stop_internal()
{
if(!m_failed)
if (! m_failed)
{
m_formatter->stop_msg_format(this);
}
@ -289,7 +292,7 @@ void Audit_io_handler::handler_stop_internal()
bool Audit_handler::handler_start_nolock()
{
bool res = handler_start_internal();
if(res)
if (res)
{
m_failed = false;
}
@ -307,6 +310,7 @@ void Audit_handler::handler_start()
handler_start_nolock();
pthread_mutex_unlock(&LOCK_io);
}
void Audit_handler::handler_stop()
{
pthread_mutex_lock(&LOCK_io);
@ -320,11 +324,11 @@ bool Audit_file_handler::handler_log_audit(ThdSesData *pThdData)
if (res && m_sync_period && ++m_sync_counter >= 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).
// 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).
res = (fflush(m_log_file) == 0);
if(res)
if (res)
{
int fd = fileno(m_log_file);
res = (my_sync(fd, MYF(MY_WME)) == 0);
@ -339,16 +343,16 @@ void Audit_socket_handler::close()
{
if (m_vio)
{
//no need for vio_close as is called by delete (additionally close changed its name to vio_shutdown in 5.6.11)
// no need for vio_close as is called by delete (additionally close changed its name to vio_shutdown in 5.6.11)
vio_delete((Vio*)m_vio);
}
m_vio = NULL;
}
ssize_t Audit_socket_handler::write(const char * data, size_t size)
ssize_t Audit_socket_handler::write(const char *data, size_t size)
{
ssize_t res = vio_write((Vio*)m_vio, (const uchar *) data, size);
if(res < 0) // log the error
if (res < 0) // log the error
{
sql_print_error("%s failed writing to socket: %s. Err: %s",
AUDIT_LOG_PREFIX, m_io_dest, strerror(vio_errno((Vio*)m_vio)));
@ -356,13 +360,13 @@ ssize_t Audit_socket_handler::write(const char * data, size_t size)
return res;
}
int Audit_socket_handler::open(const char * io_dest, bool log_errors)
int Audit_socket_handler::open(const char *io_dest, bool log_errors)
{
//open the socket
int sock = socket(AF_UNIX,SOCK_STREAM,0);
// open the socket
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
{
if(log_errors)
if (log_errors)
{
sql_print_error(
"%s unable to create unix socket: %s.",
@ -371,8 +375,8 @@ int Audit_socket_handler::open(const char * io_dest, bool log_errors)
return -1;
}
//connect the socket
m_vio= vio_new(sock, VIO_TYPE_SOCKET, VIO_LOCALHOST);
// 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, io_dest, sizeof(UNIXaddr.sun_path)-1);
@ -380,12 +384,12 @@ int Audit_socket_handler::open(const char * io_dest, bool log_errors)
if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
m_connect_timeout))
#else
//in 5.6 timeout is in ms
// in 5.6 timeout is in ms
if (vio_socket_connect((Vio*)m_vio,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
m_connect_timeout * 1000))
#endif
{
if(log_errors)
if (log_errors)
{
sql_print_error(
"%s unable to connect to socket: %s. err: %s.",
@ -406,38 +410,38 @@ bool Audit_socket_handler::handler_log_audit(ThdSesData *pThdData)
static yajl_gen_status yajl_add_string(yajl_gen hand, const char * str)
static 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 void yajl_add_string_val(yajl_gen hand, const char * name, const char* val)
static void yajl_add_string_val(yajl_gen hand, const char *name, const char *val)
{
if(0 == val)
if (0 == val)
{
return; //we don't add NULL values to json
return; // we don't add NULL values to json
}
yajl_add_string(hand, name);
yajl_add_string(hand, val);
}
static void yajl_add_string_val(yajl_gen hand, const char * name, const char* val, size_t val_len)
static 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);
}
static void yajl_add_uint64(yajl_gen gen, const char * name, uint64 num)
static 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);
}
static void yajl_add_obj( yajl_gen gen, const char *db,const char* ptype,const char * name =NULL)
static void yajl_add_obj(yajl_gen gen, const char *db, const char *ptype, const char *name = NULL)
{
if(db)
if (db)
{
yajl_add_string_val(gen, "db", db);
}
@ -445,37 +449,36 @@ static void yajl_add_obj( yajl_gen gen, const char *db,const char* ptype,const
{
yajl_add_string_val(gen, "name", name);
}
yajl_add_string_val(gen, "obj_type",ptype);
yajl_add_string_val(gen, "obj_type", ptype);
}
static const char * retrieve_user (THD * thd)
static const char *retrieve_user(THD *thd)
{
const char * user = Audit_formatter::thd_inst_main_security_ctx_user(thd);
if(user != NULL && *user != 0x0) //non empty
const char *user = Audit_formatter::thd_inst_main_security_ctx_user(thd);
if (user != NULL && *user != '\0') // non empty
{
return user;
}
user = Audit_formatter::thd_inst_main_security_ctx_priv_user(thd); //try using priv user
if(user != NULL && *user != 0x0) //non empty
user = Audit_formatter::thd_inst_main_security_ctx_priv_user(thd); // try using priv user
if (user != NULL && *user != '\0') // non empty
{
return user;
}
return ""; //always use at least the empty string
return ""; // always use at least the empty string
}
//will return a pointer to the query and set len with the length of the query
//starting with MySQL version 5.1.41 thd_query_string is added
//And at 5.7 it changed
// will return a pointer to the query and set len with the length of the query
// starting with MySQL version 5.1.41 thd_query_string is added
// And at 5.7 it changed
#if ! defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50709
extern "C" LEX_CSTRING thd_query_unsafe(MYSQL_THD thd);
static const char * thd_query_str(THD * thd, size_t * len)
static const char *thd_query_str(THD *thd, size_t *len)
{
const LEX_CSTRING str = thd_query_unsafe(thd);
if(str.length > 0)
if (str.length > 0)
{
*len = str.length;
return str.str;
@ -489,10 +492,11 @@ static const char * thd_query_str(THD * thd, size_t * len)
extern "C" {
MYSQL_LEX_STRING *thd_query_string(MYSQL_THD thd);
}
static const char * thd_query_str(THD * thd, size_t * len)
static const char *thd_query_str(THD *thd, size_t *len)
{
MYSQL_LEX_STRING * str = thd_query_string(thd);
if(str)
if (str)
{
*len = str->length;
return str->str;
@ -501,21 +505,22 @@ static const char * thd_query_str(THD * thd, size_t * len)
return NULL;
}
#else
//we are being compiled against mysql version 5.1.40 or lower (our default compilation env)
//we still want to support thd_query_string if we are run on a version higher than 5.1.40, so we try to lookup the symbol
// we are being compiled against mysql version 5.1.40 or lower (our default compilation env)
// we still want to support thd_query_string if we are run on a version higher than 5.1.40, so we try to lookup the symbol
static LEX_STRING * (*thd_query_string_func)(THD *thd) = (LEX_STRING*(*)(THD*))dlsym(RTLD_DEFAULT, "thd_query_string");
static bool print_thd_query_string_func = true; //debug info print only once
static const char * thd_query_str(THD * thd, size_t * len)
static bool print_thd_query_string_func = true; // debug info print only once
static const char *thd_query_str(THD *thd, size_t *len)
{
if(print_thd_query_string_func)
if (print_thd_query_string_func)
{
sql_print_information("%s thd_query_string_func: 0x%lx", AUDIT_LOG_PREFIX, (unsigned long)thd_query_string_func);
print_thd_query_string_func = false;
}
if(thd_query_string_func)
if (thd_query_string_func)
{
MYSQL_LEX_STRING * str = thd_query_string_func(thd);
if(str)
MYSQL_LEX_STRING *str = thd_query_string_func(thd);
if (str)
{
*len = str->length;
return str->str;
@ -528,13 +533,14 @@ static const char * thd_query_str(THD * thd, size_t * len)
}
#endif
ssize_t Audit_json_formatter::start_msg_format(IWriter * writer)
ssize_t Audit_json_formatter::start_msg_format(IWriter *writer)
{
if(!m_write_start_msg) //disabled
if (! m_write_start_msg) // disabled
{
return 0;
}
//initialize yajl
// initialize yajl
yajl_gen gen = yajl_gen_alloc(&config, NULL);
yajl_gen_map_open(gen);
yajl_add_string_val(gen, "msg-type", "header");
@ -548,24 +554,24 @@ ssize_t Audit_json_formatter::start_msg_format(IWriter * writer)
yajl_add_string_val(gen, "mysql-socket", mysqld_unix_port);
yajl_add_uint64(gen, "mysql-port", mysqld_port);
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
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;
const unsigned char *text = NULL;
unsigned int len = 0;
yajl_gen_get_buf(gen, &text, &len);
//print the json
// print the json
res = writer->write((const char *)text, len);
if(res >= 0)
if (res >= 0)
{
//TODO: use the msg_delimiter
// 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
yajl_gen_free(gen); // free the generator
return res;
}
// This routine replaces clear text with the string in `replace', leaving the rest of the string intact.
@ -602,19 +608,19 @@ static const char *replace_in_string(THD *thd,
return new_str;
}
ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * writer)
ssize_t Audit_json_formatter::event_format(ThdSesData *pThdData, IWriter *writer)
{
THD * thd = pThdData->getTHD();
THD *thd = pThdData->getTHD();
unsigned long thdid = thd_get_thread_id(thd);
query_id_t qid = thd_inst_query_id(thd);
//initialize yajl
// 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
// 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);
@ -625,15 +631,16 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
yajl_add_string_val(gen, "ip", Audit_formatter::thd_inst_main_security_ctx_ip(thd));
const char *cmd = pThdData->getCmdName();
yajl_add_string_val(gen, "cmd", cmd);
//get objects
if(pThdData->startGetObjects())
// get objects
if (pThdData->startGetObjects())
{
yajl_add_string(gen, "objects");
yajl_gen_array_open(gen);
const char * db_name = NULL;
const char * obj_name = NULL;
const char * obj_type = NULL;
while(pThdData->getNextObject(&db_name, &obj_name, &obj_type))
const char *db_name = NULL;
const char *obj_name = NULL;
const char *obj_type = NULL;
while (pThdData->getNextObject(&db_name, &obj_name, &obj_type))
{
yajl_gen_map_open(gen);
yajl_add_obj (gen, db_name, obj_type, obj_name );
@ -643,7 +650,7 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
}
size_t qlen = 0;
const char * query = thd_query_str(pThdData->getTHD(), &qlen);
const char *query = thd_query_str(pThdData->getTHD(), &qlen);
if (query && qlen > 0)
{
#if MYSQL_VERSION_ID < 50600
@ -658,7 +665,8 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
const char *query_text = query;
size_t query_len = qlen;
if (strcmp(col_connection->csname, "utf8") != 0) {
if (strcmp(col_connection->csname, "utf8") != 0)
{
// max UTF-8 bytes per char is 4.
size_t to_amount = (qlen * 4) + 1;
char* to = (char *) thd_alloc(thd, to_amount);
@ -676,20 +684,23 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
qlen = len;
}
if(m_perform_password_masking && m_password_mask_regex_compiled && m_password_mask_regex_preg && m_perform_password_masking(cmd))
if (m_perform_password_masking
&& m_password_mask_regex_compiled
&& m_password_mask_regex_preg
&& m_perform_password_masking(cmd))
{
//do password masking
int matches[90] = {0};
if(pcre_exec(m_password_mask_regex_preg, NULL, query_text, query_len, 0, 0, matches, array_elements(matches)) >= 0)
// do password masking
int matches[90] = { 0 };
if (pcre_exec(m_password_mask_regex_preg, NULL, query_text, query_len, 0, 0, matches, array_elements(matches)) >= 0)
{
//search for the first substring that matches with the name psw
// search for the first substring that matches with the name psw
char *first = NULL, *last = NULL;
int entrysize = pcre_get_stringtable_entries(m_password_mask_regex_preg, "psw", &first, &last);
if(entrysize > 0)
if (entrysize > 0)
{
for (unsigned char * entry = (unsigned char *)first; entry <= (unsigned char *)last; entry += entrysize)
for (unsigned char *entry = (unsigned char *)first; entry <= (unsigned char *)last; entry += entrysize)
{
//first 2 bytes give us the number
// first 2 bytes give us the number
int n = (((int)(entry)[0]) << 8) | (entry)[1];
if (n > 0 && n < (int)array_elements(matches) && matches[n*2] >= 0)
{
@ -700,7 +711,12 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
// interfaces in MySQL have changed fairly drastically. So we just do the
// replacement ourselves.
const char *pass_replace = "***";
const char *updated = replace_in_string(thd, query_text, query_len, matches[n*2], matches[(n*2) + 1] - matches[n*2], pass_replace);
const char *updated = replace_in_string(thd,
query_text,
query_len,
matches[n*2],
matches[(n*2) + 1] - matches[n*2],
pass_replace);
query_text = updated;
query_len = strlen(query_text);
break;
@ -713,39 +729,38 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
}
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
{
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
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;
const unsigned char *text = NULL;
unsigned int len = 0;
yajl_gen_get_buf(gen, &text, &len);
//print the json
// print the json
res = writer->write((const char *)text, len);
if(res >= 0)
if (res >= 0)
{
//TODO: use the msg_delimiter
// 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
yajl_gen_free(gen); // free the generator
return res;
}
ThdSesData::ThdSesData (THD *pTHD) :
m_pThd (pTHD), m_CmdName(NULL), m_UserName(NULL),
ThdSesData::ThdSesData(THD *pTHD)
: 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)
{
@ -755,56 +770,56 @@ ThdSesData::ThdSesData (THD *pTHD) :
bool ThdSesData::startGetObjects()
{
//reset vars as this may be called multiple times
// reset vars as this may be called multiple times
m_objIterType = OBJ_NONE;
m_tables = NULL;
m_firstTable = true;
m_index = 0;
m_tableInf = Audit_formatter::getQueryCacheTableList1(getTHD());
int command = Audit_formatter::thd_inst_command(getTHD());
LEX * pLex = Audit_formatter::thd_lex(getTHD());
//query cache case
if(pLex && command == COM_QUERY && m_tableInf && m_tableInf->num_of_elem > 0)
LEX *pLex = Audit_formatter::thd_lex(getTHD());
// query cache case
if (pLex && command == COM_QUERY && m_tableInf && m_tableInf->num_of_elem > 0)
{
m_objIterType = OBJ_QUERY_CACHE;
return true;
}
const char *cmd = getCmdName();
//commands which have single database object
if (strcmp (cmd,"Init DB") ==0
|| strcmp (cmd, "SHOW TABLES")== 0
|| strcmp (cmd, "SHOW TABLE")==0)
// commands which have single database object
if (strcmp(cmd,"Init DB") == 0
|| strcmp(cmd, "SHOW TABLES") == 0
|| strcmp(cmd, "SHOW TABLE") == 0)
{
if(Audit_formatter::thd_db(getTHD()))
if (Audit_formatter::thd_db(getTHD()))
{
m_objIterType = OBJ_DB;
return true;
}
return false;
}
//only return query tabls if command is COM_QUERY
//TODO: check if other commands can also generate query tables such as "show fields"
// only return query tables if command is COM_QUERY
// TODO: check if other commands can also generate query tables such as "show fields"
if (pLex && command == COM_QUERY && pLex->query_tables)
{
m_tables = pLex->query_tables;
m_objIterType = OBJ_TABLE_LIST;
return true;
}
//no objects
// no objects
return false;
}
bool ThdSesData::getNextObject(const char ** db_name, const char ** obj_name, const char ** obj_type)
bool ThdSesData::getNextObject(const char **db_name, const char **obj_name, const char **obj_type)
{
switch(m_objIterType)
{
case OBJ_DB:
{
if(m_firstTable)
if (m_firstTable)
{
*db_name = Audit_formatter::thd_db(getTHD());
*obj_name = NULL;
if(obj_type)
if (obj_type)
{
*obj_type = "DATABASE";
}
@ -815,12 +830,12 @@ bool ThdSesData::getNextObject(const char ** db_name, const char ** obj_name, co
}
case OBJ_QUERY_CACHE:
{
if(m_index < m_tableInf->num_of_elem &&
if (m_index < m_tableInf->num_of_elem &&
m_index< MAX_NUM_QUERY_TABLE_ELEM)
{
*db_name = m_tableInf->db[m_index];
*obj_name = m_tableInf->table_name[m_index];
if(obj_type)
if (obj_type)
{
*obj_type = m_tableInf->object_type[m_index];
}
@ -831,15 +846,15 @@ bool ThdSesData::getNextObject(const char ** db_name, const char ** obj_name, co
}
case OBJ_TABLE_LIST:
{
if(m_tables)
if (m_tables)
{
*db_name = Audit_formatter::table_get_db_name(m_tables);
*obj_name = Audit_formatter::table_get_name(m_tables);
if(obj_type)
if (obj_type)
{
//object is a view if it view command (alter_view, drop_view ..)
//and first object or view field is populated
if((m_firstTable && strstr(getCmdName(), "_view") != NULL) ||
// object is a view if it view command (alter_view, drop_view ..)
// and first object or view field is populated
if ((m_firstTable && strstr(getCmdName(), "_view") != NULL) ||
Audit_formatter::table_is_view(m_tables))
{
*obj_type = "VIEW";
@ -855,16 +870,16 @@ bool ThdSesData::getNextObject(const char ** db_name, const char ** obj_name, co
}
return false;
}
default :
default:
return false;
}
}
pcre * Audit_json_formatter::regex_compile(const char * str)
pcre *Audit_json_formatter::regex_compile(const char *str)
{
const char *error;
int erroffset;
pcre * re = pcre_compile(str, regex_flags, &error, &erroffset, NULL);
pcre *re = pcre_compile(str, regex_flags, &error, &erroffset, NULL);
if (!re)
{
sql_print_error("%s unable to compile regex [%s]. offset: %d message: [%s].",
@ -873,25 +888,26 @@ pcre * Audit_json_formatter::regex_compile(const char * str)
return re;
}
int Audit_json_formatter::compile_password_masking_regex(const char * str)
bool Audit_json_formatter::compile_password_masking_regex(const char *str)
{
//first free existing
if(m_password_mask_regex_compiled)
// first free existing
if (m_password_mask_regex_compiled)
{
m_password_mask_regex_compiled = false;
//small sleep to let threads oomplete regexc
// small sleep to let threads complete regexec
my_sleep(10 * 1000);
pcre_free(m_password_mask_regex_preg);
}
int error = 1; //default is error (case of empty string)
if(NULL != str && str[0] != '\0')
bool success = false; // default is error (case of empty string)
if (NULL != str && str[0] != '\0')
{
m_password_mask_regex_preg = regex_compile(str);
if(m_password_mask_regex_preg)
if (m_password_mask_regex_preg)
{
m_password_mask_regex_compiled = true;
error = 0;
success = true;
}
}
return error;
return success;
}

View File

@ -72,7 +72,6 @@ const ThdOffsets thd_offsets_arr[] =
{"5.5.38","ae5937fbe5856b36b1ac7b0cb400abdd", 6136, 6184, 3816, 4312, 88, 2592, 96, 0, 32, 104},
//offsets for: /mysqlrpm/5.6.19/usr/sbin/mysqld (5.6.19)
{"5.6.19","2a01471dc6b6b59ae25a7efe675d1af4", 7928, 7976, 3992, 4512, 72, 2704, 96, 0, 32, 104},
//offsets for: mysqlrpm/5.1.30/usr/sbin/mysqld (5.1.30-community)
{"5.1.30-community","8e43bda3644a883d46a1d064304b4f1d", 6184, 6248, 3656, 3928, 88, 2048},
//offsets for: mysqlrpm/5.1.31/usr/sbin/mysqld (5.1.31-community)
@ -157,7 +156,6 @@ const ThdOffsets thd_offsets_arr[] =
{"5.1.68-community","4042e9a2778090df6fd8481e03ed6737", 6376, 6440, 3736, 4008, 88, 2056},
//offsets for: /mysqlrpm/5.1.69/usr/sbin/mysqld (5.1.69-community)
{"5.1.69-community","e9cb524b604419964f4dd55a8c87d618", 6376, 6440, 3736, 4008, 88, 2056},
//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)
@ -216,7 +214,6 @@ const ThdOffsets thd_offsets_arr[] =
{"5.5.30-ndb-7.2.12-cluster-commercial-advanced","9f96bc38bf06a9b18a945227ff9e5c42", 6096, 6144, 3816, 4240, 88, 2568},
//offsets for: /mysqlrpm/5.5.31/usr/sbin/mysqld (5.5.31)
{"5.5.31","f6604e70b9592f484a7a04a0173f0b25", 6064, 6112, 3816, 4240, 88, 2568},
//offsets for: MySQL-server-5.6.10-1.el6.x86_64/usr/sbin/mysqld (5.6.10)
{"5.6.10","7016428728fe057d6825682d30e37b3d", 7808, 7856, 3960, 4400, 72, 2664},
//offsets for: /mysqlrpm/5.6.10/usr/sbin/mysqld (5.6.10)
@ -308,7 +305,6 @@ const ThdOffsets thd_offsets_arr[] =
{"5.1.68","673dd031ea4ad3493b47d74662a49079", 6392, 6456, 3752, 4024, 88, 2056},
//offsets for: /mysql/5.1.69/bin/mysqld (5.1.69)
{"5.1.69","af2936f85db019bfd44c7e12a2138707", 6392, 6456, 3752, 4024, 88, 2056},
//offsets for: mysql/5.5.8/bin/mysqld (5.5.8)
{"5.5.8","a32b163f08ca8bfd7486cd77200d9df3", 6032, 6080, 3776, 4200, 88, 2560},
//offsets for: mysql/5.5.9/bin/mysqld (5.5.9)
@ -362,12 +358,10 @@ const ThdOffsets thd_offsets_arr[] =
{"5.5.31","858dc19ffc5d34e669ab85d32a8a0623", 6064, 6112, 3816, 4240, 88, 2568},
//offsets for: /mysql/5.5.31/bin/mysqld (5.5.31)
{"5.5.31","61e65a4cc9360e03f3810ef2928c916d", 6064, 6112, 3816, 4240, 88, 2568},
//offsets for: /mysql/5.6.10/bin/mysqld (5.6.10)
{"5.6.10","37f9c31dd092bb2d0da7eb6e2098732f", 7808, 7856, 3960, 4400, 72, 2664},
//offsets for: /mysql/5.6.11/bin/mysqld (5.6.11)
{"5.6.11","85fd884192cc5cd12fba52b7b140c819", 7808, 7856, 3960, 4400, 72, 2672},
//offsets for: /mysqlrpm/5.1.70/usr/sbin/mysqld (5.1.70-community)
{"5.1.70-community","e70f9d48dad2a30b24e6c2744bed94d2", 6376, 6440, 3736, 4008, 88, 2072},
//offsets for: /mysqlrpm/5.5.32/usr/sbin/mysqld (5.5.32)
@ -481,7 +475,6 @@ const ThdOffsets thd_offsets_arr[] =
{"5.5.38","89e8b85dd5731e15df3d5597020c0ec8", 3868, 3896, 2368, 2748, 44, 1656, 60, 0, 20, 64},
//offsets for: /mysqlrpm/5.6.19/usr/sbin/mysqld (5.6.19)
{"5.6.19","3f94430e20b564951159aa78627df97f", 5652, 5680, 2656, 3048, 36, 1748, 60, 0, 20, 64},
//offsets for: mysqlrpm/5.1.30/usr/sbin/mysqld (5.1.30-community)
{"5.1.30-community","fdfe108d05c262c185a7c28b2e493c10", 4024, 4064, 2224, 2404, 44, 1180},
//offsets for: mysqlrpm/5.1.31/usr/sbin/mysqld (5.1.31-community)
@ -563,7 +556,6 @@ const ThdOffsets thd_offsets_arr[] =
{"5.1.68-community","df5dc268b36dbe853ed37d91fd4b6b3f", 4124, 4164, 2268, 2448, 44, 1180},
//offsets for: /mysqlrpm/5.1.69/usr/sbin/mysqld (5.1.69-community)
{"5.1.69-community","4c8acbca31f3f4ba44d35db9f5c65bc0", 4124, 4164, 2268, 2448, 44, 1180},
//offsets for: mysqlrpm/5.5.8/usr/sbin/mysqld (5.5.8)
{"5.5.8","3132e8c883f72caf4c8eddb24fd005b4", 3792, 3820, 2336, 2668, 44, 1640},
//offsets for: mysqlrpm/5.5.9/usr/sbin/mysqld (5.5.9)
@ -610,7 +602,6 @@ const ThdOffsets thd_offsets_arr[] =
{"5.5.30","0186d1ef4725814924bfe968e3455138", 3816, 3844, 2368, 2700, 44, 1644},
//offsets for: /mysqlrpm/5.5.31/usr/sbin/mysqld (5.5.31)
{"5.5.31","190e7556e226f8690ba8672869178e4c", 3816, 3844, 2368, 2700, 44, 1644},
//offsets for: /mysqlrpm/5.6.10/usr/sbin/mysqld (5.6.10)
{"5.6.10","dd3abddcfd0015de81b6a26b6190cefb", 5572, 5600, 2640, 2980, 36, 1712},
//offsets for: /mysqlrpm/5.6.11/usr/sbin/mysqld (5.6.11)
@ -696,7 +687,6 @@ const ThdOffsets thd_offsets_arr[] =
{"5.1.68","d03c42d8a8946f11ace86a5e1189114d", 4140, 4180, 2284, 2464, 44, 1180},
//offsets for: /mysql/5.1.69/bin/mysqld (5.1.69)
{"5.1.69","5abf5a9f9f9c01be997595b066a40986", 4140, 4180, 2284, 2464, 44, 1180},
//offsets for: /mysqlrpm/5.5.8/usr/sbin/mysqld (5.5.8)
{"5.5.8","3132e8c883f72caf4c8eddb24fd005b4", 3792, 3820, 2336, 2668, 44, 1640},
{"5.5.8","ad8a16d9bbfb783dab53f38cef757900", 3792, 3820, 2336, 2668, 44, 1640},
@ -748,12 +738,10 @@ const ThdOffsets thd_offsets_arr[] =
{"5.5.30","c7b98be45d35b77da6679c354c23d1fa", 3816, 3844, 2368, 2700, 44, 1644},
//offsets for: /mysql/5.5.31/bin/mysqld (5.5.31)
{"5.5.31","36631a7c748358598ba21cd4157545d9", 3816, 3844, 2368, 2700, 44, 1644},
//offsets for: /mysql/5.6.10/bin/mysqld (5.6.10)
{"5.6.10","84600f18354f519e38302c04fe55ed9c", 5572, 5600, 2640, 2980, 36, 1712},
//offsets for: /mysql/5.6.11/bin/mysqld (5.6.11)
{"5.6.11","72e67111f3c1d1c1d4e7095e3a004fcf", 5572, 5600, 2640, 2980, 36, 1724},
//offsets for: /mysqlrpm/5.1.70/usr/sbin/mysqld (5.1.70-community)
{"5.1.70-community","605c76c9d37a890cea85c075aeaaa2e6", 4124, 4164, 2268, 2448, 44, 1188},
//offsets for: /mysqlrpm/5.5.32/usr/sbin/mysqld (5.5.32)
@ -812,7 +800,6 @@ const ThdOffsets thd_offsets_arr[] =
#endif
#else
//start offsets for MariaDB
#ifdef __x86_64__
@ -820,6 +807,8 @@ const ThdOffsets thd_offsets_arr[] =
const ThdOffsets thd_offsets_arr[] =
{
/* +++ MARIADB 64 OFFSETS GO HERE +++ */
//offsets for: /mariadb/10.1.13/bin/mysqld (10.1.13-MariaDB)
{"10.1.13-MariaDB","cd322698dcd46dd82770dc091f1eec51", 13592, 13656, 6368, 7976, 88, 2976, 8, 0, 16, 24, 152, 13748},
//offsets for: /mariadb/10.1.12/bin/mysqld (10.1.12-MariaDB)
{"10.1.12-MariaDB","e2ba726e2e6f56976518581da0a2c443", 13592, 13656, 6368, 7976, 88, 2976, 8, 0, 16, 24, 152, 13748},
//offsets for: /mariadb/10.0.24/bin/mysqld (10.0.24-MariaDB)
@ -911,6 +900,8 @@ const ThdOffsets thd_offsets_arr[] =
const ThdOffsets thd_offsets_arr[] =
{
/* +++ MARIADB 32 OFFSETS GO HERE +++ */
//offsets for: /mariadb/10.1.13/bin/mysqld (10.1.13-MariaDB)
{"10.1.13-MariaDB","546cb7233e8567aea304fda3d9812a7b", 8472, 8508, 3816, 5276, 44, 1892, 4, 0, 8, 12, 84, 8584},
//offsets for: /mariadb/10.1.12/bin/mysqld (10.1.12-MariaDB)
{"10.1.12-MariaDB","590bb2be8fb17c7b3599539d4a69ab44", 8472, 8508, 3816, 5276, 44, 1892, 4, 0, 8, 12, 84, 8584},
//offsets for: /mariadb/10.0.24/bin/mysqld (10.0.24-MariaDB)
@ -1003,4 +994,3 @@ const ThdOffsets thd_offsets_arr[] =
//the size of the offsets arr
const size_t thd_offsets_arr_size = array_elements(thd_offsets_arr);

File diff suppressed because it is too large Load Diff

View File

@ -11,33 +11,33 @@
#define ULONG_PTR uint32_t
#endif
static const char * log_prefix = "Audit Plugin:";
static const char *log_prefix = "Audit Plugin:";
static const unsigned long PAGE_SIZE = GETPAGESIZE() ;
//used to indicate how to do the protect/unprotect
// used to indicate how to do the protect/unprotect
static bool use_exec_prot = true;
static int protect(void *addr, size_t len)
{
int res = 0;
if(use_exec_prot)
if (use_exec_prot)
{
res = mprotect(addr,len,PROT_READ|PROT_EXEC);
}
else //try doing in a 2 step fashion
else // try doing in a 2 step fashion
{
mprotect(addr,len,PROT_READ);
res = mprotect(addr,len,PROT_READ|PROT_EXEC);
}
if(res)
if (res)
{
sql_print_information(
"%s unable to protect mode: PROT_READ|PROT_EXEC. Page: %p, Size: %zu, errno: %d, res %d.",
log_prefix, (void *)addr, len, errno, res);
//fail only if nx bit is enabled
FILE * fp = fopen("/proc/cpuinfo", "r");
if(NULL == fp)
// fail only if nx bit is enabled
FILE *fp = fopen("/proc/cpuinfo", "r");
if (NULL == fp)
{
sql_print_error(
"%s unable to verify nx bit. Failed checking /proc/cpuinfo. This may happen if you have SELinux enabled. Disable SELinux execmod protection for mysqld. Page: %p, Size: %zu, errno: %d.",
@ -45,21 +45,21 @@ static int protect(void *addr, size_t len)
return res;
}
char buff[1024] = {0};
const char * flags = "flags";
const char *flags = "flags";
bool nxchecked = false;
while(fgets(buff, 1024, fp) != NULL)
while (fgets(buff, 1024, fp) != NULL)
{
char * line = buff;
//trim white space at start
char *line = buff;
// trim white space at start
while ((strlen(line) > 0) && (isspace(line[0])))
{
line++;
}
if(strncmp(line, flags, strlen(flags)) == 0)
if (strncmp(line, flags, strlen(flags)) == 0)
{
nxchecked = true;
sql_print_information("%s cpuinfo flags line: %s. ",log_prefix, line);
if(strstr(line, " nx")) //nx enabled so fail
if (strstr(line, " nx")) // nx enabled so fail
{
sql_print_error(
"%s unable to protect page and nx bit enabled. This may happen if you have SELinux enabled. Disable SELinux execmod protection for mysqld. Page: %p, Size: %zu.",
@ -71,7 +71,7 @@ static int protect(void *addr, size_t len)
}
}
fclose(fp);
if(!nxchecked) //we didn't find flags string for some reason
if (! nxchecked) // we didn't find flags string for some reason
{
sql_print_error(
"%s unable to verify nx bit. Failed finding: %s in /proc/cpuinfo. This may happen if you have SELinux enabled. Disable SELinux execmod protection for mysqld. Page: %p, Size: %zu.",
@ -82,23 +82,23 @@ static int protect(void *addr, size_t len)
return 0;
}
//will try to unprotect with PROT_READ|PROT_WRITE|PROT_EXEC. If fails (might happen under SELinux)
//will use PROT_READ|PROT_WRITE
// will try to unprotect with PROT_READ|PROT_WRITE|PROT_EXEC. If fails (might happen under SELinux)
// will use PROT_READ|PROT_WRITE
static int unprotect(void *addr, size_t len)
{
int res;
if(use_exec_prot)
if (use_exec_prot)
{
res = mprotect(addr,len,PROT_READ|PROT_WRITE|PROT_EXEC);
if(res)
res = mprotect(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC);
if (res)
{
sql_print_information(
"%s unable to unprotect. Page: %p, Size: %zu, errno: %d. Using NO EXEC mode.",
log_prefix, (void *)addr, len, errno);
use_exec_prot = false;
//do a sanity test that we can actually unprotect/protect and that nx bit is off
// do a sanity test that we can actually unprotect/protect and that nx bit is off
res = unprotect(addr, len);
if(res)
if (res)
{
sql_print_error(
"%s unable to unprotect page. This may happen if you have SELinux enabled. Disable SELinux execmod protection for mysqld. Aborting. Page: %p, Size: %zu, errno: %d.",
@ -107,7 +107,7 @@ static int unprotect(void *addr, size_t len)
}
res = protect(addr, len);
sql_print_information("%s protect res: %d", log_prefix, res);
if(res)
if (res)
{
sql_print_error(
"%s unable to protect page. This may happen if you have SELinux enabled. Disable SELinux execmod protection for mysqld. Aborting. Page: %p, Size: %zu, errno: %d.",
@ -115,13 +115,14 @@ static int unprotect(void *addr, size_t len)
return res;
}
}
else //all is good
else // all is good
{
return res;
}
}
res = mprotect(addr,len,PROT_READ|PROT_WRITE);
if(0 != res) //log the failure
res = mprotect(addr, len, PROT_READ|PROT_WRITE);
if (0 != res) // log the failure
{
sql_print_error(
"%s unable to unprotect. Page: %p, Size: %zu, errno: %d. Error.",
@ -130,14 +131,14 @@ static int unprotect(void *addr, size_t len)
return res;
}
//macro to log via sql_print_information only if cond test is enabled
#define cond_info_print(cond_test, ...) do{if(cond_test) sql_print_information(__VA_ARGS__);}while(0)
// macro to log via sql_print_information only if cond test is enabled
#define cond_info_print(cond_test, ...) do { if (cond_test) sql_print_information(__VA_ARGS__);} while (0)
/*
* Get the page address of a given pointer
*/
static DATATYPE_ADDRESS get_page_address(void * pointer)
static DATATYPE_ADDRESS get_page_address(void *pointer)
{
DATATYPE_ADDRESS pageMask = ( ~(PAGE_SIZE - 1) ) ;
DATATYPE_ADDRESS longp = (unsigned long) pointer;
@ -183,9 +184,7 @@ static void WriteJump(void *pAddress, ULONG_PTR JumpTo)
*((ULONG_PTR *)pCur) = JumpTo;
#endif
//}
//DWORD dwBuf = 0; // nessary othewrise the function fails
// DWORD dwBuf = 0; // necessary othewrise the function fails
protect((void*)AddressPage, PAGE_SIZE);
}
@ -196,16 +195,16 @@ static void WriteJump(void *pAddress, ULONG_PTR JumpTo)
static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG_PTR trampolineFunction,
unsigned int *trampolinesize)
{
#define MAX_INSTRUCTIONS 100
#define MAX_INSTRUCTIONS 100
uint8_t raw[MAX_INSTRUCTIONS];
unsigned int uCurrentSize =0;
#ifndef __x86_64__
#define ASM_MODE 32
#define ASM_MODE 32
#else
#define ASM_MODE 64
#define ASM_MODE 64
#endif
memcpy (raw,(void*)targetFunction,MAX_INSTRUCTIONS);
memcpy(raw, (void*)targetFunction, MAX_INSTRUCTIONS);
ud_t ud_obj;
ud_init(&ud_obj);
ud_set_input_buffer(&ud_obj, raw, MAX_INSTRUCTIONS);
@ -215,26 +214,28 @@ static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG
DWORD InstrSize = 0;
DATATYPE_ADDRESS trampolineFunctionPage = get_page_address((void*)trampolineFunction);
if(unprotect((void*)trampolineFunctionPage, PAGE_SIZE) != 0)
if (unprotect((void*)trampolineFunctionPage, PAGE_SIZE) != 0)
{
sql_print_error(
"%s unable to unprotect trampoline function page: %p. Aborting.",
log_prefix, (void *)trampolineFunctionPage);
return false;
}
bool disassemble_valid = false;
while (ud_disassemble(&ud_obj))
{
if(ud_obj.mnemonic == UD_Iinvalid)
if (ud_obj.mnemonic == UD_Iinvalid)
{
sql_print_error(
"%s unable to disassemble at address: %p. Aborting.",
log_prefix, (void *)(InstrSize + targetFunction));
break;
}
//make sure there isn't a jmp/call (or similar operand) as these use
//relative addressing and if we copy as is we will mess up the jmp/call target
if(ud_obj.mnemonic == UD_Ijmp || ud_obj.mnemonic == UD_Icall ||
// make sure there isn't a jmp/call (or similar operand) as these use
// relative addressing and if we copy as is we will mess up the jmp/call target
if (ud_obj.mnemonic == UD_Ijmp || ud_obj.mnemonic == UD_Icall ||
ud_obj.operand[0].type == UD_OP_JIMM)
{
sql_print_error(
@ -249,24 +250,27 @@ static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG
uCurrentSize += ud_insn_len (&ud_obj);
InstrSize += ud_insn_len (&ud_obj);
if (InstrSize >= jump_size()) //we have enough space so break
if (InstrSize >= jump_size()) // we have enough space so break
{
disassemble_valid = true;
break;
}
}
if(protect((void*)trampolineFunctionPage, PAGE_SIZE)) //0 valid return
if (protect((void*)trampolineFunctionPage, PAGE_SIZE)) // 0 valid return
{
sql_print_error(
"%s unable to protect page. Error. Page: %p.",
log_prefix, (void *)trampolineFunctionPage);
return false;
}
if(!disassemble_valid) //something went wrong. log was written before so return false
if (! disassemble_valid) // something went wrong. log was written before so return false
{
return false;
}
WriteJump( (BYTE*)trampolineFunction + uCurrentSize, targetFunction + InstrSize);
WriteJump((BYTE*)trampolineFunction + uCurrentSize, targetFunction + InstrSize);
WriteJump((void *) targetFunction, newFunction);
*trampolinesize = uCurrentSize;
return true;
@ -277,10 +281,10 @@ static bool HookFunction(ULONG_PTR targetFunction, ULONG_PTR newFunction, ULONG
//
static void UnhookFunction(ULONG_PTR Function,ULONG_PTR trampolineFunction , unsigned int trampolinesize)
static void UnhookFunction(ULONG_PTR Function, ULONG_PTR trampolineFunction, unsigned int trampolinesize)
{
DATATYPE_ADDRESS FunctionPage = get_page_address((void*)Function);
if(unprotect((void*)FunctionPage, PAGE_SIZE) != 0)
if (unprotect((void*)FunctionPage, PAGE_SIZE) != 0)
{
sql_print_error(
"%s Unhook not able to unprotect function page: %p. Aborting.",
@ -306,9 +310,9 @@ static void UnhookFunction(ULONG_PTR Function,ULONG_PTR trampolineFunction , uns
* which contains a bunch of nops.
* @param info_print if true will print info as progressing
* @Return 0 on success otherwise failure
* @See MS Detours paper: http://research.microsoft.com/pubs/68568/huntusenixnt99.pdf for some background info.
* @See MS Detours paper: http:// research.microsoft.com/pubs/68568/huntusenixnt99.pdf for some background info.
*/
int hot_patch_function (void* targetFunction, void* newFunction, void * trampolineFunction, unsigned int *trampolinesize, bool info_print)
int hot_patch_function(void *targetFunction, void *newFunction, void *trampolineFunction, unsigned int *trampolinesize, bool info_print)
{
DATATYPE_ADDRESS trampolinePage = get_page_address(trampolineFunction);
cond_info_print(info_print, "%s hot patching function: %p, trampolineFunction: %p trampolinePage: %p",log_prefix, (void *)targetFunction, (void *)trampolineFunction, (void *)trampolinePage);
@ -332,11 +336,11 @@ int hot_patch_function (void* targetFunction, void* newFunction, void * trampoli
* @param trampolineFunction a function which contains a jump back to the targetFunction.
* @param log_file if not null will log about progress of installing the plugin
*/
void remove_hot_patch_function (void* targetFunction, void * trampolineFunction, unsigned int trampolinesize, bool info_print)
void remove_hot_patch_function(void *targetFunction, void *trampolineFunction, unsigned int trampolinesize, bool info_print)
{
if(trampolinesize == 0)
if (trampolinesize == 0)
{
//nothing todo. As hot patch was not set.
// nothing todo. As hot patch was not set.
return;
}
DATATYPE_ADDRESS targetPage = get_page_address(targetFunction);

0
src/md5.cc Executable file → Normal file
View File