Commit 4a585999 authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru Committed by Sergei Golubchik

Implemented SHOW GRANTS functionality

parent d24ead2c
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';
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role2');
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
localhost test_user test_role2
flush privileges;
select user, host from mysql.db;
user host
%
%
grant select on mysql.* to test_role2@'';
flush privileges;
show grants;
Grants for test_user@localhost
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT test_role1 TO 'test_user'@'localhost'
GRANT test_role2 TO 'test_user'@'localhost'
set role test_role1;
show grants;
Grants for test_user@localhost
GRANT SELECT ON `mysql`.* 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'
GRANT test_role2 TO 'test_user'@'localhost'
set role none;
show grants;
Grants for test_user@localhost
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT test_role1 TO 'test_user'@'localhost'
GRANT test_role2 TO 'test_user'@'localhost'
show grants for test_user@localhost;
ERROR 42000: Access denied for user 'test_user'@'localhost' to database 'mysql'
show grants for test_role1;
ERROR 42000: Access denied for user 'test_user'@'localhost' to database 'mysql'
show grants for test_role2;
ERROR 42000: Access denied for user 'test_user'@'localhost' to database 'mysql'
show grants for CURRENT_USER;
Grants for test_user@localhost
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT test_role1 TO 'test_user'@'localhost'
GRANT test_role2 TO 'test_user'@'localhost'
show grants for CURRENT_USER();
Grants for test_user@localhost
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT test_role1 TO 'test_user'@'localhost'
GRANT test_role2 TO 'test_user'@'localhost'
show grants for CURRENT_ROLE;
ERROR 42000: There is no such grant defined for user 'test_user' on host 'localhost'
show grants for CURRENT_ROLE();
ERROR 42000: There is no such grant defined for user 'test_user' on host 'localhost'
set role test_role2;
show grants;
Grants for test_user@localhost
GRANT SELECT ON `mysql`.* TO 'test_role2'
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_user'@'localhost'
show grants for test_user@localhost;
Grants for test_user@localhost
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT test_role1 TO 'test_user'@'localhost'
GRANT test_role2 TO 'test_user'@'localhost'
show grants for test_role1;
Grants for test_role1
GRANT SELECT ON `mysql`.* TO 'test_role2'
GRANT USAGE ON *.* TO 'test_role1'
GRANT USAGE ON *.* TO 'test_role2'
GRANT test_role2 TO 'test_role1'
show grants for test_role2;
Grants for test_role2
GRANT SELECT ON `mysql`.* TO 'test_role2'
GRANT USAGE ON *.* TO 'test_role2'
show grants for CURRENT_USER;
Grants for test_user@localhost
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT test_role1 TO 'test_user'@'localhost'
GRANT test_role2 TO 'test_user'@'localhost'
show grants for CURRENT_USER();
Grants for test_user@localhost
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT test_role1 TO 'test_user'@'localhost'
GRANT test_role2 TO 'test_user'@'localhost'
show grants for CURRENT_ROLE;
Grants for test_role2
GRANT SELECT ON `mysql`.* TO 'test_role2'
GRANT USAGE ON *.* TO 'test_role2'
show grants for CURRENT_ROLE();
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';
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'@'';
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');
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role2');
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;
flush privileges;
--sorted_result
select user, host from mysql.db;
grant select on mysql.* to test_role2@'';
flush privileges;
change_user 'test_user';
--sorted_result
show grants;
set role test_role1;
--sorted_result
show grants;
set role none;
--sorted_result
show grants;
--error ER_DBACCESS_DENIED_ERROR
show grants for test_user@localhost;
--error ER_DBACCESS_DENIED_ERROR
show grants for test_role1;
--error ER_DBACCESS_DENIED_ERROR
show grants for test_role2;
--sorted_result
show grants for CURRENT_USER;
--sorted_result
show grants for CURRENT_USER();
--error ER_NONEXISTING_GRANT
show grants for CURRENT_ROLE;
--error ER_NONEXISTING_GRANT
show grants for CURRENT_ROLE();
set role test_role2;
--sorted_result
show grants;
--sorted_result
show grants for test_user@localhost;
--sorted_result
show grants for test_role1;
--sorted_result
show grants for test_role2;
--sorted_result
show grants for CURRENT_USER;
--sorted_result
show grants for CURRENT_USER();
--sorted_result
show grants for CURRENT_ROLE;
--sorted_result
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';
delete from mysql.roles_mapping where RoleFk='test_role1';
delete from mysql.roles_mapping where RoleFk='test_role2';
flush privileges;
...@@ -153,6 +153,7 @@ static SYMBOL symbols[] = { ...@@ -153,6 +153,7 @@ static SYMBOL symbols[] = {
{ "CUBE", SYM(CUBE_SYM)}, { "CUBE", SYM(CUBE_SYM)},
{ "CURRENT_DATE", SYM(CURDATE)}, { "CURRENT_DATE", SYM(CURDATE)},
{ "CURRENT_POS", SYM(CURRENT_POS_SYM)}, { "CURRENT_POS", SYM(CURRENT_POS_SYM)},
{ "CURRENT_ROLE", SYM(CURRENT_ROLE)},
{ "CURRENT_TIME", SYM(CURTIME)}, { "CURRENT_TIME", SYM(CURTIME)},
{ "CURRENT_TIMESTAMP", SYM(NOW_SYM)}, { "CURRENT_TIMESTAMP", SYM(NOW_SYM)},
{ "CURRENT_USER", SYM(CURRENT_USER)}, { "CURRENT_USER", SYM(CURRENT_USER)},
......
...@@ -3517,7 +3517,6 @@ SHOW_VAR com_status_vars[]= { ...@@ -3517,7 +3517,6 @@ SHOW_VAR com_status_vars[]= {
#endif #endif
{"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS}, {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS},
{"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS}, {"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
{"show_grants_self", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS_SELF]), SHOW_LONG_STATUS},
{"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS}, {"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
{"show_index_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INDEX_STATS]), SHOW_LONG_STATUS}, {"show_index_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INDEX_STATS]), SHOW_LONG_STATUS},
{"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS}, {"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
......
...@@ -223,7 +223,6 @@ sp_get_flags_for_command(LEX *lex) ...@@ -223,7 +223,6 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_SHOW_FIELDS: case SQLCOM_SHOW_FIELDS:
case SQLCOM_SHOW_FUNC_CODE: case SQLCOM_SHOW_FUNC_CODE:
case SQLCOM_SHOW_GRANTS: case SQLCOM_SHOW_GRANTS:
case SQLCOM_SHOW_GRANTS_SELF:
case SQLCOM_SHOW_ENGINE_STATUS: case SQLCOM_SHOW_ENGINE_STATUS:
case SQLCOM_SHOW_ENGINE_LOGS: case SQLCOM_SHOW_ENGINE_LOGS:
case SQLCOM_SHOW_ENGINE_MUTEX: case SQLCOM_SHOW_ENGINE_MUTEX:
......
...@@ -193,6 +193,12 @@ const char *HOST_NOT_SPECIFIED= "%"; ...@@ -193,6 +193,12 @@ const char *HOST_NOT_SPECIFIED= "%";
Constant used in the SET ROLE NONE command Constant used in the SET ROLE NONE command
*/ */
const char *NONE_ROLE= "NONE"; const char *NONE_ROLE= "NONE";
/*
Constants, used in the SHOW GRANTS command
*/
LEX_USER current_user;
LEX_USER current_role;
LEX_USER current_user_and_current_role;
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
...@@ -307,18 +313,24 @@ static void update_hostname(acl_host_and_ip *host, const char *hostname); ...@@ -307,18 +313,24 @@ static void update_hostname(acl_host_and_ip *host, const char *hostname);
static ulong get_sort(uint count,...); static ulong get_sort(uint count,...);
static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
const char *ip); const char *ip);
static bool show_proxy_grants (THD *thd, LEX_USER *user, static bool show_proxy_grants (THD *thd,
const char *username, const char *hostname,
char *buff, size_t buffsize); char *buff, size_t buffsize);
static bool show_role_grants(THD *thd, LEX_USER *lex_user, static bool show_role_grants(THD *thd,
const char *username, const char *hostname,
ACL_USER_BASE *acl_entry, ACL_USER_BASE *acl_entry,
char *buff, size_t buffsize); char *buff, size_t buffsize);
static bool show_global_privileges(THD *thd, LEX_USER *lex_user, static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry,
ACL_USER_BASE *acl_entry, bool handle_as_role, bool handle_as_role,
char *buff, size_t buffsize); char *buff, size_t buffsize);
static bool show_database_privileges(THD *thd, LEX_USER *lex_user, static bool show_database_privileges(THD *thd,
const char *username,
const char *hostname,
bool handle_as_role, bool handle_as_role,
char *buff, size_t buffsize); char *buff, size_t buffsize);
static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, static bool show_table_and_column_privileges(THD *thd,
const char *username,
const char *hostname,
bool handle_as_role, bool handle_as_role,
char *buff, size_t buffsize); char *buff, size_t buffsize);
...@@ -6382,50 +6394,60 @@ static uint command_lengths[]= ...@@ -6382,50 +6394,60 @@ static uint command_lengths[]=
}; };
static int show_routine_grants(THD *thd, LEX_USER *lex_user, HASH *hash, static int show_routine_grants(THD *thd,
const char *username,
const char *hostname,
HASH *hash,
const char *type, int typelen, const char *type, int typelen,
bool handle_as_role, bool handle_as_role,
char *buff, int buffsize); char *buff, int buffsize);
/*
SHOW GRANTS; Send grants for a user to the client
IMPLEMENTATION
Send to client grant-like strings depicting user@host privileges
*/
bool print_grants_for_role(THD *thd, ACL_ROLE * role, bool print_grants_for_role(THD *thd, ACL_ROLE * role,
char *buff, size_t buffsize) char *buff, size_t buffsize)
{ {
LEX_USER lex_user; if (show_role_grants(thd, role->user.str, "", role, buff, sizeof(buff)))
lex_user.user= role->user; return TRUE;
if (show_global_privileges(thd, &lex_user, role, TRUE, buff, buffsize))
if (show_global_privileges(thd, role, TRUE, buff, buffsize))
return TRUE; return TRUE;
if (show_database_privileges(thd, &lex_user, TRUE, buff, buffsize)) if (show_database_privileges(thd, role->user.str, "", TRUE, buff, buffsize))
return TRUE; return TRUE;
if (show_table_and_column_privileges(thd, &lex_user, TRUE, buff, buffsize)) if (show_table_and_column_privileges(thd, role->user.str, "", TRUE, buff, buffsize))
return TRUE; return TRUE;
if (show_routine_grants(thd, &lex_user, &proc_priv_hash, if (show_routine_grants(thd, role->user.str, "", &proc_priv_hash,
STRING_WITH_LEN("PROCEDURE"), TRUE, buff, buffsize)) STRING_WITH_LEN("PROCEDURE"), TRUE, buff, buffsize))
return TRUE; return TRUE;
if (show_routine_grants(thd, &lex_user, &func_priv_hash, if (show_routine_grants(thd, role->user.str, "", &func_priv_hash,
STRING_WITH_LEN("FUNCTION"), TRUE, buff, buffsize)) STRING_WITH_LEN("FUNCTION"), TRUE, buff, buffsize))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role)
/*
SHOW GRANTS; Send grants for a user to the client
IMPLEMENTATION
Send to client grant-like strings depicting user@host privileges
*/
bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
{ {
int error = 0; int error = 0;
ACL_USER *acl_user; ACL_USER *acl_user;
ACL_ROLE *acl_role= NULL;
char buff[1024]; char buff[1024];
Protocol *protocol= thd->protocol; Protocol *protocol= thd->protocol;
bool print_user_entry= FALSE;
bool print_role_entry= FALSE;
char *username= NULL;
char *hostname= NULL;
char *rolename= NULL;
DBUG_ENTER("mysql_show_grants"); DBUG_ENTER("mysql_show_grants");
LINT_INIT(acl_user); LINT_INIT(acl_user);
...@@ -6437,24 +6459,53 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role) ...@@ -6437,24 +6459,53 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role)
mysql_rwlock_rdlock(&LOCK_grant); mysql_rwlock_rdlock(&LOCK_grant);
mysql_mutex_lock(&acl_cache->lock); mysql_mutex_lock(&acl_cache->lock);
if (lex_user == &current_user || lex_user == &current_role ||
acl_user= find_user_no_anon(lex_user->host.str, lex_user->user.str, TRUE); lex_user == &current_user_and_current_role)
if (!acl_user)
{ {
mysql_mutex_unlock(&acl_cache->lock); username= thd->security_ctx->priv_user;
mysql_rwlock_unlock(&LOCK_grant); hostname= thd->security_ctx->priv_host;
rolename= thd->security_ctx->priv_role;
}
my_error(ER_NONEXISTING_GRANT, MYF(0), if (lex_user == &current_user)
lex_user->user.str, lex_user->host.str); {
DBUG_RETURN(TRUE); print_user_entry= TRUE;
}
else if (lex_user == &current_role)
{
print_role_entry= TRUE;
}
else if (lex_user == &current_user_and_current_role)
{
print_user_entry= TRUE;
print_role_entry= TRUE;
}
else
{
/* this lex_user could represent a role */
if (lex_user->host.str == HOST_NOT_SPECIFIED &&
find_acl_role(lex_user->user.str))
{
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;
}
} }
Item_string *field=new Item_string("",0,&my_charset_latin1); Item_string *field=new Item_string("",0,&my_charset_latin1);
List<Item> field_list; List<Item> field_list;
field->name=buff; field->name=buff;
field->max_length=1024; field->max_length=1024;
strxmov(buff,"Grants for ",lex_user->user.str,"@", if (print_user_entry == FALSE)
lex_user->host.str,NullS); strxmov(buff,"Grants for ",rolename, NullS);
else
strxmov(buff,"Grants for ",username,"@",hostname, NullS);
field_list.push_back(field); field_list.push_back(field);
if (protocol->send_result_set_metadata(&field_list, if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
...@@ -6465,64 +6516,79 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role) ...@@ -6465,64 +6516,79 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role)
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
if (print_user_entry)
{
acl_user= find_user_no_anon(hostname, username, TRUE);
if (!acl_user)
{
mysql_mutex_unlock(&acl_cache->lock);
mysql_rwlock_unlock(&LOCK_grant);
my_error(ER_NONEXISTING_GRANT, MYF(0),
username, hostname);
DBUG_RETURN(TRUE);
}
/* Show granted roles to acl_user */ /* Show granted roles to acl_user */
if (show_role_grants(thd, lex_user, acl_user, buff, sizeof(buff))) if (show_role_grants(thd, username, hostname, acl_user, buff, sizeof(buff)))
{ {
error= -1; error= -1;
goto end; goto end;
} }
/* Add first global access grants */ /* Add first global access grants */
if (show_global_privileges(thd, lex_user, acl_user, FALSE, buff, sizeof(buff))) if (show_global_privileges(thd, acl_user, FALSE, buff, sizeof(buff)))
{ {
error= -1; error= -1;
goto end; goto end;
}; };
/* Add database access */ /* Add database access */
if (show_database_privileges(thd, lex_user, FALSE, buff, sizeof(buff))) if (show_database_privileges(thd, username, hostname, FALSE, buff, sizeof(buff)))
{ {
error= -1; error= -1;
goto end; goto end;
} }
/* Add table & column access */ /* Add table & column access */
if (show_table_and_column_privileges(thd, lex_user, FALSE, buff, sizeof(buff))) if (show_table_and_column_privileges(thd, username, hostname, FALSE, buff, sizeof(buff)))
{ {
error= -1; error= -1;
goto end; goto end;
} }
if (show_routine_grants(thd, lex_user, &proc_priv_hash, if (show_routine_grants(thd, username, hostname, &proc_priv_hash,
STRING_WITH_LEN("PROCEDURE"), FALSE, buff, sizeof(buff))) STRING_WITH_LEN("PROCEDURE"), FALSE, buff, sizeof(buff)))
{ {
error= -1; error= -1;
goto end; goto end;
} }
if (show_routine_grants(thd, lex_user, &func_priv_hash, if (show_routine_grants(thd, username, hostname, &func_priv_hash,
STRING_WITH_LEN("FUNCTION"), FALSE, buff, sizeof(buff))) STRING_WITH_LEN("FUNCTION"), FALSE, buff, sizeof(buff)))
{ {
error= -1; error= -1;
goto end; goto end;
} }
if (show_proxy_grants(thd, lex_user, buff, sizeof(buff))) if (show_proxy_grants(thd, username, hostname, buff, sizeof(buff)))
{ {
error= -1; error= -1;
goto end; goto end;
} }
}
if (print_current_role) if (print_role_entry)
{ {
ACL_ROLE *role= find_acl_role(thd->security_ctx->priv_role); acl_role= find_acl_role(rolename);
if (role) if (acl_role)
{ {
DYNAMIC_ARRAY role_list; DYNAMIC_ARRAY role_list;
(void) my_init_dynamic_array(&role_list,sizeof(ACL_ROLE *), (void) my_init_dynamic_array(&role_list,sizeof(ACL_ROLE *),
50, 100, MYF(0)); 50, 100, MYF(0));
/* get a list of all inherited roles */ /* get a list of all inherited roles */
traverse_role_graph(role, traverse_role_graph(acl_role,
&role_list, NULL, NULL, NULL, &role_list, NULL, NULL, NULL,
role_explore_create_list); role_explore_create_list);
for (uint i= 0; i < role_list.elements; i++) for (uint i= 0; i < role_list.elements; i++)
...@@ -6537,6 +6603,17 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role) ...@@ -6537,6 +6603,17 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role)
} }
delete_dynamic(&role_list); delete_dynamic(&role_list);
} }
else
{
if (lex_user == &current_role)
{
mysql_mutex_unlock(&acl_cache->lock);
mysql_rwlock_unlock(&LOCK_grant);
my_error(ER_NONEXISTING_GRANT, MYF(0),
username, hostname);
DBUG_RETURN(TRUE);
}
}
} }
end: end:
...@@ -6547,12 +6624,15 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role) ...@@ -6547,12 +6624,15 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role)
DBUG_RETURN(error); DBUG_RETURN(error);
} }
static bool show_role_grants(THD *thd, LEX_USER *lex_user, static bool show_role_grants(THD *thd,
const char *username,
const char *hostname,
ACL_USER_BASE *acl_entry, ACL_USER_BASE *acl_entry,
char *buff, size_t buffsize) char *buff, size_t buffsize)
{ {
uint counter; uint counter;
Protocol *protocol= thd->protocol; Protocol *protocol= thd->protocol;
uint hostname_length = strlen(hostname);
String grant(buff,sizeof(buff),system_charset_info); String grant(buff,sizeof(buff),system_charset_info);
for (counter= 0; counter < acl_entry->role_grants.elements; counter++) for (counter= 0; counter < acl_entry->role_grants.elements; counter++)
...@@ -6564,12 +6644,12 @@ static bool show_role_grants(THD *thd, LEX_USER *lex_user, ...@@ -6564,12 +6644,12 @@ static bool show_role_grants(THD *thd, LEX_USER *lex_user,
grant.append(acl_role->user.str, acl_role->user.length, grant.append(acl_role->user.str, acl_role->user.length,
system_charset_info); system_charset_info);
grant.append(STRING_WITH_LEN(" TO '")); grant.append(STRING_WITH_LEN(" TO '"));
grant.append(lex_user->user.str, lex_user->user.length, grant.append(acl_entry->user.str, acl_entry->user.length,
system_charset_info); system_charset_info);
if (!(acl_entry->flags & IS_ROLE)) if (!(acl_entry->flags & IS_ROLE))
{ {
grant.append(STRING_WITH_LEN("'@'")); grant.append(STRING_WITH_LEN("'@'"));
grant.append(lex_user->host.str, lex_user->host.length, grant.append(hostname, hostname_length,
system_charset_info); system_charset_info);
} }
grant.append('\''); grant.append('\'');
...@@ -6583,8 +6663,8 @@ static bool show_role_grants(THD *thd, LEX_USER *lex_user, ...@@ -6583,8 +6663,8 @@ static bool show_role_grants(THD *thd, LEX_USER *lex_user,
return FALSE; return FALSE;
} }
static bool show_global_privileges(THD *thd, LEX_USER *lex_user, static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry,
ACL_USER_BASE *acl_entry, bool handle_as_role, bool handle_as_role,
char *buff, size_t buffsize) char *buff, size_t buffsize)
{ {
uint counter; uint counter;
...@@ -6619,7 +6699,7 @@ static bool show_global_privileges(THD *thd, LEX_USER *lex_user, ...@@ -6619,7 +6699,7 @@ static bool show_global_privileges(THD *thd, LEX_USER *lex_user,
} }
} }
global.append (STRING_WITH_LEN(" ON *.* TO '")); global.append (STRING_WITH_LEN(" ON *.* TO '"));
global.append(lex_user->user.str, lex_user->user.length, global.append(acl_entry->user.str, acl_entry->user.length,
system_charset_info); system_charset_info);
global.append('\''); global.append('\'');
...@@ -6628,7 +6708,7 @@ static bool show_global_privileges(THD *thd, LEX_USER *lex_user, ...@@ -6628,7 +6708,7 @@ static bool show_global_privileges(THD *thd, LEX_USER *lex_user,
ACL_USER *acl_user= (ACL_USER *)acl_entry; ACL_USER *acl_user= (ACL_USER *)acl_entry;
global.append (STRING_WITH_LEN("@'")); global.append (STRING_WITH_LEN("@'"));
global.append(lex_user->host.str, lex_user->host.length, global.append(acl_user->host.hostname, acl_user->hostname_length,
system_charset_info); system_charset_info);
global.append ('\''); global.append ('\'');
...@@ -6718,7 +6798,9 @@ static bool show_global_privileges(THD *thd, LEX_USER *lex_user, ...@@ -6718,7 +6798,9 @@ static bool show_global_privileges(THD *thd, LEX_USER *lex_user,
} }
static bool show_database_privileges(THD *thd, LEX_USER *lex_user, static bool show_database_privileges(THD *thd,
const char *username,
const char *hostname,
bool handle_as_role, bool handle_as_role,
char *buff, size_t buffsize) char *buff, size_t buffsize)
{ {
...@@ -6744,8 +6826,8 @@ static bool show_database_privileges(THD *thd, LEX_USER *lex_user, ...@@ -6744,8 +6826,8 @@ static bool show_database_privileges(THD *thd, LEX_USER *lex_user,
would be wrong from a security point of view. would be wrong from a security point of view.
*/ */
if (!strcmp(lex_user->user.str,user) && if (!strcmp(username, user) &&
!my_strcasecmp(system_charset_info, lex_user->host.str, host)) !my_strcasecmp(system_charset_info, hostname, host))
{ {
/* do not print inherited access bits, the role bits present in the /* do not print inherited access bits, the role bits present in the
table are what matters */ table are what matters */
...@@ -6781,7 +6863,7 @@ static bool show_database_privileges(THD *thd, LEX_USER *lex_user, ...@@ -6781,7 +6863,7 @@ static bool show_database_privileges(THD *thd, LEX_USER *lex_user,
db.append (STRING_WITH_LEN(" ON ")); db.append (STRING_WITH_LEN(" ON "));
append_identifier(thd, &db, acl_db->db, strlen(acl_db->db)); append_identifier(thd, &db, acl_db->db, strlen(acl_db->db));
db.append (STRING_WITH_LEN(".* TO '")); db.append (STRING_WITH_LEN(".* TO '"));
db.append(lex_user->user.str, lex_user->user.length, db.append(username, strlen(username),
system_charset_info); system_charset_info);
if (!handle_as_role) if (!handle_as_role)
{ {
...@@ -6805,7 +6887,9 @@ static bool show_database_privileges(THD *thd, LEX_USER *lex_user, ...@@ -6805,7 +6887,9 @@ static bool show_database_privileges(THD *thd, LEX_USER *lex_user,
} }
static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, static bool show_table_and_column_privileges(THD *thd,
const char *username,
const char *hostname,
bool handle_as_role, bool handle_as_role,
char *buff, size_t buffsize) char *buff, size_t buffsize)
{ {
...@@ -6830,8 +6914,8 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, ...@@ -6830,8 +6914,8 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user,
would be wrong from a security point of view. would be wrong from a security point of view.
*/ */
if (!strcmp(lex_user->user.str,user) && if (!strcmp(username,user) &&
!my_strcasecmp(system_charset_info, lex_user->host.str, host)) !my_strcasecmp(system_charset_info, hostname, host))
{ {
ulong table_access; ulong table_access;
ulong cols_access; ulong cols_access;
...@@ -6925,7 +7009,7 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, ...@@ -6925,7 +7009,7 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user,
append_identifier(thd, &global, grant_table->tname, append_identifier(thd, &global, grant_table->tname,
strlen(grant_table->tname)); strlen(grant_table->tname));
global.append(STRING_WITH_LEN(" TO '")); global.append(STRING_WITH_LEN(" TO '"));
global.append(lex_user->user.str, lex_user->user.length, global.append(username, strlen(username),
system_charset_info); system_charset_info);
if (!handle_as_role) if (!handle_as_role)
{ {
...@@ -6949,7 +7033,9 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, ...@@ -6949,7 +7033,9 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user,
} }
static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, static int show_routine_grants(THD* thd,
const char *username, const char *hostname,
HASH *hash,
const char *type, int typelen, const char *type, int typelen,
bool handle_as_role, bool handle_as_role,
char *buff, int buffsize) char *buff, int buffsize)
...@@ -6975,8 +7061,8 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, ...@@ -6975,8 +7061,8 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash,
would be wrong from a security point of view. would be wrong from a security point of view.
*/ */
if (!strcmp(lex_user->user.str,user) && if (!strcmp(username, user) &&
!my_strcasecmp(system_charset_info, lex_user->host.str, host)) !my_strcasecmp(system_charset_info, hostname, host))
{ {
ulong proc_access; ulong proc_access;
if (handle_as_role) if (handle_as_role)
...@@ -7020,7 +7106,7 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, ...@@ -7020,7 +7106,7 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash,
append_identifier(thd, &global, grant_proc->tname, append_identifier(thd, &global, grant_proc->tname,
strlen(grant_proc->tname)); strlen(grant_proc->tname));
global.append(STRING_WITH_LEN(" TO '")); global.append(STRING_WITH_LEN(" TO '"));
global.append(lex_user->user.str, lex_user->user.length, global.append(username, strlen(username),
system_charset_info); system_charset_info);
if (!handle_as_role) if (!handle_as_role)
{ {
...@@ -8834,7 +8920,8 @@ acl_check_proxy_grant_access(THD *thd, const char *host, const char *user, ...@@ -8834,7 +8920,8 @@ acl_check_proxy_grant_access(THD *thd, const char *host, const char *user,
static bool static bool
show_proxy_grants(THD *thd, LEX_USER *user, char *buff, size_t buffsize) show_proxy_grants(THD *thd, const char *username, const char *hostname,
char *buff, size_t buffsize)
{ {
Protocol *protocol= thd->protocol; Protocol *protocol= thd->protocol;
int error= 0; int error= 0;
...@@ -8843,7 +8930,7 @@ show_proxy_grants(THD *thd, LEX_USER *user, char *buff, size_t buffsize) ...@@ -8843,7 +8930,7 @@ show_proxy_grants(THD *thd, LEX_USER *user, char *buff, size_t buffsize)
{ {
ACL_PROXY_USER *proxy= dynamic_element(&acl_proxy_users, i, ACL_PROXY_USER *proxy= dynamic_element(&acl_proxy_users, i,
ACL_PROXY_USER *); ACL_PROXY_USER *);
if (proxy->granted_on(user->host.str, user->user.str)) if (proxy->granted_on(hostname, username))
{ {
String global(buff, buffsize, system_charset_info); String global(buff, buffsize, system_charset_info);
global.length(0); global.length(0);
......
...@@ -175,6 +175,9 @@ extern bool mysql_user_table_is_in_short_password_format; ...@@ -175,6 +175,9 @@ extern bool mysql_user_table_is_in_short_password_format;
extern const char *HOST_NOT_SPECIFIED; extern const char *HOST_NOT_SPECIFIED;
extern const char *NONE_ROLE; extern const char *NONE_ROLE;
extern LEX_USER current_user;
extern LEX_USER current_role;
extern LEX_USER current_user_and_current_role;
static inline int access_denied_error_code(int passwd_used) static inline int access_denied_error_code(int passwd_used)
...@@ -227,7 +230,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table); ...@@ -227,7 +230,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table);
ulong get_column_grant(THD *thd, GRANT_INFO *grant, ulong get_column_grant(THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
const char *field_name); const char *field_name);
bool mysql_show_grants(THD *thd, LEX_USER *user, bool print_current_role); bool mysql_show_grants(THD *thd, LEX_USER *user);
void get_privilege_desc(char *to, uint max_length, ulong access); void get_privilege_desc(char *to, uint max_length, ulong access);
void get_mqh(const char *user, const char *host, USER_CONN *uc); void get_mqh(const char *user, const char *host, USER_CONN *uc);
bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role); bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role);
......
...@@ -146,7 +146,6 @@ enum enum_sql_command { ...@@ -146,7 +146,6 @@ enum enum_sql_command {
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS, SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
SQLCOM_SHOW_TRIGGERS, SQLCOM_SHOW_TRIGGERS,
SQLCOM_SHOW_GRANTS_SELF,
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT, SQLCOM_GRANT_ROLE, SQLCOM_GRANT, SQLCOM_GRANT_ROLE,
......
...@@ -341,7 +341,6 @@ void init_update_queries(void) ...@@ -341,7 +341,6 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_EXPLAIN]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_EXPLAIN]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_GRANTS_SELF]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
...@@ -3991,18 +3990,16 @@ case SQLCOM_PREPARE: ...@@ -3991,18 +3990,16 @@ case SQLCOM_PREPARE:
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
case SQLCOM_SHOW_GRANTS: case SQLCOM_SHOW_GRANTS:
case SQLCOM_SHOW_GRANTS_SELF:
{ {
LEX_USER *grant_user= get_current_user(thd, lex->grant_user); LEX_USER *grant_user= lex->grant_user;
if (!grant_user) if (!grant_user)
goto error; goto error;
if ((thd->security_ctx->priv_user && if (grant_user == &current_user ||
!strcmp(thd->security_ctx->priv_user, grant_user->user.str)) || grant_user == &current_role ||
grant_user == &current_user_and_current_role ||
!check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0)) !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0))
{ {
res = mysql_show_grants(thd, grant_user, res = mysql_show_grants(thd, grant_user);
(lex->sql_command == SQLCOM_SHOW_GRANTS_SELF) ?
TRUE : FALSE);
} }
break; break;
} }
......
...@@ -910,6 +910,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -910,6 +910,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CUBE_SYM /* SQL-2003-R */ %token CUBE_SYM /* SQL-2003-R */
%token CURDATE /* MYSQL-FUNC */ %token CURDATE /* MYSQL-FUNC */
%token CURRENT_USER /* SQL-2003-R */ %token CURRENT_USER /* SQL-2003-R */
%token CURRENT_ROLE /* SQL-2003-R */
%token CURRENT_POS_SYM %token CURRENT_POS_SYM
%token CURSOR_SYM /* SQL-2003-R */ %token CURSOR_SYM /* SQL-2003-R */
%token CURSOR_NAME_SYM /* SQL-2003-N */ %token CURSOR_NAME_SYM /* SQL-2003-N */
...@@ -11757,12 +11758,8 @@ show_param: ...@@ -11757,12 +11758,8 @@ show_param:
| GRANTS | GRANTS
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_GRANTS_SELF; lex->sql_command= SQLCOM_SHOW_GRANTS;
LEX_USER *curr_user; lex->grant_user= &current_user_and_current_role;
if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
bzero(curr_user, sizeof(st_lex_user));
lex->grant_user= curr_user;
} }
| GRANTS FOR_SYM user | GRANTS FOR_SYM user
{ {
...@@ -11771,6 +11768,12 @@ show_param: ...@@ -11771,6 +11768,12 @@ show_param:
lex->grant_user=$3; lex->grant_user=$3;
lex->grant_user->password=null_lex_str; lex->grant_user->password=null_lex_str;
} }
| GRANTS FOR_SYM CURRENT_ROLE optional_braces
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_GRANTS;
lex->grant_user= &current_role;
}
| CREATE DATABASE opt_if_not_exists ident | CREATE DATABASE opt_if_not_exists ident
{ {
Lex->sql_command=SQLCOM_SHOW_CREATE_DB; Lex->sql_command=SQLCOM_SHOW_CREATE_DB;
...@@ -13201,14 +13204,7 @@ user: ...@@ -13201,14 +13204,7 @@ user:
} }
| CURRENT_USER optional_braces | CURRENT_USER optional_braces
{ {
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) $$= &current_user;
MYSQL_YYABORT;
/*
empty LEX_USER means current_user and
will be handled in the get_current_user() function
later
*/
bzero($$, sizeof(LEX_USER));
} }
; ;
......
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