Commit 7b1b744f authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-5849 MySQL bug#12602983 - User without privilege on routine can discover...

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
parent 9ff0c9f7
......@@ -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 @@ case SQLCOM_PREPARE:
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 @@ case SQLCOM_PREPARE:
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;
......
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