summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2014-03-20 23:26:41 +0100
committerSergei Golubchik <sergii@pisem.net>2014-03-20 23:26:41 +0100
commit7b1b744f53aca6ca77f06cb1980c40da666387d1 (patch)
tree1d42894ed10d0e66db74614304f04293ab33dcde
parent9ff0c9f730a79d4dab4303163d45c919f612cc37 (diff)
downloadmariadb-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.result2
-rw-r--r--mysql-test/r/sp-security.result30
-rw-r--r--mysql-test/t/sp-security.test41
-rw-r--r--sql/item_func.cc32
-rw-r--r--sql/sql_parse.cc9
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;