diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2015-03-31 13:10:43 +0500 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2015-03-31 13:10:43 +0500 |
commit | cc84ac3be41d9d6ac480d55449d5bf4e324cca10 (patch) | |
tree | dfe6d3990cd177ec5b44b36a704a54ff2f0684e7 /plugin | |
parent | 995f622ceaf96d8e37d260cba0833975e61c756f (diff) | |
download | mariadb-git-cc84ac3be41d9d6ac480d55449d5bf4e324cca10.tar.gz |
MDEV-7596 audit plugin - record full query / document line length / make buffer configurable.
The serve_audit_query_log_limit variable implemented.
Also QUERY_DCL filter added.
Diffstat (limited to 'plugin')
-rw-r--r-- | plugin/server_audit/server_audit.c | 130 |
1 files changed, 102 insertions, 28 deletions
diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index ce5d5397d9b..a4d726b0c7d 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -14,8 +14,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define PLUGIN_VERSION 0x102 -#define PLUGIN_STR_VERSION "1.2.0" +#define PLUGIN_VERSION 0x103 +#define PLUGIN_STR_VERSION "1.3.0" #include <my_config.h> #include <stdio.h> @@ -185,6 +185,9 @@ static char logging; static int internal_stop_logging= 0; static char incl_user_buffer[1024]; static char excl_user_buffer[1024]; +static char *big_buffer= NULL; +static size_t big_buffer_alloced= 0; +static unsigned int query_log_limit= 0; static char servhost[256]; static size_t servhost_len; @@ -227,14 +230,15 @@ static MYSQL_SYSVAR_STR(excl_users, excl_users, PLUGIN_VAR_RQCMDARG, /* bits in the event filter. */ #define EVENT_CONNECT 1 #define EVENT_QUERY_ALL 2 -#define EVENT_QUERY 26 +#define EVENT_QUERY 58 #define EVENT_TABLE 4 #define EVENT_QUERY_DDL 8 #define EVENT_QUERY_DML 16 +#define EVENT_QUERY_DCL 32 static const char *event_names[]= { - "CONNECT", "QUERY", "TABLE", "QUERY_DDL", "QUERY_DML", + "CONNECT", "QUERY", "TABLE", "QUERY_DDL", "QUERY_DML", "QUERY_DCL", NULL }; static TYPELIB events_typelib= @@ -279,6 +283,9 @@ static MYSQL_SYSVAR_STR(syslog_ident, syslog_ident, PLUGIN_VAR_RQCMDARG, static MYSQL_SYSVAR_STR(syslog_info, syslog_info, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, "The <info> string to be added to the SYSLOG record.", NULL, NULL, ""); +static MYSQL_SYSVAR_UINT(query_log_limit, query_log_limit, + PLUGIN_VAR_OPCMDARG, "Limit on the length of the query string in a record.", + NULL, NULL, 1024, 0, 0x7FFFFFFF, 1); static const char *syslog_facility_names[]= { @@ -358,6 +365,7 @@ static struct st_mysql_sys_var* vars[] = { MYSQL_SYSVAR(syslog_ident), MYSQL_SYSVAR(syslog_facility), MYSQL_SYSVAR(syslog_priority), + MYSQL_SYSVAR(query_log_limit), NULL }; @@ -382,9 +390,11 @@ static struct st_mysql_show_var audit_status[]= static PSI_mutex_key key_LOCK_operations; static PSI_mutex_info mutex_key_list[]= {{ &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations", +{{ &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer", PSI_FLAG_GLOBAL}}; #endif static mysql_mutex_t lock_operations; +static mysql_mutex_t lock_bigbuffer; /* The Percona server and partly MySQL don't support */ /* launching client errors in the 'update_variable' methods. */ @@ -617,6 +627,18 @@ struct sa_keyword dml_keywords[]= }; +struct sa_keyword dcl_keywords[]= +{ + {6, "CREATE", &user_word, SQLCOM_DCL}, + {4, "DROP", &user_word, SQLCOM_DCL}, + {6, "RENAME", &user_word, SQLCOM_DCL}, + {5, "GRANT", 0, SQLCOM_DCL}, + {6, "REVOKE", 0, SQLCOM_DCL}, + {3, "SET", &password_word, SQLCOM_DCL}, + {0, NULL, 0, SQLCOM_DDL} +}; + + struct sa_keyword passwd_keywords[]= { {3, "SET", &password_word, SQLCOM_SET_OPTION}, @@ -1084,11 +1106,15 @@ static size_t escape_string(const char *str, unsigned int len, break; if (*str == '\'') { + if (result+1 >= res_end) + break; *(result++)= '\\'; *(result++)= '\''; } else if (*str == '\\') { + if (result+1 >= res_end) + break; *(result++)= '\\'; *(result++)= '\\'; } @@ -1173,11 +1199,15 @@ no_password: break; if (*str == '\'') { + if (result+1 >= res_end) + break; *(result++)= '\\'; *(result++)= '\''; } else if (*str == '\\') { + if (result+1 >= res_end) + break; *(result++)= '\\'; *(result++)= '\\'; } @@ -1307,12 +1337,16 @@ static int log_statement_ex(const struct connection_info *cn, const char *query, unsigned int query_len, int error_code, const char *type) { - size_t csize, esc_q_len; - char message[1024]; - char uh_buffer[768]; + size_t csize; + char message_loc[1024]; + char *message= message_loc; + size_t message_size= sizeof(message_loc); + char *uh_buffer; + size_t uh_buffer_size; const char *db; unsigned int db_length; long long query_id; + int result; if ((db= cn->db)) db_length= cn->db_length; @@ -1325,14 +1359,6 @@ static int log_statement_ex(const struct connection_info *cn, if (!(query_id= cn->query_id)) query_id= query_counter++; - csize= log_header(message, sizeof(message)-1, &ev_time, - servhost, servhost_len, - cn->user, cn->user_length,cn->host, cn->host_length, - cn->ip, cn->ip_length, thd_id, query_id, type); - - csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, - ",%.*s", db_length, db); - if (query == 0) { /* Can happen after the error in mysqld_prepare_stmt() */ @@ -1374,45 +1400,89 @@ static int log_statement_ex(const struct connection_info *cn, if (filter_query_type(query, dml_keywords)) goto do_log_query; } + if (events & EVENT_QUERY_DCL) + { + if (filter_query_type(query, dcl_keywords)) + goto do_log_query; + } return 0; do_log_query: query= orig_query; } + csize= log_header(message, message_size-1, &ev_time, + servhost, servhost_len, + cn->user, cn->user_length,cn->host, cn->host_length, + cn->ip, cn->ip_length, thd_id, query_id, type); + + csize+= my_snprintf(message+csize, message_size - 1 - csize, + ",%.*s,\'", db_length, db); + + if (query_log_limit > 0 && query_len > query_log_limit) + query_len= query_log_limit; + + if (query_len > (message_size - csize)/2) + { + flogger_mutex_lock(&lock_bigbuffer); + if (big_buffer_alloced < (query_len * 2 + csize)) + { + big_buffer_alloced= (query_len * 2 + csize + 4095) & ~4095L; + big_buffer= realloc(big_buffer, big_buffer_alloced); + if (big_buffer == NULL) + { + big_buffer_alloced= 0; + return 0; + } + } + + memcpy(big_buffer, message, csize); + message= big_buffer; + message_size= big_buffer_alloced; + } + + uh_buffer= message + csize; + uh_buffer_size= message_size - csize; + if (query_log_limit > 0 && uh_buffer_size > query_log_limit+2) + uh_buffer_size= query_log_limit+2; + 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), + csize+= escape_string_hide_passwords(query, query_len, + uh_buffer, uh_buffer_size, "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), + csize+= escape_string_hide_passwords(query, query_len, + uh_buffer, uh_buffer_size, "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), + csize+= escape_string_hide_passwords(query, query_len, + uh_buffer, uh_buffer_size, "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), + csize+= escape_string_hide_passwords(query, query_len, + uh_buffer, uh_buffer_size, "=", 1, NULL, 0, 1); break; default: - esc_q_len= escape_string(query, query_len, - uh_buffer, sizeof(uh_buffer)); + csize+= escape_string(query, query_len, + uh_buffer, uh_buffer_size); break; } - csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, - ",\'%.*s\',%d", esc_q_len, uh_buffer, error_code); + csize+= my_snprintf(message+csize, message_size - 1 - csize, + "\',%d", error_code); message[csize]= '\n'; - return write_log(message, csize + 1); + result= write_log(message, csize + 1); + if (message == big_buffer) + flogger_mutex_unlock(&lock_bigbuffer); + + return result; } @@ -1980,6 +2050,7 @@ static int server_audit_init(void *p __attribute__((unused))) PSI_server->register_mutex("server_audit", mutex_key_list, 1); #endif flogger_mutex_init(key_LOCK_operations, &lock_operations, MY_MUTEX_INIT_FAST); + flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST); my_hash_clear(&incl_user_hash); my_hash_clear(&excl_user_hash); @@ -2056,7 +2127,10 @@ static int server_audit_deinit(void *p __attribute__((unused))) logger_close(logfile); else if (output_type == OUTPUT_SYSLOG) closelog(); + + (void) free(big_buffer); flogger_mutex_destroy(&lock_operations); + flogger_mutex_destroy(&lock_bigbuffer); error_header(); fprintf(stderr, "STOPPED\n"); |