pull/8/merge
Mocker 2012-07-30 09:47:15 -07:00
commit 3195fbdb67
3 changed files with 1559 additions and 1467 deletions

View File

@ -35,6 +35,9 @@ typedef size_t OFFSET;
#define MAX_COM_STATUS_VARS_RECORDS 512 #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. * The struct usd to hold offsets. We should have one per version.
*/ */

View File

@ -391,7 +391,6 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
} }
else else
{ {
yajl_add_string_val(gen, "cmd", cmd); yajl_add_string_val(gen, "cmd", cmd);
} }

View File

@ -104,6 +104,8 @@ static const ThdOffsets thd_offsets_arr[] =
{"5.1.60-community","d9497964e8983a348538c0d05eaee7f0", 6328, 6392, 3688, 3960, 88, 2048}, {"5.1.60-community","d9497964e8983a348538c0d05eaee7f0", 6328, 6392, 3688, 3960, 88, 2048},
//offsets for: /mysqlrpm/5.1.61/usr/sbin/mysqld (5.1.61-community) //offsets for: /mysqlrpm/5.1.61/usr/sbin/mysqld (5.1.61-community)
{"5.1.61-community","bda6030d35e7fafa5b1e57154a53b804", 6328, 6392, 3688, 3960, 88, 2048}, {"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) //offsets for: mysqlrpm/5.5.8/usr/sbin/mysqld (5.5.8)
{"5.5.8","70a882693d54df8ab7c7d9f256e317bb", 6032, 6080, 3776, 4200, 88, 2560}, {"5.5.8","70a882693d54df8ab7c7d9f256e317bb", 6032, 6080, 3776, 4200, 88, 2560},
//offsets for: mysqlrpm/5.5.9/usr/sbin/mysqld (5.5.9) //offsets for: mysqlrpm/5.5.9/usr/sbin/mysqld (5.5.9)
@ -452,10 +454,19 @@ static my_bool json_socket_handler_enable = FALSE;
static my_bool uninstall_plugin_enable = FALSE; static my_bool uninstall_plugin_enable = FALSE;
static my_bool validate_checksum_enable = FALSE; static my_bool validate_checksum_enable = FALSE;
static char * offsets_string = NULL; static char * offsets_string = NULL;
static char * checksum_string = NULL;
static int delay_ms_val =0; static int delay_ms_val =0;
static char *delay_cmds_string = NULL; 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 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}; 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. * The trampoline function we use. Define it via a macro which simply fills it with nops.
@ -506,9 +517,49 @@ THDPRINTED * GetThdPrintedList (THD *thd)
return NULL; 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) static void audit(ThdSesData *pThdData)
{ {
THDPRINTED *pThdPrintedList = GetThdPrintedList (pThdData->getTHD()); 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 && pThdPrintedList->cur_index < MAX_NUM_QUEUE_ELEM)
{ {
if (pThdPrintedList->is_thd_printed_queue[pThdPrintedList->cur_index] == 0) if (pThdPrintedList->is_thd_printed_queue[pThdPrintedList->cur_index] == 0)
@ -528,21 +579,11 @@ static void audit(ThdSesData *pThdData)
if (delay_ms_val > 0) if (delay_ms_val > 0)
{ {
const char * cmd = pThdData->getCmdName(); const char * cmd = pThdData->getCmdName();
for (int k=0; delay_cmds_array[k][0] !='\0';k++) int delay = check_array(cmd, (char *) delay_cmds_array, MAX_COMMAND_CHAR_NUMBERS);
{ if (delay)
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); //Audit_file_handler::print_sleep(thd,delay_ms_val);
my_sleep (delay_ms_val *1000); my_sleep (delay_ms_val *1000);
break;
}
} }
} }
} }
@ -947,8 +988,44 @@ static int setup_offsets()
//[mysqld] //[mysqld]
//audit_offsets=6200, 6264, 3672, 3944, 88, 2048 //audit_offsets=6200, 6264, 3672, 3944, 88, 2048
if (validate_checksum_enable)
{
sql_print_information ("%s Audit validate checksum enabled. Mysqld %s ",log_prefix, my_progname);
my_MD5Context context;
my_MD5Init (&context);
unsigned char * file_buff;
MY_STAT stat_arg;
File fd;
if (my_stat(my_progname,&stat_arg,MYF(MY_WME)))
{
if ((fd = my_open(my_progname,O_RDONLY, MYF(MY_WME))) > 0)
{
file_buff = (unsigned char*) my_malloc ((uint) stat_arg.st_size, MYF (MY_WME));
if (read(fd,(char*) file_buff,(uint) stat_arg.st_size) >= 0L)
{
my_MD5Update (&context, file_buff, stat_arg.st_size);
my_MD5Final (digest, &context);
}
(void) my_close(fd,MYF(0));
free (file_buff);
}
}
for (int j = 0; j < 16; j++) {
sprintf(&(digest_str[j*2]), "%02x", digest[j]);
}
}
if (offsets_string !=NULL) if (offsets_string !=NULL)
{ {
if (checksum_string != NULL && strlen(checksum_string) > 0) {
if (strncasecmp(checksum_string, digest_str, 32)) {
// Checksum failed
sql_print_information("%s checksum check failed for %s, but found %s", log_prefix, checksum_string, digest_str);
DBUG_RETURN(1);
}
}
char buf[32*1024] = {0}; char buf[32*1024] = {0};
THD * thd = (THD *)buf; THD * thd = (THD *)buf;
@ -989,31 +1066,7 @@ static int setup_offsets()
//[mysqld] //[mysqld]
//audit_validate_checksum=1 //audit_validate_checksum=1
//plugin-load=AUDIT=libaudit_plugin.so //plugin-load=AUDIT=libaudit_plugin.so
if (validate_checksum_enable)
{
sql_print_information ("%s Audit validate checksum enabled. Mysqld %s ",log_prefix, my_progname);
my_MD5Context context;
my_MD5Init (&context);
unsigned char * file_buff;
MY_STAT stat_arg;
File fd;
if (my_stat(my_progname,&stat_arg,MYF(MY_WME)))
{
if ((fd = my_open(my_progname,O_RDONLY, MYF(MY_WME))) > 0)
{
file_buff = (unsigned char*) my_malloc ((uint) stat_arg.st_size, MYF (MY_WME));
if (read(fd,(char*) file_buff,(uint) stat_arg.st_size) >= 0L)
{
my_MD5Update (&context, file_buff, stat_arg.st_size);
my_MD5Final (digest, &context);
}
(void) my_close(fd,MYF(0));
free (file_buff);
}
}
}
bool bCheckSumValidation = false; bool bCheckSumValidation = false;
for(int i=0; i < arr_size; i++) for(int i=0; i < arr_size; i++)
{ {
@ -1025,24 +1078,9 @@ static int setup_offsets()
//plugin-load=AUDIT=libaudit_plugin.so //plugin-load=AUDIT=libaudit_plugin.so
if (validate_checksum_enable && strlen (offset->md5digest) >0) if (validate_checksum_enable && strlen (offset->md5digest) >0)
{ {
memset (digest_str,0,sizeof (digest_str));
bCheckSumValidation = true; bCheckSumValidation = true;
int kd=0; int kd=0;
for (int j=0;j<16;j++) if (!strncasecmp(digest_str, offset->md5digest, 32)) {
{
unsigned char Dig=0;
char DigStr[3]={0};
DigStr[0]= offset->md5digest[kd++];
DigStr[1]= offset->md5digest[kd++];
sscanf (DigStr,"%x",&Dig);
sprintf (digest_str,"%s %2x",digest_str,digest[j]);
if (Dig != digest[j])
{
bCheckSumValidation = false;
}
}
if (bCheckSumValidation)
{
sql_print_information ("%s Checksum is %s verified", log_prefix, digest_str); sql_print_information ("%s Checksum is %s verified", log_prefix, digest_str);
sql_print_information("%s Using offsets from offset version: %s", log_prefix, offset->version); sql_print_information("%s Using offsets from offset version: %s", log_prefix, offset->version);
Audit_formatter::thd_offsets = *offset; Audit_formatter::thd_offsets = *offset;
@ -1161,6 +1199,50 @@ static int set_com_status_vars_array ()
} }
DBUG_RETURN (0); DBUG_RETURN (0);
} }
static int string_to_array (const void *save, void *array, int rows, int length)
{
const char* save_string;
save_string = *static_cast<const char*const*>(save);
char* string_array;
string_array = (char *) array;
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';
}
return r;
}
/* /*
Initialize the daemon plugin installation. Initialize the daemon plugin installation.
@ -1188,6 +1270,20 @@ static int audit_plugin_init(void *p)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
// setup any values from my.cnf
if (delay_cmds_string != NULL) {
num_delay_cmds = string_to_array(&delay_cmds_string, delay_cmds_array, SQLCOM_END + 2, MAX_COMMAND_CHAR_NUMBERS);
sql_print_information("%s Set num_delay_cmds: %d", log_prefix, num_delay_cmds);
}
if (record_cmds_string != NULL) {
num_record_cmds = string_to_array(&record_cmds_string, record_cmds_array, SQLCOM_END + 2, MAX_COMMAND_CHAR_NUMBERS);
sql_print_information("%s Set num_record_cmds: %d", log_prefix, num_record_cmds);
}
if (record_objs_string != NULL) {
num_record_objs = string_to_array(&record_objs_string, 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 audit handlers (initially disabled) //setup audit handlers (initially disabled)
int res = json_file_handler.init(&json_formatter); int res = json_file_handler.init(&json_formatter);
if (res != 0) if (res != 0)
@ -1414,56 +1510,32 @@ 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,
static void delay_cmds_string_update (THD *thd, struct st_mysql_sys_var *var,
void *tgt, const void *save) void *tgt, const void *save)
{ {
// FIXME: This might leak memory for each update, but prevents a crash when original settings were in my.cnf
char *old= *(char **) tgt;
*(char **)tgt= my_strdup(*(char **) save, MYF(0)); *(char **)tgt= my_strdup(*(char **) save, MYF(0));
#if MYSQL_VERSION_ID > 50505 num_delay_cmds = string_to_array(save, delay_cmds_array, SQLCOM_END + 2, MAX_COMMAND_CHAR_NUMBERS);
my_free(old); sql_print_information("%s Set num_delay_cmds: %d", log_prefix, num_delay_cmds);
#else
my_free(old, MYF(0));
#endif
const char* save_string;
save_string = *static_cast<const char*const*>(save);
int k =0;
if (save_string !=NULL)
{
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';
} }
} static void record_cmds_string_update (THD *thd, struct st_mysql_sys_var *var,
if (k < SQLCOM_END) void *tgt, const void *save)
{ {
delay_cmds_array[k+1][0]='\0'; // FIXME: This might leak memory for each update, but prevents a crash when original settings were in my.cnf
*(char **)tgt= my_strdup(*(char **) save, MYF(0));
num_record_cmds = string_to_array(save, 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_update (THD *thd, struct st_mysql_sys_var *var,
void *tgt, const void *save)
{
// FIXME: This might leak memory for each update, but prevents a crash when original settings were in my.cnf
*(char **)tgt= my_strdup(*(char **) save, MYF(0));
num_record_objs = string_to_array(save, 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 //setup sysvars which update directly the relevant plugins
@ -1480,7 +1552,7 @@ static MYSQL_SYSVAR_UINT(json_file_sync, json_file_handler.m_sync_period,
NULL, NULL, 0, 0, UINT_MAX32, 0); NULL, NULL, 0, 0, UINT_MAX32, 0);
static MYSQL_SYSVAR_BOOL(json_file, json_file_handler_enable, static MYSQL_SYSVAR_BOOL(json_file, json_file_handler_enable,
PLUGIN_VAR_OPCMDARG, PLUGIN_VAR_RQCMDARG,
"AUDIT plugin json log file Enable|Disable", NULL, json_log_file_enable, 0); "AUDIT plugin json log file Enable|Disable", NULL, json_log_file_enable, 0);
@ -1494,6 +1566,11 @@ static MYSQL_SYSVAR_STR(offsets, offsets_string,
"AUDIT plugin offsets. Comma separated list of offsets to use for extracting data", "AUDIT plugin offsets. Comma separated list of offsets to use for extracting data",
NULL, NULL, NULL); NULL, NULL, NULL);
static MYSQL_SYSVAR_STR(checksum, checksum_string,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
"AUDIT plugin checksum. Checksum for mysqld corresponding to offsets",
NULL, NULL, "");
static MYSQL_SYSVAR_BOOL(uninstall_plugin, uninstall_plugin_enable, static MYSQL_SYSVAR_BOOL(uninstall_plugin, uninstall_plugin_enable,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY , PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY ,
"AUDIT uninstall plugin Enable|Disable. Default disabled. If disabled attempts to uninstall the AUDIT plugin via the sql UNINSTALL command will fail.", NULL, NULL, 0); "AUDIT uninstall plugin Enable|Disable. Default disabled. If disabled attempts to uninstall the AUDIT plugin via the sql UNINSTALL command will fail.", NULL, NULL, 0);
@ -1504,7 +1581,7 @@ static MYSQL_SYSVAR_BOOL(validate_checksum, validate_checksum_enable,
"AUDIT plugin binary checksum validation Enable|Disable", NULL, NULL, 1); "AUDIT plugin binary checksum validation Enable|Disable", NULL, NULL, 1);
static MYSQL_SYSVAR_BOOL(json_socket, json_socket_handler_enable, static MYSQL_SYSVAR_BOOL(json_socket, json_socket_handler_enable,
PLUGIN_VAR_OPCMDARG, PLUGIN_VAR_RQCMDARG,
"AUDIT plugin json log unix socket Enable|Disable", NULL, json_log_socket_enable, 0); "AUDIT plugin json log unix socket Enable|Disable", NULL, json_log_socket_enable, 0);
static MYSQL_SYSVAR_INT(delay_ms, delay_ms_val, static MYSQL_SYSVAR_INT(delay_ms, delay_ms_val,
@ -1515,7 +1592,17 @@ static MYSQL_SYSVAR_INT(delay_ms, delay_ms_val,
static MYSQL_SYSVAR_STR(delay_cmds, delay_cmds_string, static MYSQL_SYSVAR_STR(delay_cmds, delay_cmds_string,
PLUGIN_VAR_RQCMDARG, PLUGIN_VAR_RQCMDARG,
"AUDIT plugin delay commands to match against comma separated. If empty then delay is disabled.", "AUDIT plugin delay commands to match against comma separated. If empty then delay is disabled.",
NULL, delay_cmds_string_handler, NULL); NULL, delay_cmds_string_update, NULL);
static MYSQL_SYSVAR_STR(record_cmds, record_cmds_string,
PLUGIN_VAR_RQCMDARG,
"AUDIT plugin commands to record, comma separated",
NULL, record_cmds_string_update, NULL);
static MYSQL_SYSVAR_STR(record_objs, record_objs_string,
PLUGIN_VAR_RQCMDARG,
"AUDIT plugin objects to record, comma separated",
NULL, record_objs_string_update, NULL);
/* /*
* Plugin system vars * Plugin system vars
@ -1534,6 +1621,9 @@ static struct st_mysql_sys_var* audit_system_variables[] =
MYSQL_SYSVAR(is_thd_printed_list), MYSQL_SYSVAR(is_thd_printed_list),
MYSQL_SYSVAR(delay_ms), MYSQL_SYSVAR(delay_ms),
MYSQL_SYSVAR(delay_cmds), MYSQL_SYSVAR(delay_cmds),
MYSQL_SYSVAR(record_cmds),
MYSQL_SYSVAR(record_objs),
MYSQL_SYSVAR(checksum),
NULL }; NULL };
//declare our plugin //declare our plugin