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();
|
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'
|
||||||
call 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);
|
select f1(1);
|
||||||
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.f1'
|
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.f1'
|
||||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;
|
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;
|
||||||
|
@ -617,3 +617,33 @@ SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci
|
|||||||
# Connection default
|
# Connection default
|
||||||
DROP USER user2@localhost;
|
DROP USER user2@localhost;
|
||||||
DROP DATABASE db1;
|
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 USER user2@localhost;
|
||||||
DROP DATABASE db1;
|
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
|
# Wait till all disconnects are completed
|
||||||
--source include/wait_until_count_sessions.inc
|
--source include/wait_until_count_sessions.inc
|
||||||
|
@ -6741,22 +6741,18 @@ Item_func_sp::execute_impl(THD *thd)
|
|||||||
{
|
{
|
||||||
bool err_status= TRUE;
|
bool err_status= TRUE;
|
||||||
Sub_statement_state statement_state;
|
Sub_statement_state statement_state;
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
Security_context *save_security_ctx= thd->security_ctx;
|
Security_context *save_security_ctx= thd->security_ctx;
|
||||||
#endif
|
|
||||||
enum enum_sp_data_access access=
|
enum enum_sp_data_access access=
|
||||||
(m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
|
(m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
|
||||||
SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess;
|
SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess;
|
||||||
|
|
||||||
DBUG_ENTER("Item_func_sp::execute_impl");
|
DBUG_ENTER("Item_func_sp::execute_impl");
|
||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
if (context->security_ctx)
|
if (context->security_ctx)
|
||||||
{
|
{
|
||||||
/* Set view definer security context */
|
/* Set view definer security context */
|
||||||
thd->security_ctx= context->security_ctx;
|
thd->security_ctx= context->security_ctx;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (sp_check_access(thd))
|
if (sp_check_access(thd))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -6784,9 +6780,7 @@ Item_func_sp::execute_impl(THD *thd)
|
|||||||
thd->restore_sub_statement_state(&statement_state);
|
thd->restore_sub_statement_state(&statement_state);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
thd->security_ctx= save_security_ctx;
|
thd->security_ctx= save_security_ctx;
|
||||||
#endif
|
|
||||||
|
|
||||||
DBUG_RETURN(err_status);
|
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_ENTER("Item_func_sp::sp_check_access");
|
||||||
DBUG_ASSERT(m_sp);
|
DBUG_ASSERT(m_sp);
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
if (check_routine_access(thd, EXECUTE_ACL,
|
if (check_routine_access(thd, EXECUTE_ACL,
|
||||||
m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
|
m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
#endif
|
|
||||||
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
@ -6873,7 +6865,29 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
|
|||||||
bool res;
|
bool res;
|
||||||
DBUG_ENTER("Item_func_sp::fix_fields");
|
DBUG_ENTER("Item_func_sp::fix_fields");
|
||||||
DBUG_ASSERT(fixed == 0);
|
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()
|
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(),
|
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))
|
open_and_lock_tables(thd, all_tables, TRUE, 0))
|
||||||
goto error;
|
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
|
By this moment all needed SPs should be in cache so no need to look
|
||||||
into DB.
|
into DB.
|
||||||
@ -4691,11 +4695,6 @@ create_sp_error:
|
|||||||
thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
|
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;
|
select_limit= thd->variables.select_limit;
|
||||||
thd->variables.select_limit= HA_POS_ERROR;
|
thd->variables.select_limit= HA_POS_ERROR;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user