Commit 353576f3 authored by Sergei Golubchik's avatar Sergei Golubchik

GRANT/REVOKE should specify role name as 'role' not as 'role'@'%'

parent 06e16b8c
create user 'test_user'@'localhost';
create user 'test_role1'@'';
create user 'test_role2'@'';
update mysql.user set is_role='Y' where user='test_role1';
update mysql.user set is_role='Y' where user='test_role2';
create role test_role1;
create role test_role2;
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
......@@ -27,7 +25,7 @@ select user, host from mysql.db;
user host
%
%
grant select on mysql.* to test_role2@'';
grant select on mysql.* to test_role2;
flush privileges;
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
......@@ -59,7 +57,7 @@ HostFk UserFk RoleFk
localhost test_user test_role1
localhost test_user test_role2
drop user 'test_user'@'localhost';
revoke select on mysql.* from test_role2@'';
revoke select on mysql.* from test_role2;
delete from mysql.user where user='test_role1';
delete from mysql.user where user='test_role2';
delete from mysql.roles_mapping where RoleFk='test_role1';
......
create user 'test_user'@'localhost';
create user 'test_role1'@'';
update mysql.user set is_role='Y' where user='test_role1';
create role test_role1;
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
......@@ -12,9 +11,9 @@ select * from mysql.roles_mapping;
HostFk UserFk RoleFk
localhost test_user test_role1
flush privileges;
grant select on mysql.* to test_role1@'';
grant insert, delete on mysql.roles_mapping to test_role1@'';
grant reload on *.* to test_role1@'';
grant select on mysql.* to test_role1;
grant insert, delete on mysql.roles_mapping to test_role1;
grant reload on *.* to test_role1;
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
select current_user(), current_role();
......@@ -51,8 +50,8 @@ ERROR 42000: INSERT command denied to user 'test_user'@'localhost' for table 'ro
delete from mysql.roles_mapping where RoleFk='test_role2';
ERROR 42000: DELETE command denied to user 'test_user'@'localhost' for table 'roles_mapping'
drop user 'test_user'@'localhost';
revoke select on mysql.* from test_role1@'';
revoke insert, delete on mysql.roles_mapping from test_role1@'';
delete from mysql.user where user='test_role1';
revoke select on mysql.* from test_role1;
revoke insert, delete on mysql.roles_mapping from test_role1;
drop role test_role1;
delete from mysql.roles_mapping where RoleFk='test_role1';
flush privileges;
......@@ -29,9 +29,9 @@ create procedure mysql.test_proc (OUT param1 INT)
begin
select COUNT(*) into param1 from mysql.roles_mapping;
end|
grant execute on function mysql.test_func to test_role2@'';
grant execute on procedure mysql.test_proc to test_role2@'';
grant execute on mysql.* to test_role3@'';
grant execute on function mysql.test_func to test_role2;
grant execute on procedure mysql.test_proc to test_role2;
grant execute on mysql.* to test_role3;
flush privileges;
show grants;
Grants for test_user@localhost
......@@ -97,9 +97,9 @@ SELECT test_func('AABBCCDD');
test_func('AABBCCDD')
Test string: AABBCCDD
drop user 'test_user'@'localhost';
revoke execute on function mysql.test_func from test_role2@'';
revoke execute on procedure mysql.test_proc from test_role2@'';
revoke execute on mysql.* from test_role3@'';
revoke execute on function mysql.test_func from test_role2;
revoke execute on procedure mysql.test_proc from test_role2;
revoke execute on mysql.* from test_role3;
delete from mysql.user where user like'test_%';
delete from mysql.roles_mapping where RoleFk like 'test%';
drop function mysql.test_func;
......
......@@ -16,7 +16,7 @@ select * from mysql.roles_mapping;
HostFk UserFk RoleFk
test_role1 test_role2
localhost test_user test_role1
grant select (RoleFk) on mysql.roles_mapping to test_role2@'';
grant select (RoleFk) on mysql.roles_mapping to test_role2;
flush privileges;
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
......@@ -64,7 +64,7 @@ drop user 'test_user'@'localhost';
select * from mysql.tables_priv;
Host Db User Table_name Grantor Timestamp Table_priv Column_priv
mysql test_role2 roles_mapping root@localhost 0000-00-00 00:00:00 Select
revoke select on mysql.roles_mapping from test_role2@'';
revoke select on mysql.roles_mapping from test_role2;
delete from mysql.user where user like'test_%';
delete from mysql.roles_mapping where RoleFk like 'test%';
flush privileges;
......@@ -16,7 +16,7 @@ select * from mysql.roles_mapping;
HostFk UserFk RoleFk
test_role1 test_role2
localhost test_user test_role1
grant select on mysql.roles_mapping to test_role2@'';
grant select on mysql.roles_mapping to test_role2;
flush privileges;
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
......@@ -62,7 +62,7 @@ drop user 'test_user'@'localhost';
select * from mysql.tables_priv;
Host Db User Table_name Grantor Timestamp Table_priv Column_priv
mysql test_role2 roles_mapping root@localhost 0000-00-00 00:00:00 Select
revoke select on mysql.roles_mapping from test_role2@'';
revoke select on mysql.roles_mapping from test_role2;
delete from mysql.user where user like'test_%';
delete from mysql.roles_mapping where RoleFk like 'test%';
flush privileges;
create user 'test_user'@'localhost';
create user 'test_role1'@'';
create user 'test_role2'@'';
update mysql.user set is_role='Y' where user='test_role1';
update mysql.user set is_role='Y' where user='test_role2';
create role test_role1;
create role test_role2;
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
......@@ -27,7 +25,7 @@ select user, host from mysql.db;
user host
%
%
grant select on mysql.* to test_role2@'';
grant select on mysql.* to test_role2;
flush privileges;
show grants;
Grants for test_user@localhost
......@@ -127,9 +125,9 @@ Grants for test_role2
GRANT SELECT ON `mysql`.* TO 'test_role2'
GRANT USAGE ON *.* TO 'test_role2'
drop user 'test_user'@'localhost';
revoke select on mysql.* from test_role2@'';
delete from mysql.user where user='test_role1';
delete from mysql.user where user='test_role2';
revoke select on mysql.* from test_role2;
drop role test_role1;
drop role test_role2;
delete from mysql.roles_mapping where RoleFk='test_role1';
delete from mysql.roles_mapping where RoleFk='test_role2';
flush privileges;
#create a user with no privileges
create user 'test_user'@'localhost';
create user 'test_role1'@'';
create user 'test_role2'@'';
create role test_role1;
create role test_role2;
update mysql.user set is_role='Y' where user='test_role1';
update mysql.user set is_role='Y' where user='test_role2';
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
......@@ -23,7 +21,7 @@ flush privileges;
--sorted_result
select user, host from mysql.db;
grant select on mysql.* to test_role2@'';
grant select on mysql.* to test_role2;
flush privileges;
change_user 'test_user';
......@@ -47,7 +45,7 @@ select * from mysql.roles_mapping;
change_user 'root';
drop user 'test_user'@'localhost';
revoke select on mysql.* from test_role2@'';
revoke select on mysql.* from test_role2;
delete from mysql.user where user='test_role1';
delete from mysql.user where user='test_role2';
delete from mysql.roles_mapping where RoleFk='test_role1';
......
#create a user with no privileges
create user 'test_user'@'localhost';
create user 'test_role1'@'';
create role test_role1;
update mysql.user set is_role='Y' where user='test_role1';
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
......@@ -12,10 +11,10 @@ select user, host from mysql.user where user not like 'root';
select * from mysql.roles_mapping;
flush privileges;
grant select on mysql.* to test_role1@'';
grant insert, delete on mysql.roles_mapping to test_role1@'';
grant select on mysql.* to test_role1;
grant insert, delete on mysql.roles_mapping to test_role1;
grant reload on *.* to test_role1@'';
grant reload on *.* to test_role1;
change_user 'test_user';
......@@ -53,9 +52,9 @@ delete from mysql.roles_mapping where RoleFk='test_role2';
change_user 'root';
drop user 'test_user'@'localhost';
revoke select on mysql.* from test_role1@'';
revoke insert, delete on mysql.roles_mapping from test_role1@'';
delete from mysql.user where user='test_role1';
revoke select on mysql.* from test_role1;
revoke insert, delete on mysql.roles_mapping from test_role1;
drop role test_role1;
delete from mysql.roles_mapping where RoleFk='test_role1';
flush privileges;
......@@ -31,10 +31,10 @@ end|
delimiter ;|
grant execute on function mysql.test_func to test_role2@'';
grant execute on procedure mysql.test_proc to test_role2@'';
grant execute on function mysql.test_func to test_role2;
grant execute on procedure mysql.test_proc to test_role2;
grant execute on mysql.* to test_role3@'';
grant execute on mysql.* to test_role3;
flush privileges;
......@@ -78,9 +78,9 @@ SELECT test_func('AABBCCDD');
change_user 'root';
drop user 'test_user'@'localhost';
revoke execute on function mysql.test_func from test_role2@'';
revoke execute on procedure mysql.test_proc from test_role2@'';
revoke execute on mysql.* from test_role3@'';
revoke execute on function mysql.test_func from test_role2;
revoke execute on procedure mysql.test_proc from test_role2;
revoke execute on mysql.* from test_role3;
delete from mysql.user where user like'test_%';
delete from mysql.roles_mapping where RoleFk like 'test%';
drop function mysql.test_func;
......
......@@ -13,7 +13,7 @@ select user, host from mysql.user where user not like 'root';
--sorted_result
select * from mysql.roles_mapping;
grant select (RoleFk) on mysql.roles_mapping to test_role2@'';
grant select (RoleFk) on mysql.roles_mapping to test_role2;
flush privileges;
......@@ -53,7 +53,7 @@ select RoleFk from mysql.roles_mapping;
change_user 'root';
drop user 'test_user'@'localhost';
select * from mysql.tables_priv;
revoke select on mysql.roles_mapping from test_role2@'';
revoke select on mysql.roles_mapping from test_role2;
delete from mysql.user where user like'test_%';
delete from mysql.roles_mapping where RoleFk like 'test%';
......
......@@ -13,7 +13,7 @@ select user, host from mysql.user where user not like 'root';
--sorted_result
select * from mysql.roles_mapping;
grant select on mysql.roles_mapping to test_role2@'';
grant select on mysql.roles_mapping to test_role2;
flush privileges;
......@@ -50,7 +50,7 @@ select * from mysql.roles_mapping;
change_user 'root';
drop user 'test_user'@'localhost';
select * from mysql.tables_priv;
revoke select on mysql.roles_mapping from test_role2@'';
revoke select on mysql.roles_mapping from test_role2;
delete from mysql.user where user like'test_%';
delete from mysql.roles_mapping where RoleFk like 'test%';
......
#create a user with no privileges
create user 'test_user'@'localhost';
create user 'test_role1'@'';
create user 'test_role2'@'';
create role test_role1;
create role test_role2;
update mysql.user set is_role='Y' where user='test_role1';
update mysql.user set is_role='Y' where user='test_role2';
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
......@@ -23,7 +21,7 @@ flush privileges;
--sorted_result
select user, host from mysql.db;
grant select on mysql.* to test_role2@'';
grant select on mysql.* to test_role2;
flush privileges;
change_user 'test_user';
......@@ -77,9 +75,9 @@ show grants for CURRENT_ROLE();
change_user 'root';
drop user 'test_user'@'localhost';
revoke select on mysql.* from test_role2@'';
delete from mysql.user where user='test_role1';
delete from mysql.user where user='test_role2';
revoke select on mysql.* from test_role2;
drop role test_role1;
drop role test_role2;
delete from mysql.roles_mapping where RoleFk='test_role1';
delete from mysql.roles_mapping where RoleFk='test_role2';
flush privileges;
......@@ -4708,6 +4708,26 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
}
/*
A user name specified without a host can be either a
username@% (where '@%' is added automatically by the parser)
or a role name. Treat it as a role, if such a role exists.
*/
static ACL_ROLE *find_and_mark_as_role(LEX_USER *user)
{
if (user->host.str == host_not_specified.str)
{
ACL_ROLE *role= find_acl_role(user->user.str);
if (role)
{
user->host= empty_lex_str;
return role;
}
}
return NULL;
}
/*
Store table level and column level grants in the privilege tables
......@@ -4879,6 +4899,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
result= TRUE;
continue;
}
find_and_mark_as_role(Str);
/* Create user if needed */
error=replace_user_table(thd, tables[0].table, *Str,
0, revoke_grant, create_new_users,
......@@ -5085,6 +5106,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
result= TRUE;
continue;
}
find_and_mark_as_role(Str);
/* Create user if needed */
error=replace_user_table(thd, tables[0].table, *Str,
0, revoke_grant, create_new_users,
......@@ -5161,6 +5183,7 @@ static void append_user(String *str, const char *u, const char *h,
str->append('\'');
}
bool mysql_grant_role(THD *thd, List <LEX_USER> &list)
{
DBUG_ENTER("mysql_grant_role");
......@@ -5175,7 +5198,6 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list)
char *rolename;
char *username;
char *hostname;
bool handle_as_role;
ACL_ROLE *role, *role_as_user;
List_iterator <LEX_USER> user_list(list);
......@@ -5206,11 +5228,10 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list)
while ((user= user_list++))
{
handle_as_role= FALSE;
role_as_user= NULL;
/* current_role is treated slightly different */
if (user->user.str == current_role.str)
{
handle_as_role= TRUE;
/* current_role is NONE */
if (!thd->security_ctx->priv_role[0])
{
......@@ -5236,21 +5257,13 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list)
}
else
{
role_as_user= find_and_mark_as_role(user);
username= user->user.str;
hostname= user->host.str;
if (user->host.str == host_not_specified.str)
{
if ((role_as_user= find_acl_role(username)))
{
handle_as_role= TRUE;
hostname= (char *)"";
}
}
}
ROLE_GRANT_PAIR *mapping= (ROLE_GRANT_PAIR *)
alloc_root(&mem,
sizeof(ROLE_GRANT_PAIR));
alloc_root(&mem, sizeof(ROLE_GRANT_PAIR));
/* TODO write into roles_mapping table */
init_role_grant_pair(&mem, mapping,
......@@ -5258,7 +5271,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list)
int res= add_role_user_mapping(mapping);
if (res == -1)
{
append_user(&wrong_users, username, hostname, handle_as_role);
append_user(&wrong_users, username, hostname, role_as_user != NULL);
result= 1;
continue;
}
......@@ -5267,7 +5280,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list)
Check if this grant would cause a cycle. It only needs to be run
if we're granting a role to a role
*/
if (handle_as_role &&
if (role_as_user &&
traverse_role_graph(role, NULL, NULL, NULL, role_explore_detect_cycle,
NULL) == 2)
{
......@@ -5277,7 +5290,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list)
}
/* only need to propagate grants when granting a role to a role */
if (handle_as_role)
if (role_as_user)
{
acl_update_role_entry(role_as_user, role_as_user->initial_role_access);
}
......@@ -5392,6 +5405,9 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
*/
if (tmp_Str->user.str == current_user.str && tmp_Str->password.str)
Str->password= tmp_Str->password;
find_and_mark_as_role(Str);
if (replace_user_table(thd, tables[0].table, *Str,
(!db ? rights : 0), revoke_grant, create_new_users,
test(thd->variables.sql_mode &
......@@ -6694,8 +6710,6 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
ACL_ROLE *acl_role= NULL;
char buff[1024];
Protocol *protocol= thd->protocol;
bool print_user_entry= FALSE;
bool print_role_entry= FALSE;
char *username= NULL;
char *hostname= NULL;
char *rolename= NULL;
......@@ -6710,51 +6724,41 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
mysql_rwlock_rdlock(&LOCK_grant);
mysql_mutex_lock(&acl_cache->lock);
if (lex_user->user.str == current_user.str ||
lex_user->user.str == current_role.str ||
lex_user->user.str == current_user_and_current_role.str)
{
username= thd->security_ctx->priv_user;
hostname= thd->security_ctx->priv_host;
rolename= thd->security_ctx->priv_role;
}
if (lex_user->user.str == current_user.str)
{
print_user_entry= TRUE;
username= thd->security_ctx->priv_user;
hostname= thd->security_ctx->priv_host;
}
else if (lex_user->user.str == current_role.str)
{
print_role_entry= TRUE;
rolename= thd->security_ctx->priv_role;
}
else if (lex_user->user.str == current_user_and_current_role.str)
{
print_user_entry= TRUE;
print_role_entry= TRUE;
username= thd->security_ctx->priv_user;
hostname= thd->security_ctx->priv_host;
rolename= thd->security_ctx->priv_role;
}
else
{
/* this lex_user could represent a role */
if (lex_user->host.str == host_not_specified.str &&
find_acl_role(lex_user->user.str))
if (find_and_mark_as_role(lex_user))
{
rolename= lex_user->user.str;
hostname= (char *)"";
print_role_entry= TRUE;
}
else
{
username= lex_user->user.str;
hostname= lex_user->host.str;
print_user_entry= TRUE;
}
}
DBUG_ASSERT(rolename || username);
Item_string *field=new Item_string("",0,&my_charset_latin1);
List<Item> field_list;
field->name=buff;
field->max_length=1024;
if (print_user_entry == FALSE)
if (!username)
strxmov(buff,"Grants for ",rolename, NullS);
else
strxmov(buff,"Grants for ",username,"@",hostname, NullS);
......@@ -6768,7 +6772,7 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
DBUG_RETURN(TRUE);
}
if (print_user_entry)
if (username)
{
acl_user= find_user_no_anon(hostname, username, TRUE);
if (!acl_user)
......@@ -6831,7 +6835,7 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
}
}
if (print_role_entry)
if (rolename)
{
acl_role= find_acl_role(rolename);
if (acl_role)
......@@ -6862,7 +6866,8 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
mysql_mutex_unlock(&acl_cache->lock);
mysql_rwlock_unlock(&LOCK_grant);
my_error(ER_NONEXISTING_GRANT, MYF(0),
username, hostname);
thd->security_ctx->priv_user,
thd->security_ctx->priv_host);
DBUG_RETURN(TRUE);
}
}
......
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