mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-5849 MySQL bug#12602983 - User without privilege on routine can discover its existence by executing "select non_existing_func();" or by "call non_existing_proc()"
add or move privilege checks before existence checks
This commit is contained in:
@ -44,7 +44,7 @@ f1(1)
|
||||
call p1();
|
||||
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1'
|
||||
call P1();
|
||||
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1'
|
||||
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.P1'
|
||||
select f1(1);
|
||||
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.f1'
|
||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;
|
||||
|
@ -617,3 +617,33 @@ SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci
|
||||
# Connection default
|
||||
DROP USER user2@localhost;
|
||||
DROP DATABASE db1;
|
||||
#
|
||||
# Test for bug#12602983 - User without privilege on routine can discover
|
||||
# its existence by executing "select non_existing_func();" or by
|
||||
# "call non_existing_proc()";
|
||||
#
|
||||
drop database if exists mysqltest_db;
|
||||
create database mysqltest_db;
|
||||
create function mysqltest_db.f1() returns int return 0;
|
||||
create procedure mysqltest_db.p1() begin end;
|
||||
# Create user with no privileges on mysqltest_db database.
|
||||
create user bug12602983_user@localhost;
|
||||
# Connect as user 'bug12602983_user@localhost'
|
||||
# Attempt to execute routine on which user doesn't have privileges
|
||||
# should result in the same 'access denied' error whether
|
||||
# routine exists or not.
|
||||
select mysqltest_db.f_does_not_exist();
|
||||
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.f_does_not_exist'
|
||||
call mysqltest_db.p_does_not_exist();
|
||||
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.p_does_not_exist'
|
||||
select mysqltest_db.f1();
|
||||
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.f1'
|
||||
call mysqltest_db.p1();
|
||||
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.p1'
|
||||
create view bug12602983_v1 as select mysqltest_db.f_does_not_exist();
|
||||
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.f_does_not_exist'
|
||||
create view bug12602983_v1 as select mysqltest_db.f1();
|
||||
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.f1'
|
||||
# Connection 'default'.
|
||||
drop user bug12602983_user@localhost;
|
||||
drop database mysqltest_db;
|
||||
|
@ -995,6 +995,47 @@ disconnect con2;
|
||||
DROP USER user2@localhost;
|
||||
DROP DATABASE db1;
|
||||
|
||||
--echo #
|
||||
--echo # Test for bug#12602983 - User without privilege on routine can discover
|
||||
--echo # its existence by executing "select non_existing_func();" or by
|
||||
--echo # "call non_existing_proc()";
|
||||
--echo #
|
||||
--disable_warnings
|
||||
drop database if exists mysqltest_db;
|
||||
--enable_warnings
|
||||
create database mysqltest_db;
|
||||
create function mysqltest_db.f1() returns int return 0;
|
||||
create procedure mysqltest_db.p1() begin end;
|
||||
|
||||
--echo # Create user with no privileges on mysqltest_db database.
|
||||
create user bug12602983_user@localhost;
|
||||
|
||||
--echo # Connect as user 'bug12602983_user@localhost'
|
||||
connect (conn1, localhost, bug12602983_user,,);
|
||||
|
||||
--echo # Attempt to execute routine on which user doesn't have privileges
|
||||
--echo # should result in the same 'access denied' error whether
|
||||
--echo # routine exists or not.
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
select mysqltest_db.f_does_not_exist();
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
call mysqltest_db.p_does_not_exist();
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
select mysqltest_db.f1();
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
call mysqltest_db.p1();
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
create view bug12602983_v1 as select mysqltest_db.f_does_not_exist();
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
create view bug12602983_v1 as select mysqltest_db.f1();
|
||||
|
||||
--echo # Connection 'default'.
|
||||
connection default;
|
||||
disconnect conn1;
|
||||
drop user bug12602983_user@localhost;
|
||||
drop database mysqltest_db;
|
||||
|
||||
# Wait till all disconnects are completed
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
@ -6741,22 +6741,18 @@ Item_func_sp::execute_impl(THD *thd)
|
||||
{
|
||||
bool err_status= TRUE;
|
||||
Sub_statement_state statement_state;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
Security_context *save_security_ctx= thd->security_ctx;
|
||||
#endif
|
||||
enum enum_sp_data_access access=
|
||||
(m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
|
||||
SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess;
|
||||
|
||||
DBUG_ENTER("Item_func_sp::execute_impl");
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (context->security_ctx)
|
||||
{
|
||||
/* Set view definer security context */
|
||||
thd->security_ctx= context->security_ctx;
|
||||
}
|
||||
#endif
|
||||
if (sp_check_access(thd))
|
||||
goto error;
|
||||
|
||||
@ -6784,9 +6780,7 @@ Item_func_sp::execute_impl(THD *thd)
|
||||
thd->restore_sub_statement_state(&statement_state);
|
||||
|
||||
error:
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
thd->security_ctx= save_security_ctx;
|
||||
#endif
|
||||
|
||||
DBUG_RETURN(err_status);
|
||||
}
|
||||
@ -6857,11 +6851,9 @@ Item_func_sp::sp_check_access(THD *thd)
|
||||
{
|
||||
DBUG_ENTER("Item_func_sp::sp_check_access");
|
||||
DBUG_ASSERT(m_sp);
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (check_routine_access(thd, EXECUTE_ACL,
|
||||
m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
|
||||
DBUG_RETURN(TRUE);
|
||||
#endif
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
@ -6873,7 +6865,29 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
|
||||
bool res;
|
||||
DBUG_ENTER("Item_func_sp::fix_fields");
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
|
||||
|
||||
/*
|
||||
Checking privileges to execute the function while creating view and
|
||||
executing the function of select.
|
||||
*/
|
||||
if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) ||
|
||||
(thd->lex->sql_command == SQLCOM_CREATE_VIEW))
|
||||
{
|
||||
Security_context *save_security_ctx= thd->security_ctx;
|
||||
if (context->security_ctx)
|
||||
thd->security_ctx= context->security_ctx;
|
||||
|
||||
res= check_routine_access(thd, EXECUTE_ACL, m_name->m_db.str,
|
||||
m_name->m_name.str, 0, FALSE);
|
||||
thd->security_ctx= save_security_ctx;
|
||||
|
||||
if (res)
|
||||
{
|
||||
context->process_error(thd);
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
We must call init_result_field before Item_func::fix_fields()
|
||||
to make m_sp and result_field members available to fix_length_and_dec(),
|
||||
|
@ -4642,6 +4642,10 @@ create_sp_error:
|
||||
open_and_lock_tables(thd, all_tables, TRUE, 0))
|
||||
goto error;
|
||||
|
||||
if (check_routine_access(thd, EXECUTE_ACL, lex->spname->m_db.str,
|
||||
lex->spname->m_name.str, TRUE, FALSE))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
By this moment all needed SPs should be in cache so no need to look
|
||||
into DB.
|
||||
@ -4691,11 +4695,6 @@ create_sp_error:
|
||||
thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
|
||||
}
|
||||
|
||||
if (check_routine_access(thd, EXECUTE_ACL,
|
||||
sp->m_db.str, sp->m_name.str, TRUE, FALSE))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
select_limit= thd->variables.select_limit;
|
||||
thd->variables.select_limit= HA_POS_ERROR;
|
||||
|
||||
|
Reference in New Issue
Block a user