diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2021-10-07 11:39:02 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2021-10-08 16:34:32 +0200 |
commit | 00c9a45a0fed8e78a5b43fde5b71c33228d2a706 (patch) | |
tree | 50fe9bf123e2abee55f7ac94b4c7b6466ca7fdf9 | |
parent | a75813d46739f1e3aea9821b163c0ff1332a017e (diff) | |
download | mariadb-git-bb-10.4-MDEV-26650.tar.gz |
MDEV-26650: Failed ALTER USER/GRANT statement removes the password from the cachebb-10.4-MDEV-26650
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.
-rw-r--r-- | mysql-test/suite/plugins/r/simple_password_check.result | 20 | ||||
-rw-r--r-- | mysql-test/suite/plugins/t/simple_password_check.test | 14 | ||||
-rw-r--r-- | 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 '<GDFH:3ghj'; +show grants for foo1@localhost; +Grants for foo1@localhost +GRANT USAGE ON *.* TO `foo1`@`localhost` IDENTIFIED BY PASSWORD '*1D62FA326F98258451ED56A404F15452423DCC1D' +install soname "simple_password_check"; +ALTER USER foo1@localhost identified by 'foo1'; +ERROR HY000: Operation ALTER USER failed for 'foo1'@'localhost' +show grants for foo1@localhost; +Grants for foo1@localhost +GRANT USAGE ON *.* TO `foo1`@`localhost` IDENTIFIED BY PASSWORD '*1D62FA326F98258451ED56A404F15452423DCC1D' +flush privileges; +show grants for foo1@localhost; +Grants for foo1@localhost +GRANT USAGE ON *.* TO `foo1`@`localhost` IDENTIFIED BY PASSWORD '*1D62FA326F98258451ED56A404F15452423DCC1D' +drop user foo1@localhost; +uninstall plugin simple_password_check; diff --git a/mysql-test/suite/plugins/t/simple_password_check.test b/mysql-test/suite/plugins/t/simple_password_check.test index b7d631ab4bb..dfb078df638 100644 --- a/mysql-test/suite/plugins/t/simple_password_check.test +++ b/mysql-test/suite/plugins/t/simple_password_check.test @@ -122,3 +122,17 @@ uninstall plugin simple_password_check; create user foo1 identified by 'pwd'; drop user foo1; +--echo # +--echo # MDEV-26650: Failed ALTER USER/GRANT statement removes the +--echo # password from the cache +--echo # +create user foo1@localhost identified by '<GDFH:3ghj'; +show grants for foo1@localhost; +install soname "simple_password_check"; +--error ER_CANNOT_USER +ALTER USER foo1@localhost identified by 'foo1'; +show grants for foo1@localhost; +flush privileges; +show grants for foo1@localhost; +drop user foo1@localhost; +uninstall plugin simple_password_check; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0e2c044e3a1..23b086145bd 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -188,6 +188,9 @@ public: class ACL_USER :public ACL_USER_BASE, public ACL_USER_PARAM { +protected: + // default shallow copy constructor (protect from non-authorized usage) + ACL_USER(const ACL_USER &)= default; public: ACL_USER() { } @@ -195,7 +198,29 @@ public: const Account_options &options, const ulong privileges); - ACL_USER *copy(MEM_ROOT *root) + // Copy constructor to make a bit deeper copy on the MEM_ROOT + ACL_USER(MEM_ROOT *mem_root, const ACL_USER &orig) + { + AUTH *dauth= (AUTH*) alloc_root(mem_root, sizeof(AUTH) * orig.nauth); + if (!dauth) + { + bzero((void*)this, sizeof(*this)); + return; + } + *this= orig; + auth= dauth; + for (uint i=0; i < nauth; i++) + { + auth[i]= orig.auth[i]; + } + } + + void shallow_copy(const ACL_USER &orig) + { + *this= orig; + } + + ACL_USER *copy(MEM_ROOT *root) const { ACL_USER *dst; AUTH *dauth; @@ -4390,7 +4415,7 @@ static int replace_user_table(THD *thd, const User_table &user_table, bool handle_as_role= combo->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 */ |