17 #include "sql_audit.h"
22 #ifndef EMBEDDED_LIBRARY
26 unsigned int event_class;
30 unsigned long mysql_global_audit_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
34 static void event_class_dispatch(THD *thd,
unsigned int event_class,
39 void set_audit_mask(
unsigned long *mask, uint event_class)
42 mask[0]<<= event_class;
46 void add_audit_mask(
unsigned long *mask,
const unsigned long *rhs)
52 bool check_audit_mask(
const unsigned long *lhs,
53 const unsigned long *rhs)
55 return !(lhs[0] & rhs[0]);
59 typedef void (*audit_handler_t)(THD *thd, uint event_subtype, va_list ap);
71 static void general_class_handler(THD *thd, uint event_subtype, va_list ap)
74 event.event_subclass= event_subtype;
75 event.general_error_code= va_arg(ap,
int);
76 event.general_thread_id= thd ? thd->thread_id : 0;
77 event.general_time= va_arg(ap, time_t);
78 event.general_user= va_arg(ap,
const char *);
79 event.general_user_length= va_arg(ap,
unsigned int);
80 event.general_command= va_arg(ap,
const char *);
81 event.general_command_length= va_arg(ap,
unsigned int);
82 event.general_query= va_arg(ap,
const char *);
83 event.general_query_length= va_arg(ap,
unsigned int);
85 event.general_rows= (
unsigned long long) va_arg(ap, ha_rows);
90 event_class_dispatch(thd, MYSQL_AUDIT_GENERAL_CLASS, &event);
94 static void connection_class_handler(THD *thd, uint event_subclass, va_list ap)
97 event.event_subclass= event_subclass;
98 event.status= va_arg(ap,
int);
99 event.thread_id= va_arg(ap,
unsigned long);
100 event.user= va_arg(ap,
const char *);
101 event.user_length= va_arg(ap,
unsigned int);
102 event.priv_user= va_arg(ap,
const char *);
103 event.priv_user_length= va_arg(ap,
unsigned int);
104 event.external_user= va_arg(ap,
const char *);
105 event.external_user_length= va_arg(ap,
unsigned int);
106 event.proxy_user= va_arg(ap,
const char *);
107 event.proxy_user_length= va_arg(ap,
unsigned int);
108 event.host= va_arg(ap,
const char *);
109 event.host_length= va_arg(ap,
unsigned int);
110 event.ip= va_arg(ap,
const char *);
111 event.ip_length= va_arg(ap,
unsigned int);
112 event.database= va_arg(ap,
const char *);
113 event.database_length= va_arg(ap,
unsigned int);
114 event_class_dispatch(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event);
118 static audit_handler_t audit_handlers[] =
120 general_class_handler, connection_class_handler
123 static const uint audit_handlers_count=
124 (
sizeof(audit_handlers) /
sizeof(audit_handler_t));
137 static my_bool acquire_plugins(THD *thd,
plugin_ref plugin,
void *arg)
139 uint event_class= *(uint*) arg;
140 unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
143 set_audit_mask(event_class_mask, event_class);
146 if (check_audit_mask(data->class_mask, event_class_mask))
155 if (!check_audit_mask(data->class_mask, thd->audit_class_mask))
159 if (unlikely(!thd->audit_class_plugins.buffer))
162 my_init_dynamic_array(&thd->audit_class_plugins,
167 plugin= my_plugin_lock(NULL, &plugin);
168 insert_dynamic(&thd->audit_class_plugins, &plugin);
183 void mysql_audit_acquire_plugins(THD *thd, uint event_class)
185 unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
186 DBUG_ENTER(
"mysql_audit_acquire_plugins");
187 set_audit_mask(event_class_mask, event_class);
188 if (thd && !check_audit_mask(mysql_global_audit_mask, event_class_mask) &&
189 check_audit_mask(thd->audit_class_mask, event_class_mask))
191 plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, &event_class);
192 add_audit_mask(thd->audit_class_mask, event_class_mask);
208 void mysql_audit_notify(THD *thd, uint event_class, uint event_subtype, ...)
211 audit_handler_t *handlers= audit_handlers + event_class;
212 DBUG_ASSERT(event_class < audit_handlers_count);
213 mysql_audit_acquire_plugins(thd, event_class);
214 va_start(ap, event_subtype);
215 (*handlers)(thd, event_subtype, ap);
227 void mysql_audit_release(THD *thd)
231 if (!thd || !(thd->audit_class_plugins.elements))
234 plugins= (
plugin_ref*) thd->audit_class_plugins.buffer;
235 plugins_last= plugins + thd->audit_class_plugins.elements;
236 for (; plugins < plugins_last; plugins++)
241 if (!(data->release_thd))
245 data->release_thd(thd);
249 plugin_unlock_list(NULL, (
plugin_ref*) thd->audit_class_plugins.buffer,
250 thd->audit_class_plugins.elements);
253 reset_dynamic(&thd->audit_class_plugins);
254 memset(thd->audit_class_mask, 0,
sizeof(thd->audit_class_mask));
265 void mysql_audit_init_thd(THD *thd)
267 memset(&thd->audit_class_plugins, 0,
sizeof(thd->audit_class_plugins));
268 memset(thd->audit_class_mask, 0,
sizeof(thd->audit_class_mask));
282 void mysql_audit_free_thd(THD *thd)
284 mysql_audit_release(thd);
285 DBUG_ASSERT(thd->audit_class_plugins.elements == 0);
286 delete_dynamic(&thd->audit_class_plugins);
289 #ifdef HAVE_PSI_INTERFACE
290 static PSI_mutex_key key_LOCK_audit_mask;
292 static PSI_mutex_info all_audit_mutexes[]=
294 { &key_LOCK_audit_mask,
"LOCK_audit_mask", PSI_FLAG_GLOBAL}
297 static void init_audit_psi_keys(
void)
299 const char* category=
"sql";
302 count= array_elements(all_audit_mutexes);
311 void mysql_audit_initialize()
313 #ifdef HAVE_PSI_INTERFACE
314 init_audit_psi_keys();
317 mysql_mutex_init(key_LOCK_audit_mask, &LOCK_audit_mask, MY_MUTEX_INIT_FAST);
318 memset(mysql_global_audit_mask, 0,
sizeof(mysql_global_audit_mask));
326 void mysql_audit_finalize()
345 if (!data->class_mask || !data->event_notify ||
346 !data->class_mask[0])
348 sql_print_error(
"Plugin '%s' has invalid data.",
353 if (plugin->plugin->init && plugin->plugin->init(plugin))
355 sql_print_error(
"Plugin '%s' init function returned error.",
361 plugin->data= plugin->plugin->info;
365 add_audit_mask(mysql_global_audit_mask, data->class_mask);
381 static my_bool calc_class_mask(THD *thd,
plugin_ref plugin,
void *arg)
385 add_audit_mask((
unsigned long *) arg, data->class_mask);
400 unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
402 if (plugin->plugin->deinit && plugin->plugin->deinit(NULL))
404 DBUG_PRINT(
"warning", (
"Plugin '%s' deinit function returned error.",
406 DBUG_EXECUTE(
"finalize_audit_plugin",
return 1; );
410 memset(&event_class_mask, 0,
sizeof(event_class_mask));
419 plugin_foreach(current_thd, calc_class_mask, MYSQL_AUDIT_PLUGIN,
423 bmove(mysql_global_audit_mask, event_class_mask,
sizeof(event_class_mask));
440 static my_bool plugins_dispatch(THD *thd,
plugin_ref plugin,
void *arg)
444 unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
447 set_audit_mask(event_class_mask, event_generic->event_class);
450 if (check_audit_mask(data->class_mask, event_class_mask))
454 data->event_notify(thd, event_generic->event_class, event_generic->event);
467 static void event_class_dispatch(THD *thd,
unsigned int event_class,
471 event_generic.event_class= event_class;
472 event_generic.event= event;
479 plugin_foreach(thd, plugins_dispatch, MYSQL_AUDIT_PLUGIN, &event_generic);
486 plugins= (
plugin_ref*) thd->audit_class_plugins.buffer;
487 plugins_last= plugins + thd->audit_class_plugins.elements;
489 for (; plugins < plugins_last; plugins++)
490 plugins_dispatch(thd, *plugins, &event_generic);
498 void mysql_audit_acquire_plugins(THD *thd, uint event_class)
503 void mysql_audit_initialize()
508 void mysql_audit_finalize()
525 void mysql_audit_release(THD *thd)