[Commits] Rev 4424: Audit plugin v1.2.0. in file:///home/hf/wmar/55exp/

holyfoot at askmonty.org holyfoot at askmonty.org
Sun Feb 8 21:56:00 EET 2015


At file:///home/hf/wmar/55exp/

------------------------------------------------------------
revno: 4424
revision-id: holyfoot at askmonty.org-20150208183819-nxto11r353jnv5x3
parent: elenst at montyprogram.com-20150208124700-871uamawu1oi9iu4
committer: Alexey Botchkov <holyfoot at askmonty.org>
branch nick: 55exp
timestamp: Sun 2015-02-08 22:38:19 +0400
message:
  Audit plugin v1.2.0.
-------------- next part --------------
=== modified file 'mysql-test/suite/plugins/r/server_audit.result'
--- a/mysql-test/suite/plugins/r/server_audit.result	2014-02-24 19:40:16 +0000
+++ b/mysql-test/suite/plugins/r/server_audit.result	2015-02-08 18:38:19 +0000
@@ -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
 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

=== modified file 'mysql-test/suite/plugins/t/server_audit.test'
--- a/mysql-test/suite/plugins/t/server_audit.test	2014-03-26 19:58:27 +0000
+++ b/mysql-test/suite/plugins/t/server_audit.test	2015-02-08 18:38:19 +0000
@@ -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';

=== modified file 'plugin/server_audit/server_audit.c'
--- a/plugin/server_audit/server_audit.c	2014-10-02 09:57:40 +0000
+++ b/plugin/server_audit/server_audit.c	2015-02-08 18:38:19 +0000
@@ -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_I
 #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_I
 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
        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 
 }
 
 
+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;
@@ -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 *
 }
 
 
+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
     /* 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;
   }
 
-  esc_q_len= escape_string(query, query_len,
-                           uh_buffer, sizeof(uh_buffer)); 
+  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 @@ static void auditing(MYSQL_THD thd __att
 }
 
 
+#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
@@ -1464,12 +1934,15 @@ typedef struct loc_system_variables
 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");
+    serv_ver= (const char *) GetProcAddress(0, "server_version");
 #else
-  serv_ver= server_version;
+    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 __a
     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)
   {
@@ -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_TH
 }
 
 
+#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
+}
+



More information about the commits mailing list