Browse Source
Backport from 6.0-codebase.
Backport from 6.0-codebase.
WL#3771
"Audit Plugin Interface"
Implement new plug-in type - AUDIT
New plug-in: audit_null
simply increments counter for how many times it was called.
pull/73/head
23 changed files with 1125 additions and 229 deletions
-
3include/Makefile.am
-
220include/mysql/plugin.h
-
10include/mysql/plugin.h.pp
-
98include/mysql/plugin_audit.h
-
211include/mysql/plugin_ftparser.h
-
3libmysqld/CMakeLists.txt
-
4libmysqld/Makefile.am
-
32plugin/audit_null/Makefile.am
-
130plugin/audit_null/audit_null.c
-
4plugin/audit_null/plug.in
-
2sql/CMakeLists.txt
-
4sql/Makefile.am
-
8sql/event_queue.cc
-
9sql/log.cc
-
31sql/mysqld.cc
-
448sql/sql_audit.cc
-
78sql/sql_audit.h
-
5sql/sql_class.cc
-
15sql/sql_class.h
-
2sql/sql_connect.cc
-
3sql/sql_insert.cc
-
10sql/sql_parse.cc
-
24sql/sql_plugin.cc
@ -0,0 +1,98 @@ |
|||||
|
/* Copyright (C) 2007 MySQL AB |
||||
|
|
||||
|
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 |
||||
|
the Free Software Foundation; version 2 of the License. |
||||
|
|
||||
|
This program is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
||||
|
|
||||
|
#ifndef _my_audit_h |
||||
|
#define _my_audit_h |
||||
|
|
||||
|
/************************************************************************* |
||||
|
API for Audit plugin. (MYSQL_AUDIT_PLUGIN) |
||||
|
*/ |
||||
|
|
||||
|
#include "plugin.h" |
||||
|
|
||||
|
#define MYSQL_AUDIT_CLASS_MASK_SIZE 1 |
||||
|
|
||||
|
#define MYSQL_AUDIT_INTERFACE_VERSION ( 0x010000 | MYSQL_AUDIT_CLASS_MASK_SIZE ) |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
The first word in every event class struct indicates the specific |
||||
|
class of the event. |
||||
|
*/ |
||||
|
struct mysql_event |
||||
|
{ |
||||
|
int event_class; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/************************************************************************* |
||||
|
AUDIT CLASS : GENERAL |
||||
|
|
||||
|
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. |
||||
|
*/ |
||||
|
|
||||
|
#define MYSQL_AUDIT_GENERAL_CLASS 0 |
||||
|
#define MYSQL_AUDIT_GENERAL_CLASSMASK (1 << MYSQL_AUDIT_GENERAL_CLASS) |
||||
|
#define MYSQL_AUDIT_GENERAL_LOG 0 |
||||
|
#define MYSQL_AUDIT_GENERAL_ERROR 1 |
||||
|
#define MYSQL_AUDIT_GENERAL_RESULT 2 |
||||
|
|
||||
|
struct mysql_event_general |
||||
|
{ |
||||
|
int event_class; |
||||
|
int general_error_code; |
||||
|
unsigned long general_thread_id; |
||||
|
const char *general_user; |
||||
|
unsigned int general_user_length; |
||||
|
const char *general_command; |
||||
|
unsigned int general_command_length; |
||||
|
const char *general_query; |
||||
|
unsigned int general_query_length; |
||||
|
struct charset_info_st *general_charset; |
||||
|
unsigned long long general_time; |
||||
|
unsigned long long general_rows; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/************************************************************************* |
||||
|
Here we define the descriptor structure, that is referred from |
||||
|
st_mysql_plugin. |
||||
|
|
||||
|
release_thd() event occurs when the event class consumer is to be |
||||
|
disassociated from the specified THD. This would typically occur |
||||
|
before some operation which may require sleeping - such as when |
||||
|
waiting for the next query from the client. |
||||
|
|
||||
|
event_notify() is invoked whenever an event occurs which is of any |
||||
|
class for which the plugin has interest. The first word of the |
||||
|
mysql_event argument indicates the specific event class and the |
||||
|
remainder of the structure is as required for that class. |
||||
|
|
||||
|
class_mask is an array of bits used to indicate what event classes |
||||
|
that this plugin wants to receive. |
||||
|
*/ |
||||
|
|
||||
|
struct st_mysql_audit |
||||
|
{ |
||||
|
int interface_version; |
||||
|
void (*release_thd)(MYSQL_THD); |
||||
|
void (*event_notify)(MYSQL_THD, const struct mysql_event *); |
||||
|
unsigned long class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,211 @@ |
|||||
|
/* Copyright (C) 2005 MySQL AB |
||||
|
|
||||
|
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 |
||||
|
the Free Software Foundation; version 2 of the License. |
||||
|
|
||||
|
This program is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
||||
|
|
||||
|
#ifndef _my_plugin_ftparser_h |
||||
|
#define _my_plugin_ftparser_h |
||||
|
#include "plugin.h" |
||||
|
|
||||
|
/************************************************************************* |
||||
|
API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN) |
||||
|
*/ |
||||
|
|
||||
|
#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0100 |
||||
|
|
||||
|
/* Parsing modes. Set in MYSQL_FTPARSER_PARAM::mode */ |
||||
|
enum enum_ftparser_mode |
||||
|
{ |
||||
|
/* |
||||
|
Fast and simple mode. This mode is used for indexing, and natural |
||||
|
language queries. |
||||
|
|
||||
|
The parser is expected to return only those words that go into the |
||||
|
index. Stopwords or too short/long words should not be returned. The |
||||
|
'boolean_info' argument of mysql_add_word() does not have to be set. |
||||
|
*/ |
||||
|
MYSQL_FTPARSER_SIMPLE_MODE= 0, |
||||
|
|
||||
|
/* |
||||
|
Parse with stopwords mode. This mode is used in boolean searches for |
||||
|
"phrase matching." |
||||
|
|
||||
|
The parser is not allowed to ignore words in this mode. Every word |
||||
|
should be returned, including stopwords and words that are too short |
||||
|
or long. The 'boolean_info' argument of mysql_add_word() does not |
||||
|
have to be set. |
||||
|
*/ |
||||
|
MYSQL_FTPARSER_WITH_STOPWORDS= 1, |
||||
|
|
||||
|
/* |
||||
|
Parse in boolean mode. This mode is used to parse a boolean query string. |
||||
|
|
||||
|
The parser should provide a valid MYSQL_FTPARSER_BOOLEAN_INFO |
||||
|
structure in the 'boolean_info' argument to mysql_add_word(). |
||||
|
Usually that means that the parser should recognize boolean operators |
||||
|
in the parsing stream and set appropriate fields in |
||||
|
MYSQL_FTPARSER_BOOLEAN_INFO structure accordingly. As for |
||||
|
MYSQL_FTPARSER_WITH_STOPWORDS mode, no word should be ignored. |
||||
|
Instead, use FT_TOKEN_STOPWORD for the token type of such a word. |
||||
|
*/ |
||||
|
MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 |
||||
|
}; |
||||
|
|
||||
|
/* |
||||
|
Token types for boolean mode searching (used for the type member of |
||||
|
MYSQL_FTPARSER_BOOLEAN_INFO struct) |
||||
|
|
||||
|
FT_TOKEN_EOF: End of data. |
||||
|
FT_TOKEN_WORD: Regular word. |
||||
|
FT_TOKEN_LEFT_PAREN: Left parenthesis (start of group/sub-expression). |
||||
|
FT_TOKEN_RIGHT_PAREN: Right parenthesis (end of group/sub-expression). |
||||
|
FT_TOKEN_STOPWORD: Stopword. |
||||
|
*/ |
||||
|
|
||||
|
enum enum_ft_token_type |
||||
|
{ |
||||
|
FT_TOKEN_EOF= 0, |
||||
|
FT_TOKEN_WORD= 1, |
||||
|
FT_TOKEN_LEFT_PAREN= 2, |
||||
|
FT_TOKEN_RIGHT_PAREN= 3, |
||||
|
FT_TOKEN_STOPWORD= 4 |
||||
|
}; |
||||
|
|
||||
|
/* |
||||
|
This structure is used in boolean search mode only. It conveys |
||||
|
boolean-mode metadata to the MySQL search engine for every word in |
||||
|
the search query. A valid instance of this structure must be filled |
||||
|
in by the plugin parser and passed as an argument in the call to |
||||
|
mysql_add_word (the callback function in the MYSQL_FTPARSER_PARAM |
||||
|
structure) when a query is parsed in boolean mode. |
||||
|
|
||||
|
type: The token type. Should be one of the enum_ft_token_type values. |
||||
|
|
||||
|
yesno: Whether the word must be present for a match to occur: |
||||
|
>0 Must be present |
||||
|
<0 Must not be present |
||||
|
0 Neither; the word is optional but its presence increases the relevance |
||||
|
With the default settings of the ft_boolean_syntax system variable, |
||||
|
>0 corresponds to the '+' operator, <0 corrresponds to the '-' operator, |
||||
|
and 0 means neither operator was used. |
||||
|
|
||||
|
weight_adjust: A weighting factor that determines how much a match |
||||
|
for the word counts. Positive values increase, negative - decrease the |
||||
|
relative word's importance in the query. |
||||
|
|
||||
|
wasign: The sign of the word's weight in the query. If it's non-negative |
||||
|
the match for the word will increase document relevance, if it's |
||||
|
negative - decrease (the word becomes a "noise word", the less of it the |
||||
|
better). |
||||
|
|
||||
|
trunc: Corresponds to the '*' operator in the default setting of the |
||||
|
ft_boolean_syntax system variable. |
||||
|
*/ |
||||
|
|
||||
|
typedef struct st_mysql_ftparser_boolean_info |
||||
|
{ |
||||
|
enum enum_ft_token_type type; |
||||
|
int yesno; |
||||
|
int weight_adjust; |
||||
|
char wasign; |
||||
|
char trunc; |
||||
|
/* These are parser state and must be removed. */ |
||||
|
char prev; |
||||
|
char *quot; |
||||
|
} MYSQL_FTPARSER_BOOLEAN_INFO; |
||||
|
|
||||
|
/* |
||||
|
The following flag means that buffer with a string (document, word) |
||||
|
may be overwritten by the caller before the end of the parsing (that is |
||||
|
before st_mysql_ftparser::deinit() call). If one needs the string |
||||
|
to survive between two successive calls of the parsing function, she |
||||
|
needs to save a copy of it. The flag may be set by MySQL before calling |
||||
|
st_mysql_ftparser::parse(), or it may be set by a plugin before calling |
||||
|
st_mysql_ftparser_param::mysql_parse() or |
||||
|
st_mysql_ftparser_param::mysql_add_word(). |
||||
|
*/ |
||||
|
#define MYSQL_FTFLAGS_NEED_COPY 1 |
||||
|
|
||||
|
/* |
||||
|
An argument of the full-text parser plugin. This structure is |
||||
|
filled in by MySQL server and passed to the parsing function of the |
||||
|
plugin as an in/out parameter. |
||||
|
|
||||
|
mysql_parse: A pointer to the built-in parser implementation of the |
||||
|
server. It's set by the server and can be used by the parser plugin |
||||
|
to invoke the MySQL default parser. If plugin's role is to extract |
||||
|
textual data from .doc, .pdf or .xml content, it might extract |
||||
|
plaintext from the content, and then pass the text to the default |
||||
|
MySQL parser to be parsed. |
||||
|
|
||||
|
mysql_add_word: A server callback to add a new word. When parsing |
||||
|
a document, the server sets this to point at a function that adds |
||||
|
the word to MySQL full-text index. When parsing a search query, |
||||
|
this function will add the new word to the list of words to search |
||||
|
for. The boolean_info argument can be NULL for all cases except |
||||
|
when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO. |
||||
|
|
||||
|
ftparser_state: A generic pointer. The plugin can set it to point |
||||
|
to information to be used internally for its own purposes. |
||||
|
|
||||
|
mysql_ftparam: This is set by the server. It is used by MySQL functions |
||||
|
called via mysql_parse() and mysql_add_word() callback. The plugin |
||||
|
should not modify it. |
||||
|
|
||||
|
cs: Information about the character set of the document or query string. |
||||
|
|
||||
|
doc: A pointer to the document or query string to be parsed. |
||||
|
|
||||
|
length: Length of the document or query string, in bytes. |
||||
|
|
||||
|
flags: See MYSQL_FTFLAGS_* constants above. |
||||
|
|
||||
|
mode: The parsing mode. With boolean operators, with stopwords, or |
||||
|
nothing. See enum_ftparser_mode above. |
||||
|
*/ |
||||
|
|
||||
|
typedef struct st_mysql_ftparser_param |
||||
|
{ |
||||
|
int (*mysql_parse)(struct st_mysql_ftparser_param *, |
||||
|
char *doc, int doc_len); |
||||
|
int (*mysql_add_word)(struct st_mysql_ftparser_param *, |
||||
|
char *word, int word_len, |
||||
|
MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); |
||||
|
void *ftparser_state; |
||||
|
void *mysql_ftparam; |
||||
|
struct charset_info_st *cs; |
||||
|
char *doc; |
||||
|
int length; |
||||
|
int flags; |
||||
|
enum enum_ftparser_mode mode; |
||||
|
} MYSQL_FTPARSER_PARAM; |
||||
|
|
||||
|
/* |
||||
|
Full-text parser descriptor. |
||||
|
|
||||
|
interface_version is, e.g., MYSQL_FTPARSER_INTERFACE_VERSION. |
||||
|
The parsing, initialization, and deinitialization functions are |
||||
|
invoked per SQL statement for which the parser is used. |
||||
|
*/ |
||||
|
|
||||
|
struct st_mysql_ftparser |
||||
|
{ |
||||
|
int interface_version; |
||||
|
int (*parse)(MYSQL_FTPARSER_PARAM *param); |
||||
|
int (*init)(MYSQL_FTPARSER_PARAM *param); |
||||
|
int (*deinit)(MYSQL_FTPARSER_PARAM *param); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
#endif |
||||
|
|
||||
@ -0,0 +1,32 @@ |
|||||
|
# Copyright (C) 2007 MySQL AB
|
||||
|
#
|
||||
|
# 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
|
||||
|
# the Free Software Foundation; version 2 of the License.
|
||||
|
#
|
||||
|
# This program is distributed in the hope that it will be useful,
|
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
|
# GNU General Public License for more details.
|
||||
|
#
|
||||
|
# You should have received a copy of the GNU General Public License
|
||||
|
# along with this program; if not, write to the Free Software
|
||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
|
||||
|
#Makefile.am example for a plugin
|
||||
|
|
||||
|
pkgplugindir= $(pkglibdir)/plugin |
||||
|
|
||||
|
AM_CPPFLAGS = -I$(top_srcdir)/include |
||||
|
|
||||
|
EXTRA_LTLIBRARIES= adt_null.la |
||||
|
pkgplugin_LTLIBRARIES= @plugin_audit_null_shared_target@ |
||||
|
adt_null_la_LDFLAGS= -module -rpath $(pkgplugindir) |
||||
|
adt_null_la_CPPFLAGS= $(AM_CPPFLAGS) -DMYSQL_DYNAMIC_PLUGIN |
||||
|
adt_null_la_SOURCES= audit_null.c |
||||
|
|
||||
|
EXTRA_LIBRARIES= libadtnull.a |
||||
|
noinst_LIBRARIES= @plugin_audit_null_static_target@ |
||||
|
libadtnull_a_SOURCES= audit_null.c |
||||
|
|
||||
|
EXTRA_DIST= plug.in |
||||
@ -0,0 +1,130 @@ |
|||||
|
/* Copyright (C) 2006-2007 MySQL AB |
||||
|
|
||||
|
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 |
||||
|
the Free Software Foundation; version 2 of the License. |
||||
|
|
||||
|
This program is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
#include <mysql/plugin.h> |
||||
|
#include <mysql/plugin_audit.h> |
||||
|
|
||||
|
#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) |
||||
|
#define __attribute__(A) |
||||
|
#endif |
||||
|
|
||||
|
static volatile int number_of_calls; /* for SHOW STATUS, see below */ |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
Initialize the plugin at server start or plugin installation. |
||||
|
|
||||
|
SYNOPSIS |
||||
|
audit_null_plugin_init() |
||||
|
|
||||
|
DESCRIPTION |
||||
|
Does nothing. |
||||
|
|
||||
|
RETURN VALUE |
||||
|
0 success |
||||
|
1 failure (cannot happen) |
||||
|
*/ |
||||
|
|
||||
|
static int audit_null_plugin_init(void *arg __attribute__((unused))) |
||||
|
{ |
||||
|
number_of_calls= 0; |
||||
|
return(0); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
Terminate the plugin at server shutdown or plugin deinstallation. |
||||
|
|
||||
|
SYNOPSIS |
||||
|
audit_null_plugin_deinit() |
||||
|
Does nothing. |
||||
|
|
||||
|
RETURN VALUE |
||||
|
0 success |
||||
|
1 failure (cannot happen) |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
static int audit_null_plugin_deinit(void *arg __attribute__((unused))) |
||||
|
{ |
||||
|
printf("audit_null was invoked %u times\n", number_of_calls); |
||||
|
return(0); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
Foo |
||||
|
|
||||
|
SYNOPSIS |
||||
|
audit_null_notify() |
||||
|
thd connection context |
||||
|
|
||||
|
DESCRIPTION |
||||
|
*/ |
||||
|
|
||||
|
static void audit_null_notify(MYSQL_THD thd __attribute__((unused)), |
||||
|
const struct mysql_event *event |
||||
|
__attribute__((unused))) |
||||
|
{ |
||||
|
/* prone to races, oh well */ |
||||
|
number_of_calls++; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
Plugin type-specific descriptor |
||||
|
*/ |
||||
|
|
||||
|
static struct st_mysql_audit audit_null_descriptor= |
||||
|
{ |
||||
|
MYSQL_AUDIT_INTERFACE_VERSION, /* interface version */ |
||||
|
NULL, /* release_thd function */ |
||||
|
audit_null_notify, /* notify function */ |
||||
|
{ (unsigned long) -1 } /* class mask */ |
||||
|
}; |
||||
|
|
||||
|
/* |
||||
|
Plugin status variables for SHOW STATUS |
||||
|
*/ |
||||
|
|
||||
|
static struct st_mysql_show_var simple_status[]= |
||||
|
{ |
||||
|
{"audit_null_called", (char *)&number_of_calls, SHOW_INT}, |
||||
|
{0,0,0} |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
Plugin library descriptor |
||||
|
*/ |
||||
|
|
||||
|
mysql_declare_plugin(audit_null) |
||||
|
{ |
||||
|
MYSQL_AUDIT_PLUGIN, /* type */ |
||||
|
&audit_null_descriptor, /* descriptor */ |
||||
|
"NULL_AUDIT", /* name */ |
||||
|
"MySQL AB", /* author */ |
||||
|
"Simple NULL Audit", /* description */ |
||||
|
PLUGIN_LICENSE_GPL, |
||||
|
audit_null_plugin_init, /* init function (when loaded) */ |
||||
|
audit_null_plugin_deinit, /* deinit function (when unloaded) */ |
||||
|
0x0001, /* version */ |
||||
|
simple_status, /* status variables */ |
||||
|
NULL, /* system variables */ |
||||
|
NULL |
||||
|
} |
||||
|
mysql_declare_plugin_end; |
||||
|
|
||||
@ -0,0 +1,4 @@ |
|||||
|
MYSQL_PLUGIN(audit_null, [NULL Audit Plug-in], |
||||
|
[Simple black-hole Audit example plug-in]) |
||||
|
MYSQL_PLUGIN_DYNAMIC(audit_null, [adt_null.la]) |
||||
|
MYSQL_PLUGIN_STATIC(audit_null, [libadtnull.a]) |
||||
@ -0,0 +1,448 @@ |
|||||
|
/* Copyright (C) 2007 MySQL AB
|
||||
|
|
||||
|
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 |
||||
|
the Free Software Foundation; version 2 of the License. |
||||
|
|
||||
|
This program is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
||||
|
|
||||
|
#include "mysql_priv.h"
|
||||
|
#include "sql_audit.h"
|
||||
|
|
||||
|
extern int initialize_audit_plugin(st_plugin_int *plugin); |
||||
|
extern int finalize_audit_plugin(st_plugin_int *plugin); |
||||
|
|
||||
|
#ifndef EMBEDDED_LIBRARY
|
||||
|
|
||||
|
unsigned long mysql_global_audit_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; |
||||
|
|
||||
|
static pthread_mutex_t LOCK_audit_mask; |
||||
|
|
||||
|
static void event_class_dispatch(THD *thd, const struct mysql_event *event); |
||||
|
|
||||
|
|
||||
|
static inline |
||||
|
void set_audit_mask(unsigned long *mask, uint event_class) |
||||
|
{ |
||||
|
mask[0]= 1; |
||||
|
mask[0]<<= event_class; |
||||
|
} |
||||
|
|
||||
|
static inline |
||||
|
void add_audit_mask(unsigned long *mask, const unsigned long *rhs) |
||||
|
{ |
||||
|
mask[0]|= rhs[0]; |
||||
|
} |
||||
|
|
||||
|
static inline |
||||
|
bool check_audit_mask(const unsigned long *lhs, |
||||
|
const unsigned long *rhs) |
||||
|
{ |
||||
|
return !(lhs[0] & rhs[0]); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
typedef void (*audit_handler_t)(THD *thd, uint event_subtype, va_list ap); |
||||
|
|
||||
|
/**
|
||||
|
MYSQL_AUDIT_GENERAL_CLASS handler |
||||
|
|
||||
|
@param[in] thd |
||||
|
@param[in] event_subtype |
||||
|
@param[in] error_code |
||||
|
@param[in] ap |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
static void general_class_handler(THD *thd, uint event_subtype, va_list ap) |
||||
|
{ |
||||
|
mysql_event_general event; |
||||
|
event.event_class= MYSQL_AUDIT_GENERAL_CLASS; |
||||
|
event.general_error_code= va_arg(ap, int); |
||||
|
event.general_thread_id= thd ? thd->thread_id : 0; |
||||
|
event.general_time= va_arg(ap, time_t); |
||||
|
event.general_user= va_arg(ap, const char *); |
||||
|
event.general_user_length= va_arg(ap, unsigned int); |
||||
|
event.general_command= va_arg(ap, const char *); |
||||
|
event.general_command_length= va_arg(ap, unsigned int); |
||||
|
event.general_query= va_arg(ap, const char *); |
||||
|
event.general_query_length= va_arg(ap, unsigned int); |
||||
|
event.general_charset= va_arg(ap, struct charset_info_st *); |
||||
|
event.general_rows= (unsigned long long) va_arg(ap, ha_rows); |
||||
|
event_class_dispatch(thd, (const mysql_event*) &event); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static audit_handler_t audit_handlers[] = |
||||
|
{ |
||||
|
general_class_handler |
||||
|
}; |
||||
|
|
||||
|
static const uint audit_handlers_count= |
||||
|
(sizeof(audit_handlers) / sizeof(audit_handler_t)); |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Acquire and lock any additional audit plugins as required |
||||
|
|
||||
|
@param[in] thd |
||||
|
@param[in] plugin |
||||
|
@param[in] arg |
||||
|
|
||||
|
@retval FALSE Always |
||||
|
*/ |
||||
|
|
||||
|
static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg) |
||||
|
{ |
||||
|
uint event_class= *(uint*) arg; |
||||
|
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; |
||||
|
st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *); |
||||
|
|
||||
|
set_audit_mask(event_class_mask, event_class); |
||||
|
|
||||
|
/* Check if this plugin is interested in the event */ |
||||
|
if (check_audit_mask(data->class_mask, event_class_mask)) |
||||
|
return 0; |
||||
|
|
||||
|
/*
|
||||
|
Check if this plugin may already be registered. This will fail to |
||||
|
acquire a newly installed plugin on a specific corner case where |
||||
|
one or more event classes already in use by the calling thread |
||||
|
are an event class of which the audit plugin has interest. |
||||
|
*/ |
||||
|
if (!check_audit_mask(data->class_mask, thd->audit_class_mask)) |
||||
|
return 0; |
||||
|
|
||||
|
/* Check if we need to initialize the array of acquired plugins */ |
||||
|
if (unlikely(!thd->audit_class_plugins.buffer)) |
||||
|
{ |
||||
|
/* specify some reasonable initialization defaults */ |
||||
|
my_init_dynamic_array(&thd->audit_class_plugins, |
||||
|
sizeof(plugin_ref), 16, 16); |
||||
|
} |
||||
|
|
||||
|
/* lock the plugin and add it to the list */ |
||||
|
plugin= my_plugin_lock(NULL, &plugin); |
||||
|
insert_dynamic(&thd->audit_class_plugins, (uchar*) &plugin); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Notify the audit system of an event |
||||
|
|
||||
|
@param[in] thd |
||||
|
@param[in] event_class |
||||
|
@param[in] event_subtype |
||||
|
@param[in] error_code |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
void mysql_audit_notify(THD *thd, uint event_class, uint event_subtype, ...) |
||||
|
{ |
||||
|
va_list ap; |
||||
|
audit_handler_t *handlers= audit_handlers + event_class; |
||||
|
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; |
||||
|
|
||||
|
DBUG_ASSERT(event_class < audit_handlers_count); |
||||
|
|
||||
|
set_audit_mask(event_class_mask, event_class); |
||||
|
/*
|
||||
|
Check to see if we have acquired the audit plugins for the |
||||
|
required audit event classes. |
||||
|
*/ |
||||
|
if (thd && check_audit_mask(thd->audit_class_mask, event_class_mask)) |
||||
|
{ |
||||
|
plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, &event_class); |
||||
|
add_audit_mask(thd->audit_class_mask, event_class_mask); |
||||
|
} |
||||
|
|
||||
|
va_start(ap, event_subtype); |
||||
|
(*handlers)(thd, event_subtype, ap); |
||||
|
va_end(ap); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Release any resources associated with the current thd. |
||||
|
|
||||
|
@param[in] thd |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
void mysql_audit_release(THD *thd) |
||||
|
{ |
||||
|
plugin_ref *plugins, *plugins_last; |
||||
|
|
||||
|
if (!thd || !(thd->audit_class_plugins.elements)) |
||||
|
return; |
||||
|
|
||||
|
plugins= (plugin_ref*) thd->audit_class_plugins.buffer; |
||||
|
plugins_last= plugins + thd->audit_class_plugins.elements; |
||||
|
for (; plugins < plugins_last; plugins++) |
||||
|
{ |
||||
|
st_mysql_audit *data= plugin_data(*plugins, struct st_mysql_audit *); |
||||
|
|
||||
|
/* Check to see if the plugin has a release method */ |
||||
|
if (!(data->release_thd)) |
||||
|
continue; |
||||
|
|
||||
|
/* Tell the plugin to release its resources */ |
||||
|
data->release_thd(thd); |
||||
|
} |
||||
|
|
||||
|
/* Now we actually unlock the plugins */ |
||||
|
plugin_unlock_list(NULL, (plugin_ref*) thd->audit_class_plugins.buffer, |
||||
|
thd->audit_class_plugins.elements); |
||||
|
|
||||
|
/* Reset the state of thread values */ |
||||
|
reset_dynamic(&thd->audit_class_plugins); |
||||
|
bzero(thd->audit_class_mask, sizeof(thd->audit_class_mask)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Initialize thd variables used by Audit |
||||
|
|
||||
|
@param[in] thd |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
void mysql_audit_init_thd(THD *thd) |
||||
|
{ |
||||
|
bzero(&thd->audit_class_plugins, sizeof(thd->audit_class_plugins)); |
||||
|
bzero(thd->audit_class_mask, sizeof(thd->audit_class_mask)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Free thd variables used by Audit |
||||
|
|
||||
|
@param[in] thd |
||||
|
@param[in] plugin |
||||
|
@param[in] arg |
||||
|
|
||||
|
@retval FALSE Always |
||||
|
*/ |
||||
|
|
||||
|
void mysql_audit_free_thd(THD *thd) |
||||
|
{ |
||||
|
mysql_audit_release(thd); |
||||
|
DBUG_ASSERT(thd->audit_class_plugins.elements == 0); |
||||
|
delete_dynamic(&thd->audit_class_plugins); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Initialize Audit global variables |
||||
|
*/ |
||||
|
|
||||
|
void mysql_audit_initialize() |
||||
|
{ |
||||
|
pthread_mutex_init(&LOCK_audit_mask, MY_MUTEX_INIT_FAST); |
||||
|
bzero(mysql_global_audit_mask, sizeof(mysql_global_audit_mask)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Finalize Audit global variables |
||||
|
*/ |
||||
|
|
||||
|
void mysql_audit_finalize() |
||||
|
{ |
||||
|
pthread_mutex_destroy(&LOCK_audit_mask); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Initialize an Audit plug-in |
||||
|
|
||||
|
@param[in] plugin |
||||
|
|
||||
|
@retval FALSE OK |
||||
|
@retval TRUE There was an error. |
||||
|
*/ |
||||
|
|
||||
|
int initialize_audit_plugin(st_plugin_int *plugin) |
||||
|
{ |
||||
|
st_mysql_audit *data= (st_mysql_audit*) plugin->plugin->info; |
||||
|
|
||||
|
if (!data->class_mask || !data->event_notify || |
||||
|
!data->class_mask[0]) |
||||
|
{ |
||||
|
sql_print_error("Plugin '%s' has invalid data.", |
||||
|
plugin->name.str); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
if (plugin->plugin->init && plugin->plugin->init(NULL)) |
||||
|
{ |
||||
|
sql_print_error("Plugin '%s' init function returned error.", |
||||
|
plugin->name.str); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
/* Make the interface info more easily accessible */ |
||||
|
plugin->data= plugin->plugin->info; |
||||
|
|
||||
|
/* Add the bits the plugin is interested in to the global mask */ |
||||
|
pthread_mutex_lock(&LOCK_audit_mask); |
||||
|
add_audit_mask(mysql_global_audit_mask, data->class_mask); |
||||
|
pthread_mutex_unlock(&LOCK_audit_mask); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Performs a bitwise OR of the installed plugins event class masks |
||||
|
|
||||
|
@param[in] thd |
||||
|
@param[in] plugin |
||||
|
@param[in] arg |
||||
|
|
||||
|
@retval FALSE always |
||||
|
*/ |
||||
|
static my_bool calc_class_mask(THD *thd, plugin_ref plugin, void *arg) |
||||
|
{ |
||||
|
st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *); |
||||
|
if ((data= plugin_data(plugin, struct st_mysql_audit *))) |
||||
|
add_audit_mask((unsigned long *) arg, data->class_mask); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Finalize an Audit plug-in |
||||
|
|
||||
|
@param[in] plugin |
||||
|
|
||||
|
@retval FALSE OK |
||||
|
@retval TRUE There was an error. |
||||
|
*/ |
||||
|
int finalize_audit_plugin(st_plugin_int *plugin) |
||||
|
{ |
||||
|
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; |
||||
|
|
||||
|
if (plugin->plugin->deinit && plugin->plugin->deinit(NULL)) |
||||
|
{ |
||||
|
DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.", |
||||
|
plugin->name.str)); |
||||
|
DBUG_EXECUTE("finalize_audit_plugin", return 1; ); |
||||
|
} |
||||
|
|
||||
|
plugin->data= NULL; |
||||
|
bzero(&event_class_mask, sizeof(event_class_mask)); |
||||
|
|
||||
|
/* Iterate through all the installed plugins to create new mask */ |
||||
|
pthread_mutex_lock(&LOCK_audit_mask); |
||||
|
plugin_foreach(current_thd, calc_class_mask, MYSQL_AUDIT_PLUGIN, |
||||
|
&event_class_mask); |
||||
|
|
||||
|
/* Set the global audit mask */ |
||||
|
bmove(mysql_global_audit_mask, event_class_mask, sizeof(event_class_mask)); |
||||
|
pthread_mutex_unlock(&LOCK_audit_mask); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Dispatches an event by invoking the plugin's event_notify method. |
||||
|
|
||||
|
@param[in] thd |
||||
|
@param[in] plugin |
||||
|
@param[in] arg |
||||
|
|
||||
|
@retval FALSE always |
||||
|
*/ |
||||
|
|
||||
|
static my_bool plugins_dispatch(THD *thd, plugin_ref plugin, void *arg) |
||||
|
{ |
||||
|
const struct mysql_event *event= (const struct mysql_event *) arg; |
||||
|
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; |
||||
|
st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *); |
||||
|
|
||||
|
set_audit_mask(event_class_mask, event->event_class); |
||||
|
|
||||
|
/* Check to see if the plugin is interested in this event */ |
||||
|
if (check_audit_mask(data->class_mask, event_class_mask)) |
||||
|
return 0; |
||||
|
|
||||
|
/* Actually notify the plugin */ |
||||
|
data->event_notify(thd, event); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
Distributes an audit event to plug-ins |
||||
|
|
||||
|
@param[in] thd |
||||
|
@param[in] event |
||||
|
*/ |
||||
|
|
||||
|
static void event_class_dispatch(THD *thd, const struct mysql_event *event) |
||||
|
{ |
||||
|
/*
|
||||
|
Check if we are doing a slow global dispatch. This event occurs when |
||||
|
thd == NULL as it is not associated with any particular thread. |
||||
|
*/ |
||||
|
if (unlikely(!thd)) |
||||
|
{ |
||||
|
plugin_foreach(thd, plugins_dispatch, MYSQL_AUDIT_PLUGIN, (void*) event); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
plugin_ref *plugins, *plugins_last; |
||||
|
|
||||
|
/* Use the cached set of audit plugins */ |
||||
|
plugins= (plugin_ref*) thd->audit_class_plugins.buffer; |
||||
|
plugins_last= plugins + thd->audit_class_plugins.elements; |
||||
|
|
||||
|
for (; plugins < plugins_last; plugins++) |
||||
|
plugins_dispatch(thd, *plugins, (void*) event); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#else /* EMBEDDED_LIBRARY */
|
||||
|
|
||||
|
|
||||
|
void mysql_audit_initialize() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void mysql_audit_finalize() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int initialize_audit_plugin(st_plugin_int *plugin) |
||||
|
{ |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int finalize_audit_plugin(st_plugin_int *plugin) |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void mysql_audit_release(THD *thd) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#endif /* EMBEDDED_LIBRARY */
|
||||
@ -0,0 +1,78 @@ |
|||||
|
#ifndef SQL_AUDIT_INCLUDED |
||||
|
#define SQL_AUDIT_INCLUDED |
||||
|
|
||||
|
/* Copyright (C) 2007 MySQL AB |
||||
|
|
||||
|
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 |
||||
|
the Free Software Foundation; version 2 of the License. |
||||
|
|
||||
|
This program is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with this program; if not, write to the Free Software |
||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
||||
|
|
||||
|
|
||||
|
#include <mysql/plugin_audit.h> |
||||
|
|
||||
|
extern unsigned long mysql_global_audit_mask[]; |
||||
|
|
||||
|
|
||||
|
extern void mysql_audit_initialize(); |
||||
|
extern void mysql_audit_finalize(); |
||||
|
|
||||
|
|
||||
|
extern void mysql_audit_init_thd(THD *thd); |
||||
|
extern void mysql_audit_free_thd(THD *thd); |
||||
|
|
||||
|
|
||||
|
extern void mysql_audit_notify(THD *thd, uint event_class, |
||||
|
uint event_subtype, ...); |
||||
|
extern void mysql_audit_release(THD *thd); |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
Call audit plugins of GENERAL audit class. |
||||
|
event_subtype should be set to one of: |
||||
|
MYSQL_AUDIT_GENERAL_LOG |
||||
|
MYSQL_AUDIT_GENERAL_ERROR |
||||
|
MYSQL_AUDIT_GENERAL_RESULT |
||||
|
|
||||
|
@param[in] thd |
||||
|
@param[in] event_subtype Type of general audit event. |
||||
|
@param[in] error_code Error code |
||||
|
@param[in] time time that event occurred |
||||
|
@param[in] user User name |
||||
|
@param[in] userlen User name length |
||||
|
@param[in] cmd Command name |
||||
|
@param[in] cmdlen Command name length |
||||
|
@param[in] query Query string |
||||
|
@param[in] querylen Query string length |
||||
|
@param[in] clientcs Charset of query string |
||||
|
@param[in] rows Number of affected rows |
||||
|
*/ |
||||
|
|
||||
|
static inline |
||||
|
void mysql_audit_general(THD *thd, uint event_subtype, |
||||
|
int error_code, time_t time, |
||||
|
const char *user, uint userlen, |
||||
|
const char *cmd, uint cmdlen, |
||||
|
const char *query, uint querylen, |
||||
|
CHARSET_INFO *clientcs, |
||||
|
ha_rows rows) |
||||
|
{ |
||||
|
#ifndef EMBEDDED_LIBRARY |
||||
|
if (mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK) |
||||
|
mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, event_subtype, |
||||
|
error_code, time, user, userlen, cmd, cmdlen, |
||||
|
query, querylen, clientcs, rows); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#endif /* SQL_AUDIT_INCLUDED */ |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue