Skip to content

Commit

Permalink
MDEV-26650: Failed ALTER USER/GRANT statement removes the password fr…
Browse files Browse the repository at this point in the history
…om the cache

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.
  • Loading branch information
sanja-byelkin committed Oct 18, 2021
1 parent a736a31 commit c9a9ae6
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 11 deletions.
20 changes: 20 additions & 0 deletions mysql-test/suite/plugins/r/simple_password_check.result
Expand Up @@ -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;
14 changes: 14 additions & 0 deletions mysql-test/suite/plugins/t/simple_password_check.test
Expand Up @@ -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;
46 changes: 35 additions & 11 deletions sql/sql_acl.cc
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit c9a9ae6

Please sign in to comment.