mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
SET ROLE now works recursively for table and column level privileges
This commit is contained in:
committed by
Sergei Golubchik
parent
1aedd4a585
commit
bbc2771d24
61
mysql-test/r/acl_roles_set_role-table-column-priv.result
Normal file
61
mysql-test/r/acl_roles_set_role-table-column-priv.result
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
create user 'test_user'@'localhost';
|
||||||
|
create role test_role1;
|
||||||
|
create role test_role2;
|
||||||
|
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
|
||||||
|
'test_user',
|
||||||
|
'test_role1');
|
||||||
|
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('',
|
||||||
|
'test_role1',
|
||||||
|
'test_role2');
|
||||||
|
select user, host from mysql.user where user not like 'root';
|
||||||
|
user host
|
||||||
|
test_role1
|
||||||
|
test_role2
|
||||||
|
test_user localhost
|
||||||
|
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@'';
|
||||||
|
flush privileges;
|
||||||
|
select * from mysql.roles_mapping;
|
||||||
|
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
|
||||||
|
show grants;
|
||||||
|
Grants for test_user@localhost
|
||||||
|
GRANT USAGE ON *.* TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role1 TO 'test_user'@'localhost'
|
||||||
|
set role test_role1;
|
||||||
|
show grants;
|
||||||
|
Grants for test_user@localhost
|
||||||
|
GRANT SELECT (RoleFk) ON `mysql`.`roles_mapping` TO 'test_role2'
|
||||||
|
GRANT USAGE ON *.* TO 'test_role1'
|
||||||
|
GRANT USAGE ON *.* TO 'test_role2'
|
||||||
|
GRANT USAGE ON *.* TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role1 TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role2 TO 'test_role1'
|
||||||
|
select * from mysql.roles_mapping;
|
||||||
|
ERROR 42000: command denied to user 'test_user'@'localhost' for table 'roles_mapping'
|
||||||
|
select RoleFk from mysql.roles_mapping;
|
||||||
|
RoleFk
|
||||||
|
test_role1
|
||||||
|
test_role2
|
||||||
|
show grants;
|
||||||
|
Grants for test_user@localhost
|
||||||
|
GRANT SELECT (RoleFk) ON `mysql`.`roles_mapping` TO 'test_role2'
|
||||||
|
GRANT USAGE ON *.* TO 'test_role1'
|
||||||
|
GRANT USAGE ON *.* TO 'test_role2'
|
||||||
|
GRANT USAGE ON *.* TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role1 TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role2 TO 'test_role1'
|
||||||
|
use mysql;
|
||||||
|
set role none;
|
||||||
|
select RoleFk from mysql.roles_mapping;
|
||||||
|
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
|
||||||
|
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@'';
|
||||||
|
delete from mysql.user where user like'test_%';
|
||||||
|
delete from mysql.roles_mapping where RoleFk like 'test%';
|
||||||
|
flush privileges;
|
59
mysql-test/r/acl_roles_set_role-table-simple.result
Normal file
59
mysql-test/r/acl_roles_set_role-table-simple.result
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
create user 'test_user'@'localhost';
|
||||||
|
create role test_role1;
|
||||||
|
create role test_role2;
|
||||||
|
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
|
||||||
|
'test_user',
|
||||||
|
'test_role1');
|
||||||
|
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('',
|
||||||
|
'test_role1',
|
||||||
|
'test_role2');
|
||||||
|
select user, host from mysql.user where user not like 'root';
|
||||||
|
user host
|
||||||
|
test_role1
|
||||||
|
test_role2
|
||||||
|
test_user localhost
|
||||||
|
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@'';
|
||||||
|
flush privileges;
|
||||||
|
select * from mysql.roles_mapping;
|
||||||
|
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
|
||||||
|
show grants;
|
||||||
|
Grants for test_user@localhost
|
||||||
|
GRANT USAGE ON *.* TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role1 TO 'test_user'@'localhost'
|
||||||
|
set role test_role1;
|
||||||
|
show grants;
|
||||||
|
Grants for test_user@localhost
|
||||||
|
GRANT SELECT ON `mysql`.`roles_mapping` TO 'test_role2'
|
||||||
|
GRANT USAGE ON *.* TO 'test_role1'
|
||||||
|
GRANT USAGE ON *.* TO 'test_role2'
|
||||||
|
GRANT USAGE ON *.* TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role1 TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role2 TO 'test_role1'
|
||||||
|
select * from mysql.roles_mapping;
|
||||||
|
HostFk UserFk RoleFk
|
||||||
|
test_role1 test_role2
|
||||||
|
localhost test_user test_role1
|
||||||
|
show grants;
|
||||||
|
Grants for test_user@localhost
|
||||||
|
GRANT SELECT ON `mysql`.`roles_mapping` TO 'test_role2'
|
||||||
|
GRANT USAGE ON *.* TO 'test_role1'
|
||||||
|
GRANT USAGE ON *.* TO 'test_role2'
|
||||||
|
GRANT USAGE ON *.* TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role1 TO 'test_user'@'localhost'
|
||||||
|
GRANT test_role2 TO 'test_role1'
|
||||||
|
use mysql;
|
||||||
|
set role none;
|
||||||
|
select * from mysql.roles_mapping;
|
||||||
|
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
|
||||||
|
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@'';
|
||||||
|
delete from mysql.user where user like'test_%';
|
||||||
|
delete from mysql.roles_mapping where RoleFk like 'test%';
|
||||||
|
flush privileges;
|
57
mysql-test/t/acl_roles_set_role-table-column-priv.test
Normal file
57
mysql-test/t/acl_roles_set_role-table-column-priv.test
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
create user 'test_user'@'localhost';
|
||||||
|
create role test_role1;
|
||||||
|
create role test_role2;
|
||||||
|
|
||||||
|
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
|
||||||
|
'test_user',
|
||||||
|
'test_role1');
|
||||||
|
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('',
|
||||||
|
'test_role1',
|
||||||
|
'test_role2');
|
||||||
|
--sorted_result
|
||||||
|
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@'';
|
||||||
|
|
||||||
|
flush privileges;
|
||||||
|
|
||||||
|
change_user 'test_user';
|
||||||
|
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
select * from mysql.roles_mapping;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
show grants;
|
||||||
|
|
||||||
|
set role test_role1;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
show grants;
|
||||||
|
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
select * from mysql.roles_mapping;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
select RoleFk from mysql.roles_mapping;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
show grants;
|
||||||
|
|
||||||
|
use mysql;
|
||||||
|
|
||||||
|
set role none;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
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@'';
|
||||||
|
delete from mysql.user where user like'test_%';
|
||||||
|
delete from mysql.roles_mapping where RoleFk like 'test%';
|
||||||
|
|
||||||
|
flush privileges;
|
54
mysql-test/t/acl_roles_set_role-table-simple.test
Normal file
54
mysql-test/t/acl_roles_set_role-table-simple.test
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
create user 'test_user'@'localhost';
|
||||||
|
create role test_role1;
|
||||||
|
create role test_role2;
|
||||||
|
|
||||||
|
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
|
||||||
|
'test_user',
|
||||||
|
'test_role1');
|
||||||
|
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('',
|
||||||
|
'test_role1',
|
||||||
|
'test_role2');
|
||||||
|
--sorted_result
|
||||||
|
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@'';
|
||||||
|
|
||||||
|
flush privileges;
|
||||||
|
|
||||||
|
change_user 'test_user';
|
||||||
|
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
select * from mysql.roles_mapping;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
show grants;
|
||||||
|
|
||||||
|
set role test_role1;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
show grants;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
select * from mysql.roles_mapping;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
show grants;
|
||||||
|
|
||||||
|
use mysql;
|
||||||
|
|
||||||
|
set role none;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
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@'';
|
||||||
|
delete from mysql.user where user like'test_%';
|
||||||
|
delete from mysql.roles_mapping where RoleFk like 'test%';
|
||||||
|
|
||||||
|
flush privileges;
|
283
sql/sql_acl.cc
283
sql/sql_acl.cc
@ -1443,9 +1443,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
|
|||||||
free_root(&temp_root, MYF(0));
|
free_root(&temp_root, MYF(0));
|
||||||
end_read_record(&read_record_info);
|
end_read_record(&read_record_info);
|
||||||
|
|
||||||
my_hash_iterate(&acl_roles,
|
|
||||||
(my_hash_walk_action) acl_role_propagate_grants, NULL);
|
|
||||||
|
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
mysql_mutex_unlock(&acl_cache->lock);
|
mysql_mutex_unlock(&acl_cache->lock);
|
||||||
|
|
||||||
@ -2419,78 +2416,6 @@ my_bool acl_user_reset_grant(ACL_USER *user,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
The function merges access bits from a granted role to a grantee.
|
|
||||||
|
|
||||||
It creates data structures if they don't exist for the grantee.
|
|
||||||
This includes data structures related to database privileges, tables
|
|
||||||
privileges, column privileges, function and procedures privileges
|
|
||||||
*/
|
|
||||||
|
|
||||||
void merge_role_grant_privileges(ACL_ROLE *target, ACL_ROLE *source)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(source->flags & ROLE_GRANTS_FINAL);
|
|
||||||
|
|
||||||
/* Merge global access rights */
|
|
||||||
target->access|= source->access;
|
|
||||||
|
|
||||||
/* Merge database privileges */
|
|
||||||
DYNAMIC_ARRAY target_dbs, source_dbs; /* arrays of pointers to ACL_DB elements */
|
|
||||||
ACL_DB *target_db, *source_db; /* elements of the arrays */
|
|
||||||
|
|
||||||
(void) my_init_dynamic_array(&target_dbs,sizeof(ACL_DB *), 50, 100, MYF(0));
|
|
||||||
(void) my_init_dynamic_array(&source_dbs,sizeof(ACL_DB *), 50, 100, MYF(0));
|
|
||||||
|
|
||||||
/* get all acl_db elements for the source and the target */
|
|
||||||
for (uint i=0 ; i < acl_dbs.elements ; i++)
|
|
||||||
{
|
|
||||||
ACL_DB *acl_db= dynamic_element(&acl_dbs,i,ACL_DB*);
|
|
||||||
if (acl_db->user && !acl_db->host.hostname)
|
|
||||||
{
|
|
||||||
if (!strcmp(target->user.str, acl_db->user))
|
|
||||||
push_dynamic(&target_dbs, (uchar*)&acl_db);
|
|
||||||
if (!strcmp(source->user.str, acl_db->user))
|
|
||||||
push_dynamic(&source_dbs, (uchar*)&acl_db);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint i=0 ; i < source_dbs.elements; i++)
|
|
||||||
{
|
|
||||||
source_db= *dynamic_element(&source_dbs, i, ACL_DB **);
|
|
||||||
target_db= NULL;
|
|
||||||
for (uint j=0; j < target_dbs.elements; j++)
|
|
||||||
{
|
|
||||||
ACL_DB *acl_db= *dynamic_element(&target_dbs, i, ACL_DB **);
|
|
||||||
if (!strcmp(source_db->db, acl_db->db)) /* only need to compare DB here */
|
|
||||||
target_db= acl_db;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* acl_db element found for the target, only need to update acces bits */
|
|
||||||
if (target_db)
|
|
||||||
{
|
|
||||||
target_db->access|= source_db->access;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Need to create an acl_db element as this role inherits database
|
|
||||||
privileges
|
|
||||||
*/
|
|
||||||
acl_insert_db(target->user.str, "", source_db->db,
|
|
||||||
source_db->access, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete_dynamic(&source_dbs);
|
|
||||||
delete_dynamic(&target_dbs);
|
|
||||||
|
|
||||||
/* Merge table and column privileges */
|
|
||||||
|
|
||||||
|
|
||||||
/* Merge function and procedure privileges */
|
|
||||||
/* TODO */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void role_explore_create_list(ACL_ROLE *unused __attribute__((unused)),
|
static void role_explore_create_list(ACL_ROLE *unused __attribute__((unused)),
|
||||||
ACL_ROLE *role, void *context_data)
|
ACL_ROLE *role, void *context_data)
|
||||||
{
|
{
|
||||||
@ -3904,6 +3829,12 @@ public:
|
|||||||
{
|
{
|
||||||
column= (char*) memdup_root(&memex,c.ptr(), key_length=c.length());
|
column= (char*) memdup_root(&memex,c.ptr(), key_length=c.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GRANT_COLUMN(GRANT_COLUMN *source) : rights (source->rights), init_rights(0)
|
||||||
|
{
|
||||||
|
column= (char *) memdup_root(&memex, source->column,
|
||||||
|
key_length=source->key_length);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -3914,6 +3845,43 @@ static uchar* get_key_column(GRANT_COLUMN *buff, size_t *length,
|
|||||||
return (uchar*) buff->column;
|
return (uchar*) buff->column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void merge_grant_table_hash_columns(HASH *target, HASH *source)
|
||||||
|
{
|
||||||
|
MEM_ROOT *memex_ptr= &memex;
|
||||||
|
for (uint i=0 ; i < source->records ; i++)
|
||||||
|
{
|
||||||
|
GRANT_COLUMN *source_col = (GRANT_COLUMN *)my_hash_element(source, i);
|
||||||
|
GRANT_COLUMN *target_col = (GRANT_COLUMN *)
|
||||||
|
my_hash_search(target,
|
||||||
|
(uchar *)source_col->column,
|
||||||
|
source_col->key_length);
|
||||||
|
/* target has the column in the hashtable */
|
||||||
|
if (target_col)
|
||||||
|
{
|
||||||
|
target_col->rights|= source_col->rights;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GRANT_COLUMN *target_col = new (memex_ptr) GRANT_COLUMN(source_col);
|
||||||
|
my_hash_insert(target, (uchar *)target_col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* same as merge_grant_table_hash_columns, but without
|
||||||
|
the existing hash check */
|
||||||
|
static void copy_grant_table_hash_columns(HASH *target, HASH *source)
|
||||||
|
{
|
||||||
|
|
||||||
|
MEM_ROOT *memex_ptr= &memex;
|
||||||
|
for (uint i=0 ; i < source->records ; i++)
|
||||||
|
{
|
||||||
|
GRANT_COLUMN *source_col = (GRANT_COLUMN *)my_hash_element(source, i);
|
||||||
|
GRANT_COLUMN *target_col = new (memex_ptr) GRANT_COLUMN(source_col);
|
||||||
|
my_hash_insert(target, (uchar *)target_col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class GRANT_NAME :public Sql_alloc
|
class GRANT_NAME :public Sql_alloc
|
||||||
{
|
{
|
||||||
@ -3945,6 +3913,7 @@ public:
|
|||||||
GRANT_TABLE(const char *h, const char *d,const char *u,
|
GRANT_TABLE(const char *h, const char *d,const char *u,
|
||||||
const char *t, ulong p, ulong c);
|
const char *t, ulong p, ulong c);
|
||||||
GRANT_TABLE (TABLE *form, TABLE *col_privs);
|
GRANT_TABLE (TABLE *form, TABLE *col_privs);
|
||||||
|
GRANT_TABLE(GRANT_TABLE *source, char *u);
|
||||||
~GRANT_TABLE();
|
~GRANT_TABLE();
|
||||||
bool ok() { return privs != 0 || cols != 0; }
|
bool ok() { return privs != 0 || cols != 0; }
|
||||||
};
|
};
|
||||||
@ -3990,6 +3959,21 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u,
|
|||||||
0,0,0, (my_hash_get_key) get_key_column,0,0);
|
0,0,0, (my_hash_get_key) get_key_column,0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
create a new GRANT_TABLE entry for role inheritance. init_* fields are set
|
||||||
|
to 0
|
||||||
|
*/
|
||||||
|
GRANT_TABLE::GRANT_TABLE(GRANT_TABLE *source, char *u)
|
||||||
|
:GRANT_NAME("", source->db, u, source->tname,
|
||||||
|
source->privs, FALSE), cols(source->cols)
|
||||||
|
{
|
||||||
|
this->init_cols= 0;
|
||||||
|
this->init_privs= 0;
|
||||||
|
(void) my_hash_init2(&hash_columns,4,system_charset_info,
|
||||||
|
0,0,0, (my_hash_get_key) get_key_column,0,0);
|
||||||
|
copy_grant_table_hash_columns(&hash_columns, &source->hash_columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GRANT_NAME::GRANT_NAME(TABLE *form, bool is_routine)
|
GRANT_NAME::GRANT_NAME(TABLE *form, bool is_routine)
|
||||||
{
|
{
|
||||||
@ -5611,6 +5595,11 @@ my_bool grant_reload(THD *thd)
|
|||||||
return_val= 1;
|
return_val= 1;
|
||||||
|
|
||||||
mysql_rwlock_wrlock(&LOCK_grant);
|
mysql_rwlock_wrlock(&LOCK_grant);
|
||||||
|
mysql_mutex_lock(&acl_cache->lock);
|
||||||
|
my_hash_iterate(&acl_roles,
|
||||||
|
(my_hash_walk_action) acl_role_propagate_grants, NULL);
|
||||||
|
mysql_mutex_unlock(&acl_cache->lock);
|
||||||
|
|
||||||
grant_version++;
|
grant_version++;
|
||||||
mysql_rwlock_unlock(&LOCK_grant);
|
mysql_rwlock_unlock(&LOCK_grant);
|
||||||
|
|
||||||
@ -6044,24 +6033,27 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
grant_table= grant->grant_table_user;
|
grant_table= grant->grant_table_user;
|
||||||
DBUG_ASSERT (grant_table);
|
|
||||||
grant_table_role= grant->grant_table_role;
|
grant_table_role= grant->grant_table_role;
|
||||||
|
DBUG_ASSERT (grant_table || grant_table_role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (want_access)
|
if (want_access)
|
||||||
{
|
{
|
||||||
GRANT_COLUMN *grant_column=
|
if (grant_table)
|
||||||
column_hash_search(grant_table, field_name,
|
|
||||||
(uint) strlen(field_name));
|
|
||||||
if (grant_column)
|
|
||||||
{
|
{
|
||||||
using_column_privileges= TRUE;
|
GRANT_COLUMN *grant_column=
|
||||||
want_access&= ~grant_column->rights;
|
column_hash_search(grant_table, field_name,
|
||||||
|
(uint) strlen(field_name));
|
||||||
|
if (grant_column)
|
||||||
|
{
|
||||||
|
using_column_privileges= TRUE;
|
||||||
|
want_access&= ~grant_column->rights;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (grant_table_role)
|
if (grant_table_role)
|
||||||
{
|
{
|
||||||
grant_column=
|
GRANT_COLUMN *grant_column=
|
||||||
column_hash_search(grant_table_role, field_name,
|
column_hash_search(grant_table_role, field_name,
|
||||||
(uint) strlen(field_name));
|
(uint) strlen(field_name));
|
||||||
if (grant_column)
|
if (grant_column)
|
||||||
@ -6178,7 +6170,7 @@ bool check_grant_db(THD *thd, const char *db)
|
|||||||
}
|
}
|
||||||
if (sctx->priv_role[0] &&
|
if (sctx->priv_role[0] &&
|
||||||
len2 < grant_table->key_length &&
|
len2 < grant_table->key_length &&
|
||||||
!memcmp(grant_table->hash_key,helping,len) &&
|
!memcmp(grant_table->hash_key,helping2,len) &&
|
||||||
(!grant_table->host.hostname || !grant_table->host.hostname[0]))
|
(!grant_table->host.hostname || !grant_table->host.hostname[0]))
|
||||||
{
|
{
|
||||||
error= FALSE; /* Found role match */
|
error= FALSE; /* Found role match */
|
||||||
@ -7401,10 +7393,129 @@ static int modify_grant_table(TABLE *table, Field *host_field,
|
|||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The function merges access bits from a granted role to a grantee.
|
||||||
|
|
||||||
|
It creates data structures if they don't exist for the grantee.
|
||||||
|
This includes data structures related to database privileges, tables
|
||||||
|
privileges, column privileges, function and procedures privileges
|
||||||
|
*/
|
||||||
|
|
||||||
|
void merge_role_grant_privileges(ACL_ROLE *target, ACL_ROLE *source)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(source->flags & ROLE_GRANTS_FINAL);
|
||||||
|
|
||||||
|
/* Merge global access rights */
|
||||||
|
target->access|= source->access;
|
||||||
|
|
||||||
|
/* Merge database privileges */
|
||||||
|
DYNAMIC_ARRAY target_objs, source_objs; /* arrays of pointers to priv objects */
|
||||||
|
|
||||||
|
/* elements of the arrays */
|
||||||
|
ACL_DB *target_db, *source_db;
|
||||||
|
GRANT_TABLE *target_table, *source_table;
|
||||||
|
MEM_ROOT *memex_ptr = &memex;
|
||||||
|
|
||||||
|
(void) my_init_dynamic_array(&target_objs,sizeof(void *), 50, 100, MYF(0));
|
||||||
|
(void) my_init_dynamic_array(&source_objs,sizeof(void *), 50, 100, MYF(0));
|
||||||
|
|
||||||
|
/* get all acl_db elements for the source and the target */
|
||||||
|
for (uint i=0 ; i < acl_dbs.elements ; i++)
|
||||||
|
{
|
||||||
|
ACL_DB *acl_db= dynamic_element(&acl_dbs,i,ACL_DB*);
|
||||||
|
if (acl_db->user && (!acl_db->host.hostname || !acl_db->host.hostname[0]))
|
||||||
|
{
|
||||||
|
if (!strcmp(target->user.str, acl_db->user))
|
||||||
|
push_dynamic(&target_objs, (uchar*)&acl_db);
|
||||||
|
if (!strcmp(source->user.str, acl_db->user))
|
||||||
|
push_dynamic(&source_objs, (uchar*)&acl_db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i=0 ; i < source_objs.elements; i++)
|
||||||
|
{
|
||||||
|
source_db= (ACL_DB *)*dynamic_element(&source_objs, i, void **);
|
||||||
|
target_db= NULL;
|
||||||
|
for (uint j=0; j < target_objs.elements; j++)
|
||||||
|
{
|
||||||
|
ACL_DB *acl_db= (ACL_DB *)*dynamic_element(&target_objs, i, void **);
|
||||||
|
if (!strcmp(source_db->db, acl_db->db)) /* only need to compare DB here */
|
||||||
|
target_db= acl_db;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acl_db element found for the target, only need to update acces bits */
|
||||||
|
if (target_db)
|
||||||
|
{
|
||||||
|
target_db->access|= source_db->access;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Need to create an acl_db element as this role inherits database
|
||||||
|
privileges
|
||||||
|
*/
|
||||||
|
acl_insert_db(target->user.str, "", source_db->db,
|
||||||
|
source_db->access, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_dynamic(&source_objs);
|
||||||
|
reset_dynamic(&target_objs);
|
||||||
|
|
||||||
|
/* Merge table and column privileges */
|
||||||
|
for (uint i=0 ; i < column_priv_hash.records ; i++)
|
||||||
|
{
|
||||||
|
GRANT_TABLE *grant_table= (GRANT_TABLE *)
|
||||||
|
my_hash_element(&column_priv_hash, i);
|
||||||
|
if (grant_table->user && (!grant_table->host.hostname ||
|
||||||
|
!grant_table->host.hostname[0]))
|
||||||
|
{
|
||||||
|
if (!strcmp(target->user.str, grant_table->user))
|
||||||
|
push_dynamic(&target_objs, (uchar*)&grant_table);
|
||||||
|
if (!strcmp(source->user.str, grant_table->user))
|
||||||
|
push_dynamic(&source_objs, (uchar*)&grant_table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (uint i=0 ; i < source_objs.elements; i++)
|
||||||
|
{
|
||||||
|
source_table= (GRANT_TABLE *)*dynamic_element(&source_objs, i, void **);
|
||||||
|
target_table= NULL;
|
||||||
|
for (uint j=0; j < target_objs.elements; j++)
|
||||||
|
{
|
||||||
|
GRANT_TABLE *grant_table= (GRANT_TABLE *)*dynamic_element(&target_objs, i,
|
||||||
|
void **);
|
||||||
|
if (!strcmp(source_table->db, grant_table->db) &&
|
||||||
|
!strcmp(source_table->tname, grant_table->tname))
|
||||||
|
target_table= grant_table;;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_table)
|
||||||
|
{
|
||||||
|
target_table->privs|= source_table->privs;
|
||||||
|
target_table->cols|= source_table->cols;
|
||||||
|
merge_grant_table_hash_columns(&target_table->hash_columns,
|
||||||
|
&source_table->hash_columns);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
target_table= new (memex_ptr) GRANT_TABLE(source_table, target->user.str);
|
||||||
|
my_hash_insert(&column_priv_hash, (uchar *) target_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge function and procedure privileges */
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
delete_dynamic(&source_objs);
|
||||||
|
delete_dynamic(&target_objs);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Handle the roles_mappings privilege table
|
Handle the roles_mappings privilege table
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
static int handle_roles_mappings_table(TABLE *table, bool drop,
|
static int handle_roles_mappings_table(TABLE *table, bool drop,
|
||||||
LEX_USER *user_from, LEX_USER *user_to)
|
LEX_USER *user_from, LEX_USER *user_to)
|
||||||
|
Reference in New Issue
Block a user