diff options
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r-- | sql/sql_acl.cc | 85 |
1 files changed, 50 insertions, 35 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d4d69345689..becf519901a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -5394,7 +5394,7 @@ GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u, GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, const char *t, privilege_t p, privilege_t c) - :GRANT_NAME(h,d,u,t,p, FALSE), cols(c), init_cols(NO_ACL) + :GRANT_NAME(h,d,u,t,p, FALSE), cols(c), init_cols(c) { init_hash(); } @@ -6185,6 +6185,7 @@ static int count_subgraph_nodes(ACL_ROLE *role, ACL_ROLE *grantee, void *context } static int merge_role_privileges(ACL_ROLE *, ACL_ROLE *, void *); +static bool merge_one_role_privileges(ACL_ROLE *grantee, PRIVS_TO_MERGE what); /** rebuild privileges of all affected roles @@ -6204,6 +6205,11 @@ static void propagate_role_grants(ACL_ROLE *role, PRIVS_TO_MERGE data= { what, db, name }; /* + Before updating grants to roles that inherit from this role, ensure that + the effective grants on this role are up-to-date from *its* granted roles. + */ + merge_one_role_privileges(role, data); + /* Changing privileges of a role causes all other roles that had this role granted to them to have their rights invalidated. @@ -6651,7 +6657,6 @@ static int table_name_sort(GRANT_TABLE * const *tbl1, GRANT_TABLE * const *tbl2) */ static int update_role_columns(GRANT_TABLE *merged, GRANT_TABLE **cur, GRANT_TABLE **last) - { privilege_t rights __attribute__((unused)) (NO_ACL); int changed= 0; @@ -7002,11 +7007,12 @@ static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)), return !changed; // don't recurse into the subgraph if privs didn't change } -static bool merge_one_role_privileges(ACL_ROLE *grantee) +static +bool merge_one_role_privileges(ACL_ROLE *grantee, + PRIVS_TO_MERGE what) { - PRIVS_TO_MERGE data= { PRIVS_TO_MERGE::ALL, 0, 0 }; grantee->counter= 1; - return merge_role_privileges(0, grantee, &data); + return merge_role_privileges(0, grantee, &what); } /***************************************************************** @@ -7197,15 +7203,15 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, /* Find/create cached table grant */ grant_table= table_hash_search(Str->host.str, NullS, db_name, - Str->user.str, table_name, 1); + Str->user.str, table_name, 1); if (!grant_table) { if (revoke_grant) { - my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0), + my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0), Str->user.str, Str->host.str, table_list->table_name.str); - result= TRUE; - continue; + result= TRUE; + continue; } grant_table= new (&grant_memroot) GRANT_TABLE(Str->host.str, db_name, Str->user.str, table_name, @@ -7214,8 +7220,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!grant_table || column_priv_insert(grant_table)) { - result= TRUE; /* purecov: deadcode */ - continue; /* purecov: deadcode */ + result= TRUE; /* purecov: deadcode */ + continue; /* purecov: deadcode */ } } @@ -7229,11 +7235,15 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, /* Fix old grants */ while ((column = column_iter++)) { - grant_column = column_hash_search(grant_table, - column->column.ptr(), - column->column.length()); - if (grant_column) - grant_column->rights&= ~(column->rights | rights); + grant_column = column_hash_search(grant_table, + column->column.ptr(), + column->column.length()); + if (grant_column) + { + grant_column->init_rights&= ~(column->rights | rights); + // If this is a role, rights will need to be reconstructed. + grant_column->rights= grant_column->init_rights; + } } /* scan trough all columns to get new column grant */ column_priv= NO_ACL; @@ -7241,13 +7251,14 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, { grant_column= (GRANT_COLUMN*) my_hash_element(&grant_table->hash_columns, idx); - grant_column->rights&= ~rights; // Fix other columns - column_priv|= grant_column->rights; + grant_column->init_rights&= ~rights; // Fix other columns + grant_column->rights= grant_column->init_rights; + column_priv|= grant_column->init_rights; } } else { - column_priv|= grant_table->cols; + column_priv|= grant_table->init_cols; } @@ -7375,23 +7386,24 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, table_name= table_list->table_name.str; grant_name= routine_hash_search(Str->host.str, NullS, db_name, Str->user.str, table_name, sph, 1); - if (!grant_name || !grant_name->init_privs) + if (revoke_grant && (!grant_name || !grant_name->init_privs)) { - if (revoke_grant) - { - my_error(ER_NONEXISTING_PROC_GRANT, MYF(0), - Str->user.str, Str->host.str, table_name); - result= TRUE; - continue; - } + my_error(ER_NONEXISTING_PROC_GRANT, MYF(0), + Str->user.str, Str->host.str, table_name); + result= TRUE; + continue; + } + if (!grant_name) + { + DBUG_ASSERT(!revoke_grant); grant_name= new GRANT_NAME(Str->host.str, db_name, - Str->user.str, table_name, - rights, TRUE); + Str->user.str, table_name, + rights, TRUE); if (!grant_name || - my_hash_insert(sph->get_priv_hash(), (uchar*) grant_name)) + my_hash_insert(sph->get_priv_hash(), (uchar*) grant_name)) { result= TRUE; - continue; + continue; } } @@ -7728,7 +7740,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) Only need to propagate grants when granting/revoking a role to/from a role */ - if (role_as_user && merge_one_role_privileges(role_as_user) == 0) + if (role_as_user) propagate_role_grants(role_as_user, PRIVS_TO_MERGE::ALL); } @@ -10348,9 +10360,6 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, size_t old_key_length= acl_role->user.length; if (drop) { - /* all grants must be revoked from this role by now. propagate this */ - propagate_role_grants(acl_role, PRIVS_TO_MERGE::ALL); - // delete the role from cross-reference arrays for (size_t i=0; i < acl_role->role_grants.elements; i++) { @@ -10366,6 +10375,12 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, remove_ptr_from_dynarray(&grantee->role_grants, acl_role); } + /* Remove all of the role_grants from this role. */ + delete_dynamic(&acl_role->role_grants); + + /* all grants must be revoked from this role by now. propagate this */ + propagate_role_grants(acl_role, PRIVS_TO_MERGE::ALL); + my_hash_delete(&acl_roles, (uchar*) acl_role); DBUG_RETURN(1); } |