summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/grant2.result11
-rw-r--r--mysql-test/t/grant2.test32
-rw-r--r--sql/sql_acl.cc33
3 files changed, 70 insertions, 6 deletions
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 9c744396403..246aaa3a93e 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -107,6 +107,17 @@ delete from mysql.columns_priv where user like 'mysqltest\_%';
flush privileges;
drop database mysqltest;
use test;
+create user mysqltest_1@host1;
+create user mysqltest_2@host2;
+create user mysqltest_3@host3;
+create user mysqltest_4@host4;
+create user mysqltest_5@host5;
+create user mysqltest_6@host6;
+create user mysqltest_7@host7;
+flush privileges;
+drop user mysqltest_3@host3;
+drop user mysqltest_1@host1, mysqltest_2@host2, mysqltest_4@host4,
+mysqltest_5@host5, mysqltest_6@host6, mysqltest_7@host7;
set sql_mode='maxdb';
drop table if exists t1, t2;
create table t1(c1 int);
diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test
index 2fa82ce5dce..c19bb1482d6 100644
--- a/mysql-test/t/grant2.test
+++ b/mysql-test/t/grant2.test
@@ -155,6 +155,38 @@ flush privileges;
drop database mysqltest;
use test;
+
+#
+# Bug #15775: "drop user" command does not refresh acl_check_hosts
+#
+
+# Create some test users
+create user mysqltest_1@host1;
+create user mysqltest_2@host2;
+create user mysqltest_3@host3;
+create user mysqltest_4@host4;
+create user mysqltest_5@host5;
+create user mysqltest_6@host6;
+create user mysqltest_7@host7;
+flush privileges;
+
+# Drop one user
+drop user mysqltest_3@host3;
+
+# This connect failed before fix since the acl_check_hosts list was corrupted by the "drop user"
+connect (con8,127.0.0.1,root,,test,$MASTER_MYPORT,);
+disconnect con8;
+connection default;
+
+# Clean up - Drop all of the remaining users at once
+drop user mysqltest_1@host1, mysqltest_2@host2, mysqltest_4@host4,
+ mysqltest_5@host5, mysqltest_6@host6, mysqltest_7@host7;
+
+# Check that it's still possible to connect
+connect (con9,127.0.0.1,root,,test,$MASTER_MYPORT,);
+disconnect con9;
+connection default;
+
#
# Create and drop user
#
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index cd83efcac2c..110b529fffc 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -68,6 +68,7 @@ static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0);
static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b);
static ulong get_sort(uint count,...);
static void init_check_host(void);
+static void rebuild_check_host(void);
static ACL_USER *find_acl_user(const char *host, const char *user,
my_bool exact);
static bool update_user_table(THD *thd, TABLE *table,
@@ -1095,10 +1096,8 @@ static void acl_insert_user(const char *user, const char *host,
qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements,
sizeof(ACL_USER),(qsort_cmp) acl_compare);
- /* We must free acl_check_hosts as its memory is mapped to acl_user */
- delete_dynamic(&acl_wild_hosts);
- hash_free(&acl_check_hosts);
- init_check_host();
+ /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */
+ rebuild_check_host();
}
@@ -1283,7 +1282,7 @@ static void init_check_host(void)
if (j == acl_wild_hosts.elements) // If new
(void) push_dynamic(&acl_wild_hosts,(char*) &acl_user->host);
}
- else if (!hash_search(&acl_check_hosts,(byte*) &acl_user->host,
+ else if (!hash_search(&acl_check_hosts,(byte*) acl_user->host.hostname,
(uint) strlen(acl_user->host.hostname)))
{
if (my_hash_insert(&acl_check_hosts,(byte*) acl_user))
@@ -1300,6 +1299,22 @@ static void init_check_host(void)
}
+/*
+ Rebuild lists used for checking of allowed hosts
+
+ We need to rebuild 'acl_check_hosts' and 'acl_wild_hosts' after adding,
+ dropping or renaming user, since they contain pointers to elements of
+ 'acl_user' array, which are invalidated by drop operation, and use
+ ACL_USER::host::hostname as a key, which is changed by rename.
+*/
+void rebuild_check_host(void)
+{
+ delete_dynamic(&acl_wild_hosts);
+ hash_free(&acl_check_hosts);
+ init_check_host();
+}
+
+
/* Return true if there is no users that can match the given host */
bool acl_check_host(const char *host, const char *ip)
@@ -5241,6 +5256,9 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
}
}
+ /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */
+ rebuild_check_host();
+
VOID(pthread_mutex_unlock(&acl_cache->lock));
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
@@ -5265,7 +5283,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
{
- int result= 0;
+ int result;
String wrong_users;
LEX_USER *user_from;
LEX_USER *user_to;
@@ -5297,6 +5315,9 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
}
}
+ /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */
+ rebuild_check_host();
+
VOID(pthread_mutex_unlock(&acl_cache->lock));
rw_unlock(&LOCK_grant);
close_thread_tables(thd);