Commit da6a6abc authored by Sergey Vojtovich's avatar Sergey Vojtovich

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.
parent 20cd65b9
...@@ -42,6 +42,8 @@ struct mysql_event ...@@ -42,6 +42,8 @@ struct mysql_event
LOG events occurs before emitting to the general query log. LOG events occurs before emitting to the general query log.
ERROR events occur before transmitting errors to the user. ERROR events occur before transmitting errors to the user.
RESULT events occur after transmitting a resultset 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 #define MYSQL_AUDIT_GENERAL_CLASS 0
...@@ -49,6 +51,7 @@ struct mysql_event ...@@ -49,6 +51,7 @@ struct mysql_event
#define MYSQL_AUDIT_GENERAL_LOG 0 #define MYSQL_AUDIT_GENERAL_LOG 0
#define MYSQL_AUDIT_GENERAL_ERROR 1 #define MYSQL_AUDIT_GENERAL_ERROR 1
#define MYSQL_AUDIT_GENERAL_RESULT 2 #define MYSQL_AUDIT_GENERAL_RESULT 2
#define MYSQL_AUDIT_GENERAL_STATUS 3
struct mysql_event_general struct mysql_event_general
{ {
...@@ -68,6 +71,43 @@ 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 Here we define the descriptor structure, that is referred from
st_mysql_plugin. st_mysql_plugin.
......
...@@ -208,6 +208,27 @@ struct mysql_event_general ...@@ -208,6 +208,27 @@ struct mysql_event_general
unsigned long long general_time; unsigned long long general_time;
unsigned long long general_rows; 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 struct st_mysql_audit
{ {
int interface_version; int interface_version;
......
...@@ -1992,6 +1992,7 @@ void close_connection(THD *thd, uint errcode, bool lock) ...@@ -1992,6 +1992,7 @@ void close_connection(THD *thd, uint errcode, bool lock)
{ {
sleep(0); /* Workaround to avoid tailcall optimisation */ sleep(0); /* Workaround to avoid tailcall optimisation */
} }
MYSQL_AUDIT_NOTIFY_CONNECTION_DISCONNECT(thd, errcode);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
#endif /* EMBEDDED_LIBRARY */ #endif /* EMBEDDED_LIBRARY */
......
...@@ -81,9 +81,34 @@ static void general_class_handler(THD *thd, uint event_subtype, va_list ap) ...@@ -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[] = static audit_handler_t audit_handlers[] =
{ {
general_class_handler general_class_handler, connection_class_handler
}; };
static const uint audit_handlers_count= static const uint audit_handlers_count=
......
...@@ -32,8 +32,12 @@ extern void mysql_audit_free_thd(THD *thd); ...@@ -32,8 +32,12 @@ extern void mysql_audit_free_thd(THD *thd);
extern void mysql_audit_acquire_plugins(THD *thd, uint event_class); extern void mysql_audit_acquire_plugins(THD *thd, uint event_class);
#ifndef EMBEDDED_LIBRARY
extern void mysql_audit_notify(THD *thd, uint event_class, extern void mysql_audit_notify(THD *thd, uint event_class,
uint event_subtype, ...); uint event_subtype, ...);
#else
#define mysql_audit_notify(...)
#endif
extern void mysql_audit_release(THD *thd); extern void mysql_audit_release(THD *thd);
#define MAX_USER_HOST_SIZE 512 #define MAX_USER_HOST_SIZE 512
...@@ -84,6 +88,7 @@ void mysql_audit_general_log(THD *thd, time_t time, ...@@ -84,6 +88,7 @@ void mysql_audit_general_log(THD *thd, time_t time,
event_subtype should be set to one of: event_subtype should be set to one of:
MYSQL_AUDIT_GENERAL_ERROR MYSQL_AUDIT_GENERAL_ERROR
MYSQL_AUDIT_GENERAL_RESULT MYSQL_AUDIT_GENERAL_RESULT
MYSQL_AUDIT_GENERAL_STATUS
@param[in] thd @param[in] thd
@param[in] event_subtype Type of general audit event. @param[in] event_subtype Type of general audit event.
...@@ -126,5 +131,41 @@ void mysql_audit_general(THD *thd, uint event_subtype, ...@@ -126,5 +131,41 @@ void mysql_audit_general(THD *thd, uint event_subtype,
#endif #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 */ #endif /* SQL_AUDIT_INCLUDED */
...@@ -728,9 +728,12 @@ void do_handle_one_connection(THD *thd_arg) ...@@ -728,9 +728,12 @@ void do_handle_one_connection(THD *thd_arg)
for (;;) for (;;)
{ {
NET *net= &thd->net; NET *net= &thd->net;
bool rc;
lex_start(thd); lex_start(thd);
if (login_connection(thd)) rc= login_connection(thd);
MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd);
if (rc)
goto end_thread; goto end_thread;
MYSQL_CONNECTION_START(thd->thread_id, thd->security_ctx->priv_user, MYSQL_CONNECTION_START(thd->thread_id, thd->security_ctx->priv_user,
......
...@@ -937,6 +937,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -937,6 +937,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif #endif
case COM_CHANGE_USER: case COM_CHANGE_USER:
{ {
bool rc;
status_var_increment(thd->status_var.com_other); status_var_increment(thd->status_var.com_other);
thd->change_user(); thd->change_user();
...@@ -956,7 +957,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -956,7 +957,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
CHARSET_INFO *save_character_set_results= CHARSET_INFO *save_character_set_results=
thd->variables.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); my_free(thd->security_ctx->user);
*thd->security_ctx= save_security_ctx; *thd->security_ctx= save_security_ctx;
...@@ -1395,6 +1398,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1395,6 +1398,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (!thd->is_error() && !thd->killed_errno()) if (!thd->is_error() && !thd->killed_errno())
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0); 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); log_slow_statement(thd);
thd_proc_info(thd, "cleaning up"); thd_proc_info(thd, "cleaning up");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment