2015-05-04 22:00:24 +02:00
|
|
|
/* Copyright (C) 2013, 2015, Alexey Botchkov and SkySQL Ab
|
2020-04-16 11:12:26 +02:00
|
|
|
Copyright (c) 2019, 2020, MariaDB Corporation.
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
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
|
Update FSF address
This commit is based on the work of Michal Schorm, rebased on the
earliest MariaDB version.
Th command line used to generate this diff was:
find ./ -type f \
-exec sed -i -e 's/Foundation, Inc., 59 Temple Place, Suite 330, Boston, /Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, /g' {} \; \
-exec sed -i -e 's/Foundation, Inc. 59 Temple Place.* Suite 330, Boston, /Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, /g' {} \; \
-exec sed -i -e 's/MA.*.....-1307.*USA/MA 02110-1335 USA/g' {} \; \
-exec sed -i -e 's/Foundation, Inc., 59 Temple/Foundation, Inc., 51 Franklin/g' {} \; \
-exec sed -i -e 's/Place, Suite 330, Boston, MA.*02111-1307.*USA/Street, Fifth Floor, Boston, MA 02110-1335 USA/g' {} \; \
-exec sed -i -e 's/MA.*.....-1307/MA 02110-1335/g' {} \;
2019-05-10 19:49:46 +02:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
#define PLUGIN_VERSION 0x104
|
2022-04-28 07:34:21 +02:00
|
|
|
#define PLUGIN_STR_VERSION "1.4.14"
|
2016-01-12 13:29:02 +01:00
|
|
|
|
|
|
|
#define _my_thread_var loc_thread_var
|
2014-02-24 20:40:16 +01:00
|
|
|
|
2014-10-02 11:57:40 +02:00
|
|
|
#include <my_config.h>
|
2017-10-03 21:42:16 +02:00
|
|
|
#include <assert.h>
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
#ifndef _WIN32
|
2019-07-03 14:41:01 +02:00
|
|
|
#define DO_SYSLOG
|
2014-02-24 20:40:16 +01:00
|
|
|
#include <syslog.h>
|
2019-07-06 13:22:45 +02:00
|
|
|
static const char out_type_desc[]= "Desired output type. Possible values - 'syslog', 'file'"
|
|
|
|
" or 'null' as no output.";
|
2014-02-24 20:40:16 +01:00
|
|
|
#else
|
2019-07-06 13:22:45 +02:00
|
|
|
static const char out_type_desc[]= "Desired output type. Possible values - 'file'"
|
|
|
|
" or 'null' as no output.";
|
2014-02-24 20:40:16 +01:00
|
|
|
#define syslog(PRIORITY, FORMAT, INFO, MESSAGE_LEN, MESSAGE) do {}while(0)
|
|
|
|
static void closelog() {}
|
|
|
|
#define openlog(IDENT, LOG_NOWAIT, LOG_USER) do {}while(0)
|
|
|
|
|
|
|
|
/* priorities */
|
|
|
|
#define LOG_EMERG 0 /* system is unusable */
|
|
|
|
#define LOG_ALERT 1 /* action must be taken immediately */
|
|
|
|
#define LOG_CRIT 2 /* critical conditions */
|
|
|
|
#define LOG_ERR 3 /* error conditions */
|
|
|
|
#define LOG_WARNING 4 /* warning conditions */
|
|
|
|
#define LOG_NOTICE 5 /* normal but significant condition */
|
|
|
|
#define LOG_INFO 6 /* informational */
|
|
|
|
#define LOG_DEBUG 7 /* debug-level messages */
|
|
|
|
|
|
|
|
#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
|
|
|
|
|
|
|
|
/* facility codes */
|
|
|
|
#define LOG_KERN (0<<3) /* kernel messages */
|
|
|
|
#define LOG_USER (1<<3) /* random user-level messages */
|
|
|
|
#define LOG_MAIL (2<<3) /* mail system */
|
|
|
|
#define LOG_DAEMON (3<<3) /* system daemons */
|
|
|
|
#define LOG_AUTH (4<<3) /* security/authorization messages */
|
|
|
|
#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
|
|
|
|
#define LOG_LPR (6<<3) /* line printer subsystem */
|
|
|
|
#define LOG_NEWS (7<<3) /* network news subsystem */
|
|
|
|
#define LOG_UUCP (8<<3) /* UUCP subsystem */
|
|
|
|
#define LOG_CRON (9<<3) /* clock daemon */
|
|
|
|
#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
|
|
|
|
#define LOG_FTP (11<<3) /* ftp daemon */
|
|
|
|
#define LOG_LOCAL0 (16<<3) /* reserved for local use */
|
|
|
|
#define LOG_LOCAL1 (17<<3) /* reserved for local use */
|
|
|
|
#define LOG_LOCAL2 (18<<3) /* reserved for local use */
|
|
|
|
#define LOG_LOCAL3 (19<<3) /* reserved for local use */
|
|
|
|
#define LOG_LOCAL4 (20<<3) /* reserved for local use */
|
|
|
|
#define LOG_LOCAL5 (21<<3) /* reserved for local use */
|
|
|
|
#define LOG_LOCAL6 (22<<3) /* reserved for local use */
|
|
|
|
#define LOG_LOCAL7 (23<<3) /* reserved for local use */
|
|
|
|
|
|
|
|
#endif /*!_WIN32*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Defines that can be used to reshape the pluging:
|
|
|
|
#define MARIADB_ONLY
|
|
|
|
#define USE_MARIA_PLUGIN_INTERFACE
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if !defined(MYSQL_DYNAMIC_PLUGIN) && !defined(MARIADB_ONLY)
|
2017-06-18 05:42:16 +02:00
|
|
|
#include <typelib.h>
|
2014-02-24 20:40:16 +01:00
|
|
|
#define MARIADB_ONLY
|
|
|
|
#endif /*MYSQL_PLUGIN_DYNAMIC*/
|
|
|
|
|
|
|
|
#ifndef MARIADB_ONLY
|
|
|
|
#define MYSQL_SERVICE_LOGGER_INCLUDED
|
|
|
|
#endif /*MARIADB_ONLY*/
|
|
|
|
|
2017-06-18 05:42:16 +02:00
|
|
|
#include <my_global.h>
|
2014-02-24 20:40:16 +01:00
|
|
|
#include <my_base.h>
|
|
|
|
#include <typelib.h>
|
|
|
|
#include <mysql/plugin.h>
|
|
|
|
#include <mysql/plugin_audit.h>
|
2017-06-18 05:42:16 +02:00
|
|
|
#include <string.h>
|
2019-07-06 13:22:45 +02:00
|
|
|
#include "../../mysys/mysys_priv.h"
|
2014-03-23 15:44:48 +01:00
|
|
|
#ifndef RTLD_DEFAULT
|
|
|
|
#define RTLD_DEFAULT NULL
|
|
|
|
#endif
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
#ifndef MARIADB_ONLY
|
|
|
|
#undef MYSQL_SERVICE_LOGGER_INCLUDED
|
|
|
|
#undef MYSQL_DYNAMIC_PLUGIN
|
|
|
|
#define FLOGGER_NO_PSI
|
2014-05-07 10:21:41 +02:00
|
|
|
|
|
|
|
/* How to access the pthread_mutex in mysql_mutex_t */
|
2016-02-08 21:34:41 +01:00
|
|
|
#ifdef SAFE_MUTEX
|
|
|
|
#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
|
|
|
|
#else
|
2014-05-07 10:21:41 +02:00
|
|
|
#define mysql_mutex_real_mutex(A) &(A)->m_mutex
|
2016-02-08 21:34:41 +01:00
|
|
|
#endif
|
2014-05-07 10:21:41 +02:00
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
#define flogger_mutex_init(A,B,C) do{}while(0)
|
|
|
|
#define flogger_mutex_destroy(A) do{}while(0)
|
|
|
|
#define flogger_mutex_lock(A) do{}while(0)
|
|
|
|
#define flogger_mutex_unlock(A) do{}while(0)
|
2014-02-24 20:40:16 +01:00
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
static char **int_mysql_data_home;
|
|
|
|
static char *default_home= (char *)".";
|
|
|
|
#define mysql_data_home (*int_mysql_data_home)
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
#define FLOGGER_SKIP_INCLUDES
|
|
|
|
#define my_open(A, B, C) loc_open(A, B)
|
2016-01-15 06:50:27 +01:00
|
|
|
#define my_close(A, B) loc_close(A)
|
2016-01-12 13:29:02 +01:00
|
|
|
#define my_rename(A, B, C) loc_rename(A, B)
|
|
|
|
#define my_tell(A, B) loc_tell(A)
|
2016-01-15 06:50:27 +01:00
|
|
|
#define my_write(A, B, C, D) loc_write(A, B, C)
|
2020-01-29 13:50:26 +01:00
|
|
|
#define my_malloc(A, B, C) malloc(B)
|
2016-01-12 13:29:02 +01:00
|
|
|
#define my_free(A) free(A)
|
2016-01-15 06:50:27 +01:00
|
|
|
#ifdef my_errno
|
|
|
|
#undef my_errno
|
|
|
|
#endif
|
|
|
|
static int loc_file_errno;
|
|
|
|
#define my_errno loc_file_errno
|
2016-01-12 13:29:02 +01:00
|
|
|
#ifdef my_vsnprintf
|
|
|
|
#undef my_vsnprintf
|
|
|
|
#endif
|
|
|
|
#define my_vsnprintf vsnprintf
|
2016-01-15 06:50:27 +01:00
|
|
|
#define logger_open loc_logger_open
|
|
|
|
#define logger_close loc_logger_close
|
|
|
|
#define logger_write loc_logger_write
|
|
|
|
#define logger_rotate loc_logger_rotate
|
|
|
|
#define logger_init_mutexts loc_logger_init_mutexts
|
2021-02-25 10:55:08 +01:00
|
|
|
#define logger_time_to_rotate loc_logger_time_to_rotate
|
2016-01-15 06:50:27 +01:00
|
|
|
|
|
|
|
|
|
|
|
static size_t loc_write(File Filedes, const uchar *Buffer, size_t Count)
|
|
|
|
{
|
|
|
|
size_t writtenbytes;
|
|
|
|
#ifdef _WIN32
|
2017-10-03 21:42:16 +02:00
|
|
|
writtenbytes= (size_t)_write(Filedes, Buffer, (unsigned int)Count);
|
2016-01-15 06:50:27 +01:00
|
|
|
#else
|
|
|
|
writtenbytes= write(Filedes, Buffer, Count);
|
|
|
|
#endif
|
|
|
|
return writtenbytes;
|
|
|
|
}
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
|
2016-01-15 06:50:27 +01:00
|
|
|
static File loc_open(const char *FileName, int Flags)
|
2016-01-12 13:29:02 +01:00
|
|
|
/* Path-name of file */
|
|
|
|
/* Read | write .. */
|
|
|
|
/* Special flags */
|
|
|
|
{
|
|
|
|
File fd;
|
2017-10-03 21:42:16 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
HANDLE h;
|
|
|
|
/*
|
|
|
|
We could just use _open() here. but prefer to open in unix-similar way
|
|
|
|
just like my_open() does it on Windows.
|
2017-10-04 07:07:41 +02:00
|
|
|
This gives atomic multiprocess-safe appends, and possibility to rename
|
2017-10-03 21:42:16 +02:00
|
|
|
or even delete file while it is open, and CRT lacks this features.
|
|
|
|
*/
|
|
|
|
assert(Flags == (O_APPEND | O_CREAT | O_WRONLY));
|
|
|
|
h= CreateFile(FileName, FILE_APPEND_DATA,
|
|
|
|
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL,
|
|
|
|
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
fd= -1;
|
|
|
|
my_osmaperr(GetLastError());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fd= _open_osfhandle((intptr)h, O_WRONLY|O_BINARY);
|
|
|
|
}
|
2016-01-12 13:29:02 +01:00
|
|
|
#else
|
2017-10-03 21:42:16 +02:00
|
|
|
fd= open(FileName, Flags, my_umask);
|
2016-01-12 13:29:02 +01:00
|
|
|
#endif
|
2016-01-15 06:50:27 +01:00
|
|
|
my_errno= errno;
|
2016-01-12 13:29:02 +01:00
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2016-01-15 06:50:27 +01:00
|
|
|
|
|
|
|
static int loc_close(File fd)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
#ifndef _WIN32
|
|
|
|
do
|
|
|
|
{
|
|
|
|
err= close(fd);
|
|
|
|
} while (err == -1 && errno == EINTR);
|
|
|
|
#else
|
2017-10-03 21:42:16 +02:00
|
|
|
err= close(fd);
|
2016-01-15 06:50:27 +01:00
|
|
|
#endif
|
|
|
|
my_errno=errno;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static int loc_rename(const char *from, const char *to)
|
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
#if defined(__WIN__)
|
|
|
|
if (!MoveFileEx(from, to, MOVEFILE_COPY_ALLOWED |
|
|
|
|
MOVEFILE_REPLACE_EXISTING))
|
|
|
|
{
|
|
|
|
my_osmaperr(GetLastError());
|
|
|
|
#elif defined(HAVE_RENAME)
|
|
|
|
if (rename(from,to))
|
|
|
|
{
|
|
|
|
#else
|
|
|
|
if (link(from, to) || unlink(from))
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
my_errno=errno;
|
|
|
|
error = -1;
|
|
|
|
}
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static my_off_t loc_tell(File fd)
|
|
|
|
{
|
2017-10-03 21:42:16 +02:00
|
|
|
os_off_t pos= IF_WIN(_telli64(fd),lseek(fd, 0, SEEK_CUR));
|
2016-01-12 13:29:02 +01:00
|
|
|
if (pos == (os_off_t) -1)
|
|
|
|
{
|
|
|
|
my_errno= errno;
|
|
|
|
}
|
|
|
|
return (my_off_t) pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_PSI_INTERFACE
|
|
|
|
#undef HAVE_PSI_INTERFACE
|
|
|
|
#include <mysql/service_logger.h>
|
|
|
|
#include "../../mysys/file_logger.c"
|
|
|
|
#define HAVE_PSI_INTERFACE
|
|
|
|
#else
|
|
|
|
#include <mysql/service_logger.h>
|
2014-02-24 20:40:16 +01:00
|
|
|
#include "../../mysys/file_logger.c"
|
2016-01-12 13:29:02 +01:00
|
|
|
#endif
|
2014-02-24 20:40:16 +01:00
|
|
|
#endif /*!MARIADB_ONLY*/
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
#undef flogger_mutex_init
|
|
|
|
#undef flogger_mutex_destroy
|
|
|
|
#undef flogger_mutex_lock
|
|
|
|
#undef flogger_mutex_unlock
|
|
|
|
|
|
|
|
#define flogger_mutex_init(A,B,C) pthread_mutex_init(mysql_mutex_real_mutex(B), C)
|
|
|
|
#define flogger_mutex_destroy(A) pthread_mutex_destroy(mysql_mutex_real_mutex(A))
|
|
|
|
#define flogger_mutex_lock(A) pthread_mutex_lock(mysql_mutex_real_mutex(A))
|
|
|
|
#define flogger_mutex_unlock(A) pthread_mutex_unlock(mysql_mutex_real_mutex(A))
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
#ifndef DBUG_OFF
|
|
|
|
#define PLUGIN_DEBUG_VERSION "-debug"
|
|
|
|
#else
|
|
|
|
#define PLUGIN_DEBUG_VERSION ""
|
|
|
|
#endif /*DBUG_OFF*/
|
|
|
|
/*
|
|
|
|
Disable __attribute__() on non-gcc compilers.
|
|
|
|
*/
|
|
|
|
#if !defined(__attribute__) && !defined(__GNUC__)
|
|
|
|
#define __attribute__(A)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#define localtime_r(a, b) localtime_s(b, a)
|
|
|
|
#endif /*WIN32*/
|
|
|
|
|
|
|
|
|
MDEV-22214 mariadbd.exe calls function mysqld.exe, and crashes
Stop linking plugins to the server executable on Windows.
Instead, extract whole server functionality into a large DLL, called
server.dll. Link both plugins, and small server "stub" exe to it.
This eliminates plugin dependency on the name of the server executable.
It also reduces the size of the packages (since tiny mysqld.exe
and mariadbd.exe are now both linked to one big DLL)
Also, simplify the functionality of exporing all symbols from selected
static libraries. Rely on WINDOWS_EXPORT_ALL_SYMBOLS, rather than old
self-backed solution.
fix compile error
replace GetProcAddress(GetModuleHandle(NULL), "variable_name")
for server exported data with actual variable names.
Runtime loading was never required,was error prone
, since symbols could be missing at runtime, and now it actually failed,
because we do not export symbols from executable anymore, but from a shared
library
This did require a MYSQL_PLUGIN_IMPORT decoration for the plugin,
but made the code more straightforward, and avoids missing symbols at
runtime (as mentioned before).
The audit plugin is still doing some dynamic loading, as it aims to work
cross-version. Now it won't work cross-version on Windows, as it already
uses some symbols that are *not* dynamically loaded, e.g fn_format
and those symbols now exported from server.dll , when earlier they were
exported by mysqld.exe
Windows, fixes for storage engine plugin loading
after various rebranding stuff
Create server.dll containing functionality of the whole server
make mariadbd.exe/mysqld.exe a stub that is only calling mysqld_main()
fix build
2020-04-10 14:09:18 +02:00
|
|
|
extern MYSQL_PLUGIN_IMPORT char server_version[];
|
2014-02-24 20:40:16 +01:00
|
|
|
static const char *serv_ver= NULL;
|
|
|
|
static int started_mysql= 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
static int mysql_57_started= 0;
|
|
|
|
static int debug_server_started= 0;
|
|
|
|
static int use_event_data_for_disconnect= 0;
|
2015-02-08 19:38:19 +01:00
|
|
|
static int started_mariadb= 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
static int maria_55_started= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
static int maria_above_5= 0;
|
|
|
|
static char *incl_users, *excl_users,
|
|
|
|
*file_path, *syslog_info;
|
|
|
|
static char path_buffer[FN_REFLEN];
|
|
|
|
static unsigned int mode, mode_readonly= 0;
|
|
|
|
static ulong output_type;
|
|
|
|
static ulong syslog_facility, syslog_priority;
|
|
|
|
|
|
|
|
static ulonglong events; /* mask for events to log */
|
|
|
|
static unsigned long long file_rotate_size;
|
|
|
|
static unsigned int rotations;
|
|
|
|
static my_bool rotate= TRUE;
|
|
|
|
static char logging;
|
2019-06-14 23:02:55 +02:00
|
|
|
static volatile int internal_stop_logging= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
static char incl_user_buffer[1024];
|
|
|
|
static char excl_user_buffer[1024];
|
2015-03-31 10:10:43 +02:00
|
|
|
static unsigned int query_log_limit= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
static char servhost[256];
|
2018-01-12 19:25:02 +01:00
|
|
|
static uint servhost_len;
|
2014-02-24 20:40:16 +01:00
|
|
|
static char *syslog_ident;
|
|
|
|
static char syslog_ident_buffer[128]= "mysql-server_auditing";
|
2016-01-12 13:29:02 +01:00
|
|
|
|
|
|
|
struct connection_info
|
|
|
|
{
|
|
|
|
int header;
|
|
|
|
unsigned long thread_id;
|
|
|
|
unsigned long long query_id;
|
|
|
|
char db[256];
|
|
|
|
int db_length;
|
|
|
|
char user[64];
|
|
|
|
int user_length;
|
|
|
|
char host[64];
|
|
|
|
int host_length;
|
|
|
|
char ip[64];
|
|
|
|
int ip_length;
|
|
|
|
const char *query;
|
|
|
|
int query_length;
|
|
|
|
char query_buffer[1024];
|
|
|
|
time_t query_time;
|
|
|
|
int log_always;
|
2020-10-22 12:00:17 +02:00
|
|
|
char proxy[64];
|
|
|
|
int proxy_length;
|
|
|
|
char proxy_host[64];
|
|
|
|
int proxy_host_length;
|
2016-01-12 13:29:02 +01:00
|
|
|
};
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
#define DEFAULT_FILENAME_LEN 16
|
|
|
|
static char default_file_name[DEFAULT_FILENAME_LEN+1]= "server_audit.log";
|
|
|
|
|
|
|
|
static void update_file_path(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
2014-03-17 16:09:53 +01:00
|
|
|
static void update_file_rotate_size(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
|
|
|
static void update_file_rotations(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
2014-02-24 20:40:16 +01:00
|
|
|
static void update_incl_users(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
2019-04-28 22:11:48 +02:00
|
|
|
static int check_incl_users(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save,
|
|
|
|
struct st_mysql_value *value);
|
|
|
|
static int check_excl_users(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save,
|
|
|
|
struct st_mysql_value *value);
|
2014-02-24 20:40:16 +01:00
|
|
|
static void update_excl_users(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
|
|
|
static void update_output_type(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
|
|
|
static void update_syslog_facility(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
|
|
|
static void update_syslog_priority(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
|
|
|
static void update_mode(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
|
|
|
static void update_logging(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
|
|
|
static void update_syslog_ident(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
|
|
|
static void rotate_log(MYSQL_THD thd, struct st_mysql_sys_var *var,
|
|
|
|
void *var_ptr, const void *save);
|
|
|
|
|
|
|
|
static MYSQL_SYSVAR_STR(incl_users, incl_users, PLUGIN_VAR_RQCMDARG,
|
|
|
|
"Comma separated list of users to monitor.",
|
2019-04-28 22:11:48 +02:00
|
|
|
check_incl_users, update_incl_users, NULL);
|
2014-02-24 20:40:16 +01:00
|
|
|
static MYSQL_SYSVAR_STR(excl_users, excl_users, PLUGIN_VAR_RQCMDARG,
|
|
|
|
"Comma separated list of users to exclude from auditing.",
|
2019-04-28 22:11:48 +02:00
|
|
|
check_excl_users, update_excl_users, NULL);
|
2014-02-24 20:40:16 +01:00
|
|
|
/* bits in the event filter. */
|
|
|
|
#define EVENT_CONNECT 1
|
2015-02-08 19:38:19 +01:00
|
|
|
#define EVENT_QUERY_ALL 2
|
2018-05-10 17:00:54 +02:00
|
|
|
#define EVENT_QUERY 122
|
2014-02-24 20:40:16 +01:00
|
|
|
#define EVENT_TABLE 4
|
2015-02-08 19:38:19 +01:00
|
|
|
#define EVENT_QUERY_DDL 8
|
|
|
|
#define EVENT_QUERY_DML 16
|
2015-03-31 10:10:43 +02:00
|
|
|
#define EVENT_QUERY_DCL 32
|
2018-05-10 17:00:54 +02:00
|
|
|
#define EVENT_QUERY_DML_NO_SELECT 64
|
2015-02-08 19:38:19 +01:00
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static const char *event_names[]=
|
|
|
|
{
|
2015-03-31 10:10:43 +02:00
|
|
|
"CONNECT", "QUERY", "TABLE", "QUERY_DDL", "QUERY_DML", "QUERY_DCL",
|
2018-05-10 17:00:54 +02:00
|
|
|
"QUERY_DML_NO_SELECT", NULL
|
2014-02-24 20:40:16 +01:00
|
|
|
};
|
|
|
|
static TYPELIB events_typelib=
|
|
|
|
{
|
|
|
|
array_elements(event_names) - 1, "", event_names, NULL
|
|
|
|
};
|
|
|
|
static MYSQL_SYSVAR_SET(events, events, PLUGIN_VAR_RQCMDARG,
|
2016-01-12 13:29:02 +01:00
|
|
|
"Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE,"
|
2018-05-10 17:00:54 +02:00
|
|
|
" QUERY_DDL, QUERY_DML, QUERY_DML_NO_SELECT, QUERY_DCL.",
|
2014-02-24 20:40:16 +01:00
|
|
|
NULL, NULL, 0, &events_typelib);
|
2019-07-03 14:41:01 +02:00
|
|
|
#ifdef DO_SYSLOG
|
2014-02-24 20:40:16 +01:00
|
|
|
#define OUTPUT_SYSLOG 0
|
|
|
|
#define OUTPUT_FILE 1
|
2019-07-03 14:41:01 +02:00
|
|
|
#else
|
|
|
|
#define OUTPUT_SYSLOG 0xFFFF
|
|
|
|
#define OUTPUT_FILE 0
|
|
|
|
#endif /*DO_SYSLOG*/
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
#define OUTPUT_NO 0xFFFF
|
2019-07-03 14:41:01 +02:00
|
|
|
static const char *output_type_names[]= {
|
|
|
|
#ifdef DO_SYSLOG
|
|
|
|
"syslog",
|
|
|
|
#endif
|
|
|
|
"file", 0 };
|
2014-02-24 20:40:16 +01:00
|
|
|
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,
|
2019-07-06 13:22:45 +02:00
|
|
|
out_type_desc,
|
2019-07-05 13:22:04 +02:00
|
|
|
0, update_output_type, OUTPUT_FILE,
|
2014-02-24 20:40:16 +01:00
|
|
|
&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);
|
|
|
|
static MYSQL_SYSVAR_ULONGLONG(file_rotate_size, file_rotate_size,
|
|
|
|
PLUGIN_VAR_RQCMDARG, "Maximum size of the log to start the rotation.",
|
2014-03-17 16:09:53 +01:00
|
|
|
NULL, update_file_rotate_size,
|
2014-02-24 20:40:16 +01:00
|
|
|
1000000, 100, ((long long) 0x7FFFFFFFFFFFFFFFLL), 1);
|
|
|
|
static MYSQL_SYSVAR_UINT(file_rotations, rotations,
|
|
|
|
PLUGIN_VAR_RQCMDARG, "Number of rotations before log is removed.",
|
2014-03-17 16:09:53 +01:00
|
|
|
NULL, update_file_rotations, 9, 0, 999, 1);
|
2014-02-24 20:40:16 +01:00
|
|
|
static MYSQL_SYSVAR_BOOL(file_rotate_now, rotate, PLUGIN_VAR_OPCMDARG,
|
|
|
|
"Force log rotation now.", NULL, rotate_log, FALSE);
|
|
|
|
static MYSQL_SYSVAR_BOOL(logging, logging,
|
|
|
|
PLUGIN_VAR_OPCMDARG, "Turn on/off the logging.", NULL,
|
|
|
|
update_logging, 0);
|
|
|
|
static MYSQL_SYSVAR_UINT(mode, mode,
|
|
|
|
PLUGIN_VAR_OPCMDARG, "Auditing mode.", NULL, update_mode, 0, 0, 1, 1);
|
|
|
|
static MYSQL_SYSVAR_STR(syslog_ident, syslog_ident, PLUGIN_VAR_RQCMDARG,
|
|
|
|
"The SYSLOG identifier - the beginning of each SYSLOG record.",
|
|
|
|
NULL, update_syslog_ident, syslog_ident_buffer);
|
|
|
|
static MYSQL_SYSVAR_STR(syslog_info, syslog_info,
|
|
|
|
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
|
|
|
|
"The <info> string to be added to the SYSLOG record.", NULL, NULL, "");
|
2015-03-31 10:10:43 +02:00
|
|
|
static MYSQL_SYSVAR_UINT(query_log_limit, query_log_limit,
|
|
|
|
PLUGIN_VAR_OPCMDARG, "Limit on the length of the query string in a record.",
|
|
|
|
NULL, NULL, 1024, 0, 0x7FFFFFFF, 1);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
char locinfo_ini_value[sizeof(struct connection_info)+4];
|
|
|
|
|
|
|
|
static MYSQL_THDVAR_STR(loc_info,
|
2016-09-26 17:48:08 +02:00
|
|
|
PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_MEMALLOC,
|
|
|
|
"Internal info", NULL, NULL, locinfo_ini_value);
|
2016-01-12 13:29:02 +01:00
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static const char *syslog_facility_names[]=
|
|
|
|
{
|
|
|
|
"LOG_USER", "LOG_MAIL", "LOG_DAEMON", "LOG_AUTH",
|
|
|
|
"LOG_SYSLOG", "LOG_LPR", "LOG_NEWS", "LOG_UUCP",
|
2014-03-18 09:26:50 +01:00
|
|
|
"LOG_CRON",
|
|
|
|
#ifdef LOG_AUTHPRIV
|
|
|
|
"LOG_AUTHPRIV",
|
|
|
|
#endif
|
|
|
|
#ifdef LOG_FTP
|
|
|
|
"LOG_FTP",
|
|
|
|
#endif
|
2014-02-24 20:40:16 +01:00
|
|
|
"LOG_LOCAL0", "LOG_LOCAL1", "LOG_LOCAL2", "LOG_LOCAL3",
|
|
|
|
"LOG_LOCAL4", "LOG_LOCAL5", "LOG_LOCAL6", "LOG_LOCAL7",
|
|
|
|
0
|
|
|
|
};
|
2018-02-20 22:17:36 +01:00
|
|
|
#ifndef _WIN32
|
2014-02-24 20:40:16 +01:00
|
|
|
static unsigned int syslog_facility_codes[]=
|
|
|
|
{
|
|
|
|
LOG_USER, LOG_MAIL, LOG_DAEMON, LOG_AUTH,
|
|
|
|
LOG_SYSLOG, LOG_LPR, LOG_NEWS, LOG_UUCP,
|
2014-03-18 09:26:50 +01:00
|
|
|
LOG_CRON,
|
|
|
|
#ifdef LOG_AUTHPRIV
|
|
|
|
LOG_AUTHPRIV,
|
|
|
|
#endif
|
|
|
|
#ifdef LOG_FTP
|
|
|
|
LOG_FTP,
|
|
|
|
#endif
|
2014-02-24 20:40:16 +01:00
|
|
|
LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3,
|
|
|
|
LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7,
|
|
|
|
};
|
2018-02-20 22:17:36 +01:00
|
|
|
#endif
|
2014-02-24 20:40:16 +01:00
|
|
|
static TYPELIB syslog_facility_typelib=
|
|
|
|
{
|
|
|
|
array_elements(syslog_facility_names) - 1, "syslog_facility_typelib",
|
|
|
|
syslog_facility_names, NULL
|
|
|
|
};
|
|
|
|
static MYSQL_SYSVAR_ENUM(syslog_facility, syslog_facility, PLUGIN_VAR_RQCMDARG,
|
|
|
|
"The 'facility' parameter of the SYSLOG record."
|
|
|
|
" The default is LOG_USER.", 0, update_syslog_facility, 0/*LOG_USER*/,
|
|
|
|
&syslog_facility_typelib);
|
|
|
|
|
|
|
|
static const char *syslog_priority_names[]=
|
|
|
|
{
|
|
|
|
"LOG_EMERG", "LOG_ALERT", "LOG_CRIT", "LOG_ERR",
|
|
|
|
"LOG_WARNING", "LOG_NOTICE", "LOG_INFO", "LOG_DEBUG",
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2018-02-20 22:17:36 +01:00
|
|
|
#ifndef _WIN32
|
2014-02-24 20:40:16 +01:00
|
|
|
static unsigned int syslog_priority_codes[]=
|
|
|
|
{
|
|
|
|
LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
|
|
|
|
LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG,
|
|
|
|
};
|
2018-02-20 22:17:36 +01:00
|
|
|
#endif
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
static TYPELIB syslog_priority_typelib=
|
|
|
|
{
|
|
|
|
array_elements(syslog_priority_names) - 1, "syslog_priority_typelib",
|
|
|
|
syslog_priority_names, NULL
|
|
|
|
};
|
|
|
|
static MYSQL_SYSVAR_ENUM(syslog_priority, syslog_priority, PLUGIN_VAR_RQCMDARG,
|
|
|
|
"The 'priority' parameter of the SYSLOG record."
|
|
|
|
" The default is LOG_INFO.", 0, update_syslog_priority, 6/*LOG_INFO*/,
|
|
|
|
&syslog_priority_typelib);
|
|
|
|
|
|
|
|
|
|
|
|
static struct st_mysql_sys_var* vars[] = {
|
|
|
|
MYSQL_SYSVAR(incl_users),
|
|
|
|
MYSQL_SYSVAR(excl_users),
|
|
|
|
MYSQL_SYSVAR(events),
|
|
|
|
MYSQL_SYSVAR(output_type),
|
|
|
|
MYSQL_SYSVAR(file_path),
|
|
|
|
MYSQL_SYSVAR(file_rotate_size),
|
|
|
|
MYSQL_SYSVAR(file_rotations),
|
|
|
|
MYSQL_SYSVAR(file_rotate_now),
|
|
|
|
MYSQL_SYSVAR(logging),
|
|
|
|
MYSQL_SYSVAR(mode),
|
|
|
|
MYSQL_SYSVAR(syslog_info),
|
|
|
|
MYSQL_SYSVAR(syslog_ident),
|
|
|
|
MYSQL_SYSVAR(syslog_facility),
|
|
|
|
MYSQL_SYSVAR(syslog_priority),
|
2015-03-31 10:10:43 +02:00
|
|
|
MYSQL_SYSVAR(query_log_limit),
|
2016-01-12 13:29:02 +01:00
|
|
|
MYSQL_SYSVAR(loc_info),
|
2014-02-24 20:40:16 +01:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Status variables for SHOW STATUS */
|
|
|
|
static int is_active= 0;
|
|
|
|
static long log_write_failures= 0;
|
|
|
|
static char current_log_buf[FN_REFLEN]= "";
|
|
|
|
static char last_error_buf[512]= "";
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
extern void *mysql_v4_descriptor;
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static struct st_mysql_show_var audit_status[]=
|
|
|
|
{
|
|
|
|
{"server_audit_active", (char *)&is_active, SHOW_BOOL},
|
|
|
|
{"server_audit_current_log", current_log_buf, SHOW_CHAR},
|
|
|
|
{"server_audit_writes_failed", (char *)&log_write_failures, SHOW_LONG},
|
|
|
|
{"server_audit_last_error", last_error_buf, SHOW_CHAR},
|
|
|
|
{0,0,0}
|
|
|
|
};
|
|
|
|
|
2021-02-25 10:55:08 +01:00
|
|
|
#ifdef HAVE_PSI_INTERFACE
|
2014-02-24 20:40:16 +01:00
|
|
|
static PSI_mutex_key key_LOCK_operations;
|
|
|
|
static PSI_mutex_info mutex_key_list[]=
|
2016-02-12 09:04:11 +01:00
|
|
|
{
|
|
|
|
{ &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations",
|
2021-02-25 10:55:08 +01:00
|
|
|
PSI_FLAG_GLOBAL}
|
2016-02-12 09:04:11 +01:00
|
|
|
};
|
2021-02-25 10:55:08 +01:00
|
|
|
#endif /*HAVE_PSI_INTERFACE*/
|
|
|
|
static mysql_prlock_t lock_operations;
|
2019-06-14 23:02:55 +02:00
|
|
|
static mysql_mutex_t lock_atomic;
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
/* The Percona server and partly MySQL don't support */
|
|
|
|
/* launching client errors in the 'update_variable' methods. */
|
|
|
|
/* So the client errors just disabled for them. */
|
|
|
|
/* The possible solution is to implement the 'check_variable'*/
|
|
|
|
/* methods there properly, but at the moment i'm not sure it */
|
|
|
|
/* worths doing. */
|
|
|
|
#define CLIENT_ERROR if (!started_mysql) my_printf_error
|
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
#define ADD_ATOMIC(x, a) \
|
|
|
|
do { \
|
|
|
|
flogger_mutex_lock(&lock_atomic); \
|
|
|
|
x+= a; \
|
|
|
|
flogger_mutex_unlock(&lock_atomic); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static uchar *getkey_user(const char *entry, size_t *length,
|
|
|
|
my_bool nu __attribute__((unused)) )
|
|
|
|
{
|
|
|
|
const char *e= entry;
|
|
|
|
while (*e && *e != ' ' && *e != ',')
|
|
|
|
++e;
|
|
|
|
*length= e - entry;
|
|
|
|
return (uchar *) entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static void blank_user(char *user)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
for (; *user && *user != ','; user++)
|
|
|
|
*user= ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void remove_user(char *user)
|
|
|
|
{
|
|
|
|
char *start_user= user;
|
|
|
|
while (*user != ',')
|
|
|
|
{
|
|
|
|
if (*user == 0)
|
|
|
|
{
|
|
|
|
*start_user= 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
user++;
|
|
|
|
}
|
|
|
|
user++;
|
|
|
|
while (*user == ' ')
|
|
|
|
user++;
|
|
|
|
|
|
|
|
do {
|
|
|
|
*(start_user++)= *user;
|
|
|
|
} while (*(user++));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void remove_blanks(char *user)
|
|
|
|
{
|
|
|
|
char *user_orig= user;
|
|
|
|
char *user_to= user;
|
|
|
|
char *start_tok;
|
|
|
|
int blank_name;
|
|
|
|
|
|
|
|
while (*user != 0)
|
|
|
|
{
|
|
|
|
start_tok= user;
|
|
|
|
blank_name= 1;
|
|
|
|
while (*user !=0 && *user != ',')
|
|
|
|
{
|
|
|
|
if (*user != ' ')
|
|
|
|
blank_name= 0;
|
|
|
|
user++;
|
|
|
|
}
|
|
|
|
if (!blank_name)
|
|
|
|
{
|
|
|
|
while (start_tok <= user)
|
|
|
|
*(user_to++)= *(start_tok++);
|
|
|
|
}
|
|
|
|
if (*user == ',')
|
|
|
|
user++;
|
|
|
|
}
|
|
|
|
if (user_to > user_orig && user_to[-1] == ',')
|
|
|
|
user_to--;
|
|
|
|
*user_to= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
struct user_name
|
|
|
|
{
|
2018-01-12 19:25:02 +01:00
|
|
|
size_t name_len;
|
2016-01-12 13:29:02 +01:00
|
|
|
char *name;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct user_coll
|
|
|
|
{
|
|
|
|
int n_users;
|
|
|
|
struct user_name *users;
|
|
|
|
int n_alloced;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void coll_init(struct user_coll *c)
|
|
|
|
{
|
|
|
|
c->n_users= 0;
|
|
|
|
c->users= 0;
|
|
|
|
c->n_alloced= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void coll_free(struct user_coll *c)
|
|
|
|
{
|
|
|
|
if (c->users)
|
|
|
|
{
|
|
|
|
free(c->users);
|
|
|
|
coll_init(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int cmp_users(const void *ia, const void *ib)
|
|
|
|
{
|
|
|
|
const struct user_name *a= (const struct user_name *) ia;
|
|
|
|
const struct user_name *b= (const struct user_name *) ib;
|
2018-01-12 19:25:02 +01:00
|
|
|
int dl= (int)(a->name_len - b->name_len);
|
2016-01-12 13:29:02 +01:00
|
|
|
if (dl != 0)
|
|
|
|
return dl;
|
|
|
|
|
|
|
|
return strncmp(a->name, b->name, a->name_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-12 19:25:02 +01:00
|
|
|
static char *coll_search(struct user_coll *c, const char *n, size_t len)
|
2016-01-12 13:29:02 +01:00
|
|
|
{
|
|
|
|
struct user_name un;
|
|
|
|
struct user_name *found;
|
2020-11-02 13:19:21 +01:00
|
|
|
if (!c->n_users)
|
|
|
|
return 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
un.name_len= len;
|
|
|
|
un.name= (char *) n;
|
|
|
|
found= (struct user_name*) bsearch(&un, c->users, c->n_users,
|
|
|
|
sizeof(c->users[0]), cmp_users);
|
|
|
|
return found ? found->name : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-12 19:25:02 +01:00
|
|
|
static int coll_insert(struct user_coll *c, char *n, size_t len)
|
2016-01-12 13:29:02 +01:00
|
|
|
{
|
|
|
|
if (c->n_users >= c->n_alloced)
|
|
|
|
{
|
|
|
|
c->n_alloced+= 128;
|
|
|
|
if (c->users == NULL)
|
|
|
|
c->users= malloc(c->n_alloced * sizeof(c->users[0]));
|
|
|
|
else
|
|
|
|
c->users= realloc(c->users, c->n_alloced * sizeof(c->users[0]));
|
|
|
|
|
|
|
|
if (c->users == NULL)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
c->users[c->n_users].name= n;
|
|
|
|
c->users[c->n_users].name_len= len;
|
|
|
|
c->n_users++;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void coll_sort(struct user_coll *c)
|
|
|
|
{
|
2020-11-02 13:19:21 +01:00
|
|
|
if (c->n_users)
|
|
|
|
qsort(c->users, c->n_users, sizeof(c->users[0]), cmp_users);
|
2016-01-12 13:29:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int user_coll_fill(struct user_coll *c, char *users,
|
|
|
|
struct user_coll *cmp_c, int take_over_cmp)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
char *orig_users= users;
|
2016-01-12 13:29:02 +01:00
|
|
|
char *cmp_user= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
size_t cmp_length;
|
2016-01-12 13:29:02 +01:00
|
|
|
int refill_cmp_coll= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
c->n_users= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
while (*users)
|
|
|
|
{
|
|
|
|
while (*users == ' ')
|
|
|
|
users++;
|
|
|
|
if (!*users)
|
|
|
|
return 0;
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
(void) getkey_user(users, &cmp_length, FALSE);
|
|
|
|
if (cmp_c)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
2016-01-12 13:29:02 +01:00
|
|
|
cmp_user= coll_search(cmp_c, users, cmp_length);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if (cmp_user && take_over_cmp)
|
|
|
|
{
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, 1);
|
2020-03-16 16:53:10 +01:00
|
|
|
CLIENT_ERROR(1, "User '%.*b' was removed from the"
|
2014-02-24 20:40:16 +01:00
|
|
|
" server_audit_excl_users.",
|
2018-05-29 23:54:25 +02:00
|
|
|
MYF(ME_WARNING), (int) cmp_length, users);
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, -1);
|
2014-02-24 20:40:16 +01:00
|
|
|
blank_user(cmp_user);
|
2016-01-12 13:29:02 +01:00
|
|
|
refill_cmp_coll= 1;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
else if (cmp_user)
|
|
|
|
{
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, 1);
|
2020-03-16 16:53:10 +01:00
|
|
|
CLIENT_ERROR(1, "User '%.*b' is in the server_audit_incl_users, "
|
2018-05-29 23:54:25 +02:00
|
|
|
"so wasn't added.", MYF(ME_WARNING), (int) cmp_length, users);
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, -1);
|
2014-02-24 20:40:16 +01:00
|
|
|
remove_user(users);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2016-01-12 13:29:02 +01:00
|
|
|
if (coll_insert(c, users, cmp_length))
|
2014-02-24 20:40:16 +01:00
|
|
|
return 1;
|
|
|
|
while (*users && *users != ',')
|
|
|
|
users++;
|
|
|
|
if (!*users)
|
|
|
|
break;
|
|
|
|
users++;
|
|
|
|
}
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
if (refill_cmp_coll)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
remove_blanks(excl_users);
|
2016-01-12 13:29:02 +01:00
|
|
|
return user_coll_fill(cmp_c, excl_users, 0, 0);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (users > orig_users && users[-1] == ',')
|
|
|
|
users[-1]= 0;
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
coll_sort(c);
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
enum sa_keywords
|
|
|
|
{
|
|
|
|
SQLCOM_NOTHING=0,
|
|
|
|
SQLCOM_DDL,
|
|
|
|
SQLCOM_DML,
|
|
|
|
SQLCOM_GRANT,
|
|
|
|
SQLCOM_CREATE_USER,
|
2021-02-26 10:26:00 +01:00
|
|
|
SQLCOM_ALTER_USER,
|
2015-02-08 19:38:19 +01:00
|
|
|
SQLCOM_CHANGE_MASTER,
|
|
|
|
SQLCOM_CREATE_SERVER,
|
|
|
|
SQLCOM_SET_OPTION,
|
|
|
|
SQLCOM_ALTER_SERVER,
|
|
|
|
SQLCOM_TRUNCATE,
|
|
|
|
SQLCOM_QUERY_ADMIN,
|
|
|
|
SQLCOM_DCL,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct sa_keyword
|
|
|
|
{
|
|
|
|
int length;
|
|
|
|
const char *wd;
|
|
|
|
struct sa_keyword *next;
|
|
|
|
enum sa_keywords type;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct sa_keyword xml_word= {3, "XML", 0, SQLCOM_NOTHING};
|
|
|
|
struct sa_keyword user_word= {4, "USER", 0, SQLCOM_NOTHING};
|
|
|
|
struct sa_keyword data_word= {4, "DATA", 0, SQLCOM_NOTHING};
|
|
|
|
struct sa_keyword server_word= {6, "SERVER", 0, SQLCOM_NOTHING};
|
|
|
|
struct sa_keyword master_word= {6, "MASTER", 0, SQLCOM_NOTHING};
|
|
|
|
struct sa_keyword password_word= {8, "PASSWORD", 0, SQLCOM_NOTHING};
|
|
|
|
struct sa_keyword function_word= {8, "FUNCTION", 0, SQLCOM_NOTHING};
|
|
|
|
struct sa_keyword statement_word= {9, "STATEMENT", 0, SQLCOM_NOTHING};
|
|
|
|
struct sa_keyword procedure_word= {9, "PROCEDURE", 0, SQLCOM_NOTHING};
|
|
|
|
|
|
|
|
|
|
|
|
struct sa_keyword keywords_to_skip[]=
|
|
|
|
{
|
|
|
|
{3, "SET", &statement_word, SQLCOM_QUERY_ADMIN},
|
|
|
|
{0, NULL, 0, SQLCOM_DDL}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct sa_keyword not_ddl_keywords[]=
|
|
|
|
{
|
|
|
|
{4, "DROP", &user_word, SQLCOM_DCL},
|
|
|
|
{6, "CREATE", &user_word, SQLCOM_DCL},
|
|
|
|
{6, "RENAME", &user_word, SQLCOM_DCL},
|
|
|
|
{0, NULL, 0, SQLCOM_DDL}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct sa_keyword ddl_keywords[]=
|
|
|
|
{
|
|
|
|
{4, "DROP", 0, SQLCOM_DDL},
|
|
|
|
{5, "ALTER", 0, SQLCOM_DDL},
|
|
|
|
{6, "CREATE", 0, SQLCOM_DDL},
|
|
|
|
{6, "RENAME", 0, SQLCOM_DDL},
|
|
|
|
{8, "TRUNCATE", 0, SQLCOM_DDL},
|
|
|
|
{0, NULL, 0, SQLCOM_DDL}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct sa_keyword dml_keywords[]=
|
|
|
|
{
|
|
|
|
{2, "DO", 0, SQLCOM_DML},
|
|
|
|
{4, "CALL", 0, SQLCOM_DML},
|
|
|
|
{4, "LOAD", &data_word, SQLCOM_DML},
|
|
|
|
{4, "LOAD", &xml_word, SQLCOM_DML},
|
|
|
|
{6, "DELETE", 0, SQLCOM_DML},
|
|
|
|
{6, "INSERT", 0, SQLCOM_DML},
|
|
|
|
{6, "SELECT", 0, SQLCOM_DML},
|
|
|
|
{6, "UPDATE", 0, SQLCOM_DML},
|
|
|
|
{7, "HANDLER", 0, SQLCOM_DML},
|
|
|
|
{7, "REPLACE", 0, SQLCOM_DML},
|
|
|
|
{0, NULL, 0, SQLCOM_DML}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-05-10 17:00:54 +02:00
|
|
|
struct sa_keyword dml_no_select_keywords[]=
|
|
|
|
{
|
|
|
|
{2, "DO", 0, SQLCOM_DML},
|
|
|
|
{4, "CALL", 0, SQLCOM_DML},
|
|
|
|
{4, "LOAD", &data_word, SQLCOM_DML},
|
|
|
|
{4, "LOAD", &xml_word, SQLCOM_DML},
|
|
|
|
{6, "DELETE", 0, SQLCOM_DML},
|
|
|
|
{6, "INSERT", 0, SQLCOM_DML},
|
|
|
|
{6, "UPDATE", 0, SQLCOM_DML},
|
|
|
|
{7, "HANDLER", 0, SQLCOM_DML},
|
|
|
|
{7, "REPLACE", 0, SQLCOM_DML},
|
|
|
|
{0, NULL, 0, SQLCOM_DML}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-03-31 10:10:43 +02:00
|
|
|
struct sa_keyword dcl_keywords[]=
|
|
|
|
{
|
|
|
|
{6, "CREATE", &user_word, SQLCOM_DCL},
|
|
|
|
{4, "DROP", &user_word, SQLCOM_DCL},
|
|
|
|
{6, "RENAME", &user_word, SQLCOM_DCL},
|
|
|
|
{5, "GRANT", 0, SQLCOM_DCL},
|
|
|
|
{6, "REVOKE", 0, SQLCOM_DCL},
|
|
|
|
{3, "SET", &password_word, SQLCOM_DCL},
|
|
|
|
{0, NULL, 0, SQLCOM_DDL}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
struct sa_keyword passwd_keywords[]=
|
|
|
|
{
|
|
|
|
{3, "SET", &password_word, SQLCOM_SET_OPTION},
|
|
|
|
{5, "ALTER", &server_word, SQLCOM_ALTER_SERVER},
|
2021-02-26 10:26:00 +01:00
|
|
|
{5, "ALTER", &user_word, SQLCOM_ALTER_USER},
|
2015-02-08 19:38:19 +01:00
|
|
|
{5, "GRANT", 0, SQLCOM_GRANT},
|
|
|
|
{6, "CREATE", &user_word, SQLCOM_CREATE_USER},
|
|
|
|
{6, "CREATE", &server_word, SQLCOM_CREATE_SERVER},
|
|
|
|
{6, "CHANGE", &master_word, SQLCOM_CHANGE_MASTER},
|
|
|
|
{0, NULL, 0, SQLCOM_NOTHING}
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_KEYWORD 9
|
|
|
|
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static void error_header()
|
|
|
|
{
|
|
|
|
struct tm tm_time;
|
|
|
|
time_t curtime;
|
|
|
|
|
|
|
|
(void) time(&curtime);
|
|
|
|
(void) localtime_r(&curtime, &tm_time);
|
|
|
|
|
|
|
|
(void) fprintf(stderr,"%02d%02d%02d %2d:%02d:%02d server_audit: ",
|
|
|
|
tm_time.tm_year % 100, tm_time.tm_mon + 1,
|
|
|
|
tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static LOGGER_HANDLE *logfile;
|
2016-01-12 13:29:02 +01:00
|
|
|
static struct user_coll incl_user_coll, excl_user_coll;
|
2014-02-24 20:40:16 +01:00
|
|
|
static unsigned long long query_counter= 1;
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static struct connection_info *get_loc_info(MYSQL_THD thd)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
2022-04-28 07:34:21 +02:00
|
|
|
/*
|
|
|
|
This is the original code and supposed to be returned
|
|
|
|
bach to this as the MENT-1438 is finally understood/resolved.
|
2016-01-12 13:29:02 +01:00
|
|
|
return (struct connection_info *) THDVAR(thd, loc_info);
|
2022-04-28 07:34:21 +02:00
|
|
|
*/
|
|
|
|
struct connection_info *ci= (struct connection_info *) THDVAR(thd, loc_info);
|
|
|
|
if ((size_t) ci->user_length > sizeof(ci->user))
|
|
|
|
{
|
|
|
|
ci->user_length= 0;
|
|
|
|
ci->host_length= 0;
|
|
|
|
ci->ip_length= 0;
|
|
|
|
}
|
|
|
|
return ci;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static int ci_needs_setup(const struct connection_info *ci)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
2016-01-12 13:29:02 +01:00
|
|
|
return ci->header != 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void get_str_n(char *dest, int *dest_len, size_t dest_size,
|
|
|
|
const char *src, size_t src_len)
|
|
|
|
{
|
|
|
|
if (src_len >= dest_size)
|
|
|
|
src_len= dest_size - 1;
|
|
|
|
|
2020-11-02 13:19:21 +01:00
|
|
|
if (src_len)
|
|
|
|
memcpy(dest, src, src_len);
|
2014-02-24 20:40:16 +01:00
|
|
|
dest[src_len]= 0;
|
2018-01-12 19:25:02 +01:00
|
|
|
*dest_len= (int)src_len;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int get_user_host(const char *uh_line, unsigned int uh_len,
|
|
|
|
char *buffer, size_t buf_len,
|
|
|
|
size_t *user_len, size_t *host_len, size_t *ip_len)
|
|
|
|
{
|
|
|
|
const char *buf_end= buffer + buf_len - 1;
|
|
|
|
const char *buf_start;
|
|
|
|
const char *uh_end= uh_line + uh_len;
|
|
|
|
|
|
|
|
while (uh_line < uh_end && *uh_line != '[')
|
|
|
|
++uh_line;
|
|
|
|
|
|
|
|
if (uh_line == uh_end)
|
|
|
|
return 1;
|
|
|
|
++uh_line;
|
|
|
|
|
|
|
|
buf_start= buffer;
|
|
|
|
while (uh_line < uh_end && *uh_line != ']')
|
|
|
|
{
|
|
|
|
if (buffer == buf_end)
|
|
|
|
return 1;
|
|
|
|
*(buffer++)= *(uh_line++);
|
|
|
|
}
|
|
|
|
if (uh_line == uh_end)
|
|
|
|
return 1;
|
|
|
|
*user_len= buffer - buf_start;
|
|
|
|
*(buffer++)= 0;
|
|
|
|
|
|
|
|
while (uh_line < uh_end && *uh_line != '@')
|
|
|
|
++uh_line;
|
|
|
|
if (uh_line == uh_end || *(++uh_line) == 0)
|
|
|
|
return 1;
|
|
|
|
++uh_line;
|
|
|
|
|
|
|
|
buf_start= buffer;
|
|
|
|
while (uh_line < uh_end && *uh_line != ' ' && *uh_line != '[')
|
|
|
|
{
|
|
|
|
if (buffer == buf_end)
|
|
|
|
break;
|
|
|
|
*(buffer++)= *(uh_line++);
|
|
|
|
}
|
|
|
|
*host_len= buffer - buf_start;
|
|
|
|
*(buffer++)= 0;
|
|
|
|
|
|
|
|
while (uh_line < uh_end && *uh_line != '[')
|
|
|
|
++uh_line;
|
|
|
|
|
|
|
|
buf_start= buffer;
|
|
|
|
if (*uh_line == '[')
|
|
|
|
{
|
|
|
|
++uh_line;
|
|
|
|
while (uh_line < uh_end && *uh_line != ']')
|
|
|
|
*(buffer++)= *(uh_line++);
|
|
|
|
}
|
|
|
|
*ip_len= buffer - buf_start;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(__WIN__) && !defined(S_ISDIR)
|
|
|
|
#define S_ISDIR(x) ((x) & _S_IFDIR)
|
|
|
|
#endif /*__WIN__ && !S_ISDIR*/
|
|
|
|
|
|
|
|
static int start_logging()
|
|
|
|
{
|
|
|
|
last_error_buf[0]= 0;
|
|
|
|
log_write_failures= 0;
|
|
|
|
if (output_type == OUTPUT_FILE)
|
|
|
|
{
|
|
|
|
char alt_path_buffer[FN_REFLEN+1+DEFAULT_FILENAME_LEN];
|
2017-10-03 21:42:16 +02:00
|
|
|
struct stat *f_stat= (struct stat *)alt_path_buffer;
|
2014-02-24 20:40:16 +01:00
|
|
|
const char *alt_fname= file_path;
|
|
|
|
|
|
|
|
while (*alt_fname == ' ')
|
|
|
|
alt_fname++;
|
|
|
|
|
|
|
|
if (*alt_fname == 0)
|
|
|
|
{
|
|
|
|
/* Empty string means the default file name. */
|
|
|
|
alt_fname= default_file_name;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* See if the directory exists with the name of file_path. */
|
|
|
|
/* Log file name should be [file_path]/server_audit.log then. */
|
2017-10-03 21:42:16 +02:00
|
|
|
if (stat(file_path, (struct stat *)alt_path_buffer) == 0 &&
|
2014-02-24 20:40:16 +01:00
|
|
|
S_ISDIR(f_stat->st_mode))
|
|
|
|
{
|
|
|
|
size_t p_len= strlen(file_path);
|
|
|
|
memcpy(alt_path_buffer, file_path, p_len);
|
|
|
|
if (alt_path_buffer[p_len-1] != FN_LIBCHAR)
|
|
|
|
{
|
|
|
|
alt_path_buffer[p_len]= FN_LIBCHAR;
|
|
|
|
p_len++;
|
|
|
|
}
|
|
|
|
memcpy(alt_path_buffer+p_len, default_file_name, DEFAULT_FILENAME_LEN);
|
|
|
|
alt_path_buffer[p_len+DEFAULT_FILENAME_LEN]= 0;
|
|
|
|
alt_fname= alt_path_buffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
logfile= logger_open(alt_fname, file_rotate_size, rotations);
|
|
|
|
|
|
|
|
if (logfile == NULL)
|
|
|
|
{
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "Could not create file '%s'.\n",
|
|
|
|
alt_fname);
|
|
|
|
logging= 0;
|
|
|
|
my_snprintf(last_error_buf, sizeof(last_error_buf),
|
|
|
|
"Could not create file '%s'.", alt_fname);
|
|
|
|
is_active= 0;
|
|
|
|
CLIENT_ERROR(1, "SERVER AUDIT plugin can't create file '%s'.",
|
2018-05-29 23:54:25 +02:00
|
|
|
MYF(ME_WARNING), alt_fname);
|
2014-02-24 20:40:16 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "logging started to the file %s.\n", alt_fname);
|
2019-03-21 09:29:59 +01:00
|
|
|
strncpy(current_log_buf, alt_fname, sizeof(current_log_buf)-1);
|
2017-05-17 15:16:24 +02:00
|
|
|
current_log_buf[sizeof(current_log_buf)-1]= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
else if (output_type == OUTPUT_SYSLOG)
|
|
|
|
{
|
|
|
|
openlog(syslog_ident, LOG_NOWAIT, syslog_facility_codes[syslog_facility]);
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "logging started to the syslog.\n");
|
2019-03-21 09:29:59 +01:00
|
|
|
strncpy(current_log_buf, "[SYSLOG]", sizeof(current_log_buf)-1);
|
|
|
|
compile_time_assert(sizeof current_log_buf > sizeof "[SYSLOG]");
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
is_active= 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stop_logging()
|
|
|
|
{
|
|
|
|
last_error_buf[0]= 0;
|
|
|
|
if (output_type == OUTPUT_FILE && logfile)
|
|
|
|
{
|
|
|
|
logger_close(logfile);
|
|
|
|
logfile= NULL;
|
|
|
|
}
|
|
|
|
else if (output_type == OUTPUT_SYSLOG)
|
|
|
|
{
|
|
|
|
closelog();
|
|
|
|
}
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "logging was stopped.\n");
|
|
|
|
is_active= 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
|
|
|
|
static void setup_connection_simple(struct connection_info *ci)
|
|
|
|
{
|
|
|
|
ci->db_length= 0;
|
|
|
|
ci->user_length= 0;
|
|
|
|
ci->host_length= 0;
|
|
|
|
ci->ip_length= 0;
|
|
|
|
ci->query_length= 0;
|
|
|
|
ci->header= 0;
|
2020-10-22 12:00:17 +02:00
|
|
|
ci->proxy_length= 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-22 12:00:17 +02:00
|
|
|
#define MAX_HOSTNAME 61
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static void setup_connection_connect(struct connection_info *cn,
|
|
|
|
const struct mysql_event_connection *event)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
cn->query_id= 0;
|
2017-09-19 11:08:24 +02:00
|
|
|
cn->query_length= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
cn->log_always= 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
cn->thread_id= event->thread_id;
|
2014-02-24 20:40:16 +01:00
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
|
2018-01-07 17:03:44 +01:00
|
|
|
event->database.str, event->database.length);
|
2014-02-24 20:40:16 +01:00
|
|
|
get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
|
|
|
|
event->user, event->user_length);
|
|
|
|
get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
|
|
|
|
event->host, event->host_length);
|
|
|
|
get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
|
|
|
|
event->ip, event->ip_length);
|
2016-01-12 13:29:02 +01:00
|
|
|
cn->header= 0;
|
2020-10-22 12:00:17 +02:00
|
|
|
if (event->proxy_user && event->proxy_user[0])
|
|
|
|
{
|
|
|
|
const char *priv_host= event->proxy_user +
|
|
|
|
sizeof(char[MAX_HOSTNAME+USERNAME_LENGTH+5]);
|
|
|
|
size_t priv_host_length;
|
|
|
|
|
|
|
|
if (mysql_57_started)
|
|
|
|
{
|
|
|
|
priv_host+= sizeof(size_t);
|
|
|
|
priv_host_length= *(size_t *) (priv_host + MAX_HOSTNAME);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
priv_host_length= strlen(priv_host);
|
|
|
|
|
|
|
|
|
|
|
|
get_str_n(cn->proxy, &cn->proxy_length, sizeof(cn->proxy),
|
|
|
|
event->priv_user, event->priv_user_length);
|
|
|
|
get_str_n(cn->proxy_host, &cn->proxy_host_length,
|
|
|
|
sizeof(cn->proxy_host),
|
|
|
|
priv_host, priv_host_length);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cn->proxy_length= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define SAFE_STRLEN(s) (s ? strlen(s) : 0)
|
2019-07-06 13:22:45 +02:00
|
|
|
#define SAFE_STRLEN_UI(s) ((unsigned int) (s ? strlen(s) : 0))
|
2015-03-19 16:46:08 +01:00
|
|
|
static char empty_str[1]= { 0 };
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
static int is_space(char c)
|
|
|
|
{
|
|
|
|
return c == ' ' || c == '\r' || c == '\n' || c == '\t';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define SKIP_SPACES(str) \
|
|
|
|
do { \
|
|
|
|
while (is_space(*str)) \
|
|
|
|
++str; \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
|
2017-11-03 14:05:41 +01:00
|
|
|
#define ESC_MAP_SIZE 0x60
|
|
|
|
static const char esc_map[ESC_MAP_SIZE]=
|
|
|
|
{
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, '\'', 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0
|
|
|
|
};
|
|
|
|
|
|
|
|
static char escaped_char(char c)
|
|
|
|
{
|
|
|
|
return ((unsigned char ) c) >= ESC_MAP_SIZE ? 0 : esc_map[(unsigned char) c];
|
|
|
|
}
|
2015-02-08 19:38:19 +01:00
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static void setup_connection_initdb(struct connection_info *cn,
|
|
|
|
const struct mysql_event_general *event)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
size_t user_len, host_len, ip_len;
|
|
|
|
char uh_buffer[512];
|
|
|
|
|
|
|
|
cn->thread_id= event->general_thread_id;
|
|
|
|
cn->query_id= 0;
|
2017-09-19 11:08:24 +02:00
|
|
|
cn->query_length= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
cn->log_always= 0;
|
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
|
|
|
|
event->general_query, event->general_query_length);
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
if (get_user_host(event->general_user, event->general_user_length,
|
|
|
|
uh_buffer, sizeof(uh_buffer),
|
|
|
|
&user_len, &host_len, &ip_len))
|
|
|
|
{
|
|
|
|
/* The user@host line is incorrect. */
|
|
|
|
cn->user_length= 0;
|
|
|
|
cn->host_length= 0;
|
|
|
|
cn->ip_length= 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-26 20:06:12 +02:00
|
|
|
get_str_n(cn->user, &cn->user_length, sizeof(cn->user),
|
2016-01-12 13:29:02 +01:00
|
|
|
uh_buffer, user_len);
|
|
|
|
get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
|
|
|
|
uh_buffer+user_len+1, host_len);
|
|
|
|
get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
|
|
|
|
uh_buffer+user_len+1+host_len+1, ip_len);
|
|
|
|
}
|
|
|
|
cn->header= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static void setup_connection_table(struct connection_info *cn,
|
|
|
|
const struct mysql_event_table *event)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
cn->thread_id= event->thread_id;
|
|
|
|
cn->query_id= query_counter++;
|
|
|
|
cn->log_always= 0;
|
2017-09-19 11:08:24 +02:00
|
|
|
cn->query_length= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
|
2018-01-07 17:03:44 +01:00
|
|
|
event->database.str, event->database.length);
|
2014-02-24 20:40:16 +01:00
|
|
|
get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
|
|
|
|
event->user, SAFE_STRLEN(event->user));
|
|
|
|
get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
|
|
|
|
event->host, SAFE_STRLEN(event->host));
|
|
|
|
get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
|
|
|
|
event->ip, SAFE_STRLEN(event->ip));
|
2016-01-12 13:29:02 +01:00
|
|
|
cn->header= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static void setup_connection_query(struct connection_info *cn,
|
|
|
|
const struct mysql_event_general *event)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
size_t user_len, host_len, ip_len;
|
|
|
|
char uh_buffer[512];
|
|
|
|
|
|
|
|
cn->thread_id= event->general_thread_id;
|
|
|
|
cn->query_id= query_counter++;
|
|
|
|
cn->log_always= 0;
|
2017-09-19 11:08:24 +02:00
|
|
|
cn->query_length= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db), "", 0);
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
if (get_user_host(event->general_user, event->general_user_length,
|
|
|
|
uh_buffer, sizeof(uh_buffer),
|
|
|
|
&user_len, &host_len, &ip_len))
|
|
|
|
{
|
|
|
|
/* The user@host line is incorrect. */
|
|
|
|
cn->user_length= 0;
|
|
|
|
cn->host_length= 0;
|
|
|
|
cn->ip_length= 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-26 20:06:12 +02:00
|
|
|
get_str_n(cn->user, &cn->user_length, sizeof(cn->user),
|
2016-01-12 13:29:02 +01:00
|
|
|
uh_buffer, user_len);
|
|
|
|
get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
|
|
|
|
uh_buffer+user_len+1, host_len);
|
|
|
|
get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
|
|
|
|
uh_buffer+user_len+1+host_len+1, ip_len);
|
|
|
|
}
|
|
|
|
cn->header= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void change_connection(struct connection_info *cn,
|
|
|
|
const struct mysql_event_connection *event)
|
|
|
|
{
|
|
|
|
get_str_n(cn->user, &cn->user_length, sizeof(cn->user),
|
|
|
|
event->user, event->user_length);
|
|
|
|
get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
|
|
|
|
event->ip, event->ip_length);
|
|
|
|
}
|
|
|
|
|
2021-02-25 10:55:08 +01:00
|
|
|
/*
|
|
|
|
Write to the log
|
|
|
|
|
|
|
|
@param take_lock If set, take a read lock (or write lock on rotate).
|
|
|
|
If not set, the caller has a already taken a write lock
|
|
|
|
*/
|
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
static int write_log(const char *message, size_t len, int take_lock)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
2019-06-14 23:02:55 +02:00
|
|
|
int result= 0;
|
|
|
|
if (take_lock)
|
2021-02-25 10:55:08 +01:00
|
|
|
{
|
|
|
|
/* Start by taking a read lock */
|
|
|
|
mysql_prlock_rdlock(&lock_operations);
|
|
|
|
}
|
2019-06-14 23:02:55 +02:00
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
if (output_type == OUTPUT_FILE)
|
|
|
|
{
|
2021-02-25 10:55:08 +01:00
|
|
|
if (logfile)
|
|
|
|
{
|
|
|
|
my_bool allow_rotate= !take_lock; /* Allow rotate if caller write lock */
|
|
|
|
if (take_lock && logger_time_to_rotate(logfile))
|
|
|
|
{
|
|
|
|
/* We have to rotate the log, change above read lock to write lock */
|
|
|
|
mysql_prlock_unlock(&lock_operations);
|
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
|
|
|
allow_rotate= 1;
|
|
|
|
}
|
|
|
|
if (!(is_active= (logger_write_r(logfile, allow_rotate, message, len) ==
|
|
|
|
(int) len)))
|
|
|
|
{
|
|
|
|
++log_write_failures;
|
|
|
|
result= 1;
|
|
|
|
}
|
|
|
|
}
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
else if (output_type == OUTPUT_SYSLOG)
|
|
|
|
{
|
|
|
|
syslog(syslog_facility_codes[syslog_facility] |
|
|
|
|
syslog_priority_codes[syslog_priority],
|
2019-06-14 23:02:55 +02:00
|
|
|
"%s %.*s", syslog_info, (int) len, message);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
2019-06-14 23:02:55 +02:00
|
|
|
if (take_lock)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2019-06-14 23:02:55 +02:00
|
|
|
return result;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static size_t log_header(char *message, size_t message_len,
|
|
|
|
time_t *ts,
|
2019-07-06 13:22:45 +02:00
|
|
|
const char *serverhost, size_t serverhost_len,
|
2014-02-24 20:40:16 +01:00
|
|
|
const char *username, unsigned int username_len,
|
|
|
|
const char *host, unsigned int host_len,
|
|
|
|
const char *userip, unsigned int userip_len,
|
|
|
|
unsigned int connection_id, long long query_id,
|
|
|
|
const char *operation)
|
|
|
|
{
|
|
|
|
struct tm tm_time;
|
|
|
|
|
|
|
|
if (host_len == 0 && userip_len != 0)
|
|
|
|
{
|
|
|
|
host_len= userip_len;
|
|
|
|
host= userip;
|
|
|
|
}
|
|
|
|
|
2022-04-28 07:34:21 +02:00
|
|
|
/*
|
|
|
|
That was added to find the possible cause of the MENT-1438.
|
|
|
|
Supposed to be removed after that.
|
|
|
|
*/
|
|
|
|
if (username_len > 1024)
|
|
|
|
{
|
|
|
|
username= "unknown_user";
|
|
|
|
username_len= (unsigned int) strlen(username);
|
|
|
|
}
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
if (output_type == OUTPUT_SYSLOG)
|
|
|
|
return my_snprintf(message, message_len,
|
|
|
|
"%.*s,%.*s,%.*s,%d,%lld,%s",
|
2019-07-06 13:22:45 +02:00
|
|
|
(unsigned int) serverhost_len, serverhost,
|
2014-02-24 20:40:16 +01:00
|
|
|
username_len, username,
|
|
|
|
host_len, host,
|
|
|
|
connection_id, query_id, operation);
|
|
|
|
|
|
|
|
(void) localtime_r(ts, &tm_time);
|
|
|
|
return my_snprintf(message, message_len,
|
|
|
|
"%04d%02d%02d %02d:%02d:%02d,%.*s,%.*s,%.*s,%d,%lld,%s",
|
|
|
|
tm_time.tm_year+1900, tm_time.tm_mon+1, tm_time.tm_mday,
|
|
|
|
tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec,
|
|
|
|
serverhost_len, serverhost,
|
|
|
|
username_len, username,
|
|
|
|
host_len, host,
|
|
|
|
connection_id, query_id, operation);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-22 12:00:17 +02:00
|
|
|
static int log_proxy(const struct connection_info *cn,
|
|
|
|
const struct mysql_event_connection *event)
|
|
|
|
|
|
|
|
{
|
|
|
|
time_t ctime;
|
|
|
|
size_t csize;
|
|
|
|
char message[1024];
|
|
|
|
|
|
|
|
(void) time(&ctime);
|
|
|
|
csize= log_header(message, sizeof(message)-1, &ctime,
|
|
|
|
servhost, servhost_len,
|
|
|
|
cn->user, cn->user_length,
|
|
|
|
cn->host, cn->host_length,
|
|
|
|
cn->ip, cn->ip_length,
|
|
|
|
event->thread_id, 0, "PROXY_CONNECT");
|
|
|
|
csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
|
|
|
|
",%.*s,`%.*s`@`%.*s`,%d", cn->db_length, cn->db,
|
|
|
|
cn->proxy_length, cn->proxy,
|
|
|
|
cn->proxy_host_length, cn->proxy_host,
|
|
|
|
event->status);
|
|
|
|
message[csize]= '\n';
|
|
|
|
return write_log(message, csize + 1, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static int log_connection(const struct connection_info *cn,
|
|
|
|
const struct mysql_event_connection *event,
|
|
|
|
const char *type)
|
|
|
|
{
|
|
|
|
time_t ctime;
|
|
|
|
size_t csize;
|
|
|
|
char message[1024];
|
|
|
|
|
|
|
|
(void) time(&ctime);
|
|
|
|
csize= log_header(message, sizeof(message)-1, &ctime,
|
|
|
|
servhost, servhost_len,
|
|
|
|
cn->user, cn->user_length,
|
|
|
|
cn->host, cn->host_length,
|
|
|
|
cn->ip, cn->ip_length,
|
|
|
|
event->thread_id, 0, type);
|
|
|
|
csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
|
|
|
|
",%.*s,,%d", cn->db_length, cn->db, event->status);
|
|
|
|
message[csize]= '\n';
|
2019-06-14 23:02:55 +02:00
|
|
|
return write_log(message, csize + 1, 1);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static int log_connection_event(const struct mysql_event_connection *event,
|
|
|
|
const char *type)
|
|
|
|
{
|
|
|
|
time_t ctime;
|
|
|
|
size_t csize;
|
|
|
|
char message[1024];
|
|
|
|
|
|
|
|
(void) time(&ctime);
|
|
|
|
csize= log_header(message, sizeof(message)-1, &ctime,
|
|
|
|
servhost, servhost_len,
|
|
|
|
event->user, event->user_length,
|
|
|
|
event->host, event->host_length,
|
|
|
|
event->ip, event->ip_length,
|
|
|
|
event->thread_id, 0, type);
|
|
|
|
csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
|
2018-01-07 17:03:44 +01:00
|
|
|
",%.*s,,%d", event->database.length, event->database.str, event->status);
|
2016-01-12 13:29:02 +01:00
|
|
|
message[csize]= '\n';
|
2019-06-14 23:02:55 +02:00
|
|
|
return write_log(message, csize + 1, 1);
|
2016-01-12 13:29:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static size_t escape_string(const char *str, unsigned int len,
|
|
|
|
char *result, size_t result_len)
|
|
|
|
{
|
|
|
|
const char *res_start= result;
|
|
|
|
const char *res_end= result + result_len - 2;
|
|
|
|
while (len)
|
|
|
|
{
|
2017-11-03 14:05:41 +01:00
|
|
|
char esc_c;
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
if (result >= res_end)
|
|
|
|
break;
|
2017-11-03 14:05:41 +01:00
|
|
|
if ((esc_c= escaped_char(*str)))
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
2015-03-31 10:10:43 +02:00
|
|
|
if (result+1 >= res_end)
|
|
|
|
break;
|
2014-02-24 20:40:16 +01:00
|
|
|
*(result++)= '\\';
|
2017-11-03 14:05:41 +01:00
|
|
|
*(result++)= esc_c;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
2015-06-06 16:12:44 +02:00
|
|
|
else if (is_space(*str))
|
|
|
|
*(result++)= ' ';
|
2014-02-24 20:40:16 +01:00
|
|
|
else
|
|
|
|
*(result++)= *str;
|
|
|
|
str++;
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
*result= 0;
|
|
|
|
return result - res_start;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
static size_t escape_string_hide_passwords(const char *str, unsigned int len,
|
|
|
|
char *result, size_t result_len,
|
|
|
|
const char *word1, size_t word1_len,
|
|
|
|
const char *word2, size_t word2_len,
|
|
|
|
int next_text_string)
|
|
|
|
{
|
|
|
|
const char *res_start= result;
|
|
|
|
const char *res_end= result + result_len - 2;
|
|
|
|
size_t d_len;
|
|
|
|
|
|
|
|
while (len)
|
|
|
|
{
|
|
|
|
if (len > word1_len + 1 && strncasecmp(str, word1, word1_len) == 0)
|
|
|
|
{
|
|
|
|
const char *next_s= str + word1_len;
|
|
|
|
size_t c;
|
|
|
|
|
|
|
|
if (next_text_string)
|
|
|
|
{
|
|
|
|
while (*next_s && *next_s != '\'' && *next_s != '"')
|
|
|
|
++next_s;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (word2)
|
|
|
|
{
|
|
|
|
SKIP_SPACES(next_s);
|
|
|
|
if (len < (next_s - str) + word2_len + 1 ||
|
|
|
|
strncasecmp(next_s, word2, word2_len) != 0)
|
|
|
|
goto no_password;
|
|
|
|
next_s+= word2_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (*next_s && *next_s != '\'' && *next_s != '"')
|
|
|
|
++next_s;
|
|
|
|
}
|
|
|
|
|
|
|
|
d_len= next_s - str;
|
|
|
|
if (result + d_len + 5 > res_end)
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (c=0; c<d_len; c++)
|
|
|
|
result[c]= is_space(str[c]) ? ' ' : str[c];
|
|
|
|
|
2015-06-07 12:40:42 +02:00
|
|
|
if (*next_s)
|
|
|
|
{
|
2020-08-11 14:48:58 +02:00
|
|
|
const char b_char= *next_s++;
|
|
|
|
memset(result + d_len, '*', 5);
|
2015-06-07 12:40:42 +02:00
|
|
|
result+= d_len + 5;
|
|
|
|
|
2020-08-11 14:48:58 +02:00
|
|
|
while (*next_s)
|
2015-02-08 19:38:19 +01:00
|
|
|
{
|
2020-08-11 14:48:58 +02:00
|
|
|
if (*next_s == b_char)
|
|
|
|
{
|
|
|
|
++next_s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*next_s == '\\')
|
|
|
|
{
|
|
|
|
if (next_s[1])
|
|
|
|
next_s++;
|
|
|
|
}
|
|
|
|
next_s++;
|
2015-02-08 19:38:19 +01:00
|
|
|
}
|
|
|
|
}
|
2020-08-11 14:48:58 +02:00
|
|
|
else
|
|
|
|
result+= d_len;
|
|
|
|
|
2017-09-28 12:38:02 +02:00
|
|
|
len-= (uint)(next_s - str);
|
2015-02-08 19:38:19 +01:00
|
|
|
str= next_s;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
no_password:
|
|
|
|
if (result >= res_end)
|
|
|
|
break;
|
2020-08-11 14:48:58 +02:00
|
|
|
else
|
2015-02-08 19:38:19 +01:00
|
|
|
{
|
2020-08-11 14:48:58 +02:00
|
|
|
const char b_char= escaped_char(*str);
|
|
|
|
if (b_char)
|
|
|
|
{
|
|
|
|
if (result+1 >= res_end)
|
|
|
|
break;
|
|
|
|
*(result++)= '\\';
|
|
|
|
*(result++)= b_char;
|
|
|
|
}
|
|
|
|
else if (is_space(*str))
|
|
|
|
*(result++)= ' ';
|
|
|
|
else
|
|
|
|
*(result++)= *str;
|
|
|
|
str++;
|
|
|
|
len--;
|
2015-02-08 19:38:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
*result= 0;
|
|
|
|
return result - res_start;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-28 12:12:32 +01:00
|
|
|
static int do_log_user(const char *name, int len,
|
|
|
|
const char *proxy, int proxy_len, int take_lock)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
2019-06-14 23:02:55 +02:00
|
|
|
int result;
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if (!name)
|
|
|
|
return 0;
|
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
if (take_lock)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_rdlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
if (incl_user_coll.n_users)
|
2020-12-28 12:12:32 +01:00
|
|
|
{
|
|
|
|
result= coll_search(&incl_user_coll, name, len) != 0 ||
|
|
|
|
(proxy && coll_search(&incl_user_coll, proxy, proxy_len) != 0);
|
|
|
|
}
|
2019-06-14 23:02:55 +02:00
|
|
|
else if (excl_user_coll.n_users)
|
2020-12-28 12:12:32 +01:00
|
|
|
{
|
|
|
|
result= coll_search(&excl_user_coll, name, len) == 0 &&
|
|
|
|
(proxy && coll_search(&excl_user_coll, proxy, proxy_len) == 0);
|
|
|
|
}
|
2019-06-14 23:02:55 +02:00
|
|
|
else
|
|
|
|
result= 1;
|
2014-02-24 20:40:16 +01:00
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
if (take_lock)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2019-06-14 23:02:55 +02:00
|
|
|
return result;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
static int get_next_word(const char *query, char *word)
|
|
|
|
{
|
|
|
|
int len= 0;
|
|
|
|
char c;
|
|
|
|
while ((c= query[len]))
|
|
|
|
{
|
|
|
|
if (c >= 'a' && c <= 'z')
|
|
|
|
word[len]= 'A' + (c-'a');
|
|
|
|
else if (c >= 'A' && c <= 'Z')
|
|
|
|
word[len]= c;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (len++ == MAX_KEYWORD)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
word[len]= 0;
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int filter_query_type(const char *query, struct sa_keyword *kwd)
|
|
|
|
{
|
|
|
|
int qwe_in_list;
|
|
|
|
char fword[MAX_KEYWORD + 1], nword[MAX_KEYWORD + 1];
|
|
|
|
int len, nlen= 0;
|
|
|
|
const struct sa_keyword *l_keywords;
|
|
|
|
|
|
|
|
while (*query && (is_space(*query) || *query == '(' || *query == '/'))
|
|
|
|
{
|
|
|
|
/* comment handling */
|
|
|
|
if (*query == '/' && query[1] == '*')
|
|
|
|
{
|
|
|
|
if (query[2] == '!')
|
|
|
|
{
|
|
|
|
query+= 3;
|
|
|
|
while (*query >= '0' && *query <= '9')
|
|
|
|
query++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
query+= 2;
|
|
|
|
while (*query)
|
|
|
|
{
|
|
|
|
if (*query=='*' && query[1] == '/')
|
|
|
|
{
|
|
|
|
query+= 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
query++;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
query++;
|
|
|
|
}
|
|
|
|
|
|
|
|
qwe_in_list= 0;
|
|
|
|
if (!(len= get_next_word(query, fword)))
|
|
|
|
goto not_in_list;
|
|
|
|
query+= len+1;
|
|
|
|
|
|
|
|
l_keywords= kwd;
|
|
|
|
while (l_keywords->length)
|
|
|
|
{
|
|
|
|
if (l_keywords->length == len && strncmp(l_keywords->wd, fword, len) == 0)
|
|
|
|
{
|
|
|
|
if (l_keywords->next)
|
|
|
|
{
|
|
|
|
if (nlen == 0)
|
|
|
|
{
|
|
|
|
while (*query && is_space(*query))
|
|
|
|
query++;
|
|
|
|
nlen= get_next_word(query, nword);
|
|
|
|
}
|
|
|
|
if (l_keywords->next->length != nlen ||
|
|
|
|
strncmp(l_keywords->next->wd, nword, nlen) != 0)
|
|
|
|
goto do_loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
qwe_in_list= l_keywords->type;
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
do_loop:
|
|
|
|
l_keywords++;
|
|
|
|
}
|
|
|
|
|
|
|
|
not_in_list:
|
|
|
|
return qwe_in_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
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,
|
2019-06-14 23:02:55 +02:00
|
|
|
int error_code, const char *type, int take_lock)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
2015-03-31 10:10:43 +02:00
|
|
|
size_t csize;
|
2021-10-21 13:11:20 +02:00
|
|
|
char message_loc[2048];
|
2015-03-31 10:10:43 +02:00
|
|
|
char *message= message_loc;
|
|
|
|
size_t message_size= sizeof(message_loc);
|
|
|
|
char *uh_buffer;
|
|
|
|
size_t uh_buffer_size;
|
2014-02-24 20:40:16 +01:00
|
|
|
const char *db;
|
|
|
|
unsigned int db_length;
|
|
|
|
long long query_id;
|
2015-03-31 10:10:43 +02:00
|
|
|
int result;
|
2021-10-21 13:11:20 +02:00
|
|
|
char *big_buffer= NULL;
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if ((db= cn->db))
|
|
|
|
db_length= cn->db_length;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
db= "";
|
|
|
|
db_length= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(query_id= cn->query_id))
|
|
|
|
query_id= query_counter++;
|
|
|
|
|
|
|
|
if (query == 0)
|
|
|
|
{
|
|
|
|
/* Can happen after the error in mysqld_prepare_stmt() */
|
|
|
|
query= cn->query;
|
|
|
|
query_len= cn->query_length;
|
2015-02-08 19:38:19 +01:00
|
|
|
if (query == 0 || query_len == 0)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (query && !(events & EVENT_QUERY_ALL) &&
|
2019-04-28 23:25:17 +02:00
|
|
|
(events & EVENT_QUERY && !cn->log_always))
|
2015-02-08 19:38:19 +01:00
|
|
|
{
|
|
|
|
const char *orig_query= query;
|
|
|
|
|
|
|
|
if (filter_query_type(query, keywords_to_skip))
|
|
|
|
{
|
|
|
|
char fword[MAX_KEYWORD + 1];
|
|
|
|
int len;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
len= get_next_word(query, fword);
|
|
|
|
query+= len ? len : 1;
|
|
|
|
if (len == 3 && strncmp(fword, "FOR", 3) == 0)
|
|
|
|
break;
|
|
|
|
} while (*query);
|
|
|
|
|
|
|
|
if (*query == 0)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (events & EVENT_QUERY_DDL)
|
|
|
|
{
|
|
|
|
if (!filter_query_type(query, not_ddl_keywords) &&
|
|
|
|
filter_query_type(query, ddl_keywords))
|
|
|
|
goto do_log_query;
|
|
|
|
}
|
|
|
|
if (events & EVENT_QUERY_DML)
|
|
|
|
{
|
|
|
|
if (filter_query_type(query, dml_keywords))
|
|
|
|
goto do_log_query;
|
|
|
|
}
|
2018-05-10 17:00:54 +02:00
|
|
|
if (events & EVENT_QUERY_DML_NO_SELECT)
|
|
|
|
{
|
|
|
|
if (filter_query_type(query, dml_no_select_keywords))
|
|
|
|
goto do_log_query;
|
|
|
|
}
|
2015-03-31 10:10:43 +02:00
|
|
|
if (events & EVENT_QUERY_DCL)
|
|
|
|
{
|
|
|
|
if (filter_query_type(query, dcl_keywords))
|
|
|
|
goto do_log_query;
|
|
|
|
}
|
2015-02-08 19:38:19 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
do_log_query:
|
|
|
|
query= orig_query;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
2015-03-31 10:10:43 +02:00
|
|
|
csize= log_header(message, message_size-1, &ev_time,
|
|
|
|
servhost, servhost_len,
|
|
|
|
cn->user, cn->user_length,cn->host, cn->host_length,
|
|
|
|
cn->ip, cn->ip_length, thd_id, query_id, type);
|
|
|
|
|
|
|
|
csize+= my_snprintf(message+csize, message_size - 1 - csize,
|
|
|
|
",%.*s,\'", db_length, db);
|
|
|
|
|
|
|
|
if (query_log_limit > 0 && query_len > query_log_limit)
|
|
|
|
query_len= query_log_limit;
|
|
|
|
|
|
|
|
if (query_len > (message_size - csize)/2)
|
|
|
|
{
|
2021-10-21 13:11:20 +02:00
|
|
|
size_t big_buffer_alloced= (query_len * 2 + csize + 4095) & ~4095L;
|
|
|
|
if(!(big_buffer= malloc(big_buffer_alloced)))
|
|
|
|
return 0;
|
2015-03-31 10:10:43 +02:00
|
|
|
|
|
|
|
memcpy(big_buffer, message, csize);
|
|
|
|
message= big_buffer;
|
|
|
|
message_size= big_buffer_alloced;
|
|
|
|
}
|
|
|
|
|
|
|
|
uh_buffer= message + csize;
|
|
|
|
uh_buffer_size= message_size - csize;
|
|
|
|
if (query_log_limit > 0 && uh_buffer_size > query_log_limit+2)
|
|
|
|
uh_buffer_size= query_log_limit+2;
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
switch (filter_query_type(query, passwd_keywords))
|
|
|
|
{
|
|
|
|
case SQLCOM_GRANT:
|
|
|
|
case SQLCOM_CREATE_USER:
|
2021-02-26 10:26:00 +01:00
|
|
|
case SQLCOM_ALTER_USER:
|
2015-03-31 10:10:43 +02:00
|
|
|
csize+= escape_string_hide_passwords(query, query_len,
|
|
|
|
uh_buffer, uh_buffer_size,
|
2015-02-08 19:38:19 +01:00
|
|
|
"IDENTIFIED", 10, "BY", 2, 0);
|
|
|
|
break;
|
|
|
|
case SQLCOM_CHANGE_MASTER:
|
2015-03-31 10:10:43 +02:00
|
|
|
csize+= escape_string_hide_passwords(query, query_len,
|
|
|
|
uh_buffer, uh_buffer_size,
|
2015-02-08 19:38:19 +01:00
|
|
|
"MASTER_PASSWORD", 15, "=", 1, 0);
|
|
|
|
break;
|
|
|
|
case SQLCOM_CREATE_SERVER:
|
|
|
|
case SQLCOM_ALTER_SERVER:
|
2015-03-31 10:10:43 +02:00
|
|
|
csize+= escape_string_hide_passwords(query, query_len,
|
|
|
|
uh_buffer, uh_buffer_size,
|
2015-02-08 19:38:19 +01:00
|
|
|
"PASSWORD", 8, NULL, 0, 0);
|
|
|
|
break;
|
|
|
|
case SQLCOM_SET_OPTION:
|
2015-03-31 10:10:43 +02:00
|
|
|
csize+= escape_string_hide_passwords(query, query_len,
|
|
|
|
uh_buffer, uh_buffer_size,
|
2015-02-08 19:38:19 +01:00
|
|
|
"=", 1, NULL, 0, 1);
|
|
|
|
break;
|
|
|
|
default:
|
2015-03-31 10:10:43 +02:00
|
|
|
csize+= escape_string(query, query_len,
|
|
|
|
uh_buffer, uh_buffer_size);
|
2015-02-08 19:38:19 +01:00
|
|
|
break;
|
|
|
|
}
|
2015-03-31 10:10:43 +02:00
|
|
|
csize+= my_snprintf(message+csize, message_size - 1 - csize,
|
|
|
|
"\',%d", error_code);
|
2014-02-24 20:40:16 +01:00
|
|
|
message[csize]= '\n';
|
2019-06-14 23:02:55 +02:00
|
|
|
result= write_log(message, csize + 1, take_lock);
|
2021-10-21 13:11:20 +02:00
|
|
|
if (big_buffer)
|
|
|
|
free(big_buffer);
|
2015-03-31 10:10:43 +02:00
|
|
|
|
|
|
|
return result;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int log_statement(const struct connection_info *cn,
|
|
|
|
const struct mysql_event_general *event,
|
|
|
|
const char *type)
|
|
|
|
{
|
|
|
|
return log_statement_ex(cn, event->general_time, event->general_thread_id,
|
|
|
|
event->general_query, event->general_query_length,
|
2019-06-14 23:02:55 +02:00
|
|
|
event->general_error_code, type, 1);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int log_table(const struct connection_info *cn,
|
|
|
|
const struct mysql_event_table *event, const char *type)
|
|
|
|
{
|
|
|
|
size_t csize;
|
|
|
|
char message[1024];
|
|
|
|
time_t ctime;
|
|
|
|
|
|
|
|
(void) time(&ctime);
|
|
|
|
csize= log_header(message, sizeof(message)-1, &ctime,
|
|
|
|
servhost, servhost_len,
|
2019-07-06 13:22:45 +02:00
|
|
|
event->user, SAFE_STRLEN_UI(event->user),
|
|
|
|
event->host, SAFE_STRLEN_UI(event->host),
|
|
|
|
event->ip, SAFE_STRLEN_UI(event->ip),
|
2014-02-24 20:40:16 +01:00
|
|
|
event->thread_id, cn->query_id, type);
|
|
|
|
csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
|
2018-01-07 17:03:44 +01:00
|
|
|
",%.*s,%.*s,",event->database.length, event->database.str,
|
|
|
|
event->table.length, event->table.str);
|
2014-02-24 20:40:16 +01:00
|
|
|
message[csize]= '\n';
|
2019-06-14 23:02:55 +02:00
|
|
|
return write_log(message, csize + 1, 1);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int log_rename(const struct connection_info *cn,
|
|
|
|
const struct mysql_event_table *event)
|
|
|
|
{
|
|
|
|
size_t csize;
|
|
|
|
char message[1024];
|
|
|
|
time_t ctime;
|
|
|
|
|
|
|
|
(void) time(&ctime);
|
|
|
|
csize= log_header(message, sizeof(message)-1, &ctime,
|
|
|
|
servhost, servhost_len,
|
2019-07-06 13:22:45 +02:00
|
|
|
event->user, SAFE_STRLEN_UI(event->user),
|
|
|
|
event->host, SAFE_STRLEN_UI(event->host),
|
|
|
|
event->ip, SAFE_STRLEN_UI(event->ip),
|
2014-02-24 20:40:16 +01:00
|
|
|
event->thread_id, cn->query_id, "RENAME");
|
|
|
|
csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
|
2018-01-07 17:03:44 +01:00
|
|
|
",%.*s,%.*s|%.*s.%.*s,",event->database.length, event->database.str,
|
|
|
|
event->table.length, event->table.str,
|
|
|
|
event->new_database.length, event->new_database.str,
|
|
|
|
event->new_table.length, event->new_table.str);
|
2014-02-24 20:40:16 +01:00
|
|
|
message[csize]= '\n';
|
2019-06-14 23:02:55 +02:00
|
|
|
return write_log(message, csize + 1, 1);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int event_query_command(const struct mysql_event_general *event)
|
|
|
|
{
|
|
|
|
return (event->general_command_length == 5 &&
|
|
|
|
strncmp(event->general_command, "Query", 5) == 0) ||
|
|
|
|
(event->general_command_length == 7 &&
|
|
|
|
(strncmp(event->general_command, "Execute", 7) == 0 ||
|
|
|
|
(event->general_error_code != 0 &&
|
|
|
|
strncmp(event->general_command, "Prepare", 7) == 0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update_general_user(struct connection_info *cn,
|
|
|
|
const struct mysql_event_general *event)
|
|
|
|
{
|
|
|
|
char uh_buffer[768];
|
|
|
|
size_t user_len, host_len, ip_len;
|
|
|
|
if (cn->user_length == 0 && cn->host_length == 0 && cn->ip_length == 0 &&
|
|
|
|
get_user_host(event->general_user, event->general_user_length,
|
|
|
|
uh_buffer, sizeof(uh_buffer),
|
|
|
|
&user_len, &host_len, &ip_len) == 0)
|
|
|
|
{
|
|
|
|
get_str_n(cn->user, &cn->user_length, sizeof(cn->user),
|
|
|
|
uh_buffer, user_len);
|
|
|
|
get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
|
|
|
|
uh_buffer+user_len+1, host_len);
|
|
|
|
get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
|
|
|
|
uh_buffer+user_len+1+host_len+1, ip_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static struct connection_info ci_disconnect_buffer;
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
#define AA_FREE_CONNECTION 1
|
|
|
|
#define AA_CHANGE_USER 2
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
static void update_connection_info(struct connection_info *cn,
|
|
|
|
unsigned int event_class, const void *ev, int *after_action)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
*after_action= 0;
|
|
|
|
|
|
|
|
switch (event_class) {
|
|
|
|
case MYSQL_AUDIT_GENERAL_CLASS:
|
|
|
|
{
|
|
|
|
const struct mysql_event_general *event =
|
|
|
|
(const struct mysql_event_general *) ev;
|
|
|
|
switch (event->event_subclass) {
|
|
|
|
case MYSQL_AUDIT_GENERAL_LOG:
|
|
|
|
{
|
|
|
|
int init_db_command= event->general_command_length == 7 &&
|
|
|
|
strncmp(event->general_command, "Init DB", 7) == 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
if (!ci_needs_setup(cn))
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
if (init_db_command)
|
|
|
|
{
|
|
|
|
/* Change DB */
|
2016-01-12 13:29:02 +01:00
|
|
|
if (mysql_57_started)
|
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
|
2018-01-07 17:03:44 +01:00
|
|
|
event->database.str, event->database.length);
|
2016-01-12 13:29:02 +01:00
|
|
|
else
|
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
|
|
|
|
event->general_query, event->general_query_length);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
cn->query_id= mode ? query_counter++ : event->query_id;
|
|
|
|
cn->query= event->general_query;
|
|
|
|
cn->query_length= event->general_query_length;
|
|
|
|
cn->query_time= (time_t) event->general_time;
|
|
|
|
update_general_user(cn, event);
|
|
|
|
}
|
|
|
|
else if (init_db_command)
|
2016-01-12 13:29:02 +01:00
|
|
|
setup_connection_initdb(cn, event);
|
2014-02-24 20:40:16 +01:00
|
|
|
else if (event_query_command(event))
|
2016-01-12 13:29:02 +01:00
|
|
|
setup_connection_query(cn, event);
|
|
|
|
else
|
|
|
|
setup_connection_simple(cn);
|
2014-02-24 20:40:16 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case MYSQL_AUDIT_GENERAL_STATUS:
|
|
|
|
if (event_query_command(event))
|
|
|
|
{
|
2016-01-12 13:29:02 +01:00
|
|
|
if (ci_needs_setup(cn))
|
|
|
|
setup_connection_query(cn, event);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
2018-01-07 17:03:44 +01:00
|
|
|
if (mode == 0 && cn->db_length == 0 && event->database.length > 0)
|
2014-02-24 20:40:16 +01:00
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
|
2018-01-07 17:03:44 +01:00
|
|
|
event->database.str, event->database.length);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if (event->general_error_code == 0)
|
|
|
|
{
|
|
|
|
/* We need to check if it's the USE command to change the DB */
|
|
|
|
int use_command= event->general_query_length > 4 &&
|
|
|
|
strncasecmp(event->general_query, "use ", 4) == 0;
|
|
|
|
if (use_command)
|
|
|
|
{
|
|
|
|
/* Change DB */
|
|
|
|
if (mode)
|
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
|
|
|
|
event->general_query + 4, event->general_query_length - 4);
|
|
|
|
else
|
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
|
2018-01-07 17:03:44 +01:00
|
|
|
event->database.str, event->database.length);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
update_general_user(cn, event);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MYSQL_AUDIT_GENERAL_ERROR:
|
2016-01-12 13:29:02 +01:00
|
|
|
/*
|
|
|
|
We need this because the MariaDB returns NULL query field for the
|
|
|
|
MYSQL_AUDIT_GENERAL_STATUS in the mysqld_stmt_prepare.
|
|
|
|
As a result we get empty QUERY field for errors.
|
|
|
|
*/
|
|
|
|
if (ci_needs_setup(cn))
|
|
|
|
setup_connection_query(cn, event);
|
2014-02-24 20:40:16 +01:00
|
|
|
cn->query_id= mode ? query_counter++ : event->query_id;
|
|
|
|
get_str_n(cn->query_buffer, &cn->query_length, sizeof(cn->query_buffer),
|
|
|
|
event->general_query, event->general_query_length);
|
|
|
|
cn->query= cn->query_buffer;
|
|
|
|
cn->query_time= (time_t) event->general_time;
|
|
|
|
break;
|
|
|
|
default:;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MYSQL_AUDIT_TABLE_CLASS:
|
|
|
|
{
|
|
|
|
const struct mysql_event_table *event =
|
|
|
|
(const struct mysql_event_table *) ev;
|
2016-01-12 13:29:02 +01:00
|
|
|
if (ci_needs_setup(cn))
|
|
|
|
setup_connection_table(cn, event);
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
if (cn->user_length == 0 && cn->host_length == 0 && cn->ip_length == 0)
|
|
|
|
{
|
|
|
|
get_str_n(cn->user, &cn->user_length, sizeof(cn->user),
|
|
|
|
event->user, SAFE_STRLEN(event->user));
|
|
|
|
get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
|
|
|
|
event->host, SAFE_STRLEN(event->host));
|
|
|
|
get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
|
|
|
|
event->ip, SAFE_STRLEN(event->ip));
|
|
|
|
}
|
|
|
|
|
2018-01-07 17:03:44 +01:00
|
|
|
if (cn->db_length == 0 && event->database.length != 0)
|
2014-02-24 20:40:16 +01:00
|
|
|
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
|
2018-01-07 17:03:44 +01:00
|
|
|
event->database.str, event->database.length);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if (mode == 0)
|
|
|
|
cn->query_id= event->query_id;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MYSQL_AUDIT_CONNECTION_CLASS:
|
|
|
|
{
|
|
|
|
const struct mysql_event_connection *event =
|
|
|
|
(const struct mysql_event_connection *) ev;
|
|
|
|
switch (event->event_subclass)
|
|
|
|
{
|
|
|
|
case MYSQL_AUDIT_CONNECTION_CONNECT:
|
2016-01-12 13:29:02 +01:00
|
|
|
setup_connection_connect(cn, event);
|
2014-02-24 20:40:16 +01:00
|
|
|
break;
|
|
|
|
case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
|
2016-01-12 13:29:02 +01:00
|
|
|
*after_action= AA_CHANGE_USER;
|
2014-02-24 20:40:16 +01:00
|
|
|
break;
|
|
|
|
default:;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
struct connection_info cn_error_buffer;
|
|
|
|
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
#define FILTER(MASK) (events == 0 || (events & MASK))
|
2016-01-12 13:29:02 +01:00
|
|
|
void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
2016-01-12 13:29:02 +01:00
|
|
|
struct connection_info *cn= 0;
|
|
|
|
int after_action= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
/* That one is important as this function can be called with */
|
|
|
|
/* &lock_operations locked when the server logs an error reported */
|
|
|
|
/* by this plugin. */
|
2017-06-26 20:06:12 +02:00
|
|
|
if (!thd || internal_stop_logging)
|
2014-02-24 20:40:16 +01:00
|
|
|
return;
|
|
|
|
|
2016-01-13 12:24:33 +01:00
|
|
|
if (maria_55_started && debug_server_started &&
|
|
|
|
event_class == MYSQL_AUDIT_GENERAL_CLASS)
|
2016-01-12 13:29:02 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
There's a bug in MariaDB 5.5 that prevents using thread local
|
|
|
|
variables in some cases.
|
|
|
|
The 'select * from notexisting_table;' query produces such case.
|
|
|
|
So just use the static buffer in this case.
|
|
|
|
*/
|
2016-01-13 12:24:33 +01:00
|
|
|
const struct mysql_event_general *event =
|
|
|
|
(const struct mysql_event_general *) ev;
|
|
|
|
|
|
|
|
if (event->event_subclass == MYSQL_AUDIT_GENERAL_ERROR ||
|
|
|
|
(event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS &&
|
|
|
|
event->general_query_length == 0 &&
|
|
|
|
cn_error_buffer.query_id == event->query_id))
|
|
|
|
{
|
|
|
|
cn= &cn_error_buffer;
|
|
|
|
cn->header= 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cn= get_loc_info(thd);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cn= get_loc_info(thd);
|
2016-01-12 13:29:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
update_connection_info(cn, event_class, ev, &after_action);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if (!logging)
|
2019-05-19 21:50:23 +02:00
|
|
|
{
|
|
|
|
if (cn)
|
|
|
|
cn->log_always= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
goto exit_func;
|
2019-05-19 21:50:23 +02:00
|
|
|
}
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if (event_class == MYSQL_AUDIT_GENERAL_CLASS && FILTER(EVENT_QUERY) &&
|
2020-12-28 12:12:32 +01:00
|
|
|
cn && (cn->log_always || do_log_user(cn->user, cn->user_length,
|
|
|
|
cn->proxy, cn->proxy_length,
|
|
|
|
1)))
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
const struct mysql_event_general *event =
|
|
|
|
(const struct mysql_event_general *) ev;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Only one subclass is logged.
|
|
|
|
*/
|
2016-01-12 13:29:02 +01:00
|
|
|
if (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS &&
|
|
|
|
event_query_command(event))
|
|
|
|
{
|
2014-02-24 20:40:16 +01:00
|
|
|
log_statement(cn, event, "QUERY");
|
2017-09-19 11:08:24 +02:00
|
|
|
cn->query_length= 0; /* So the log_current_query() won't log this again. */
|
2019-05-19 21:50:23 +02:00
|
|
|
cn->log_always= 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
}
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
else if (event_class == MYSQL_AUDIT_TABLE_CLASS && FILTER(EVENT_TABLE) && cn)
|
|
|
|
{
|
|
|
|
const struct mysql_event_table *event =
|
|
|
|
(const struct mysql_event_table *) ev;
|
2021-01-06 18:55:55 +01:00
|
|
|
if (do_log_user(event->user, (int) SAFE_STRLEN(event->user),
|
2020-12-28 12:12:32 +01:00
|
|
|
cn->proxy, cn->proxy_length, 1))
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
|
|
|
switch (event->event_subclass)
|
|
|
|
{
|
|
|
|
case MYSQL_AUDIT_TABLE_LOCK:
|
|
|
|
log_table(cn, event, event->read_only ? "READ" : "WRITE");
|
|
|
|
break;
|
|
|
|
case MYSQL_AUDIT_TABLE_CREATE:
|
|
|
|
log_table(cn, event, "CREATE");
|
|
|
|
break;
|
|
|
|
case MYSQL_AUDIT_TABLE_DROP:
|
|
|
|
log_table(cn, event, "DROP");
|
|
|
|
break;
|
|
|
|
case MYSQL_AUDIT_TABLE_RENAME:
|
|
|
|
log_rename(cn, event);
|
|
|
|
break;
|
|
|
|
case MYSQL_AUDIT_TABLE_ALTER:
|
|
|
|
log_table(cn, event, "ALTER");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (event_class == MYSQL_AUDIT_CONNECTION_CLASS &&
|
|
|
|
FILTER(EVENT_CONNECT) && cn)
|
|
|
|
{
|
|
|
|
const struct mysql_event_connection *event =
|
|
|
|
(const struct mysql_event_connection *) ev;
|
|
|
|
switch (event->event_subclass)
|
|
|
|
{
|
|
|
|
case MYSQL_AUDIT_CONNECTION_CONNECT:
|
|
|
|
log_connection(cn, event, event->status ? "FAILED_CONNECT": "CONNECT");
|
2020-12-01 11:13:05 +01:00
|
|
|
if (event->status == 0 && event->proxy_user && event->proxy_user[0])
|
|
|
|
log_proxy(cn, event);
|
2014-02-24 20:40:16 +01:00
|
|
|
break;
|
|
|
|
case MYSQL_AUDIT_CONNECTION_DISCONNECT:
|
2016-01-12 13:29:02 +01:00
|
|
|
if (use_event_data_for_disconnect)
|
|
|
|
log_connection_event(event, "DISCONNECT");
|
|
|
|
else
|
|
|
|
log_connection(&ci_disconnect_buffer, event, "DISCONNECT");
|
2014-02-24 20:40:16 +01:00
|
|
|
break;
|
|
|
|
case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
|
|
|
|
log_connection(cn, event, "CHANGEUSER");
|
2020-12-01 11:13:05 +01:00
|
|
|
if (event->proxy_user && event->proxy_user[0])
|
|
|
|
log_proxy(cn, event);
|
2014-02-24 20:40:16 +01:00
|
|
|
break;
|
|
|
|
default:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
exit_func:
|
|
|
|
/*
|
|
|
|
This must work always, whether logging is ON or not.
|
|
|
|
*/
|
|
|
|
if (after_action)
|
|
|
|
{
|
|
|
|
switch (after_action) {
|
|
|
|
case AA_CHANGE_USER:
|
|
|
|
{
|
|
|
|
const struct mysql_event_connection *event =
|
|
|
|
(const struct mysql_event_connection *) ev;
|
|
|
|
change_connection(cn, event);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
struct mysql_event_general_v8
|
|
|
|
{
|
|
|
|
unsigned int event_class;
|
|
|
|
unsigned int event_subclass;
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
static void auditing_v8(MYSQL_THD thd, struct mysql_event_general_v8 *ev_v8)
|
|
|
|
{
|
2018-02-20 22:17:36 +01:00
|
|
|
#ifdef __linux__
|
2016-01-12 13:29:02 +01:00
|
|
|
#ifdef DBUG_OFF
|
|
|
|
#ifdef __x86_64__
|
|
|
|
static const int cmd_off= 4200;
|
|
|
|
static const int db_off= 120;
|
|
|
|
static const int db_len_off= 128;
|
|
|
|
#else
|
|
|
|
static const int cmd_off= 2668;
|
|
|
|
static const int db_off= 60;
|
|
|
|
static const int db_len_off= 64;
|
|
|
|
#endif /*x86_64*/
|
|
|
|
#else
|
|
|
|
#ifdef __x86_64__
|
|
|
|
static const int cmd_off= 4432;
|
|
|
|
static const int db_off= 120;
|
|
|
|
static const int db_len_off= 128;
|
|
|
|
#else
|
|
|
|
static const int cmd_off= 2808;
|
|
|
|
static const int db_off= 64;
|
|
|
|
static const int db_len_off= 68;
|
|
|
|
#endif /*x86_64*/
|
|
|
|
#endif /*DBUG_OFF*/
|
2018-02-20 22:17:36 +01:00
|
|
|
#endif /* __linux__ */
|
2016-01-12 13:29:02 +01:00
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
struct mysql_event_general event;
|
|
|
|
|
|
|
|
if (ev_v8->event_class != MYSQL_AUDIT_GENERAL_CLASS)
|
|
|
|
return;
|
|
|
|
|
|
|
|
event.event_subclass= ev_v8->event_subclass;
|
|
|
|
event.general_error_code= ev_v8->general_error_code;
|
|
|
|
event.general_thread_id= ev_v8->general_thread_id;
|
|
|
|
event.general_user= ev_v8->general_user;
|
|
|
|
event.general_user_length= ev_v8->general_user_length;
|
|
|
|
event.general_command= ev_v8->general_command;
|
|
|
|
event.general_command_length= ev_v8->general_command_length;
|
|
|
|
event.general_query= ev_v8->general_query;
|
|
|
|
event.general_query_length= ev_v8->general_query_length;
|
|
|
|
event.general_charset= ev_v8->general_charset;
|
|
|
|
event.general_time= ev_v8->general_time;
|
|
|
|
event.general_rows= ev_v8->general_rows;
|
2018-01-07 17:03:44 +01:00
|
|
|
event.database.str= 0;
|
|
|
|
event.database.length= 0;
|
2015-02-08 19:38:19 +01:00
|
|
|
|
|
|
|
if (event.general_query_length > 0)
|
|
|
|
{
|
|
|
|
event.event_subclass= MYSQL_AUDIT_GENERAL_STATUS;
|
|
|
|
event.general_command= "Query";
|
|
|
|
event.general_command_length= 5;
|
|
|
|
#ifdef __linux__
|
2018-01-07 17:03:44 +01:00
|
|
|
event.database.str= *(char **) (((char *) thd) + db_off);
|
|
|
|
event.database.length= *(size_t *) (((char *) thd) + db_len_off);
|
2015-02-08 19:38:19 +01:00
|
|
|
#endif /*__linux*/
|
|
|
|
}
|
|
|
|
#ifdef __linux__
|
|
|
|
else if (*((int *) (((char *)thd) + cmd_off)) == 2)
|
|
|
|
{
|
|
|
|
event.event_subclass= MYSQL_AUDIT_GENERAL_LOG;
|
|
|
|
event.general_command= "Init DB";
|
|
|
|
event.general_command_length= 7;
|
|
|
|
event.general_query= *(char **) (((char *) thd) + db_off);
|
|
|
|
event.general_query_length= *(size_t *) (((char *) thd) + db_len_off);
|
|
|
|
}
|
|
|
|
#endif /*__linux*/
|
|
|
|
auditing(thd, ev_v8->event_class, &event);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void auditing_v13(MYSQL_THD thd, unsigned int *ev_v0)
|
|
|
|
{
|
|
|
|
struct mysql_event_general event= *(const struct mysql_event_general *) (ev_v0+1);
|
|
|
|
|
|
|
|
if (event.general_query_length > 0)
|
|
|
|
{
|
|
|
|
event.event_subclass= MYSQL_AUDIT_GENERAL_STATUS;
|
|
|
|
event.general_command= "Query";
|
|
|
|
event.general_command_length= 5;
|
|
|
|
}
|
|
|
|
auditing(thd, ev_v0[0], &event);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-26 06:44:43 +02:00
|
|
|
int get_db_mysql57(MYSQL_THD thd, char **name, size_t *len)
|
2016-01-12 13:29:02 +01:00
|
|
|
{
|
2020-04-04 04:27:43 +02:00
|
|
|
#ifdef __linux__
|
2016-01-12 13:29:02 +01:00
|
|
|
int db_off;
|
|
|
|
int db_len_off;
|
|
|
|
if (debug_server_started)
|
|
|
|
{
|
|
|
|
#ifdef __x86_64__
|
|
|
|
db_off= 608;
|
|
|
|
db_len_off= 616;
|
2022-03-25 12:47:40 +01:00
|
|
|
#elif __aarch64__
|
|
|
|
db_off= 632;
|
|
|
|
db_len_off= 640;
|
2016-01-12 13:29:02 +01:00
|
|
|
#else
|
|
|
|
db_off= 0;
|
|
|
|
db_len_off= 0;
|
|
|
|
#endif /*x86_64*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifdef __x86_64__
|
|
|
|
db_off= 536;
|
|
|
|
db_len_off= 544;
|
2022-03-25 12:47:40 +01:00
|
|
|
#elif __aarch64__
|
|
|
|
db_off= 552;
|
|
|
|
db_len_off= 560;
|
2016-01-12 13:29:02 +01:00
|
|
|
#else
|
|
|
|
db_off= 0;
|
|
|
|
db_len_off= 0;
|
|
|
|
#endif /*x86_64*/
|
|
|
|
}
|
|
|
|
|
|
|
|
*name= *(char **) (((char *) thd) + db_off);
|
2019-07-26 06:44:43 +02:00
|
|
|
*len= *((size_t *) (((char*) thd) + db_len_off));
|
2016-01-12 13:29:02 +01:00
|
|
|
if (*name && (*name)[*len] != 0)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
}
|
2014-02-24 20:40:16 +01:00
|
|
|
/*
|
|
|
|
As it's just too difficult to #include "sql_class.h",
|
|
|
|
let's just copy the necessary part of the system_variables
|
|
|
|
structure here.
|
|
|
|
*/
|
|
|
|
typedef struct loc_system_variables
|
|
|
|
{
|
|
|
|
ulong dynamic_variables_version;
|
|
|
|
char* dynamic_variables_ptr;
|
|
|
|
uint dynamic_variables_head; /* largest valid variable offset */
|
|
|
|
uint dynamic_variables_size; /* how many bytes are in use */
|
|
|
|
|
|
|
|
ulonglong max_heap_table_size;
|
|
|
|
ulonglong tmp_table_size;
|
|
|
|
ulonglong long_query_time;
|
|
|
|
ulonglong optimizer_switch;
|
|
|
|
ulonglong sql_mode; ///< which non-standard SQL behaviour should be enabled
|
|
|
|
ulonglong option_bits; ///< OPTION_xxx constants, e.g. OPTION_PROFILING
|
|
|
|
ulonglong join_buff_space_limit;
|
|
|
|
ulonglong log_slow_filter;
|
|
|
|
ulonglong log_slow_verbosity;
|
|
|
|
ulonglong bulk_insert_buff_size;
|
|
|
|
ulonglong join_buff_size;
|
|
|
|
ulonglong sortbuff_size;
|
|
|
|
ulonglong group_concat_max_len;
|
|
|
|
ha_rows select_limit;
|
|
|
|
ha_rows max_join_size;
|
|
|
|
ha_rows expensive_subquery_limit;
|
|
|
|
ulong auto_increment_increment, auto_increment_offset;
|
|
|
|
ulong lock_wait_timeout;
|
|
|
|
ulong join_cache_level;
|
|
|
|
ulong max_allowed_packet;
|
|
|
|
ulong max_error_count;
|
|
|
|
ulong max_length_for_sort_data;
|
|
|
|
ulong max_sort_length;
|
|
|
|
ulong max_tmp_tables;
|
|
|
|
ulong max_insert_delayed_threads;
|
|
|
|
ulong min_examined_row_limit;
|
|
|
|
ulong net_buffer_length;
|
|
|
|
ulong net_interactive_timeout;
|
|
|
|
ulong net_read_timeout;
|
|
|
|
ulong net_retry_count;
|
|
|
|
ulong net_wait_timeout;
|
|
|
|
ulong net_write_timeout;
|
|
|
|
ulong optimizer_prune_level;
|
|
|
|
ulong optimizer_search_depth;
|
|
|
|
ulong preload_buff_size;
|
|
|
|
ulong profiling_history_size;
|
|
|
|
ulong read_buff_size;
|
|
|
|
ulong read_rnd_buff_size;
|
|
|
|
ulong mrr_buff_size;
|
|
|
|
ulong div_precincrement;
|
|
|
|
/* Total size of all buffers used by the subselect_rowid_merge_engine. */
|
|
|
|
ulong rowid_merge_buff_size;
|
|
|
|
ulong max_sp_recursion_depth;
|
|
|
|
ulong default_week_format;
|
|
|
|
ulong max_seeks_for_key;
|
|
|
|
ulong range_alloc_block_size;
|
|
|
|
ulong query_alloc_block_size;
|
|
|
|
ulong query_prealloc_size;
|
|
|
|
ulong trans_alloc_block_size;
|
|
|
|
ulong trans_prealloc_size;
|
|
|
|
ulong log_warnings;
|
|
|
|
/* Flags for slow log filtering */
|
|
|
|
ulong log_slow_rate_limit;
|
|
|
|
ulong binlog_format; ///< binlog format for this thd (see enum_binlog_format)
|
|
|
|
ulong progress_report_time;
|
|
|
|
my_bool binlog_annotate_row_events;
|
|
|
|
my_bool binlog_direct_non_trans_update;
|
|
|
|
my_bool sql_log_bin;
|
|
|
|
ulong completion_type;
|
|
|
|
ulong query_cache_type;
|
|
|
|
} LOC_SV;
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
|
2017-02-20 15:22:01 +01:00
|
|
|
static int init_done= 0;
|
|
|
|
|
MDEV-22214 mariadbd.exe calls function mysqld.exe, and crashes
Stop linking plugins to the server executable on Windows.
Instead, extract whole server functionality into a large DLL, called
server.dll. Link both plugins, and small server "stub" exe to it.
This eliminates plugin dependency on the name of the server executable.
It also reduces the size of the packages (since tiny mysqld.exe
and mariadbd.exe are now both linked to one big DLL)
Also, simplify the functionality of exporing all symbols from selected
static libraries. Rely on WINDOWS_EXPORT_ALL_SYMBOLS, rather than old
self-backed solution.
fix compile error
replace GetProcAddress(GetModuleHandle(NULL), "variable_name")
for server exported data with actual variable names.
Runtime loading was never required,was error prone
, since symbols could be missing at runtime, and now it actually failed,
because we do not export symbols from executable anymore, but from a shared
library
This did require a MYSQL_PLUGIN_IMPORT decoration for the plugin,
but made the code more straightforward, and avoids missing symbols at
runtime (as mentioned before).
The audit plugin is still doing some dynamic loading, as it aims to work
cross-version. Now it won't work cross-version on Windows, as it already
uses some symbols that are *not* dynamically loaded, e.g fn_format
and those symbols now exported from server.dll , when earlier they were
exported by mysqld.exe
Windows, fixes for storage engine plugin loading
after various rebranding stuff
Create server.dll containing functionality of the whole server
make mariadbd.exe/mysqld.exe a stub that is only calling mysqld_main()
fix build
2020-04-10 14:09:18 +02:00
|
|
|
static void* find_sym(const char *sym)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
return GetProcAddress(GetModuleHandle("server.dll"),sym);
|
|
|
|
#else
|
|
|
|
return dlsym(RTLD_DEFAULT, sym);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static int server_audit_init(void *p __attribute__((unused)))
|
|
|
|
{
|
2015-02-08 19:38:19 +01:00
|
|
|
if (!serv_ver)
|
|
|
|
{
|
MDEV-22214 mariadbd.exe calls function mysqld.exe, and crashes
Stop linking plugins to the server executable on Windows.
Instead, extract whole server functionality into a large DLL, called
server.dll. Link both plugins, and small server "stub" exe to it.
This eliminates plugin dependency on the name of the server executable.
It also reduces the size of the packages (since tiny mysqld.exe
and mariadbd.exe are now both linked to one big DLL)
Also, simplify the functionality of exporing all symbols from selected
static libraries. Rely on WINDOWS_EXPORT_ALL_SYMBOLS, rather than old
self-backed solution.
fix compile error
replace GetProcAddress(GetModuleHandle(NULL), "variable_name")
for server exported data with actual variable names.
Runtime loading was never required,was error prone
, since symbols could be missing at runtime, and now it actually failed,
because we do not export symbols from executable anymore, but from a shared
library
This did require a MYSQL_PLUGIN_IMPORT decoration for the plugin,
but made the code more straightforward, and avoids missing symbols at
runtime (as mentioned before).
The audit plugin is still doing some dynamic loading, as it aims to work
cross-version. Now it won't work cross-version on Windows, as it already
uses some symbols that are *not* dynamically loaded, e.g fn_format
and those symbols now exported from server.dll , when earlier they were
exported by mysqld.exe
Windows, fixes for storage engine plugin loading
after various rebranding stuff
Create server.dll containing functionality of the whole server
make mariadbd.exe/mysqld.exe a stub that is only calling mysqld_main()
fix build
2020-04-10 14:09:18 +02:00
|
|
|
serv_ver= find_sym("server_version");
|
2015-02-08 19:38:19 +01:00
|
|
|
}
|
MDEV-22214 mariadbd.exe calls function mysqld.exe, and crashes
Stop linking plugins to the server executable on Windows.
Instead, extract whole server functionality into a large DLL, called
server.dll. Link both plugins, and small server "stub" exe to it.
This eliminates plugin dependency on the name of the server executable.
It also reduces the size of the packages (since tiny mysqld.exe
and mariadbd.exe are now both linked to one big DLL)
Also, simplify the functionality of exporing all symbols from selected
static libraries. Rely on WINDOWS_EXPORT_ALL_SYMBOLS, rather than old
self-backed solution.
fix compile error
replace GetProcAddress(GetModuleHandle(NULL), "variable_name")
for server exported data with actual variable names.
Runtime loading was never required,was error prone
, since symbols could be missing at runtime, and now it actually failed,
because we do not export symbols from executable anymore, but from a shared
library
This did require a MYSQL_PLUGIN_IMPORT decoration for the plugin,
but made the code more straightforward, and avoids missing symbols at
runtime (as mentioned before).
The audit plugin is still doing some dynamic loading, as it aims to work
cross-version. Now it won't work cross-version on Windows, as it already
uses some symbols that are *not* dynamically loaded, e.g fn_format
and those symbols now exported from server.dll , when earlier they were
exported by mysqld.exe
Windows, fixes for storage engine plugin loading
after various rebranding stuff
Create server.dll containing functionality of the whole server
make mariadbd.exe/mysqld.exe a stub that is only calling mysqld_main()
fix build
2020-04-10 14:09:18 +02:00
|
|
|
|
2017-02-20 15:22:01 +01:00
|
|
|
if (!mysql_57_started)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
MDEV-22214 mariadbd.exe calls function mysqld.exe, and crashes
Stop linking plugins to the server executable on Windows.
Instead, extract whole server functionality into a large DLL, called
server.dll. Link both plugins, and small server "stub" exe to it.
This eliminates plugin dependency on the name of the server executable.
It also reduces the size of the packages (since tiny mysqld.exe
and mariadbd.exe are now both linked to one big DLL)
Also, simplify the functionality of exporing all symbols from selected
static libraries. Rely on WINDOWS_EXPORT_ALL_SYMBOLS, rather than old
self-backed solution.
fix compile error
replace GetProcAddress(GetModuleHandle(NULL), "variable_name")
for server exported data with actual variable names.
Runtime loading was never required,was error prone
, since symbols could be missing at runtime, and now it actually failed,
because we do not export symbols from executable anymore, but from a shared
library
This did require a MYSQL_PLUGIN_IMPORT decoration for the plugin,
but made the code more straightforward, and avoids missing symbols at
runtime (as mentioned before).
The audit plugin is still doing some dynamic loading, as it aims to work
cross-version. Now it won't work cross-version on Windows, as it already
uses some symbols that are *not* dynamically loaded, e.g fn_format
and those symbols now exported from server.dll , when earlier they were
exported by mysqld.exe
Windows, fixes for storage engine plugin loading
after various rebranding stuff
Create server.dll containing functionality of the whole server
make mariadbd.exe/mysqld.exe a stub that is only calling mysqld_main()
fix build
2020-04-10 14:09:18 +02:00
|
|
|
const void *my_hash_init_ptr= find_sym("_my_hash_init");
|
2017-02-20 15:22:01 +01:00
|
|
|
if (!my_hash_init_ptr)
|
|
|
|
{
|
|
|
|
maria_above_5= 1;
|
MDEV-22214 mariadbd.exe calls function mysqld.exe, and crashes
Stop linking plugins to the server executable on Windows.
Instead, extract whole server functionality into a large DLL, called
server.dll. Link both plugins, and small server "stub" exe to it.
This eliminates plugin dependency on the name of the server executable.
It also reduces the size of the packages (since tiny mysqld.exe
and mariadbd.exe are now both linked to one big DLL)
Also, simplify the functionality of exporing all symbols from selected
static libraries. Rely on WINDOWS_EXPORT_ALL_SYMBOLS, rather than old
self-backed solution.
fix compile error
replace GetProcAddress(GetModuleHandle(NULL), "variable_name")
for server exported data with actual variable names.
Runtime loading was never required,was error prone
, since symbols could be missing at runtime, and now it actually failed,
because we do not export symbols from executable anymore, but from a shared
library
This did require a MYSQL_PLUGIN_IMPORT decoration for the plugin,
but made the code more straightforward, and avoids missing symbols at
runtime (as mentioned before).
The audit plugin is still doing some dynamic loading, as it aims to work
cross-version. Now it won't work cross-version on Windows, as it already
uses some symbols that are *not* dynamically loaded, e.g fn_format
and those symbols now exported from server.dll , when earlier they were
exported by mysqld.exe
Windows, fixes for storage engine plugin loading
after various rebranding stuff
Create server.dll containing functionality of the whole server
make mariadbd.exe/mysqld.exe a stub that is only calling mysqld_main()
fix build
2020-04-10 14:09:18 +02:00
|
|
|
my_hash_init_ptr= find_sym("my_hash_init2");
|
2017-02-20 15:22:01 +01:00
|
|
|
}
|
|
|
|
if (!my_hash_init_ptr)
|
|
|
|
return 1;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
MDEV-22214 mariadbd.exe calls function mysqld.exe, and crashes
Stop linking plugins to the server executable on Windows.
Instead, extract whole server functionality into a large DLL, called
server.dll. Link both plugins, and small server "stub" exe to it.
This eliminates plugin dependency on the name of the server executable.
It also reduces the size of the packages (since tiny mysqld.exe
and mariadbd.exe are now both linked to one big DLL)
Also, simplify the functionality of exporing all symbols from selected
static libraries. Rely on WINDOWS_EXPORT_ALL_SYMBOLS, rather than old
self-backed solution.
fix compile error
replace GetProcAddress(GetModuleHandle(NULL), "variable_name")
for server exported data with actual variable names.
Runtime loading was never required,was error prone
, since symbols could be missing at runtime, and now it actually failed,
because we do not export symbols from executable anymore, but from a shared
library
This did require a MYSQL_PLUGIN_IMPORT decoration for the plugin,
but made the code more straightforward, and avoids missing symbols at
runtime (as mentioned before).
The audit plugin is still doing some dynamic loading, as it aims to work
cross-version. Now it won't work cross-version on Windows, as it already
uses some symbols that are *not* dynamically loaded, e.g fn_format
and those symbols now exported from server.dll , when earlier they were
exported by mysqld.exe
Windows, fixes for storage engine plugin loading
after various rebranding stuff
Create server.dll containing functionality of the whole server
make mariadbd.exe/mysqld.exe a stub that is only calling mysqld_main()
fix build
2020-04-10 14:09:18 +02:00
|
|
|
if(!(int_mysql_data_home= find_sym("mysql_data_home")))
|
2015-02-08 19:38:19 +01:00
|
|
|
{
|
MDEV-22214 mariadbd.exe calls function mysqld.exe, and crashes
Stop linking plugins to the server executable on Windows.
Instead, extract whole server functionality into a large DLL, called
server.dll. Link both plugins, and small server "stub" exe to it.
This eliminates plugin dependency on the name of the server executable.
It also reduces the size of the packages (since tiny mysqld.exe
and mariadbd.exe are now both linked to one big DLL)
Also, simplify the functionality of exporing all symbols from selected
static libraries. Rely on WINDOWS_EXPORT_ALL_SYMBOLS, rather than old
self-backed solution.
fix compile error
replace GetProcAddress(GetModuleHandle(NULL), "variable_name")
for server exported data with actual variable names.
Runtime loading was never required,was error prone
, since symbols could be missing at runtime, and now it actually failed,
because we do not export symbols from executable anymore, but from a shared
library
This did require a MYSQL_PLUGIN_IMPORT decoration for the plugin,
but made the code more straightforward, and avoids missing symbols at
runtime (as mentioned before).
The audit plugin is still doing some dynamic loading, as it aims to work
cross-version. Now it won't work cross-version on Windows, as it already
uses some symbols that are *not* dynamically loaded, e.g fn_format
and those symbols now exported from server.dll , when earlier they were
exported by mysqld.exe
Windows, fixes for storage engine plugin loading
after various rebranding stuff
Create server.dll containing functionality of the whole server
make mariadbd.exe/mysqld.exe a stub that is only calling mysqld_main()
fix build
2020-04-10 14:09:18 +02:00
|
|
|
if(!(int_mysql_data_home= find_sym("?mysql_data_home@@3PADA")))
|
2015-02-08 19:38:19 +01:00
|
|
|
int_mysql_data_home= &default_home;
|
|
|
|
}
|
|
|
|
|
2017-02-20 15:22:01 +01:00
|
|
|
if (!serv_ver)
|
2015-02-08 19:38:19 +01:00
|
|
|
return 1;
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if (!started_mysql)
|
|
|
|
{
|
|
|
|
if (!maria_above_5 && serv_ver[4]=='3' && serv_ver[5]<'3')
|
|
|
|
{
|
|
|
|
mode= 1;
|
|
|
|
mode_readonly= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gethostname(servhost, sizeof(servhost)))
|
|
|
|
strcpy(servhost, "unknown");
|
|
|
|
|
2018-01-12 19:25:02 +01:00
|
|
|
servhost_len= (uint)strlen(servhost);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
logger_init_mutexes();
|
2021-02-25 10:55:08 +01:00
|
|
|
#ifdef HAVE_PSI_INTERFACE
|
2014-02-24 20:40:16 +01:00
|
|
|
if (PSI_server)
|
|
|
|
PSI_server->register_mutex("server_audit", mutex_key_list, 1);
|
|
|
|
#endif
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_init(key_LOCK_operations, &lock_operations);
|
2019-06-14 23:02:55 +02:00
|
|
|
flogger_mutex_init(key_LOCK_operations, &lock_atomic, MY_MUTEX_INIT_FAST);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
coll_init(&incl_user_coll);
|
|
|
|
coll_init(&excl_user_coll);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if (incl_users)
|
|
|
|
{
|
|
|
|
if (excl_users)
|
|
|
|
{
|
|
|
|
incl_users= excl_users= NULL;
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "INCL_DML_USERS and EXCL_DML_USERS specified"
|
|
|
|
" simultaneously - both set to empty\n");
|
|
|
|
}
|
|
|
|
update_incl_users(NULL, NULL, NULL, &incl_users);
|
|
|
|
}
|
|
|
|
else if (excl_users)
|
|
|
|
{
|
|
|
|
update_excl_users(NULL, NULL, NULL, &excl_users);
|
|
|
|
}
|
|
|
|
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "MariaDB Audit Plugin version %s%s STARTED.\n",
|
|
|
|
PLUGIN_STR_VERSION, PLUGIN_DEBUG_VERSION);
|
|
|
|
|
|
|
|
/* The Query Cache shadows TABLE events if the result is taken from it */
|
|
|
|
/* so we warn users if both Query Cashe and TABLE events enabled. */
|
|
|
|
if (!started_mysql && FILTER(EVENT_TABLE))
|
|
|
|
{
|
2014-03-23 15:44:48 +01:00
|
|
|
ulonglong *qc_size= (ulonglong *) dlsym(RTLD_DEFAULT, "query_cache_size");
|
2014-02-24 20:40:16 +01:00
|
|
|
if (qc_size == NULL || *qc_size != 0)
|
|
|
|
{
|
|
|
|
struct loc_system_variables *g_sys_var=
|
2014-03-23 15:44:48 +01:00
|
|
|
(struct loc_system_variables *) dlsym(RTLD_DEFAULT,
|
|
|
|
"global_system_variables");
|
2014-02-24 20:40:16 +01:00
|
|
|
if (g_sys_var && g_sys_var->query_cache_type != 0)
|
|
|
|
{
|
|
|
|
error_header();
|
2014-03-23 15:44:48 +01:00
|
|
|
fprintf(stderr, "Query cache is enabled with the TABLE events."
|
|
|
|
" Some table reads can be veiled.");
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
ci_disconnect_buffer.header= 10;
|
|
|
|
ci_disconnect_buffer.thread_id= 0;
|
|
|
|
ci_disconnect_buffer.query_id= 0;
|
|
|
|
ci_disconnect_buffer.db_length= 0;
|
|
|
|
ci_disconnect_buffer.user_length= 0;
|
|
|
|
ci_disconnect_buffer.host_length= 0;
|
|
|
|
ci_disconnect_buffer.ip_length= 0;
|
|
|
|
ci_disconnect_buffer.query= empty_str;
|
|
|
|
ci_disconnect_buffer.query_length= 0;
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
if (logging)
|
|
|
|
start_logging();
|
|
|
|
|
2017-02-20 15:22:01 +01:00
|
|
|
init_done= 1;
|
2014-02-24 20:40:16 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int server_audit_init_mysql(void *p)
|
|
|
|
{
|
|
|
|
started_mysql= 1;
|
|
|
|
mode= 1;
|
|
|
|
mode_readonly= 1;
|
|
|
|
return server_audit_init(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int server_audit_deinit(void *p __attribute__((unused)))
|
|
|
|
{
|
2017-02-20 15:22:01 +01:00
|
|
|
if (!init_done)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
init_done= 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
coll_free(&incl_user_coll);
|
|
|
|
coll_free(&excl_user_coll);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
if (output_type == OUTPUT_FILE && logfile)
|
|
|
|
logger_close(logfile);
|
|
|
|
else if (output_type == OUTPUT_SYSLOG)
|
|
|
|
closelog();
|
2015-03-31 10:10:43 +02:00
|
|
|
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_destroy(&lock_operations);
|
2019-06-14 23:02:55 +02:00
|
|
|
flogger_mutex_destroy(&lock_atomic);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "STOPPED\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void rotate_log(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)),
|
|
|
|
const void *save __attribute__((unused)))
|
|
|
|
{
|
|
|
|
if (output_type == OUTPUT_FILE && logfile && *(my_bool*) save)
|
|
|
|
(void) logger_rotate(logfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static struct st_mysql_audit mysql_descriptor =
|
|
|
|
{
|
|
|
|
MYSQL_AUDIT_INTERFACE_VERSION,
|
|
|
|
NULL,
|
|
|
|
auditing,
|
|
|
|
{ MYSQL_AUDIT_GENERAL_CLASSMASK | MYSQL_AUDIT_CONNECTION_CLASSMASK }
|
|
|
|
};
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
mysql_declare_plugin(server_audit)
|
|
|
|
{
|
|
|
|
MYSQL_AUDIT_PLUGIN,
|
|
|
|
&mysql_descriptor,
|
|
|
|
"SERVER_AUDIT",
|
2015-02-08 19:38:19 +01:00
|
|
|
" Alexey Botchkov (MariaDB Corporation)",
|
|
|
|
"Audit the server activity",
|
2014-02-24 20:40:16 +01:00
|
|
|
PLUGIN_LICENSE_GPL,
|
|
|
|
server_audit_init_mysql,
|
|
|
|
server_audit_deinit,
|
|
|
|
PLUGIN_VERSION,
|
|
|
|
audit_status,
|
|
|
|
vars,
|
|
|
|
NULL,
|
|
|
|
0
|
|
|
|
}
|
|
|
|
mysql_declare_plugin_end;
|
|
|
|
|
|
|
|
|
|
|
|
static struct st_mysql_audit maria_descriptor =
|
|
|
|
{
|
|
|
|
MYSQL_AUDIT_INTERFACE_VERSION,
|
|
|
|
NULL,
|
|
|
|
auditing,
|
|
|
|
{ MYSQL_AUDIT_GENERAL_CLASSMASK |
|
|
|
|
MYSQL_AUDIT_TABLE_CLASSMASK |
|
|
|
|
MYSQL_AUDIT_CONNECTION_CLASSMASK }
|
|
|
|
};
|
|
|
|
maria_declare_plugin(server_audit)
|
|
|
|
{
|
|
|
|
MYSQL_AUDIT_PLUGIN,
|
|
|
|
&maria_descriptor,
|
|
|
|
"SERVER_AUDIT",
|
2015-02-08 19:38:19 +01:00
|
|
|
"Alexey Botchkov (MariaDB Corporation)",
|
|
|
|
"Audit the server activity",
|
2014-02-24 20:40:16 +01:00
|
|
|
PLUGIN_LICENSE_GPL,
|
|
|
|
server_audit_init,
|
|
|
|
server_audit_deinit,
|
|
|
|
PLUGIN_VERSION,
|
|
|
|
audit_status,
|
|
|
|
vars,
|
|
|
|
PLUGIN_STR_VERSION,
|
2014-06-13 13:25:32 +02:00
|
|
|
MariaDB_PLUGIN_MATURITY_STABLE
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
maria_declare_plugin_end;
|
|
|
|
|
|
|
|
|
|
|
|
static void mark_always_logged(MYSQL_THD thd)
|
|
|
|
{
|
|
|
|
struct connection_info *cn;
|
2016-01-12 13:29:02 +01:00
|
|
|
if (thd && (cn= get_loc_info(thd)))
|
2014-02-24 20:40:16 +01:00
|
|
|
cn->log_always= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void log_current_query(MYSQL_THD thd)
|
|
|
|
{
|
|
|
|
struct connection_info *cn;
|
2016-01-12 13:29:02 +01:00
|
|
|
if (!thd)
|
2014-02-24 20:40:16 +01:00
|
|
|
return;
|
2016-01-12 13:29:02 +01:00
|
|
|
cn= get_loc_info(thd);
|
2019-05-19 21:50:23 +02:00
|
|
|
if (!ci_needs_setup(cn) && cn->query_length)
|
2014-02-24 20:40:16 +01:00
|
|
|
{
|
2019-04-28 23:25:17 +02:00
|
|
|
cn->log_always= 1;
|
2016-01-12 13:29:02 +01:00
|
|
|
log_statement_ex(cn, cn->query_time, thd_get_thread_id(thd),
|
2019-06-23 18:07:20 +02:00
|
|
|
cn->query, cn->query_length, 0, "QUERY", 0);
|
2019-04-28 23:25:17 +02:00
|
|
|
cn->log_always= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update_file_path(MYSQL_THD thd,
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
2015-03-19 16:46:08 +01:00
|
|
|
char *new_name= (*(char **) save) ? *(char **) save : empty_str;
|
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, 1);
|
2014-02-24 20:40:16 +01:00
|
|
|
error_header();
|
2015-03-19 16:46:08 +01:00
|
|
|
fprintf(stderr, "Log file name was changed to '%s'.\n", new_name);
|
2014-02-24 20:40:16 +01:00
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2019-06-14 23:02:55 +02:00
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
if (logging)
|
|
|
|
log_current_query(thd);
|
|
|
|
|
|
|
|
if (logging && output_type == OUTPUT_FILE)
|
|
|
|
{
|
|
|
|
char *sav_path= file_path;
|
|
|
|
|
2015-03-19 16:46:08 +01:00
|
|
|
file_path= new_name;
|
2014-02-24 20:40:16 +01:00
|
|
|
stop_logging();
|
|
|
|
if (start_logging())
|
|
|
|
{
|
|
|
|
file_path= sav_path;
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "Reverting log filename back to '%s'.\n", file_path);
|
|
|
|
logging= (start_logging() == 0);
|
|
|
|
if (!logging)
|
|
|
|
{
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "Logging was disabled..\n");
|
2018-05-29 23:54:25 +02:00
|
|
|
CLIENT_ERROR(1, "Logging was disabled.", MYF(ME_WARNING));
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
goto exit_func;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-21 09:29:59 +01:00
|
|
|
strncpy(path_buffer, new_name, sizeof(path_buffer)-1);
|
2017-05-17 15:16:24 +02:00
|
|
|
path_buffer[sizeof(path_buffer)-1]= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
file_path= path_buffer;
|
|
|
|
exit_func:
|
2016-01-13 12:24:33 +01:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, -1);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-17 16:09:53 +01:00
|
|
|
static void update_file_rotations(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
|
|
|
rotations= *(unsigned int *) save;
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "Log file rotations was changed to '%d'.\n", rotations);
|
|
|
|
|
|
|
|
if (!logging || output_type != OUTPUT_FILE)
|
|
|
|
return;
|
|
|
|
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2014-03-17 16:09:53 +01:00
|
|
|
logfile->rotations= rotations;
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2014-03-17 16:09:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update_file_rotate_size(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
|
|
|
file_rotate_size= *(unsigned long long *) save;
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "Log file rotate size was changed to '%lld'.\n",
|
|
|
|
file_rotate_size);
|
|
|
|
|
|
|
|
if (!logging || output_type != OUTPUT_FILE)
|
|
|
|
return;
|
|
|
|
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2014-03-17 16:09:53 +01:00
|
|
|
logfile->size_limit= file_rotate_size;
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2014-03-17 16:09:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-04-28 22:11:48 +02:00
|
|
|
static int check_users(void *save, struct st_mysql_value *value,
|
|
|
|
size_t s, const char *name)
|
|
|
|
{
|
|
|
|
const char *users;
|
|
|
|
int len= 0;
|
|
|
|
|
|
|
|
users= value->val_str(value, NULL, &len);
|
|
|
|
if ((size_t) len > s)
|
|
|
|
{
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr,
|
2019-04-29 08:24:59 +02:00
|
|
|
"server_audit_%s_users value can't be longer than %zu characters.\n",
|
|
|
|
name, s);
|
2019-04-28 22:11:48 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
*((const char**)save)= users;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int check_incl_users(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *save, struct st_mysql_value *value)
|
|
|
|
{
|
|
|
|
return check_users(save, value, sizeof(incl_user_buffer), "incl");
|
|
|
|
}
|
|
|
|
|
|
|
|
static int check_excl_users(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *save, struct st_mysql_value *value)
|
|
|
|
{
|
|
|
|
return check_users(save, value, sizeof(excl_user_buffer), "excl");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static void update_incl_users(MYSQL_THD thd,
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
2015-03-19 16:46:08 +01:00
|
|
|
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
|
2019-04-28 22:11:48 +02:00
|
|
|
size_t new_len= strlen(new_users) + 1;
|
2016-01-13 12:24:33 +01:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
mark_always_logged(thd);
|
2019-04-28 22:11:48 +02:00
|
|
|
|
|
|
|
if (new_len > sizeof(incl_user_buffer))
|
|
|
|
new_len= sizeof(incl_user_buffer);
|
|
|
|
|
|
|
|
memcpy(incl_user_buffer, new_users, new_len - 1);
|
|
|
|
incl_user_buffer[new_len - 1]= 0;
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
incl_users= incl_user_buffer;
|
2016-01-12 13:29:02 +01:00
|
|
|
user_coll_fill(&incl_user_coll, incl_users, &excl_user_coll, 1);
|
2014-02-24 20:40:16 +01:00
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "server_audit_incl_users set to '%s'.\n", incl_users);
|
2016-01-13 12:24:33 +01:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update_excl_users(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
2015-03-19 16:46:08 +01:00
|
|
|
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
|
2019-04-28 22:11:48 +02:00
|
|
|
size_t new_len= strlen(new_users) + 1;
|
2016-01-13 12:24:33 +01:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
mark_always_logged(thd);
|
2019-04-28 22:11:48 +02:00
|
|
|
|
|
|
|
if (new_len > sizeof(excl_user_buffer))
|
|
|
|
new_len= sizeof(excl_user_buffer);
|
|
|
|
|
|
|
|
memcpy(excl_user_buffer, new_users, new_len - 1);
|
|
|
|
excl_user_buffer[new_len - 1]= 0;
|
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
excl_users= excl_user_buffer;
|
2016-01-12 13:29:02 +01:00
|
|
|
user_coll_fill(&excl_user_coll, excl_users, &incl_user_coll, 0);
|
2014-02-24 20:40:16 +01:00
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "server_audit_excl_users set to '%s'.\n", excl_users);
|
2016-01-13 12:24:33 +01:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update_output_type(MYSQL_THD thd,
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
|
|
|
ulong new_output_type= *((ulong *) save);
|
|
|
|
if (output_type == new_output_type)
|
|
|
|
return;
|
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, 1);
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
if (logging)
|
|
|
|
{
|
|
|
|
log_current_query(thd);
|
|
|
|
stop_logging();
|
|
|
|
}
|
|
|
|
|
|
|
|
output_type= new_output_type;
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "Output was redirected to '%s'\n",
|
|
|
|
output_type_names[output_type]);
|
|
|
|
|
|
|
|
if (logging)
|
|
|
|
start_logging();
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, -1);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update_syslog_facility(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
|
|
|
ulong new_facility= *((ulong *) save);
|
|
|
|
if (syslog_facility == new_facility)
|
|
|
|
return;
|
|
|
|
|
|
|
|
mark_always_logged(thd);
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "SysLog facility was changed from '%s' to '%s'.\n",
|
|
|
|
syslog_facility_names[syslog_facility],
|
|
|
|
syslog_facility_names[new_facility]);
|
|
|
|
syslog_facility= new_facility;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update_syslog_priority(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
|
|
|
ulong new_priority= *((ulong *) save);
|
|
|
|
if (syslog_priority == new_priority)
|
|
|
|
return;
|
|
|
|
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
mark_always_logged(thd);
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "SysLog priority was changed from '%s' to '%s'.\n",
|
|
|
|
syslog_priority_names[syslog_priority],
|
|
|
|
syslog_priority_names[new_priority]);
|
|
|
|
syslog_priority= new_priority;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update_logging(MYSQL_THD thd,
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
|
|
|
char new_logging= *(char *) save;
|
|
|
|
if (new_logging == logging)
|
|
|
|
return;
|
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, 1);
|
2016-01-13 12:24:33 +01:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
if ((logging= new_logging))
|
|
|
|
{
|
|
|
|
start_logging();
|
|
|
|
if (!logging)
|
|
|
|
{
|
2018-05-29 23:54:25 +02:00
|
|
|
CLIENT_ERROR(1, "Logging was disabled.", MYF(ME_WARNING));
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
2019-05-19 21:50:23 +02:00
|
|
|
mark_always_logged(thd);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
log_current_query(thd);
|
|
|
|
stop_logging();
|
|
|
|
}
|
|
|
|
|
2016-01-13 12:24:33 +01:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, -1);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update_mode(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
|
|
|
unsigned int new_mode= *(unsigned int *) save;
|
|
|
|
if (mode_readonly || new_mode == mode)
|
|
|
|
return;
|
|
|
|
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, 1);
|
2016-01-13 12:24:33 +01:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
mark_always_logged(thd);
|
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode);
|
|
|
|
mode= new_mode;
|
2016-01-13 12:24:33 +01:00
|
|
|
if (!maria_55_started || !debug_server_started)
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2019-06-14 23:02:55 +02:00
|
|
|
ADD_ATOMIC(internal_stop_logging, -1);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
2014-03-17 16:09:53 +01:00
|
|
|
|
2014-02-24 20:40:16 +01:00
|
|
|
static void update_syslog_ident(MYSQL_THD thd __attribute__((unused)),
|
|
|
|
struct st_mysql_sys_var *var __attribute__((unused)),
|
|
|
|
void *var_ptr __attribute__((unused)), const void *save)
|
|
|
|
{
|
2015-03-19 16:46:08 +01:00
|
|
|
char *new_ident= (*(char **) save) ? *(char **) save : empty_str;
|
2019-03-21 09:29:59 +01:00
|
|
|
strncpy(syslog_ident_buffer, new_ident, sizeof(syslog_ident_buffer)-1);
|
2017-05-17 15:16:24 +02:00
|
|
|
syslog_ident_buffer[sizeof(syslog_ident_buffer)-1]= 0;
|
2014-02-24 20:40:16 +01:00
|
|
|
syslog_ident= syslog_ident_buffer;
|
2014-03-17 16:09:53 +01:00
|
|
|
error_header();
|
|
|
|
fprintf(stderr, "SYSYLOG ident was changed to '%s'\n", syslog_ident);
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_wrlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
mark_always_logged(thd);
|
2014-03-17 16:09:53 +01:00
|
|
|
if (logging && output_type == OUTPUT_SYSLOG)
|
|
|
|
{
|
|
|
|
stop_logging();
|
|
|
|
start_logging();
|
|
|
|
}
|
2021-02-25 10:55:08 +01:00
|
|
|
mysql_prlock_unlock(&lock_operations);
|
2014-02-24 20:40:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
struct st_my_thread_var *loc_thread_var(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|
|
|
{
|
|
|
|
if (fdwReason != DLL_PROCESS_ATTACH)
|
|
|
|
return 1;
|
|
|
|
|
MDEV-22214 mariadbd.exe calls function mysqld.exe, and crashes
Stop linking plugins to the server executable on Windows.
Instead, extract whole server functionality into a large DLL, called
server.dll. Link both plugins, and small server "stub" exe to it.
This eliminates plugin dependency on the name of the server executable.
It also reduces the size of the packages (since tiny mysqld.exe
and mariadbd.exe are now both linked to one big DLL)
Also, simplify the functionality of exporing all symbols from selected
static libraries. Rely on WINDOWS_EXPORT_ALL_SYMBOLS, rather than old
self-backed solution.
fix compile error
replace GetProcAddress(GetModuleHandle(NULL), "variable_name")
for server exported data with actual variable names.
Runtime loading was never required,was error prone
, since symbols could be missing at runtime, and now it actually failed,
because we do not export symbols from executable anymore, but from a shared
library
This did require a MYSQL_PLUGIN_IMPORT decoration for the plugin,
but made the code more straightforward, and avoids missing symbols at
runtime (as mentioned before).
The audit plugin is still doing some dynamic loading, as it aims to work
cross-version. Now it won't work cross-version on Windows, as it already
uses some symbols that are *not* dynamically loaded, e.g fn_format
and those symbols now exported from server.dll , when earlier they were
exported by mysqld.exe
Windows, fixes for storage engine plugin loading
after various rebranding stuff
Create server.dll containing functionality of the whole server
make mariadbd.exe/mysqld.exe a stub that is only calling mysqld_main()
fix build
2020-04-10 14:09:18 +02:00
|
|
|
serv_ver= server_version;
|
2015-02-08 19:38:19 +01:00
|
|
|
#else
|
|
|
|
void __attribute__ ((constructor)) audit_plugin_so_init(void)
|
|
|
|
{
|
|
|
|
serv_ver= server_version;
|
|
|
|
#endif /*_WIN32*/
|
|
|
|
|
|
|
|
if (!serv_ver)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
started_mariadb= strstr(serv_ver, "MariaDB") != 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
debug_server_started= strstr(serv_ver, "debug") != 0;
|
2015-02-08 19:38:19 +01:00
|
|
|
|
2016-01-12 13:29:02 +01:00
|
|
|
if (started_mariadb)
|
2015-02-08 19:38:19 +01:00
|
|
|
{
|
2016-01-12 13:29:02 +01:00
|
|
|
if (serv_ver[0] == '1')
|
|
|
|
use_event_data_for_disconnect= 1;
|
|
|
|
else
|
|
|
|
maria_55_started= 1;
|
|
|
|
}
|
|
|
|
else
|
2015-02-08 19:38:19 +01:00
|
|
|
{
|
2016-01-12 13:29:02 +01:00
|
|
|
/* Started MySQL. */
|
2015-02-08 19:38:19 +01:00
|
|
|
if (serv_ver[0] == '5' && serv_ver[2] == '5')
|
|
|
|
{
|
|
|
|
int sc= serv_ver[4] - '0';
|
|
|
|
if (serv_ver[5] >= '0' && serv_ver[5] <= '9')
|
|
|
|
sc= sc * 10 + serv_ver[5] - '0';
|
|
|
|
if (sc <= 10)
|
|
|
|
{
|
|
|
|
mysql_descriptor.interface_version= 0x0200;
|
|
|
|
mysql_descriptor.event_notify= (void *) auditing_v8;
|
|
|
|
}
|
|
|
|
else if (sc < 14)
|
|
|
|
{
|
|
|
|
mysql_descriptor.interface_version= 0x0200;
|
|
|
|
mysql_descriptor.event_notify= (void *) auditing_v13;
|
|
|
|
}
|
|
|
|
}
|
2016-01-12 13:29:02 +01:00
|
|
|
else if (serv_ver[0] == '5' && serv_ver[2] == '6')
|
|
|
|
{
|
|
|
|
int sc= serv_ver[4] - '0';
|
|
|
|
if (serv_ver[5] >= '0' && serv_ver[5] <= '9')
|
|
|
|
sc= sc * 10 + serv_ver[5] - '0';
|
|
|
|
if (sc >= 24)
|
|
|
|
use_event_data_for_disconnect= 1;
|
|
|
|
}
|
2017-02-20 15:22:01 +01:00
|
|
|
else if ((serv_ver[0] == '5' && serv_ver[2] == '7') ||
|
|
|
|
(serv_ver[0] == '8' && serv_ver[2] == '0'))
|
2016-01-12 13:29:02 +01:00
|
|
|
{
|
|
|
|
mysql_57_started= 1;
|
|
|
|
_mysql_plugin_declarations_[0].info= mysql_v4_descriptor;
|
|
|
|
use_event_data_for_disconnect= 1;
|
|
|
|
}
|
2017-02-20 15:22:01 +01:00
|
|
|
MYSQL_SYSVAR_NAME(loc_info).flags= PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL |
|
|
|
|
PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC;
|
2015-02-08 19:38:19 +01:00
|
|
|
}
|
2016-01-12 13:29:02 +01:00
|
|
|
|
|
|
|
memset(locinfo_ini_value, 'O', sizeof(locinfo_ini_value)-1);
|
2016-02-15 12:59:47 +01:00
|
|
|
locinfo_ini_value[sizeof(locinfo_ini_value)-1]= 0;
|
2016-01-12 13:29:02 +01:00
|
|
|
|
2015-02-08 19:38:19 +01:00
|
|
|
exit:
|
|
|
|
#ifdef _WIN32
|
|
|
|
return 1;
|
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|