diff --git a/.bzrignore b/.bzrignore index 6fd772740b1..85fc5d0a607 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1931,3 +1931,6 @@ client/rpl_filter.cc client/rpl_filter.h client/sql_list.cc client/sql_list.h +libmysqld/client_plugin.c +sql/client_plugin.c +*.dgcov diff --git a/Makefile.am b/Makefile.am index b59e25b8234..78a023df225 100644 --- a/Makefile.am +++ b/Makefile.am @@ -271,12 +271,13 @@ test-full-qa: # after which TEST_PREPROCESSOR_HEADER will be used. # -API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \ - $(top_srcdir)/include/mysql.h +API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql.h \ + $(top_srcdir)/include/mysql/client_plugin.h \ + $(top_srcdir)/include/mysql/plugin_auth.h -TEST_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \ - $(top_srcdir)/sql/mysql_priv.h \ - $(top_srcdir)/include/mysql.h +TEST_PREPROCESSOR_HEADER = $(API_PREPROCESSOR_HEADER) \ + $(top_srcdir)/sql/mysql_priv.h + # # Rules for checking that the abi/api has not changed. diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index e96437d40d0..99d67acbc5b 100755 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -83,3 +83,5 @@ IF(EMBED_MANIFESTS) MYSQL_EMBED_MANIFEST("echo" "asInvoker") ENDIF(EMBED_MANIFESTS) +ADD_DEFINITIONS(-DHAVE_DLOPEN) + diff --git a/client/Makefile.am b/client/Makefile.am index ee56662da01..bfca0ba4bb2 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -100,8 +100,8 @@ mysql_upgrade_SOURCES= mysql_upgrade.c \ # Fix for mit-threads DEFS = -DMYSQL_CLIENT_NO_THREADS \ - -DDEFAULT_MYSQL_HOME="\"$(prefix)\"" \ - -DMYSQL_DATADIR="\"$(localstatedir)\"" + -DDEFAULT_MYSQL_HOME='"$(prefix)"' \ + -DMYSQL_DATADIR='"$(localstatedir)"' sql_src=log_event.h mysql_priv.h rpl_constants.h \ rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \ diff --git a/client/client_priv.h b/client/client_priv.h index e639129cae5..f6bde7a594c 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -93,5 +93,7 @@ enum options_client OPT_FIRST_SLAVE, OPT_ALL, OPT_REWRITE_DB, - OPT_MAX_CLIENT_OPTION + OPT_PLUGIN_DIR, + OPT_DEFAULT_PLUGIN, + OPT_MAX_CLIENT_OPTION /* should be always the last */ }; diff --git a/client/mysql.cc b/client/mysql.cc index 6203e51d73e..08e53df75fe 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -167,6 +167,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[] = { "&", "&", "<", "<", @@ -1542,6 +1543,13 @@ static struct my_option my_long_options[] = {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.", (uchar**) &show_warnings, (uchar**) &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} }; @@ -4238,6 +4246,56 @@ char *get_arg(char *line, my_bool get_next_arg) } +/** + An example of mysql_authentication_dialog_ask callback. + + The C function with the name "mysql_authentication_dialog_ask", if exists, + will be used by the "dialog" client authentication plugin when user + input is needed. This function should be of mysql_authentication_dialog_ask_t + type. If the function does not exists, a built-in implementation will be + used. + + @param mysql mysql + @param type type of the input + 1 - normal string input + 2 - password string + @param prompt prompt + @param buf a buffer to store the use input + @param buf_len the length of the buffer + + @retval a pointer to the user input string. + It may be equal to 'buf' or to 'mysql->password'. + In all other cases it is assumed to be an allocated + string, and the "dialog" plugin will free() it. +*/ + +extern "C" char *mysql_authentication_dialog_ask(MYSQL *mysql, int type, + const char *prompt, + char *buf, int buf_len) +{ + char *s=buf; + + fputs("[mariadb] ", stdout); + fputs(prompt, stdout); + fputs(" ", stdout); + + if (type == 2) /* password */ + { + s= get_tty_password(""); + strnmov(buf, s, buf_len); + buf[buf_len-1]= 0; + my_free(s, MYF(0)); + } + else + { + fgets(buf, buf_len-1, stdin); + if (buf[0] && (s= strend(buf))[-1] == '\n') + s[-1]= 0; + } + + return buf; +} + static int sql_real_connect(char *host,char *database,char *user,char *password, uint silent) @@ -4283,6 +4341,13 @@ sql_real_connect(char *host,char *database,char *user,char *password, } if (default_charset_used) 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)) diff --git a/configure.in b/configure.in index bad6b94cfe7..412d11e2c7c 100644 --- a/configure.in +++ b/configure.in @@ -1605,9 +1605,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 d5f68f25026..bb364586ac1 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -24,6 +24,8 @@ pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \ my_xml.h mysql_embed.h mysql/services.h \ mysql/service_my_snprintf.h mysql/service_thd_alloc.h \ my_pthread.h my_no_pthread.h \ + mysql/plugin_auth.h mysql/client_plugin.h \ + mysql/plugin_auth_common.h \ decimal.h errmsg.h my_global.h my_net.h \ my_getopt.h sslopt-longopts.h my_dir.h \ sslopt-vars.h sslopt-case.h sql_common.h keycache.h \ @@ -42,7 +44,7 @@ noinst_HEADERS = config-win.h config-netware.h lf.h my_bit.h \ atomic/rwlock.h atomic/x86-gcc.h atomic/generic-msvc.h \ atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h \ wqueue.h waiting_threads.h -EXTRA_DIST = mysql.h.pp mysql/plugin.h.pp +EXTRA_DIST = mysql.h.pp mysql/plugin_auth.h.pp mysql/client_plugin.h.pp # Remove built files and the symlinked directories CLEANFILES = $(BUILT_SOURCES) readline openssl diff --git a/include/errmsg.h b/include/errmsg.h index a6d8c770de8..94209f35a61 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -97,6 +97,7 @@ extern const char *client_errors[]; /* Error messages */ #define CR_SERVER_LOST_EXTENDED 2055 #define CR_STMT_CLOSED 2056 #define CR_NEW_STMT_METADATA 2057 -#define CR_ERROR_LAST /*Copy last error nr:*/ 2057 +#define CR_AUTH_PLUGIN_CANNOT_LOAD 2058 +#define CR_ERROR_LAST /*Copy last error nr:*/ 2058 /* Add error numbers before CR_ERROR_LAST and change it accordingly. */ diff --git a/include/my_global.h b/include/my_global.h index 6c11a4b461a..4b96f79ccc8 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -578,6 +578,14 @@ int __void__; #define IF_VALGRIND(A,B) (B) #endif +#ifdef _WIN32 +#define SO_EXT ".dll" +#elif defined(__APPLE__) +#define SO_EXT ".dylib" +#else +#define SO_EXT ".so" +#endif + /* Suppress uninitialized variable warning without generating code. @@ -1522,10 +1530,12 @@ do { doubleget_union _tmp; \ #endif #ifndef HAVE_DLERROR -#define dlerror() "" +#define dlerror() "No support for dynamic loading (static build?)" +#define dlopen(A,B) 0 +#define dlsym(A,B) 0 +#define dlclose(A) 0 #endif - #ifndef __NETWARE__ /* * Include standard definitions of operator new and delete. diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h index 511fac407d5..ca3fbe2d13b 100644 --- a/include/my_no_pthread.h +++ b/include/my_no_pthread.h @@ -46,6 +46,7 @@ #define rw_wrlock(A) #define rw_unlock(A) #define rwlock_destroy(A) +#define safe_mutex_assert_owner(mp) typedef int my_pthread_once_t; #define MY_PTHREAD_ONCE_INIT 0 diff --git a/include/my_sys.h b/include/my_sys.h index 6ab6a41ed44..742f1c0b61e 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -210,7 +210,7 @@ extern void my_large_free(uchar * ptr, myf my_flags); #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,MYF(MY_WME)) #endif /* HAVE_ALLOCA */ @@ -870,6 +870,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 929842eec45..52475dbc0dd 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; @@ -217,7 +223,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 @@ -752,38 +758,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); -#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); @@ -846,18 +820,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 __NETWARE__ #pragma pack(pop) /* restore alignment */ #endif diff --git a/include/mysql.h.pp b/include/mysql.h.pp index e2d66bd3e35..88a2dce1555 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -128,13 +128,13 @@ void create_random_string(char *to, unsigned int length, 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); @@ -258,8 +258,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; @@ -289,7 +290,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 { @@ -601,34 +602,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); - 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..5e9a337dfc6 --- /dev/null +++ b/include/mysql/client_plugin.h @@ -0,0 +1,164 @@ +#ifndef MYSQL_CLIENT_PLUGIN_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 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) \ + 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]; \ + int (*init)(char *, size_t, int, va_list); \ + int (*deinit)(); + +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); +}; + +/** + type of the mysql_authentication_dialog_ask function + + @param mysql mysql + @param type type of the input + 1 - ordinary string input + 2 - password string + @param prompt prompt + @param buf a buffer to store the use input + @param buf_len the length of the buffer + + @retval a pointer to the user input string. + It may be equal to 'buf' or to 'mysql->password'. + In all other cases it is assumed to be an allocated + string, and the "dialog" plugin will free() it. +*/ +typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql, + int type, const char *prompt, char *buf, int buf_len); +/******** 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); + +#endif + diff --git a/include/mysql/client_plugin.h.pp b/include/mysql/client_plugin.h.pp new file mode 100644 index 00000000000..20d353422dd --- /dev/null +++ b/include/mysql/client_plugin.h.pp @@ -0,0 +1,41 @@ +#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]; int (*init)(char *, size_t, int, va_list); int (*deinit)(); +}; +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]; int (*init)(char *, size_t, int, va_list); int (*deinit)(); + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); +}; +typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql, + int type, const char *prompt, char *buf, int buf_len); +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); diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 5ac0472fc5f..83f6f163e6e 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -67,7 +67,10 @@ typedef struct st_mysql_xid MYSQL_XID; #define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */ #define MYSQL_DAEMON_PLUGIN 3 /* The daemon/raw plugin type */ #define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */ -#define MYSQL_MAX_PLUGIN_TYPE_NUM 5 /* The number of plugin types */ +#define MYSQL_AUDIT_PLUGIN 5 /* The Audit plugin type */ +#define MYSQL_REPLICATION_PLUGIN 6 /* The replication plugin type */ +#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..2b84a6c73af --- /dev/null +++ b/include/mysql/plugin_auth.h @@ -0,0 +1,83 @@ +#ifndef MYSQL_PLUGIN_AUTH_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 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 + +/** + 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. + */ + const char *user_name; + /** + A corresponding column value from the mysql.user table for the + matching account name + */ + const char *auth_string; + + /** + 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]; + /** + This only affects the "Authentication failed. Password used: %s" + error message. If set, %s will be YES, otherwise - NO. + Set it as appropriate or ignore at will. + */ + int password_used; +} 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.h.pp b/include/mysql/plugin_auth.h.pp similarity index 85% rename from include/mysql/plugin.h.pp rename to include/mysql/plugin_auth.h.pp index c5c520dfe51..9ab379a1f0f 100644 --- a/include/mysql/plugin.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -161,3 +162,32 @@ 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); +#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 +{ + const char *user_name; + const char *auth_string; + char authenticated_as[48 +1]; + int password_used; +} 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..b71591d6eb6 --- /dev/null +++ b/include/mysql/plugin_auth_common.h @@ -0,0 +1,105 @@ +#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 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 3a93da3e9d2..093807a65cb 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -152,9 +152,17 @@ enum enum_server_command #define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */ #define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */ +#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 | \ @@ -175,7 +183,8 @@ enum enum_server_command CLIENT_MULTI_STATEMENTS | \ CLIENT_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 @@ -488,14 +497,14 @@ void create_random_string(char *to, unsigned int length, 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/sql_common.h b/include/sql_common.h index 9e43d076ba9..8a687baa285 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -1,3 +1,4 @@ +#ifndef SQL_COMMON_INCLUDED /* Copyright (C) 2003-2004, 2006 MySQL AB This program is free software; you can redistribute it and/or modify @@ -13,14 +14,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); + 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, @@ -42,9 +89,23 @@ 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, + 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 #define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41) +#endif diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index b033aeb4665..e9adfaf767e 100755 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -98,7 +98,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c ../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c ../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c - ../mysys/my_getsystime.c ../mysys/my_sync.c ${LIB_SOURCES}) + ../mysys/my_getsystime.c ../mysys/my_sync.c ../sql-common/client_plugin.c ${LIB_SOURCES}) # Need to set USE_TLS for building the DLL, since __declspec(thread) # approach to thread local storage does not work properly in DLLs. @@ -125,6 +125,7 @@ IF(WIN32) ENDIF(WIN32) ADD_DEPENDENCIES(libmysql GenError) TARGET_LINK_LIBRARIES(libmysql wsock32) +ADD_DEFINITIONS(-DHAVE_DLOPEN) IF(EMBED_MANIFESTS) MYSQL_EMBED_MANIFEST("myTest" "asInvoker") diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index c5e1acab2d1..34e8f2e3b92 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) @@ -71,26 +72,27 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ my_getopt.lo my_gethostbyname.lo my_port.lo \ my_rename.lo my_chsize.lo my_sync.lo my_getsystime.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)\"" $(target_defs) + -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \ + -DSHAREDIR='"$(MYSQLSHAREdir)"' $(target_defs) if HAVE_YASSL yassl_las = $(top_builddir)/extra/yassl/src/libyassl.la \ diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index f87e625771f..b486c101327 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -18,7 +18,8 @@ extern char * mysql_unix_port; #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \ CLIENT_TRANSACTIONS | \ - CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION) + CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \ + CLIENT_PLUGIN_AUTH) sig_handler my_pipe_sig_handler(int sig); void read_user_name(char *name); @@ -57,7 +58,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 95ee6862aa8..fc77db151aa 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -85,6 +85,7 @@ 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", + "Authentication plugin '%s' cannot be loaded: %s", "" }; @@ -151,6 +152,7 @@ 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", + "Authentication plugin '%s' cannot be loaded: %s", "" }; @@ -215,6 +217,7 @@ 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", + "Authentication plugin '%s' cannot be loaded: %s", "" }; #endif diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 77068edd7ec..22ebe411513 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -126,12 +126,13 @@ 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) { mysql_port = MYSQL_PORT; #ifndef MSDOS { - struct servent *serv_ptr; char *env; /* @@ -145,6 +146,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)), */ #if MYSQL_PORT_DEFAULT == 0 + struct servent *serv_ptr; if ((serv_ptr = getservbyname("mysql", "tcp"))) mysql_port = (uint) ntohs((ushort) serv_ptr->s_port); #endif @@ -198,6 +200,8 @@ void STDCALL mysql_server_end() if (!mysql_client_init) return; + mysql_client_plugin_deinit(); + #ifdef EMBEDDED_LIBRARY end_embedded_server(); #endif @@ -662,44 +666,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"); @@ -713,49 +687,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 @@ -765,18 +701,21 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, if (rc == 0) { /* Free old connect information */ - my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); + my_free(saved_user, MYF(MY_ALLOW_ZERO_PTR)); + my_free(saved_passwd, MYF(MY_ALLOW_ZERO_PTR)); + my_free(saved_db, MYF(MY_ALLOW_ZERO_PTR)); /* 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/libmysqld/Makefile.am b/libmysqld/Makefile.am index f5da13b145b..c2cdba613e1 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -25,10 +25,10 @@ pkgplugindir = $(pkglibdir)/plugin EXTRA_DIST = libmysqld.def CMakeLists.txt DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \ - -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \ - -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \ - -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \ - -DPLUGINDIR="\"$(pkgplugindir)\"" + -DDEFAULT_MYSQL_HOME='"$(MYSQLBASEdir)"' \ + -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \ + -DSHAREDIR='"$(MYSQLSHAREdir)"' \ + -DPLUGINDIR='"$(pkgplugindir)"' INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \ -I$(top_builddir)/sql -I$(top_srcdir)/sql \ -I$(top_srcdir)/sql/examples \ @@ -41,7 +41,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 7de1ecd6ef3..5521e024f8f 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; @@ -413,11 +412,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= @@ -428,6 +426,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, @@ -436,7 +435,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 }; @@ -584,6 +582,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); } @@ -648,14 +647,19 @@ 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->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); net_end_statement(thd); emb_read_query_result(mysql); return result; @@ -664,14 +668,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)); @@ -682,36 +687,44 @@ 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; - return 0; -err: + 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)) { - NET *net= &mysql->net; - 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); + x_free(thd->security_ctx->user); + goto err; } - return result; + return 0; + +err: + 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 0c20b35236d..afb91b7ff81 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -18,7 +18,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 @@ -81,9 +81,9 @@ static my_bool is_NT(void) ** Shut down connection **************************************************************************/ -static void end_server(MYSQL *mysql) +void embedded_end_server(MYSQL *mysql) { - DBUG_ENTER("end_server"); + DBUG_ENTER("embedded_end_server"); free_old_query(mysql); DBUG_VOID_RETURN; } @@ -169,7 +169,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; @@ -216,7 +220,7 @@ error: { /* Free alloced memory */ my_bool free_me=mysql->free_me; - end_server(mysql); + embedded_end_server(mysql); mysql->free_me=0; mysql_close(mysql); mysql->free_me=free_me; diff --git a/mysql-test/r/change_user.result b/mysql-test/r/change_user.result index 679e656c381..3c1e2b6f262 100644 --- a/mysql-test/r/change_user.result +++ b/mysql-test/r/change_user.result @@ -1,3 +1,36 @@ +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 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/grant.result b/mysql-test/r/grant.result index 8a3312da05e..61cd498a4fd 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -13,8 +13,8 @@ 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 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 SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0 +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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string +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 SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0 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 +44,15 @@ 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 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 10 0 0 0 +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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string +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 10 0 0 0 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 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 10 20 30 0 +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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string +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 10 20 30 0 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 +164,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 'auth_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; diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 12269f0cb1c..ee3fe1540b9 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -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 'auth_string' doesn't have a default value create user mysqltest_A@'%'; rename user mysqltest_B@'%' to mysqltest_C@'%'; drop user mysqltest_C@'%'; @@ -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 'auth_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/ps.result b/mysql-test/r/ps.result index 1e67bfa7d37..38fa7d84527 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(*) -39 +41 execute my_stmt; COUNT(*) -39 +41 execute my_stmt; COUNT(*) -39 +41 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 af73d637590..b21cac8af90 100644 --- a/mysql-test/r/sp_notembedded.result +++ b/mysql-test/r/sp_notembedded.result @@ -191,6 +191,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 'auth_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 17fd95ab1c8..91a7f242ce0 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -118,6 +118,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) CHARACTER SET latin1 NOT NULL DEFAULT '', + `auth_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/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index 98eeacdb74c..e2d9fc104d8 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -178,6 +178,7 @@ NULL mysql time_zone_transition_type Time_zone_id 1 NULL NO int NULL NULL 10 0 N NULL 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 NULL mysql user Alter_priv 17 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NULL mysql user Alter_routine_priv 28 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references +NULL mysql user auth_string 41 NULL NO text 65535 65535 NULL NULL utf8 utf8_bin text select,insert,update,references NULL mysql user Create_priv 8 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NULL mysql user Create_routine_priv 27 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NULL mysql user Create_tmp_table_priv 20 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references @@ -198,6 +199,7 @@ NULL mysql user max_questions 36 0 NO int NULL NULL 10 0 NULL NULL int(11) unsig NULL mysql user max_updates 37 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references NULL mysql user max_user_connections 39 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references NULL mysql user Password 3 NO char 41 41 NULL NULL latin1 latin1_bin char(41) select,insert,update,references +NULL mysql user plugin 40 NO char 60 60 NULL NULL latin1 latin1_swedish_ci char(60) select,insert,update,references NULL mysql user Process_priv 12 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NULL mysql user References_priv 15 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NULL mysql user Reload_priv 10 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references @@ -233,6 +235,7 @@ COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME 1.0000 char latin1 latin1_bin 1.0000 char latin1 latin1_swedish_ci 1.0000 varchar latin1 latin1_swedish_ci +1.0000 text utf8 utf8_bin 1.0000 mediumtext utf8 utf8_general_ci 1.0000 text utf8 utf8_general_ci SELECT DISTINCT @@ -497,3 +500,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 +1.0000 mysql user plugin char 60 60 latin1 latin1_swedish_ci char(60) +1.0000 mysql user auth_string text 65535 65535 utf8 utf8_bin text 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 03865f59c2c..b9a19f98d65 100644 --- a/mysql-test/suite/funcs_1/r/is_user_privileges.result +++ b/mysql-test/suite/funcs_1/r/is_user_privileges.result @@ -76,10 +76,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE 'testuser3'@'localhost' NULL USAGE 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 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 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 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 0 0 0 0 +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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string +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 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 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 0 0 0 0 # # Add GRANT OPTION db_datadict.* to testuser1; GRANT UPDATE ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION; @@ -93,10 +93,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE 'testuser3'@'localhost' NULL USAGE 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 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 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 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 0 0 0 0 +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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string +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 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 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 0 0 0 0 # Establish connection testuser1 (user=testuser1) SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -105,10 +105,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE 'testuser1'@'localhost' NULL USAGE 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 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 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 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 0 0 0 0 +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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string +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 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 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 0 0 0 0 SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' @@ -130,10 +130,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE 'testuser3'@'localhost' NULL USAGE 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 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 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 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 0 0 0 0 +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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string +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 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 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 0 0 0 0 GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION; # # Here