diff options
Diffstat (limited to 'plugin/server_audit/server_audit.c')
-rw-r--r-- | plugin/server_audit/server_audit.c | 150 |
1 files changed, 96 insertions, 54 deletions
diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index e0504a0a24c..0832e7f390d 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -1,4 +1,5 @@ /* Copyright (C) 2013, 2015, Alexey Botchkov and SkySQL Ab + Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,7 +16,7 @@ #define PLUGIN_VERSION 0x104 -#define PLUGIN_STR_VERSION "1.4.6" +#define PLUGIN_STR_VERSION "1.4.7" #define _my_thread_var loc_thread_var @@ -23,8 +24,13 @@ #include <assert.h> #ifndef _WIN32 +#define DO_SYSLOG #include <syslog.h> +static const char out_type_desc[]= "Desired output type. Possible values - 'syslog', 'file'" + " or 'null' as no output."; #else +static const char out_type_desc[]= "Desired output type. Possible values - 'file'" + " or 'null' as no output."; #define syslog(PRIORITY, FORMAT, INFO, MESSAGE_LEN, MESSAGE) do {}while(0) static void closelog() {} #define openlog(IDENT, LOG_NOWAIT, LOG_USER) do {}while(0) @@ -86,6 +92,7 @@ static void closelog() {} #include <mysql/plugin.h> #include <mysql/plugin_audit.h> #include <string.h> +#include "../../mysys/mysys_priv.h" #ifndef RTLD_DEFAULT #define RTLD_DEFAULT NULL #endif @@ -290,7 +297,7 @@ static unsigned long long file_rotate_size; static unsigned int rotations; static my_bool rotate= TRUE; static char logging; -static int internal_stop_logging= 0; +static volatile int internal_stop_logging= 0; static char incl_user_buffer[1024]; static char excl_user_buffer[1024]; static char *big_buffer= NULL; @@ -383,18 +390,28 @@ static MYSQL_SYSVAR_SET(events, events, PLUGIN_VAR_RQCMDARG, "Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE," " QUERY_DDL, QUERY_DML, QUERY_DML_NO_SELECT, QUERY_DCL.", NULL, NULL, 0, &events_typelib); +#ifdef DO_SYSLOG #define OUTPUT_SYSLOG 0 #define OUTPUT_FILE 1 +#else +#define OUTPUT_SYSLOG 0xFFFF +#define OUTPUT_FILE 0 +#endif /*DO_SYSLOG*/ + #define OUTPUT_NO 0xFFFF -static const char *output_type_names[]= { "syslog", "file", 0 }; +static const char *output_type_names[]= { +#ifdef DO_SYSLOG + "syslog", +#endif + "file", 0 }; static TYPELIB output_typelib= { array_elements(output_type_names) - 1, "output_typelib", output_type_names, NULL }; static MYSQL_SYSVAR_ENUM(output_type, output_type, PLUGIN_VAR_RQCMDARG, - "Desired output type. Possible values - 'syslog', 'file'" - " or 'null' as no output.", 0, update_output_type, OUTPUT_FILE, + out_type_desc, + 0, update_output_type, OUTPUT_FILE, &output_typelib); static MYSQL_SYSVAR_STR(file_path, file_path, PLUGIN_VAR_RQCMDARG, "Path to the log file.", NULL, update_file_path, default_file_name); @@ -536,16 +553,20 @@ static struct st_mysql_show_var audit_status[]= #if defined(HAVE_PSI_INTERFACE) && !defined(FLOGGER_NO_PSI) /* These belong to the service initialization */ static PSI_mutex_key key_LOCK_operations; +static PSI_mutex_key key_LOCK_atomic; static PSI_mutex_key key_LOCK_bigbuffer; static PSI_mutex_info mutex_key_list[]= { { &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations", PSI_FLAG_GLOBAL}, + { &key_LOCK_atomic, "SERVER_AUDIT_plugin::lock_atomic", + PSI_FLAG_GLOBAL}, { &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer", PSI_FLAG_GLOBAL} }; #endif static mysql_mutex_t lock_operations; +static mysql_mutex_t lock_atomic; static mysql_mutex_t lock_bigbuffer; /* The Percona server and partly MySQL don't support */ @@ -556,6 +577,14 @@ static mysql_mutex_t lock_bigbuffer; /* worths doing. */ #define CLIENT_ERROR if (!started_mysql) my_printf_error +#define ADD_ATOMIC(x, a) \ + do { \ + flogger_mutex_lock(&lock_atomic); \ + x+= a; \ + flogger_mutex_unlock(&lock_atomic); \ + } while (0) + + static uchar *getkey_user(const char *entry, size_t *length, my_bool nu __attribute__((unused)) ) { @@ -734,20 +763,20 @@ static int user_coll_fill(struct user_coll *c, char *users, if (cmp_user && take_over_cmp) { - internal_stop_logging= 1; + ADD_ATOMIC(internal_stop_logging, 1); CLIENT_ERROR(1, "User '%.*s' was removed from the" " server_audit_excl_users.", MYF(ME_WARNING), (int) cmp_length, users); - internal_stop_logging= 0; + ADD_ATOMIC(internal_stop_logging, -1); blank_user(cmp_user); refill_cmp_coll= 1; } else if (cmp_user) { - internal_stop_logging= 1; + ADD_ATOMIC(internal_stop_logging, 1); CLIENT_ERROR(1, "User '%.*s' is in the server_audit_incl_users, " "so wasn't added.", MYF(ME_WARNING), (int) cmp_length, users); - internal_stop_logging= 0; + ADD_ATOMIC(internal_stop_logging, -1); remove_user(users); continue; } @@ -1125,6 +1154,7 @@ static void setup_connection_connect(struct connection_info *cn, #define SAFE_STRLEN(s) (s ? strlen(s) : 0) +#define SAFE_STRLEN_UI(s) ((unsigned int) (s ? strlen(s) : 0)) static char empty_str[1]= { 0 }; @@ -1255,29 +1285,36 @@ static void change_connection(struct connection_info *cn, event->ip, event->ip_length); } -static int write_log(const char *message, size_t len) +static int write_log(const char *message, size_t len, int take_lock) { + int result= 0; + if (take_lock) + flogger_mutex_lock(&lock_operations); + if (output_type == OUTPUT_FILE) { if (logfile && - (is_active= (logger_write(logfile, message, len) == (int)len))) - return 0; + (is_active= (logger_write(logfile, message, len) == (int) len))) + goto exit; ++log_write_failures; - return 1; + result= 1; } else if (output_type == OUTPUT_SYSLOG) { syslog(syslog_facility_codes[syslog_facility] | syslog_priority_codes[syslog_priority], - "%s %.*s", syslog_info, (int)len, message); + "%s %.*s", syslog_info, (int) len, message); } - return 0; +exit: + if (take_lock) + flogger_mutex_unlock(&lock_operations); + return result; } static size_t log_header(char *message, size_t message_len, time_t *ts, - const char *serverhost, unsigned int serverhost_len, + const char *serverhost, size_t serverhost_len, const char *username, unsigned int username_len, const char *host, unsigned int host_len, const char *userip, unsigned int userip_len, @@ -1295,7 +1332,7 @@ static size_t log_header(char *message, size_t message_len, if (output_type == OUTPUT_SYSLOG) return my_snprintf(message, message_len, "%.*s,%.*s,%.*s,%d,%lld,%s", - serverhost_len, serverhost, + (unsigned int) serverhost_len, serverhost, username_len, username, host_len, host, connection_id, query_id, operation); @@ -1330,7 +1367,7 @@ static int log_connection(const struct connection_info *cn, csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, ",%.*s,,%d", cn->db_length, cn->db, event->status); message[csize]= '\n'; - return write_log(message, csize + 1); + return write_log(message, csize + 1, 1); } @@ -1351,7 +1388,7 @@ static int log_connection_event(const struct mysql_event_connection *event, csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, ",%.*s,,%d", event->database.length, event->database.str, event->status); message[csize]= '\n'; - return write_log(message, csize + 1); + return write_log(message, csize + 1, 1); } @@ -1480,21 +1517,28 @@ no_password: -static int do_log_user(const char *name) +static int do_log_user(const char *name, int take_lock) { size_t len; + int result; if (!name) return 0; len= strlen(name); - if (incl_user_coll.n_users) - return coll_search(&incl_user_coll, name, len) != 0; + if (take_lock) + flogger_mutex_lock(&lock_operations); - if (excl_user_coll.n_users) - return coll_search(&excl_user_coll, name, len) == 0; + if (incl_user_coll.n_users) + result= coll_search(&incl_user_coll, name, len) != 0; + else if (excl_user_coll.n_users) + result= coll_search(&excl_user_coll, name, len) == 0; + else + result= 1; - return 1; + if (take_lock) + flogger_mutex_unlock(&lock_operations); + return result; } @@ -1591,7 +1635,7 @@ not_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, - int error_code, const char *type) + int error_code, const char *type, int take_lock) { size_t csize; char message_loc[1024]; @@ -1739,7 +1783,7 @@ do_log_query: csize+= my_snprintf(message+csize, message_size - 1 - csize, "\',%d", error_code); message[csize]= '\n'; - result= write_log(message, csize + 1); + result= write_log(message, csize + 1, take_lock); if (message == big_buffer) flogger_mutex_unlock(&lock_bigbuffer); @@ -1753,7 +1797,7 @@ static int log_statement(const struct connection_info *cn, { return log_statement_ex(cn, event->general_time, event->general_thread_id, event->general_query, event->general_query_length, - event->general_error_code, type); + event->general_error_code, type, 1); } @@ -1767,15 +1811,15 @@ static int log_table(const struct connection_info *cn, (void) time(&ctime); csize= log_header(message, sizeof(message)-1, &ctime, servhost, servhost_len, - event->user, (unsigned int)SAFE_STRLEN(event->user), - event->host, (unsigned int)SAFE_STRLEN(event->host), - event->ip, (unsigned int)SAFE_STRLEN(event->ip), + event->user, SAFE_STRLEN_UI(event->user), + event->host, SAFE_STRLEN_UI(event->host), + event->ip, SAFE_STRLEN_UI(event->ip), event->thread_id, cn->query_id, type); csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, ",%.*s,%.*s,",event->database.length, event->database.str, event->table.length, event->table.str); message[csize]= '\n'; - return write_log(message, csize + 1); + return write_log(message, csize + 1, 1); } @@ -1789,9 +1833,9 @@ static int log_rename(const struct connection_info *cn, (void) time(&ctime); csize= log_header(message, sizeof(message)-1, &ctime, servhost, servhost_len, - event->user, (unsigned int)SAFE_STRLEN(event->user), - event->host, (unsigned int)SAFE_STRLEN(event->host), - event->ip, (unsigned int)SAFE_STRLEN(event->ip), + event->user, SAFE_STRLEN_UI(event->user), + event->host, SAFE_STRLEN_UI(event->host), + event->ip, SAFE_STRLEN_UI(event->ip), event->thread_id, cn->query_id, "RENAME"); csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, ",%.*s,%.*s|%.*s.%.*s,",event->database.length, event->database.str, @@ -1799,7 +1843,7 @@ static int log_rename(const struct connection_info *cn, event->new_database.length, event->new_database.str, event->new_table.length, event->new_table.str); message[csize]= '\n'; - return write_log(message, csize + 1); + return write_log(message, csize + 1, 1); } @@ -1991,8 +2035,6 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) if (!thd || internal_stop_logging) return; - flogger_mutex_lock(&lock_operations); - if (maria_55_started && debug_server_started && event_class == MYSQL_AUDIT_GENERAL_CLASS) { @@ -2031,7 +2073,7 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) } if (event_class == MYSQL_AUDIT_GENERAL_CLASS && FILTER(EVENT_QUERY) && - cn && (cn->log_always || do_log_user(cn->user))) + cn && (cn->log_always || do_log_user(cn->user, 1))) { const struct mysql_event_general *event = (const struct mysql_event_general *) ev; @@ -2051,7 +2093,7 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) { const struct mysql_event_table *event = (const struct mysql_event_table *) ev; - if (do_log_user(event->user)) + if (do_log_user(event->user, 1)) { switch (event->event_subclass) { @@ -2115,7 +2157,6 @@ exit_func: break; } } - flogger_mutex_unlock(&lock_operations); } @@ -2384,6 +2425,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_atomic, MY_MUTEX_INIT_FAST); flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST); coll_init(&incl_user_coll); @@ -2471,6 +2513,7 @@ static int server_audit_deinit(void *p __attribute__((unused))) (void) free(big_buffer); flogger_mutex_destroy(&lock_operations); + flogger_mutex_destroy(&lock_atomic); flogger_mutex_destroy(&lock_bigbuffer); error_header(); @@ -2563,7 +2606,7 @@ static void log_current_query(MYSQL_THD thd) { cn->log_always= 1; log_statement_ex(cn, cn->query_time, thd_get_thread_id(thd), - cn->query, cn->query_length, 0, "QUERY"); + cn->query, cn->query_length, 0, "QUERY", 0); cn->log_always= 0; } } @@ -2575,12 +2618,13 @@ static void update_file_path(MYSQL_THD thd, { char *new_name= (*(char **) save) ? *(char **) save : empty_str; - if (!maria_55_started || !debug_server_started) - flogger_mutex_lock(&lock_operations); - internal_stop_logging= 1; + ADD_ATOMIC(internal_stop_logging, 1); error_header(); fprintf(stderr, "Log file name was changed to '%s'.\n", new_name); + if (!maria_55_started || !debug_server_started) + flogger_mutex_lock(&lock_operations); + if (logging) log_current_query(thd); @@ -2589,7 +2633,6 @@ static void update_file_path(MYSQL_THD thd, char *sav_path= file_path; file_path= new_name; - internal_stop_logging= 1; stop_logging(); if (start_logging()) { @@ -2605,16 +2648,15 @@ static void update_file_path(MYSQL_THD thd, } goto exit_func; } - internal_stop_logging= 0; } strncpy(path_buffer, new_name, sizeof(path_buffer)-1); path_buffer[sizeof(path_buffer)-1]= 0; file_path= path_buffer; exit_func: - internal_stop_logging= 0; if (!maria_55_started || !debug_server_started) flogger_mutex_unlock(&lock_operations); + ADD_ATOMIC(internal_stop_logging, -1); } @@ -2745,8 +2787,8 @@ static void update_output_type(MYSQL_THD thd, if (output_type == new_output_type) return; + ADD_ATOMIC(internal_stop_logging, 1); flogger_mutex_lock(&lock_operations); - internal_stop_logging= 1; if (logging) { log_current_query(thd); @@ -2760,8 +2802,8 @@ static void update_output_type(MYSQL_THD thd, if (logging) start_logging(); - internal_stop_logging= 0; flogger_mutex_unlock(&lock_operations); + ADD_ATOMIC(internal_stop_logging, -1); } @@ -2809,9 +2851,9 @@ static void update_logging(MYSQL_THD thd, if (new_logging == logging) return; + ADD_ATOMIC(internal_stop_logging, 1); if (!maria_55_started || !debug_server_started) flogger_mutex_lock(&lock_operations); - internal_stop_logging= 1; if ((logging= new_logging)) { start_logging(); @@ -2827,9 +2869,9 @@ static void update_logging(MYSQL_THD thd, stop_logging(); } - internal_stop_logging= 0; if (!maria_55_started || !debug_server_started) flogger_mutex_unlock(&lock_operations); + ADD_ATOMIC(internal_stop_logging, -1); } @@ -2841,16 +2883,16 @@ static void update_mode(MYSQL_THD thd __attribute__((unused)), if (mode_readonly || new_mode == mode) return; + ADD_ATOMIC(internal_stop_logging, 1); if (!maria_55_started || !debug_server_started) flogger_mutex_lock(&lock_operations); - internal_stop_logging= 1; mark_always_logged(thd); error_header(); fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode); mode= new_mode; - internal_stop_logging= 0; if (!maria_55_started || !debug_server_started) flogger_mutex_unlock(&lock_operations); + ADD_ATOMIC(internal_stop_logging, -1); } |