diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2021-10-14 16:19:09 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2021-10-18 12:09:59 +0200 |
commit | c9a9ae65544e03f9585a65db9c0e6d729616a40c (patch) | |
tree | efd7997de5204b000dba1c7fb0cf2df98ea37eb8 | |
parent | a736a3174a4e7c0d92a38901ae61f563d4afede7 (diff) | |
download | mariadb-git-c9a9ae65544e03f9585a65db9c0e6d729616a40c.tar.gz |
MDEV-26650: Failed ALTER USER/GRANT statement removes the password from the cachebb-10.4-MDEV-26650-2
Starting from 10.4 AUTH is not part of ACL_USER so changes have to be done
over a copy, and bring in the cache only in case of success.
-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 | 46 |
3 files changed, 69 insertions, 11 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..e854f9a4a35 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3227,21 +3227,22 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, uint nauth, const Account_options &options, const ulong privileges) { + ACL_USER_PARAM::AUTH *work_copy= NULL; if (nauth) { - if (acl_user->nauth >= nauth) - acl_user->nauth= nauth; - else - acl_user->alloc_auth(&acl_memroot, nauth); + if (!(work_copy= (ACL_USER_PARAM::AUTH*) + alloc_root(thd->mem_root, nauth * sizeof(ACL_USER_PARAM::AUTH)))) + return 1; USER_AUTH *auth= combo.auth; for (uint i= 0; i < nauth; i++, auth= auth->next) { - acl_user->auth[i].plugin= auth->plugin; - acl_user->auth[i].auth_string= safe_lexcstrdup_root(&acl_memroot, auth->auth_str); - if (fix_user_plugin_ptr(acl_user->auth + i)) - acl_user->auth[i].plugin= safe_lexcstrdup_root(&acl_memroot, auth->plugin); - if (set_user_auth(thd, acl_user->user, acl_user->auth + i, auth->pwtext)) + work_copy[i].plugin= auth->plugin; + work_copy[i].auth_string= safe_lexcstrdup_root(&acl_memroot, + auth->auth_str); + if (fix_user_plugin_ptr(work_copy + i)) + work_copy[i].plugin= safe_lexcstrdup_root(&acl_memroot, auth->plugin); + if (set_user_auth(thd, acl_user->user, work_copy + i, auth->pwtext)) return 1; } } @@ -3269,11 +3270,34 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, uint nauth, if (options.account_locked != ACCOUNTLOCK_UNSPECIFIED) acl_user->account_locked= options.account_locked == ACCOUNTLOCK_LOCKED; - /* Unexpire the user password */ + if (thd->is_error()) + { + // If something went wrong (including OOM) we will not spoil acl cache + return 1; + } + /* Unexpire the user password and copy AUTH (when no more errors possible)*/ if (nauth) { acl_user->password_expired= false; - acl_user->password_last_changed= thd->query_start();; + acl_user->password_last_changed= thd->query_start(); + + if (acl_user->nauth >= nauth) + { + acl_user->nauth= nauth; + } + else + { + if (acl_user->alloc_auth(&acl_memroot, nauth)) + { + /* + acl_user is a copy, so NULL assigned in case of an error do not + change the acl cache + */ + return 1; + } + } + DBUG_ASSERT(work_copy); // allocated under the same condinition + memcpy(acl_user->auth, work_copy, nauth * sizeof(ACL_USER_PARAM::AUTH)); } switch (options.password_expire) { |