From c94ec9fc6721f50fadb1d86d1d0bf004b39c69d2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Jan 2019 15:56:25 +0100 Subject: [PATCH] MDEV-17950 SHOW GRANTS FOR does not work for a user identified with non-existing plugin Revert the side effect of 7c40996cc866. Do not convert password hash to its binary representation when a user entry is loaded. Do it lazily on the first authenticatation attempt. As a collateral - force all authentication plugins to follow the protocol and read_packet at least once before accessing info->username (username is not available before first client handshake packet is read). Fix PAM and GSSAPI plugins to behave. --- mysql-test/main/failed_auth_unixsocket.result | 9 +- mysql-test/main/failed_auth_unixsocket.test | 4 +- mysql-test/main/grant5.result | 22 +-- mysql-test/main/grant5.test | 8 - mysql-test/main/plugin_auth_qa_1.result | 4 +- mysql-test/main/plugin_auth_qa_1.test | 2 +- plugin/auth_gssapi/gssapi_server.cc | 20 ++- plugin/auth_gssapi/server_plugin.cc | 32 +--- plugin/auth_gssapi/server_plugin.h | 2 +- plugin/auth_gssapi/sspi_server.cc | 17 +- plugin/auth_pam/auth_pam.c | 32 ++-- plugin/auth_pam/auth_pam_v1.c | 20 ++- sql/sql_acl.cc | 159 ++++++++++-------- 13 files changed, 186 insertions(+), 145 deletions(-) diff --git a/mysql-test/main/failed_auth_unixsocket.result b/mysql-test/main/failed_auth_unixsocket.result index b2081c9ba84..690476cd753 100644 --- a/mysql-test/main/failed_auth_unixsocket.result +++ b/mysql-test/main/failed_auth_unixsocket.result @@ -1,13 +1,8 @@ update mysql.global_priv set priv=json_insert(priv, '$.plugin', 'unix_socket'); flush privileges; -Warnings: -Warning 1524 Plugin 'unix_socket' is not loaded -Warning 1524 Plugin 'unix_socket' is not loaded -Warning 1524 Plugin 'unix_socket' is not loaded -Warning 1524 Plugin 'unix_socket' is not loaded connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); -ERROR 28000: Access denied for user 'USER'@'localhost' (using password: NO) -ERROR 28000: Access denied for user 'USER'@'localhost' (using password: NO) +ERROR HY000: Plugin 'unix_socket' is not loaded +ERROR HY000: Plugin 'unix_socket' is not loaded install plugin unix_socket soname 'auth_socket.so'; flush privileges; connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); diff --git a/mysql-test/main/failed_auth_unixsocket.test b/mysql-test/main/failed_auth_unixsocket.test index 179e561e9ed..a7ae7d64a6b 100644 --- a/mysql-test/main/failed_auth_unixsocket.test +++ b/mysql-test/main/failed_auth_unixsocket.test @@ -14,12 +14,12 @@ let $replace=Access denied for user '$USER'; --echo connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); --replace_result $replace "Access denied for user 'USER'" --disable_query_log ---error ER_ACCESS_DENIED_ERROR +--error ER_PLUGIN_IS_NOT_LOADED connect (fail,localhost,$USER); --enable_query_log --replace_result $replace "Access denied for user 'USER'" ---error ER_ACCESS_DENIED_ERROR +--error ER_PLUGIN_IS_NOT_LOADED change_user $USER; eval install plugin unix_socket soname '$AUTH_SOCKET_SO'; diff --git a/mysql-test/main/grant5.result b/mysql-test/main/grant5.result index 5bf7b2d1934..c35e8201582 100644 --- a/mysql-test/main/grant5.result +++ b/mysql-test/main/grant5.result @@ -59,12 +59,9 @@ update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad') where user='u5'; update mysql.global_priv set priv=json_set(priv, '$.plugin', 'nonexistent') where user='u8'; flush privileges; -Warnings: -Error 1372 Password hash should be a 41-digit hexadecimal number -Error 1372 Password hash should be a 16-digit hexadecimal number -Warning 1524 Plugin 'nonexistent' is not loaded show create user u1@h; -ERROR 28000: Can't find any matching row in the user table +CREATE USER for u1@h +CREATE USER 'u1'@'h' IDENTIFIED BY PASSWORD 'bad' show create user u2@h; CREATE USER for u2@h CREATE USER 'u2'@'h' IDENTIFIED BY PASSWORD '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD' @@ -75,7 +72,8 @@ show create user u4@h; CREATE USER for u4@h CREATE USER 'u4'@'h' IDENTIFIED BY PASSWORD '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD' show create user u5@h; -ERROR 28000: Can't find any matching row in the user table +CREATE USER for u5@h +CREATE USER 'u5'@'h' IDENTIFIED BY PASSWORD 'bad' show create user u6@h; CREATE USER for u6@h CREATE USER 'u6'@'h' IDENTIFIED BY PASSWORD '78a302dd267f6044' @@ -83,26 +81,24 @@ show create user u7@h; CREATE USER for u7@h CREATE USER 'u7'@'h' IDENTIFIED BY PASSWORD '78a302dd267f6044' show create user u8@h; -ERROR 28000: Can't find any matching row in the user table +CREATE USER for u8@h +CREATE USER 'u8'@'h' IDENTIFIED VIA nonexistent USING '78a302dd267f6044' grant select on *.* to u1@h; -ERROR 28000: Can't find any matching row in the user table grant select on *.* to u2@h; grant select on *.* to u3@h; grant select on *.* to u4@h; grant select on *.* to u5@h; -ERROR 28000: Can't find any matching row in the user table grant select on *.* to u6@h; grant select on *.* to u7@h; grant select on *.* to u8@h; -ERROR 28000: Can't find any matching row in the user table select user,select_priv,plugin,authentication_string from mysql.user where user like 'u_'; User Select_priv plugin authentication_string -u1 N mysql_native_password bad +u1 Y mysql_native_password bad u2 Y mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD u3 Y mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD u4 Y mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD -u5 N mysql_old_password bad +u5 Y mysql_old_password bad u6 Y mysql_old_password 78a302dd267f6044 u7 Y mysql_old_password 78a302dd267f6044 -u8 N nonexistent 78a302dd267f6044 +u8 Y nonexistent 78a302dd267f6044 drop user u1@h, u2@h, u3@h, u4@h, u5@h, u6@h, u7@h, u8@h; diff --git a/mysql-test/main/grant5.test b/mysql-test/main/grant5.test index daf972dbe4b..cc673754461 100644 --- a/mysql-test/main/grant5.test +++ b/mysql-test/main/grant5.test @@ -66,29 +66,21 @@ update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad') where user='u5'; update mysql.global_priv set priv=json_set(priv, '$.plugin', 'nonexistent') where user='u8'; flush privileges; -# invalid entries are skipped, users don't exist -error ER_PASSWORD_NO_MATCH; show create user u1@h; show create user u2@h; show create user u3@h; show create user u4@h; -error ER_PASSWORD_NO_MATCH; show create user u5@h; show create user u6@h; show create user u7@h; -error ER_PASSWORD_NO_MATCH; show create user u8@h; -#grants don't work either -error ER_PASSWORD_NO_MATCH; grant select on *.* to u1@h; grant select on *.* to u2@h; grant select on *.* to u3@h; grant select on *.* to u4@h; -error ER_PASSWORD_NO_MATCH; grant select on *.* to u5@h; grant select on *.* to u6@h; grant select on *.* to u7@h; -error ER_PASSWORD_NO_MATCH; grant select on *.* to u8@h; select user,select_priv,plugin,authentication_string from mysql.user where user like 'u_'; diff --git a/mysql-test/main/plugin_auth_qa_1.result b/mysql-test/main/plugin_auth_qa_1.result index dd709fee04c..d2d902cb6a6 100644 --- a/mysql-test/main/plugin_auth_qa_1.result +++ b/mysql-test/main/plugin_auth_qa_1.result @@ -149,13 +149,11 @@ new_user test_plugin_server new_dest plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'new_plugin_server') WHERE user='new_user'; FLUSH PRIVILEGES; -Warnings: -Warning 1524 Plugin 'new_plugin_server' is not loaded SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; User plugin authentication_string new_user new_plugin_server new_dest plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 -ERROR 28000: Access denied for user 'new_user'@'localhost' (using password: YES) +ERROR HY000: Plugin 'new_plugin_server' is not loaded UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'test_plugin_server') WHERE user='new_user'; UPDATE mysql.global_priv SET user='new_dest' WHERE user='plug_dest'; FLUSH PRIVILEGES; diff --git a/mysql-test/main/plugin_auth_qa_1.test b/mysql-test/main/plugin_auth_qa_1.test index 81a9155a390..fb577fc178f 100644 --- a/mysql-test/main/plugin_auth_qa_1.test +++ b/mysql-test/main/plugin_auth_qa_1.test @@ -141,7 +141,7 @@ FLUSH PRIVILEGES; --sorted_result SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; --disable_query_log ---error ER_ACCESS_DENIED_ERROR +--error ER_PLUGIN_IS_NOT_LOADED connect(plug_user,localhost,new_user,new_dest); --enable_query_log UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'test_plugin_server') WHERE user='new_user'; diff --git a/plugin/auth_gssapi/gssapi_server.cc b/plugin/auth_gssapi/gssapi_server.cc index a498aba982d..8aa13aac6c9 100644 --- a/plugin/auth_gssapi/gssapi_server.cc +++ b/plugin/auth_gssapi/gssapi_server.cc @@ -145,7 +145,7 @@ int plugin_deinit() } -int auth_server(MYSQL_PLUGIN_VIO *vio,const char *user, size_t userlen, int use_full_name) +int auth_server(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info) { int rc= CR_ERROR; /* return code */ @@ -157,6 +157,9 @@ int auth_server(MYSQL_PLUGIN_VIO *vio,const char *user, size_t userlen, int use_ gss_name_t client_name; gss_buffer_desc client_name_buf, input, output; char *client_name_str; + const char *user= 0; + size_t userlen; + int use_full_name; /* server acquires credential */ major= gss_acquire_cred(&minor, service_name, GSS_C_INDEFINITE, @@ -180,6 +183,21 @@ int auth_server(MYSQL_PLUGIN_VIO *vio,const char *user, size_t userlen, int use_ log_error(0, 0, "fail to read token from client"); goto cleanup; } + if (!user) + { + if (auth_info->auth_string_length > 0) + { + use_full_name= 1; + user= auth_info->auth_string; + userlen= auth_info->auth_string_length; + } + else + { + use_full_name= 0; + user= auth_info->user_name; + userlen= auth_info->user_name_length; + } + } input.length= len; major= gss_accept_sec_context(&minor, &ctxt, cred, &input, diff --git a/plugin/auth_gssapi/server_plugin.cc b/plugin/auth_gssapi/server_plugin.cc index 5db86cffbe4..550ae775e0f 100644 --- a/plugin/auth_gssapi/server_plugin.cc +++ b/plugin/auth_gssapi/server_plugin.cc @@ -64,41 +64,11 @@ unsigned long srv_mech; */ static int gssapi_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info) { - int use_full_name; - const char *user; - int user_len; - - /* No user name yet ? Read the client handshake packet with the user name. */ - if (auth_info->user_name == 0) - { - unsigned char *pkt; - if (vio->read_packet(vio, &pkt) < 0) - return CR_ERROR; - } - /* Send first packet with target name and mech name */ if (vio->write_packet(vio, (unsigned char *)first_packet, first_packet_len)) - { return CR_ERROR; - } - /* Figure out whether to use full name (as given in IDENTIFIED AS clause) - * or just short username auth_string - */ - if (auth_info->auth_string_length > 0) - { - use_full_name= 1; - user= auth_info->auth_string; - user_len= auth_info->auth_string_length; - } - else - { - use_full_name= 0; - user= auth_info->user_name; - user_len= auth_info->user_name_length; - } - - return auth_server(vio, user, user_len, use_full_name); + return auth_server(vio, auth_info); } static int initialize_plugin(void *unused) diff --git a/plugin/auth_gssapi/server_plugin.h b/plugin/auth_gssapi/server_plugin.h index 6284a319d03..84552d3a263 100644 --- a/plugin/auth_gssapi/server_plugin.h +++ b/plugin/auth_gssapi/server_plugin.h @@ -48,4 +48,4 @@ extern char *srv_keytab_path; int plugin_init(); int plugin_deinit(); -int auth_server(MYSQL_PLUGIN_VIO *vio, const char *username, size_t username_len, int use_full_name); +int auth_server(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info); diff --git a/plugin/auth_gssapi/sspi_server.cc b/plugin/auth_gssapi/sspi_server.cc index af78829df6e..44aa5051472 100644 --- a/plugin/auth_gssapi/sspi_server.cc +++ b/plugin/auth_gssapi/sspi_server.cc @@ -140,7 +140,7 @@ static int get_client_name_from_context(CtxtHandle *ctxt, } -int auth_server(MYSQL_PLUGIN_VIO *vio, const char *user, size_t user_len, int compare_full_name) +int auth_server(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info) { int ret; SECURITY_STATUS sspi_ret; @@ -155,6 +155,8 @@ int auth_server(MYSQL_PLUGIN_VIO *vio, const char *user, size_t user_len, int co SecBuffer outbuf; void* out= NULL; char client_name[MYSQL_USERNAME_LENGTH + 1]; + const char *user= 0; + int compare_full_name; ret= CR_ERROR; SecInvalidateHandle(&cred); @@ -207,6 +209,19 @@ int auth_server(MYSQL_PLUGIN_VIO *vio, const char *user, size_t user_len, int co log_error(SEC_E_OK, "communication error(read)"); goto cleanup; } + if (!user) + { + if (auth_info->auth_string_length > 0) + { + compare_full_name= 1; + user= auth_info->auth_string; + } + else + { + compare_full_name= 0; + user= auth_info->user_name; + } + } inbuf.cbBuffer= len; outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE; sspi_ret= AcceptSecurityContext( diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c index 1ffc3285a3d..56154fb1656 100644 --- a/plugin/auth_pam/auth_pam.c +++ b/plugin/auth_pam/auth_pam.c @@ -36,8 +36,8 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { int p_to_c[2], c_to_p[2]; /* Parent-to-child and child-to-parent pipes. */ pid_t proc_id; - int result= CR_ERROR; - unsigned char field; + int result= CR_ERROR, pkt_len; + unsigned char field, *pkt; PAM_DEBUG((stderr, "PAM: opening pipes.\n")); if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0) @@ -96,6 +96,14 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) close(c_to_p[1]) < 0) goto error_ret; + /* no user name yet ? read the client handshake packet with the user name */ + if (info->user_name == 0) + { + if ((pkt_len= vio->read_packet(vio, &pkt) < 0)) + return CR_ERROR; + } + else + pkt= NULL; PAM_DEBUG((stderr, "PAM: parent sends user data [%s], [%s].\n", info->user_name, info->auth_string)); @@ -140,23 +148,27 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { unsigned char buf[10240]; int buf_len; - unsigned char *pkt; PAM_DEBUG((stderr, "PAM: getting CONV string.\n")); if ((buf_len= read_string(c_to_p[0], (char *) buf, sizeof(buf))) < 0) goto error_ret; - PAM_DEBUG((stderr, "PAM: sending CONV string.\n")); - if (vio->write_packet(vio, buf, buf_len)) - goto error_ret; + if (!pkt || (buf[0] >> 1) != 2) + { + PAM_DEBUG((stderr, "PAM: sending CONV string.\n")); + if (vio->write_packet(vio, buf, buf_len)) + goto error_ret; - PAM_DEBUG((stderr, "PAM: reading CONV answer.\n")); - if ((buf_len= vio->read_packet(vio, &pkt)) < 0) - goto error_ret; + PAM_DEBUG((stderr, "PAM: reading CONV answer.\n")); + if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) + goto error_ret; + } PAM_DEBUG((stderr, "PAM: answering CONV.\n")); - if (write_string(p_to_c[1], pkt, buf_len)) + if (write_string(p_to_c[1], pkt, pkt_len)) goto error_ret; + + pkt= NULL; } break; diff --git a/plugin/auth_pam/auth_pam_v1.c b/plugin/auth_pam/auth_pam_v1.c index 95110a5e310..6e0b2ea9991 100644 --- a/plugin/auth_pam/auth_pam_v1.c +++ b/plugin/auth_pam/auth_pam_v1.c @@ -17,13 +17,21 @@ #include struct param { - unsigned char buf[10240], *ptr; + unsigned char buf[10240], *ptr, *cached; + int cached_len; MYSQL_PLUGIN_VIO *vio; }; static int roundtrip(struct param *param, const unsigned char *buf, int buf_len, unsigned char **pkt) { + if (param->cached && (buf[0] >> 1) == 2) + { + *pkt= param->cached; + param->cached= NULL; + return param->cached_len; + } + param->cached= NULL; if (param->vio->write_packet(param->vio, buf, buf_len)) return -1; return param->vio->read_packet(param->vio, pkt); @@ -35,6 +43,16 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { struct param param; param.vio = vio; + + /* no user name yet ? read the client handshake packet with the user name */ + if (info->user_name == 0) + { + if ((param.cached_len= vio->read_packet(vio, ¶m.cached) < 0)) + return CR_ERROR; + } + else + param.cached= NULL; + return pam_auth_base(¶m, info); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 01b560cd59b..b4ceec66a9e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -170,7 +170,8 @@ public: else dst->plugin= safe_lexcstrdup_root(root, plugin); dst->auth_string= safe_lexcstrdup_root(root, auth_string); - dst->salt= safe_lexcstrdup_root(root, salt); + if (salt.str) + dst->salt= safe_lexcstrdup_root(root, salt); dst->host.hostname= safe_strdup_root(root, host.hostname); dst->default_rolename= safe_lexcstrdup_root(root, default_rolename); bzero(&dst->role_grants, sizeof(role_grants)); @@ -1781,6 +1782,26 @@ static bool validate_password(THD *thd, const LEX_CSTRING &user, return false; } +static int set_user_salt(ACL_USER *acl_user, plugin_ref plugin) +{ + st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info; + if (auth->interface_version >= 0x0202 && acl_user->auth_string.length && + auth->preprocess_hash) + { + uchar buf[MAX_SCRAMBLE_LENGTH]; + size_t len= sizeof(buf); + if (auth->preprocess_hash(acl_user->auth_string.str, + acl_user->auth_string.length, buf, &len)) + return 1; // ER_PASSWD_LENGTH? + acl_user->salt.str= (char*)memdup_root(&acl_memroot, buf, len); + acl_user->salt.length= len; + } + else + acl_user->salt= acl_user->auth_string; + + return 0; +} + /** Fills in ACL_USER::auth_string and ACL_USER::salt fields, as needed @@ -1789,11 +1810,8 @@ static bool validate_password(THD *thd, const LEX_CSTRING &user, Fails if the plain-text password fails validation, if the plugin is not loaded, if the auth_string is invalid. - - Using NULL for a password disables validation - (needed for loading from mysql.user table). */ -static int set_user_auth(THD *thd, ACL_USER *acl_user, const LEX_CSTRING *pwtext) +static int set_user_auth(THD *thd, ACL_USER *acl_user, const LEX_CSTRING &pwtext) { const char *plugin_name= acl_user->plugin.str; bool unlock_plugin= false; @@ -1813,49 +1831,32 @@ static int set_user_auth(THD *thd, ACL_USER *acl_user, const LEX_CSTRING *pwtext st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info; if (auth->interface_version >= 0x0202) { - if (pwtext) + if (auth->hash_password && + validate_password(thd, acl_user->user, pwtext, + acl_user->auth_string.length)) + goto end; + if (pwtext.length) { - if (auth->hash_password && - validate_password(thd, acl_user->user, *pwtext, - acl_user->auth_string.length)) - goto end; - if (pwtext->length) + if (auth->hash_password) { - if (auth->hash_password) - { - char buf[MAX_SCRAMBLE_LENGTH]; - size_t len= sizeof(buf) - 1; - if (auth->hash_password(pwtext->str, pwtext->length, buf, &len)) - goto end; // OOM? - buf[len] = 0; - acl_user->auth_string.str= (char*)memdup_root(&acl_memroot, buf, len+1); - acl_user->auth_string.length= len; - } - else - { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_SET_PASSWORD_AUTH_PLUGIN, - ER_THD(thd, ER_SET_PASSWORD_AUTH_PLUGIN), - acl_user->plugin.str); - } - } - } - - if (acl_user->auth_string.length) - { - if (auth->preprocess_hash) - { - uchar buf[MAX_SCRAMBLE_LENGTH]; - size_t len= sizeof(buf); - if (auth->preprocess_hash(acl_user->auth_string.str, - acl_user->auth_string.length, buf, &len)) - goto end; // ER_PASSWD_LENGTH? - acl_user->salt.str= (char*)memdup_root(&acl_memroot, buf, len); - acl_user->salt.length= len; + char buf[MAX_SCRAMBLE_LENGTH]; + size_t len= sizeof(buf) - 1; + if (auth->hash_password(pwtext.str, pwtext.length, buf, &len)) + goto end; // OOM? + buf[len] = 0; + acl_user->auth_string.str= (char*)memdup_root(&acl_memroot, buf, len+1); + acl_user->auth_string.length= len; } else - acl_user->salt= acl_user->auth_string; + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_SET_PASSWORD_AUTH_PLUGIN, + ER_THD(thd, ER_SET_PASSWORD_AUTH_PLUGIN), + acl_user->plugin.str); + } } + if (set_user_salt(acl_user, plugin)) + goto end; } res= 0; @@ -1865,6 +1866,34 @@ end: return res; } + +/** + Lazily computes user's salt from the password hash +*/ +static bool set_user_salt_if_needed(ACL_USER *user_copy, plugin_ref plugin) +{ + DBUG_ASSERT(!strcasecmp(user_copy->plugin.str, plugin_name(plugin)->str)); + + if (user_copy->salt.str) + return 0; // already done + + if (set_user_salt(user_copy, plugin)) + return 1; + + mysql_mutex_lock(&acl_cache->lock); + ACL_USER *user= find_user_exact(user_copy->host.hostname, user_copy->user.str); + // make sure the user wasn't altered or dropped meanwhile + if (user && !user->salt.str && + user->plugin.length == user_copy->plugin.length && + user->auth_string.length == user_copy->auth_string.length && + !memcmp(user->plugin.str, user_copy->plugin.str, user->plugin.length) && + !memcmp(user->auth_string.str, user_copy->auth_string.str, user->auth_string.length)) + user->salt= user_copy->salt; + mysql_mutex_unlock(&acl_cache->lock); + return 0; +} + + /** Fix ACL::plugin pointer to point to a hard-coded string, if appropriate @@ -2128,12 +2157,6 @@ static bool acl_load(THD *thd, const Grant_tables& tables) user.default_rolename.str= user_table.get_default_role(&acl_memroot); user.default_rolename.length= safe_strlen(user.default_rolename.str); - - if (set_user_auth(thd, &user, NULL)) - { - thd->clear_error(); // the warning is still issued - continue; - } } push_new_user(user); } @@ -2852,7 +2875,7 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, const ACL_USER *from, acl_user->hostname_length= combo.host.length; acl_user->sort= get_sort(2, acl_user->host.hostname, acl_user->user.str); acl_user->plugin= native_password_plugin_name; - acl_user->salt= acl_user->auth_string= empty_clex_str; + acl_user->auth_string= empty_clex_str; my_init_dynamic_array(&acl_user->role_grants, sizeof(ACL_USER *), 0, 8, MYF(0)); } @@ -2863,7 +2886,7 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, const ACL_USER *from, acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, combo.auth); if (fix_user_plugin_ptr(acl_user)) acl_user->plugin= safe_lexcstrdup_root(&acl_memroot, combo.plugin); - if (set_user_auth(thd, acl_user, &combo.pwtext)) + if (set_user_auth(thd, acl_user, combo.pwtext)) return 1; } acl_user->access= privileges; @@ -3429,7 +3452,7 @@ bool change_password(THD *thd, LEX_USER *user) } acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, user->auth); - if (set_user_auth(thd, acl_user, &user->pwtext)) + if (set_user_auth(thd, acl_user, user->pwtext)) { mysql_mutex_unlock(&acl_cache->lock); goto end; @@ -11275,10 +11298,10 @@ static int show_database_grants(THD *thd, SHOW_VAR *var, char *buff, } #else +static bool set_user_salt_if_needed(ACL_USER *, plugin_ref) +{ return 0; } bool check_grant(THD *, ulong, TABLE_LIST *, bool, uint, bool) -{ - return 0; -} +{ return 0; } #endif /*NO_EMBEDDED_ACCESS_CHECKS */ SHOW_VAR acl_statistics[] = { @@ -12432,12 +12455,6 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio) DBUG_RETURN (1); } - mpvio->auth_info.user_name= sctx->user; - mpvio->auth_info.user_name_length= (uint)strlen(sctx->user); - mpvio->auth_info.auth_string= mpvio->acl_user->salt.str; - mpvio->auth_info.auth_string_length= (unsigned long) mpvio->acl_user->salt.length; - strmake_buf(mpvio->auth_info.authenticated_as, mpvio->acl_user->user.str); - DBUG_PRINT("info", ("exit: user=%s, auth_string=%s, authenticated as=%s" "plugin=%s", mpvio->auth_info.user_name, @@ -12609,8 +12626,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) } if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) && - read_client_connect_attrs(&next_field, end, - thd->charset())) + read_client_connect_attrs(&next_field, end, thd->charset())) { my_message(ER_UNKNOWN_COM_ERROR, ER_THD(thd, ER_UNKNOWN_COM_ERROR), MYF(0)); @@ -12970,7 +12986,7 @@ static int server_mpvio_write_packet(MYSQL_PLUGIN_VIO *param, */ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) { - MPVIO_EXT *mpvio= (MPVIO_EXT *) param; + MPVIO_EXT * const mpvio= (MPVIO_EXT *) param; ulong pkt_len; DBUG_ENTER("server_mpvio_read_packet"); if (mpvio->packets_written == 0) @@ -13001,11 +13017,11 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) client_auth_plugin) == 0) { mpvio->status= MPVIO_EXT::FAILURE; + pkt_len= mpvio->cached_client_reply.pkt_len; *buf= (uchar*) mpvio->cached_client_reply.pkt; mpvio->cached_client_reply.pkt= 0; mpvio->packets_read++; - - DBUG_RETURN ((int) mpvio->cached_client_reply.pkt_len); + goto done; } /* @@ -13039,6 +13055,16 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) else *buf= mpvio->auth_info.thd->net.read_pos; +done: + if (set_user_salt_if_needed(mpvio->acl_user, mpvio->plugin)) + goto err; + + mpvio->auth_info.user_name= mpvio->auth_info.thd->security_ctx->user; + mpvio->auth_info.user_name_length= (uint)strlen(mpvio->auth_info.user_name); + mpvio->auth_info.auth_string= mpvio->acl_user->salt.str; + mpvio->auth_info.auth_string_length= (ulong) mpvio->acl_user->salt.length; + strmake_buf(mpvio->auth_info.authenticated_as, mpvio->acl_user->user.str); + DBUG_RETURN((int)pkt_len); err: @@ -13179,6 +13205,7 @@ static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name, plugin_ref plugin= get_auth_plugin(thd, *auth_plugin_name, &unlock_plugin); mpvio->plugin= plugin; + mpvio->auth_info.user_name= NULL; old_status= mpvio->status; if (plugin)