summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2021-10-07 11:39:02 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2021-10-08 16:34:32 +0200
commit00c9a45a0fed8e78a5b43fde5b71c33228d2a706 (patch)
tree50fe9bf123e2abee55f7ac94b4c7b6466ca7fdf9
parenta75813d46739f1e3aea9821b163c0ff1332a017e (diff)
downloadmariadb-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.result20
-rw-r--r--mysql-test/suite/plugins/t/simple_password_check.test14
-rw-r--r--sql/sql_acl.cc55
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 */