diff options
author | Sergey Vojtovich <sergey.vojtovich@oracle.com> | 2010-12-14 17:34:23 +0300 |
---|---|---|
committer | Sergey Vojtovich <sergey.vojtovich@oracle.com> | 2010-12-14 17:34:23 +0300 |
commit | 9a3e46c520e857c9e32eebc612fe00991dcc5fe3 (patch) | |
tree | a01ebb52ef2a45d385cf45850e61c8b584256240 | |
parent | b7b33fd9d6bfe683d6c3d96742aca57282a20d45 (diff) | |
download | mariadb-git-9a3e46c520e857c9e32eebc612fe00991dcc5fe3.tar.gz |
WL#5571 - Audit interface: MYSQL_AUDIT_GENERAL_STATUS event
include/mysql/plugin_audit.h:
Connection auditing class.
include/mysql/plugin_audit.h.pp:
Connection auditing class.
sql/mysqld.cc:
Notify disconnect to auditing.
sql/sql_audit.cc:
Connection class event dispatcher.
sql/sql_audit.h:
mysql_audit_notify() is not available in embedded.
sql/sql_connect.cc:
Notify connect to auditing.
sql/sql_parse.cc:
Notify user change to auditing.
-rw-r--r-- | include/mysql/plugin_audit.h | 40 | ||||
-rw-r--r-- | include/mysql/plugin_audit.h.pp | 21 | ||||
-rw-r--r-- | sql/mysqld.cc | 1 | ||||
-rw-r--r-- | sql/sql_audit.cc | 27 | ||||
-rw-r--r-- | sql/sql_audit.h | 41 | ||||
-rw-r--r-- | sql/sql_connect.cc | 5 | ||||
-rw-r--r-- | sql/sql_parse.cc | 9 |
7 files changed, 141 insertions, 3 deletions
diff --git a/include/mysql/plugin_audit.h b/include/mysql/plugin_audit.h index 41505da64af..8811c832949 100644 --- a/include/mysql/plugin_audit.h +++ b/include/mysql/plugin_audit.h @@ -42,6 +42,8 @@ struct mysql_event LOG events occurs before emitting to the general query log. ERROR events occur before transmitting errors to the user. RESULT events occur after transmitting a resultset to the user. + STATUS events occur after transmitting a resultset or errors + to the user. */ #define MYSQL_AUDIT_GENERAL_CLASS 0 @@ -49,6 +51,7 @@ struct mysql_event #define MYSQL_AUDIT_GENERAL_LOG 0 #define MYSQL_AUDIT_GENERAL_ERROR 1 #define MYSQL_AUDIT_GENERAL_RESULT 2 +#define MYSQL_AUDIT_GENERAL_STATUS 3 struct mysql_event_general { @@ -68,6 +71,43 @@ struct mysql_event_general }; +/* + AUDIT CLASS : CONNECTION + + CONNECT occurs after authentication phase is completed. + DISCONNECT occurs after connection is terminated. + CHANGE_USER occurs after COM_CHANGE_USER RPC is completed. +*/ + +#define MYSQL_AUDIT_CONNECTION_CLASS 1 +#define MYSQL_AUDIT_CONNECTION_CLASSMASK (1 << MYSQL_AUDIT_CONNECTION_CLASS) +#define MYSQL_AUDIT_CONNECTION_CONNECT 0 +#define MYSQL_AUDIT_CONNECTION_DISCONNECT 1 +#define MYSQL_AUDIT_CONNECTION_CHANGE_USER 2 + +struct mysql_event_connection +{ + unsigned int event_class; + unsigned int event_subclass; + int status; + unsigned long thread_id; + const char *user; + unsigned int user_length; + const char *priv_user; + unsigned int priv_user_length; + const char *external_user; + unsigned int external_user_length; + const char *proxy_user; + unsigned int proxy_user_length; + const char *host; + unsigned int host_length; + const char *ip; + unsigned int ip_length; + const char *database; + unsigned int database_length; +}; + + /************************************************************************* Here we define the descriptor structure, that is referred from st_mysql_plugin. diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index b48cbca2e87..0e5b97d8717 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -208,6 +208,27 @@ struct mysql_event_general unsigned long long general_time; unsigned long long general_rows; }; +struct mysql_event_connection +{ + unsigned int event_class; + unsigned int event_subclass; + int status; + unsigned long thread_id; + const char *user; + unsigned int user_length; + const char *priv_user; + unsigned int priv_user_length; + const char *external_user; + unsigned int external_user_length; + const char *proxy_user; + unsigned int proxy_user_length; + const char *host; + unsigned int host_length; + const char *ip; + unsigned int ip_length; + const char *database; + unsigned int database_length; +}; struct st_mysql_audit { int interface_version; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 49523a5b007..5fb63fb61ba 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1992,6 +1992,7 @@ void close_connection(THD *thd, uint errcode, bool lock) { sleep(0); /* Workaround to avoid tailcall optimisation */ } + MYSQL_AUDIT_NOTIFY_CONNECTION_DISCONNECT(thd, errcode); DBUG_VOID_RETURN; } #endif /* EMBEDDED_LIBRARY */ diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc index b7d363dc09a..74e9e603ebe 100644 --- a/sql/sql_audit.cc +++ b/sql/sql_audit.cc @@ -81,9 +81,34 @@ static void general_class_handler(THD *thd, uint event_subtype, va_list ap) } +static void connection_class_handler(THD *thd, uint event_subclass, va_list ap) +{ + mysql_event_connection event; + event.event_class= MYSQL_AUDIT_CONNECTION_CLASS; + event.event_subclass= event_subclass; + event.status= va_arg(ap, int); + event.thread_id= va_arg(ap, unsigned long); + event.user= va_arg(ap, const char *); + event.user_length= va_arg(ap, unsigned int); + event.priv_user= va_arg(ap, const char *); + event.priv_user_length= va_arg(ap, unsigned int); + event.external_user= va_arg(ap, const char *); + event.external_user_length= va_arg(ap, unsigned int); + event.proxy_user= va_arg(ap, const char *); + event.proxy_user_length= va_arg(ap, unsigned int); + event.host= va_arg(ap, const char *); + event.host_length= va_arg(ap, unsigned int); + event.ip= va_arg(ap, const char *); + event.ip_length= va_arg(ap, unsigned int); + event.database= va_arg(ap, const char *); + event.database_length= va_arg(ap, unsigned int); + event_class_dispatch(thd, (const mysql_event *) &event); +} + + static audit_handler_t audit_handlers[] = { - general_class_handler + general_class_handler, connection_class_handler }; static const uint audit_handlers_count= diff --git a/sql/sql_audit.h b/sql/sql_audit.h index cbc4c7a7232..d676c3974bc 100644 --- a/sql/sql_audit.h +++ b/sql/sql_audit.h @@ -32,8 +32,12 @@ extern void mysql_audit_free_thd(THD *thd); extern void mysql_audit_acquire_plugins(THD *thd, uint event_class); +#ifndef EMBEDDED_LIBRARY extern void mysql_audit_notify(THD *thd, uint event_class, uint event_subtype, ...); +#else +#define mysql_audit_notify(...) +#endif extern void mysql_audit_release(THD *thd); #define MAX_USER_HOST_SIZE 512 @@ -84,6 +88,7 @@ void mysql_audit_general_log(THD *thd, time_t time, event_subtype should be set to one of: MYSQL_AUDIT_GENERAL_ERROR MYSQL_AUDIT_GENERAL_RESULT + MYSQL_AUDIT_GENERAL_STATUS @param[in] thd @param[in] event_subtype Type of general audit event. @@ -126,5 +131,41 @@ void mysql_audit_general(THD *thd, uint event_subtype, #endif } +#define MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd) mysql_audit_notify(\ + (thd), MYSQL_AUDIT_CONNECTION_CLASS, MYSQL_AUDIT_CONNECTION_CONNECT,\ + (thd)->stmt_da->is_error() ? (thd)->stmt_da->sql_errno() : 0,\ + (thd)->thread_id, (thd)->security_ctx->user,\ + (thd)->security_ctx->user ? strlen((thd)->security_ctx->user) : 0,\ + (thd)->security_ctx->priv_user, strlen((thd)->security_ctx->priv_user),\ + (thd)->security_ctx->external_user,\ + (thd)->security_ctx->external_user ?\ + strlen((thd)->security_ctx->external_user) : 0,\ + (thd)->security_ctx->proxy_user, strlen((thd)->security_ctx->proxy_user),\ + (thd)->security_ctx->host,\ + (thd)->security_ctx->host ? strlen((thd)->security_ctx->host) : 0,\ + (thd)->security_ctx->ip,\ + (thd)->security_ctx->ip ? strlen((thd)->security_ctx->ip) : 0,\ + (thd)->db, (thd)->db ? strlen((thd)->db) : 0) + +#define MYSQL_AUDIT_NOTIFY_CONNECTION_DISCONNECT(thd, errcode)\ + mysql_audit_notify(\ + (thd), MYSQL_AUDIT_CONNECTION_CLASS, MYSQL_AUDIT_CONNECTION_DISCONNECT,\ + (errcode), (thd)->thread_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +#define MYSQL_AUDIT_NOTIFY_CONNECTION_CHANGE_USER(thd) mysql_audit_notify(\ + (thd), MYSQL_AUDIT_CONNECTION_CLASS, MYSQL_AUDIT_CONNECTION_CHANGE_USER,\ + (thd)->stmt_da->is_error() ? (thd)->stmt_da->sql_errno() : 0,\ + (thd)->thread_id, (thd)->security_ctx->user,\ + (thd)->security_ctx->user ? strlen((thd)->security_ctx->user) : 0,\ + (thd)->security_ctx->priv_user, strlen((thd)->security_ctx->priv_user),\ + (thd)->security_ctx->external_user,\ + (thd)->security_ctx->external_user ?\ + strlen((thd)->security_ctx->external_user) : 0,\ + (thd)->security_ctx->proxy_user, strlen((thd)->security_ctx->proxy_user),\ + (thd)->security_ctx->host,\ + (thd)->security_ctx->host ? strlen((thd)->security_ctx->host) : 0,\ + (thd)->security_ctx->ip,\ + (thd)->security_ctx->ip ? strlen((thd)->security_ctx->ip) : 0,\ + (thd)->db, (thd)->db ? strlen((thd)->db) : 0) #endif /* SQL_AUDIT_INCLUDED */ diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index d03d77c1f66..a47493b7d0d 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -728,9 +728,12 @@ void do_handle_one_connection(THD *thd_arg) for (;;) { NET *net= &thd->net; + bool rc; lex_start(thd); - if (login_connection(thd)) + rc= login_connection(thd); + MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd); + if (rc) goto end_thread; MYSQL_CONNECTION_START(thd->thread_id, thd->security_ctx->priv_user, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3d5f99c8953..cdeaeee18c1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -937,6 +937,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif case COM_CHANGE_USER: { + bool rc; status_var_increment(thd->status_var.com_other); thd->change_user(); @@ -956,7 +957,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, CHARSET_INFO *save_character_set_results= thd->variables.character_set_results; - if (acl_authenticate(thd, 0, packet_length)) + rc= acl_authenticate(thd, 0, packet_length); + MYSQL_AUDIT_NOTIFY_CONNECTION_CHANGE_USER(thd); + if (rc) { my_free(thd->security_ctx->user); *thd->security_ctx= save_security_ctx; @@ -1395,6 +1398,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (!thd->is_error() && !thd->killed_errno()) mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0); + mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_STATUS, + thd->stmt_da->is_error() ? thd->stmt_da->sql_errno() : 0, + command_name[command].str); + log_slow_statement(thd); thd_proc_info(thd, "cleaning up"); |