mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Audit plugin v1.2.0.
This commit is contained in:
@ -85,6 +85,66 @@ create table sa_t1(id int);
|
||||
insert into sa_t1 values (1), (2);
|
||||
drop table sa_t1;
|
||||
drop database sa_db;
|
||||
create database sa_db;
|
||||
use sa_db;
|
||||
CREATE USER u1 IDENTIFIED BY 'pwd-123';
|
||||
GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
|
||||
SET PASSWORD FOR u1 = PASSWORD('pwd 098');
|
||||
CREATE USER u3 IDENTIFIED BY '';
|
||||
drop user u1, u2, u3;
|
||||
set global server_audit_events='query_ddl';
|
||||
create table t1(id int);
|
||||
insert into t1 values (1), (2);
|
||||
select * from t1;
|
||||
id
|
||||
1
|
||||
2
|
||||
select 2;
|
||||
2
|
||||
2
|
||||
(select 2);
|
||||
2
|
||||
2
|
||||
/*! select 2*/;
|
||||
2
|
||||
2
|
||||
/*comment*/ select 2;
|
||||
2
|
||||
2
|
||||
drop table t1;
|
||||
set global server_audit_events='query_ddl,query_dml';
|
||||
create table t1(id int);
|
||||
insert into t1 values (1), (2);
|
||||
select * from t1;
|
||||
id
|
||||
1
|
||||
2
|
||||
select 2;
|
||||
2
|
||||
2
|
||||
drop table t1;
|
||||
set global server_audit_events='query_dml';
|
||||
create table t1(id int);
|
||||
insert into t1 values (1), (2);
|
||||
select * from t1;
|
||||
id
|
||||
1
|
||||
2
|
||||
select 2;
|
||||
2
|
||||
2
|
||||
(select 2);
|
||||
2
|
||||
2
|
||||
/*! select 2*/;
|
||||
2
|
||||
2
|
||||
/*comment*/ select 2;
|
||||
2
|
||||
2
|
||||
drop table t1;
|
||||
set global server_audit_events='';
|
||||
drop database sa_db;
|
||||
set global server_audit_file_path='.';
|
||||
show status like 'server_audit_current_log';
|
||||
Variable_name Value
|
||||
@ -176,19 +236,65 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'.\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'.\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show status like \'server_audit_current_log\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show status like \'server_audit_current_log\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\' \'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\' \'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show status like \'server_audit_current_log\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'nonexisting_dir/\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'nonexisting_dir/\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'SHOW WARNINGS',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show status like \'server_audit_current_log\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show variables like \'server_audit%\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'insert into t1 values (1), (2)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select * from t1',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select 2',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'insert into t1 values (1), (2)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select * from t1',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select 2',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'(select 2)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*! select 2*/',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*comment*/ select 2',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_events=\'\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'.\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'.\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show status like \'server_audit_current_log\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show status like \'server_audit_current_log\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\' \'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\' \'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show status like \'server_audit_current_log\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'nonexisting_dir/\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'nonexisting_dir/\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SHOW WARNINGS',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show status like \'server_audit_current_log\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show variables like \'server_audit%\'',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,plugin,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'uninstall plugin server_audit',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'uninstall plugin server_audit',0
|
||||
|
@ -15,6 +15,7 @@ connect (con1,localhost,root,,mysql);
|
||||
connection default;
|
||||
disconnect con1;
|
||||
--sleep 2
|
||||
--sleep 2
|
||||
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
|
||||
--error ER_ACCESS_DENIED_ERROR
|
||||
connect (con1,localhost,no_such_user,,mysql);
|
||||
@ -45,6 +46,8 @@ set global server_audit_events='';
|
||||
create database sa_db;
|
||||
connect (con1,localhost,root,,test);
|
||||
connection con1;
|
||||
--sleep 2
|
||||
--sleep 2
|
||||
create table t1 (id2 int);
|
||||
insert into t1 values (1), (2);
|
||||
select * from t1;
|
||||
@ -56,8 +59,43 @@ drop table sa_t1;
|
||||
drop database sa_db;
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
--sleep 2
|
||||
--sleep 2
|
||||
create database sa_db;
|
||||
use sa_db;
|
||||
CREATE USER u1 IDENTIFIED BY 'pwd-123';
|
||||
GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
|
||||
SET PASSWORD FOR u1 = PASSWORD('pwd 098');
|
||||
CREATE USER u3 IDENTIFIED BY '';
|
||||
drop user u1, u2, u3;
|
||||
|
||||
set global server_audit_events='query_ddl';
|
||||
create table t1(id int);
|
||||
insert into t1 values (1), (2);
|
||||
select * from t1;
|
||||
select 2;
|
||||
(select 2);
|
||||
/*! select 2*/;
|
||||
/*comment*/ select 2;
|
||||
drop table t1;
|
||||
set global server_audit_events='query_ddl,query_dml';
|
||||
create table t1(id int);
|
||||
insert into t1 values (1), (2);
|
||||
select * from t1;
|
||||
select 2;
|
||||
drop table t1;
|
||||
set global server_audit_events='query_dml';
|
||||
create table t1(id int);
|
||||
insert into t1 values (1), (2);
|
||||
select * from t1;
|
||||
select 2;
|
||||
(select 2);
|
||||
/*! select 2*/;
|
||||
/*comment*/ select 2;
|
||||
drop table t1;
|
||||
set global server_audit_events='';
|
||||
drop database sa_db;
|
||||
|
||||
set global server_audit_file_path='.';
|
||||
--replace_regex /\.[\\\/]/HOME_DIR\//
|
||||
show status like 'server_audit_current_log';
|
||||
|
@ -14,11 +14,10 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#define PLUGIN_VERSION 0x101
|
||||
#define PLUGIN_STR_VERSION "1.1.7"
|
||||
#define PLUGIN_VERSION 0x102
|
||||
#define PLUGIN_STR_VERSION "1.2.0"
|
||||
|
||||
#include <my_config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
@ -142,6 +141,10 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
|
||||
#define flogger_mutex_lock(A) pthread_mutex_lock(&(A)->m_mutex)
|
||||
#define flogger_mutex_unlock(A) pthread_mutex_unlock(&(A)->m_mutex)
|
||||
|
||||
static char **int_mysql_data_home;
|
||||
static char *default_home= (char *)".";
|
||||
#define mysql_data_home (*int_mysql_data_home)
|
||||
|
||||
#include "../../mysys/file_logger.c"
|
||||
#endif /*!MARIADB_ONLY*/
|
||||
|
||||
@ -165,6 +168,7 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
|
||||
extern char server_version[];
|
||||
static const char *serv_ver= NULL;
|
||||
static int started_mysql= 0;
|
||||
static int started_mariadb= 0;
|
||||
static int maria_above_5= 0;
|
||||
static char *incl_users, *excl_users,
|
||||
*file_path, *syslog_info;
|
||||
@ -222,11 +226,15 @@ static MYSQL_SYSVAR_STR(excl_users, excl_users, PLUGIN_VAR_RQCMDARG,
|
||||
NULL, update_excl_users, NULL);
|
||||
/* bits in the event filter. */
|
||||
#define EVENT_CONNECT 1
|
||||
#define EVENT_QUERY 2
|
||||
#define EVENT_QUERY_ALL 2
|
||||
#define EVENT_QUERY 26
|
||||
#define EVENT_TABLE 4
|
||||
#define EVENT_QUERY_DDL 8
|
||||
#define EVENT_QUERY_DML 16
|
||||
|
||||
static const char *event_names[]=
|
||||
{
|
||||
"CONNECT", "QUERY", "TABLE",
|
||||
"CONNECT", "QUERY", "TABLE", "QUERY_DDL", "QUERY_DML",
|
||||
NULL
|
||||
};
|
||||
static TYPELIB events_typelib=
|
||||
@ -234,7 +242,7 @@ static TYPELIB events_typelib=
|
||||
array_elements(event_names) - 1, "", event_names, NULL
|
||||
};
|
||||
static MYSQL_SYSVAR_SET(events, events, PLUGIN_VAR_RQCMDARG,
|
||||
"Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE.",
|
||||
"Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE, QUERY_DDL, QUERY_DML.",
|
||||
NULL, NULL, 0, &events_typelib);
|
||||
#define OUTPUT_SYSLOG 0
|
||||
#define OUTPUT_FILE 1
|
||||
@ -526,6 +534,103 @@ static int user_hash_fill(HASH *h, char *users,
|
||||
}
|
||||
|
||||
|
||||
enum sa_keywords
|
||||
{
|
||||
SQLCOM_NOTHING=0,
|
||||
SQLCOM_DDL,
|
||||
SQLCOM_DML,
|
||||
SQLCOM_GRANT,
|
||||
SQLCOM_CREATE_USER,
|
||||
SQLCOM_CHANGE_MASTER,
|
||||
SQLCOM_CREATE_SERVER,
|
||||
SQLCOM_SET_OPTION,
|
||||
SQLCOM_ALTER_SERVER,
|
||||
SQLCOM_TRUNCATE,
|
||||
SQLCOM_QUERY_ADMIN,
|
||||
SQLCOM_DCL,
|
||||
};
|
||||
|
||||
struct sa_keyword
|
||||
{
|
||||
int length;
|
||||
const char *wd;
|
||||
struct sa_keyword *next;
|
||||
enum sa_keywords type;
|
||||
};
|
||||
|
||||
|
||||
struct sa_keyword xml_word= {3, "XML", 0, SQLCOM_NOTHING};
|
||||
struct sa_keyword user_word= {4, "USER", 0, SQLCOM_NOTHING};
|
||||
struct sa_keyword data_word= {4, "DATA", 0, SQLCOM_NOTHING};
|
||||
struct sa_keyword server_word= {6, "SERVER", 0, SQLCOM_NOTHING};
|
||||
struct sa_keyword master_word= {6, "MASTER", 0, SQLCOM_NOTHING};
|
||||
struct sa_keyword password_word= {8, "PASSWORD", 0, SQLCOM_NOTHING};
|
||||
struct sa_keyword function_word= {8, "FUNCTION", 0, SQLCOM_NOTHING};
|
||||
struct sa_keyword statement_word= {9, "STATEMENT", 0, SQLCOM_NOTHING};
|
||||
struct sa_keyword procedure_word= {9, "PROCEDURE", 0, SQLCOM_NOTHING};
|
||||
|
||||
|
||||
struct sa_keyword keywords_to_skip[]=
|
||||
{
|
||||
{3, "SET", &statement_word, SQLCOM_QUERY_ADMIN},
|
||||
{0, NULL, 0, SQLCOM_DDL}
|
||||
};
|
||||
|
||||
|
||||
struct sa_keyword not_ddl_keywords[]=
|
||||
{
|
||||
{4, "DROP", &function_word, SQLCOM_QUERY_ADMIN},
|
||||
{4, "DROP", &procedure_word, SQLCOM_QUERY_ADMIN},
|
||||
{4, "DROP", &user_word, SQLCOM_DCL},
|
||||
{6, "CREATE", &user_word, SQLCOM_DCL},
|
||||
{6, "CREATE", &function_word, SQLCOM_QUERY_ADMIN},
|
||||
{6, "CREATE", &procedure_word, SQLCOM_QUERY_ADMIN},
|
||||
{6, "RENAME", &user_word, SQLCOM_DCL},
|
||||
{0, NULL, 0, SQLCOM_DDL}
|
||||
};
|
||||
|
||||
|
||||
struct sa_keyword ddl_keywords[]=
|
||||
{
|
||||
{4, "DROP", 0, SQLCOM_DDL},
|
||||
{5, "ALTER", 0, SQLCOM_DDL},
|
||||
{6, "CREATE", 0, SQLCOM_DDL},
|
||||
{6, "RENAME", 0, SQLCOM_DDL},
|
||||
{8, "TRUNCATE", 0, SQLCOM_DDL},
|
||||
{0, NULL, 0, SQLCOM_DDL}
|
||||
};
|
||||
|
||||
|
||||
struct sa_keyword dml_keywords[]=
|
||||
{
|
||||
{2, "DO", 0, SQLCOM_DML},
|
||||
{4, "CALL", 0, SQLCOM_DML},
|
||||
{4, "LOAD", &data_word, SQLCOM_DML},
|
||||
{4, "LOAD", &xml_word, SQLCOM_DML},
|
||||
{6, "DELETE", 0, SQLCOM_DML},
|
||||
{6, "INSERT", 0, SQLCOM_DML},
|
||||
{6, "SELECT", 0, SQLCOM_DML},
|
||||
{6, "UPDATE", 0, SQLCOM_DML},
|
||||
{7, "HANDLER", 0, SQLCOM_DML},
|
||||
{7, "REPLACE", 0, SQLCOM_DML},
|
||||
{0, NULL, 0, SQLCOM_DML}
|
||||
};
|
||||
|
||||
|
||||
struct sa_keyword passwd_keywords[]=
|
||||
{
|
||||
{3, "SET", &password_word, SQLCOM_SET_OPTION},
|
||||
{5, "ALTER", &server_word, SQLCOM_ALTER_SERVER},
|
||||
{5, "GRANT", 0, SQLCOM_GRANT},
|
||||
{6, "CREATE", &user_word, SQLCOM_CREATE_USER},
|
||||
{6, "CREATE", &server_word, SQLCOM_CREATE_SERVER},
|
||||
{6, "CHANGE", &master_word, SQLCOM_CHANGE_MASTER},
|
||||
{0, NULL, 0, SQLCOM_NOTHING}
|
||||
};
|
||||
|
||||
#define MAX_KEYWORD 9
|
||||
|
||||
|
||||
static void error_header()
|
||||
{
|
||||
struct tm tm_time;
|
||||
@ -563,6 +668,7 @@ struct connection_info
|
||||
int log_always;
|
||||
};
|
||||
|
||||
|
||||
static HASH connection_hash;
|
||||
|
||||
|
||||
@ -773,6 +879,21 @@ static struct connection_info *
|
||||
#define SAFE_STRLEN(s) (s ? strlen(s) : 0)
|
||||
|
||||
|
||||
static int is_space(char c)
|
||||
{
|
||||
return c == ' ' || c == '\r' || c == '\n' || c == '\t';
|
||||
}
|
||||
|
||||
|
||||
#define SKIP_SPACES(str) \
|
||||
do { \
|
||||
while (is_space(*str)) \
|
||||
++str; \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
||||
|
||||
static struct connection_info *
|
||||
add_connection_initdb(const struct mysql_event_general *event)
|
||||
{
|
||||
@ -980,6 +1101,98 @@ static size_t escape_string(const char *str, unsigned int len,
|
||||
}
|
||||
|
||||
|
||||
static size_t escape_string_hide_passwords(const char *str, unsigned int len,
|
||||
char *result, size_t result_len,
|
||||
const char *word1, size_t word1_len,
|
||||
const char *word2, size_t word2_len,
|
||||
int next_text_string)
|
||||
{
|
||||
const char *res_start= result;
|
||||
const char *res_end= result + result_len - 2;
|
||||
size_t d_len;
|
||||
char b_char;
|
||||
|
||||
while (len)
|
||||
{
|
||||
if (len > word1_len + 1 && strncasecmp(str, word1, word1_len) == 0)
|
||||
{
|
||||
const char *next_s= str + word1_len;
|
||||
size_t c;
|
||||
|
||||
if (next_text_string)
|
||||
{
|
||||
while (*next_s && *next_s != '\'' && *next_s != '"')
|
||||
++next_s;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (word2)
|
||||
{
|
||||
SKIP_SPACES(next_s);
|
||||
if (len < (next_s - str) + word2_len + 1 ||
|
||||
strncasecmp(next_s, word2, word2_len) != 0)
|
||||
goto no_password;
|
||||
next_s+= word2_len;
|
||||
}
|
||||
|
||||
while (*next_s && *next_s != '\'' && *next_s != '"')
|
||||
++next_s;
|
||||
}
|
||||
|
||||
d_len= next_s - str;
|
||||
if (result + d_len + 5 > res_end)
|
||||
break;
|
||||
|
||||
for (c=0; c<d_len; c++)
|
||||
result[c]= is_space(str[c]) ? ' ' : str[c];
|
||||
|
||||
memmove(result + d_len, "*****", 5);
|
||||
result+= d_len + 5;
|
||||
b_char= *(next_s++);
|
||||
while (*next_s)
|
||||
{
|
||||
if (*next_s == b_char)
|
||||
{
|
||||
++next_s;
|
||||
break;
|
||||
}
|
||||
if (*next_s == '\\')
|
||||
{
|
||||
if (next_s[1])
|
||||
next_s++;
|
||||
}
|
||||
next_s++;
|
||||
}
|
||||
len-= next_s - str;
|
||||
str= next_s;
|
||||
continue;
|
||||
}
|
||||
no_password:
|
||||
if (result >= res_end)
|
||||
break;
|
||||
if (*str == '\'')
|
||||
{
|
||||
*(result++)= '\\';
|
||||
*(result++)= '\'';
|
||||
}
|
||||
else if (*str == '\\')
|
||||
{
|
||||
*(result++)= '\\';
|
||||
*(result++)= '\\';
|
||||
}
|
||||
else if (is_space(*str))
|
||||
*(result++)= ' ';
|
||||
else
|
||||
*(result++)= *str;
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
*result= 0;
|
||||
return result - res_start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int do_log_user(const char *name)
|
||||
{
|
||||
size_t len;
|
||||
@ -998,6 +1211,96 @@ static int do_log_user(const char *name)
|
||||
}
|
||||
|
||||
|
||||
static int get_next_word(const char *query, char *word)
|
||||
{
|
||||
int len= 0;
|
||||
char c;
|
||||
while ((c= query[len]))
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
word[len]= 'A' + (c-'a');
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
word[len]= c;
|
||||
else
|
||||
break;
|
||||
|
||||
if (len++ == MAX_KEYWORD)
|
||||
return 0;
|
||||
}
|
||||
word[len]= 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int filter_query_type(const char *query, struct sa_keyword *kwd)
|
||||
{
|
||||
int qwe_in_list;
|
||||
char fword[MAX_KEYWORD + 1], nword[MAX_KEYWORD + 1];
|
||||
int len, nlen= 0;
|
||||
const struct sa_keyword *l_keywords;
|
||||
|
||||
while (*query && (is_space(*query) || *query == '(' || *query == '/'))
|
||||
{
|
||||
/* comment handling */
|
||||
if (*query == '/' && query[1] == '*')
|
||||
{
|
||||
if (query[2] == '!')
|
||||
{
|
||||
query+= 3;
|
||||
while (*query >= '0' && *query <= '9')
|
||||
query++;
|
||||
continue;
|
||||
}
|
||||
query+= 2;
|
||||
while (*query)
|
||||
{
|
||||
if (*query=='*' && query[1] == '/')
|
||||
{
|
||||
query+= 2;
|
||||
break;
|
||||
}
|
||||
query++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
query++;
|
||||
}
|
||||
|
||||
qwe_in_list= 0;
|
||||
if (!(len= get_next_word(query, fword)))
|
||||
goto not_in_list;
|
||||
query+= len+1;
|
||||
|
||||
l_keywords= kwd;
|
||||
while (l_keywords->length)
|
||||
{
|
||||
if (l_keywords->length == len && strncmp(l_keywords->wd, fword, len) == 0)
|
||||
{
|
||||
if (l_keywords->next)
|
||||
{
|
||||
if (nlen == 0)
|
||||
{
|
||||
while (*query && is_space(*query))
|
||||
query++;
|
||||
nlen= get_next_word(query, nword);
|
||||
}
|
||||
if (l_keywords->next->length != nlen ||
|
||||
strncmp(l_keywords->next->wd, nword, nlen) != 0)
|
||||
goto do_loop;
|
||||
}
|
||||
|
||||
qwe_in_list= l_keywords->type;
|
||||
break;
|
||||
};
|
||||
do_loop:
|
||||
l_keywords++;
|
||||
}
|
||||
|
||||
not_in_list:
|
||||
return qwe_in_list;
|
||||
}
|
||||
|
||||
|
||||
static int log_statement_ex(const struct connection_info *cn,
|
||||
time_t ev_time, unsigned long thd_id,
|
||||
const char *query, unsigned int query_len,
|
||||
@ -1034,10 +1337,77 @@ static int log_statement_ex(const struct connection_info *cn,
|
||||
/* Can happen after the error in mysqld_prepare_stmt() */
|
||||
query= cn->query;
|
||||
query_len= cn->query_length;
|
||||
if (query == 0 || query_len == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (query && !(events & EVENT_QUERY_ALL) &&
|
||||
(events & EVENT_QUERY))
|
||||
{
|
||||
const char *orig_query= query;
|
||||
|
||||
if (filter_query_type(query, keywords_to_skip))
|
||||
{
|
||||
char fword[MAX_KEYWORD + 1];
|
||||
int len;
|
||||
do
|
||||
{
|
||||
len= get_next_word(query, fword);
|
||||
query+= len ? len : 1;
|
||||
if (len == 3 && strncmp(fword, "FOR", 3) == 0)
|
||||
break;
|
||||
} while (*query);
|
||||
|
||||
if (*query == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (events & EVENT_QUERY_DDL)
|
||||
{
|
||||
if (!filter_query_type(query, not_ddl_keywords) &&
|
||||
filter_query_type(query, ddl_keywords))
|
||||
goto do_log_query;
|
||||
}
|
||||
if (events & EVENT_QUERY_DML)
|
||||
{
|
||||
if (filter_query_type(query, dml_keywords))
|
||||
goto do_log_query;
|
||||
}
|
||||
|
||||
return 0;
|
||||
do_log_query:
|
||||
query= orig_query;
|
||||
}
|
||||
|
||||
switch (filter_query_type(query, passwd_keywords))
|
||||
{
|
||||
case SQLCOM_GRANT:
|
||||
case SQLCOM_CREATE_USER:
|
||||
esc_q_len= escape_string_hide_passwords(query, query_len,
|
||||
uh_buffer, sizeof(uh_buffer),
|
||||
"IDENTIFIED", 10, "BY", 2, 0);
|
||||
break;
|
||||
case SQLCOM_CHANGE_MASTER:
|
||||
esc_q_len= escape_string_hide_passwords(query, query_len,
|
||||
uh_buffer, sizeof(uh_buffer),
|
||||
"MASTER_PASSWORD", 15, "=", 1, 0);
|
||||
break;
|
||||
case SQLCOM_CREATE_SERVER:
|
||||
case SQLCOM_ALTER_SERVER:
|
||||
esc_q_len= escape_string_hide_passwords(query, query_len,
|
||||
uh_buffer, sizeof(uh_buffer),
|
||||
"PASSWORD", 8, NULL, 0, 0);
|
||||
break;
|
||||
case SQLCOM_SET_OPTION:
|
||||
esc_q_len= escape_string_hide_passwords(query, query_len,
|
||||
uh_buffer, sizeof(uh_buffer),
|
||||
"=", 1, NULL, 0, 1);
|
||||
break;
|
||||
default:
|
||||
esc_q_len= escape_string(query, query_len,
|
||||
uh_buffer, sizeof(uh_buffer));
|
||||
break;
|
||||
}
|
||||
csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
|
||||
",\'%.*s\',%d", esc_q_len, uh_buffer, error_code);
|
||||
message[csize]= '\n';
|
||||
@ -1386,6 +1756,105 @@ exit_func:
|
||||
}
|
||||
|
||||
|
||||
#ifdef DBUG_OFF
|
||||
#ifdef __x86_64__
|
||||
static const int cmd_off= 4200;
|
||||
static const int db_off= 120;
|
||||
static const int db_len_off= 128;
|
||||
#else
|
||||
static const int cmd_off= 2668;
|
||||
static const int db_off= 60;
|
||||
static const int db_len_off= 64;
|
||||
#endif /*x86_64*/
|
||||
#else
|
||||
#ifdef __x86_64__
|
||||
static const int cmd_off= 4432;
|
||||
static const int db_off= 120;
|
||||
static const int db_len_off= 128;
|
||||
#else
|
||||
static const int cmd_off= 2808;
|
||||
static const int db_off= 64;
|
||||
static const int db_len_off= 68;
|
||||
#endif /*x86_64*/
|
||||
#endif /*DBUG_OFF*/
|
||||
|
||||
struct mysql_event_general_v8
|
||||
{
|
||||
unsigned int event_class;
|
||||
unsigned int event_subclass;
|
||||
int general_error_code;
|
||||
unsigned long general_thread_id;
|
||||
const char *general_user;
|
||||
unsigned int general_user_length;
|
||||
const char *general_command;
|
||||
unsigned int general_command_length;
|
||||
const char *general_query;
|
||||
unsigned int general_query_length;
|
||||
struct charset_info_st *general_charset;
|
||||
unsigned long long general_time;
|
||||
unsigned long long general_rows;
|
||||
};
|
||||
|
||||
static void auditing_v8(MYSQL_THD thd, struct mysql_event_general_v8 *ev_v8)
|
||||
{
|
||||
struct mysql_event_general event;
|
||||
|
||||
if (ev_v8->event_class != MYSQL_AUDIT_GENERAL_CLASS)
|
||||
return;
|
||||
|
||||
event.event_subclass= ev_v8->event_subclass;
|
||||
event.general_error_code= ev_v8->general_error_code;
|
||||
event.general_thread_id= ev_v8->general_thread_id;
|
||||
event.general_user= ev_v8->general_user;
|
||||
event.general_user_length= ev_v8->general_user_length;
|
||||
event.general_command= ev_v8->general_command;
|
||||
event.general_command_length= ev_v8->general_command_length;
|
||||
event.general_query= ev_v8->general_query;
|
||||
event.general_query_length= ev_v8->general_query_length;
|
||||
event.general_charset= ev_v8->general_charset;
|
||||
event.general_time= ev_v8->general_time;
|
||||
event.general_rows= ev_v8->general_rows;
|
||||
event.database= 0;
|
||||
event.database_length= 0;
|
||||
|
||||
if (event.general_query_length > 0)
|
||||
{
|
||||
event.event_subclass= MYSQL_AUDIT_GENERAL_STATUS;
|
||||
event.general_command= "Query";
|
||||
event.general_command_length= 5;
|
||||
#ifdef __linux__
|
||||
event.database= *(char **) (((char *) thd) + db_off);
|
||||
event.database_length= *(size_t *) (((char *) thd) + db_len_off);
|
||||
#endif /*__linux*/
|
||||
}
|
||||
#ifdef __linux__
|
||||
else if (*((int *) (((char *)thd) + cmd_off)) == 2)
|
||||
{
|
||||
event.event_subclass= MYSQL_AUDIT_GENERAL_LOG;
|
||||
event.general_command= "Init DB";
|
||||
event.general_command_length= 7;
|
||||
event.general_query= *(char **) (((char *) thd) + db_off);
|
||||
event.general_query_length= *(size_t *) (((char *) thd) + db_len_off);
|
||||
}
|
||||
#endif /*__linux*/
|
||||
auditing(thd, ev_v8->event_class, &event);
|
||||
}
|
||||
|
||||
|
||||
static void auditing_v13(MYSQL_THD thd, unsigned int *ev_v0)
|
||||
{
|
||||
struct mysql_event_general event= *(const struct mysql_event_general *) (ev_v0+1);
|
||||
|
||||
if (event.general_query_length > 0)
|
||||
{
|
||||
event.event_subclass= MYSQL_AUDIT_GENERAL_STATUS;
|
||||
event.general_command= "Query";
|
||||
event.general_command_length= 5;
|
||||
}
|
||||
auditing(thd, ev_v0[0], &event);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
As it's just too difficult to #include "sql_class.h",
|
||||
let's just copy the necessary part of the system_variables
|
||||
@ -1461,15 +1930,19 @@ typedef struct loc_system_variables
|
||||
ulong query_cache_type;
|
||||
} LOC_SV;
|
||||
|
||||
|
||||
static int server_audit_init(void *p __attribute__((unused)))
|
||||
{
|
||||
const void *my_hash_init_ptr;
|
||||
|
||||
if (!serv_ver)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
serv_ver= (const char *) GetProcAddress(0, "server_version");
|
||||
#else
|
||||
serv_ver= server_version;
|
||||
#endif /*_WIN32*/
|
||||
|
||||
}
|
||||
my_hash_init_ptr= dlsym(RTLD_DEFAULT, "_my_hash_init");
|
||||
if (!my_hash_init_ptr)
|
||||
{
|
||||
@ -1477,8 +1950,14 @@ static int server_audit_init(void *p __attribute__((unused)))
|
||||
my_hash_init_ptr= dlsym(RTLD_DEFAULT, "my_hash_init2");
|
||||
}
|
||||
|
||||
if(!(int_mysql_data_home= dlsym(RTLD_DEFAULT, "mysql_data_home")))
|
||||
{
|
||||
if(!(int_mysql_data_home= dlsym(RTLD_DEFAULT, "?mysql_data_home@@3PADA")))
|
||||
int_mysql_data_home= &default_home;
|
||||
}
|
||||
|
||||
if (!serv_ver || !my_hash_init_ptr)
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
if (!started_mysql)
|
||||
{
|
||||
@ -1489,7 +1968,6 @@ static int server_audit_init(void *p __attribute__((unused)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (gethostname(servhost, sizeof(servhost)))
|
||||
strcpy(servhost, "unknown");
|
||||
|
||||
@ -1608,8 +2086,8 @@ mysql_declare_plugin(server_audit)
|
||||
MYSQL_AUDIT_PLUGIN,
|
||||
&mysql_descriptor,
|
||||
"SERVER_AUDIT",
|
||||
" Alexey Botchkov (MariaDB)",
|
||||
"Audit the server activity.",
|
||||
" Alexey Botchkov (MariaDB Corporation)",
|
||||
"Audit the server activity",
|
||||
PLUGIN_LICENSE_GPL,
|
||||
server_audit_init_mysql,
|
||||
server_audit_deinit,
|
||||
@ -1636,8 +2114,8 @@ maria_declare_plugin(server_audit)
|
||||
MYSQL_AUDIT_PLUGIN,
|
||||
&maria_descriptor,
|
||||
"SERVER_AUDIT",
|
||||
"Alexey Botchkov (MariaDB)",
|
||||
"Audit the server activity.",
|
||||
"Alexey Botchkov (MariaDB Corporation)",
|
||||
"Audit the server activity",
|
||||
PLUGIN_LICENSE_GPL,
|
||||
server_audit_init,
|
||||
server_audit_deinit,
|
||||
@ -1645,7 +2123,7 @@ maria_declare_plugin(server_audit)
|
||||
audit_status,
|
||||
vars,
|
||||
PLUGIN_STR_VERSION,
|
||||
MariaDB_PLUGIN_MATURITY_BETA
|
||||
MariaDB_PLUGIN_MATURITY_GAMMA
|
||||
}
|
||||
maria_declare_plugin_end;
|
||||
|
||||
@ -1915,3 +2393,48 @@ static void update_syslog_ident(MYSQL_THD thd __attribute__((unused)),
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
if (fdwReason != DLL_PROCESS_ATTACH)
|
||||
return 1;
|
||||
|
||||
serv_ver= (const char *) GetProcAddress(0, "server_version");
|
||||
#else
|
||||
void __attribute__ ((constructor)) audit_plugin_so_init(void)
|
||||
{
|
||||
serv_ver= server_version;
|
||||
#endif /*_WIN32*/
|
||||
|
||||
if (!serv_ver)
|
||||
goto exit;
|
||||
|
||||
started_mariadb= strstr(serv_ver, "MariaDB") != 0;
|
||||
|
||||
if (!started_mariadb)
|
||||
{
|
||||
if (serv_ver[0] == '5' && serv_ver[2] == '5')
|
||||
{
|
||||
int sc= serv_ver[4] - '0';
|
||||
if (serv_ver[5] >= '0' && serv_ver[5] <= '9')
|
||||
sc= sc * 10 + serv_ver[5] - '0';
|
||||
if (sc <= 10)
|
||||
{
|
||||
mysql_descriptor.interface_version= 0x0200;
|
||||
mysql_descriptor.event_notify= (void *) auditing_v8;
|
||||
}
|
||||
else if (sc < 14)
|
||||
{
|
||||
mysql_descriptor.interface_version= 0x0200;
|
||||
mysql_descriptor.event_notify= (void *) auditing_v13;
|
||||
}
|
||||
}
|
||||
}
|
||||
exit:
|
||||
#ifdef _WIN32
|
||||
return 1;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user