summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <cvicentiu@gmail.com>2013-10-18 06:47:49 -0700
committerSergei Golubchik <sergii@pisem.net>2013-10-18 06:47:49 -0700
commitbbc2771d242c6d91f1834b35e66924220f94e2d9 (patch)
tree379a85127a7032605d1ac7a1e60161869aa14265 /sql
parent1aedd4a5850d69d93abb2487122981c5eee2bbc2 (diff)
downloadmariadb-git-bbc2771d242c6d91f1834b35e66924220f94e2d9.tar.gz
SET ROLE now works recursively for table and column level privileges
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_acl.cc281
1 files changed, 196 insertions, 85 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index d2c920ff118..69e619c01b5 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1443,9 +1443,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
free_root(&temp_root, MYF(0));
end_read_record(&read_record_info);
- my_hash_iterate(&acl_roles,
- (my_hash_walk_action) acl_role_propagate_grants, NULL);
-
if (!initialized)
mysql_mutex_unlock(&acl_cache->lock);
@@ -2419,78 +2416,6 @@ my_bool acl_user_reset_grant(ACL_USER *user,
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)),
ACL_ROLE *role, void *context_data)
{
@@ -3904,6 +3829,12 @@ public:
{
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;
}
+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
{
@@ -3945,6 +3913,7 @@ public:
GRANT_TABLE(const char *h, const char *d,const char *u,
const char *t, ulong p, ulong c);
GRANT_TABLE (TABLE *form, TABLE *col_privs);
+ GRANT_TABLE(GRANT_TABLE *source, char *u);
~GRANT_TABLE();
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);
}
+/*
+ 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)
{
@@ -5611,6 +5595,11 @@ my_bool grant_reload(THD *thd)
return_val= 1;
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++;
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;
- DBUG_ASSERT (grant_table);
grant_table_role= grant->grant_table_role;
+ DBUG_ASSERT (grant_table || grant_table_role);
}
}
if (want_access)
{
- GRANT_COLUMN *grant_column=
- column_hash_search(grant_table, field_name,
- (uint) strlen(field_name));
- if (grant_column)
+ if (grant_table)
{
- using_column_privileges= TRUE;
- want_access&= ~grant_column->rights;
+ GRANT_COLUMN *grant_column=
+ 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)
{
- grant_column=
+ GRANT_COLUMN *grant_column=
column_hash_search(grant_table_role, field_name,
(uint) strlen(field_name));
if (grant_column)
@@ -6178,7 +6170,7 @@ bool check_grant_db(THD *thd, const char *db)
}
if (sctx->priv_role[0] &&
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]))
{
error= FALSE; /* Found role match */
@@ -7402,9 +7394,128 @@ static int modify_grant_table(TABLE *table, Field *host_field,
}
/*
- Handle the roles_mappings privilege table
+ 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
*/
static int handle_roles_mappings_table(TABLE *table, bool drop,
LEX_USER *user_from, LEX_USER *user_to)