diff --git a/Makefile.am b/Makefile.am index ca84e52a5a3..fadd73d5094 100644 --- a/Makefile.am +++ b/Makefile.am @@ -268,7 +268,9 @@ API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin_audit.h \ $(top_srcdir)/include/mysql/plugin_ftparser.h \ $(top_srcdir)/include/mysql.h \ $(top_srcdir)/include/mysql/psi/psi_abi_v1.h \ - $(top_srcdir)/include/mysql/psi/psi_abi_v2.h + $(top_srcdir)/include/mysql/psi/psi_abi_v2.h \ + $(top_srcdir)/include/mysql/client_plugin.h \ + $(top_srcdir)/include/mysql/plugin_auth.h # # Rules for checking that the abi/api has not changed. diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index e39e8d7178a..80c5bbd1c9f 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -72,3 +72,5 @@ ENDIF(WIN32) SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap PROPERTIES HAS_CXX TRUE) +ADD_DEFINITIONS(-DHAVE_DLOPEN) + diff --git a/client/client_priv.h b/client/client_priv.h index e7911fc31f7..1a81768adc4 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -84,6 +84,8 @@ enum options_client OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE, OPT_WRITE_BINLOG, OPT_DUMP_DATE, OPT_INIT_COMMAND, + OPT_PLUGIN_DIR, + OPT_DEFAULT_PLUGIN, OPT_MAX_CLIENT_OPTION }; diff --git a/client/mysql.cc b/client/mysql.cc index b61a751198a..14473ba4b51 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -166,6 +166,7 @@ static int wait_time = 5; static STATUS status; static ulong select_limit,max_join_size,opt_connect_timeout=0; static char mysql_charsets_dir[FN_REFLEN+1]; +static char *opt_plugin_dir= 0, *opt_default_auth; static const char *xmlmeta[] = { "&", "&", "<", "<", @@ -1564,6 +1565,13 @@ static struct my_option my_long_options[] = {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.", &show_warnings, &show_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.", + (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"default_auth", OPT_PLUGIN_DIR, + "Default authentication client-side plugin to use.", + (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -4295,9 +4303,15 @@ sql_real_connect(char *host,char *database,char *user,char *password, mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); + if (opt_plugin_dir && *opt_plugin_dir) + mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir); + + if (opt_default_auth && *opt_default_auth) + mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); + if (!mysql_real_connect(&mysql, host, user, password, - database, opt_mysql_port, opt_mysql_unix_port, - connect_flag | CLIENT_MULTI_STATEMENTS)) + database, opt_mysql_port, opt_mysql_unix_port, + connect_flag | CLIENT_MULTI_STATEMENTS)) { if (!silent || (mysql_errno(&mysql) != CR_CONN_HOST_ERROR && diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 2ec4edc1b61..b75fae7b685 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -36,6 +36,7 @@ #include "client_priv.h" #include #include +#include #include #include #include @@ -191,6 +192,8 @@ static ulonglong timer_now(void); static ulong connection_retry_sleep= 100000; /* Microseconds */ +static char *opt_plugin_dir= 0; + /* Precompiled re's */ static my_regex_t ps_re; /* the query can be run using PS protocol */ static my_regex_t sp_re; /* the query can be run as a SP */ @@ -3897,13 +3900,15 @@ void do_change_user(struct st_command *command) } if (!ds_user.length) + { dynstr_set(&ds_user, mysql->user); - if (!ds_passwd.length) - dynstr_set(&ds_passwd, mysql->passwd); + if (!ds_passwd.length) + dynstr_set(&ds_passwd, mysql->passwd); - if (!ds_db.length) - dynstr_set(&ds_db, mysql->db); + if (!ds_db.length) + dynstr_set(&ds_db, mysql->db); + } DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'", cur_con->name, ds_user.str, ds_passwd.str, ds_db.str)); @@ -5272,6 +5277,7 @@ void do_connect(struct st_command *command) static DYNAMIC_STRING ds_port; static DYNAMIC_STRING ds_sock; static DYNAMIC_STRING ds_options; + static DYNAMIC_STRING ds_default_auth; #ifdef HAVE_SMEM static DYNAMIC_STRING ds_shm; #endif @@ -5283,7 +5289,8 @@ void do_connect(struct st_command *command) { "database", ARG_STRING, FALSE, &ds_database, "Database to select after connect" }, { "port", ARG_STRING, FALSE, &ds_port, "Port to connect to" }, { "socket", ARG_STRING, FALSE, &ds_sock, "Socket to connect with" }, - { "options", ARG_STRING, FALSE, &ds_options, "Options to use while connecting" } + { "options", ARG_STRING, FALSE, &ds_options, "Options to use while connecting" }, + { "default_auth", ARG_STRING, FALSE, &ds_default_auth, "Default authentication to use" } }; DBUG_ENTER("do_connect"); @@ -5433,6 +5440,12 @@ void do_connect(struct st_command *command) if (ds_database.length == 0) dynstr_set(&ds_database, opt_db); + if (opt_plugin_dir && *opt_plugin_dir) + mysql_options(&con_slot->mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir); + + if (ds_default_auth.length) + mysql_options(&con_slot->mysql, MYSQL_DEFAULT_AUTH, ds_default_auth.str); + /* Special database to allow one to connect without a database name */ if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*")) dynstr_set(&ds_database, ""); @@ -6231,6 +6244,9 @@ static struct my_option my_long_options[] = "Number of seconds before connection timeout.", &opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG, 120, 0, 3600 * 12, 0, 0, 0}, + {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.", + (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index 732f5d74181..4936ae369bc 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -131,6 +131,7 @@ SET(HAVE_PASE_ENVIRONMENT CACHE INTERNAL "") SET(HAVE_PATHS_H CACHE INTERNAL "") SET(HAVE_PCLOSE CACHE INTERNAL "") SET(HAVE_PERROR 1 CACHE INTERNAL "") +SET(HAVE_PEERCRED CACHE INTERNAL "") SET(HAVE_POLL_H CACHE INTERNAL "") SET(HAVE_POPEN CACHE INTERNAL "") SET(HAVE_POLL CACHE INTERNAL "") diff --git a/config.h.cmake b/config.h.cmake index 7047cc6bbf5..54567df4548 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -602,6 +602,8 @@ #cmakedefine PLUGINDIR "@PLUGINDIR@" #cmakedefine DEFAULT_SYSCONFDIR "@DEFAULT_SYSCONFDIR@" +#cmakedefine SO_EXT "@CMAKE_SHARED_MODULE_SUFFIX@" + #define PACKAGE "mysql" #define PACKAGE_BUGREPORT "" #define PACKAGE_NAME "MySQL Server" diff --git a/configure.in b/configure.in index 341c145e22f..a5fe8d292da 100644 --- a/configure.in +++ b/configure.in @@ -1617,9 +1617,8 @@ case "$with_mysqld_ldflags " in ;; *) - # Check for dlopen, needed for user definable functions + # Check for dlopen, needed for user definable functions and plugins # This must be checked after threads on AIX - # We only need this for mysqld, not for the clients. my_save_LIBS="$LIBS" LIBS="" diff --git a/include/Makefile.am b/include/Makefile.am index 909f68936dc..415e2ef8c8c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -24,7 +24,9 @@ HEADERS_ABI = mysql.h mysql_com.h mysql_time.h \ my_list.h my_alloc.h typelib.h mysql/plugin.h \ mysql/plugin_audit.h mysql/plugin_ftparser.h pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \ - my_xml.h mysql_embed.h mysql/services.h \ + my_xml.h mysql_embed.h mysql/plugin_auth.h \ + mysql/client_plugin.h mysql/plugin_auth_common.h \ + mysql/services.h \ mysql/service_my_snprintf.h mysql/service_thd_alloc.h \ mysql/service_thread_scheduler.h \ mysql/service_thd_wait.h \ @@ -56,7 +58,8 @@ pkgpsiinclude_HEADERS = mysql/psi/psi.h mysql/psi/mysql_thread.h \ EXTRA_DIST = mysql.h.pp mysql/plugin.h.pp probes_mysql.d.base \ CMakeLists.txt \ mysql/psi/psi_abi_v1.h.pp \ - mysql/psi/psi_abi_v2.h.pp + mysql/psi/psi_abi_v2.h.pp \ + mysql/plugin_auth.h.pp mysql/client_plugin.h.pp # Remove built files and the symlinked directories CLEANFILES = $(BUILT_SOURCES) readline openssl probes_mysql.d probes_mysql_nodtrace.h diff --git a/include/errmsg.h b/include/errmsg.h index c55c94af169..f1d7dd65f97 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -101,7 +101,8 @@ extern const char *client_errors[]; /* Error messages */ #define CR_STMT_CLOSED 2056 #define CR_NEW_STMT_METADATA 2057 #define CR_ALREADY_CONNECTED 2058 -#define CR_ERROR_LAST /*Copy last error nr:*/ 2058 +#define CR_AUTH_PLUGIN_CANNOT_LOAD 2059 +#define CR_ERROR_LAST /*Copy last error nr:*/ 2059 /* Add error numbers before CR_ERROR_LAST and change it accordingly. */ #endif /* ERRMSG_INCLUDED */ diff --git a/include/my_global.h b/include/my_global.h index 4902f06c7c0..8540c3f100e 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -452,6 +452,16 @@ extern "C" int madvise(void *addr, size_t len, int behav); #define LINT_INIT(var) #endif +#ifndef SO_EXT +#ifdef _WIN32 +#define SO_EXT ".dll" +#elif defined(__APPLE__) +#define SO_EXT ".dylib" +#else +#define SO_EXT ".so" +#endif +#endif + /* Suppress uninitialized variable warning without generating code. @@ -1355,8 +1365,10 @@ do { doubleget_union _tmp; \ #define dlsym(lib, name) (void*)GetProcAddress((HMODULE)lib, name) #define dlopen(libname, unused) LoadLibraryEx(libname, NULL, 0) #define dlclose(lib) FreeLibrary((HMODULE)lib) +#ifndef HAVE_DLOPEN #define HAVE_DLOPEN #endif +#endif #ifdef HAVE_DLOPEN #if defined(HAVE_DLFCN_H) @@ -1365,7 +1377,11 @@ do { doubleget_union _tmp; \ #endif #ifndef HAVE_DLERROR +#ifdef _WIN32 #define dlerror() "" +#else +#define dlerror() "No support for dynamic loading (static build?)" +#endif #endif diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h index a805a9151f8..633a5b94a6c 100644 --- a/include/my_no_pthread.h +++ b/include/my_no_pthread.h @@ -47,6 +47,7 @@ #define rw_wrlock(A) #define rw_unlock(A) #define rwlock_destroy(A) +#define safe_mutex_assert_owner(mp) #define mysql_mutex_init(A, B, C) do {} while (0) #define mysql_mutex_lock(A) do {} while (0) diff --git a/include/my_sys.h b/include/my_sys.h index 95689535be5..23c9b2da55f 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -197,7 +197,7 @@ extern void my_large_free(uchar *ptr); #define my_alloca(SZ) alloca((size_t) (SZ)) #define my_afree(PTR) {} #else -#define my_alloca(SZ) my_malloc(SZ,MYF(0)) +#define my_alloca(SZ) my_malloc(SZ,MYF(MY_FAE)) #define my_afree(PTR) my_free(PTR) #endif /* HAVE_ALLOCA */ @@ -824,6 +824,10 @@ extern void set_prealloc_root(MEM_ROOT *root, char *ptr); extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, size_t prealloc_size); extern char *strdup_root(MEM_ROOT *root,const char *str); +static inline char *safe_strdup_root(MEM_ROOT *root, const char *str) +{ + return str ? strdup_root(root, str) : 0; +} extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len); extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len); extern int get_defaults_options(int argc, char **argv, diff --git a/include/mysql.h b/include/mysql.h index fdb29124d68..b52235b484e 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -167,9 +167,15 @@ enum mysql_option MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, - MYSQL_OPT_SSL_VERIFY_SERVER_CERT + MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH }; +/** + @todo remove the "extension", move st_mysql_options completely + out of mysql.h +*/ +struct st_mysql_options_extention; + struct st_mysql_options { unsigned int connect_timeout, read_timeout, write_timeout; unsigned int port, protocol; @@ -203,7 +209,7 @@ struct st_mysql_options { void (*local_infile_end)(void *); int (*local_infile_error)(void *, char *, unsigned int); void *local_infile_userdata; - void *extension; + struct st_mysql_options_extention *extension; }; enum mysql_status @@ -639,38 +645,6 @@ enum enum_stmt_attr_type }; -typedef struct st_mysql_methods -{ - my_bool (*read_query_result)(MYSQL *mysql); - my_bool (*advanced_command)(MYSQL *mysql, - enum enum_server_command command, - const unsigned char *header, - unsigned long header_length, - const unsigned char *arg, - unsigned long arg_length, - my_bool skip_check, - MYSQL_STMT *stmt); - MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - unsigned int fields); - MYSQL_RES * (*use_result)(MYSQL *mysql); - void (*fetch_lengths)(unsigned long *to, - MYSQL_ROW column, unsigned int field_count); - void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results); -#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) - MYSQL_FIELD * (*list_fields)(MYSQL *mysql); - my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt); - int (*stmt_execute)(MYSQL_STMT *stmt); - int (*read_binary_rows)(MYSQL_STMT *stmt); - int (*unbuffered_fetch)(MYSQL *mysql, char **row); - void (*free_embedded_thd)(MYSQL *mysql); - const char *(*read_statistics)(MYSQL *mysql); - my_bool (*next_result)(MYSQL *mysql); - int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd); - int (*read_rows_from_cursor)(MYSQL_STMT *stmt); -#endif -} MYSQL_METHODS; - - MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql); int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length); @@ -733,18 +707,6 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); #endif #define HAVE_MYSQL_REAL_CONNECT -/* - The following functions are mainly exported because of mysqlbinlog; - They are not for general usage -*/ - -#define simple_command(mysql, command, arg, length, skip_check) \ - (*(mysql)->methods->advanced_command)(mysql, command, 0, \ - 0, arg, length, skip_check, NULL) -#define stmt_command(mysql, command, arg, length, stmt) \ - (*(mysql)->methods->advanced_command)(mysql, command, 0, \ - 0, arg, length, 1, stmt) - #ifdef __cplusplus } #endif diff --git a/include/mysql.h.pp b/include/mysql.h.pp index c7bc5c294ce..0a5c3d83148 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -130,13 +130,13 @@ void create_random_string(char *to, unsigned int length, struct rand_struct *ran void hash_password(unsigned long *to, const char *password, unsigned int password_len); void make_scrambled_password_323(char *to, const char *password); void scramble_323(char *to, const char *message, const char *password); -my_bool check_scramble_323(const char *, const char *message, +my_bool check_scramble_323(const unsigned char *reply, const char *message, unsigned long *salt); void get_salt_from_password_323(unsigned long *res, const char *password); void make_password_from_salt_323(char *to, const unsigned long *salt); void make_scrambled_password(char *to, const char *password); void scramble(char *to, const char *message, const char *password); -my_bool check_scramble(const char *reply, const char *message, +my_bool check_scramble(const unsigned char *reply, const char *message, const unsigned char *hash_stage2); void get_salt_from_password(unsigned char *res, const char *password); void make_password_from_salt(char *to, const unsigned char *hash_stage2); @@ -262,8 +262,9 @@ enum mysql_option MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, - MYSQL_OPT_SSL_VERIFY_SERVER_CERT + MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH }; +struct st_mysql_options_extention; struct st_mysql_options { unsigned int connect_timeout, read_timeout, write_timeout; unsigned int port, protocol; @@ -293,7 +294,7 @@ struct st_mysql_options { void (*local_infile_end)(void *); int (*local_infile_error)(void *, char *, unsigned int); void *local_infile_userdata; - void *extension; + struct st_mysql_options_extention *extension; }; enum mysql_status { @@ -548,34 +549,6 @@ enum enum_stmt_attr_type STMT_ATTR_CURSOR_TYPE, STMT_ATTR_PREFETCH_ROWS }; -typedef struct st_mysql_methods -{ - my_bool (*read_query_result)(MYSQL *mysql); - my_bool (*advanced_command)(MYSQL *mysql, - enum enum_server_command command, - const unsigned char *header, - unsigned long header_length, - const unsigned char *arg, - unsigned long arg_length, - my_bool skip_check, - MYSQL_STMT *stmt); - MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - unsigned int fields); - MYSQL_RES * (*use_result)(MYSQL *mysql); - void (*fetch_lengths)(unsigned long *to, - MYSQL_ROW column, unsigned int field_count); - void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results); - MYSQL_FIELD * (*list_fields)(MYSQL *mysql); - my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt); - int (*stmt_execute)(MYSQL_STMT *stmt); - int (*read_binary_rows)(MYSQL_STMT *stmt); - int (*unbuffered_fetch)(MYSQL *mysql, char **row); - void (*free_embedded_thd)(MYSQL *mysql); - const char *(*read_statistics)(MYSQL *mysql); - my_bool (*next_result)(MYSQL *mysql); - int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd); - int (*read_rows_from_cursor)(MYSQL_STMT *stmt); -} MYSQL_METHODS; MYSQL_STMT * mysql_stmt_init(MYSQL *mysql); int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length); diff --git a/include/mysql/client_plugin.h b/include/mysql/client_plugin.h new file mode 100644 index 00000000000..ddd3b64ca56 --- /dev/null +++ b/include/mysql/client_plugin.h @@ -0,0 +1,164 @@ +#ifndef MYSQL_CLIENT_PLUGIN_INCLUDED +/* Copyright (C) 2010 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + + MySQL Client Plugin API + + This file defines the API for plugins that work on the client side +*/ +#define MYSQL_CLIENT_PLUGIN_INCLUDED + +#include +#include + +/* known plugin types */ +#define MYSQL_CLIENT_reserved1 0 +#define MYSQL_CLIENT_reserved2 1 +#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 + +#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100 + +#define MYSQL_CLIENT_MAX_PLUGINS 3 + +#define mysql_declare_client_plugin(X) \ + MYSQL_PLUGIN_EXPORT struct st_mysql_client_plugin_ ## X \ + _mysql_client_plugin_declaration_ = { \ + MYSQL_CLIENT_ ## X ## _PLUGIN, \ + MYSQL_CLIENT_ ## X ## _PLUGIN_INTERFACE_VERSION, +#define mysql_end_client_plugin } + +/* generic plugin header structure */ +#define MYSQL_CLIENT_PLUGIN_HEADER \ + int type; \ + unsigned int interface_version; \ + const char *name; \ + const char *author; \ + const char *desc; \ + unsigned int version[3]; \ + const char *license; \ + void *mysql_api; \ + int (*init)(char *, size_t, int, va_list); \ + int (*deinit)(); \ + int (*options)(const char *option, const void *); + +struct st_mysql_client_plugin +{ + MYSQL_CLIENT_PLUGIN_HEADER +}; + +struct st_mysql; + +/******** authentication plugin specific declarations *********/ +#include + +struct st_mysql_client_plugin_AUTHENTICATION +{ + MYSQL_CLIENT_PLUGIN_HEADER + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); +}; + +/******** using plugins ************/ + +/** + loads a plugin and initializes it + + @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used, + and last_errno/last_error, for error reporting + @param name a name of the plugin to load + @param type type of plugin that should be loaded, -1 to disable type check + @param argc number of arguments to pass to the plugin initialization + function + @param ... arguments for the plugin initialization function + + @retval + a pointer to the loaded plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, + int argc, ...); + +/** + loads a plugin and initializes it, taking va_list as an argument + + This is the same as mysql_load_plugin, but take va_list instead of + a list of arguments. + + @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used, + and last_errno/last_error, for error reporting + @param name a name of the plugin to load + @param type type of plugin that should be loaded, -1 to disable type check + @param argc number of arguments to pass to the plugin initialization + function + @param args arguments for the plugin initialization function + + @retval + a pointer to the loaded plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, + int argc, va_list args); + +/** + finds an already loaded plugin by name, or loads it, if necessary + + @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used, + and last_errno/last_error, for error reporting + @param name a name of the plugin to load + @param type type of plugin that should be loaded + + @retval + a pointer to the plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); + +/** + adds a plugin structure to the list of loaded plugins + + This is useful if an application has the necessary functionality + (for example, a special load data handler) statically linked into + the application binary. It can use this function to register the plugin + directly, avoiding the need to factor it out into a shared object. + + @param mysql MYSQL structure. It is only used for error reporting + @param plugin an st_mysql_client_plugin structure to register + + @retval + a pointer to the plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_client_register_plugin(struct st_mysql *mysql, + struct st_mysql_client_plugin *plugin); + +/** + set plugin options + + Can be used to set extra options and affect behavior for a plugin. + This function may be called multiple times to set several options + + @param plugin an st_mysql_client_plugin structure + @param option a string which specifies the option to set + @param value value for the option. + + @retval 0 on success, 1 in case of failure +**/ +int STDCALL mysql_plugin_options(struct st_mysql_client_plugin *plugin, + const char *option, + const void *value); +#endif + diff --git a/include/mysql/client_plugin.h.pp b/include/mysql/client_plugin.h.pp new file mode 100644 index 00000000000..58627e06f09 --- /dev/null +++ b/include/mysql/client_plugin.h.pp @@ -0,0 +1,42 @@ +#include +#include +struct st_mysql_client_plugin +{ + int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(); int (*options)(const char *option, const void *); +}; +struct st_mysql; +#include +typedef struct st_plugin_vio_info +{ + enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; + int socket; +} MYSQL_PLUGIN_VIO_INFO; +typedef struct st_plugin_vio +{ + int (*read_packet)(struct st_plugin_vio *vio, + unsigned char **buf); + int (*write_packet)(struct st_plugin_vio *vio, + const unsigned char *packet, + int packet_len); + void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); +} MYSQL_PLUGIN_VIO; +struct st_mysql_client_plugin_AUTHENTICATION +{ + int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(); int (*options)(const char *option, const void *); + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); +}; +struct st_mysql_client_plugin * +mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, + int argc, ...); +struct st_mysql_client_plugin * +mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, + int argc, va_list args); +struct st_mysql_client_plugin * +mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); +struct st_mysql_client_plugin * +mysql_client_register_plugin(struct st_mysql *mysql, + struct st_mysql_client_plugin *plugin); +int STDCALL mysql_plugin_options(struct st_mysql_client_plugin *plugin, + const char *option, + const void *value); diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 43de7deef74..7ec68ff5040 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -83,7 +83,8 @@ typedef struct st_mysql_xid MYSQL_XID; #define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */ #define MYSQL_AUDIT_PLUGIN 5 /* The Audit plugin type */ #define MYSQL_REPLICATION_PLUGIN 6 /* The replication plugin type */ -#define MYSQL_MAX_PLUGIN_TYPE_NUM 7 /* The number of plugin types */ +#define MYSQL_AUTHENTICATION_PLUGIN 7 /* The authentication plugin type */ +#define MYSQL_MAX_PLUGIN_TYPE_NUM 8 /* The number of plugin types */ /* We use the following strings to define licenses for plugins */ #define PLUGIN_LICENSE_PROPRIETARY 0 diff --git a/include/mysql/plugin_auth.h b/include/mysql/plugin_auth.h new file mode 100644 index 00000000000..5622e9cdebe --- /dev/null +++ b/include/mysql/plugin_auth.h @@ -0,0 +1,125 @@ +#ifndef MYSQL_PLUGIN_AUTH_INCLUDED +/* Copyright (C) 2010 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + + Authentication Plugin API. + + This file defines the API for server authentication plugins. +*/ + +#define MYSQL_PLUGIN_AUTH_INCLUDED + +#include + +#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0100 + +#include + +/* defines for MYSQL_SERVER_AUTH_INFO.password_used */ + +#define PASSWORD_USED_NO 0 +#define PASSWORD_USED_YES 1 +#define PASSWORD_USED_NO_MENTION 2 + + +/** + Provides server plugin access to authentication information +*/ +typedef struct st_mysql_server_auth_info +{ + /** + User name as sent by the client and shown in USER(). + NULL if the client packet with the user name was not received yet. + */ + char *user_name; + + /** + Length of user_name + */ + unsigned int user_name_length; + + /** + A corresponding column value from the mysql.user table for the + matching account name + */ + const char *auth_string; + + /** + Length of auth_string + */ + unsigned long auth_string_length; + + /** + Matching account name as found in the mysql.user table. + A plugin can override it with another name that will be + used by MySQL for authorization, and shown in CURRENT_USER() + */ + char authenticated_as[MYSQL_USERNAME_LENGTH+1]; + + + /** + The unique user name that was used by the plugin to authenticate. + Plugins should put null-terminated UTF-8 here. + Available through the @@EXTERNAL_USER variable. + */ + char external_user[512]; + + /** + This only affects the "Authentication failed. Password used: %s" + error message. has the following values : + 0 : %s will be NO. + 1 : %s will be YES. + 2 : there will be no %s. + Set it as appropriate or ignore at will. + */ + int password_used; + + /** + Set to the name of the connected client if it can be resolved, or to + the address otherwise + */ + const char *host_or_ip; + + /** + Length of host_or_ip + */ + unsigned int host_or_ip_length; + +} MYSQL_SERVER_AUTH_INFO; + +/** + Server authentication plugin descriptor +*/ +struct st_mysql_auth +{ + int interface_version; /**< version plugin uses */ + /** + A plugin that a client must use for authentication with this server + plugin. Can be NULL to mean "any plugin". + */ + const char *client_auth_plugin; + /** + Function provided by the plugin which should perform authentication (using + the vio functions if necessary) and return 0 if successful. The plugin can + also fill the info.authenticated_as field if a different username should be + used for authorization. + */ + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info); +}; +#endif + diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp new file mode 100644 index 00000000000..88588d03b9e --- /dev/null +++ b/include/mysql/plugin_auth.h.pp @@ -0,0 +1,224 @@ +#include +#include +#include +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +#include +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(void*, unsigned int); + void *(*thd_calloc_func)(void*, unsigned int); + char *(*thd_strdup_func)(void*, const char *); + char *(*thd_strmake_func)(void*, const char *, unsigned int); + void *(*thd_memdup_func)(void*, const void*, unsigned int); + MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *, + const char *, unsigned int, int); +} *thd_alloc_service; +void *thd_alloc(void* thd, unsigned int size); +void *thd_calloc(void* thd, unsigned int size); +char *thd_strdup(void* thd, const char *str); +char *thd_strmake(void* thd, const char *str, unsigned int size); +void *thd_memdup(void* thd, const void* str, unsigned int size); +MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, + const char *str, unsigned int size, + int allocate_lex_string); +#include +typedef enum _thd_wait_type_e { + THD_WAIT_MUTEX= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_TABLE_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(void*, thd_wait_type); + void (*thd_wait_end_func)(void*); +} *thd_wait_service; +void thd_wait_begin(void* thd, thd_wait_type wait_type); +void thd_wait_end(void* thd); +#include +struct scheduler_functions; +extern struct my_thread_scheduler_service { + int (*set)(struct scheduler_functions *scheduler); + int (*reset)(); +} *my_thread_scheduler_service; +int my_thread_scheduler_set(struct scheduler_functions *scheduler); +int my_thread_scheduler_reset(); +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG, + SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_always_last +}; +struct st_mysql_show_var { + const char *name; + char *value; + enum enum_mysql_show_type type; +}; +typedef int (*mysql_show_var_func)(void*, struct st_mysql_show_var*, char *); +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(void* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(void* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; +}; +#include "plugin_ftparser.h" +#include "plugin.h" +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + struct charset_info_st *cs; + char *doc; + int length; + int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +int thd_in_lock_tables(const void* thd); +int thd_tablespace_op(const void* thd); +long long thd_test_options(const void* thd, long long test_options); +int thd_sql_command(const void* thd); +const char *thd_proc_info(void* thd, const char *info); +void **thd_ha_data(const void* thd, const struct handlerton *hton); +void thd_storage_lock_wait(void* thd, long long value); +int thd_tx_isolation(const void* thd); +char *thd_security_context(void* thd, char *buffer, unsigned int length, + unsigned int max_query_len); +void thd_inc_row_count(void* thd); +int mysql_tmpfile(const char *prefix); +int thd_killed(const void* thd); +unsigned long thd_get_thread_id(const void* thd); +void thd_get_xid(const void* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(void* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const void* thd, const struct handlerton *hton); +void thd_set_ha_data(void* thd, const struct handlerton *hton, + const void *ha_data); +#include +typedef struct st_plugin_vio_info +{ + enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; + int socket; +} MYSQL_PLUGIN_VIO_INFO; +typedef struct st_plugin_vio +{ + int (*read_packet)(struct st_plugin_vio *vio, + unsigned char **buf); + int (*write_packet)(struct st_plugin_vio *vio, + const unsigned char *packet, + int packet_len); + void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); +} MYSQL_PLUGIN_VIO; +typedef struct st_mysql_server_auth_info +{ + char *user_name; + unsigned int user_name_length; + const char *auth_string; + unsigned long auth_string_length; + char authenticated_as[48 +1]; + char external_user[512]; + int password_used; + const char *host_or_ip; + unsigned int host_or_ip_length; +} MYSQL_SERVER_AUTH_INFO; +struct st_mysql_auth +{ + int interface_version; + const char *client_auth_plugin; + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info); +}; diff --git a/include/mysql/plugin_auth_common.h b/include/mysql/plugin_auth_common.h new file mode 100644 index 00000000000..4ad92d01bfb --- /dev/null +++ b/include/mysql/plugin_auth_common.h @@ -0,0 +1,105 @@ +#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED +/* Copyright (C) 2010 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + + This file defines constants and data structures that are the same for + both client- and server-side authentication plugins. +*/ +#define MYSQL_PLUGIN_AUTH_COMMON_INCLUDED + +/** the max allowed length for a user name */ +#define MYSQL_USERNAME_LENGTH 48 + +/** + return values of the plugin authenticate_user() method. +*/ + +/** + Authentication failed. Additionally, all other CR_xxx values + (libmysql error code) can be used too. + + The client plugin may set the error code and the error message directly + in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error + code was returned, an error message in the MYSQL structure will be + overwritten. If CR_ERROR is returned without setting the error in MYSQL, + CR_UNKNOWN_ERROR will be user. +*/ +#define CR_ERROR 0 +/** + Authentication (client part) was successful. It does not mean that the + authentication as a whole was successful, usually it only means + that the client was able to send the user name and the password to the + server. If CR_OK is returned, the libmysql reads the next packet expecting + it to be one of OK, ERROR, or CHANGE_PLUGIN packets. +*/ +#define CR_OK -1 +/** + Authentication was successful. + It means that the client has done its part successfully and also that + a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN). + In this case, libmysql will not read a packet from the server, + but it will use the data at mysql->net.read_pos. + + A plugin may return this value if the number of roundtrips in the + authentication protocol is not known in advance, and the client plugin + needs to read one packet more to determine if the authentication is finished + or not. +*/ +#define CR_OK_HANDSHAKE_COMPLETE -2 + +typedef struct st_plugin_vio_info +{ + enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; + int socket; /**< it's set, if the protocol is SOCKET or TCP */ +#ifdef _WIN32 + HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */ +#endif +} MYSQL_PLUGIN_VIO_INFO; + +/** + Provides plugin access to communication channel +*/ +typedef struct st_plugin_vio +{ + /** + Plugin provides a pointer reference and this function sets it to the + contents of any incoming packet. Returns the packet length, or -1 if + the plugin should terminate. + */ + int (*read_packet)(struct st_plugin_vio *vio, + unsigned char **buf); + + /** + Plugin provides a buffer with data and the length and this + function sends it as a packet. Returns 0 on success, 1 on failure. + */ + int (*write_packet)(struct st_plugin_vio *vio, + const unsigned char *packet, + int packet_len); + + /** + Fills in a st_plugin_vio_info structure, providing the information + about the connection. + */ + void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); + +} MYSQL_PLUGIN_VIO; + +#endif + diff --git a/include/mysql_com.h b/include/mysql_com.h index 90fe4ac1995..d4223211710 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -162,9 +162,17 @@ enum enum_server_command #define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */ #define CLIENT_PS_MULTI_RESULTS (1UL << 18) /* Multi-results in PS-protocol */ +#define CLIENT_PLUGIN_AUTH (1UL << 19) /* Client supports plugin authentication */ + #define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) #define CLIENT_REMEMBER_OPTIONS (1UL << 31) +#ifdef HAVE_COMPRESS +#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS +#else +#define CAN_CLIENT_COMPRESS 0 +#endif + /* Gather all possible capabilites (flags) supported by the server */ #define CLIENT_ALL_FLAGS (CLIENT_LONG_PASSWORD | \ CLIENT_FOUND_ROWS | \ @@ -186,7 +194,8 @@ enum enum_server_command CLIENT_MULTI_RESULTS | \ CLIENT_PS_MULTI_RESULTS | \ CLIENT_SSL_VERIFY_SERVER_CERT | \ - CLIENT_REMEMBER_OPTIONS) + CLIENT_REMEMBER_OPTIONS | \ + CLIENT_PLUGIN_AUTH) /* Switch off the flags that are optional and depending on build flags @@ -518,14 +527,14 @@ void create_random_string(char *to, unsigned int length, struct rand_struct *ran void hash_password(unsigned long *to, const char *password, unsigned int password_len); void make_scrambled_password_323(char *to, const char *password); void scramble_323(char *to, const char *message, const char *password); -my_bool check_scramble_323(const char *, const char *message, +my_bool check_scramble_323(const unsigned char *reply, const char *message, unsigned long *salt); void get_salt_from_password_323(unsigned long *res, const char *password); void make_password_from_salt_323(char *to, const unsigned long *salt); void make_scrambled_password(char *to, const char *password); void scramble(char *to, const char *message, const char *password); -my_bool check_scramble(const char *reply, const char *message, +my_bool check_scramble(const unsigned char *reply, const char *message, const unsigned char *hash_stage2); void get_salt_from_password(unsigned char *res, const char *password); void make_password_from_salt(char *to, const unsigned char *hash_stage2); diff --git a/include/sha1.h b/include/sha1.h index 5b4dc5d46ed..d60d5e17c60 100644 --- a/include/sha1.h +++ b/include/sha1.h @@ -9,12 +9,13 @@ 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 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* This is the header file for code which implements the Secure @@ -28,6 +29,38 @@ Please read the file sha1.c for more information. Modified 2002 by Peter Zaitsev to better follow MySQL standards + + Original Source from: http://www.faqs.org/rfcs/rfc3174.html + + Copyright (C) The Internet Society (2001). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + Acknowledgement + Funding for the RFC Editor function is currently provided by the + Internet Society. */ diff --git a/include/sql_common.h b/include/sql_common.h index 5fd8778d62b..a9a3168b691 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -16,14 +16,60 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define SQL_COMMON_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include extern const char *unknown_sqlstate; extern const char *cant_connect_sqlstate; extern const char *not_error_sqlstate; -#ifdef __cplusplus -extern "C" { +struct st_mysql_options_extention { + char *plugin_dir; + char *default_auth; +}; + +typedef struct st_mysql_methods +{ + my_bool (*read_query_result)(MYSQL *mysql); + my_bool (*advanced_command)(MYSQL *mysql, + enum enum_server_command command, + const unsigned char *header, + unsigned long header_length, + const unsigned char *arg, + unsigned long arg_length, + my_bool skip_check, + MYSQL_STMT *stmt); + MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields, + unsigned int fields); + MYSQL_RES * (*use_result)(MYSQL *mysql); + void (*fetch_lengths)(unsigned long *to, + MYSQL_ROW column, unsigned int field_count); + void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results); + int (*read_change_user_result)(MYSQL *mysql); +#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) + MYSQL_FIELD * (*list_fields)(MYSQL *mysql); + my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt); + int (*stmt_execute)(MYSQL_STMT *stmt); + int (*read_binary_rows)(MYSQL_STMT *stmt); + int (*unbuffered_fetch)(MYSQL *mysql, char **row); + void (*free_embedded_thd)(MYSQL *mysql); + const char *(*read_statistics)(MYSQL *mysql); + my_bool (*next_result)(MYSQL *mysql); + int (*read_rows_from_cursor)(MYSQL_STMT *stmt); #endif +} MYSQL_METHODS; + +#define simple_command(mysql, command, arg, length, skip_check) \ + (*(mysql)->methods->advanced_command)(mysql, command, 0, \ + 0, arg, length, skip_check, NULL) +#define stmt_command(mysql, command, arg, length, stmt) \ + (*(mysql)->methods->advanced_command)(mysql, command, 0, \ + 0, arg, length, 1, stmt) extern CHARSET_INFO *default_client_charset_info; MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, @@ -45,6 +91,19 @@ void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net); void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate, const char *err); void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate); +void set_mysql_extended_error(MYSQL *mysql, int errcode, const char *sqlstate, + const char *format, ...); + +/* client side of the pluggable authentication */ +struct st_plugin_vio_info; +void mpvio_info(Vio *vio, struct st_plugin_vio_info *info); +int run_plugin_auth(MYSQL *mysql, char *data, uint data_len, + const char *data_plugin, const char *db); +int mysql_client_plugin_init(); +void mysql_client_plugin_deinit(); +struct st_mysql_client_plugin; +extern struct st_mysql_client_plugin *mysql_client_builtins[]; + #ifdef __cplusplus } #endif diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index 0de582a0212..7441423743e 100644 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -140,6 +140,7 @@ SET(CLIENT_SOURCES errmsg.c ../sql-common/client.c ../sql-common/my_time.c + ../sql-common/client_plugin.c ../sql/net_serv.cc ../sql-common/pack.c ../sql/password.c @@ -148,7 +149,7 @@ ADD_CONVENIENCE_LIBRARY(clientlib ${CLIENT_SOURCES}) DTRACE_INSTRUMENT(clientlib) ADD_DEPENDENCIES(clientlib GenError) -SET(LIBS clientlib dbug strings vio mysys ${ZLIB_LIBRARY} ${SSL_LIBRARIES}) +SET(LIBS clientlib dbug strings vio mysys ${ZLIB_LIBRARY} ${SSL_LIBRARIES} ${LIBDL}) # Merge several convenience libraries into one big mysqlclient # and link them together into shared library. diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 887af62229a..5a7236f1e6d 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -23,6 +23,7 @@ MYSQLDATAdir = $(localstatedir) MYSQLSHAREdir = $(pkgdatadir) MYSQLBASEdir= $(prefix) +pkgplugindir = $(pkglibdir)/plugin ## We'll use CLIENT_EXTRA_LDFLAGS for threaded and non-threaded ## until someone complains that they need separate options. LDADD = @CLIENT_EXTRA_LDFLAGS@ $(target) @@ -70,26 +71,27 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo \ my_rename.lo my_chsize.lo my_sync.lo \ my_getsystime.lo my_symlink2.lo mf_same.lo sqlobjects = net.lo -sql_cmn_objects = pack.lo client.lo my_time.lo +sql_cmn_objects = pack.lo client.lo my_time.lo client_plugin.lo # Not needed in the minimum library mysysobjects2 = my_lib.lo mf_qsort.lo mysysobjects = $(mysysobjects1) $(mysysobjects2) target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \ $(sql_cmn_objects) $(vio_objects) $(sqlobjects) -target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@ +target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@ @LIBDL@ vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo BUILT_SOURCES = link_sources CLEANFILES = $(target_libadd) $(SHLIBOBJS) \ $(target) $(BUILT_SOURCES) -DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \ - -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \ +DEFS = -DDEFAULT_CHARSET_HOME='"$(MYSQLBASEdir)"' \ + -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \ -DDEFAULT_HOME_ENV=MYSQL_HOME \ + -DPLUGINDIR='"$(pkgplugindir)"' \ -DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \ - -DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \ - -DSHAREDIR="\"$(MYSQLSHAREdir)\"" -DDISABLE_DTRACE \ + -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \ + -DSHAREDIR='"$(MYSQLSHAREdir)"' -DDISABLE_DTRACE \ $(target_defs) if HAVE_YASSL diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index aaec08d1b1e..5204d03e5af 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -28,7 +28,8 @@ extern char * mysql_unix_port; CLIENT_PROTOCOL_41 | \ CLIENT_SECURE_CONNECTION | \ CLIENT_MULTI_RESULTS | \ - CLIENT_PS_MULTI_RESULTS) + CLIENT_PS_MULTI_RESULTS | \ + CLIENT_PLUGIN_AUTH) sig_handler my_pipe_sig_handler(int sig); void read_user_name(char *name); @@ -67,7 +68,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt); int cli_read_binary_rows(MYSQL_STMT *stmt); int cli_unbuffered_fetch(MYSQL *mysql, char **row); const char * cli_read_statistics(MYSQL *mysql); -int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd); +int cli_read_change_user_result(MYSQL *mysql); #ifdef EMBEDDED_LIBRARY int init_embedded_server(int argc, char **argv, char **groups); diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index febbded6af2..823f83026c9 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -84,7 +84,8 @@ const char *client_errors[]= "Lost connection to MySQL server at '%s', system error: %d", "Statement closed indirectly because of a preceeding %s() call", "The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again", - "This handle is already connected. Use a separate handle for each connection." + "This handle is already connected. Use a separate handle for each connection.", + "Authentication plugin '%s' cannot be loaded: %s", "" }; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index a44395578c6..e9327d770fb 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -126,6 +126,8 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)), if (my_init()) /* Will init threads */ return 1; init_client_errs(); + if (mysql_client_plugin_init()) + return 1; if (!mysql_port) { char *env; @@ -196,6 +198,8 @@ void STDCALL mysql_server_end() if (!mysql_client_init) return; + mysql_client_plugin_deinit(); + #ifdef EMBEDDED_LIBRARY end_embedded_server(); #endif @@ -345,44 +349,14 @@ mysql_connect(MYSQL *mysql,const char *host, Change user and database **************************************************************************/ -int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd) -{ - NET *net= &mysql->net; - ulong pkt_length; - - pkt_length= cli_safe_read(mysql); - - if (pkt_length == packet_error) - return 1; - - if (pkt_length == 1 && net->read_pos[0] == 254 && - mysql->server_capabilities & CLIENT_SECURE_CONNECTION) - { - /* - By sending this very specific reply server asks us to send scrambled - password in old format. The reply contains scramble_323. - */ - scramble_323(buff, mysql->scramble, passwd); - if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) || - net_flush(net)) - { - set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); - return 1; - } - /* Read what server thinks about out new auth message report */ - if (cli_safe_read(mysql) == packet_error) - return 1; - } - return 0; -} - my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, const char *passwd, const char *db) { - char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2]; - char *end= buff; int rc; CHARSET_INFO *saved_cs= mysql->charset; + char *saved_user= mysql->user; + char *saved_passwd= mysql->passwd; + char *saved_db= mysql->db; DBUG_ENTER("mysql_change_user"); @@ -396,49 +370,11 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, /* Use an empty string instead of NULL. */ - if (!user) - user=""; - if (!passwd) - passwd=""; + mysql->user= (char*)(user ? user : ""); + mysql->passwd= (char*)(passwd ? passwd : ""); + mysql->db= 0; - /* - Store user into the buffer. - Advance position as strmake returns a pointer to the closing NUL. - */ - end= strmake(end, user, USERNAME_LENGTH) + 1; - - /* write scrambled password according to server capabilities */ - if (passwd[0]) - { - if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) - { - *end++= SCRAMBLE_LENGTH; - scramble(end, mysql->scramble, passwd); - end+= SCRAMBLE_LENGTH; - } - else - { - scramble_323(end, mysql->scramble, passwd); - end+= SCRAMBLE_LENGTH_323 + 1; - } - } - else - *end++= '\0'; /* empty password */ - /* Add database if needed */ - end= strmake(end, db ? db : "", NAME_LEN) + 1; - - /* Add character set number. */ - - if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) - { - int2store(end, (ushort) mysql->charset->number); - end+= 2; - } - - /* Write authentication package */ - simple_command(mysql,COM_CHANGE_USER, (uchar*) buff, (ulong) (end-buff), 1); - - rc= (*mysql->methods->read_change_user_result)(mysql, buff, passwd); + rc= run_plugin_auth(mysql, 0, 0, 0, db); /* The server will close all statements no matter was the attempt @@ -448,18 +384,21 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, if (rc == 0) { /* Free old connect information */ - my_free(mysql->user); - my_free(mysql->passwd); - my_free(mysql->db); + my_free(saved_user); + my_free(saved_passwd); + my_free(saved_db); /* alloc new connect information */ - mysql->user= my_strdup(user,MYF(MY_WME)); - mysql->passwd=my_strdup(passwd,MYF(MY_WME)); - mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0; + mysql->user= my_strdup(mysql->user, MYF(MY_WME)); + mysql->passwd= my_strdup(mysql->passwd, MYF(MY_WME)); + mysql->db= db ? my_strdup(db, MYF(MY_WME)) : 0; } else { mysql->charset= saved_cs; + mysql->user= saved_user; + mysql->passwd= saved_passwd; + mysql->db= saved_db; } DBUG_RETURN(rc); diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index ce85d2a4086..fc15fcf0884 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -104,3 +104,4 @@ EXPORTS mysql_server_end mysql_set_character_set mysql_get_character_set_info + mysql_plugin_options diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 87bb7994835..545d03532c1 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -42,6 +42,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../libmysql/libmysql.c ../libmysql/errmsg.c ../client/get_password.c ../sql-common/client.c ../sql-common/my_time.c ../sql-common/my_user.c ../sql-common/pack.c + ../sql-common/client_plugin.c ../sql/password.c ../sql/discover.cc ../sql/derror.cc ../sql/field.cc ../sql/field_conv.cc ../sql/filesort.cc ../sql/gstream.cc diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index dabfa2b02cc..279f1007243 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -39,7 +39,7 @@ pkglib_LIBRARIES = libmysqld.a SUBDIRS = . examples libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \ - my_time.c + my_time.c client_plugin.c noinst_HEADERS = embedded_priv.h emb_qcache.h diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h index 369b344d4bd..c246693594b 100644 --- a/libmysqld/embedded_priv.h +++ b/libmysqld/embedded_priv.h @@ -15,6 +15,8 @@ /* Prototypes for the embedded version of MySQL */ +#include + C_MODE_START void lib_connection_phase(NET *net, int phase); void init_embedded_mysql(MYSQL *mysql, int client_flag); diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 7d61dbc55f4..1c9b773de15 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -35,7 +35,6 @@ C_MODE_START #include #undef ER #include "errmsg.h" -#include #include "embedded_priv.h" extern unsigned int mysql_server_last_errno; @@ -414,11 +413,10 @@ static MYSQL_RES * emb_store_result(MYSQL *mysql) return mysql_store_result(mysql); } -int emb_read_change_user_result(MYSQL *mysql, - char *buff __attribute__((unused)), - const char *passwd __attribute__((unused))) +int emb_read_change_user_result(MYSQL *mysql) { - return mysql_errno(mysql); + mysql->net.read_pos= (uchar*)""; // fake an OK packet + return mysql_errno(mysql) ? packet_error : 1 /* length of the OK packet */; } MYSQL_METHODS embedded_methods= @@ -429,6 +427,7 @@ MYSQL_METHODS embedded_methods= emb_store_result, emb_fetch_lengths, emb_flush_use_result, + emb_read_change_user_result, emb_list_fields, emb_read_prepare_result, emb_stmt_execute, @@ -437,7 +436,6 @@ MYSQL_METHODS embedded_methods= emb_free_embedded_thd, emb_read_statistics, emb_read_query_result, - emb_read_change_user_result, emb_read_rows_from_cursor }; @@ -605,6 +603,7 @@ void init_embedded_mysql(MYSQL *mysql, int client_flag) THD *thd = (THD *)mysql->thd; thd->mysql= mysql; mysql->server_version= server_version; + mysql->client_flag= client_flag; init_alloc_root(&mysql->field_alloc, 8192, 0); } @@ -668,14 +667,20 @@ err: int check_embedded_connection(MYSQL *mysql, const char *db) { int result; + LEX_STRING db_str = { (char*)db, db ? strlen(db) : 0 }; THD *thd= (THD*)mysql->thd; thd_init_client_charset(thd, mysql->charset->number); thd->update_charset(); Security_context *sctx= thd->security_ctx; sctx->host_or_ip= sctx->host= (char*) my_localhost; strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1); - sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0)); - result= check_user(thd, COM_CONNECT, NULL, 0, db, true); + strmake(sctx->priv_user, mysql->user, USERNAME_LENGTH-1); + sctx->user= my_strdup(mysql->user, MYF(0)); + sctx->proxy_user[0]= 0; + sctx->master_access= GLOBAL_ACLS; // Full rights + /* Change database if necessary */ + if (!(result= (db && db[0] && mysql_change_db(thd, &db_str, FALSE)))) + my_ok(thd); thd->protocol->end_statement(); emb_read_query_result(mysql); return result; @@ -684,14 +689,15 @@ int check_embedded_connection(MYSQL *mysql, const char *db) #else int check_embedded_connection(MYSQL *mysql, const char *db) { + /* + we emulate a COM_CHANGE_USER user here, + it's easier than to emulate the complete 3-way handshake + */ + char buf[USERNAME_LENGTH + SCRAMBLE_LENGTH + 1 + 2*NAME_LEN + 2], *end; + NET *net= &mysql->net; THD *thd= (THD*)mysql->thd; Security_context *sctx= thd->security_ctx; - int result; - char scramble_buff[SCRAMBLE_LENGTH]; - int passwd_len; - thd_init_client_charset(thd, mysql->charset->number); - thd->update_charset(); if (mysql->options.client_ip) { sctx->host= my_strdup(mysql->options.client_ip, MYF(0)); @@ -702,37 +708,43 @@ int check_embedded_connection(MYSQL *mysql, const char *db) sctx->host_or_ip= sctx->host; if (acl_check_host(sctx->host, sctx->ip)) - { - result= ER_HOST_NOT_PRIVILEGED; goto err; - } - sctx->user= my_strdup(mysql->user, MYF(0)); + /* construct a COM_CHANGE_USER packet */ + end= strmake(buf, mysql->user, USERNAME_LENGTH) + 1; + + memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble + thd->scramble[SCRAMBLE_LENGTH]= 0; + if (mysql->passwd && mysql->passwd[0]) { - memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble - thd->scramble[SCRAMBLE_LENGTH]= 0; - scramble(scramble_buff, thd->scramble, mysql->passwd); - passwd_len= SCRAMBLE_LENGTH; + *end++= SCRAMBLE_LENGTH; + scramble(end, thd->scramble, mysql->passwd); + end+= SCRAMBLE_LENGTH; } else - passwd_len= 0; + *end++= 0; - if((result= check_user(thd, COM_CONNECT, - scramble_buff, passwd_len, db, true))) - goto err; + end= strmake(end, db ? db : "", NAME_LEN) + 1; + int2store(end, (ushort) mysql->charset->number); + end+= 2; + + /* acl_authenticate() takes the data from thd->net->read_pos */ + thd->net.read_pos= (uchar*)buf; + + if (acl_authenticate(thd, 0, end - buf)) + { + x_free(thd->security_ctx->user); + goto err; + } return 0; err: - { - NET *net= &mysql->net; - strmake(net->last_error, thd->stmt_da->message(), - sizeof(net->last_error)-1); - memcpy(net->sqlstate, - mysql_errno_to_sqlstate(thd->stmt_da->sql_errno()), - sizeof(net->sqlstate)-1); - } - return result; + strmake(net->last_error, thd->main_da.message(), sizeof(net->last_error)-1); + memcpy(net->sqlstate, + mysql_errno_to_sqlstate(thd->main_da.sql_errno()), + sizeof(net->sqlstate)-1); + return 1; } #endif diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index 603fc3bc2f0..f6f0e1ba3db 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -17,7 +17,6 @@ #include #include #include -#include "embedded_priv.h" #include #include #include @@ -28,6 +27,7 @@ #include #include #include +#include "embedded_priv.h" #include "client_settings.h" #ifdef HAVE_PWD_H #include @@ -165,7 +165,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, client_flag|=CLIENT_CAPABILITIES; if (client_flag & CLIENT_MULTI_STATEMENTS) client_flag|= CLIENT_MULTI_RESULTS; - client_flag&= ~CLIENT_COMPRESS; + /* + no compression in embedded as we don't send any data, + and no pluggable auth, as we cannot do a client-server dialog + */ + client_flag&= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH); if (db) client_flag|=CLIENT_CONNECT_WITH_DB; diff --git a/mysql-test/collections/default.daily b/mysql-test/collections/default.daily index d23ae8a6d51..81dffff91ce 100644 --- a/mysql-test/collections/default.daily +++ b/mysql-test/collections/default.daily @@ -2,5 +2,4 @@ perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collection perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=embedded --vardir=var-emebbed --embedded perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 -perl mysql-test-run.pl --timer --force --parallel=auto --comment=rpl_ndb_row --vardir=var-rpl_ndb_row --mysqld=--binlog-format=row --suite=rpl_ndb,ndb perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog --skip-ndb diff --git a/mysql-test/include/have_plugin_auth.inc b/mysql-test/include/have_plugin_auth.inc new file mode 100644 index 00000000000..41f11419c64 --- /dev/null +++ b/mysql-test/include/have_plugin_auth.inc @@ -0,0 +1,4 @@ +disable_query_log; +--require r/true.require +select (PLUGIN_LIBRARY LIKE 'auth_test_plugin%') as `TRUE` FROM INFORMATION_SCHEMA.PLUGINS + WHERE PLUGIN_NAME='test_plugin_server'; diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 3c684062600..87f96496c73 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -926,7 +926,7 @@ sub collect_one_test_case { { # Ndb is not supported, skip it $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "No ndbcluster support"; + $tinfo->{'comment'}= "No ndbcluster support or ndb tests not enabled"; return $tinfo; } elsif ( $::opt_skip_ndbcluster ) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 494ec7a9be3..baf179a4ae6 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -131,6 +131,9 @@ my $opt_start_dirty; my $opt_start_exit; my $start_only; +my $auth_filename; # the name of the authentication test plugin +my $auth_plugin; # the path to the authentication test plugin + END { if ( defined $opt_tmpdir_pid and $opt_tmpdir_pid == $$ ) { @@ -281,7 +284,8 @@ sub testcase_timeout ($) { our $opt_warnings= 1; -our $opt_skip_ndbcluster= 0; +our $opt_include_ndbcluster= 0; +our $opt_skip_ndbcluster= 1; my $exe_ndbd; my $exe_ndb_mgmd; @@ -877,6 +881,7 @@ sub command_line_setup { # Control what test suites or cases to run 'force' => \$opt_force, 'with-ndbcluster-only' => \&collect_option, + 'include-ndbcluster' => \$opt_include_ndbcluster, 'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster, 'suite|suites=s' => \$opt_suites, 'skip-rpl' => \&collect_option, @@ -1057,6 +1062,22 @@ sub command_line_setup { "$basedir/sql/share/charsets", "$basedir/share/charsets"); + # Look for client test plugin + if (IS_WINDOWS) + { + $auth_filename = "auth_test_plugin.dll"; + } + else + { + $auth_filename = "auth_test_plugin.so"; + } + $auth_plugin= + mtr_file_exists(vs_config_dirs('plugin/auth/',$auth_filename), + "$basedir/plugin/auth/.libs/" . $auth_filename, + "$basedir/lib/mysql/plugin/" . $auth_filename, + "$basedir/lib/plugin/" . $auth_filename); + + if (using_extern()) { # Connect to the running mysqld and find out what it supports @@ -1943,6 +1964,24 @@ sub environment_setup { $ENV{'UDF_EXAMPLE_LIB_OPT'}= "--plugin-dir=". ($lib_udf_example ? dirname($lib_udf_example) : ""); + # -------------------------------------------------------------------------- + # Add the path where mysqld will find the auth test plugin (dialog.so/dll) + # -------------------------------------------------------------------------- + if ($auth_plugin) + { + $ENV{'PLUGIN_AUTH'}= basename($auth_plugin); + $ENV{'PLUGIN_AUTH_OPT'}= "--plugin-dir=".dirname($auth_plugin); + + $ENV{'PLUGIN_AUTH_LOAD'}="--plugin_load=test_plugin_server=".$auth_filename; + } + else + { + $ENV{'PLUGIN_AUTH'}= ""; + $ENV{'PLUGIN_AUTH_OPT'}="--plugin-dir="; + $ENV{'PLUGIN_AUTH_LOAD'}=""; + } + + # -------------------------------------------------------------------------- # Add the path where mysqld will find ha_example.so # -------------------------------------------------------------------------- @@ -2471,6 +2510,11 @@ sub vs_config_dirs ($$) { sub check_ndbcluster_support ($) { my $mysqld_variables= shift; + if ($opt_include_ndbcluster) + { + $opt_skip_ndbcluster= 0; + } + if ($opt_skip_ndbcluster) { mtr_report(" - skipping ndbcluster"); @@ -5032,6 +5076,10 @@ sub start_mysqltest ($) { mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); mtr_add_arg($args, "--logdir=%s/log", $opt_vardir); + if ($auth_plugin) + { + mtr_add_arg($args, "--plugin_dir=%s", dirname($auth_plugin)); + } # Log line number and time for each line in .test file mtr_add_arg($args, "--mark-progress") @@ -5510,7 +5558,8 @@ Options to control what test suites or cases to run force Continue to run the suite after failure with-ndbcluster-only Run only tests that include "ndb" in the filename - skip-ndb[cluster] Skip all tests that need cluster + skip-ndb[cluster] Skip all tests that need cluster. Default. + include-ndb[cluster] Enable all tests that need cluster do-test=PREFIX or REGEX Run test cases which name are prefixed with PREFIX or fulfills REGEX diff --git a/mysql-test/r/1st.result b/mysql-test/r/1st.result index ae9989ce563..e8562662bfd 100644 --- a/mysql-test/r/1st.result +++ b/mysql-test/r/1st.result @@ -21,6 +21,7 @@ ndb_binlog_index plugin proc procs_priv +proxy_priv servers slow_log tables_priv diff --git a/mysql-test/r/change_user.result b/mysql-test/r/change_user.result index 1ed7fcbb8fa..3021b5472bf 100644 --- a/mysql-test/r/change_user.result +++ b/mysql-test/r/change_user.result @@ -1,3 +1,39 @@ +grant select on test.* to test_nopw; +grant select on test.* to test_oldpw identified by password "09301740536db389"; +grant select on test.* to test_newpw identified by "newpw"; +select user(), current_user(), database(); +user() current_user() database() +root@localhost root@localhost test +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); +concat('<', user(), '>') concat('<', current_user(), '>') database() + test +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); +concat('<', user(), '>') concat('<', current_user(), '>') database() + NULL +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); +concat('<', user(), '>') concat('<', current_user(), '>') database() + NULL +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); +concat('<', user(), '>') concat('<', current_user(), '>') database() + NULL +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); +concat('<', user(), '>') concat('<', current_user(), '>') database() + NULL +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); +concat('<', user(), '>') concat('<', current_user(), '>') database() + test +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); +concat('<', user(), '>') concat('<', current_user(), '>') database() + test +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); +concat('<', user(), '>') concat('<', current_user(), '>') database() + test +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); +concat('<', user(), '>') concat('<', current_user(), '>') database() + test +drop user test_nopw; +drop user test_oldpw; +drop user test_newpw; Bug#20023 SELECT @@session.sql_big_selects; @@session.sql_big_selects diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result index 5e6c013bb38..bbd0273c1c6 100644 --- a/mysql-test/r/connect.result +++ b/mysql-test/r/connect.result @@ -15,6 +15,7 @@ ndb_binlog_index plugin proc procs_priv +proxy_priv servers slow_log tables_priv @@ -48,6 +49,7 @@ ndb_binlog_index plugin proc procs_priv +proxy_priv servers slow_log tables_priv @@ -89,6 +91,7 @@ ndb_binlog_index plugin proc procs_priv +proxy_priv servers slow_log tables_priv diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result index a5003c936e8..a27c7dc18ee 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -568,6 +568,7 @@ USE test; SHOW GRANTS FOR CURRENT_USER; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION SET GLOBAL event_scheduler = ON; CREATE TABLE events_test.event_log (id int KEY AUTO_INCREMENT, ev_nm char(40), ev_cnt int, ev_tm timestamp) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 65ebbd71c39..84cac386b57 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -13,8 +13,48 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3 GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost' grant delete on mysqltest.* to mysqltest_1@localhost; select * from mysql.user where user="mysqltest_1"; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections -localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0 +Host localhost +User mysqltest_1 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type SPECIFIED +ssl_cipher EDH-RSA-DES-CBC3-SHA +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA' @@ -44,15 +84,95 @@ delete from mysql.user where user='mysqltest_1'; flush privileges; grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10; select * from mysql.user where user="mysqltest_1"; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections -localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0 +Host localhost +User mysqltest_1 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 10 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30; select * from mysql.user where user="mysqltest_1"; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections -localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0 +Host localhost +User mysqltest_1 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 10 +max_updates 20 +max_connections 30 +max_user_connections 0 +plugin +authentication_string show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30 @@ -164,6 +284,7 @@ Warnings: Warning 1364 Field 'ssl_cipher' doesn't have a default value Warning 1364 Field 'x509_issuer' doesn't have a default value Warning 1364 Field 'x509_subject' doesn't have a default value +Warning 1364 Field 'authentication_string' doesn't have a default value insert into mysql.db (host, db, user, select_priv) values ('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y'); alter table mysql.db order by db asc; @@ -625,16 +746,19 @@ show grants for root@localhost; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION GRANT SELECT ON `ÂÄ`.* TO 'root'@'localhost' +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION flush privileges; show grants for root@localhost; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION GRANT SELECT ON `ÂÄ`.* TO 'root'@'localhost' +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION drop database ÂÄ; revoke all privileges on ÂÄ.* from root@localhost; show grants for root@localhost; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION set names latin1; create user mysqltest_7@; set password for mysqltest_7@ = password('systpass'); diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 3032ca854bd..b5e82794658 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -11,7 +11,7 @@ grant create user on *.* to mysqltest_1@localhost; create user mysqltest_2@localhost; grant select on `my\_1`.* to mysqltest_2@localhost; grant select on `my\_1`.* to mysqltest_2@localhost identified by 'pass'; -ERROR 42000: You must have privileges to update tables in the mysql database to be able to change passwords for others +ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysql' grant update on mysql.* to mysqltest_1@localhost; grant select on `my\_1`.* to mysqltest_2@localhost identified by 'pass'; grant select on `my\_1`.* to mysqltest_3@localhost; @@ -287,6 +287,7 @@ Warnings: Warning 1364 Field 'ssl_cipher' doesn't have a default value Warning 1364 Field 'x509_issuer' doesn't have a default value Warning 1364 Field 'x509_subject' doesn't have a default value +Warning 1364 Field 'authentication_string' doesn't have a default value create user mysqltest_A@'%'; rename user mysqltest_B@'%' to mysqltest_C@'%'; drop user mysqltest_C@'%'; @@ -334,7 +335,7 @@ delete from mysql.user where user like 'mysqltest\_1'; flush privileges; drop database mysqltest_1; set password = password("changed"); -ERROR 42000: Access denied for user ''@'localhost' to database 'mysql' +ERROR 42000: Can't find any matching row in the user table lock table mysql.user write; flush privileges; grant all on *.* to 'mysqltest_1'@'localhost'; @@ -354,6 +355,7 @@ Warnings: Warning 1364 Field 'ssl_cipher' doesn't have a default value Warning 1364 Field 'x509_issuer' doesn't have a default value Warning 1364 Field 'x509_subject' doesn't have a default value +Warning 1364 Field 'authentication_string' doesn't have a default value INSERT INTO mysql.db (host, db, user, select_priv) VALUES ('%','TESTDB','mysqltest_1','Y'); FLUSH PRIVILEGES; diff --git a/mysql-test/r/grant_cache_no_prot.result b/mysql-test/r/grant_cache_no_prot.result index 32bb9cce90e..019edb72086 100644 --- a/mysql-test/r/grant_cache_no_prot.result +++ b/mysql-test/r/grant_cache_no_prot.result @@ -7,9 +7,11 @@ flush status; show grants for current_user; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION show grants; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION create database if not exists mysqltest; create table mysqltest.t1 (a int,b int,c int); create table mysqltest.t2 (a int,b int,c int); diff --git a/mysql-test/r/grant_cache_ps_prot.result b/mysql-test/r/grant_cache_ps_prot.result index 281468ee2e1..e95a858fd9a 100644 --- a/mysql-test/r/grant_cache_ps_prot.result +++ b/mysql-test/r/grant_cache_ps_prot.result @@ -7,9 +7,11 @@ flush status; show grants for current_user; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION show grants; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION create database if not exists mysqltest; create table mysqltest.t1 (a int,b int,c int); create table mysqltest.t2 (a int,b int,c int); diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 21b42577a11..aa47b8c437e 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -88,6 +88,7 @@ host plugin proc procs_priv +proxy_priv servers slow_log tables_priv @@ -684,6 +685,7 @@ Alter_routine_priv select,insert,update,references max_questions select,insert,update,references max_connections select,insert,update,references max_user_connections select,insert,update,references +authentication_string select,insert,update,references use test; create function sub1(i int) returns int return i+1; @@ -870,7 +872,7 @@ AND table_name not like 'ndb%' AND table_name not like 'innodb_%' GROUP BY TABLE_SCHEMA; table_schema count(*) information_schema 30 -mysql 22 +mysql 23 create table t1 (i int, j int); create trigger trg1 before insert on t1 for each row begin diff --git a/mysql-test/r/log_tables_upgrade.result b/mysql-test/r/log_tables_upgrade.result index 814ebd7d5dc..13b08c2e771 100644 --- a/mysql-test/r/log_tables_upgrade.result +++ b/mysql-test/r/log_tables_upgrade.result @@ -27,6 +27,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.renamed_general_log OK mysql.servers OK mysql.slow_log OK diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index 5252d5f0c17..f705db3e509 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -15,6 +15,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.servers OK mysql.slow_log OK mysql.tables_priv OK @@ -43,6 +44,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.servers OK mysql.slow_log OK mysql.tables_priv OK @@ -71,6 +73,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.servers OK mysql.slow_log OK mysql.tables_priv OK @@ -101,6 +104,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.servers OK mysql.slow_log OK mysql.tables_priv OK @@ -135,6 +139,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.servers OK mysql.slow_log OK mysql.tables_priv OK @@ -172,6 +177,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.servers OK mysql.slow_log OK mysql.tables_priv OK diff --git a/mysql-test/r/mysql_upgrade_ssl.result b/mysql-test/r/mysql_upgrade_ssl.result index b89862966b5..694eb1e7d88 100644 --- a/mysql-test/r/mysql_upgrade_ssl.result +++ b/mysql-test/r/mysql_upgrade_ssl.result @@ -17,6 +17,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.servers OK mysql.slow_log OK mysql.tables_priv OK diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index 06175955d7f..c51d71510f4 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -18,6 +18,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.servers OK mysql.slow_log note : The storage engine for the table doesn't support optimize @@ -43,6 +44,7 @@ mysql.ndb_binlog_index OK mysql.plugin OK mysql.proc OK mysql.procs_priv OK +mysql.proxy_priv OK mysql.servers OK mysql.slow_log note : The storage engine for the table doesn't support optimize diff --git a/mysql-test/r/mysqld--help-win.result b/mysql-test/r/mysqld--help-win.result index e1098b71e25..c5996981e92 100644 --- a/mysql-test/r/mysqld--help-win.result +++ b/mysql-test/r/mysqld--help-win.result @@ -919,7 +919,6 @@ slave-transaction-retries 10 slave-type-conversions slow-launch-time 2 slow-query-log FALSE -socket MySQL sort-buffer-size 2097152 sporadic-binlog-dump-fail FALSE sql-mode diff --git a/mysql-test/r/plugin_auth.result b/mysql-test/r/plugin_auth.result new file mode 100644 index 00000000000..54467b78f19 --- /dev/null +++ b/mysql-test/r/plugin_auth.result @@ -0,0 +1,237 @@ +SELECT PLUGIN_STATUS, PLUGIN_TYPE, PLUGIN_DESCRIPTION +FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='test_plugin_server'; +PLUGIN_STATUS ACTIVE +PLUGIN_TYPE AUTHENTICATION +PLUGIN_DESCRIPTION plugin API test plugin +CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; +CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; +SELECT plugin,authentication_string FROM mysql.user WHERE User='plug'; +plugin authentication_string +test_plugin_server plug_dest +## test plugin auth +ERROR 28000: Access denied for user 'plug'@'localhost' (using password: YES) +GRANT PROXY ON plug_dest TO plug; +select USER(),CURRENT_USER(); +USER() CURRENT_USER() +plug@localhost plug_dest@% +## test SET PASSWORD +SET PASSWORD = PASSWORD('plug_dest'); +Warnings: +Note 1699 SET PASSWORD has no significance for users authenticating via plugins +## test bad credentials +ERROR 28000: Access denied for user 'plug'@'localhost' (using password: YES) +## test bad default plugin : should get CR_AUTH_PLUGIN_CANNOT_LOAD +## test correct default plugin +select USER(),CURRENT_USER(); +USER() CURRENT_USER() +plug@localhost plug@% +## test no_auto_create_user sql mode with plugin users +SET @@sql_mode=no_auto_create_user; +GRANT INSERT ON TEST.* TO grant_user IDENTIFIED WITH 'test_plugin_server'; +SET @@sql_mode=default; +DROP USER grant_user; +## test utf-8 user name +CREATE USER `Ÿ` IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; +GRANT PROXY ON plug_dest TO `Ÿ`; +select USER(),CURRENT_USER(); +USER() CURRENT_USER() +Ÿ@localhost plug_dest@% +DROP USER `Ÿ`; +## test GRANT ... IDENTIFIED WITH/BY ... +CREATE DATABASE test_grant_db; +# create new user via GRANT WITH +GRANT ALL PRIVILEGES ON test_grant_db.* TO new_grant_user +IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; +GRANT PROXY ON plug_dest TO new_grant_user; +select USER(),CURRENT_USER(); +USER() CURRENT_USER() +new_grant_user@localhost plug_dest@% +USE test_grant_db; +CREATE TABLE t1 (a INT); +DROP TABLE t1; +REVOKE ALL PRIVILEGES ON test_grant_db.* FROM new_grant_user; +# try re-create existing user via GRANT IDENTIFIED BY +GRANT ALL PRIVILEGES ON test_grant_db.* TO new_grant_user +IDENTIFIED BY 'unused_password'; +# make sure password doesn't take precendence +ERROR 28000: Access denied for user 'new_grant_user'@'localhost' (using password: YES) +#make sure plugin auth still available +select USER(),CURRENT_USER(); +USER() CURRENT_USER() +new_grant_user@localhost plug_dest@% +USE test_grant_db; +CREATE TABLE t1 (a INT); +DROP TABLE t1; +DROP USER new_grant_user; +# try re-create existing user via GRANT IDENTIFIED WITH +GRANT ALL PRIVILEGES ON test_grant_db.* TO plug +IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; +ERROR HY000: GRANT with IDENTIFIED WITH is illegal because the user plug already exists +GRANT ALL PRIVILEGES ON test_grant_db.* TO plug_dest +IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; +ERROR HY000: GRANT with IDENTIFIED WITH is illegal because the user plug_dest already exists +REVOKE SELECT on test_grant_db.* FROM joro +INDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'' at line 2 +REVOKE SELECT on test_grant_db.* FROM joro +INDENTIFIED BY 'plug_dest_passwd'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INDENTIFIED BY 'plug_dest_passwd'' at line 2 +REVOKE SELECT on test_grant_db.* FROM joro +INDENTIFIED BY PASSWORD 'plug_dest_passwd'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INDENTIFIED BY PASSWORD 'plug_dest_passwd'' at line 2 +DROP DATABASE test_grant_db; +## GRANT PROXY tests +CREATE USER grant_plug IDENTIFIED WITH 'test_plugin_server' +AS 'grant_plug_dest'; +CREATE USER grant_plug_dest IDENTIFIED BY 'grant_plug_dest_passwd'; +CREATE USER grant_plug_dest2 IDENTIFIED BY 'grant_plug_dest_passwd2'; +# ALL PRIVILEGES doesn't include PROXY +GRANT ALL PRIVILEGES ON *.* TO grant_plug; +ERROR 28000: Access denied for user 'grant_plug'@'localhost' (using password: YES) +GRANT ALL PRIVILEGES,PROXY ON grant_plug_dest TO grant_plug; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PROXY ON grant_plug_dest TO grant_plug' at line 1 +this should fail : can't combine PROXY +GRANT ALL SELECT,PROXY ON grant_plug_dest TO grant_plug; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT,PROXY ON grant_plug_dest TO grant_plug' at line 1 +# this should fail : no such grant +REVOKE PROXY ON grant_plug_dest FROM grant_plug; +ERROR 42000: There is no such grant defined for user 'grant_plug' on host '%' +in grant_plug_dest_con +## testing what an ordinary user can grant +this should fail : no rights to grant all +GRANT PROXY ON ''@'' TO grant_plug; +ERROR 28000: Access denied for user 'grant_plug_dest'@'localhost' +this should fail : not the same user +GRANT PROXY ON grant_plug TO grant_plug_dest; +ERROR 28000: Access denied for user 'grant_plug_dest'@'localhost' +this should fail : same user, but on a different host +GRANT PROXY ON grant_plug_dest TO grant_plug; +ERROR 28000: Access denied for user 'grant_plug_dest'@'localhost' +this should work : same user +GRANT PROXY ON grant_plug_dest@localhost TO grant_plug_dest2; +REVOKE PROXY ON grant_plug_dest@localhost FROM grant_plug_dest2; +this should work : same user +GRANT PROXY ON grant_plug_dest@localhost TO grant_plug WITH GRANT OPTION; +REVOKE PROXY ON grant_plug_dest@localhost FROM grant_plug; +this should fail : can't create users +GRANT PROXY ON grant_plug_dest@localhost TO grant_plug@localhost; +ERROR 42000: You are not allowed to create a user with GRANT +in default connection +# test what root can grant +should work : root has PROXY to all users +GRANT PROXY ON ''@'' TO grant_plug; +REVOKE PROXY ON ''@'' FROM grant_plug; +should work : root has PROXY to all users +GRANT PROXY ON ''@'' TO proxy_admin IDENTIFIED BY 'test' +WITH GRANT OPTION; +need USAGE : PROXY doesn't contain it. +GRANT USAGE on *.* TO proxy_admin; +in proxy_admin_con; +should work : proxy_admin has proxy to ''@'' +GRANT PROXY ON future_user TO grant_plug; +in default connection +SHOW GRANTS FOR grant_plug; +Grants for grant_plug@% +GRANT ALL PRIVILEGES ON *.* TO 'grant_plug'@'%' WITH GRANT OPTION +GRANT PROXY ON 'future_user'@'%' TO 'grant_plug'@'%' +REVOKE PROXY ON future_user FROM grant_plug; +SHOW GRANTS FOR grant_plug; +Grants for grant_plug@% +GRANT ALL PRIVILEGES ON *.* TO 'grant_plug'@'%' WITH GRANT OPTION +## testing drop user +CREATE USER test_drop@localhost; +GRANT PROXY ON future_user TO test_drop@localhost; +SHOW GRANTS FOR test_drop@localhost; +Grants for test_drop@localhost +GRANT USAGE ON *.* TO 'test_drop'@'localhost' +GRANT PROXY ON 'future_user'@'%' TO 'test_drop'@'localhost' +DROP USER test_drop@localhost; +SELECT * FROM mysql.proxy_priv WHERE Host = 'test_drop' AND User = 'localhost'; +Host User Proxied_Host Proxied_User With_Grant +DROP USER proxy_admin; +DROP USER grant_plug,grant_plug_dest,grant_plug_dest2; +## END GRANT PROXY tests +## cleanup +DROP USER plug; +DROP USER plug_dest; +## @@proxy_user tests +CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; +CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; +GRANT PROXY ON plug_dest TO plug; +SELECT USER(),CURRENT_USER(),@@LOCAL.proxy_user; +USER() CURRENT_USER() @@LOCAL.proxy_user +root@localhost root@localhost NULL +SELECT @@GLOBAL.proxy_user; +ERROR HY000: Variable 'proxy_user' is a SESSION variable +SELECT @@LOCAL.proxy_user; +@@LOCAL.proxy_user +NULL +SET GLOBAL proxy_user = 'test'; +ERROR HY000: Variable 'proxy_user' is a read only variable +SET LOCAL proxy_user = 'test'; +ERROR HY000: Variable 'proxy_user' is a read only variable +SELECT @@LOCAL.proxy_user; +@@LOCAL.proxy_user +NULL +# in connection plug_con +SELECT @@LOCAL.proxy_user; +@@LOCAL.proxy_user +'plug'@'%' +# in connection default +## cleanup +DROP USER plug; +DROP USER plug_dest; +## END @@proxy_user tests +## @@external_user tests +CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; +CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; +GRANT PROXY ON plug_dest TO plug; +SELECT USER(),CURRENT_USER(),@@LOCAL.external_user; +USER() CURRENT_USER() @@LOCAL.external_user +root@localhost root@localhost NULL +SELECT @@GLOBAL.external_user; +ERROR HY000: Variable 'external_user' is a SESSION variable +SELECT @@LOCAL.external_user; +@@LOCAL.external_user +NULL +SET GLOBAL external_user = 'test'; +ERROR HY000: Variable 'external_user' is a read only variable +SET LOCAL external_user = 'test'; +ERROR HY000: Variable 'external_user' is a read only variable +SELECT @@LOCAL.external_user; +@@LOCAL.external_user +NULL +# in connection plug_con +SELECT @@LOCAL.external_user; +@@LOCAL.external_user +'plug'@'%' +# in connection default +## cleanup +DROP USER plug; +DROP USER plug_dest; +## END @@external_user tests +# +# Bug #56798 : Wrong credentials assigned when using a proxy user. +# +GRANT ALL PRIVILEGES ON *.* TO power_user; +GRANT USAGE ON anonymous_db.* TO ''@'' + IDENTIFIED WITH 'test_plugin_server' AS 'power_user'; +GRANT PROXY ON power_user TO ''@''; +CREATE DATABASE confidential_db; +SELECT user(),current_user(),@@proxy_user; +user() current_user() @@proxy_user +test_login_user@localhost power_user@% ''@'' +DROP USER power_user; +DROP USER ''@''; +DROP DATABASE confidential_db; +# Test case #2 (crash with double grant proxy) +CREATE USER ''@'' IDENTIFIED WITH 'test_plugin_server' AS 'standard_user'; +CREATE USER standard_user; +CREATE DATABASE shared; +GRANT ALL PRIVILEGES ON shared.* TO standard_user; +GRANT PROXY ON standard_user TO ''@''; +#should not crash +GRANT PROXY ON standard_user TO ''@''; +DROP USER ''@''; +DROP USER standard_user; +DROP DATABASE shared; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 0e75ebd57ec..cf3594f32a8 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1194,13 +1194,13 @@ SET @aux= "SELECT COUNT(*) prepare my_stmt from @aux; execute my_stmt; COUNT(*) -40 +42 execute my_stmt; COUNT(*) -40 +42 execute my_stmt; COUNT(*) -40 +42 deallocate prepare my_stmt; drop procedure if exists p1| drop table if exists t1| diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result index e4170cc3a49..7da95416e29 100644 --- a/mysql-test/r/sp_notembedded.result +++ b/mysql-test/r/sp_notembedded.result @@ -9,9 +9,11 @@ end| call bug4902()| Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION call bug4902()| Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION drop procedure bug4902| drop procedure if exists bug4902_2| create procedure bug4902_2() @@ -206,9 +208,11 @@ create procedure 15298_2 () sql security definer show grants; call 15298_1(); Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION call 15298_2(); Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION drop user mysqltest_1@localhost; drop procedure 15298_1; drop procedure 15298_2; @@ -245,6 +249,8 @@ max_updates, max_connections, max_user_connections) VALUES('%', 'mysqltest_1', password(''), 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'N', 'N', 'N', 'N', 'Y', 'Y', 'N', 'N', 'Y', 'Y', 'N', 'N', 'N', 'N', 'N', 'Y', 'Y', 'N', '', '', '', '', '0', '0', '0', '0'); +Warnings: +Warning 1364 Field 'authentication_string' doesn't have a default value FLUSH PRIVILEGES; CREATE PROCEDURE p1(i INT) BEGIN END; DROP PROCEDURE p1; diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 679e50fcad9..e82cf229912 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -14,6 +14,7 @@ ndb_binlog_index plugin proc procs_priv +proxy_priv servers slow_log tables_priv @@ -119,6 +120,8 @@ user CREATE TABLE `user` ( `max_updates` int(11) unsigned NOT NULL DEFAULT '0', `max_connections` int(11) unsigned NOT NULL DEFAULT '0', `max_user_connections` int(11) unsigned NOT NULL DEFAULT '0', + `plugin` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `authentication_string` text COLLATE utf8_bin NOT NULL, PRIMARY KEY (`Host`,`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges' show create table func; diff --git a/mysql-test/suite/federated/federated.result b/mysql-test/suite/federated/federated.result index db4ffc38213..4cd7b416621 100644 --- a/mysql-test/suite/federated/federated.result +++ b/mysql-test/suite/federated/federated.result @@ -60,7 +60,7 @@ CREATE TABLE federated.t1 ( ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1'; SELECT * FROM federated.t1; -ERROR HY000: Unable to connect to foreign data source: Access denied for user 'user'@'localhost' (using password: YES) +ERROR HY000: Unable to connect to foreign data source: Access denied for user 'user'@'localhost' (using password: NO) DROP TABLE federated.t1; CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_03e.result b/mysql-test/suite/funcs_1/r/innodb_trig_03e.result index c963be41a35..9dabfcbef49 100644 --- a/mysql-test/suite/funcs_1/r/innodb_trig_03e.result +++ b/mysql-test/suite/funcs_1/r/innodb_trig_03e.result @@ -573,6 +573,7 @@ root@localhost show grants; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION drop trigger trg1_1; use priv_db; diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index 1ab2b3513f0..767f9e47f13 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -134,6 +134,11 @@ def mysql procs_priv Routine_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ def mysql procs_priv Routine_type 5 NULL NO enum 9 27 NULL NULL utf8 utf8_bin enum('FUNCTION','PROCEDURE') PRI select,insert,update,references def mysql procs_priv Timestamp 8 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL NULL NULL timestamp on update CURRENT_TIMESTAMP select,insert,update,references def mysql procs_priv User 3 NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references +def mysql proxy_priv Host 1 NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references +def mysql proxy_priv Proxied_Host 3 NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references +def mysql proxy_priv Proxied_User 4 NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references +def mysql proxy_priv User 2 NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references +def mysql proxy_priv With_Grant 5 0 NO tinyint NULL NULL 3 0 NULL NULL tinyint(1) select,insert,update,references def mysql servers Db 3 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references def mysql servers Host 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references def mysql servers Owner 9 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references @@ -178,6 +183,7 @@ def mysql time_zone_transition_type Time_zone_id 1 NULL NO int NULL NULL 10 0 NU def mysql time_zone_transition_type Transition_type_id 2 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned PRI select,insert,update,references def mysql user Alter_priv 17 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references def mysql user Alter_routine_priv 28 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references +def mysql user authentication_string 42 NULL NO text 65535 65535 NULL NULL utf8 utf8_bin text select,insert,update,references def mysql user Create_priv 8 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references def mysql user Create_routine_priv 27 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references def mysql user Create_tablespace_priv 32 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references @@ -199,6 +205,7 @@ def mysql user max_questions 37 0 NO int NULL NULL 10 0 NULL NULL int(11) unsign def mysql user max_updates 38 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references def mysql user max_user_connections 40 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references def mysql user Password 3 NO char 41 41 NULL NULL latin1 latin1_bin char(41) select,insert,update,references +def mysql user plugin 41 NO char 60 180 NULL NULL utf8 utf8_bin char(60) select,insert,update,references def mysql user Process_priv 12 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references def mysql user References_priv 15 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references def mysql user Reload_priv 10 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references @@ -418,6 +425,11 @@ NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp 3.0000 mysql procs_priv Grantor char 77 231 utf8 utf8_bin char(77) 3.0000 mysql procs_priv Proc_priv set 27 81 utf8 utf8_general_ci set('Execute','Alter Routine','Grant') NULL mysql procs_priv Timestamp timestamp NULL NULL NULL NULL timestamp +3.0000 mysql proxy_priv Host char 60 180 utf8 utf8_bin char(60) +3.0000 mysql proxy_priv User char 16 48 utf8 utf8_bin char(16) +3.0000 mysql proxy_priv Proxied_Host char 16 48 utf8 utf8_bin char(16) +3.0000 mysql proxy_priv Proxied_User char 60 180 utf8 utf8_bin char(60) +NULL mysql proxy_priv With_Grant tinyint NULL NULL NULL NULL tinyint(1) 3.0000 mysql servers Server_name char 64 192 utf8 utf8_general_ci char(64) 3.0000 mysql servers Host char 64 192 utf8 utf8_general_ci char(64) 3.0000 mysql servers Db char 64 192 utf8 utf8_general_ci char(64) @@ -500,3 +512,5 @@ NULL mysql user max_questions int NULL NULL NULL NULL int(11) unsigned NULL mysql user max_updates int NULL NULL NULL NULL int(11) unsigned NULL mysql user max_connections int NULL NULL NULL NULL int(11) unsigned NULL mysql user max_user_connections int NULL NULL NULL NULL int(11) unsigned +3.0000 mysql user plugin char 60 180 utf8 utf8_bin char(60) +1.0000 mysql user authentication_string text 65535 65535 utf8 utf8_bin text diff --git a/mysql-test/suite/funcs_1/r/is_key_column_usage.result b/mysql-test/suite/funcs_1/r/is_key_column_usage.result index a81452b7927..2e50a0c36bf 100644 --- a/mysql-test/suite/funcs_1/r/is_key_column_usage.result +++ b/mysql-test/suite/funcs_1/r/is_key_column_usage.result @@ -106,6 +106,10 @@ def mysql PRIMARY def mysql procs_priv Db def mysql PRIMARY def mysql procs_priv User def mysql PRIMARY def mysql procs_priv Routine_name def mysql PRIMARY def mysql procs_priv Routine_type +def mysql PRIMARY def mysql proxy_priv Host +def mysql PRIMARY def mysql proxy_priv User +def mysql PRIMARY def mysql proxy_priv Proxied_Host +def mysql PRIMARY def mysql proxy_priv Proxied_User def mysql PRIMARY def mysql servers Server_name def mysql PRIMARY def mysql tables_priv Host def mysql PRIMARY def mysql tables_priv Db diff --git a/mysql-test/suite/funcs_1/r/is_statistics.result b/mysql-test/suite/funcs_1/r/is_statistics.result index 873b328dc2d..0c43883789b 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics.result +++ b/mysql-test/suite/funcs_1/r/is_statistics.result @@ -118,6 +118,10 @@ def mysql procs_priv mysql PRIMARY def mysql procs_priv mysql PRIMARY def mysql procs_priv mysql PRIMARY def mysql procs_priv mysql Grantor +def mysql proxy_priv mysql PRIMARY +def mysql proxy_priv mysql PRIMARY +def mysql proxy_priv mysql PRIMARY +def mysql proxy_priv mysql PRIMARY def mysql servers mysql PRIMARY def mysql tables_priv mysql PRIMARY def mysql tables_priv mysql PRIMARY diff --git a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result index a1fa0cac9f2..584bbeb7af5 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result @@ -40,6 +40,10 @@ def mysql procs_priv 0 mysql PRIMARY 2 Db A #CARD# NULL NULL BTREE def mysql procs_priv 0 mysql PRIMARY 3 User A #CARD# NULL NULL BTREE def mysql procs_priv 0 mysql PRIMARY 4 Routine_name A #CARD# NULL NULL BTREE def mysql procs_priv 0 mysql PRIMARY 5 Routine_type A #CARD# NULL NULL BTREE +def mysql proxy_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE +def mysql proxy_priv 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE +def mysql proxy_priv 0 mysql PRIMARY 3 Proxied_Host A #CARD# NULL NULL BTREE +def mysql proxy_priv 0 mysql PRIMARY 4 Proxied_User A #CARD# NULL NULL BTREE def mysql servers 0 mysql PRIMARY 1 Server_name A #CARD# NULL NULL BTREE def mysql tables_priv 1 mysql Grantor 1 Grantor A #CARD# NULL NULL BTREE def mysql tables_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints.result b/mysql-test/suite/funcs_1/r/is_table_constraints.result index 7f1c83a8ea5..d4d2c38c9ba 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints.result @@ -73,6 +73,7 @@ def mysql PRIMARY mysql ndb_binlog_index def mysql PRIMARY mysql plugin def mysql PRIMARY mysql proc def mysql PRIMARY mysql procs_priv +def mysql PRIMARY mysql proxy_priv def mysql PRIMARY mysql servers def mysql PRIMARY mysql tables_priv def mysql PRIMARY mysql time_zone diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result index 8b7ac6994c1..38e9c9034c9 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result @@ -23,6 +23,7 @@ def mysql PRIMARY mysql ndb_binlog_index PRIMARY KEY def mysql PRIMARY mysql plugin PRIMARY KEY def mysql PRIMARY mysql proc PRIMARY KEY def mysql PRIMARY mysql procs_priv PRIMARY KEY +def mysql PRIMARY mysql proxy_priv PRIMARY KEY def mysql PRIMARY mysql servers PRIMARY KEY def mysql PRIMARY mysql tables_priv PRIMARY KEY def mysql PRIMARY mysql time_zone PRIMARY KEY diff --git a/mysql-test/suite/funcs_1/r/is_tables_mysql.result b/mysql-test/suite/funcs_1/r/is_tables_mysql.result index 0945401ba43..ae512327807 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_tables_mysql.result @@ -336,6 +336,29 @@ user_comment Procedure privileges Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql +TABLE_NAME proxy_priv +TABLE_TYPE BASE TABLE +ENGINE MyISAM +VERSION 10 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_bin +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment User proxy privileges +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA mysql TABLE_NAME servers TABLE_TYPE BASE TABLE ENGINE MyISAM diff --git a/mysql-test/suite/funcs_1/r/is_user_privileges.result b/mysql-test/suite/funcs_1/r/is_user_privileges.result index 8f68f8c802d..1ec1ffc4ce1 100644 --- a/mysql-test/suite/funcs_1/r/is_user_privileges.result +++ b/mysql-test/suite/funcs_1/r/is_user_privileges.result @@ -69,46 +69,436 @@ GRANT UPDATE ON *.* TO 'testuser2'@'localhost'; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' ORDER BY grantee, table_catalog, privilege_type; -GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE -'testuser1'@'localhost' def USAGE NO -'testuser2'@'localhost' def INSERT NO -'testuser2'@'localhost' def UPDATE NO -'testuser3'@'localhost' def USAGE NO +GRANTEE 'testuser1'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE USAGE +IS_GRANTABLE NO +GRANTEE 'testuser2'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE INSERT +IS_GRANTABLE NO +GRANTEE 'testuser2'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE UPDATE +IS_GRANTABLE NO +GRANTEE 'testuser3'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE USAGE +IS_GRANTABLE NO SELECT * FROM mysql.user WHERE user LIKE 'testuser%' ORDER BY host, user; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections -localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 -localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 -localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 +Host localhost +User testuser1 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string +Host localhost +User testuser2 +Password +Select_priv N +Insert_priv Y +Update_priv Y +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string +Host localhost +User testuser3 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string # # Add GRANT OPTION db_datadict.* to testuser1; GRANT UPDATE ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' ORDER BY grantee, table_catalog, privilege_type; -GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE -'testuser1'@'localhost' def USAGE NO -'testuser2'@'localhost' def INSERT NO -'testuser2'@'localhost' def UPDATE NO -'testuser3'@'localhost' def USAGE NO +GRANTEE 'testuser1'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE USAGE +IS_GRANTABLE NO +GRANTEE 'testuser2'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE INSERT +IS_GRANTABLE NO +GRANTEE 'testuser2'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE UPDATE +IS_GRANTABLE NO +GRANTEE 'testuser3'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE USAGE +IS_GRANTABLE NO SELECT * FROM mysql.user WHERE user LIKE 'testuser%' ORDER BY host, user; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections -localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 -localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 -localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 +Host localhost +User testuser1 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string +Host localhost +User testuser2 +Password +Select_priv N +Insert_priv Y +Update_priv Y +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string +Host localhost +User testuser3 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string # Establish connection testuser1 (user=testuser1) SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' ORDER BY grantee, table_catalog, privilege_type; -GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE -'testuser1'@'localhost' def USAGE NO +GRANTEE 'testuser1'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE USAGE +IS_GRANTABLE NO SELECT * FROM mysql.user WHERE user LIKE 'testuser%' ORDER BY host, user; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections -localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 -localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 -localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 +Host localhost +User testuser1 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string +Host localhost +User testuser2 +Password +Select_priv N +Insert_priv Y +Update_priv Y +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string +Host localhost +User testuser3 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' @@ -123,46 +513,436 @@ GRANT SELECT ON *.* TO 'testuser1'@'localhost'; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' ORDER BY grantee, table_catalog, privilege_type; -GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE -'testuser1'@'localhost' def SELECT NO -'testuser2'@'localhost' def INSERT NO -'testuser2'@'localhost' def UPDATE NO -'testuser3'@'localhost' def USAGE NO +GRANTEE 'testuser1'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE SELECT +IS_GRANTABLE NO +GRANTEE 'testuser2'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE INSERT +IS_GRANTABLE NO +GRANTEE 'testuser2'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE UPDATE +IS_GRANTABLE NO +GRANTEE 'testuser3'@'localhost' +TABLE_CATALOG def +PRIVILEGE_TYPE USAGE +IS_GRANTABLE NO SELECT * FROM mysql.user WHERE user LIKE 'testuser%' ORDER BY host, user; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections -localhost testuser1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 -localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 -localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 +Host localhost +User testuser1 +Password +Select_priv Y +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string +Host localhost +User testuser2 +Password +Select_priv N +Insert_priv Y +Update_priv Y +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string +Host localhost +User testuser3 +Password +Select_priv N +Insert_priv N +Update_priv N +Delete_priv N +Create_priv N +Drop_priv N +Reload_priv N +Shutdown_priv N +Process_priv N +File_priv N +Grant_priv N +References_priv N +Index_priv N +Alter_priv N +Show_db_priv N +Super_priv N +Create_tmp_table_priv N +Lock_tables_priv N +Execute_priv N +Repl_slave_priv N +Repl_client_priv N +Create_view_priv N +Show_view_priv N +Create_routine_priv N +Alter_routine_priv N +Create_user_priv N +Event_priv N +Trigger_priv N +Create_tablespace_priv N +ssl_type +ssl_cipher +x509_issuer +x509_subject +max_questions 0 +max_updates 0 +max_connections 0 +max_user_connections 0 +plugin +authentication_string GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION; # # Here is shown correctly for testuser1; +--vertical_results eval $my_select1; eval $my_select2; +--horizontal_results GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION; --echo # --echo # Here