Commit fd826cc3 authored by Sergei Golubchik's avatar Sergei Golubchik

properly propagate privilege changes on DROP ROLE

parent 82037f9c
create database mysqltest1;
create table mysqltest1.t1 (a int, b int);
create table mysqltest1.t2 (a int, b int);
insert mysqltest1.t1 values (1,2),(3,4);
insert mysqltest1.t2 values (5,6),(7,8);
create procedure mysqltest1.pr1() select "pr1";
create user foo@localhost;
create role role1;
create role role2;
grant role2 to role1;
grant role1 to foo@localhost;
grant reload on *.* to role2;
grant select on mysql.* to role2;
grant execute on procedure mysqltest1.pr1 to role2;
grant select on mysqltest1.t1 to role2;
grant select (a) on mysqltest1.t2 to role2;
flush tables;
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping'
show tables from mysqltest1;
ERROR 42000: Access denied for user 'foo'@'localhost' to database 'mysqltest1'
set role role1;
flush tables;
select * from mysql.roles_mapping;
Host User Role Admin_option
role1 role2 N
localhost foo role1 N
localhost root role1 Y
localhost root role2 Y
show tables from mysqltest1;
Tables_in_mysqltest1
t1
t2
select * from mysqltest1.t1;
a b
1 2
3 4
select * from mysqltest1.t2;
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2'
select a from mysqltest1.t2;
a
5
7
call mysqltest1.pr1();
pr1
pr1
revoke execute on procedure mysqltest1.pr1 from role2;
call mysqltest1.pr1();
ERROR 42000: execute command denied to user 'foo'@'localhost' for routine 'mysqltest1.pr1'
drop role role2;
show grants;
Grants for foo@localhost
GRANT role1 TO 'foo'@'localhost'
GRANT USAGE ON *.* TO 'foo'@'localhost'
GRANT USAGE ON *.* TO 'role1'
select * from information_schema.enabled_roles;
ROLE_NAME
role1
flush tables;
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping'
select * from mysqltest1.t1;
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1'
select a from mysqltest1.t2;
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2'
drop role role1;
drop user foo@localhost;
drop database mysqltest1;
--source include/not_embedded.inc
#
# test setting and dropping a role
#
create database mysqltest1;
create table mysqltest1.t1 (a int, b int);
create table mysqltest1.t2 (a int, b int);
insert mysqltest1.t1 values (1,2),(3,4);
insert mysqltest1.t2 values (5,6),(7,8);
create procedure mysqltest1.pr1() select "pr1";
create user foo@localhost;
create role role1;
create role role2;
grant role2 to role1;
grant role1 to foo@localhost;
grant reload on *.* to role2;
grant select on mysql.* to role2;
grant execute on procedure mysqltest1.pr1 to role2;
grant select on mysqltest1.t1 to role2;
grant select (a) on mysqltest1.t2 to role2;
connect (foo,localhost,foo);
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
flush tables;
--error ER_TABLEACCESS_DENIED_ERROR
select * from mysql.roles_mapping;
--error ER_DBACCESS_DENIED_ERROR
show tables from mysqltest1;
set role role1;
flush tables;
--sorted_result
select * from mysql.roles_mapping;
show tables from mysqltest1;
select * from mysqltest1.t1;
--error ER_TABLEACCESS_DENIED_ERROR
select * from mysqltest1.t2;
select a from mysqltest1.t2;
call mysqltest1.pr1();
connection default;
revoke execute on procedure mysqltest1.pr1 from role2;
connection foo;
--error ER_PROCACCESS_DENIED_ERROR
call mysqltest1.pr1();
connection default;
drop role role2;
connection foo;
show grants;
select * from information_schema.enabled_roles;
flush tables;
--error ER_TABLEACCESS_DENIED_ERROR
select * from mysql.roles_mapping;
--error ER_TABLEACCESS_DENIED_ERROR
select * from mysqltest1.t1;
--error ER_TABLEACCESS_DENIED_ERROR
select a from mysqltest1.t2;
connection default;
disconnect foo;
drop role role1;
drop user foo@localhost;
drop database mysqltest1;
...@@ -8539,6 +8539,9 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, ...@@ -8539,6 +8539,9 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
size_t old_key_length= acl_role->user.length; size_t old_key_length= acl_role->user.length;
if (drop) if (drop)
{ {
/* all grants must be revoked from this role by now. propagate this */
propagate_role_grants(acl_role, PRIVS_TO_MERGE::ALL, 0, 0);
// delete the role from cross-reference arrays // delete the role from cross-reference arrays
for (uint i=0; i < acl_role->role_grants.elements; i++) for (uint i=0; i < acl_role->role_grants.elements; i++)
{ {
...@@ -8847,46 +8850,20 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, ...@@ -8847,46 +8850,20 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
int result= 0; int result= 0;
int found; int found;
bool handle_as_role= user_from->is_role(); bool handle_as_role= user_from->is_role();
bool search_only= !drop && !user_to;
DBUG_ENTER("handle_grant_data"); DBUG_ENTER("handle_grant_data");
if (user_to) if (user_to)
DBUG_ASSERT(handle_as_role == user_to->is_role()); DBUG_ASSERT(handle_as_role == user_to->is_role());
/* Handle user table. */ if (search_only)
if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0)
{
/* Handle of table failed, don't touch the in-memory array. */
result= -1;
}
else
{ {
if (handle_as_role) /* quickly search in-memory structures first */
{ if (handle_as_role && find_acl_role(user_from->user.str))
if ((handle_grant_struct(ROLE_ACL, drop, user_from, user_to)) || found) DBUG_RETURN(1); // found
{
result= 1; /* At least one record/element found. */ if (!handle_as_role && find_user_exact(user_from->host.str, user_from->user.str))
/* If search is requested, we do not need to search further. */ DBUG_RETURN(1); // found
if (! drop && ! user_to)
goto end;
}
else
if (find_user_exact(user_from->host.str, user_from->user.str))
goto end; // looking for a role, found a user
}
else
{
/* Handle user array. */
if ((handle_grant_struct(USER_ACL, drop, user_from, user_to)) || found)
{
result= 1; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
if (! drop && ! user_to)
goto end;
}
else
if (find_acl_role(user_from->user.str))
goto end; // looking for a user, found a role
}
} }
/* Handle db table. */ /* Handle db table. */
...@@ -8898,12 +8875,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, ...@@ -8898,12 +8875,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else else
{ {
/* Handle db array. */ /* Handle db array. */
if (((handle_grant_struct(DB_ACL, drop, user_from, user_to) && ! result) || if ((handle_grant_struct(DB_ACL, drop, user_from, user_to) || found)
found) && ! result) && ! result)
{ {
result= 1; /* At least one record/element found. */ result= 1; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */ /* If search is requested, we do not need to search further. */
if (! drop && ! user_to) if (search_only)
goto end; goto end;
} }
} }
...@@ -8917,21 +8894,21 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, ...@@ -8917,21 +8894,21 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else else
{ {
/* Handle procs array. */ /* Handle procs array. */
if (((handle_grant_struct(PROC_PRIVILEGES_HASH, drop, user_from, user_to) && ! result) || if ((handle_grant_struct(PROC_PRIVILEGES_HASH, drop, user_from, user_to) || found)
found) && ! result) && ! result)
{ {
result= 1; /* At least one record/element found. */ result= 1; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */ /* If search is requested, we do not need to search further. */
if (! drop && ! user_to) if (search_only)
goto end; goto end;
} }
/* Handle funcs array. */ /* Handle funcs array. */
if (((handle_grant_struct(FUNC_PRIVILEGES_HASH, drop, user_from, user_to) && ! result) || if ((handle_grant_struct(FUNC_PRIVILEGES_HASH, drop, user_from, user_to) || found)
found) && ! result) && ! result)
{ {
result= 1; /* At least one record/element found. */ result= 1; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */ /* If search is requested, we do not need to search further. */
if (! drop && ! user_to) if (search_only)
goto end; goto end;
} }
} }
...@@ -8948,7 +8925,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, ...@@ -8948,7 +8925,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
{ {
result= 1; /* At least one record found. */ result= 1; /* At least one record found. */
/* If search is requested, we do not need to search further. */ /* If search is requested, we do not need to search further. */
if (! drop && ! user_to) if (search_only)
goto end; goto end;
} }
...@@ -8961,9 +8938,11 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, ...@@ -8961,9 +8938,11 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else else
{ {
/* Handle columns hash. */ /* Handle columns hash. */
if (((handle_grant_struct(COLUMN_PRIVILEGES_HASH, drop, user_from, user_to) && ! result) || if ((handle_grant_struct(COLUMN_PRIVILEGES_HASH, drop, user_from, user_to) || found)
found) && ! result) && ! result)
result= 1; /* At least one record/element found. */ result= 1; /* At least one record/element found. */
if (search_only)
goto end;
} }
} }
...@@ -8978,9 +8957,11 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, ...@@ -8978,9 +8957,11 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else else
{ {
/* Handle proxies_priv array. */ /* Handle proxies_priv array. */
if ((handle_grant_struct(PROXY_USERS_ACL, drop, user_from, user_to) && !result) || if ((handle_grant_struct(PROXY_USERS_ACL, drop, user_from, user_to) || found)
found) && ! result)
result= 1; /* At least one record/element found. */ result= 1; /* At least one record/element found. */
if (search_only)
goto end;
} }
} }
...@@ -8995,13 +8976,31 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, ...@@ -8995,13 +8976,31 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
else else
{ {
/* Handle acl_roles_mappings array */ /* Handle acl_roles_mappings array */
if ((handle_grant_struct(ROLES_MAPPINGS_HASH, drop, user_from, user_to) && !result) || if ((handle_grant_struct(ROLES_MAPPINGS_HASH, drop, user_from, user_to) || found)
found) && ! result)
result= 1; /* At least one record/element found */ result= 1; /* At least one record/element found */
if (search_only)
goto end;
} }
} }
end: /* Handle user table. */
if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0)
{
/* Handle of table failed, don't touch the in-memory array. */
result= -1;
}
else
{
enum enum_acl_lists what= handle_as_role ? ROLE_ACL : USER_ACL;
if (((handle_grant_struct(what, drop, user_from, user_to)) || found) && !result)
{
result= 1; /* At least one record/element found. */
DBUG_ASSERT(! search_only);
}
}
end:
DBUG_RETURN(result); DBUG_RETURN(result);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment