mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
properly propagate privilege changes on DROP ROLE
This commit is contained in:
69
mysql-test/suite/roles/set_and_drop.result
Normal file
69
mysql-test/suite/roles/set_and_drop.result
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
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;
|
74
mysql-test/suite/roles/set_and_drop.test
Normal file
74
mysql-test/suite/roles/set_and_drop.test
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
--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;
|
101
sql/sql_acl.cc
101
sql/sql_acl.cc
@ -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,
|
|||||||
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. */
|
/* quickly search in-memory structures first */
|
||||||
result= -1;
|
if (handle_as_role && find_acl_role(user_from->user.str))
|
||||||
}
|
DBUG_RETURN(1); // found
|
||||||
else
|
|
||||||
{
|
if (!handle_as_role && find_user_exact(user_from->host.str, user_from->user.str))
|
||||||
if (handle_as_role)
|
DBUG_RETURN(1); // found
|
||||||
{
|
|
||||||
if ((handle_grant_struct(ROLE_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_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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user