Merge branch '10.1' into 10.2
Conflicts: VERSION cmake/plugin.cmake config.h.cmake configure.cmake plugin/server_audit/server_audit.c sql/sql_yacc.yy
This commit is contained in:
commit
b2f8d7b410
2
.gitignore
vendored
2
.gitignore
vendored
@ -112,6 +112,8 @@ scripts/wsrep_sst_mysqldump
|
||||
scripts/wsrep_sst_rsync
|
||||
scripts/wsrep_sst_xtrabackup
|
||||
scripts/wsrep_sst_xtrabackup-v2
|
||||
scripts/maria_add_gis_sp.sql
|
||||
scripts/maria_add_gis_sp_bootstrap.sql
|
||||
sql-bench/bench-count-distinct
|
||||
sql-bench/bench-init.pl
|
||||
sql-bench/compare-results
|
||||
|
@ -31,6 +31,7 @@ Usage: $0 [-h|-n] [configure-options]
|
||||
-h, --help Show this help message.
|
||||
-n, --just-print Don't actually run any commands; just print them.
|
||||
-c, --just-configure Stop after running configure.
|
||||
Combined with --just-print shows configure options.
|
||||
--extra-configs=xxx Add this to configure options
|
||||
--extra-flags=xxx Add this C and CXX flags
|
||||
--extra-cflags=xxx Add this to C flags
|
||||
|
@ -4977,12 +4977,13 @@ static int my_kill(int pid, int sig)
|
||||
{
|
||||
#ifdef __WIN__
|
||||
HANDLE proc;
|
||||
if ((proc= OpenProcess(PROCESS_TERMINATE, FALSE, pid)) == NULL)
|
||||
if ((proc= OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid)) == NULL)
|
||||
return -1;
|
||||
if (sig == 0)
|
||||
{
|
||||
DWORD wait_result= WaitForSingleObject(proc, 0);
|
||||
CloseHandle(proc);
|
||||
return 0;
|
||||
return wait_result == WAIT_OBJECT_0?-1:0;
|
||||
}
|
||||
(void)TerminateProcess(proc, 201);
|
||||
CloseHandle(proc);
|
||||
|
@ -86,6 +86,7 @@ SET(ignored
|
||||
"%ignore ${CMAKE_INSTALL_PREFIX}/share/man"
|
||||
"%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man1*"
|
||||
"%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man8*"
|
||||
"%ignore ${CMAKE_INSTALL_PREFIX}/share/pkgconfig"
|
||||
)
|
||||
|
||||
SET(CPACK_RPM_server_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*")
|
||||
|
@ -44,11 +44,10 @@ FUNCTION (INSTALL_DEBUG_SYMBOLS)
|
||||
ENDIF()
|
||||
|
||||
set(comp "")
|
||||
IF(ARG_COMPONENT STREQUAL "Server")
|
||||
IF(target MATCHES "mysqld" OR type MATCHES "MODULE")
|
||||
#MESSAGE("PDB: ${targets}")
|
||||
SET(comp Server)
|
||||
ENDIF()
|
||||
|
||||
IF(target MATCHES "mysqld" OR type MATCHES "MODULE")
|
||||
#MESSAGE("PDB: ${targets}")
|
||||
SET(comp Server)
|
||||
ENDIF()
|
||||
|
||||
IF(NOT comp MATCHES Server)
|
||||
|
@ -87,6 +87,11 @@ MACRO(CREATE_EXPORT_FILE VAR TARGET API_FUNCTIONS)
|
||||
ENDFOREACH()
|
||||
SET(CONTENT "${CONTENT} (void *)0\n}\;")
|
||||
CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS})
|
||||
# Avoid "function redeclared as variable" error
|
||||
# when using gcc/clang option -flto(link time optimization)
|
||||
IF(" ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS} " MATCHES " -flto")
|
||||
SET_SOURCE_FILES_PROPERTIES(${EXPORTS} PROPERTIES COMPILE_FLAGS "-fno-lto")
|
||||
ENDIF()
|
||||
SET(${VAR} ${EXPORTS})
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
@ -56,3 +56,10 @@ ELSEIF(MYSQL_MAINTAINER_MODE MATCHES "AUTO")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MY_MAINTAINER_C_WARNINGS}")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MY_MAINTAINER_CXX_WARNINGS}")
|
||||
ENDIF()
|
||||
|
||||
IF(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
STRING(REPLACE " -E " " -E -dDI " CMAKE_C_CREATE_PREPROCESSED_SOURCE ${CMAKE_C_CREATE_PREPROCESSED_SOURCE})
|
||||
ENDIF()
|
||||
IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
STRING(REPLACE " -E " " -E -dDI " CMAKE_CXX_CREATE_PREPROCESSED_SOURCE ${CMAKE_CXX_CREATE_PREPROCESSED_SOURCE})
|
||||
ENDIF()
|
||||
|
@ -18,6 +18,7 @@ INCLUDE(CMakeParseArguments)
|
||||
|
||||
# MYSQL_ADD_PLUGIN(plugin_name source1...sourceN
|
||||
# [STORAGE_ENGINE]
|
||||
# [CLIENT]
|
||||
# [MANDATORY|DEFAULT]
|
||||
# [STATIC_ONLY|DYNAMIC_ONLY]
|
||||
# [MODULE_OUTPUT_NAME module_name]
|
||||
@ -28,7 +29,7 @@ INCLUDE(CMakeParseArguments)
|
||||
|
||||
MACRO(MYSQL_ADD_PLUGIN)
|
||||
CMAKE_PARSE_ARGUMENTS(ARG
|
||||
"STORAGE_ENGINE;STATIC_ONLY;MODULE_ONLY;MANDATORY;DEFAULT;DISABLED;RECOMPILE_FOR_EMBEDDED"
|
||||
"STORAGE_ENGINE;STATIC_ONLY;MODULE_ONLY;MANDATORY;DEFAULT;DISABLED;RECOMPILE_FOR_EMBEDDED;CLIENT"
|
||||
"MODULE_OUTPUT_NAME;STATIC_OUTPUT_NAME;COMPONENT;CONFIG"
|
||||
"LINK_LIBRARIES;DEPENDENCIES"
|
||||
${ARGN}
|
||||
@ -120,7 +121,7 @@ MACRO(MYSQL_ADD_PLUGIN)
|
||||
|
||||
# Build either static library or module
|
||||
IF (PLUGIN_${plugin} MATCHES "(STATIC|AUTO|YES)" AND NOT ARG_MODULE_ONLY
|
||||
AND NOT ARG_DISABLED)
|
||||
AND NOT ARG_DISABLED AND NOT ARG_CLIENT)
|
||||
|
||||
IF(CMAKE_GENERATOR MATCHES "Makefiles|Ninja")
|
||||
# If there is a shared library from previous shared build,
|
||||
@ -188,14 +189,14 @@ MACRO(MYSQL_ADD_PLUGIN)
|
||||
|
||||
TARGET_LINK_LIBRARIES (${target} mysqlservices ${ARG_LINK_LIBRARIES})
|
||||
|
||||
# Plugin uses symbols defined in mysqld executable.
|
||||
# Server plugins use symbols defined in mysqld executable.
|
||||
# Some operating systems like Windows and OSX and are pretty strict about
|
||||
# unresolved symbols. Others are less strict and allow unresolved symbols
|
||||
# in shared libraries. On Linux for example, CMake does not even add
|
||||
# executable to the linker command line (it would result into link error).
|
||||
# Thus we skip TARGET_LINK_LIBRARIES on Linux, as it would only generate
|
||||
# an additional dependency.
|
||||
IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT ARG_CLIENT)
|
||||
TARGET_LINK_LIBRARIES (${target} mysqld)
|
||||
ENDIF()
|
||||
ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDENCIES})
|
||||
@ -206,19 +207,22 @@ MACRO(MYSQL_ADD_PLUGIN)
|
||||
IF(ARG_COMPONENT)
|
||||
IF(CPACK_COMPONENTS_ALL AND
|
||||
NOT CPACK_COMPONENTS_ALL MATCHES ${ARG_COMPONENT})
|
||||
SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ${ARG_COMPONENT} PARENT_SCOPE)
|
||||
SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB" PARENT_SCOPE)
|
||||
|
||||
IF (NOT ARG_CONFIG)
|
||||
SET(ARG_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${target}.cnf")
|
||||
FILE(WRITE ${ARG_CONFIG} "[mariadb]\nplugin-load-add=${ARG_MODULE_OUTPUT_NAME}.so\n")
|
||||
SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ${ARG_COMPONENT})
|
||||
SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} PARENT_SCOPE)
|
||||
IF (NOT ARG_CLIENT)
|
||||
SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB" PARENT_SCOPE)
|
||||
ENDIF()
|
||||
INSTALL(FILES ${ARG_CONFIG} COMPONENT ${ARG_COMPONENT} DESTINATION ${INSTALL_SYSCONF2DIR})
|
||||
|
||||
# workarounds for cmake issues #13248 and #12864:
|
||||
SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_PROVIDES "cmake_bug_13248" PARENT_SCOPE)
|
||||
SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_OBSOLETES "cmake_bug_13248" PARENT_SCOPE)
|
||||
SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" PARENT_SCOPE)
|
||||
SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} PARENT_SCOPE)
|
||||
IF(NOT ARG_CLIENT AND NOT ARG_CONFIG AND UNIX)
|
||||
SET(ARG_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${target}.cnf")
|
||||
FILE(WRITE ${ARG_CONFIG} "[mariadb]\nplugin-load-add=${ARG_MODULE_OUTPUT_NAME}.so\n")
|
||||
INSTALL(FILES ${ARG_CONFIG} COMPONENT ${ARG_COMPONENT} DESTINATION ${INSTALL_SYSCONF2DIR})
|
||||
SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" PARENT_SCOPE)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(ARG_COMPONENT Server)
|
||||
|
@ -88,6 +88,7 @@
|
||||
#cmakedefine HAVE_SYS_UN_H 1
|
||||
#cmakedefine HAVE_SYS_VADVISE_H 1
|
||||
#cmakedefine HAVE_SYS_STATVFS_H 1
|
||||
#cmakedefine HAVE_UCONTEXT_H 1
|
||||
#cmakedefine HAVE_TERM_H 1
|
||||
#cmakedefine HAVE_TERMBITS_H 1
|
||||
#cmakedefine HAVE_TERMIOS_H 1
|
||||
@ -237,6 +238,7 @@
|
||||
#cmakedefine HAVE_TIME 1
|
||||
#cmakedefine HAVE_TIMES 1
|
||||
#cmakedefine HAVE_UCONTEXT 1
|
||||
#cmakedefine HAVE_VALLOC 1
|
||||
#cmakedefine HAVE_VIDATTR 1
|
||||
#define HAVE_VIO_READ_BUFF 1
|
||||
#cmakedefine HAVE_VASPRINTF 1
|
||||
|
@ -977,6 +977,14 @@ CHECK_STRUCT_HAS_MEMBER("struct sockaddr_in6" sin6_len
|
||||
|
||||
SET(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
|
||||
CHECK_STRUCT_HAS_MEMBER("struct dirent" d_ino "dirent.h" STRUCT_DIRENT_HAS_D_INO)
|
||||
CHECK_STRUCT_HAS_MEMBER("struct dirent" d_namlen "dirent.h" STRUCT_DIRENT_HAS_D_NAMLEN)
|
||||
SET(SPRINTF_RETURNS_INT 1)
|
||||
CHECK_INCLUDE_FILE(ucontext.h HAVE_UCONTEXT_H)
|
||||
IF(NOT HAVE_UCONTEXT_H)
|
||||
CHECK_INCLUDE_FILE(sys/ucontext.h HAVE_UCONTEXT_H)
|
||||
ENDIF()
|
||||
|
||||
CHECK_STRUCT_HAS_MEMBER("struct timespec" tv_sec "time.h" STRUCT_TIMESPEC_HAS_TV_SEC)
|
||||
CHECK_STRUCT_HAS_MEMBER("struct timespec" tv_nsec "time.h" STRUCT_TIMESPEC_HAS_TV_NSEC)
|
||||
|
||||
@ -997,4 +1005,3 @@ IF(NOT MSVC)
|
||||
HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
|
3
debian/mariadb-server-10.2.files.in
vendored
3
debian/mariadb-server-10.2.files.in
vendored
@ -6,6 +6,7 @@ usr/lib/mysql/plugin/ha_blackhole.so
|
||||
usr/lib/mysql/plugin/ha_federated.so
|
||||
usr/lib/mysql/plugin/ha_federatedx.so
|
||||
usr/lib/mysql/plugin/ha_innodb.so
|
||||
usr/lib/mysql/plugin/ha_mroonga.so
|
||||
usr/lib/mysql/plugin/ha_sphinx.so
|
||||
usr/lib/mysql/plugin/handlersocket.so
|
||||
usr/lib/mysql/plugin/locales.so
|
||||
@ -83,6 +84,8 @@ usr/share/mysql/echo_stderr
|
||||
usr/share/mysql/errmsg-utf8.txt
|
||||
usr/share/mysql/fill_help_tables.sql
|
||||
usr/share/mysql/maria_add_gis_sp_bootstrap.sql
|
||||
usr/share/mysql/mroonga/install.sql
|
||||
usr/share/mysql/mroonga/uninstall.sql
|
||||
usr/share/mysql/mysql_system_tables_data.sql
|
||||
usr/share/mysql/mysql_system_tables.sql
|
||||
usr/share/mysql/mysql_performance_tables.sql
|
||||
|
@ -694,14 +694,14 @@ int main(int argc, char **argv)
|
||||
if (*filename == '\0')
|
||||
{
|
||||
fprintf(stderr, "Error; File name missing\n");
|
||||
goto error;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
/* stat the file to get size and page count */
|
||||
if (stat(filename, &st))
|
||||
{
|
||||
fprintf(stderr, "Error; %s cannot be found\n", filename);
|
||||
goto error;
|
||||
goto error_out;
|
||||
}
|
||||
size= st.st_size;
|
||||
|
||||
@ -711,7 +711,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
fprintf(stderr, "Error; %s cannot be opened", filename);
|
||||
perror(" ");
|
||||
goto error;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
big_buf = (unsigned char *)malloc(2 * UNIV_PAGE_SIZE_MAX);
|
||||
@ -719,7 +719,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
fprintf(stderr, "Error; failed to allocate memory\n");
|
||||
perror("");
|
||||
goto error;
|
||||
goto error_f;
|
||||
}
|
||||
|
||||
/* Make sure the page is aligned */
|
||||
@ -731,7 +731,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
fprintf(stderr, "Error; failed to allocate memory\n");
|
||||
perror("");
|
||||
return 1;
|
||||
goto error_big_buf;
|
||||
}
|
||||
|
||||
/* Make sure the page is aligned */
|
||||
@ -983,12 +983,17 @@ ok:
|
||||
print_stats();
|
||||
free(big_xdes);
|
||||
free(big_buf);
|
||||
fclose(f);
|
||||
my_end(0);
|
||||
exit(0);
|
||||
|
||||
error:
|
||||
free(big_xdes);
|
||||
error_big_buf:
|
||||
free(big_buf);
|
||||
error_f:
|
||||
fclose(f);
|
||||
error_out:
|
||||
my_end(0);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
#define MY_CONTEXT_USE_X86_64_GCC_ASM
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__)
|
||||
#define MY_CONTEXT_USE_I386_GCC_ASM
|
||||
#elif defined(HAVE_UCONTEXT)
|
||||
#elif defined(HAVE_UCONTEXT_H)
|
||||
#define MY_CONTEXT_USE_UCONTEXT
|
||||
#else
|
||||
#define MY_CONTEXT_DISABLE
|
||||
|
@ -694,7 +694,7 @@ extern void my_mutex_end(void);
|
||||
We need to have at least 256K stack to handle calls to myisamchk_init()
|
||||
with the current number of keys and key parts.
|
||||
*/
|
||||
#define DEFAULT_THREAD_STACK (288*1024L)
|
||||
#define DEFAULT_THREAD_STACK (289*1024L)
|
||||
#endif
|
||||
|
||||
#define MY_PTHREAD_LOCK_READ 0
|
||||
|
@ -208,7 +208,7 @@ void vio_end(void);
|
||||
|
||||
/* shutdown(2) flags */
|
||||
#ifndef SHUT_RD
|
||||
#define SHUT_RD SD_BOTH
|
||||
#define SHUT_RD SD_RECEIVE
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -45,7 +45,13 @@ drop table t1;
|
||||
connection slave;
|
||||
flush tables with read lock;
|
||||
start slave;
|
||||
source include/wait_for_slave_to_start.inc;
|
||||
|
||||
# The IO thread will not be able to read the GTID because of flush tables
|
||||
let $slave_param= Slave_IO_Running;
|
||||
let $slave_param_value= Preparing;
|
||||
source include/wait_for_slave_param.inc;
|
||||
|
||||
--source include/wait_for_slave_sql_to_start.inc
|
||||
--error 1192
|
||||
stop slave;
|
||||
|
||||
|
@ -34,9 +34,11 @@ create table t1 (a mediumtext, fulltext key key1(a)) charset utf8 collate utf8_g
|
||||
insert into t1 values ('hello');
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'a'
|
||||
test.t1 analyze status OK
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'a'
|
||||
test.t1 analyze status Table is already up to date
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (a int);
|
||||
|
10
mysql-test/r/auth_named_pipe.result
Normal file
10
mysql-test/r/auth_named_pipe.result
Normal file
@ -0,0 +1,10 @@
|
||||
INSTALL SONAME 'auth_named_pipe';
|
||||
CREATE USER 'USERNAME' IDENTIFIED WITH named_pipe;
|
||||
SELECT USER(),CURRENT_USER();
|
||||
USER() CURRENT_USER()
|
||||
USERNAME@localhost USERNAME@%
|
||||
DROP USER 'USERNAME';
|
||||
CREATE USER nosuchuser IDENTIFIED WITH named_pipe;
|
||||
ERROR 28000: Access denied for user 'nosuchuser'@'localhost'
|
||||
DROP USER nosuchuser;
|
||||
UNINSTALL SONAME 'auth_named_pipe';
|
@ -162,3 +162,10 @@ a
|
||||
begin not atomic select a from t1 having a > 1; end|
|
||||
a
|
||||
drop table t1|
|
||||
#
|
||||
# MDEV-8615: Assertion `m_cpp_buf <= begin_ptr &&
|
||||
# begin_ptr <= m_cpp_buf + m_buf_length' failed in
|
||||
# Lex_input_stream::body_utf8_start
|
||||
#
|
||||
b'|
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'b'' at line 1
|
||||
|
@ -5365,14 +5365,17 @@ DROP TABLE t1;
|
||||
SET sql_mode=default;
|
||||
#
|
||||
# Bug#57687 crash when reporting duplicate group_key error and utf8
|
||||
# Make sure to modify this when Bug#58081 is fixed.
|
||||
# Bug#58081 Duplicate entry error when doing GROUP BY
|
||||
# MDEV-9332 Bug after upgrade to 10.1.10
|
||||
#
|
||||
SET NAMES utf8;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (0), (0), (1), (0), (0);
|
||||
SELECT COUNT(*) FROM t1, t1 t2
|
||||
GROUP BY INSERT('', t2.a, t1.a, (@@global.max_binlog_size));
|
||||
ERROR 23000: Duplicate entry '107374182410737418241' for key 'group_key'
|
||||
COUNT(*)
|
||||
20
|
||||
5
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#11764503 (Bug#57341) Query in EXPLAIN EXTENDED shows wrong characters
|
||||
|
@ -2,10 +2,10 @@ set sql_mode="";
|
||||
drop database if exists events_test;
|
||||
create database events_test;
|
||||
use events_test;
|
||||
create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
|
||||
create event e_26 on schedule at '2027-01-01 00:00:00' disable do set @a = 5;
|
||||
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
|
||||
db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion
|
||||
events_test e_26 set @a = 5 root@localhost 2017-01-01 00:00:00 DROP
|
||||
events_test e_26 set @a = 5 root@localhost 2027-01-01 00:00:00 DROP
|
||||
drop event e_26;
|
||||
create event e_26 on schedule at NULL disable do set @a = 5;
|
||||
ERROR HY000: Incorrect AT value: 'NULL'
|
||||
|
@ -91,7 +91,7 @@ create table events_smode_test(ev_name char(10), a date);
|
||||
"This should never insert something"
|
||||
create event ee_16407_2 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_2', 60) /*ee_16407_2*/;
|
||||
select get_lock('ee_16407_2', 60); /*ee_16407_2*/
|
||||
select release_lock('ee_16407_2');
|
||||
insert into events_test.events_smode_test values('ee_16407_2','1980-19-02');
|
||||
end|
|
||||
@ -100,7 +100,7 @@ ERROR 22007: Incorrect date value: '1980-19-02' for column 'a' at row 1
|
||||
"This is ok"
|
||||
create event ee_16407_3 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_2', 60) /*ee_16407_3*/;
|
||||
select get_lock('ee_16407_2', 60); /*ee_16407_3*/
|
||||
select release_lock('ee_16407_2');
|
||||
insert into events_test.events_smode_test values ('ee_16407_3','1980-02-19');
|
||||
insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29');
|
||||
@ -109,7 +109,7 @@ set sql_mode=""|
|
||||
"This will insert rows but they will be truncated"
|
||||
create event ee_16407_4 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_2', 60) /*ee_16407_4*/;
|
||||
select get_lock('ee_16407_2', 60); /*ee_16407_4*/
|
||||
select release_lock('ee_16407_2');
|
||||
insert into events_test.events_smode_test values ('ee_16407_4','10-11-1956');
|
||||
end|
|
||||
@ -157,13 +157,13 @@ create procedure ee_16407_5_pendant() begin insert into events_test.events_smode
|
||||
create procedure ee_16407_6_pendant() begin insert into events_test.events_smode_test values('ee_16407_6','2004-02-29'); end|
|
||||
create event ee_16407_5 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_5', 60) /*ee_16407_5*/;
|
||||
select get_lock('ee_16407_5', 60); /*ee_16407_5*/
|
||||
select release_lock('ee_16407_5');
|
||||
call events_test.ee_16407_5_pendant();
|
||||
end|
|
||||
create event ee_16407_6 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_5', 60) /*ee_16407_6*/;
|
||||
select get_lock('ee_16407_5', 60); /*ee_16407_6*/
|
||||
select release_lock('ee_16407_5');
|
||||
call events_test.ee_16407_6_pendant();
|
||||
end|
|
||||
|
@ -4571,5 +4571,17 @@ Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 18446744073709551615) and (format(`test`.`t1`.`a`,0) = '18,446,744,073,709,551,615'))
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#58081 Duplicate entry error when doing GROUP BY
|
||||
# MDEV-9332 Bug after upgrade to 10.1.10
|
||||
#
|
||||
SET NAMES latin1;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (0),(0),(1),(0),(0);
|
||||
SELECT COUNT(*) FROM t1, t1 t2 GROUP BY INSERT('', t2.a, t1.a, @@global.max_binlog_size);
|
||||
COUNT(*)
|
||||
20
|
||||
5
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.1 tests
|
||||
#
|
||||
|
@ -7,19 +7,34 @@ mtr.test_suppressions OK
|
||||
mysql.column_stats OK
|
||||
mysql.columns_priv OK
|
||||
mysql.db OK
|
||||
mysql.event OK
|
||||
mysql.event
|
||||
Warning : Engine-independent statistics are not collected for column 'body'
|
||||
Warning : Engine-independent statistics are not collected for column 'body_utf8'
|
||||
status : OK
|
||||
mysql.func OK
|
||||
mysql.gtid_slave_pos OK
|
||||
mysql.help_category OK
|
||||
mysql.help_category
|
||||
Warning : Engine-independent statistics are not collected for column 'url'
|
||||
status : OK
|
||||
mysql.help_keyword OK
|
||||
mysql.help_relation OK
|
||||
mysql.help_topic OK
|
||||
mysql.help_topic
|
||||
Warning : Engine-independent statistics are not collected for column 'description'
|
||||
Warning : Engine-independent statistics are not collected for column 'example'
|
||||
Warning : Engine-independent statistics are not collected for column 'url'
|
||||
status : OK
|
||||
mysql.host OK
|
||||
mysql.index_stats OK
|
||||
mysql.innodb_index_stats OK
|
||||
mysql.innodb_table_stats OK
|
||||
mysql.plugin OK
|
||||
mysql.proc OK
|
||||
mysql.proc
|
||||
Warning : Engine-independent statistics are not collected for column 'param_list'
|
||||
Warning : Engine-independent statistics are not collected for column 'returns'
|
||||
Warning : Engine-independent statistics are not collected for column 'body'
|
||||
Warning : Engine-independent statistics are not collected for column 'comment'
|
||||
Warning : Engine-independent statistics are not collected for column 'body_utf8'
|
||||
status : OK
|
||||
mysql.procs_priv OK
|
||||
mysql.proxies_priv OK
|
||||
mysql.roles_mapping OK
|
||||
@ -31,7 +46,12 @@ mysql.time_zone_leap_second OK
|
||||
mysql.time_zone_name OK
|
||||
mysql.time_zone_transition OK
|
||||
mysql.time_zone_transition_type OK
|
||||
mysql.user OK
|
||||
mysql.user
|
||||
Warning : Engine-independent statistics are not collected for column 'ssl_cipher'
|
||||
Warning : Engine-independent statistics are not collected for column 'x509_issuer'
|
||||
Warning : Engine-independent statistics are not collected for column 'x509_subject'
|
||||
Warning : Engine-independent statistics are not collected for column 'authentication_string'
|
||||
status : OK
|
||||
mtr.global_suppressions Table is already up to date
|
||||
mtr.test_suppressions Table is already up to date
|
||||
mysql.column_stats OK
|
||||
@ -69,19 +89,34 @@ mysql.user OK
|
||||
mysql.column_stats OK
|
||||
mysql.columns_priv OK
|
||||
mysql.db OK
|
||||
mysql.event OK
|
||||
mysql.event
|
||||
Warning : Engine-independent statistics are not collected for column 'body'
|
||||
Warning : Engine-independent statistics are not collected for column 'body_utf8'
|
||||
status : OK
|
||||
mysql.func OK
|
||||
mysql.gtid_slave_pos OK
|
||||
mysql.help_category OK
|
||||
mysql.help_category
|
||||
Warning : Engine-independent statistics are not collected for column 'url'
|
||||
status : OK
|
||||
mysql.help_keyword OK
|
||||
mysql.help_relation OK
|
||||
mysql.help_topic OK
|
||||
mysql.help_topic
|
||||
Warning : Engine-independent statistics are not collected for column 'description'
|
||||
Warning : Engine-independent statistics are not collected for column 'example'
|
||||
Warning : Engine-independent statistics are not collected for column 'url'
|
||||
status : OK
|
||||
mysql.host OK
|
||||
mysql.index_stats OK
|
||||
mysql.innodb_index_stats OK
|
||||
mysql.innodb_table_stats OK
|
||||
mysql.plugin OK
|
||||
mysql.proc OK
|
||||
mysql.proc
|
||||
Warning : Engine-independent statistics are not collected for column 'param_list'
|
||||
Warning : Engine-independent statistics are not collected for column 'returns'
|
||||
Warning : Engine-independent statistics are not collected for column 'body'
|
||||
Warning : Engine-independent statistics are not collected for column 'comment'
|
||||
Warning : Engine-independent statistics are not collected for column 'body_utf8'
|
||||
status : OK
|
||||
mysql.procs_priv OK
|
||||
mysql.proxies_priv OK
|
||||
mysql.roles_mapping OK
|
||||
@ -93,7 +128,12 @@ mysql.time_zone_leap_second OK
|
||||
mysql.time_zone_name OK
|
||||
mysql.time_zone_transition OK
|
||||
mysql.time_zone_transition_type OK
|
||||
mysql.user OK
|
||||
mysql.user
|
||||
Warning : Engine-independent statistics are not collected for column 'ssl_cipher'
|
||||
Warning : Engine-independent statistics are not collected for column 'x509_issuer'
|
||||
Warning : Engine-independent statistics are not collected for column 'x509_subject'
|
||||
Warning : Engine-independent statistics are not collected for column 'authentication_string'
|
||||
status : OK
|
||||
mysql.column_stats Table is already up to date
|
||||
mysql.columns_priv Table is already up to date
|
||||
mysql.db Table is already up to date
|
||||
|
@ -133,6 +133,6 @@
|
||||
-thread-pool-oversubscribe 3
|
||||
-thread-pool-stall-limit 500
|
||||
+thread-pool-min-threads 1
|
||||
thread-stack 294912
|
||||
thread-stack 295936
|
||||
time-format %H:%i:%s
|
||||
timed-mutexes FALSE
|
||||
|
@ -1431,7 +1431,7 @@ thread-pool-idle-timeout 60
|
||||
thread-pool-max-threads 1000
|
||||
thread-pool-oversubscribe 3
|
||||
thread-pool-stall-limit 500
|
||||
thread-stack 294912
|
||||
thread-stack 295936
|
||||
time-format %H:%i:%s
|
||||
timed-mutexes FALSE
|
||||
tmp-table-size 16777216
|
||||
|
@ -1465,5 +1465,65 @@ Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 2020) and ((case when 2020 = 2010 then NULL else `test`.`t1`.`a` end) = concat('2020',rand())))
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-9181 (NULLIF(count(table.col)), 0) gives wrong result on 10.1.x
|
||||
#
|
||||
CREATE TABLE t1 (c1 varchar(50) DEFAULT NULL);
|
||||
INSERT INTO t1 (c1) VALUES ('hello'), ('hello\r\n'), ('hello'),('hello');
|
||||
SELECT NULLIF(COUNT(c1),0) FROM t1;
|
||||
NULLIF(COUNT(c1),0)
|
||||
4
|
||||
SELECT CASE WHEN COUNT(c1)=0 THEN NULL ELSE COUNT(c1) END FROM t1;
|
||||
CASE WHEN COUNT(c1)=0 THEN NULL ELSE COUNT(c1) END
|
||||
4
|
||||
SELECT NULLIF(COUNT(c1)+0,0) AS c1,NULLIF(CAST(COUNT(c1) AS SIGNED),0) AS c2,NULLIF(CONCAT(COUNT(c1)),0) AS c3 FROM t1;
|
||||
c1 c2 c3
|
||||
4 4 4
|
||||
SELECT NULLIF(COUNT(DISTINCT c1),0) FROM t1;
|
||||
NULLIF(COUNT(DISTINCT c1),0)
|
||||
2
|
||||
SELECT CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END FROM t1;
|
||||
CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END
|
||||
2
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL,
|
||||
c1 INT DEFAULT NULL
|
||||
);
|
||||
INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(2,4);
|
||||
SELECT NULLIF(COUNT(c1),0) AS c1,NULLIF(COUNT(c1)+0,0) AS c1_wrapped,CASE WHEN COUNT(c1) IS NULL THEN 0 ELSE COUNT(c1) END AS c1_case FROM t1 GROUP BY id;
|
||||
c1 c1_wrapped c1_case
|
||||
2 2 2
|
||||
2 2 2
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1),(2),(3);
|
||||
SET @a=0;
|
||||
SELECT NULLIF(LAST_VALUE(@a:=@a+1,a),0) FROM t1;
|
||||
NULLIF(LAST_VALUE(@a:=@a+1,a),0)
|
||||
1
|
||||
2
|
||||
3
|
||||
SELECT @a;
|
||||
@a
|
||||
6
|
||||
SET @a=0;
|
||||
SELECT NULLIF(AVG(a),0), NULLIF(AVG(LAST_VALUE(@a:=@a+1,a)),0) FROM t1;
|
||||
NULLIF(AVG(a),0) NULLIF(AVG(LAST_VALUE(@a:=@a+1,a)),0)
|
||||
2.0000 2.0000
|
||||
SELECT @a;
|
||||
@a
|
||||
3
|
||||
EXPLAIN EXTENDED SELECT NULLIF(a,0) FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
|
||||
Warnings:
|
||||
Note 1003 select nullif(`test`.`t1`.`a`,0) AS `NULLIF(a,0)` from `test`.`t1`
|
||||
EXPLAIN EXTENDED SELECT NULLIF(AVG(a),0) FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
|
||||
Warnings:
|
||||
Note 1003 select nullif(<cache>(avg(`test`.`t1`.`a`)),0) AS `NULLIF(AVG(a),0)` from `test`.`t1`
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.1 tests
|
||||
#
|
||||
|
@ -11,3 +11,40 @@ a b c d
|
||||
8 NULL 9 NULL
|
||||
8 NULL 10 NULL
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-9457: Poor query plan chosen for ORDER BY query by a recent 10.1
|
||||
#
|
||||
create table t0 (a int);
|
||||
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
create table t1 (
|
||||
pk int primary key,
|
||||
key1 int,
|
||||
key2 int,
|
||||
col1 char(255),
|
||||
key(key1),
|
||||
key(key2)
|
||||
) engine=innodb;
|
||||
set @a=-1;
|
||||
insert into t1
|
||||
select
|
||||
@a:=@a+1,
|
||||
@a,
|
||||
@a,
|
||||
repeat('abcd', 63)
|
||||
from t0 A, t0 B, t0 C, t0 D;
|
||||
# The following must NOT use 'index' on PK.
|
||||
# It should use index_merge(key1,key2) + filesort
|
||||
explain
|
||||
select *
|
||||
from t1
|
||||
where key1<3 or key2<3
|
||||
order by pk;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using sort_union(key1,key2); Using where; Using filesort
|
||||
explain
|
||||
select *
|
||||
from t1
|
||||
where key1<3 or key2<3;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using sort_union(key1,key2); Using where
|
||||
drop table t0, t1;
|
||||
|
@ -3466,3 +3466,21 @@ id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t2 p_1000 ref PRIMARY PRIMARY 8 const 2 Using index
|
||||
1 PRIMARY t1 p_1000 ALL PRIMARY NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
|
||||
drop table t1,t2;
|
||||
#
|
||||
# MDEV-9505: Valgrind failure in SEL_ARG::store_min,find_used_partitions,...
|
||||
#
|
||||
create table t1 (a int, b char(10), c varchar(5), d int)
|
||||
partition by range columns(a,b,c)
|
||||
subpartition by key (c,d)
|
||||
subpartitions 3
|
||||
( partition p0 values less than (1,'abc','abc'),
|
||||
partition p1 values less than (2,'abc','abc'),
|
||||
partition p2 values less than (3,'abc','abc'),
|
||||
partition p3 values less than (4,'abc','abc')
|
||||
);
|
||||
insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3);
|
||||
select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) OR
|
||||
(a = 1 AND b >= 'a' AND (c = 'c' OR (c = 'd' AND d = 2))));
|
||||
a b c d
|
||||
1 a b 1
|
||||
drop table t1;
|
||||
|
@ -1212,6 +1212,7 @@ test t2 PRIMARY 1 1.0000
|
||||
ANALYZE TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'b'
|
||||
test.t1 analyze status OK
|
||||
SELECT * FROM mysql.column_stats;
|
||||
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
|
||||
@ -1225,7 +1226,6 @@ test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
|
||||
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
|
||||
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
|
||||
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
|
||||
test t1 b NULL NULL 0.2000 17.1250 NULL NULL NULL NULL
|
||||
SELECT * FROM mysql.index_stats;
|
||||
db_name table_name index_name prefix_arity avg_frequency
|
||||
test t1 idx2 1 7.0000
|
||||
@ -1265,6 +1265,7 @@ set use_stat_tables='never';
|
||||
ANALYZE TABLE t1 PERSISTENT FOR ALL;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'b'
|
||||
test.t1 analyze status Table is already up to date
|
||||
SELECT * FROM mysql.table_stats;
|
||||
db_name table_name cardinality
|
||||
@ -1276,7 +1277,6 @@ test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
|
||||
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
|
||||
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
|
||||
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
|
||||
test t1 b NULL NULL 0.2000 17.1250 NULL NULL NULL NULL
|
||||
SELECT * FROM mysql.index_stats;
|
||||
db_name table_name index_name prefix_arity avg_frequency
|
||||
test t1 PRIMARY 1 1.0000
|
||||
@ -1291,6 +1291,28 @@ test t1 idx4 3 NULL
|
||||
DELETE FROM mysql.table_stats;
|
||||
DELETE FROM mysql.column_stats;
|
||||
DELETE FROM mysql.index_stats;
|
||||
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES();
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'b'
|
||||
test.t1 analyze status Table is already up to date
|
||||
ANALYZE TABLE t1 PERSISTENT FOR columns(a,b) INDEXES();
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'b'
|
||||
test.t1 analyze status Table is already up to date
|
||||
ANALYZE TABLE t1 PERSISTENT FOR columns(b) indexes(idx2);
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'b'
|
||||
test.t1 analyze status Table is already up to date
|
||||
ANALYZE TABLE t1 PERSISTENT FOR columns() indexes(idx2);
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
DELETE FROM mysql.table_stats;
|
||||
DELETE FROM mysql.column_stats;
|
||||
DELETE FROM mysql.index_stats;
|
||||
DROP TABLE t1,t2;
|
||||
set names utf8;
|
||||
CREATE DATABASE world;
|
||||
|
@ -3,6 +3,7 @@ INSERT INTO t1 VALUES (unhex('3E0D0A4141414142334E7A6143317963324541414141424977
|
||||
ANALYZE TABLE t1 PERSISTENT FOR ALL;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'a'
|
||||
test.t1 analyze status OK
|
||||
SELECT * FROM mysql.index_stats WHERE index_name='a' AND table_name='t1';
|
||||
db_name table_name index_name prefix_arity avg_frequency
|
||||
@ -13,6 +14,7 @@ INSERT INTO t1 VALUES (unhex('3E0D0A4141414142334E7A6143317963324541414141424977
|
||||
ANALYZE TABLE t1 PERSISTENT FOR ALL;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'a'
|
||||
test.t1 analyze status OK
|
||||
SELECT * FROM mysql.index_stats WHERE index_name='a' AND table_name='t1';
|
||||
db_name table_name index_name prefix_arity avg_frequency
|
||||
|
@ -309,3 +309,16 @@ a b c
|
||||
1 1 1
|
||||
2 5 3
|
||||
drop table t1;
|
||||
set session sql_mode ='no_auto_value_on_zero';
|
||||
create table t1 (id int unsigned auto_increment primary key);
|
||||
insert t1 values (0);
|
||||
select * from t1;
|
||||
id
|
||||
0
|
||||
delete from t1;
|
||||
create trigger t1_bi before insert on t1 for each row begin end;
|
||||
insert t1 values (0);
|
||||
select * from t1;
|
||||
id
|
||||
0
|
||||
drop table t1;
|
||||
|
@ -36,6 +36,7 @@ count
|
||||
2
|
||||
ANALYZE TABLE articles;
|
||||
Table Op Msg_type Msg_text
|
||||
test.articles analyze Warning Engine-independent statistics are not collected for column 'body'
|
||||
test.articles analyze status OK
|
||||
SELECT * FROM articles WHERE MATCH (title,body)
|
||||
AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
|
||||
|
@ -247,6 +247,7 @@ articles CREATE TABLE `articles` (
|
||||
ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body);
|
||||
ANALYZE TABLE articles;
|
||||
Table Op Msg_type Msg_text
|
||||
test.articles analyze Warning Engine-independent statistics are not collected for column 'body'
|
||||
test.articles analyze status OK
|
||||
SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will");
|
||||
id title body
|
||||
@ -569,6 +570,7 @@ select @@innodb_ft_enable_stopword;
|
||||
1
|
||||
ANALYZE TABLE articles;
|
||||
Table Op Msg_type Msg_text
|
||||
test.articles analyze Warning Engine-independent statistics are not collected for column 'body'
|
||||
test.articles analyze status OK
|
||||
SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will");
|
||||
id title body
|
||||
|
@ -122,9 +122,11 @@ a left(b,40)
|
||||
1 1abcdefghijklmnopqrstuvwxyzAAAAAAAAAAAAA
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
mysqltest_innodb_zip.t1 analyze Warning Engine-independent statistics are not collected for column 'b'
|
||||
mysqltest_innodb_zip.t1 analyze status OK
|
||||
analyze table t2;
|
||||
Table Op Msg_type Msg_text
|
||||
mysqltest_innodb_zip.t2 analyze Warning Engine-independent statistics are not collected for column 'b'
|
||||
mysqltest_innodb_zip.t2 analyze status OK
|
||||
SELECT table_schema, table_name, row_format, data_length, index_length FROM information_schema.tables WHERE engine='innodb' AND table_schema != 'mysql';
|
||||
table_schema table_name row_format data_length index_length
|
||||
|
16
mysql-test/suite/maria/encrypt-wrong-key.result
Normal file
16
mysql-test/suite/maria/encrypt-wrong-key.result
Normal file
@ -0,0 +1,16 @@
|
||||
call mtr.add_suppression("file_key_management");
|
||||
call mtr.add_suppression("System key id 1 is missing");
|
||||
call mtr.add_suppression("Unknown key id 1");
|
||||
call mtr.add_suppression("Failed to decrypt");
|
||||
CREATE TABLE t1 (i INT, KEY(i)) ENGINE=Aria;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
repair table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair info Wrong CRC on datapage at 1
|
||||
test.t1 repair warning Number of rows changed from 1 to 0
|
||||
test.t1 repair status OK
|
||||
INSERT INTO t1 VALUES (2);
|
||||
select * from t1;
|
||||
ERROR HY000: failed to decrypt './test/t1' rc: -1 dstlen: 0 size: 8172
|
||||
|
||||
drop table t1;
|
54
mysql-test/suite/maria/encrypt-wrong-key.test
Normal file
54
mysql-test/suite/maria/encrypt-wrong-key.test
Normal file
@ -0,0 +1,54 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
#
|
||||
# Test what happens if one removes a decryption key for Aria
|
||||
#
|
||||
|
||||
call mtr.add_suppression("file_key_management");
|
||||
call mtr.add_suppression("System key id 1 is missing");
|
||||
call mtr.add_suppression("Unknown key id 1");
|
||||
call mtr.add_suppression("Failed to decrypt");
|
||||
|
||||
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--shutdown_server
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--write_file $MYSQLTEST_VARDIR/keys1.txt
|
||||
1;770A8A65DA156D24EE2A093277530142
|
||||
EOF
|
||||
|
||||
--exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
CREATE TABLE t1 (i INT, KEY(i)) ENGINE=Aria;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
|
||||
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--shutdown_server
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--write_file $MYSQLTEST_VARDIR/keys2.txt
|
||||
2;770A8A65DA156D24EE2A093277530143
|
||||
EOF
|
||||
|
||||
--exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys2.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
repair table t1;
|
||||
|
||||
INSERT INTO t1 VALUES (2);
|
||||
|
||||
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--shutdown_server
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
--replace_result \\ /
|
||||
--error 192
|
||||
select * from t1;
|
||||
drop table t1;
|
@ -322,6 +322,7 @@ FLUSH TABLES;
|
||||
# replacing p6 with a crashed MYD file (1) (splitted dynamic record)
|
||||
ANALYZE TABLE t1_will_crash;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1_will_crash analyze Warning Engine-independent statistics are not collected for column 'c'
|
||||
test.t1_will_crash analyze status OK
|
||||
OPTIMIZE TABLE t1_will_crash;
|
||||
Table Op Msg_type Msg_text
|
||||
|
@ -8,6 +8,7 @@ server_audit_file_rotate_now OFF
|
||||
server_audit_file_rotate_size 1000000
|
||||
server_audit_file_rotations 9
|
||||
server_audit_incl_users
|
||||
server_audit_loc_info
|
||||
server_audit_logging OFF
|
||||
server_audit_mode 0
|
||||
server_audit_output_type file
|
||||
@ -71,6 +72,7 @@ server_audit_file_rotate_now OFF
|
||||
server_audit_file_rotate_size 1000000
|
||||
server_audit_file_rotations 9
|
||||
server_audit_incl_users odin, root, dva, tri
|
||||
server_audit_loc_info
|
||||
server_audit_logging ON
|
||||
server_audit_mode 0
|
||||
server_audit_output_type file
|
||||
@ -216,6 +218,7 @@ server_audit_file_rotate_now OFF
|
||||
server_audit_file_rotate_size 1000000
|
||||
server_audit_file_rotations 9
|
||||
server_audit_incl_users odin, root, dva, tri
|
||||
server_audit_loc_info
|
||||
server_audit_logging ON
|
||||
server_audit_mode 1
|
||||
server_audit_output_type file
|
||||
@ -289,7 +292,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0
|
||||
TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
|
||||
|
@ -79,6 +79,7 @@ ERROR HY000: Your password does not satisfy the current policy requirements
|
||||
grant select on *.* to `BarFoo1!` identified by 'FooBar1!';
|
||||
drop user `BarFoo1!`;
|
||||
create user foo1 identified by 'aA.12345';
|
||||
grant select on *.* to foo1;
|
||||
drop user foo1;
|
||||
set global simple_password_check_digits=3;
|
||||
set global simple_password_check_letters_same_case=3;
|
||||
@ -129,7 +130,7 @@ ERROR HY000: The MariaDB server is running with the --strict-password-validation
|
||||
create user foo2 identified with mysql_native_password using '';
|
||||
ERROR HY000: Your password does not satisfy the current policy requirements
|
||||
grant select on *.* to foo2 identified with mysql_old_password;
|
||||
ERROR HY000: Your password does not satisfy the current policy requirements
|
||||
ERROR 28000: Can't find any matching row in the user table
|
||||
update mysql.user set password='xxx' where user='foo1';
|
||||
set global strict_password_validation=0;
|
||||
set password for foo1 = '';
|
||||
|
@ -35,6 +35,15 @@ SET SQL_MODE = '';
|
||||
drop table t1;
|
||||
SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'not_exists' AND TABLE_NAME = 'not_exists';
|
||||
TABLE_NAME
|
||||
CREATE procedure e1()
|
||||
BEGIN
|
||||
START TRANSACTION;
|
||||
INSERT INTO test.non_exists VALUES (0,0,0) /* e1 */;
|
||||
COMMIT;
|
||||
END|
|
||||
CALL e1();
|
||||
ERROR 42S02: Table 'test.non_exists' doesn't exist
|
||||
DROP PROCEDURE e1;
|
||||
uninstall plugin SQL_ERROR_LOG;
|
||||
Warnings:
|
||||
Warning 1620 Plugin is busy and will be uninstalled on shutdown
|
||||
@ -45,3 +54,4 @@ TIME HOSTNAME ERROR 1000: new message : RESIGNAL SQLSTATE '40000' SET
|
||||
MYSQL_ERRNO = 1000,
|
||||
MESSAGE_TEXT = 'new message'
|
||||
TIME HOSTNAME ERROR 1366: Incorrect integer value: 'aa' for column 'id' at row 1 : insert into t1 values ('aa')
|
||||
TIME HOSTNAME ERROR 1146: Table 'test.non_exists' doesn't exist : INSERT INTO test.non_exists VALUES (0,0,0) /* e1 */
|
||||
|
@ -8,6 +8,7 @@ server_audit_file_rotate_now OFF
|
||||
server_audit_file_rotate_size 1000000
|
||||
server_audit_file_rotations 9
|
||||
server_audit_incl_users
|
||||
server_audit_loc_info
|
||||
server_audit_logging OFF
|
||||
server_audit_mode 0
|
||||
server_audit_output_type file
|
||||
@ -71,6 +72,7 @@ server_audit_file_rotate_now OFF
|
||||
server_audit_file_rotate_size 1000000
|
||||
server_audit_file_rotations 9
|
||||
server_audit_incl_users odin, root, dva, tri
|
||||
server_audit_loc_info
|
||||
server_audit_logging ON
|
||||
server_audit_mode 0
|
||||
server_audit_output_type file
|
||||
@ -216,6 +218,7 @@ server_audit_file_rotate_now OFF
|
||||
server_audit_file_rotate_size 1000000
|
||||
server_audit_file_rotations 9
|
||||
server_audit_incl_users odin, root, dva, tri
|
||||
server_audit_loc_info
|
||||
server_audit_logging ON
|
||||
server_audit_mode 1
|
||||
server_audit_output_type file
|
||||
@ -289,7 +292,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0
|
||||
TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
|
||||
|
@ -26,6 +26,7 @@ grant select on *.* to `BarFoo1!` identified by 'FooBar1!';
|
||||
drop user `BarFoo1!`;
|
||||
|
||||
create user foo1 identified by 'aA.12345';
|
||||
grant select on *.* to foo1;
|
||||
drop user foo1;
|
||||
|
||||
set global simple_password_check_digits=3;
|
||||
@ -78,7 +79,7 @@ create user foo2 identified with mysql_native_password using '111111111111111111
|
||||
grant select on *.* to foo2 identified with mysql_old_password using '2222222222222222';
|
||||
--error ER_NOT_VALID_PASSWORD
|
||||
create user foo2 identified with mysql_native_password using '';
|
||||
--error ER_NOT_VALID_PASSWORD
|
||||
--error ER_PASSWORD_NO_MATCH
|
||||
grant select on *.* to foo2 identified with mysql_old_password;
|
||||
|
||||
# direct updates are not protected
|
||||
|
@ -48,6 +48,24 @@ drop table t1;
|
||||
|
||||
SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'not_exists' AND TABLE_NAME = 'not_exists';
|
||||
|
||||
#
|
||||
# MDEV-6421 SQL_ERROR_LOG doesn't log comments in Events
|
||||
# actually testing SP call is enough for that.
|
||||
|
||||
DELIMITER |;
|
||||
|
||||
CREATE procedure e1()
|
||||
BEGIN
|
||||
START TRANSACTION;
|
||||
INSERT INTO test.non_exists VALUES (0,0,0) /* e1 */;
|
||||
COMMIT;
|
||||
END|
|
||||
|
||||
DELIMITER ;|
|
||||
--error ER_NO_SUCH_TABLE
|
||||
CALL e1();
|
||||
DROP PROCEDURE e1;
|
||||
|
||||
uninstall plugin SQL_ERROR_LOG;
|
||||
|
||||
let $MYSQLD_DATADIR= `SELECT @@datadir`;
|
||||
|
@ -930,6 +930,8 @@ a
|
||||
31
|
||||
32
|
||||
SET sql_slave_skip_counter= 1;
|
||||
ERROR HY000: When using parallel replication and GTID with multiple replication domains, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position.
|
||||
include/stop_slave_io.inc
|
||||
include/start_slave.inc
|
||||
include/sync_with_master_gtid.inc
|
||||
SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
|
||||
|
@ -22,7 +22,8 @@ include/wait_for_slave_to_stop.inc
|
||||
drop table t1;
|
||||
flush tables with read lock;
|
||||
start slave;
|
||||
include/wait_for_slave_to_start.inc
|
||||
include/wait_for_slave_param.inc [Slave_IO_Running]
|
||||
include/wait_for_slave_sql_to_start.inc
|
||||
stop slave;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables;
|
||||
|
@ -14,6 +14,10 @@ DROP TABLE t1;
|
||||
[connection slave]
|
||||
include/install_semisync.inc
|
||||
[connection slave]
|
||||
show global status like "Slave%_running";
|
||||
Variable_name Value
|
||||
Slave_running ON
|
||||
Slaves_running 1
|
||||
UNINSTALL PLUGIN rpl_semi_sync_slave;
|
||||
Warnings:
|
||||
Warning 1620 Plugin is busy and will be uninstalled on shutdown
|
||||
@ -21,6 +25,10 @@ select plugin_name,plugin_status from information_schema.plugins where plugin_na
|
||||
plugin_name plugin_status
|
||||
rpl_semi_sync_slave DELETED
|
||||
[connection master]
|
||||
show global status like "Slave%_connect%";
|
||||
Variable_name Value
|
||||
Slave_connections 2
|
||||
Slaves_connected 1
|
||||
UNINSTALL PLUGIN rpl_semi_sync_master;
|
||||
Warnings:
|
||||
Warning 1620 Plugin is busy and will be uninstalled on shutdown
|
||||
|
@ -22,7 +22,8 @@ include/wait_for_slave_to_stop.inc
|
||||
drop table t1;
|
||||
flush tables with read lock;
|
||||
start slave;
|
||||
include/wait_for_slave_to_start.inc
|
||||
include/wait_for_slave_param.inc [Slave_IO_Running]
|
||||
include/wait_for_slave_sql_to_start.inc
|
||||
stop slave;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables;
|
||||
|
@ -1422,6 +1422,7 @@ SELECT * FROM t6 ORDER BY a;
|
||||
|
||||
--connection server_1
|
||||
INSERT INTO t2 VALUES (31);
|
||||
--let $gtid1= `SELECT @@LAST_GTID`
|
||||
--source include/save_master_gtid.inc
|
||||
|
||||
--connection server_2
|
||||
@ -1437,6 +1438,7 @@ SET sql_log_bin= 1;
|
||||
|
||||
--connection server_1
|
||||
INSERT INTO t2 VALUES (32);
|
||||
--let $gtid2= `SELECT @@LAST_GTID`
|
||||
# Rotate the binlog; the bug is triggered when the master binlog file changes
|
||||
# after the event group that causes the duplicate key error.
|
||||
FLUSH LOGS;
|
||||
@ -1469,7 +1471,12 @@ START SLAVE SQL_THREAD;
|
||||
SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
|
||||
|
||||
# Skip the duplicate error, so we can proceed.
|
||||
--error ER_SLAVE_SKIP_NOT_IN_GTID
|
||||
SET sql_slave_skip_counter= 1;
|
||||
--source include/stop_slave_io.inc
|
||||
--disable_query_log
|
||||
eval SET GLOBAL gtid_slave_pos = REPLACE(@@gtid_slave_pos, "$gtid1", "$gtid2");
|
||||
--enable_query_log
|
||||
--source include/start_slave.inc
|
||||
--source include/sync_with_master_gtid.inc
|
||||
|
||||
|
@ -57,6 +57,8 @@ DROP TABLE t1;
|
||||
# possible at this state
|
||||
--connection slave
|
||||
--echo [connection slave]
|
||||
show global status like "Slave%_running";
|
||||
|
||||
UNINSTALL PLUGIN rpl_semi_sync_slave;
|
||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
||||
|
||||
@ -64,6 +66,10 @@ select plugin_name,plugin_status from information_schema.plugins where plugin_na
|
||||
# possible at this state
|
||||
--connection master
|
||||
--echo [connection master]
|
||||
|
||||
# The following is to catch errors if the next uninstall plugin would succeed
|
||||
show global status like "Slave%_connect%";
|
||||
|
||||
UNINSTALL PLUGIN rpl_semi_sync_master;
|
||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
||||
|
||||
|
@ -3861,9 +3861,9 @@ READ_ONLY YES
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME THREAD_STACK
|
||||
SESSION_VALUE NULL
|
||||
GLOBAL_VALUE 294912
|
||||
GLOBAL_VALUE 295936
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 294912
|
||||
DEFAULT_VALUE 295936
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_COMMENT The stack size for each thread
|
||||
|
@ -4645,9 +4645,9 @@ READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME THREAD_STACK
|
||||
SESSION_VALUE NULL
|
||||
GLOBAL_VALUE 294912
|
||||
GLOBAL_VALUE 295936
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 294912
|
||||
DEFAULT_VALUE 295936
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_COMMENT The stack size for each thread
|
||||
|
@ -1,20 +1,20 @@
|
||||
select @@global.thread_stack;
|
||||
@@global.thread_stack
|
||||
294912
|
||||
295936
|
||||
select @@session.thread_stack;
|
||||
ERROR HY000: Variable 'thread_stack' is a GLOBAL variable
|
||||
show global variables like 'thread_stack';
|
||||
Variable_name Value
|
||||
thread_stack 294912
|
||||
thread_stack 295936
|
||||
show session variables like 'thread_stack';
|
||||
Variable_name Value
|
||||
thread_stack 294912
|
||||
thread_stack 295936
|
||||
select * from information_schema.global_variables where variable_name='thread_stack';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
THREAD_STACK 294912
|
||||
THREAD_STACK 295936
|
||||
select * from information_schema.session_variables where variable_name='thread_stack';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
THREAD_STACK 294912
|
||||
THREAD_STACK 295936
|
||||
set global thread_stack=1;
|
||||
ERROR HY000: Variable 'thread_stack' is a read only variable
|
||||
set session thread_stack=1;
|
||||
|
1
mysql-test/t/auth_named_pipe-master.opt
Normal file
1
mysql-test/t/auth_named_pipe-master.opt
Normal file
@ -0,0 +1 @@
|
||||
--loose-enable-named-pipe
|
23
mysql-test/t/auth_named_pipe.test
Normal file
23
mysql-test/t/auth_named_pipe.test
Normal file
@ -0,0 +1,23 @@
|
||||
--source include/windows.inc
|
||||
|
||||
INSTALL SONAME 'auth_named_pipe';
|
||||
|
||||
--replace_result $USERNAME USERNAME
|
||||
eval CREATE USER '$USERNAME' IDENTIFIED WITH named_pipe;
|
||||
# Connect using named pipe, correct username
|
||||
connect(pipe_con,localhost,$USERNAME,,,,,PIPE);
|
||||
--replace_result $USERNAME USERNAME
|
||||
SELECT USER(),CURRENT_USER();
|
||||
disconnect pipe_con;
|
||||
connection default;
|
||||
--replace_result $USERNAME USERNAME
|
||||
eval DROP USER '$USERNAME';
|
||||
|
||||
# test invalid user name
|
||||
CREATE USER nosuchuser IDENTIFIED WITH named_pipe;
|
||||
--disable_query_log
|
||||
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
|
||||
connect(pipe_con,localhost,nosuchuser,,,,,PIPE);
|
||||
--enable_query_log
|
||||
DROP USER nosuchuser;
|
||||
UNINSTALL SONAME 'auth_named_pipe';
|
@ -150,3 +150,10 @@ select a from t1 having a > 1|
|
||||
begin not atomic select a from t1 having a > 1; end|
|
||||
drop table t1|
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-8615: Assertion `m_cpp_buf <= begin_ptr &&
|
||||
--echo # begin_ptr <= m_cpp_buf + m_buf_length' failed in
|
||||
--echo # Lex_input_stream::body_utf8_start
|
||||
--echo #
|
||||
--error ER_PARSE_ERROR
|
||||
--query b'
|
||||
|
@ -1577,12 +1577,12 @@ SET NAMES utf8;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#57687 crash when reporting duplicate group_key error and utf8
|
||||
--echo # Make sure to modify this when Bug#58081 is fixed.
|
||||
--echo # Bug#58081 Duplicate entry error when doing GROUP BY
|
||||
--echo # MDEV-9332 Bug after upgrade to 10.1.10
|
||||
--echo #
|
||||
SET NAMES utf8;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (0), (0), (1), (0), (0);
|
||||
--error ER_DUP_ENTRY
|
||||
SELECT COUNT(*) FROM t1, t1 t2
|
||||
GROUP BY INSERT('', t2.a, t1.a, (@@global.max_binlog_size));
|
||||
DROP TABLE t1;
|
||||
|
@ -15,7 +15,7 @@ use events_test;
|
||||
# mysql.event intact checking end
|
||||
#
|
||||
|
||||
create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
|
||||
create event e_26 on schedule at '2027-01-01 00:00:00' disable do set @a = 5;
|
||||
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
|
||||
drop event e_26;
|
||||
--error ER_WRONG_VALUE
|
||||
|
@ -306,7 +306,7 @@ create table events_smode_test(ev_name char(10), a date);
|
||||
delimiter |;
|
||||
create event ee_16407_2 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_2', 60) /*ee_16407_2*/;
|
||||
select get_lock('ee_16407_2', 60); /*ee_16407_2*/
|
||||
select release_lock('ee_16407_2');
|
||||
insert into events_test.events_smode_test values('ee_16407_2','1980-19-02');
|
||||
end|
|
||||
@ -315,7 +315,7 @@ insert into events_test.events_smode_test values ('test','1980-19-02')|
|
||||
--echo "This is ok"
|
||||
create event ee_16407_3 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_2', 60) /*ee_16407_3*/;
|
||||
select get_lock('ee_16407_2', 60); /*ee_16407_3*/
|
||||
select release_lock('ee_16407_2');
|
||||
insert into events_test.events_smode_test values ('ee_16407_3','1980-02-19');
|
||||
insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29');
|
||||
@ -324,7 +324,7 @@ set sql_mode=""|
|
||||
--echo "This will insert rows but they will be truncated"
|
||||
create event ee_16407_4 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_2', 60) /*ee_16407_4*/;
|
||||
select get_lock('ee_16407_2', 60); /*ee_16407_4*/
|
||||
select release_lock('ee_16407_2');
|
||||
insert into events_test.events_smode_test values ('ee_16407_4','10-11-1956');
|
||||
end|
|
||||
@ -412,13 +412,13 @@ create procedure ee_16407_5_pendant() begin insert into events_test.events_smode
|
||||
create procedure ee_16407_6_pendant() begin insert into events_test.events_smode_test values('ee_16407_6','2004-02-29'); end|
|
||||
create event ee_16407_5 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_5', 60) /*ee_16407_5*/;
|
||||
select get_lock('ee_16407_5', 60); /*ee_16407_5*/
|
||||
select release_lock('ee_16407_5');
|
||||
call events_test.ee_16407_5_pendant();
|
||||
end|
|
||||
create event ee_16407_6 on schedule every 60 second do
|
||||
begin
|
||||
select get_lock('ee_16407_5', 60) /*ee_16407_6*/;
|
||||
select get_lock('ee_16407_5', 60); /*ee_16407_6*/
|
||||
select release_lock('ee_16407_5');
|
||||
call events_test.ee_16407_6_pendant();
|
||||
end|
|
||||
|
@ -1773,6 +1773,16 @@ EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE a=18446744073709551615 AND FORMAT(a,0)='18,446,744,073,709,551,615';
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#58081 Duplicate entry error when doing GROUP BY
|
||||
--echo # MDEV-9332 Bug after upgrade to 10.1.10
|
||||
--echo #
|
||||
SET NAMES latin1;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (0),(0),(1),(0),(0);
|
||||
SELECT COUNT(*) FROM t1, t1 t2 GROUP BY INSERT('', t2.a, t1.a, @@global.max_binlog_size);
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.1 tests
|
||||
--echo #
|
||||
|
@ -909,6 +909,45 @@ EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE a=2020 AND NULLIF(a,2010)=CONCAT('2020',RAND());
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-9181 (NULLIF(count(table.col)), 0) gives wrong result on 10.1.x
|
||||
--echo #
|
||||
CREATE TABLE t1 (c1 varchar(50) DEFAULT NULL);
|
||||
INSERT INTO t1 (c1) VALUES ('hello'), ('hello\r\n'), ('hello'),('hello');
|
||||
SELECT NULLIF(COUNT(c1),0) FROM t1;
|
||||
SELECT CASE WHEN COUNT(c1)=0 THEN NULL ELSE COUNT(c1) END FROM t1;
|
||||
SELECT NULLIF(COUNT(c1)+0,0) AS c1,NULLIF(CAST(COUNT(c1) AS SIGNED),0) AS c2,NULLIF(CONCAT(COUNT(c1)),0) AS c3 FROM t1;
|
||||
SELECT NULLIF(COUNT(DISTINCT c1),0) FROM t1;
|
||||
SELECT CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL,
|
||||
c1 INT DEFAULT NULL
|
||||
);
|
||||
INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(2,4);
|
||||
SELECT NULLIF(COUNT(c1),0) AS c1,NULLIF(COUNT(c1)+0,0) AS c1_wrapped,CASE WHEN COUNT(c1) IS NULL THEN 0 ELSE COUNT(c1) END AS c1_case FROM t1 GROUP BY id;
|
||||
DROP TABLE t1;
|
||||
|
||||
# Testing with side effects
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1),(2),(3);
|
||||
SET @a=0;
|
||||
SELECT NULLIF(LAST_VALUE(@a:=@a+1,a),0) FROM t1;
|
||||
SELECT @a;
|
||||
SET @a=0;
|
||||
SELECT NULLIF(AVG(a),0), NULLIF(AVG(LAST_VALUE(@a:=@a+1,a)),0) FROM t1;
|
||||
SELECT @a;
|
||||
|
||||
# There should not be cache in here:
|
||||
|
||||
EXPLAIN EXTENDED SELECT NULLIF(a,0) FROM t1;
|
||||
|
||||
# But there should be a cache in here:
|
||||
EXPLAIN EXTENDED SELECT NULLIF(AVG(a),0) FROM t1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.1 tests
|
||||
|
@ -21,3 +21,43 @@ SELECT * FROM t1 WHERE a = 8 AND (b = 1 OR b IS NULL) ORDER BY c;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-9457: Poor query plan chosen for ORDER BY query by a recent 10.1
|
||||
--echo #
|
||||
create table t0 (a int);
|
||||
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
|
||||
create table t1 (
|
||||
pk int primary key,
|
||||
key1 int,
|
||||
key2 int,
|
||||
col1 char(255),
|
||||
key(key1),
|
||||
key(key2)
|
||||
) engine=innodb;
|
||||
|
||||
set @a=-1;
|
||||
insert into t1
|
||||
select
|
||||
@a:=@a+1,
|
||||
@a,
|
||||
@a,
|
||||
repeat('abcd', 63)
|
||||
from t0 A, t0 B, t0 C, t0 D;
|
||||
|
||||
--echo # The following must NOT use 'index' on PK.
|
||||
--echo # It should use index_merge(key1,key2) + filesort
|
||||
--replace_column 9 #
|
||||
explain
|
||||
select *
|
||||
from t1
|
||||
where key1<3 or key2<3
|
||||
order by pk;
|
||||
|
||||
--replace_column 9 #
|
||||
explain
|
||||
select *
|
||||
from t1
|
||||
where key1<3 or key2<3;
|
||||
|
||||
drop table t0, t1;
|
||||
|
@ -1517,3 +1517,22 @@ and dept_id in (select dept_id from t2 where COMPANY_ID = 1000);
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-9505: Valgrind failure in SEL_ARG::store_min,find_used_partitions,...
|
||||
--echo #
|
||||
create table t1 (a int, b char(10), c varchar(5), d int)
|
||||
partition by range columns(a,b,c)
|
||||
subpartition by key (c,d)
|
||||
subpartitions 3
|
||||
( partition p0 values less than (1,'abc','abc'),
|
||||
partition p1 values less than (2,'abc','abc'),
|
||||
partition p2 values less than (3,'abc','abc'),
|
||||
partition p3 values less than (4,'abc','abc')
|
||||
);
|
||||
|
||||
insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3);
|
||||
select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) OR
|
||||
(a = 1 AND b >= 'a' AND (c = 'c' OR (c = 'd' AND d = 2))));
|
||||
drop table t1;
|
||||
|
||||
|
||||
|
@ -494,6 +494,17 @@ DELETE FROM mysql.table_stats;
|
||||
DELETE FROM mysql.column_stats;
|
||||
DELETE FROM mysql.index_stats;
|
||||
|
||||
|
||||
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES();
|
||||
ANALYZE TABLE t1 PERSISTENT FOR columns(a,b) INDEXES();
|
||||
ANALYZE TABLE t1 PERSISTENT FOR columns(b) indexes(idx2);
|
||||
ANALYZE TABLE t1 PERSISTENT FOR columns() indexes(idx2);
|
||||
|
||||
DELETE FROM mysql.table_stats;
|
||||
DELETE FROM mysql.column_stats;
|
||||
DELETE FROM mysql.index_stats;
|
||||
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
set names utf8;
|
||||
|
@ -325,3 +325,17 @@ insert t1 values (9, 9, 2);
|
||||
insert t1 (a,c) values (9, 3);
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# MDEV-9428 NO_AUTO_VALUE_ON_ZERO is ignored when a trigger before insert is defined
|
||||
#
|
||||
set session sql_mode ='no_auto_value_on_zero';
|
||||
create table t1 (id int unsigned auto_increment primary key);
|
||||
insert t1 values (0);
|
||||
select * from t1;
|
||||
delete from t1;
|
||||
create trigger t1_bi before insert on t1 for each row begin end;
|
||||
insert t1 values (0);
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
|
@ -1277,6 +1277,15 @@
|
||||
fun:dlopen@@GLIBC_2.2.5
|
||||
}
|
||||
|
||||
{
|
||||
vasprintf in OpenSuse 12.3
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:vasprintf
|
||||
fun:asprintf
|
||||
fun:dlerror
|
||||
}
|
||||
|
||||
{
|
||||
GitHub codership/galera#308
|
||||
Memcheck:Leak
|
||||
|
@ -14,11 +14,13 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#ifndef FLOGGER_SKIP_INCLUDES
|
||||
#include "my_global.h"
|
||||
#include <my_sys.h>
|
||||
#include <m_string.h>
|
||||
#include <mysql/service_logger.h>
|
||||
#include <my_pthread.h>
|
||||
#endif /*FLOGGER_SKIP_INCLUDES*/
|
||||
|
||||
#ifndef flogger_mutex_init
|
||||
#define flogger_mutex_init(A,B,C) mysql_mutex_init(A,B,C)
|
||||
|
@ -145,30 +145,75 @@ static int initialized= 0;
|
||||
static char output[1024];
|
||||
int my_addr_resolve(void *ptr, my_addr_loc *loc)
|
||||
{
|
||||
char input[32], *s;
|
||||
char input[32];
|
||||
size_t len;
|
||||
|
||||
ssize_t total_bytes_read = 0;
|
||||
ssize_t extra_bytes_read = 0;
|
||||
|
||||
fd_set set;
|
||||
struct timeval timeout;
|
||||
|
||||
int filename_start = -1;
|
||||
int line_number_start = -1;
|
||||
ssize_t i;
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(out[0], &set);
|
||||
|
||||
len= my_snprintf(input, sizeof(input), "%p\n", ptr - offset);
|
||||
if (write(in[1], input, len) <= 0)
|
||||
return 1;
|
||||
if (read(out[0], output, sizeof(output)) <= 0)
|
||||
return 1;
|
||||
loc->func= s= output;
|
||||
while (*s != '\n')
|
||||
s++;
|
||||
*s++= 0;
|
||||
loc->file= s;
|
||||
while (*s != ':')
|
||||
s++;
|
||||
*s++= 0;
|
||||
|
||||
/* 10 ms should be plenty of time for addr2line to issue a response. */
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 10000;
|
||||
/* Read in a loop till all the output from addr2line is complete. */
|
||||
while (select(out[0] + 1, &set, NULL, NULL, &timeout) > 0)
|
||||
{
|
||||
extra_bytes_read= read(out[0], output + total_bytes_read,
|
||||
sizeof(output) - total_bytes_read);
|
||||
if (extra_bytes_read < 0)
|
||||
return 1;
|
||||
/* Timeout or max bytes read. */
|
||||
if (extra_bytes_read == 0)
|
||||
break;
|
||||
|
||||
total_bytes_read += extra_bytes_read;
|
||||
}
|
||||
|
||||
/* Failed starting addr2line. */
|
||||
if (total_bytes_read == 0)
|
||||
return 1;
|
||||
|
||||
/* Go through the addr2line response and get the required data.
|
||||
The response is structured in 2 lines. The first line contains the function
|
||||
name, while the second one contains <filename>:<line number> */
|
||||
for (i = 0; i < total_bytes_read; i++) {
|
||||
if (output[i] == '\n') {
|
||||
filename_start = i + 1;
|
||||
output[i] = '\0';
|
||||
}
|
||||
if (filename_start != -1 && output[i] == ':') {
|
||||
line_number_start = i + 1;
|
||||
output[i] = '\0';
|
||||
}
|
||||
if (line_number_start != -1) {
|
||||
loc->line= atoi(output + line_number_start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Response is malformed. */
|
||||
if (filename_start == -1 || line_number_start == -1)
|
||||
return 1;
|
||||
|
||||
loc->func= output;
|
||||
loc->file= output + filename_start;
|
||||
|
||||
/* Addr2line was unable to extract any meaningful information. */
|
||||
if (strcmp(loc->file, "??") == 0)
|
||||
return 1;
|
||||
|
||||
loc->line= 0;
|
||||
while (isdigit(*s))
|
||||
loc->line = loc->line * 10 + (*s++ - '0');
|
||||
*s = 0;
|
||||
loc->file= strip_path(loc->file);
|
||||
|
||||
return 0;
|
||||
|
@ -15,4 +15,4 @@
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
MYSQL_ADD_PLUGIN(dialog dialog.c ${CMAKE_SOURCE_DIR}/libmysql/get_password.c
|
||||
MODULE_ONLY COMPONENT ClientPlugins)
|
||||
MODULE_ONLY CLIENT COMPONENT ClientPlugins)
|
||||
|
@ -30,4 +30,4 @@ MYSQL_ADD_PLUGIN(qa_auth_client qa_auth_client.c
|
||||
MYSQL_ADD_PLUGIN(auth_0x0100 auth_0x0100.c MODULE_ONLY COMPONENT Test)
|
||||
|
||||
MYSQL_ADD_PLUGIN(mysql_clear_password clear_password_client.c
|
||||
MODULE_ONLY COMPONENT ClientPlugins)
|
||||
MODULE_ONLY CLIENT COMPONENT ClientPlugins)
|
||||
|
36
plugin/auth_gssapi/CMakeLists.txt
Normal file
36
plugin/auth_gssapi/CMakeLists.txt
Normal file
@ -0,0 +1,36 @@
|
||||
IF (WIN32)
|
||||
SET(USE_SSPI 1)
|
||||
ENDIF()
|
||||
|
||||
IF(USE_SSPI)
|
||||
SET(GSSAPI_LIBS secur32)
|
||||
ADD_DEFINITIONS(-DPLUGIN_SSPI)
|
||||
SET(GSSAPI_CLIENT sspi_client.cc)
|
||||
SET(GSSAPI_SERVER sspi_server.cc)
|
||||
SET(GSSAPI_ERRMSG sspi_errmsg.cc)
|
||||
ELSE()
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
FIND_PACKAGE(GSSAPI)
|
||||
IF(GSSAPI_FOUND)
|
||||
INCLUDE_DIRECTORIES(${GSSAPI_INCS})
|
||||
ADD_DEFINITIONS(-DPLUGIN_GSSAPI)
|
||||
SET(GSSAPI_CLIENT gssapi_client.cc)
|
||||
SET(GSSAPI_SERVER gssapi_server.cc)
|
||||
SET(GSSAPI_ERRMSG gssapi_errmsg.cc)
|
||||
ELSE()
|
||||
# Can't build plugin
|
||||
RETURN()
|
||||
ENDIF()
|
||||
ENDIF ()
|
||||
|
||||
|
||||
MYSQL_ADD_PLUGIN(auth_gssapi server_plugin.cc ${GSSAPI_SERVER} ${GSSAPI_ERRMSG}
|
||||
LINK_LIBRARIES ${GSSAPI_LIBS}
|
||||
COMPONENT gssapi-server
|
||||
MODULE_ONLY)
|
||||
|
||||
MYSQL_ADD_PLUGIN(auth_gssapi_client client_plugin.cc ${GSSAPI_CLIENT} ${GSSAPI_ERRMSG}
|
||||
LINK_LIBRARIES ${GSSAPI_LIBS}
|
||||
COMPONENT gssapi-client
|
||||
CLIENT
|
||||
MODULE_ONLY)
|
129
plugin/auth_gssapi/README.md
Normal file
129
plugin/auth_gssapi/README.md
Normal file
@ -0,0 +1,129 @@
|
||||
# GSSAPI/SSPI authentication for MariaDB
|
||||
|
||||
This article gives instructions on configuring GSSAPI authentication plugin
|
||||
for MariaDB for passwordless login.
|
||||
|
||||
On Unix systems, GSSAPI is usually synonymous with Kerberos authentication.
|
||||
Windows has slightly different but very similar API called SSPI, that along with Kerberos, also supports NTLM authentication.
|
||||
|
||||
This plugin includes support for Kerberos on Unix, but also can be used as for Windows authentication with or without domain
|
||||
environment.
|
||||
|
||||
## Server-side preparations on Unix
|
||||
To use the plugin, some preparation need to be done on the server side on Unixes.
|
||||
MariaDB server will need read access to the Kerberos keytab file, that contains service principal name for the MariaDB server.
|
||||
|
||||
|
||||
If you are using **Unix Kerberos KDC (MIT,Heimdal)**
|
||||
|
||||
- Create service principal using kadmin tool
|
||||
|
||||
```
|
||||
kadmin -q "addprinc -randkey mariadb/host.domain.com"
|
||||
```
|
||||
|
||||
(replace host.domain.com with fully qualified DNS name for the server host)
|
||||
|
||||
- Export the newly created user to the keytab file
|
||||
|
||||
```
|
||||
kadmin -q "ktadd -k /path/to/mariadb.keytab mariadb/host.domain.com"
|
||||
```
|
||||
|
||||
More details can be found [here](http://www.microhowto.info/howto/create_a_service_principal_using_mit_kerberos.html)
|
||||
and [here](http://www.microhowto.info/howto/add_a_host_or_service_principal_to_a_keytab_using_mit_kerberos.html)
|
||||
|
||||
If you are using **Windows Active Directory KDC**
|
||||
you can need to create keytab using ktpass.exe tool on Windows, map principal user to an existing domain user like this
|
||||
|
||||
```
|
||||
ktpass.exe /princ mariadb/host.domain.com@DOMAIN.COM /mapuser someuser /pass MyPas$w0rd /out mariadb.keytab /crypto all /ptype KRB5_NT_PRINCIPAL /mapop set
|
||||
```
|
||||
|
||||
and then transfer the keytab file to the Unix server. See [Microsoft documentation](https://technet.microsoft.com/en-us/library/cc753771.aspx) for details.
|
||||
|
||||
|
||||
## Server side preparations on Windows.
|
||||
Usually nothing need to be done. MariaDB server should to run on a domain joined machine, either as NetworkService account
|
||||
(which is default if it runs as service) or run under any other domain account credentials.
|
||||
Creating service principal is not required here (but you can still do it using [_setspn_](https://technet.microsoft.com/en-us/library/cc731241.aspx) tool)
|
||||
|
||||
|
||||
# Installing plugin
|
||||
- Start the server
|
||||
|
||||
- On Unix, edit my the my.cnf/my.ini configuration file, set the parameter gssapi-keytab-path to point to previously
|
||||
created keytab path.
|
||||
|
||||
```
|
||||
gssapi-keytab-path=/path/to/mariadb.keytab
|
||||
```
|
||||
|
||||
- Optionally on Unix, in case the service principal name differs from default mariadb/host.domain.com@REALM,
|
||||
configure alternative principal name with
|
||||
|
||||
```
|
||||
gssapi-principal-name=alternative/principalname@REALM
|
||||
```
|
||||
|
||||
- In mysql command line client, execute
|
||||
|
||||
```
|
||||
INSTALL SONAME 'auth_gssapi'
|
||||
```
|
||||
|
||||
#Creating users
|
||||
|
||||
Now, you can create a user for GSSAPI/SSPI authentication. CREATE USER command, for Kerberos user
|
||||
would be like this (*long* form, see below for short one)
|
||||
|
||||
```
|
||||
CREATE USER usr1 IDENTIFIED WITH gssapi AS 'usr1@EXAMPLE.COM';
|
||||
```
|
||||
|
||||
(replace with real username and realm)
|
||||
|
||||
The part after AS is mechanism specific, and needs to be ``machine\\usr1`` for Windows users identified with NTLM.
|
||||
|
||||
You may also use alternative *short* form of CREATE USER
|
||||
|
||||
```
|
||||
CREATE USER usr1 IDENTIFIED WITH gssapi;
|
||||
```
|
||||
|
||||
If this syntax is used, realm part is *not* used for comparison
|
||||
thus 'usr1@EXAMPLE.COM', 'usr1@EXAMPLE.CO.UK' and 'mymachine\usr1' will all identify as 'usr1'.
|
||||
|
||||
#Login as GSSAPI user with command line clients
|
||||
|
||||
Using command line client, do
|
||||
|
||||
```
|
||||
mysql --plugin-dir=/path/to/plugin-dir -u usr1
|
||||
```
|
||||
|
||||
#Plugin variables
|
||||
- **gssapi-keytab-path** (Unix only) - Path to the server keytab file
|
||||
- **gssapi-principal-name** - name of the service principal.
|
||||
- **gssapi-mech-name** (Windows only) - Name of the SSPI package used by server. Can be either 'Kerberos' or 'Negotiate'.
|
||||
Defaults to 'Negotiate' (both Kerberos and NTLM users can connect)
|
||||
Set it to 'Kerberos', to prevent less secure NTLM in domain environments, but leave it as default(Negotiate)
|
||||
to allow non-domain environment (e.g if server does not run in domain enviroment).
|
||||
|
||||
|
||||
#Implementation
|
||||
|
||||
Overview of the protocol between client and server
|
||||
|
||||
1. Server : Construct gssapi-principal-name if not set in my.cnf. On Unixes defaults to hostbased name for service "mariadb". On Windows to user's or machine's domain names.
|
||||
Acquire credentials for gssapi-principal-name with ```gss_acquire_cred() / AcquireSecurityCredentials()```.
|
||||
Send packet with principal name and mech ```"gssapi-principal-name\0gssapi-mech-name\0"``` to client ( on Unix, empty string used for gssapi-mech)
|
||||
|
||||
2. Client: execute ```gss_init_sec_context() / InitializeSecurityContext()``` passing gssapi-principal-name / gssapi-mech-name parameters.
|
||||
Send resulting GSSAPI blob to server.
|
||||
|
||||
3. Server : receive blob from client, execute ```gss_accept_sec_context()/ AcceptSecurityContext()```, send resulting blob back to client
|
||||
|
||||
4. Perform 2. and 3. can until both client and server decide that authentication is done, or until some error occured. If authentication was successful, GSSAPI context (an opaque structure) is generated on both client and server sides.
|
||||
|
||||
5. Server : Client name is extracted from the context, and compared to the name provided by client(with or without realm). If name matches, plugin returns success.
|
112
plugin/auth_gssapi/client_plugin.cc
Normal file
112
plugin/auth_gssapi/client_plugin.cc
Normal file
@ -0,0 +1,112 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file
|
||||
|
||||
GSSAPI authentication plugin, client side
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <mysql/client_plugin.h>
|
||||
#include <mysql.h>
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
|
||||
extern int auth_client(char *principal_name,
|
||||
char *mech,
|
||||
MYSQL *mysql,
|
||||
MYSQL_PLUGIN_VIO *vio);
|
||||
|
||||
static void parse_server_packet(char *packet, size_t packet_len, char *spn, char *mech)
|
||||
{
|
||||
size_t spn_len;
|
||||
spn_len = strnlen(packet, packet_len);
|
||||
strncpy(spn, packet, PRINCIPAL_NAME_MAX);
|
||||
if (spn_len == packet_len - 1)
|
||||
{
|
||||
/* Mechanism not included into packet */
|
||||
*mech = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(mech, packet + spn_len + 1, MECH_NAME_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Set client error message.
|
||||
*/
|
||||
void log_client_error(MYSQL *mysql, const char *format, ...)
|
||||
{
|
||||
NET *net= &mysql->net;
|
||||
va_list args;
|
||||
|
||||
net->last_errno= ER_UNKNOWN_ERROR;
|
||||
va_start(args, format);
|
||||
vsnprintf(net->last_error, sizeof(net->last_error) - 1,
|
||||
format, args);
|
||||
va_end(args);
|
||||
memcpy(net->sqlstate, "HY000", sizeof(net->sqlstate));
|
||||
}
|
||||
|
||||
/**
|
||||
The main client function of the GSSAPI plugin.
|
||||
*/
|
||||
static int gssapi_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
|
||||
{
|
||||
int packet_len;
|
||||
unsigned char *packet;
|
||||
char spn[PRINCIPAL_NAME_MAX + 1];
|
||||
char mech[MECH_NAME_MAX + 1];
|
||||
|
||||
/* read from server for service principal name */
|
||||
packet_len= vio->read_packet(vio, &packet);
|
||||
if (packet_len < 0)
|
||||
{
|
||||
return CR_ERROR;
|
||||
}
|
||||
parse_server_packet((char *)packet, (size_t)packet_len, spn, mech);
|
||||
return auth_client(spn, mech, mysql, vio);
|
||||
}
|
||||
|
||||
|
||||
/* register client plugin */
|
||||
mysql_declare_client_plugin(AUTHENTICATION)
|
||||
"auth_gssapi_client",
|
||||
"Shuang Qiu, Robbie Harwood, Vladislav Vaintroub",
|
||||
"GSSAPI/SSPI based authentication",
|
||||
{0, 1, 0},
|
||||
"BSD",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
gssapi_auth_client
|
||||
mysql_end_client_plugin;
|
98
plugin/auth_gssapi/cmake/FindGSSAPI.cmake
Normal file
98
plugin/auth_gssapi/cmake/FindGSSAPI.cmake
Normal file
@ -0,0 +1,98 @@
|
||||
# - Try to detect the GSSAPI support
|
||||
# Once done this will define
|
||||
#
|
||||
# GSSAPI_FOUND - system supports GSSAPI
|
||||
# GSSAPI_INCS - the GSSAPI include directory
|
||||
# GSSAPI_LIBS - the libraries needed to use GSSAPI
|
||||
# GSSAPI_FLAVOR - the type of API - MIT or HEIMDAL
|
||||
|
||||
# Copyright (c) 2006, Pino Toscano, <toscano.pino@tiscali.it>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
if(GSSAPI_LIBS AND GSSAPI_FLAVOR)
|
||||
|
||||
# in cache already
|
||||
set(GSSAPI_FOUND TRUE)
|
||||
|
||||
else(GSSAPI_LIBS AND GSSAPI_FLAVOR)
|
||||
|
||||
find_program(KRB5_CONFIG NAMES krb5-config PATHS
|
||||
/opt/local/bin
|
||||
ONLY_CMAKE_FIND_ROOT_PATH # this is required when cross compiling with cmake 2.6 and ignored with cmake 2.4, Alex
|
||||
)
|
||||
mark_as_advanced(KRB5_CONFIG)
|
||||
|
||||
#reset vars
|
||||
set(GSSAPI_INCS)
|
||||
set(GSSAPI_LIBS)
|
||||
set(GSSAPI_FLAVOR)
|
||||
|
||||
if(KRB5_CONFIG)
|
||||
|
||||
set(HAVE_KRB5_GSSAPI TRUE)
|
||||
exec_program(${KRB5_CONFIG} ARGS --libs gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_LIBS)
|
||||
if(_return_VALUE)
|
||||
message(STATUS "GSSAPI configure check failed.")
|
||||
set(HAVE_KRB5_GSSAPI FALSE)
|
||||
endif(_return_VALUE)
|
||||
|
||||
exec_program(${KRB5_CONFIG} ARGS --cflags gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_INCS)
|
||||
string(REGEX REPLACE "(\r?\n)+$" "" GSSAPI_INCS "${GSSAPI_INCS}")
|
||||
string(REGEX REPLACE " *-I" ";" GSSAPI_INCS "${GSSAPI_INCS}")
|
||||
|
||||
exec_program(${KRB5_CONFIG} ARGS --vendor RETURN_VALUE _return_VALUE OUTPUT_VARIABLE gssapi_flavor_tmp)
|
||||
set(GSSAPI_FLAVOR_MIT)
|
||||
if(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
|
||||
set(GSSAPI_FLAVOR "MIT")
|
||||
else(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
|
||||
set(GSSAPI_FLAVOR "HEIMDAL")
|
||||
endif(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
|
||||
|
||||
if(NOT HAVE_KRB5_GSSAPI)
|
||||
if (gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
|
||||
message(STATUS "Solaris Kerberos does not have GSSAPI; this is normal.")
|
||||
set(GSSAPI_LIBS)
|
||||
set(GSSAPI_INCS)
|
||||
else(gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
|
||||
message(WARNING "${KRB5_CONFIG} failed unexpectedly.")
|
||||
endif(gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
|
||||
endif(NOT HAVE_KRB5_GSSAPI)
|
||||
|
||||
if(GSSAPI_LIBS) # GSSAPI_INCS can be also empty, so don't rely on that
|
||||
set(GSSAPI_FOUND TRUE CACHE STRING "")
|
||||
message(STATUS "Found GSSAPI: ${GSSAPI_LIBS}")
|
||||
|
||||
set(GSSAPI_INCS ${GSSAPI_INCS} CACHE STRING "")
|
||||
set(GSSAPI_LIBS ${GSSAPI_LIBS} CACHE STRING "")
|
||||
set(GSSAPI_FLAVOR ${GSSAPI_FLAVOR} CACHE STRING "")
|
||||
|
||||
mark_as_advanced(GSSAPI_INCS GSSAPI_LIBS GSSAPI_FLAVOR)
|
||||
|
||||
endif(GSSAPI_LIBS)
|
||||
|
||||
endif(KRB5_CONFIG)
|
||||
|
||||
endif(GSSAPI_LIBS AND GSSAPI_FLAVOR)
|
4
plugin/auth_gssapi/common.h
Normal file
4
plugin/auth_gssapi/common.h
Normal file
@ -0,0 +1,4 @@
|
||||
/** Maximal length of the target name */
|
||||
#define PRINCIPAL_NAME_MAX 256
|
||||
/** Maximal length of the mech string */
|
||||
#define MECH_NAME_MAX 30
|
127
plugin/auth_gssapi/gssapi_client.cc
Normal file
127
plugin/auth_gssapi/gssapi_client.cc
Normal file
@ -0,0 +1,127 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <gssapi/gssapi.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <mysql/plugin_auth.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <mysql.h>
|
||||
#include "gssapi_errmsg.h"
|
||||
|
||||
extern void log_client_error(MYSQL *mysql,const char *fmt,...);
|
||||
|
||||
|
||||
/* This sends the error to the client */
|
||||
static void log_error(MYSQL *mysql, OM_uint32 major, OM_uint32 minor, const char *msg)
|
||||
{
|
||||
if (GSS_ERROR(major))
|
||||
{
|
||||
char sysmsg[1024];
|
||||
gssapi_errmsg(major, minor, sysmsg, sizeof(sysmsg));
|
||||
log_client_error(mysql,
|
||||
"Client GSSAPI error (major %u, minor %u) : %s - %s",
|
||||
major, minor, msg, sysmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_client_error(mysql, "Client GSSAPI error : %s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
int auth_client(char *principal_name, char *mech, MYSQL *mysql, MYSQL_PLUGIN_VIO *vio)
|
||||
{
|
||||
|
||||
int ret= CR_ERROR;
|
||||
OM_uint32 major= 0, minor= 0;
|
||||
gss_ctx_id_t ctxt= GSS_C_NO_CONTEXT;
|
||||
gss_name_t service_name= GSS_C_NO_NAME;
|
||||
|
||||
if (principal_name && principal_name[0])
|
||||
{
|
||||
/* import principal from plain text */
|
||||
gss_buffer_desc principal_name_buf;
|
||||
principal_name_buf.length= strlen(principal_name);
|
||||
principal_name_buf.value= (void *) principal_name;
|
||||
major= gss_import_name(&minor, &principal_name_buf, GSS_C_NT_USER_NAME, &service_name);
|
||||
if (GSS_ERROR(major))
|
||||
{
|
||||
log_error(mysql, major, minor, "gss_import_name");
|
||||
return CR_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
gss_buffer_desc input= {0,0};
|
||||
do
|
||||
{
|
||||
gss_buffer_desc output= {0,0};
|
||||
major= gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ctxt, service_name,
|
||||
GSS_C_NO_OID, 0, 0, GSS_C_NO_CHANNEL_BINDINGS,
|
||||
&input, NULL, &output, NULL, NULL);
|
||||
if (output.length)
|
||||
{
|
||||
/* send credential */
|
||||
if(vio->write_packet(vio, (unsigned char *)output.value, output.length))
|
||||
{
|
||||
/* Server error packet contains detailed message. */
|
||||
ret= CR_OK_HANDSHAKE_COMPLETE;
|
||||
gss_release_buffer (&minor, &output);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
gss_release_buffer (&minor, &output);
|
||||
|
||||
if (GSS_ERROR(major))
|
||||
{
|
||||
log_error(mysql, major, minor,"gss_init_sec_context");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (major & GSS_S_CONTINUE_NEEDED)
|
||||
{
|
||||
int len= vio->read_packet(vio, (unsigned char **) &input.value);
|
||||
if (len <= 0)
|
||||
{
|
||||
/* Server error packet contains detailed message. */
|
||||
ret= CR_OK_HANDSHAKE_COMPLETE;
|
||||
goto cleanup;
|
||||
}
|
||||
input.length= len;
|
||||
}
|
||||
} while (major & GSS_S_CONTINUE_NEEDED);
|
||||
|
||||
ret= CR_OK;
|
||||
|
||||
cleanup:
|
||||
if (service_name != GSS_C_NO_NAME)
|
||||
gss_release_name(&minor, &service_name);
|
||||
if (ctxt != GSS_C_NO_CONTEXT)
|
||||
gss_delete_sec_context(&minor, &ctxt, GSS_C_NO_BUFFER);
|
||||
|
||||
return ret;
|
||||
}
|
75
plugin/auth_gssapi/gssapi_errmsg.cc
Normal file
75
plugin/auth_gssapi/gssapi_errmsg.cc
Normal file
@ -0,0 +1,75 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <gssapi.h>
|
||||
#include <string.h>
|
||||
void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size)
|
||||
{
|
||||
OM_uint32 message_context;
|
||||
OM_uint32 status_code;
|
||||
OM_uint32 maj_status;
|
||||
OM_uint32 min_status;
|
||||
gss_buffer_desc status_string;
|
||||
char *p= buf;
|
||||
char *end= buf + size - 1;
|
||||
int types[] = {GSS_C_GSS_CODE,GSS_C_MECH_CODE};
|
||||
|
||||
for(int i= 0; i < 2;i++)
|
||||
{
|
||||
message_context= 0;
|
||||
status_code= types[i] == GSS_C_GSS_CODE?major:minor;
|
||||
|
||||
if(!status_code)
|
||||
continue;
|
||||
do
|
||||
{
|
||||
maj_status = gss_display_status(
|
||||
&min_status,
|
||||
status_code,
|
||||
types[i],
|
||||
GSS_C_NO_OID,
|
||||
&message_context,
|
||||
&status_string);
|
||||
|
||||
if(maj_status)
|
||||
break;
|
||||
|
||||
if(p + status_string.length + 2 < end)
|
||||
{
|
||||
memcpy(p,status_string.value, status_string.length);
|
||||
p += status_string.length;
|
||||
*p++ = '.';
|
||||
*p++ = ' ';
|
||||
}
|
||||
|
||||
gss_release_buffer(&min_status, &status_string);
|
||||
}
|
||||
while (message_context != 0);
|
||||
}
|
||||
*p= 0;
|
||||
}
|
29
plugin/auth_gssapi/gssapi_errmsg.h
Normal file
29
plugin/auth_gssapi/gssapi_errmsg.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
extern void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size);
|
247
plugin/auth_gssapi/gssapi_server.cc
Normal file
247
plugin/auth_gssapi/gssapi_server.cc
Normal file
@ -0,0 +1,247 @@
|
||||
#include <my_config.h>
|
||||
#include <gssapi/gssapi.h>
|
||||
#include <stdio.h>
|
||||
#include <mysql/plugin_auth.h>
|
||||
#include <my_sys.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <log.h>
|
||||
#include "server_plugin.h"
|
||||
#include "gssapi_errmsg.h"
|
||||
|
||||
static gss_name_t service_name = GSS_C_NO_NAME;
|
||||
|
||||
/* This sends the error to the client */
|
||||
static void log_error( OM_uint32 major, OM_uint32 minor, const char *msg)
|
||||
{
|
||||
if (GSS_ERROR(major))
|
||||
{
|
||||
char sysmsg[1024];
|
||||
gssapi_errmsg(major, minor, sysmsg, sizeof(sysmsg));
|
||||
my_printf_error(ER_UNKNOWN_ERROR,"Server GSSAPI error (major %u, minor %u) : %s -%s",
|
||||
MYF(0), major, minor, msg, sysmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
my_printf_error(ER_UNKNOWN_ERROR, "Server GSSAPI error : %s", MYF(0), msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Generate default principal service name formatted as principal name "mariadb/server.fqdn@REALM"
|
||||
*/
|
||||
#include <krb5.h>
|
||||
static char* get_default_principal_name()
|
||||
{
|
||||
static char default_name[1024];
|
||||
char *unparsed_name= NULL;
|
||||
krb5_context context= NULL;
|
||||
krb5_principal principal= NULL;
|
||||
krb5_keyblock *key= NULL;
|
||||
|
||||
if(krb5_init_context(&context))
|
||||
{
|
||||
sql_print_warning("GSSAPI plugin : krb5_init_context failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (krb5_sname_to_principal(context, NULL, "mariadb", KRB5_NT_SRV_HST, &principal))
|
||||
{
|
||||
sql_print_warning("GSSAPI plugin : krb5_sname_to_principal failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (krb5_unparse_name(context, principal, &unparsed_name))
|
||||
{
|
||||
sql_print_warning("GSSAPI plugin : krb5_unparse_name failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Check for entry in keytab */
|
||||
if (krb5_kt_read_service_key(context, NULL, principal, 0, (krb5_enctype)0, &key))
|
||||
{
|
||||
sql_print_warning("GSSAPI plugin : default principal '%s' not found in keytab", unparsed_name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
strncpy(default_name, unparsed_name, sizeof(default_name)-1);
|
||||
|
||||
cleanup:
|
||||
if (key)
|
||||
krb5_free_keyblock(context, key);
|
||||
if (unparsed_name)
|
||||
krb5_free_unparsed_name(context, unparsed_name);
|
||||
if (principal)
|
||||
krb5_free_principal(context, principal);
|
||||
if (context)
|
||||
krb5_free_context(context);
|
||||
|
||||
return default_name;
|
||||
}
|
||||
|
||||
|
||||
int plugin_init()
|
||||
{
|
||||
gss_buffer_desc principal_name_buf;
|
||||
OM_uint32 major= 0, minor= 0;
|
||||
gss_cred_id_t cred= GSS_C_NO_CREDENTIAL;
|
||||
|
||||
if(srv_keytab_path && srv_keytab_path[0])
|
||||
{
|
||||
setenv("KRB5_KTNAME", srv_keytab_path, 1);
|
||||
}
|
||||
|
||||
if(!srv_principal_name || !srv_principal_name[0])
|
||||
srv_principal_name= get_default_principal_name();
|
||||
|
||||
/* import service principal from plain text */
|
||||
if(srv_principal_name && srv_principal_name[0])
|
||||
{
|
||||
sql_print_information("GSSAPI plugin : using principal name '%s'", srv_principal_name);
|
||||
principal_name_buf.length= strlen(srv_principal_name);
|
||||
principal_name_buf.value= srv_principal_name;
|
||||
major= gss_import_name(&minor, &principal_name_buf, GSS_C_NT_USER_NAME, &service_name);
|
||||
if(GSS_ERROR(major))
|
||||
{
|
||||
log_error(major, minor, "gss_import_name");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
service_name= GSS_C_NO_NAME;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Check if SPN configuration is OK */
|
||||
major= gss_acquire_cred(&minor, service_name, GSS_C_INDEFINITE,
|
||||
GSS_C_NO_OID_SET, GSS_C_ACCEPT, &cred, NULL,
|
||||
NULL);
|
||||
|
||||
if (GSS_ERROR(major))
|
||||
{
|
||||
log_error(major, minor, "gss_acquire_cred failed");
|
||||
return -1;
|
||||
}
|
||||
gss_release_cred(&minor, &cred);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plugin_deinit()
|
||||
{
|
||||
if (service_name != GSS_C_NO_NAME)
|
||||
{
|
||||
OM_uint32 minor;
|
||||
gss_release_name(&minor, &service_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int auth_server(MYSQL_PLUGIN_VIO *vio,const char *user, size_t userlen, int use_full_name)
|
||||
{
|
||||
|
||||
int rc= CR_ERROR; /* return code */
|
||||
|
||||
/* GSSAPI related fields */
|
||||
OM_uint32 major= 0, minor= 0, flags= 0;
|
||||
gss_cred_id_t cred= GSS_C_NO_CREDENTIAL; /* credential identifier */
|
||||
gss_ctx_id_t ctxt= GSS_C_NO_CONTEXT; /* context identifier */
|
||||
gss_name_t client_name;
|
||||
gss_buffer_desc client_name_buf, input, output;
|
||||
char *client_name_str;
|
||||
|
||||
/* server acquires credential */
|
||||
major= gss_acquire_cred(&minor, service_name, GSS_C_INDEFINITE,
|
||||
GSS_C_NO_OID_SET, GSS_C_ACCEPT, &cred, NULL,
|
||||
NULL);
|
||||
|
||||
if (GSS_ERROR(major))
|
||||
{
|
||||
log_error(major, minor, "gss_acquire_cred failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
input.length= 0;
|
||||
input.value= NULL;
|
||||
do
|
||||
{
|
||||
/* receive token from peer */
|
||||
int len= vio->read_packet(vio, (unsigned char **) &input.value);
|
||||
if (len < 0)
|
||||
{
|
||||
log_error(0, 0, "fail to read token from client");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
input.length= len;
|
||||
major= gss_accept_sec_context(&minor, &ctxt, cred, &input,
|
||||
GSS_C_NO_CHANNEL_BINDINGS, &client_name,
|
||||
NULL, &output, &flags, NULL, NULL);
|
||||
if (GSS_ERROR(major))
|
||||
{
|
||||
|
||||
log_error(major, minor, "gss_accept_sec_context");
|
||||
rc= CR_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* send token to peer */
|
||||
if (output.length)
|
||||
{
|
||||
if (vio->write_packet(vio, (const uchar *) output.value, output.length))
|
||||
{
|
||||
gss_release_buffer(&minor, &output);
|
||||
log_error(major, minor, "communication error(write)");
|
||||
goto cleanup;
|
||||
}
|
||||
gss_release_buffer(&minor, &output);
|
||||
}
|
||||
} while (major & GSS_S_CONTINUE_NEEDED);
|
||||
|
||||
/* extract plain text client name */
|
||||
major= gss_display_name(&minor, client_name, &client_name_buf, NULL);
|
||||
if (GSS_ERROR(major))
|
||||
{
|
||||
log_error(major, minor, "gss_display_name");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
client_name_str= (char *)client_name_buf.value;
|
||||
|
||||
/*
|
||||
* Compare input user name with the actual one. Return success if
|
||||
* the names match exactly, or if use_full_name parameter is not set
|
||||
* up to the '@' separator.
|
||||
*/
|
||||
if ((userlen == client_name_buf.length) ||
|
||||
(!use_full_name
|
||||
&& userlen < client_name_buf.length
|
||||
&& client_name_str[userlen] == '@'))
|
||||
{
|
||||
if (strncmp(client_name_str, user, userlen) == 0)
|
||||
{
|
||||
rc= CR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if(rc != CR_OK)
|
||||
{
|
||||
my_printf_error(ER_ACCESS_DENIED_ERROR,
|
||||
"GSSAPI name mismatch, requested '%s', actual name '%.*s'",
|
||||
MYF(0), user, (int)client_name_buf.length, client_name_str);
|
||||
}
|
||||
|
||||
gss_release_buffer(&minor, &client_name_buf);
|
||||
|
||||
|
||||
cleanup:
|
||||
if (ctxt != GSS_C_NO_CONTEXT)
|
||||
gss_delete_sec_context(&minor, &ctxt, GSS_C_NO_BUFFER);
|
||||
if (cred != GSS_C_NO_CREDENTIAL)
|
||||
gss_release_cred(&minor, &cred);
|
||||
|
||||
return(rc);
|
||||
}
|
18
plugin/auth_gssapi/mysql-test/auth_gssapi/basic.result
Normal file
18
plugin/auth_gssapi/mysql-test/auth_gssapi/basic.result
Normal file
@ -0,0 +1,18 @@
|
||||
INSTALL SONAME 'auth_gssapi';
|
||||
CREATE USER 'GSSAPI_SHORTNAME' IDENTIFIED WITH gssapi;
|
||||
SELECT USER(),CURRENT_USER();
|
||||
USER() CURRENT_USER()
|
||||
GSSAPI_SHORTNAME@localhost GSSAPI_SHORTNAME@%
|
||||
DROP USER 'GSSAPI_SHORTNAME';
|
||||
CREATE USER nosuchuser IDENTIFIED WITH gssapi;
|
||||
ERROR 28000: GSSAPI name mismatch, requested 'nosuchuser', actual name 'GSSAPI_SHORTNAME'
|
||||
DROP USER nosuchuser;
|
||||
CREATE USER usr1 IDENTIFIED WITH gssapi as 'GSSAPI_FULLNAME';
|
||||
SELECT USER(),CURRENT_USER();
|
||||
USER() CURRENT_USER()
|
||||
usr1@localhost usr1@%
|
||||
DROP USER usr1;
|
||||
CREATE USER nosuchuser IDENTIFIED WITH gssapi AS 'nosuchuser@EXAMPLE.COM';
|
||||
ERROR 28000: GSSAPI name mismatch, requested 'nosuchuser@EXAMPLE.COM', actual name 'GSSAPI_FULLNAME'
|
||||
DROP USER nosuchuser;
|
||||
UNINSTALL SONAME 'auth_gssapi';
|
45
plugin/auth_gssapi/mysql-test/auth_gssapi/basic.test
Normal file
45
plugin/auth_gssapi/mysql-test/auth_gssapi/basic.test
Normal file
@ -0,0 +1,45 @@
|
||||
INSTALL SONAME 'auth_gssapi';
|
||||
|
||||
#
|
||||
# CREATE USER without 'AS' clause
|
||||
#
|
||||
--replace_result $GSSAPI_SHORTNAME GSSAPI_SHORTNAME
|
||||
eval CREATE USER '$GSSAPI_SHORTNAME' IDENTIFIED WITH gssapi;
|
||||
connect (con1,localhost,$GSSAPI_SHORTNAME,,);
|
||||
--replace_result $GSSAPI_SHORTNAME GSSAPI_SHORTNAME
|
||||
SELECT USER(),CURRENT_USER();
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
--replace_result $GSSAPI_SHORTNAME GSSAPI_SHORTNAME
|
||||
eval DROP USER '$GSSAPI_SHORTNAME';
|
||||
|
||||
CREATE USER nosuchuser IDENTIFIED WITH gssapi;
|
||||
--disable_query_log
|
||||
--replace_regex /actual name '.*'/actual name 'GSSAPI_SHORTNAME'/
|
||||
--error ER_ACCESS_DENIED_ERROR
|
||||
connect (con1,localhost,nosuchuser,,);
|
||||
--enable_query_log
|
||||
DROP USER nosuchuser;
|
||||
|
||||
#
|
||||
# CREATE USER with 'AS' clause
|
||||
#
|
||||
--replace_result $GSSAPI_FULLNAME GSSAPI_FULLNAME
|
||||
eval CREATE USER usr1 IDENTIFIED WITH gssapi as '$GSSAPI_FULLNAME';
|
||||
connect (con1,localhost,usr1,,);
|
||||
--replace_result $GSSAPI_FULLNAME GSSAPI_FULLNAME
|
||||
SELECT USER(),CURRENT_USER();
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP USER usr1;
|
||||
|
||||
CREATE USER nosuchuser IDENTIFIED WITH gssapi AS 'nosuchuser@EXAMPLE.COM';
|
||||
--disable_query_log
|
||||
--replace_regex /actual name '.*'/actual name 'GSSAPI_FULLNAME'/
|
||||
--error ER_ACCESS_DENIED_ERROR
|
||||
connect (con1,localhost,nosuchuser,,);
|
||||
--enable_query_log
|
||||
DROP USER nosuchuser;
|
||||
|
||||
UNINSTALL SONAME 'auth_gssapi';
|
1
plugin/auth_gssapi/mysql-test/auth_gssapi/suite.opt
Normal file
1
plugin/auth_gssapi/mysql-test/auth_gssapi/suite.opt
Normal file
@ -0,0 +1 @@
|
||||
--loose-gssapi-keytab-path=$GSSAPI_KEYTAB_PATH --loose-gssapi-principal-name=$GSSAPI_PRINCIPAL_NAME
|
49
plugin/auth_gssapi/mysql-test/auth_gssapi/suite.pm
Normal file
49
plugin/auth_gssapi/mysql-test/auth_gssapi/suite.pm
Normal file
@ -0,0 +1,49 @@
|
||||
package My::Suite::AuthGSSAPI;
|
||||
|
||||
@ISA = qw(My::Suite);
|
||||
|
||||
return "No AUTH_GSSAPI plugin" unless $ENV{AUTH_GSSAPI_SO};
|
||||
|
||||
return "Not run for embedded server" if $::opt_embedded_server;
|
||||
|
||||
# Following environment variables may need to be set
|
||||
if ($^O eq "MSWin32")
|
||||
{
|
||||
chomp(my $whoami =`whoami /UPN 2>NUL` || `whoami`);
|
||||
my $fullname = $whoami;
|
||||
$fullname =~ s/\\/\\\\/; # SQL escaping for backslash
|
||||
$ENV{'GSSAPI_FULLNAME'} = $fullname;
|
||||
$ENV{'GSSAPI_SHORTNAME'} = $ENV{'USERNAME'};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$ENV{'GSSAPI_FULLNAME'})
|
||||
{
|
||||
my $s = `klist |grep 'Default principal: '`;
|
||||
if ($s)
|
||||
{
|
||||
chomp($s);
|
||||
my $fullname = substr($s,19);
|
||||
$ENV{'GSSAPI_FULLNAME'} = $fullname;
|
||||
}
|
||||
}
|
||||
$ENV{'GSSAPI_SHORTNAME'} = (split /@/, $ENV{'GSSAPI_FULLNAME'}) [0];
|
||||
}
|
||||
|
||||
|
||||
if (!$ENV{'GSSAPI_FULLNAME'} || !$ENV{'GSSAPI_SHORTNAME'})
|
||||
{
|
||||
return "Environment variable GSSAPI_SHORTNAME and GSSAPI_FULLNAME need to be set"
|
||||
}
|
||||
|
||||
if ($::opt_verbose)
|
||||
{
|
||||
foreach $var ('GSSAPI_SHORTNAME','GSSAPI_FULLNAME','GSSAPI_KEYTAB_PATH','GSSAPI_PRINCIPAL_NAME')
|
||||
{
|
||||
print "$var=$ENV{$var}\n";
|
||||
}
|
||||
}
|
||||
sub is_default { 1 }
|
||||
|
||||
bless { };
|
||||
|
183
plugin/auth_gssapi/server_plugin.cc
Normal file
183
plugin/auth_gssapi/server_plugin.cc
Normal file
@ -0,0 +1,183 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file
|
||||
|
||||
GSSAPI authentication plugin, server side
|
||||
*/
|
||||
#include <my_sys.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <mysql/plugin_auth.h>
|
||||
#include "server_plugin.h"
|
||||
#include "common.h"
|
||||
|
||||
/* First packet sent from server to client, contains srv_principal_name\0mech\0 */
|
||||
static char first_packet[PRINCIPAL_NAME_MAX + MECH_NAME_MAX +2];
|
||||
static int first_packet_len;
|
||||
|
||||
/*
|
||||
Target name in GSSAPI/SSPI , for Kerberos it is service principal name
|
||||
(often user principal name of the server user will work)
|
||||
*/
|
||||
char *srv_principal_name;
|
||||
char *srv_keytab_path;
|
||||
char *srv_mech_name=(char *)"";
|
||||
unsigned long srv_mech;
|
||||
|
||||
/**
|
||||
The main server function of the GSSAPI plugin.
|
||||
*/
|
||||
static int gssapi_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info)
|
||||
{
|
||||
int use_full_name;
|
||||
const char *user;
|
||||
int user_len;
|
||||
|
||||
/* No user name yet ? Read the client handshake packet with the user name. */
|
||||
if (auth_info->user_name == 0)
|
||||
{
|
||||
unsigned char *pkt;
|
||||
if (vio->read_packet(vio, &pkt) < 0)
|
||||
return CR_ERROR;
|
||||
}
|
||||
|
||||
/* Send first packet with target name and mech name */
|
||||
if (vio->write_packet(vio, (unsigned char *)first_packet, first_packet_len))
|
||||
{
|
||||
return CR_ERROR;
|
||||
}
|
||||
|
||||
/* Figure out whether to use full name (as given in IDENTIFIED AS clause)
|
||||
* or just short username auth_string
|
||||
*/
|
||||
if (auth_info->auth_string_length > 0)
|
||||
{
|
||||
use_full_name= 1;
|
||||
user= auth_info->auth_string;
|
||||
user_len= auth_info->auth_string_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
use_full_name= 0;
|
||||
user= auth_info->user_name;
|
||||
user_len= auth_info->user_name_length;
|
||||
}
|
||||
|
||||
return auth_server(vio, user, user_len, use_full_name);
|
||||
}
|
||||
|
||||
static int initialize_plugin(void *unused)
|
||||
{
|
||||
int rc;
|
||||
rc = plugin_init();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
strcpy(first_packet, srv_principal_name);
|
||||
strcpy(first_packet + strlen(srv_principal_name) + 1,srv_mech_name);
|
||||
first_packet_len = strlen(srv_principal_name) + strlen(srv_mech_name) + 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int deinitialize_plugin(void *unused)
|
||||
{
|
||||
return plugin_deinit();
|
||||
}
|
||||
|
||||
/* system variable */
|
||||
static MYSQL_SYSVAR_STR(keytab_path, srv_keytab_path,
|
||||
PLUGIN_VAR_RQCMDARG|PLUGIN_VAR_READONLY,
|
||||
"Keytab file path for Kerberos authentication",
|
||||
NULL,
|
||||
NULL,
|
||||
"");
|
||||
static MYSQL_SYSVAR_STR(principal_name, srv_principal_name,
|
||||
PLUGIN_VAR_RQCMDARG|PLUGIN_VAR_READONLY,
|
||||
"GSSAPI target name - service principal name for Kerberos authentication.",
|
||||
NULL,
|
||||
NULL,
|
||||
"");
|
||||
#ifdef PLUGIN_SSPI
|
||||
static const char* mech_names[] = {
|
||||
"Kerberos",
|
||||
"Negotiate",
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
static TYPELIB mech_name_typelib = {
|
||||
array_elements(mech_names) - 1,
|
||||
"mech_name_typelib",
|
||||
mech_names,
|
||||
NULL
|
||||
};
|
||||
static MYSQL_SYSVAR_ENUM(mech_name, srv_mech,
|
||||
PLUGIN_VAR_RQCMDARG|PLUGIN_VAR_READONLY,
|
||||
"GSSAPI mechanism",
|
||||
NULL,
|
||||
NULL,
|
||||
2,&mech_name_typelib);
|
||||
#endif
|
||||
|
||||
static struct st_mysql_sys_var *system_variables[]= {
|
||||
MYSQL_SYSVAR(principal_name),
|
||||
#ifdef PLUGIN_SSPI
|
||||
MYSQL_SYSVAR(mech_name),
|
||||
#endif
|
||||
#ifdef PLUGIN_GSSAPI
|
||||
MYSQL_SYSVAR(keytab_path),
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Register authentication plugin */
|
||||
static struct st_mysql_auth server_handler= {
|
||||
MYSQL_AUTHENTICATION_INTERFACE_VERSION,
|
||||
"auth_gssapi_client",
|
||||
gssapi_auth
|
||||
};
|
||||
|
||||
maria_declare_plugin(gssapi_server)
|
||||
{
|
||||
MYSQL_AUTHENTICATION_PLUGIN,
|
||||
&server_handler,
|
||||
"gssapi",
|
||||
"Shuang Qiu, Robbie Harwood, Vladislav Vaintroub",
|
||||
"Plugin for GSSAPI/SSPI based authentication.",
|
||||
PLUGIN_LICENSE_BSD,
|
||||
initialize_plugin,
|
||||
deinitialize_plugin, /* destructor */
|
||||
0x0100, /* version */
|
||||
NULL, /* status variables */
|
||||
system_variables, /* system variables */
|
||||
"1.0",
|
||||
MariaDB_PLUGIN_MATURITY_BETA
|
||||
}
|
||||
maria_declare_plugin_end;
|
||||
|
51
plugin/auth_gssapi/server_plugin.h
Normal file
51
plugin/auth_gssapi/server_plugin.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Plugin variables*/
|
||||
#include <mysql/plugin_auth.h>
|
||||
typedef enum
|
||||
{
|
||||
PLUGIN_MECH_KERBEROS = 0,
|
||||
PLUGIN_MECH_SPNEGO = 1,
|
||||
PLUGIN_MECH_DEFAULT = 2
|
||||
}PLUGIN_MECH;
|
||||
|
||||
extern unsigned long srv_mech;
|
||||
extern char *srv_principal_name;
|
||||
extern char *srv_mech_name;
|
||||
extern char *srv_keytab_path;
|
||||
/*
|
||||
Check, with GSSAPI/SSPI username of logged on user.
|
||||
|
||||
Depending on use_full_name parameter, compare either full name
|
||||
(principal name like user@real), or local name (first component)
|
||||
*/
|
||||
int plugin_init();
|
||||
int plugin_deinit();
|
||||
|
||||
int auth_server(MYSQL_PLUGIN_VIO *vio, const char *username, size_t username_len, int use_full_name);
|
38
plugin/auth_gssapi/sspi.h
Normal file
38
plugin/auth_gssapi/sspi.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define SECURITY_WIN32
|
||||
#include <windows.h>
|
||||
#include <sspi.h>
|
||||
#include <SecExt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define SSPI_MAX_TOKEN_SIZE 50000
|
||||
#define SEC_ERROR(err) (err < 0)
|
||||
extern void sspi_errmsg(int err, char *buf, size_t size);
|
183
plugin/auth_gssapi/sspi_client.cc
Normal file
183
plugin/auth_gssapi/sspi_client.cc
Normal file
@ -0,0 +1,183 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define SECURITY_WIN32
|
||||
#include <windows.h>
|
||||
#include <sspi.h>
|
||||
#include <SecExt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <mysql/plugin_auth.h>
|
||||
#include <mysql.h>
|
||||
#include <mysqld_error.h>
|
||||
|
||||
#include "sspi.h"
|
||||
|
||||
extern void log_client_error(MYSQL *mysql, const char *fmt, ...);
|
||||
static void log_error(MYSQL *mysql, SECURITY_STATUS err, const char *msg)
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
char buf[1024];
|
||||
sspi_errmsg(err, buf, sizeof(buf));
|
||||
log_client_error(mysql, "SSPI client error 0x%x - %s - %s", err, msg, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_client_error(mysql, "SSPI client error %s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Client side authentication*/
|
||||
int auth_client(char *principal_name, char *mech, MYSQL *mysql, MYSQL_PLUGIN_VIO *vio)
|
||||
{
|
||||
|
||||
int ret;
|
||||
CredHandle cred;
|
||||
CtxtHandle ctxt;
|
||||
ULONG attribs = 0;
|
||||
TimeStamp lifetime;
|
||||
SECURITY_STATUS sspi_err;
|
||||
|
||||
SecBufferDesc inbuf_desc;
|
||||
SecBuffer inbuf;
|
||||
SecBufferDesc outbuf_desc;
|
||||
SecBuffer outbuf;
|
||||
PBYTE out = NULL;
|
||||
|
||||
ret= CR_ERROR;
|
||||
SecInvalidateHandle(&ctxt);
|
||||
SecInvalidateHandle(&cred);
|
||||
|
||||
if (!mech || strcmp(mech, "Negotiate") != 0)
|
||||
{
|
||||
mech= "Kerberos";
|
||||
}
|
||||
|
||||
sspi_err = AcquireCredentialsHandle(
|
||||
NULL,
|
||||
mech,
|
||||
SECPKG_CRED_OUTBOUND,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&cred,
|
||||
&lifetime);
|
||||
|
||||
if (SEC_ERROR(sspi_err))
|
||||
{
|
||||
log_error(mysql, sspi_err, "AcquireCredentialsHandle");
|
||||
return CR_ERROR;
|
||||
}
|
||||
|
||||
out = (PBYTE)malloc(SSPI_MAX_TOKEN_SIZE);
|
||||
if (!out)
|
||||
{
|
||||
log_error(mysql, SEC_E_OK, "memory allocation error");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Prepare buffers */
|
||||
inbuf_desc.ulVersion = SECBUFFER_VERSION;
|
||||
inbuf_desc.cBuffers = 1;
|
||||
inbuf_desc.pBuffers = &inbuf;
|
||||
inbuf.BufferType = SECBUFFER_TOKEN;
|
||||
inbuf.cbBuffer = 0;
|
||||
inbuf.pvBuffer = NULL;
|
||||
|
||||
outbuf_desc.ulVersion = SECBUFFER_VERSION;
|
||||
outbuf_desc.cBuffers = 1;
|
||||
outbuf_desc.pBuffers = &outbuf;
|
||||
outbuf.BufferType = SECBUFFER_TOKEN;
|
||||
outbuf.pvBuffer = out;
|
||||
|
||||
do
|
||||
{
|
||||
outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE;
|
||||
sspi_err= InitializeSecurityContext(
|
||||
&cred,
|
||||
SecIsValidHandle(&ctxt) ? &ctxt : NULL,
|
||||
principal_name,
|
||||
0,
|
||||
0,
|
||||
SECURITY_NATIVE_DREP,
|
||||
inbuf.cbBuffer ? &inbuf_desc : NULL,
|
||||
0,
|
||||
&ctxt,
|
||||
&outbuf_desc,
|
||||
&attribs,
|
||||
&lifetime);
|
||||
if (SEC_ERROR(sspi_err))
|
||||
{
|
||||
log_error(mysql, sspi_err, "InitializeSecurityContext");
|
||||
goto cleanup;
|
||||
}
|
||||
if (sspi_err != SEC_E_OK && sspi_err != SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
log_error(mysql, sspi_err, "Unexpected response from InitializeSecurityContext");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (outbuf.cbBuffer)
|
||||
{
|
||||
/* send credential to server */
|
||||
if (vio->write_packet(vio, (unsigned char *)outbuf.pvBuffer, outbuf.cbBuffer))
|
||||
{
|
||||
/* Server error packet contains detailed message. */
|
||||
ret= CR_OK_HANDSHAKE_COMPLETE;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (sspi_err == SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
int len= vio->read_packet(vio, (unsigned char **)&inbuf.pvBuffer);
|
||||
if (len <= 0)
|
||||
{
|
||||
/* Server side error is in the last server packet. */
|
||||
ret= CR_OK_HANDSHAKE_COMPLETE;
|
||||
goto cleanup;
|
||||
}
|
||||
inbuf.cbBuffer= len;
|
||||
}
|
||||
} while (sspi_err == SEC_I_CONTINUE_NEEDED);
|
||||
|
||||
ret= CR_OK;
|
||||
|
||||
cleanup:
|
||||
|
||||
if (SecIsValidHandle(&ctxt))
|
||||
DeleteSecurityContext(&ctxt);
|
||||
if (SecIsValidHandle(&cred))
|
||||
FreeCredentialsHandle(&cred);
|
||||
free(out);
|
||||
return ret;
|
||||
}
|
150
plugin/auth_gssapi/sspi_errmsg.cc
Normal file
150
plugin/auth_gssapi/sspi_errmsg.cc
Normal file
@ -0,0 +1,150 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ERRSYM(x) {x, #x}
|
||||
static struct {
|
||||
int error;
|
||||
const char *sym;
|
||||
} error_symbols[] =
|
||||
{
|
||||
ERRSYM(SEC_E_OK),
|
||||
ERRSYM(SEC_E_INSUFFICIENT_MEMORY),
|
||||
ERRSYM(SEC_E_INVALID_HANDLE),
|
||||
ERRSYM(SEC_E_UNSUPPORTED_FUNCTION),
|
||||
ERRSYM(SEC_E_TARGET_UNKNOWN),
|
||||
ERRSYM(SEC_E_INTERNAL_ERROR),
|
||||
ERRSYM(SEC_E_SECPKG_NOT_FOUND),
|
||||
ERRSYM(SEC_E_NOT_OWNER),
|
||||
ERRSYM(SEC_E_CANNOT_INSTALL),
|
||||
ERRSYM(SEC_E_INVALID_TOKEN),
|
||||
ERRSYM(SEC_E_CANNOT_PACK),
|
||||
ERRSYM(SEC_E_QOP_NOT_SUPPORTED),
|
||||
ERRSYM(SEC_E_NO_IMPERSONATION),
|
||||
ERRSYM(SEC_E_LOGON_DENIED),
|
||||
ERRSYM(SEC_E_UNKNOWN_CREDENTIALS),
|
||||
ERRSYM(SEC_E_NO_CREDENTIALS),
|
||||
ERRSYM(SEC_E_MESSAGE_ALTERED),
|
||||
ERRSYM(SEC_E_OUT_OF_SEQUENCE),
|
||||
ERRSYM(SEC_E_NO_AUTHENTICATING_AUTHORITY),
|
||||
ERRSYM(SEC_E_BAD_PKGID),
|
||||
ERRSYM(SEC_E_CONTEXT_EXPIRED),
|
||||
ERRSYM(SEC_E_INCOMPLETE_MESSAGE),
|
||||
ERRSYM(SEC_E_INCOMPLETE_CREDENTIALS),
|
||||
ERRSYM(SEC_E_BUFFER_TOO_SMALL),
|
||||
ERRSYM(SEC_E_WRONG_PRINCIPAL),
|
||||
ERRSYM(SEC_E_TIME_SKEW),
|
||||
ERRSYM(SEC_E_UNTRUSTED_ROOT),
|
||||
ERRSYM(SEC_E_ILLEGAL_MESSAGE),
|
||||
ERRSYM(SEC_E_CERT_UNKNOWN),
|
||||
ERRSYM(SEC_E_CERT_EXPIRED),
|
||||
ERRSYM(SEC_E_ENCRYPT_FAILURE),
|
||||
ERRSYM(SEC_E_DECRYPT_FAILURE),
|
||||
ERRSYM(SEC_E_ALGORITHM_MISMATCH),
|
||||
ERRSYM(SEC_E_SECURITY_QOS_FAILED),
|
||||
ERRSYM(SEC_E_UNFINISHED_CONTEXT_DELETED),
|
||||
ERRSYM(SEC_E_NO_TGT_REPLY),
|
||||
ERRSYM(SEC_E_NO_IP_ADDRESSES),
|
||||
ERRSYM(SEC_E_WRONG_CREDENTIAL_HANDLE),
|
||||
ERRSYM(SEC_E_CRYPTO_SYSTEM_INVALID),
|
||||
ERRSYM(SEC_E_MAX_REFERRALS_EXCEEDED),
|
||||
ERRSYM(SEC_E_MUST_BE_KDC),
|
||||
ERRSYM(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED),
|
||||
ERRSYM(SEC_E_TOO_MANY_PRINCIPALS),
|
||||
ERRSYM(SEC_E_NO_PA_DATA),
|
||||
ERRSYM(SEC_E_PKINIT_NAME_MISMATCH),
|
||||
ERRSYM(SEC_E_SMARTCARD_LOGON_REQUIRED),
|
||||
ERRSYM(SEC_E_SHUTDOWN_IN_PROGRESS),
|
||||
ERRSYM(SEC_E_KDC_INVALID_REQUEST),
|
||||
ERRSYM(SEC_E_KDC_UNABLE_TO_REFER),
|
||||
ERRSYM(SEC_E_KDC_UNKNOWN_ETYPE),
|
||||
ERRSYM(SEC_E_UNSUPPORTED_PREAUTH),
|
||||
ERRSYM(SEC_E_DELEGATION_REQUIRED),
|
||||
ERRSYM(SEC_E_BAD_BINDINGS),
|
||||
ERRSYM(SEC_E_MULTIPLE_ACCOUNTS),
|
||||
ERRSYM(SEC_E_NO_KERB_KEY),
|
||||
ERRSYM(SEC_E_CERT_WRONG_USAGE),
|
||||
ERRSYM(SEC_E_DOWNGRADE_DETECTED),
|
||||
ERRSYM(SEC_E_SMARTCARD_CERT_REVOKED),
|
||||
ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED),
|
||||
ERRSYM(SEC_E_REVOCATION_OFFLINE_C),
|
||||
ERRSYM(SEC_E_PKINIT_CLIENT_FAILURE),
|
||||
ERRSYM(SEC_E_SMARTCARD_CERT_EXPIRED),
|
||||
ERRSYM(SEC_E_NO_S4U_PROT_SUPPORT),
|
||||
ERRSYM(SEC_E_CROSSREALM_DELEGATION_FAILURE),
|
||||
ERRSYM(SEC_E_REVOCATION_OFFLINE_KDC),
|
||||
ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED_KDC),
|
||||
ERRSYM(SEC_E_KDC_CERT_EXPIRED),
|
||||
ERRSYM(SEC_E_KDC_CERT_REVOKED),
|
||||
ERRSYM(SEC_E_INVALID_PARAMETER),
|
||||
ERRSYM(SEC_E_DELEGATION_POLICY),
|
||||
ERRSYM(SEC_E_POLICY_NLTM_ONLY),
|
||||
ERRSYM(SEC_E_NO_CONTEXT),
|
||||
ERRSYM(SEC_E_PKU2U_CERT_FAILURE),
|
||||
ERRSYM(SEC_E_MUTUAL_AUTH_FAILED),
|
||||
ERRSYM(SEC_E_NO_SPM),
|
||||
ERRSYM(SEC_E_NOT_SUPPORTED),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
void sspi_errmsg(int err, char *buf, size_t size)
|
||||
{
|
||||
buf[size - 1] = 0;
|
||||
size_t len;
|
||||
|
||||
for (size_t i= 0; error_symbols[i].sym; i++)
|
||||
{
|
||||
if (error_symbols[i].error == err)
|
||||
{
|
||||
size_t len= strlen(error_symbols[i].sym);
|
||||
if (len + 2 < size)
|
||||
{
|
||||
memcpy(buf, error_symbols[i].sym, len);
|
||||
buf[len]= ' ';
|
||||
buf += len + 1;
|
||||
size-= len + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
len = FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
|
||||
err, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
||||
buf, size, NULL);
|
||||
|
||||
if(len > 0)
|
||||
{
|
||||
/* Trim trailing \n\r*/
|
||||
char *p;
|
||||
for(p= buf + len;p > buf && (*p == '\n' || *p=='\r' || *p == 0);p--)
|
||||
*p= 0;
|
||||
}
|
||||
}
|
312
plugin/auth_gssapi/sspi_server.cc
Normal file
312
plugin/auth_gssapi/sspi_server.cc
Normal file
@ -0,0 +1,312 @@
|
||||
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
|
||||
Vladislav Vaintroub & MariaDB Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sspi.h"
|
||||
#include "common.h"
|
||||
#include "server_plugin.h"
|
||||
#include <mysql/plugin_auth.h>
|
||||
#include <my_sys.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <log.h>
|
||||
|
||||
|
||||
/* This sends the error to the client */
|
||||
static void log_error(SECURITY_STATUS err, const char *msg)
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
char buf[1024];
|
||||
sspi_errmsg(err, buf, sizeof(buf));
|
||||
my_printf_error(ER_UNKNOWN_ERROR, "SSPI server error 0x%x - %s - %s", MYF(0), msg, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
my_printf_error(ER_UNKNOWN_ERROR, "SSPI server error %s", MYF(0), msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static char INVALID_KERBEROS_PRINCIPAL[] = "localhost";
|
||||
|
||||
static char *get_default_principal_name()
|
||||
{
|
||||
static char default_principal[PRINCIPAL_NAME_MAX +1];
|
||||
ULONG size= sizeof(default_principal);
|
||||
|
||||
if (GetUserNameEx(NameUserPrincipal,default_principal,&size))
|
||||
return default_principal;
|
||||
|
||||
size= sizeof(default_principal);
|
||||
if (GetUserNameEx(NameServicePrincipal,default_principal,&size))
|
||||
return default_principal;
|
||||
|
||||
char domain[PRINCIPAL_NAME_MAX+1];
|
||||
char host[PRINCIPAL_NAME_MAX+1];
|
||||
size= sizeof(domain);
|
||||
if (GetComputerNameEx(ComputerNameDnsDomain,domain,&size) && size > 0)
|
||||
{
|
||||
size= sizeof(host);
|
||||
if (GetComputerNameEx(ComputerNameDnsHostname,host,&size))
|
||||
{
|
||||
_snprintf(default_principal,sizeof(default_principal),"%s$@%s",host, domain);
|
||||
return default_principal;
|
||||
}
|
||||
}
|
||||
/* Unable to retrieve useful name, return something */
|
||||
return INVALID_KERBEROS_PRINCIPAL;
|
||||
}
|
||||
|
||||
|
||||
/* Extract client name from SSPI context */
|
||||
static int get_client_name_from_context(CtxtHandle *ctxt,
|
||||
char *name,
|
||||
size_t name_len,
|
||||
int use_full_name)
|
||||
{
|
||||
SecPkgContext_NativeNames native_names;
|
||||
SECURITY_STATUS sspi_ret;
|
||||
char *p;
|
||||
|
||||
sspi_ret= QueryContextAttributes(ctxt, SECPKG_ATTR_NATIVE_NAMES, &native_names);
|
||||
if (sspi_ret == SEC_E_OK)
|
||||
{
|
||||
/* Extract user from Kerberos principal name user@realm */
|
||||
if(!use_full_name)
|
||||
{
|
||||
p = strrchr(native_names.sClientName,'@');
|
||||
if(p)
|
||||
*p = 0;
|
||||
}
|
||||
strncpy(name, native_names.sClientName, name_len);
|
||||
FreeContextBuffer(&native_names);
|
||||
return CR_OK;
|
||||
}
|
||||
|
||||
sspi_ret= ImpersonateSecurityContext(ctxt);
|
||||
if (sspi_ret == SEC_E_OK)
|
||||
{
|
||||
ULONG len= name_len;
|
||||
if (!GetUserNameEx(NameSamCompatible, name, &len))
|
||||
{
|
||||
log_error(GetLastError(), "GetUserNameEx");
|
||||
RevertSecurityContext(ctxt);
|
||||
return CR_ERROR;
|
||||
}
|
||||
RevertSecurityContext(ctxt);
|
||||
|
||||
/* Extract user from Windows name realm\user */
|
||||
if (!use_full_name)
|
||||
{
|
||||
p = strrchr(name, '\\');
|
||||
if (p)
|
||||
{
|
||||
p++;
|
||||
memmove(name, p, name + len + 1 - p);
|
||||
}
|
||||
}
|
||||
return CR_OK;
|
||||
}
|
||||
|
||||
log_error(sspi_ret, "ImpersonateSecurityContext");
|
||||
return CR_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int auth_server(MYSQL_PLUGIN_VIO *vio, const char *user, size_t user_len, int compare_full_name)
|
||||
{
|
||||
int ret;
|
||||
SECURITY_STATUS sspi_ret;
|
||||
ULONG attribs = 0;
|
||||
TimeStamp lifetime;
|
||||
CredHandle cred;
|
||||
CtxtHandle ctxt;
|
||||
|
||||
SecBufferDesc inbuf_desc;
|
||||
SecBuffer inbuf;
|
||||
SecBufferDesc outbuf_desc;
|
||||
SecBuffer outbuf;
|
||||
void* out= NULL;
|
||||
char client_name[MYSQL_USERNAME_LENGTH + 1];
|
||||
|
||||
ret= CR_ERROR;
|
||||
SecInvalidateHandle(&cred);
|
||||
SecInvalidateHandle(&ctxt);
|
||||
|
||||
out= malloc(SSPI_MAX_TOKEN_SIZE);
|
||||
if (!out)
|
||||
{
|
||||
log_error(SEC_E_OK, "memory allocation failed");
|
||||
goto cleanup;
|
||||
}
|
||||
sspi_ret= AcquireCredentialsHandle(
|
||||
srv_principal_name,
|
||||
srv_mech_name,
|
||||
SECPKG_CRED_INBOUND,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&cred,
|
||||
&lifetime);
|
||||
|
||||
if (SEC_ERROR(sspi_ret))
|
||||
{
|
||||
log_error(sspi_ret, "AcquireCredentialsHandle failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
inbuf.cbBuffer= 0;
|
||||
inbuf.BufferType= SECBUFFER_TOKEN;
|
||||
inbuf.pvBuffer= NULL;
|
||||
inbuf_desc.ulVersion= SECBUFFER_VERSION;
|
||||
inbuf_desc.cBuffers= 1;
|
||||
inbuf_desc.pBuffers= &inbuf;
|
||||
|
||||
outbuf.BufferType= SECBUFFER_TOKEN;
|
||||
outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE;
|
||||
outbuf.pvBuffer= out;
|
||||
|
||||
outbuf_desc.ulVersion= SECBUFFER_VERSION;
|
||||
outbuf_desc.cBuffers= 1;
|
||||
outbuf_desc.pBuffers= &outbuf;
|
||||
|
||||
do
|
||||
{
|
||||
/* Read SSPI blob from client. */
|
||||
int len= vio->read_packet(vio, (unsigned char **)&inbuf.pvBuffer);
|
||||
if (len < 0)
|
||||
{
|
||||
log_error(SEC_E_OK, "communication error(read)");
|
||||
goto cleanup;
|
||||
}
|
||||
inbuf.cbBuffer= len;
|
||||
outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE;
|
||||
sspi_ret= AcceptSecurityContext(
|
||||
&cred,
|
||||
SecIsValidHandle(&ctxt) ? &ctxt : NULL,
|
||||
&inbuf_desc,
|
||||
attribs,
|
||||
SECURITY_NATIVE_DREP,
|
||||
&ctxt,
|
||||
&outbuf_desc,
|
||||
&attribs,
|
||||
&lifetime);
|
||||
|
||||
if (SEC_ERROR(sspi_ret))
|
||||
{
|
||||
log_error(sspi_ret, "AcceptSecurityContext");
|
||||
goto cleanup;
|
||||
}
|
||||
if (sspi_ret != SEC_E_OK && sspi_ret != SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
log_error(sspi_ret, "AcceptSecurityContext unexpected return value");
|
||||
goto cleanup;
|
||||
}
|
||||
if (outbuf.cbBuffer)
|
||||
{
|
||||
/* Send generated blob to client. */
|
||||
if (vio->write_packet(vio, (unsigned char *)outbuf.pvBuffer, outbuf.cbBuffer))
|
||||
{
|
||||
log_error(SEC_E_OK, "communicaton error(write)");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
} while (sspi_ret == SEC_I_CONTINUE_NEEDED);
|
||||
|
||||
/* Authentication done, now extract and compare user name. */
|
||||
ret= get_client_name_from_context(&ctxt, client_name, MYSQL_USERNAME_LENGTH, compare_full_name);
|
||||
if (ret != CR_OK)
|
||||
goto cleanup;
|
||||
|
||||
/* Always compare case-insensitive on Windows. */
|
||||
ret= _stricmp(client_name, user) == 0 ? CR_OK : CR_ERROR;
|
||||
if (ret != CR_OK)
|
||||
{
|
||||
my_printf_error(ER_ACCESS_DENIED_ERROR,
|
||||
"GSSAPI name mismatch, requested '%s', actual name '%s'",
|
||||
MYF(0), user, client_name);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (SecIsValidHandle(&ctxt))
|
||||
DeleteSecurityContext(&ctxt);
|
||||
|
||||
if (SecIsValidHandle(&cred))
|
||||
FreeCredentialsHandle(&cred);
|
||||
|
||||
free(out);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int plugin_init()
|
||||
{
|
||||
CredHandle cred;
|
||||
SECURITY_STATUS ret;
|
||||
|
||||
/*
|
||||
Use negotiate by default, which accepts raw kerberos
|
||||
and also NTLM.
|
||||
*/
|
||||
if (srv_mech == PLUGIN_MECH_DEFAULT)
|
||||
srv_mech= PLUGIN_MECH_SPNEGO;
|
||||
|
||||
if(srv_mech == PLUGIN_MECH_KERBEROS)
|
||||
srv_mech_name= "Kerberos";
|
||||
else if(srv_mech == PLUGIN_MECH_SPNEGO )
|
||||
srv_mech_name= "Negotiate";
|
||||
|
||||
if(!srv_principal_name[0])
|
||||
{
|
||||
srv_principal_name= get_default_principal_name();
|
||||
}
|
||||
sql_print_information("SSPI: using principal name '%s', mech '%s'",
|
||||
srv_principal_name, srv_mech_name);
|
||||
|
||||
ret = AcquireCredentialsHandle(
|
||||
srv_principal_name,
|
||||
srv_mech_name,
|
||||
SECPKG_CRED_INBOUND,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&cred,
|
||||
NULL);
|
||||
if (SEC_ERROR(ret))
|
||||
{
|
||||
log_error(ret, "AcquireCredentialsHandle");
|
||||
return -1;
|
||||
}
|
||||
FreeCredentialsHandle(&cred);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plugin_deinit()
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -127,13 +127,13 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
|
||||
s++;
|
||||
}
|
||||
from= s;
|
||||
skip(isalnum(*s) || (*s == '_'));
|
||||
skip(isalnum(*s) || (*s == '_') || (*s == '.') || (*s == '-') || (*s == '$'));
|
||||
end_from= s;
|
||||
skip(isspace(*s));
|
||||
if (end_from == from || *s++ != ':') goto syntax_error;
|
||||
skip(isspace(*s));
|
||||
to= s;
|
||||
skip(isalnum(*s) || (*s == '_'));
|
||||
skip(isalnum(*s) || (*s == '_') || (*s == '.') || (*s == '-') || (*s == '$'));
|
||||
end_to= s;
|
||||
if (end_to == to) goto syntax_error;
|
||||
|
||||
|
3
plugin/auth_pipe/CMakeLists.txt
Normal file
3
plugin/auth_pipe/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
IF(WIN32)
|
||||
MYSQL_ADD_PLUGIN(auth_named_pipe auth_pipe.c)
|
||||
ENDIF()
|
94
plugin/auth_pipe/auth_pipe.c
Normal file
94
plugin/auth_pipe/auth_pipe.c
Normal file
@ -0,0 +1,94 @@
|
||||
/* Copyright (C) 2015 Vladislav Vaintroub, Georg Richter and Monty Program Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; version 2 of the
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/**
|
||||
@file
|
||||
|
||||
auth_pipe authentication plugin.
|
||||
|
||||
Authentication is successful if the connection is done via a named pipe
|
||||
pipe peer name matches mysql user name
|
||||
*/
|
||||
|
||||
#include <mysql/plugin_auth.h>
|
||||
#include <string.h>
|
||||
#include <lmcons.h>
|
||||
|
||||
|
||||
/**
|
||||
This authentication callback obtains user name using named pipe impersonation
|
||||
*/
|
||||
static int pipe_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
|
||||
{
|
||||
unsigned char *pkt;
|
||||
MYSQL_PLUGIN_VIO_INFO vio_info;
|
||||
char username[UNLEN + 1];
|
||||
size_t username_length;
|
||||
int ret;
|
||||
|
||||
/* no user name yet ? read the client handshake packet with the user name */
|
||||
if (info->user_name == 0)
|
||||
{
|
||||
if (vio->read_packet(vio, &pkt) < 0)
|
||||
return CR_ERROR;
|
||||
}
|
||||
info->password_used= PASSWORD_USED_NO_MENTION;
|
||||
vio->info(vio, &vio_info);
|
||||
if (vio_info.protocol != MYSQL_VIO_PIPE)
|
||||
return CR_ERROR;
|
||||
|
||||
/* Impersonate the named pipe peer, and retrieve the user name */
|
||||
if (!ImpersonateNamedPipeClient(vio_info.handle))
|
||||
return CR_ERROR;
|
||||
|
||||
username_length= sizeof(username) - 1;
|
||||
ret= CR_ERROR;
|
||||
if (GetUserName(username, &username_length))
|
||||
{
|
||||
/* Always compare names case-insensitive on Windows.*/
|
||||
if (_stricmp(username, info->user_name) == 0)
|
||||
ret= CR_OK;
|
||||
}
|
||||
RevertToSelf();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct st_mysql_auth pipe_auth_handler=
|
||||
{
|
||||
MYSQL_AUTHENTICATION_INTERFACE_VERSION,
|
||||
0,
|
||||
pipe_auth
|
||||
};
|
||||
|
||||
maria_declare_plugin(auth_named_pipe)
|
||||
{
|
||||
MYSQL_AUTHENTICATION_PLUGIN,
|
||||
&pipe_auth_handler,
|
||||
"named_pipe",
|
||||
"Vladislav Vaintroub, Georg Richter",
|
||||
"Windows named pipe based authentication",
|
||||
PLUGIN_LICENSE_GPL,
|
||||
NULL,
|
||||
NULL,
|
||||
0x0100,
|
||||
NULL,
|
||||
NULL,
|
||||
"1.0",
|
||||
MariaDB_PLUGIN_MATURITY_STABLE
|
||||
}
|
||||
maria_declare_plugin_end;
|
||||
|
@ -13,4 +13,7 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
MYSQL_ADD_PLUGIN(server_audit server_audit.c MODULE_ONLY)
|
||||
SET(SERVER_AUDIT_SOURCES
|
||||
server_audit.c test_audit_v4.c plugin_audit_v4.h)
|
||||
|
||||
MYSQL_ADD_PLUGIN(server_audit ${SERVER_AUDIT_SOURCES} MODULE_ONLY)
|
||||
|
561
plugin/server_audit/plugin_audit_v4.h
Normal file
561
plugin/server_audit/plugin_audit_v4.h
Normal file
@ -0,0 +1,561 @@
|
||||
/* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; version 2 of
|
||||
the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef _my_audit_h
|
||||
#define _my_audit_h
|
||||
|
||||
#ifndef PLUGIN_CONTEXT
|
||||
#include "plugin.h"
|
||||
#include "mysql/mysql_lex_string.h"
|
||||
#ifndef MYSQL_ABI_CHECK
|
||||
#include "m_string.h"
|
||||
#endif
|
||||
#include "my_command.h"
|
||||
#include "my_sqlcommand.h"
|
||||
#endif /*PLUGIN_CONTEXT*/
|
||||
|
||||
#define MYSQL_AUDIT_INTERFACE_VERSION 0x0401
|
||||
|
||||
/**
|
||||
@enum mysql_event_class_t
|
||||
|
||||
Audit event classes.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MYSQL_AUDIT_GENERAL_CLASS = 0,
|
||||
MYSQL_AUDIT_CONNECTION_CLASS = 1,
|
||||
MYSQL_AUDIT_PARSE_CLASS = 2,
|
||||
MYSQL_AUDIT_AUTHORIZATION_CLASS = 3,
|
||||
MYSQL_AUDIT_TABLE_ACCESS_CLASS = 4,
|
||||
MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS = 5,
|
||||
MYSQL_AUDIT_SERVER_STARTUP_CLASS = 6,
|
||||
MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS = 7,
|
||||
MYSQL_AUDIT_COMMAND_CLASS = 8,
|
||||
MYSQL_AUDIT_QUERY_CLASS = 9,
|
||||
MYSQL_AUDIT_STORED_PROGRAM_CLASS = 10,
|
||||
/* This item must be last in the list. */
|
||||
MYSQL_AUDIT_CLASS_MASK_SIZE
|
||||
} mysql_event_class_t;
|
||||
|
||||
/**
|
||||
@struct st_mysql_audit
|
||||
|
||||
The descriptor structure that is referred from st_mysql_plugin.
|
||||
*/
|
||||
struct st_mysql_audit
|
||||
{
|
||||
/**
|
||||
Interface version.
|
||||
*/
|
||||
int interface_version;
|
||||
|
||||
/**
|
||||
Event occurs when the event class consumer is to be
|
||||
disassociated from the specified THD.This would typically occur
|
||||
before some operation which may require sleeping - such as when
|
||||
waiting for the next query from the client.
|
||||
*/
|
||||
void (*release_thd)(MYSQL_THD);
|
||||
|
||||
/**
|
||||
Invoked whenever an event occurs which is of any
|
||||
class for which the plugin has interest.The second argument
|
||||
indicates the specific event class and the third argument is data
|
||||
as required for that class.
|
||||
*/
|
||||
int (*event_notify)(MYSQL_THD, mysql_event_class_t, const void *);
|
||||
|
||||
/**
|
||||
An array of bits used to indicate what event classes
|
||||
that this plugin wants to receive.
|
||||
*/
|
||||
unsigned long class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
@typedef enum_sql_command_t
|
||||
|
||||
SQL command type definition.
|
||||
*/
|
||||
typedef enum enum_sql_command enum_sql_command_t;
|
||||
|
||||
/**
|
||||
@enum mysql_event_general_subclass_t
|
||||
|
||||
Events for the MYSQL_AUDIT_GENERAL_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** occurs before emitting to the general query log. */
|
||||
MYSQL_AUDIT_GENERAL_LOG = 1 << 0,
|
||||
/** occurs before transmitting errors to the user. */
|
||||
MYSQL_AUDIT_GENERAL_ERROR = 1 << 1,
|
||||
/** occurs after transmitting a resultset to the user. */
|
||||
MYSQL_AUDIT_GENERAL_RESULT = 1 << 2,
|
||||
/** occurs after transmitting a resultset or errors */
|
||||
MYSQL_AUDIT_GENERAL_STATUS = 1 << 3
|
||||
} mysql_event_general_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_GENERAL_ALL (MYSQL_AUDIT_GENERAL_LOG | \
|
||||
MYSQL_AUDIT_GENERAL_ERROR | \
|
||||
MYSQL_AUDIT_GENERAL_RESULT | \
|
||||
MYSQL_AUDIT_GENERAL_STATUS)
|
||||
/**
|
||||
@struct mysql_event_general
|
||||
|
||||
Structure for the MYSQL_AUDIT_GENERAL_CLASS event class.
|
||||
*/
|
||||
struct mysql_event_general
|
||||
{
|
||||
mysql_event_general_subclass_t event_subclass;
|
||||
int general_error_code;
|
||||
unsigned long general_thread_id;
|
||||
MYSQL_LEX_CSTRING general_user;
|
||||
MYSQL_LEX_CSTRING general_command;
|
||||
MYSQL_LEX_CSTRING general_query;
|
||||
struct charset_info_st *general_charset;
|
||||
unsigned long long general_time;
|
||||
unsigned long long general_rows;
|
||||
MYSQL_LEX_CSTRING general_host;
|
||||
MYSQL_LEX_CSTRING general_sql_command;
|
||||
MYSQL_LEX_CSTRING general_external_user;
|
||||
MYSQL_LEX_CSTRING general_ip;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_connection_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_CONNECTION_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** occurs after authentication phase is completed. */
|
||||
MYSQL_AUDIT_CONNECTION_CONNECT = 1 << 0,
|
||||
/** occurs after connection is terminated. */
|
||||
MYSQL_AUDIT_CONNECTION_DISCONNECT = 1 << 1,
|
||||
/** occurs after COM_CHANGE_USER RPC is completed. */
|
||||
MYSQL_AUDIT_CONNECTION_CHANGE_USER = 1 << 2,
|
||||
/** occurs before authentication. */
|
||||
MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE = 1 << 3
|
||||
} mysql_event_connection_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_CONNECTION_ALL (MYSQL_AUDIT_CONNECTION_CONNECT | \
|
||||
MYSQL_AUDIT_CONNECTION_DISCONNECT | \
|
||||
MYSQL_AUDIT_CONNECTION_CHANGE_USER | \
|
||||
MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE)
|
||||
/**
|
||||
@struct mysql_event_connection
|
||||
|
||||
Structure for the MYSQL_AUDIT_CONNECTION_CLASS event class.
|
||||
*/
|
||||
struct mysql_event_connection
|
||||
{
|
||||
/** Event subclass. */
|
||||
mysql_event_connection_subclass_t event_subclass;
|
||||
/** Current status of the connection. */
|
||||
int status;
|
||||
/** Connection id. */
|
||||
unsigned long connection_id;
|
||||
/** User name of this connection. */
|
||||
MYSQL_LEX_CSTRING user;
|
||||
/** Priv user name. */
|
||||
MYSQL_LEX_CSTRING priv_user;
|
||||
/** External user name. */
|
||||
MYSQL_LEX_CSTRING external_user;
|
||||
/** Proxy user used for this connection. */
|
||||
MYSQL_LEX_CSTRING proxy_user;
|
||||
/** Connection host. */
|
||||
MYSQL_LEX_CSTRING host;
|
||||
/** IP of the connection. */
|
||||
MYSQL_LEX_CSTRING ip;
|
||||
/** Database name specified at connection time. */
|
||||
MYSQL_LEX_CSTRING database;
|
||||
/** Connection type:
|
||||
- 0 Undefined
|
||||
- 1 TCP/IP
|
||||
- 2 Socket
|
||||
- 3 Named pipe
|
||||
- 4 SSL
|
||||
- 5 Shared memory
|
||||
*/
|
||||
int connection_type;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_parse_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_PARSE_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** occurs before the query parsing. */
|
||||
MYSQL_AUDIT_PARSE_PREPARSE = 1 << 0,
|
||||
/** occurs after the query parsing. */
|
||||
MYSQL_AUDIT_PARSE_POSTPARSE = 1 << 1
|
||||
} mysql_event_parse_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_PARSE_ALL (MYSQL_AUDIT_PARSE_PREPARSE | \
|
||||
MYSQL_AUDIT_PARSE_POSTPARSE)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_NONE = 0,
|
||||
/// mysql_event_parse::flags Must be set by a plugin if the query is rewritten.
|
||||
MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_QUERY_REWRITTEN = 1 << 0,
|
||||
/// mysql_event_parse::flags Is set by the server if the query is prepared statement.
|
||||
MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_IS_PREPARED_STATEMENT = 1 << 1
|
||||
} mysql_event_parse_rewrite_plugin_flag;
|
||||
|
||||
/** Data for the MYSQL_AUDIT_PARSE events */
|
||||
struct mysql_event_parse
|
||||
{
|
||||
/** MYSQL_AUDIT_[PRE|POST]_PARSE event id */
|
||||
mysql_event_parse_subclass_t event_subclass;
|
||||
|
||||
/** one of FLAG_REWRITE_PLUGIN_* */
|
||||
mysql_event_parse_rewrite_plugin_flag *flags;
|
||||
|
||||
/** input: the original query text */
|
||||
MYSQL_LEX_CSTRING query;
|
||||
|
||||
/** output: returns the null-terminated rewriten query allocated by my_malloc() */
|
||||
MYSQL_LEX_CSTRING *rewritten_query;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_authorization_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_AUTHORIZATION_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MYSQL_AUDIT_AUTHORIZATION_USER = 1 << 0,
|
||||
/** Occurs when database privilege is checked. */
|
||||
MYSQL_AUDIT_AUTHORIZATION_DB = 1 << 1,
|
||||
/** Occurs when table privilege is checked. */
|
||||
MYSQL_AUDIT_AUTHORIZATION_TABLE = 1 << 2,
|
||||
/** Occurs when column privilege is checked. */
|
||||
MYSQL_AUDIT_AUTHORIZATION_COLUMN = 1 << 3,
|
||||
/** Occurs when procedure privilege is checked. */
|
||||
MYSQL_AUDIT_AUTHORIZATION_PROCEDURE = 1 << 4,
|
||||
/** Occurs when proxy privilege is checked. */
|
||||
MYSQL_AUDIT_AUTHORIZATION_PROXY = 1 << 5
|
||||
} mysql_event_authorization_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_AUTHORIZATION_ALL (MYSQL_AUDIT_AUTHORIZATION_USER | \
|
||||
MYSQL_AUDIT_AUTHORIZATION_DB | \
|
||||
MYSQL_AUDIT_AUTHORIZATION_TABLE | \
|
||||
MYSQL_AUDIT_AUTHORIZATION_COLUMN | \
|
||||
MYSQL_AUDIT_AUTHORIZATION_PROCEDURE | \
|
||||
MYSQL_AUDIT_AUTHORIZATION_PROXY)
|
||||
/**
|
||||
@struct mysql_event_authorization
|
||||
|
||||
Structure for MYSQL_AUDIT_AUTHORIZATION_CLASS event class.
|
||||
*/
|
||||
struct mysql_event_authorization
|
||||
{
|
||||
/** Event subclass. */
|
||||
mysql_event_authorization_subclass_t event_subclass;
|
||||
/** Event status. */
|
||||
int status;
|
||||
/** Connection id. */
|
||||
unsigned int connection_id;
|
||||
/** SQL command id. */
|
||||
enum_sql_command_t sql_command_id;
|
||||
/** SQL query text. */
|
||||
MYSQL_LEX_CSTRING query;
|
||||
/** SQL query charset. */
|
||||
const struct charset_info_st *query_charset;
|
||||
/** Database name. */
|
||||
MYSQL_LEX_CSTRING database;
|
||||
/** Table name. */
|
||||
MYSQL_LEX_CSTRING table;
|
||||
/** Other name associated with the event. */
|
||||
MYSQL_LEX_CSTRING object;
|
||||
/** Requested authorization privileges. */
|
||||
unsigned long requested_privilege;
|
||||
/** Currently granted authorization privileges. */
|
||||
unsigned long granted_privilege;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_table_row_access_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_TABLE_ACCES_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Occurs when table data are read. */
|
||||
MYSQL_AUDIT_TABLE_ACCESS_READ = 1 << 0,
|
||||
/** Occurs when table data are inserted. */
|
||||
MYSQL_AUDIT_TABLE_ACCESS_INSERT = 1 << 1,
|
||||
/** Occurs when table data are updated. */
|
||||
MYSQL_AUDIT_TABLE_ACCESS_UPDATE = 1 << 2,
|
||||
/** Occurs when table data are deleted. */
|
||||
MYSQL_AUDIT_TABLE_ACCESS_DELETE = 1 << 3
|
||||
} mysql_event_table_access_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_TABLE_ACCESS_ALL (MYSQL_AUDIT_TABLE_ACCESS_READ | \
|
||||
MYSQL_AUDIT_TABLE_ACCESS_INSERT | \
|
||||
MYSQL_AUDIT_TABLE_ACCESS_UPDATE | \
|
||||
MYSQL_AUDIT_TABLE_ACCESS_DELETE)
|
||||
|
||||
/**
|
||||
@struct mysql_event_table_row_access
|
||||
|
||||
Structure for MYSQL_AUDIT_TABLE_ACCES_CLASS event class.
|
||||
*/
|
||||
struct mysql_event_table_access
|
||||
{
|
||||
/** Event subclass. */
|
||||
mysql_event_table_access_subclass_t event_subclass;
|
||||
/** Connection id. */
|
||||
unsigned long connection_id;
|
||||
/** SQL command id. */
|
||||
enum_sql_command_t sql_command_id;
|
||||
/** SQL query. */
|
||||
MYSQL_LEX_CSTRING query;
|
||||
/** SQL query charset. */
|
||||
const struct charset_info_st *query_charset;
|
||||
/** Database name. */
|
||||
MYSQL_LEX_CSTRING table_database;
|
||||
/** Table name. */
|
||||
MYSQL_LEX_CSTRING table_name;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_global_variable_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Occurs when global variable is retrieved. */
|
||||
MYSQL_AUDIT_GLOBAL_VARIABLE_GET = 1 << 0,
|
||||
/** Occurs when global variable is set. */
|
||||
MYSQL_AUDIT_GLOBAL_VARIABLE_SET = 1 << 1
|
||||
} mysql_event_global_variable_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_GLOBAL_VARIABLE_ALL (MYSQL_AUDIT_GLOBAL_VARIABLE_GET | \
|
||||
MYSQL_AUDIT_GLOBAL_VARIABLE_SET)
|
||||
|
||||
/** Events for MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS event class. */
|
||||
struct mysql_event_global_variable
|
||||
{
|
||||
/** Event subclass. */
|
||||
mysql_event_global_variable_subclass_t event_subclass;
|
||||
/** Connection id. */
|
||||
unsigned long connection_id;
|
||||
/** SQL command id. */
|
||||
enum_sql_command_t sql_command_id;
|
||||
/** Variable name. */
|
||||
MYSQL_LEX_CSTRING variable_name;
|
||||
/** Variable value. */
|
||||
MYSQL_LEX_CSTRING variable_value;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_server_startup_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_SERVER_STARTUP_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Occurs after all subsystem are initialized during system start. */
|
||||
MYSQL_AUDIT_SERVER_STARTUP_STARTUP = 1 << 0
|
||||
} mysql_event_server_startup_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_SERVER_STARTUP_ALL (MYSQL_AUDIT_SERVER_STARTUP_STARTUP)
|
||||
|
||||
/**
|
||||
@struct mysql_event_server_startup
|
||||
|
||||
Structure for MYSQL_AUDIT_SERVER_STARTUP_CLASS event class.
|
||||
*/
|
||||
struct mysql_event_server_startup
|
||||
{
|
||||
/** Event subclass. */
|
||||
mysql_event_server_startup_subclass_t event_subclass;
|
||||
/** Command line arguments. */
|
||||
const char **argv;
|
||||
/** Command line arguments count. */
|
||||
unsigned int argc;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_server_shutdown_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Occurs when global variable is set. */
|
||||
MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN = 1 << 0
|
||||
} mysql_event_server_shutdown_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_SERVER_SHUTDOWN_ALL (MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN)
|
||||
|
||||
/**
|
||||
@enum mysql_server_shutdown_reason_t
|
||||
|
||||
Server shutdown reason.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** User requested shut down. */
|
||||
MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_SHUTDOWN,
|
||||
/** The server aborts. */
|
||||
MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_ABORT
|
||||
} mysql_server_shutdown_reason_t;
|
||||
|
||||
/**
|
||||
@struct mysql_event_server_shutdown
|
||||
|
||||
Structure for MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS event class.
|
||||
*/
|
||||
struct mysql_event_server_shutdown
|
||||
{
|
||||
/** Shutdown event. */
|
||||
mysql_event_server_shutdown_subclass_t event_subclass;
|
||||
/** Exit code associated with the shutdown event. */
|
||||
int exit_code;
|
||||
/** Shutdown reason. */
|
||||
mysql_server_shutdown_reason_t reason;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_command_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_COMMAND_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Command start event. */
|
||||
MYSQL_AUDIT_COMMAND_START = 1 << 0,
|
||||
/** Command end event. */
|
||||
MYSQL_AUDIT_COMMAND_END = 1 << 1
|
||||
} mysql_event_command_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_COMMAND_ALL (MYSQL_AUDIT_COMMAND_START | \
|
||||
MYSQL_AUDIT_COMMAND_END)
|
||||
/**
|
||||
@typedef enum_server_command_t
|
||||
|
||||
Server command type definition.
|
||||
*/
|
||||
typedef enum enum_server_command enum_server_command_t;
|
||||
|
||||
/**
|
||||
@struct mysql_event_command
|
||||
|
||||
Event for MYSQL_AUDIT_COMMAND_CLASS event class.
|
||||
Events generated as a result of RPC command requests.
|
||||
*/
|
||||
struct mysql_event_command
|
||||
{
|
||||
/** Command event subclass. */
|
||||
mysql_event_command_subclass_t event_subclass;
|
||||
/** Command event status. */
|
||||
int status;
|
||||
/** Connection id. */
|
||||
unsigned long connection_id;
|
||||
/** Command id. */
|
||||
enum_server_command_t command_id;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_query_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_QUERY_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Query start event. */
|
||||
MYSQL_AUDIT_QUERY_START = 1 << 0,
|
||||
/** Nested query start event. */
|
||||
MYSQL_AUDIT_QUERY_NESTED_START = 1 << 1,
|
||||
/** Query post parse event. */
|
||||
MYSQL_AUDIT_QUERY_STATUS_END = 1 << 2,
|
||||
/** Nested query status end event. */
|
||||
MYSQL_AUDIT_QUERY_NESTED_STATUS_END = 1 << 3
|
||||
} mysql_event_query_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_QUERY_ALL (MYSQL_AUDIT_QUERY_START | \
|
||||
MYSQL_AUDIT_QUERY_NESTED_START | \
|
||||
MYSQL_AUDIT_QUERY_STATUS_END | \
|
||||
MYSQL_AUDIT_QUERY_NESTED_STATUS_END)
|
||||
/**
|
||||
@struct mysql_event_command
|
||||
|
||||
Event for MYSQL_AUDIT_COMMAND_CLASS event class.
|
||||
*/
|
||||
struct mysql_event_query
|
||||
{
|
||||
/** Event subclass. */
|
||||
mysql_event_query_subclass_t event_subclass;
|
||||
/** Event status. */
|
||||
int status;
|
||||
/** Connection id. */
|
||||
unsigned long connection_id;
|
||||
/** SQL command id. */
|
||||
enum_sql_command_t sql_command_id;
|
||||
/** SQL query. */
|
||||
MYSQL_LEX_CSTRING query;
|
||||
/** SQL query charset. */
|
||||
const struct charset_info_st *query_charset;
|
||||
};
|
||||
|
||||
/**
|
||||
@enum mysql_event_stored_program_subclass_t
|
||||
|
||||
Events for MYSQL_AUDIT_STORED_PROGRAM_CLASS event class.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Stored program execution event. */
|
||||
MYSQL_AUDIT_STORED_PROGRAM_EXECUTE = 1 << 0
|
||||
} mysql_event_stored_program_subclass_t;
|
||||
|
||||
#define MYSQL_AUDIT_STORED_PROGRAM_ALL (MYSQL_AUDIT_STORED_PROGRAM_EXECUTE)
|
||||
|
||||
/**
|
||||
@struct mysql_event_command
|
||||
|
||||
Event for MYSQL_AUDIT_COMMAND_CLASS event class.
|
||||
*/
|
||||
struct mysql_event_stored_program
|
||||
{
|
||||
/** Event subclass. */
|
||||
mysql_event_stored_program_subclass_t event_subclass;
|
||||
/** Connection id. */
|
||||
unsigned long connection_id;
|
||||
/** SQL command id. */
|
||||
enum_sql_command_t sql_command_id;
|
||||
/** SQL query text. */
|
||||
MYSQL_LEX_CSTRING query;
|
||||
/** SQL query charset. */
|
||||
const struct charset_info_st *query_charset;
|
||||
/** The Database the procedure is defined in. */
|
||||
MYSQL_LEX_CSTRING database;
|
||||
/** Name of the stored program. */
|
||||
MYSQL_LEX_CSTRING name;
|
||||
/** Stored program parameters. */
|
||||
void *parameters;
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
162
plugin/server_audit/test_audit_v4.c
Normal file
162
plugin/server_audit/test_audit_v4.c
Normal file
@ -0,0 +1,162 @@
|
||||
#define PLUGIN_CONTEXT
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
typedef void *MYSQL_THD;
|
||||
struct st_mysql_const_lex_string
|
||||
{
|
||||
const char *str;
|
||||
size_t length;
|
||||
};
|
||||
typedef struct st_mysql_const_lex_string MYSQL_LEX_CSTRING;
|
||||
enum enum_sql_command{ SQLCOM_A, SQLCOM_B };
|
||||
enum enum_server_command{ SERVCOM_A, SERVCOM_B };
|
||||
|
||||
#include "plugin_audit_v4.h"
|
||||
|
||||
extern void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev);
|
||||
extern int get_db_mysql57(MYSQL_THD thd, char **name, int *len);
|
||||
|
||||
|
||||
struct mysql_event_general_302
|
||||
{
|
||||
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;
|
||||
unsigned long long query_id;
|
||||
char *database;
|
||||
int database_length;
|
||||
};
|
||||
|
||||
|
||||
static int auditing_v4(MYSQL_THD thd, mysql_event_class_t class, const void *ev)
|
||||
{
|
||||
int *subclass= (int *)ev;
|
||||
struct mysql_event_general_302 ev_302;
|
||||
int subclass_v3, subclass_orig;
|
||||
|
||||
if (class != MYSQL_AUDIT_GENERAL_CLASS &&
|
||||
class != MYSQL_AUDIT_CONNECTION_CLASS)
|
||||
return 0;
|
||||
|
||||
subclass_orig= *subclass;
|
||||
|
||||
if (class == MYSQL_AUDIT_GENERAL_CLASS)
|
||||
{
|
||||
struct mysql_event_general *event= (struct mysql_event_general *) ev;
|
||||
ev_302.general_error_code= event->general_error_code;
|
||||
ev_302.general_thread_id= event->general_thread_id;
|
||||
ev_302.general_user= event->general_user.str;
|
||||
ev_302.general_user_length= event->general_user.length;
|
||||
ev_302.general_command= event->general_command.str;
|
||||
ev_302.general_command_length= event->general_command.length;
|
||||
ev_302.general_query= event->general_query.str;
|
||||
ev_302.general_query_length= event->general_query.length;
|
||||
ev_302.general_charset= event->general_charset;
|
||||
ev_302.general_time= event->general_time;
|
||||
ev_302.general_rows= event->general_rows;
|
||||
if (get_db_mysql57(thd, &ev_302.database, &ev_302.database_length))
|
||||
{
|
||||
ev_302.database= 0;
|
||||
ev_302.database_length= 0;
|
||||
}
|
||||
ev= &ev_302;
|
||||
switch (subclass_orig)
|
||||
{
|
||||
case MYSQL_AUDIT_GENERAL_LOG:
|
||||
subclass_v3= 0;
|
||||
ev_302.event_subclass= 0;
|
||||
break;
|
||||
case MYSQL_AUDIT_GENERAL_ERROR:
|
||||
subclass_v3= 1;
|
||||
ev_302.event_subclass= 1;
|
||||
break;
|
||||
case MYSQL_AUDIT_GENERAL_RESULT:
|
||||
subclass_v3= 2;
|
||||
ev_302.event_subclass= 2;
|
||||
break;
|
||||
case MYSQL_AUDIT_GENERAL_STATUS:
|
||||
{
|
||||
subclass_v3= 3;
|
||||
ev_302.event_subclass= 3;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else /* if (class == MYSQL_AUDIT_CONNECTION_CLASS) */
|
||||
{
|
||||
switch (subclass_orig)
|
||||
{
|
||||
case MYSQL_AUDIT_CONNECTION_CONNECT:
|
||||
subclass_v3= 0;
|
||||
break;
|
||||
case MYSQL_AUDIT_CONNECTION_DISCONNECT:
|
||||
subclass_v3= 1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*subclass= subclass_v3;
|
||||
|
||||
auditing(thd, (int) class, ev);
|
||||
|
||||
*subclass= subclass_orig;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct st_mysql_audit mysql_descriptor =
|
||||
{
|
||||
MYSQL_AUDIT_INTERFACE_VERSION,
|
||||
NULL,
|
||||
auditing_v4,
|
||||
{ (unsigned long) MYSQL_AUDIT_GENERAL_ALL,
|
||||
(unsigned long) MYSQL_AUDIT_CONNECTION_ALL,
|
||||
(unsigned long) MYSQL_AUDIT_PARSE_ALL,
|
||||
0, /* This event class is currently not supported. */
|
||||
0, /* This event class is currently not supported. */
|
||||
(unsigned long) MYSQL_AUDIT_GLOBAL_VARIABLE_ALL,
|
||||
(unsigned long) MYSQL_AUDIT_SERVER_STARTUP_ALL,
|
||||
(unsigned long) MYSQL_AUDIT_SERVER_SHUTDOWN_ALL,
|
||||
(unsigned long) MYSQL_AUDIT_COMMAND_ALL,
|
||||
(unsigned long) MYSQL_AUDIT_QUERY_ALL,
|
||||
(unsigned long) MYSQL_AUDIT_STORED_PROGRAM_ALL }
|
||||
#ifdef WHEN_MYSQL_BUG_FIXED
|
||||
/*
|
||||
By this moment MySQL just sends no notifications at all
|
||||
when we request only those we actually need.
|
||||
So we have to request everything and filter them inside the
|
||||
handling function.
|
||||
*/
|
||||
{ (unsigned long) MYSQL_AUDIT_GENERAL_ALL,
|
||||
(unsigned long) (MYSQL_AUDIT_CONNECTION_CONNECT |
|
||||
MYSQL_AUDIT_CONNECTION_DISCONNECT),
|
||||
0,
|
||||
0, /* This event class is currently not supported. */
|
||||
0, /* This event class is currently not supported. */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
}
|
||||
#endif /*WHEN_MYSQL_BUG_FIXED*/
|
||||
};
|
||||
|
||||
|
||||
void *mysql_v4_descriptor= &mysql_descriptor;
|
||||
|
@ -79,8 +79,6 @@ INSTALL(FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mysql_performance_tables.sql
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fill_help_tables.sql
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mysql_test_data_timezone.sql
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp.sql
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp_bootstrap.sql
|
||||
${FIX_PRIVILEGES_SQL}
|
||||
DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server
|
||||
)
|
||||
@ -287,6 +285,34 @@ ELSE()
|
||||
ENDFOREACH()
|
||||
ENDIF()
|
||||
|
||||
# Configure two scripts from one 'in' file.
|
||||
# The maria_add_gis_sp.sql - to be sent to 'mysql' tool
|
||||
# and the maria_add_gis_sp_bootstrap.sql, that can be sent to
|
||||
# the server as a bootstrap command.
|
||||
|
||||
SET(ADD_GIS_SP_SET_DELIMITER "delimiter |")
|
||||
SET(ADD_GIS_SP_RESET_DELIMITER "delimiter ;")
|
||||
SET(ADD_GIS_SP_EOL "|")
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp.sql.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp.sql ESCAPE_QUOTES @ONLY)
|
||||
|
||||
INSTALL_SCRIPT(${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp.sql
|
||||
DESTINATION ${INSTALL_BINDIR}
|
||||
COMPONENT Server
|
||||
)
|
||||
|
||||
SET(ADD_GIS_SP_SET_DELIMITER "")
|
||||
SET(ADD_GIS_SP_RESET_DELIMITER "")
|
||||
SET(ADD_GIS_SP_EOL ";")
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp.sql.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp_bootstrap.sql ESCAPE_QUOTES @ONLY)
|
||||
|
||||
INSTALL_SCRIPT(${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp.sql
|
||||
${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp_bootstrap.sql
|
||||
DESTINATION ${INSTALL_MYSQLSHAREDIR}
|
||||
COMPONENT Server
|
||||
)
|
||||
|
||||
# Install libgcc as mylibgcc.a
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_FLAGS MATCHES "-static")
|
||||
EXECUTE_PROCESS (
|
||||
|
@ -1,48 +0,0 @@
|
||||
-- Copyright (C) 2014 MariaDB Ab.
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; version 2 of the License.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
-- This part creates stored procedures required by the OpenGIS standards.
|
||||
-- Proc privilege is needed to run it.
|
||||
-- To use this file, load its contents into the mysql database like that:
|
||||
-- mysql -u root -p mysql < scripts/maria_add_gis_sp.sql
|
||||
|
||||
SET sql_mode='';
|
||||
|
||||
DROP PROCEDURE IF EXISTS AddGeometryColumn;
|
||||
DROP PROCEDURE IF EXISTS DropGeometryColumn;
|
||||
|
||||
delimiter |
|
||||
|
||||
CREATE PROCEDURE AddGeometryColumn(catalog varchar(64), t_schema varchar(64),
|
||||
t_name varchar(64), geometry_column varchar(64), t_srid int)
|
||||
begin
|
||||
set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' ADD ', geometry_column,' GEOMETRY REF_SYSTEM_ID=', t_srid);
|
||||
PREPARE ls from @qwe;
|
||||
execute ls;
|
||||
deallocate prepare ls;
|
||||
end|
|
||||
|
||||
CREATE PROCEDURE DropGeometryColumn(catalog varchar(64), t_schema varchar(64),
|
||||
t_name varchar(64), geometry_column varchar(64))
|
||||
begin
|
||||
set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' DROP ', geometry_column);
|
||||
PREPARE ls from @qwe;
|
||||
execute ls;
|
||||
deallocate prepare ls;
|
||||
end|
|
||||
|
||||
delimiter ;
|
||||
|
@ -18,17 +18,20 @@
|
||||
|
||||
SET sql_mode='';
|
||||
|
||||
@ADD_GIS_SP_SET_DELIMITER@
|
||||
|
||||
DROP PROCEDURE IF EXISTS AddGeometryColumn;
|
||||
DROP PROCEDURE IF EXISTS DropGeometryColumn;
|
||||
|
||||
CREATE PROCEDURE AddGeometryColumn(catalog varchar(64), t_schema varchar(64),
|
||||
t_name varchar(64), geometry_column varchar(64), t_srid int)
|
||||
begin
|
||||
set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' ADD ', geometry_column,' GEOMETRY REF_SYSTEM_ID=', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end;
|
||||
set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' ADD ', geometry_column,' GEOMETRY REF_SYSTEM_ID=', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end @ADD_GIS_SP_EOL@
|
||||
|
||||
CREATE PROCEDURE DropGeometryColumn(catalog varchar(64), t_schema varchar(64),
|
||||
t_name varchar(64), geometry_column varchar(64))
|
||||
begin
|
||||
set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' DROP ', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end;
|
||||
set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' DROP ', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end @ADD_GIS_SP_EOL@
|
||||
|
||||
@ADD_GIS_SP_RESET_DELIMITER@
|
||||
|
@ -4337,6 +4337,7 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
|
||||
stacksize= ASYNC_CONTEXT_DEFAULT_STACK_SIZE;
|
||||
if (my_context_init(&ctxt->async_context, stacksize))
|
||||
{
|
||||
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
|
||||
my_free(ctxt);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user