From 00c9a45a0fed8e78a5b43fde5b71c33228d2a706 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 7 Oct 2021 11:39:02 +0200 Subject: MDEV-26650: Failed ALTER USER/GRANT statement removes the password from the cache Starting from 10.4 AUTH is not part of ACL_USER so have to be safely copied. Patch made in line with previous code ideas. --- .../suite/plugins/r/simple_password_check.result | 20 ++++++++ .../suite/plugins/t/simple_password_check.test | 14 ++++++ sql/sql_acl.cc | 55 +++++++++++++++++----- 3 files changed, 77 insertions(+), 12 deletions(-) diff --git a/mysql-test/suite/plugins/r/simple_password_check.result b/mysql-test/suite/plugins/r/simple_password_check.result index 2e706115bd1..b04c5535a3f 100644 --- a/mysql-test/suite/plugins/r/simple_password_check.result +++ b/mysql-test/suite/plugins/r/simple_password_check.result @@ -161,3 +161,23 @@ flush privileges; uninstall plugin simple_password_check; create user foo1 identified by 'pwd'; drop user foo1; +# +# MDEV-26650: Failed ALTER USER/GRANT statement removes the +# password from the cache +# +create user foo1@localhost identified by 'is_role(); LEX *lex= thd->lex; TABLE *table= user_table.table(); - ACL_USER new_acl_user, *old_acl_user= 0; + ACL_USER *new_acl_user= 0, *old_acl_user= 0; DBUG_ENTER("replace_user_table"); mysql_mutex_assert_owner(&acl_cache->lock); @@ -4493,13 +4518,19 @@ static int replace_user_table(THD *thd, const User_table &user_table, my_error(ER_PASSWORD_NO_MATCH, MYF(0)); goto end; } - new_acl_user= old_row_exists ? *old_acl_user : - ACL_USER(thd, *combo, lex->account_options, rights); - if (acl_user_update(thd, &new_acl_user, nauth, + + new_acl_user= (old_row_exists ? + new (thd->mem_root) ACL_USER(&acl_memroot, *old_acl_user) : + new (thd->mem_root) ACL_USER(thd, *combo, + lex->account_options, + rights)); + if (!new_acl_user) + goto end; + if (acl_user_update(thd, new_acl_user, nauth, *combo, lex->account_options, rights)) goto end; - if (user_table.set_auth(new_acl_user)) + if (user_table.set_auth(*new_acl_user)) { my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), user_table.name().str, 3, user_table.num_fields(), @@ -4554,14 +4585,14 @@ static int replace_user_table(THD *thd, const User_table &user_table, lex->account_options.max_statement_time != 0.0); if (lex->account_options.account_locked != ACCOUNTLOCK_UNSPECIFIED) - user_table.set_account_locked(new_acl_user.account_locked); + user_table.set_account_locked(new_acl_user->account_locked); if (nauth) - user_table.set_password_last_changed(new_acl_user.password_last_changed); + user_table.set_password_last_changed(new_acl_user->password_last_changed); if (lex->account_options.password_expire != PASSWORD_EXPIRE_UNSPECIFIED) { - user_table.set_password_lifetime(new_acl_user.password_lifetime); - user_table.set_password_expired(new_acl_user.password_expired); + user_table.set_password_lifetime(new_acl_user->password_lifetime); + user_table.set_password_expired(new_acl_user->password_expired); } } @@ -4611,10 +4642,10 @@ end: else { if (old_acl_user) - *old_acl_user= new_acl_user; + old_acl_user->shallow_copy(*new_acl_user); else { - push_new_user(new_acl_user); + push_new_user(*new_acl_user); rebuild_acl_users(); /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ -- cgit v1.2.1