mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
Added GRANT ROLE TO ROLE | USER functionality.
The command only currenty affects in memory data structures. Writing to the roles_mapping table needs to be implemented.
This commit is contained in:
parent
95ef78e432
commit
1ac0b920d5
5 changed files with 350 additions and 26 deletions
|
@ -6569,3 +6569,9 @@ ER_INVALID_ROLE
|
||||||
ER_INVALID_CURRENT_USER
|
ER_INVALID_CURRENT_USER
|
||||||
eng "The current user is invalid."
|
eng "The current user is invalid."
|
||||||
rum "Utilizatorul curent este invalid."
|
rum "Utilizatorul curent este invalid."
|
||||||
|
ER_RESERVED_ROLE
|
||||||
|
eng "Role name '%s' is reserved."
|
||||||
|
rum "Numele de rol '%s' este rezervat."
|
||||||
|
ER_CANNOT_GRANT_ROLE
|
||||||
|
eng "Cannot grant role '%s' to: %s."
|
||||||
|
rum "Rolul '%s' nu poate fi acordat catre: %s."
|
||||||
|
|
309
sql/sql_acl.cc
309
sql/sql_acl.cc
|
@ -742,6 +742,9 @@ static my_bool acl_role_propagate_grants(ACL_ROLE *role,
|
||||||
void * not_used __attribute__((unused)));
|
void * not_used __attribute__((unused)));
|
||||||
static int add_role_user_mapping(ROLE_GRANT_PAIR *mapping);
|
static int add_role_user_mapping(ROLE_GRANT_PAIR *mapping);
|
||||||
|
|
||||||
|
static void reset_role_db_privileges(ACL_ROLE *role);
|
||||||
|
static void reset_role_table_and_column_privileges(ACL_ROLE *role);
|
||||||
|
static void reset_role_routine_grant_privileges(ACL_ROLE *role);
|
||||||
static void role_explore_create_list(ACL_ROLE *unused,
|
static void role_explore_create_list(ACL_ROLE *unused,
|
||||||
ACL_ROLE *role,
|
ACL_ROLE *role,
|
||||||
void *context_data);
|
void *context_data);
|
||||||
|
@ -751,6 +754,9 @@ static bool role_explore_merge_if_final(ACL_ROLE *current, ACL_ROLE *neighbour,
|
||||||
static void role_explore_set_final_access_bits(ACL_ROLE *parent,
|
static void role_explore_set_final_access_bits(ACL_ROLE *parent,
|
||||||
ACL_ROLE *current,
|
ACL_ROLE *current,
|
||||||
void *unused);
|
void *unused);
|
||||||
|
static bool role_explore_detect_cycle(ACL_ROLE *current,
|
||||||
|
ACL_ROLE *neighbour,
|
||||||
|
void *context_data);
|
||||||
static int traverse_role_graph(ACL_ROLE *role,
|
static int traverse_role_graph(ACL_ROLE *role,
|
||||||
void *context_data,
|
void *context_data,
|
||||||
bool (*on_start) (ACL_ROLE *role,
|
bool (*on_start) (ACL_ROLE *role,
|
||||||
|
@ -1926,17 +1932,11 @@ static uchar* check_get_key(ACL_USER *buff, size_t *length,
|
||||||
return (uchar*) buff->host.hostname;
|
return (uchar*) buff->host.hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acl_update_role(const char *rolename,
|
|
||||||
ulong privileges)
|
|
||||||
{
|
|
||||||
ACL_ROLE *role;
|
|
||||||
mysql_mutex_assert_owner(&acl_cache->lock);
|
|
||||||
|
|
||||||
role= find_acl_role(rolename);
|
static void acl_update_role_entry(ACL_ROLE *role, ulong privileges)
|
||||||
if (!role)
|
{
|
||||||
{
|
|
||||||
return;
|
mysql_mutex_assert_owner(&acl_cache->lock);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changing privileges of a role causes all other roles that had
|
Changing privileges of a role causes all other roles that had
|
||||||
|
@ -1993,6 +1993,20 @@ static void acl_update_role(const char *rolename,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void acl_update_role(const char *rolename,
|
||||||
|
ulong privileges)
|
||||||
|
{
|
||||||
|
mysql_mutex_assert_owner(&acl_cache->lock);
|
||||||
|
ACL_ROLE *role= find_acl_role(rolename);
|
||||||
|
if (!role)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
acl_update_role_entry(role, privileges);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void acl_update_user(const char *user, const char *host,
|
static void acl_update_user(const char *user, const char *host,
|
||||||
const char *password, uint password_len,
|
const char *password, uint password_len,
|
||||||
enum SSL_type ssl_type,
|
enum SSL_type ssl_type,
|
||||||
|
@ -2006,10 +2020,14 @@ static void acl_update_user(const char *user, const char *host,
|
||||||
{
|
{
|
||||||
mysql_mutex_assert_owner(&acl_cache->lock);
|
mysql_mutex_assert_owner(&acl_cache->lock);
|
||||||
|
|
||||||
if (host[0] == '\0' && find_acl_role(user))
|
if (host[0] == '\0')
|
||||||
{
|
{
|
||||||
acl_update_role(user, privileges);
|
ACL_ROLE *acl_role= find_acl_role(user);
|
||||||
return;
|
if (acl_role)
|
||||||
|
{
|
||||||
|
acl_update_role_entry(acl_role, privileges);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint i=0 ; i < acl_users.elements ; i++)
|
for (uint i=0 ; i < acl_users.elements ; i++)
|
||||||
|
@ -2071,6 +2089,12 @@ static void acl_insert_role(const char *rolename, ulong privileges)
|
||||||
|
|
||||||
mysql_mutex_assert_owner(&acl_cache->lock);
|
mysql_mutex_assert_owner(&acl_cache->lock);
|
||||||
entry= new (&mem) ACL_ROLE(rolename, privileges, &mem);
|
entry= new (&mem) ACL_ROLE(rolename, privileges, &mem);
|
||||||
|
(void) my_init_dynamic_array(&entry->parent_grantee,
|
||||||
|
sizeof(ACL_USER_BASE *), 50, 100, MYF(0));
|
||||||
|
(void) my_init_dynamic_array(&entry->role_grants,sizeof(ACL_ROLE *),
|
||||||
|
50, 100, MYF(0));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
my_hash_insert(&acl_roles, (uchar *)entry);
|
my_hash_insert(&acl_roles, (uchar *)entry);
|
||||||
}
|
}
|
||||||
|
@ -2416,6 +2440,7 @@ my_bool acl_user_reset_grant(ACL_USER *user,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -2433,6 +2458,16 @@ static bool role_explore_start_access_check(ACL_ROLE *role,
|
||||||
*/
|
*/
|
||||||
if (role->flags & ROLE_GRANTS_FINAL)
|
if (role->flags & ROLE_GRANTS_FINAL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
/*
|
||||||
|
This function is called when the node is first opened by DFS.
|
||||||
|
If it's ROLE_GRANTS were not final, then it means that it's existing
|
||||||
|
privilege entries should be placed on their initial grant access state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
reset_role_db_privileges(role);
|
||||||
|
reset_role_table_and_column_privileges(role);
|
||||||
|
reset_role_routine_grant_privileges(role);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2464,6 +2499,13 @@ static void role_explore_set_final_access_bits(ACL_ROLE *parent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool role_explore_detect_cycle(ACL_ROLE *unused __attribute__((unused)),
|
||||||
|
ACL_ROLE *unused2 __attribute__((unused)),
|
||||||
|
void *unused3 __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The function scans through all roles granted to the role passed as argument
|
The function scans through all roles granted to the role passed as argument
|
||||||
and places the permissions in the access variable. The traverse method is
|
and places the permissions in the access variable. The traverse method is
|
||||||
|
@ -2560,7 +2602,6 @@ static int traverse_role_graph(ACL_ROLE *role,
|
||||||
if (neighbour->flags & ROLE_VISITED)
|
if (neighbour->flags & ROLE_VISITED)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Found cycle"));
|
DBUG_PRINT("info", ("Found cycle"));
|
||||||
/* TODO the edge needs to be ignored */
|
|
||||||
if (on_cycle && on_cycle(current, neighbour, context_data))
|
if (on_cycle && on_cycle(current, neighbour, context_data))
|
||||||
{
|
{
|
||||||
result= 2;
|
result= 2;
|
||||||
|
@ -5102,6 +5143,155 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void append_user(String *str, const char *u, const char *h,
|
||||||
|
bool handle_as_role)
|
||||||
|
{
|
||||||
|
if (str->length())
|
||||||
|
str->append(',');
|
||||||
|
str->append('\'');
|
||||||
|
str->append(u);
|
||||||
|
/* hostname part is not relevant for roles, it is always empty */
|
||||||
|
if (!handle_as_role)
|
||||||
|
{
|
||||||
|
str->append(STRING_WITH_LEN("'@'"));
|
||||||
|
str->append(h);
|
||||||
|
}
|
||||||
|
str->append('\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mysql_grant_role(THD *thd, List <LEX_USER> &list)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("mysql_grant_role");
|
||||||
|
/*
|
||||||
|
The first entry in the list is the granted role. Need at least two
|
||||||
|
entries for the command to be valid
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(list.elements >= 2);
|
||||||
|
bool result= 0;
|
||||||
|
String wrong_users;
|
||||||
|
LEX_USER *user, *granted_role;
|
||||||
|
char *rolename;
|
||||||
|
char *username;
|
||||||
|
char *hostname;
|
||||||
|
bool handle_as_role;
|
||||||
|
ACL_ROLE *role, *role_as_user;
|
||||||
|
|
||||||
|
List_iterator <LEX_USER> user_list(list);
|
||||||
|
granted_role= user_list++;
|
||||||
|
if (granted_role == ¤t_role)
|
||||||
|
{
|
||||||
|
rolename= thd->security_ctx->priv_role;
|
||||||
|
if (!rolename[0])
|
||||||
|
{
|
||||||
|
my_error(ER_RESERVED_ROLE, MYF(0), "NONE");
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rolename= granted_role->user.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_rwlock_wrlock(&LOCK_grant);
|
||||||
|
mysql_mutex_lock(&acl_cache->lock);
|
||||||
|
if (!(role= find_acl_role(rolename)))
|
||||||
|
{
|
||||||
|
my_error(ER_INVALID_ROLE, MYF(0), rolename);
|
||||||
|
mysql_mutex_unlock(&acl_cache->lock);
|
||||||
|
mysql_rwlock_unlock(&LOCK_grant);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((user= user_list++))
|
||||||
|
{
|
||||||
|
handle_as_role= FALSE;
|
||||||
|
/* current_role is treated slightly different */
|
||||||
|
if (user == ¤t_role)
|
||||||
|
{
|
||||||
|
handle_as_role= TRUE;
|
||||||
|
/* current_role is NONE */
|
||||||
|
if (!thd->security_ctx->priv_role[0])
|
||||||
|
{
|
||||||
|
append_user(&wrong_users, "NONE", "", TRUE);
|
||||||
|
result= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!(role_as_user= find_acl_role(thd->security_ctx->priv_role)))
|
||||||
|
{
|
||||||
|
append_user(&wrong_users, thd->security_ctx->priv_role, "", TRUE);
|
||||||
|
result= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* can not grant current_role to current_role */
|
||||||
|
if (granted_role == ¤t_role)
|
||||||
|
{
|
||||||
|
append_user(&wrong_users, thd->security_ctx->priv_role, "", TRUE);
|
||||||
|
result= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
username= thd->security_ctx->priv_role;
|
||||||
|
hostname= (char *)"";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
username= user->user.str;
|
||||||
|
hostname= user->host.str;
|
||||||
|
if (hostname == HOST_NOT_SPECIFIED)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
|
||||||
|
/* TODO write into roles_mapping table */
|
||||||
|
init_role_grant_pair(&mem, mapping,
|
||||||
|
username, hostname, rolename);
|
||||||
|
int res= add_role_user_mapping(mapping);
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
append_user(&wrong_users, username, hostname, handle_as_role);
|
||||||
|
result= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 &&
|
||||||
|
traverse_role_graph(role, NULL, NULL, NULL, role_explore_detect_cycle,
|
||||||
|
NULL) == 2)
|
||||||
|
{
|
||||||
|
append_user(&wrong_users, username, hostname, TRUE);
|
||||||
|
result= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only need to propagate grants when granting a role to a role */
|
||||||
|
if (handle_as_role)
|
||||||
|
{
|
||||||
|
acl_update_role_entry(role_as_user, role_as_user->initial_role_access);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mysql_mutex_unlock(&acl_cache->lock);
|
||||||
|
mysql_rwlock_unlock(&LOCK_grant);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
my_error(ER_CANNOT_GRANT_ROLE, MYF(0),
|
||||||
|
rolename,
|
||||||
|
wrong_users.c_ptr_safe());
|
||||||
|
|
||||||
|
|
||||||
|
DBUG_RETURN(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
||||||
ulong rights, bool revoke_grant, bool is_proxy)
|
ulong rights, bool revoke_grant, bool is_proxy)
|
||||||
|
@ -7187,6 +7377,96 @@ static int show_routine_grants(THD* thd,
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reset_role_db_privileges(ACL_ROLE *role)
|
||||||
|
{
|
||||||
|
char *rolename= role->user.str;
|
||||||
|
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])
|
||||||
|
&& (!strcmp(rolename, acl_db->user)))
|
||||||
|
{
|
||||||
|
acl_db->access= acl_db->initial_access;
|
||||||
|
}
|
||||||
|
/* this is only an inherited entry that needs to be removed */
|
||||||
|
if (!acl_db->access)
|
||||||
|
{
|
||||||
|
delete_dynamic_element(&acl_dbs, i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_role_table_and_column_privileges(ACL_ROLE *role)
|
||||||
|
{
|
||||||
|
char *rolename= role->user.str;
|
||||||
|
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]) &&
|
||||||
|
!strcmp(rolename, grant_table->user))
|
||||||
|
{
|
||||||
|
grant_table->privs= grant_table->init_privs;
|
||||||
|
grant_table->cols= grant_table->init_cols;
|
||||||
|
if (grant_table->privs | grant_table->cols)
|
||||||
|
{
|
||||||
|
for (uint j=0 ; j < grant_table->hash_columns.records ; j++)
|
||||||
|
{
|
||||||
|
GRANT_COLUMN *grant_column= (GRANT_COLUMN *)
|
||||||
|
my_hash_element(&grant_table->hash_columns, j);
|
||||||
|
if (grant_column->init_rights == 0)
|
||||||
|
{
|
||||||
|
my_hash_delete(&grant_table->hash_columns, (uchar *)grant_column);
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grant_column->rights= grant_column->init_rights;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* delete the record altogether as we have no privileges left */
|
||||||
|
my_hash_delete(&column_priv_hash, (uchar *)grant_table);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_role_routine_grant_privileges(ACL_ROLE *role)
|
||||||
|
{
|
||||||
|
char *rolename= role->user.str;
|
||||||
|
for (uint is_proc= 0; is_proc < 2; is_proc++) {
|
||||||
|
HASH *hash;
|
||||||
|
if (is_proc)
|
||||||
|
hash= &proc_priv_hash;
|
||||||
|
else
|
||||||
|
hash= &func_priv_hash;
|
||||||
|
|
||||||
|
for (uint i=0 ; i < hash->records ; i++)
|
||||||
|
{
|
||||||
|
GRANT_NAME *grant_name= (GRANT_NAME *) my_hash_element(hash, i);
|
||||||
|
if (grant_name->user && (!grant_name->host.hostname ||
|
||||||
|
!grant_name->host.hostname[0]) &&
|
||||||
|
!strcmp(rolename, grant_name->user))
|
||||||
|
{
|
||||||
|
if (grant_name->init_privs == 0)
|
||||||
|
{
|
||||||
|
my_hash_delete(hash, (uchar *)grant_name);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grant_name->privs= grant_name->init_privs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Make a clear-text version of the requested privilege.
|
Make a clear-text version of the requested privilege.
|
||||||
*/
|
*/
|
||||||
|
@ -8322,7 +8602,6 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void append_user(String *str, LEX_USER *user, bool handle_as_role)
|
static void append_user(String *str, LEX_USER *user, bool handle_as_role)
|
||||||
{
|
{
|
||||||
if (str->length())
|
if (str->length())
|
||||||
|
|
|
@ -203,6 +203,8 @@ int check_change_password(THD *thd, const char *host, const char *user,
|
||||||
char *password, uint password_len);
|
char *password, uint password_len);
|
||||||
bool change_password(THD *thd, const char *host, const char *user,
|
bool change_password(THD *thd, const char *host, const char *user,
|
||||||
char *password);
|
char *password);
|
||||||
|
|
||||||
|
bool mysql_grant_role(THD *thd, List<LEX_USER> &user_list);
|
||||||
bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
|
bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
|
||||||
ulong rights, bool revoke, bool is_proxy);
|
ulong rights, bool revoke, bool is_proxy);
|
||||||
int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
|
int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
|
||||||
|
|
|
@ -3866,9 +3866,9 @@ end_with_restore_list:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Conditionally writes to binlog */
|
/* Conditionally writes to binlog */
|
||||||
res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
|
res= mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
|
||||||
lex->sql_command == SQLCOM_REVOKE,
|
lex->sql_command == SQLCOM_REVOKE,
|
||||||
lex->type == TYPE_ENUM_PROXY);
|
lex->type == TYPE_ENUM_PROXY);
|
||||||
}
|
}
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
|
@ -3890,8 +3890,15 @@ end_with_restore_list:
|
||||||
case SQLCOM_REVOKE_ROLE:
|
case SQLCOM_REVOKE_ROLE:
|
||||||
case SQLCOM_GRANT_ROLE:
|
case SQLCOM_GRANT_ROLE:
|
||||||
{
|
{
|
||||||
/* TODO Implement grant */
|
/* TODO access check */
|
||||||
my_ok(thd);
|
|
||||||
|
if (thd->security_ctx->user) // If not replication
|
||||||
|
{
|
||||||
|
if (!(res= mysql_grant_role(thd, lex->users_list)))
|
||||||
|
my_ok(thd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
my_ok(thd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
|
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
|
||||||
|
|
|
@ -1570,7 +1570,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||||
|
|
||||||
%type <symbol> keyword keyword_sp
|
%type <symbol> keyword keyword_sp
|
||||||
|
|
||||||
%type <lex_user> user grant_user grant_role
|
%type <lex_user> user grant_user grant_role user_or_role
|
||||||
|
|
||||||
%type <charset>
|
%type <charset>
|
||||||
opt_collate
|
opt_collate
|
||||||
|
@ -1624,7 +1624,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||||
opt_option opt_place
|
opt_option opt_place
|
||||||
opt_attribute opt_attribute_list attribute column_list column_list_id
|
opt_attribute opt_attribute_list attribute column_list column_list_id
|
||||||
opt_column_list grant_privileges grant_ident grant_list grant_option
|
opt_column_list grant_privileges grant_ident grant_list grant_option
|
||||||
object_privilege object_privilege_list user_list rename_list
|
object_privilege object_privilege_list user_list user_and_role_list
|
||||||
|
rename_list
|
||||||
clear_privileges flush_options flush_option
|
clear_privileges flush_options flush_option
|
||||||
opt_with_read_lock flush_options_list
|
opt_with_read_lock flush_options_list
|
||||||
equal optional_braces
|
equal optional_braces
|
||||||
|
@ -13208,6 +13209,16 @@ user:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
user_or_role:
|
||||||
|
user
|
||||||
|
{
|
||||||
|
$$=$1;
|
||||||
|
}
|
||||||
|
| CURRENT_ROLE optional_braces
|
||||||
|
{
|
||||||
|
$$= ¤t_role;
|
||||||
|
}
|
||||||
|
|
||||||
/* Keyword that we allow for identifiers (except SP labels) */
|
/* Keyword that we allow for identifiers (except SP labels) */
|
||||||
keyword:
|
keyword:
|
||||||
keyword_sp {}
|
keyword_sp {}
|
||||||
|
@ -14240,8 +14251,8 @@ revoke_command:
|
||||||
lex->users_list.push_front ($3);
|
lex->users_list.push_front ($3);
|
||||||
lex->sql_command= SQLCOM_REVOKE;
|
lex->sql_command= SQLCOM_REVOKE;
|
||||||
lex->type= TYPE_ENUM_PROXY;
|
lex->type= TYPE_ENUM_PROXY;
|
||||||
}
|
}
|
||||||
| grant_role FROM grant_list
|
| grant_role FROM user_and_role_list
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
lex->sql_command= SQLCOM_REVOKE_ROLE;
|
lex->sql_command= SQLCOM_REVOKE_ROLE;
|
||||||
|
@ -14294,11 +14305,13 @@ grant_command:
|
||||||
lex->sql_command= SQLCOM_GRANT;
|
lex->sql_command= SQLCOM_GRANT;
|
||||||
lex->type= TYPE_ENUM_PROXY;
|
lex->type= TYPE_ENUM_PROXY;
|
||||||
}
|
}
|
||||||
| grant_role TO_SYM grant_list
|
| grant_role TO_SYM user_and_role_list
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
lex->sql_command= SQLCOM_GRANT_ROLE;
|
lex->sql_command= SQLCOM_GRANT_ROLE;
|
||||||
lex->type= 0;
|
/* The first role is the one that is granted */
|
||||||
|
if (Lex->users_list.push_front($1))
|
||||||
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
@ -14333,6 +14346,10 @@ grant_role:
|
||||||
system_charset_info, 0))
|
system_charset_info, 0))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
|
| CURRENT_ROLE optional_braces
|
||||||
|
{
|
||||||
|
$$=¤t_role;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_table:
|
opt_table:
|
||||||
|
@ -14522,6 +14539,19 @@ grant_list:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
user_and_role_list:
|
||||||
|
user_or_role
|
||||||
|
{
|
||||||
|
if (Lex->users_list.push_back($1))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
| user_and_role_list ',' user_or_role
|
||||||
|
{
|
||||||
|
if (Lex->users_list.push_back($3))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
via_or_with: VIA_SYM | WITH ;
|
via_or_with: VIA_SYM | WITH ;
|
||||||
using_or_as: USING | AS ;
|
using_or_as: USING | AS ;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue