diff options
author | Sergei Golubchik <sergii@pisem.net> | 2014-03-20 23:26:41 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2014-03-20 23:26:41 +0100 |
commit | 7b1b744f53aca6ca77f06cb1980c40da666387d1 (patch) | |
tree | 1d42894ed10d0e66db74614304f04293ab33dcde | |
parent | 9ff0c9f730a79d4dab4303163d45c919f612cc37 (diff) | |
download | mariadb-git-7b1b744f53aca6ca77f06cb1980c40da666387d1.tar.gz |
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
-rw-r--r-- | mysql-test/r/lowercase_fs_off.result | 2 | ||||
-rw-r--r-- | mysql-test/r/sp-security.result | 30 | ||||
-rw-r--r-- | mysql-test/t/sp-security.test | 41 | ||||
-rw-r--r-- | sql/item_func.cc | 32 | ||||
-rw-r--r-- | sql/sql_parse.cc | 9 |
5 files changed, 99 insertions, 15 deletions
diff --git a/mysql-test/r/lowercase_fs_off.result b/mysql-test/r/lowercase_fs_off.result index c3284b225dd..9b819cf3843 100644 --- a/mysql-test/r/lowercase_fs_off.result +++ b/mysql-test/r/lowercase_fs_off.result @@ -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; diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index 88908b05f46..e8c3fbff0e3 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -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; diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index ca4e6b04f13..a2079e91440 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -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 diff --git a/sql/item_func.cc b/sql/item_func.cc index c659d7964b9..eb176d7e490 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -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(), diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 18e1a441f68..f2bbd7462fd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -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; |