summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2017-11-14 12:22:30 -0800
committerIgor Babaev <igor@askmonty.org>2017-11-14 12:23:31 -0800
commit3afc9629fd84fbbc615f02aac0154e6b5ba92168 (patch)
tree9445aa9d8ee86603d34577344e4e82912d1a85b3
parent24184938ad9954f25c082a1afd74a053a8ab6d8c (diff)
downloadmariadb-git-3afc9629fd84fbbc615f02aac0154e6b5ba92168.tar.gz
Fixed bug mdev-13453 Executing a query via CTE requires more permissions
than the query itself ACL checks were not properly supported for tables used in CTE specifications. This patch fixes the problem.
-rw-r--r--mysql-test/r/cte_nonrecursive.result58
-rw-r--r--mysql-test/t/cte_nonrecursive.test51
-rw-r--r--sql/sql_acl.cc4
-rw-r--r--sql/sql_cte.cc3
-rw-r--r--sql/sql_parse.cc8
5 files changed, 123 insertions, 1 deletions
diff --git a/mysql-test/r/cte_nonrecursive.result b/mysql-test/r/cte_nonrecursive.result
index ebe1aae1e8f..21a1fa3164f 100644
--- a/mysql-test/r/cte_nonrecursive.result
+++ b/mysql-test/r/cte_nonrecursive.result
@@ -1147,3 +1147,61 @@ SELECT * FROM cte_test;
a
1
DROP VIEW cte_test;
+#
+# MDEV-13453: privileges checking for CTE
+#
+create database db;
+use db;
+create table t1 (i int);
+insert into t1
+values (3), (7), (1), (4), (2), (3), (1);
+create table t2 (a int, b int);
+insert into t2
+values (3,10), (7,11), (1,17), (4,15), (2,11), (3,10), (1,15);
+create user foo@localhost;
+grant SELECT on db.t1 to foo@localhost;
+grant SELECT(a) on db.t2 to foo@localhost;
+connect con1,localhost,foo,,;
+use db;
+with cte as (select * from t1 where i < 4)
+select * from cte;
+i
+3
+1
+2
+3
+1
+with cte as (select * from t1 where i < 4 group by i)
+select * from cte;
+i
+1
+2
+3
+with cte as (select * from t1 where i < 4)
+select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2;
+i
+1
+3
+with cte as (select * from t1 where i < 4 group by i)
+select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2;
+i
+1
+3
+with cte as (select b from t2 where a < 4)
+select * from cte cte1 where b < 15 union select * from cte cte2 where b > 15;
+ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'b' in table 't2'
+with cte as (select a from t2 where a < 4)
+select * from cte cte1 where a < 2 union select * from cte cte2 where a > 2;
+a
+1
+3
+connection default;
+revoke SELECT on db.t1 from foo@localhost;
+connection con1;
+with cte as (select * from t1 where i < 4)
+select * from cte;
+ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1'
+disconnect con1;
+connection default;
+drop database db;
+drop user foo@localhost;
diff --git a/mysql-test/t/cte_nonrecursive.test b/mysql-test/t/cte_nonrecursive.test
index 742e8f6e4d7..03e6e298fa8 100644
--- a/mysql-test/t/cte_nonrecursive.test
+++ b/mysql-test/t/cte_nonrecursive.test
@@ -790,3 +790,54 @@ SHOW CREATE VIEW cte_test;
SELECT * FROM cte_test;
DROP VIEW cte_test;
+
+--echo #
+--echo # MDEV-13453: privileges checking for CTE
+--echo #
+
+create database db;
+use db;
+create table t1 (i int);
+insert into t1
+ values (3), (7), (1), (4), (2), (3), (1);
+
+create table t2 (a int, b int);
+insert into t2
+ values (3,10), (7,11), (1,17), (4,15), (2,11), (3,10), (1,15);
+
+create user foo@localhost;
+grant SELECT on db.t1 to foo@localhost;
+grant SELECT(a) on db.t2 to foo@localhost;
+
+--connect (con1,localhost,foo,,)
+use db;
+with cte as (select * from t1 where i < 4)
+ select * from cte;
+with cte as (select * from t1 where i < 4 group by i)
+ select * from cte;
+with cte as (select * from t1 where i < 4)
+ select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2;
+with cte as (select * from t1 where i < 4 group by i)
+ select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2;
+
+--error ER_COLUMNACCESS_DENIED_ERROR
+with cte as (select b from t2 where a < 4)
+ select * from cte cte1 where b < 15 union select * from cte cte2 where b > 15;
+with cte as (select a from t2 where a < 4)
+ select * from cte cte1 where a < 2 union select * from cte cte2 where a > 2;
+
+--connection default
+revoke SELECT on db.t1 from foo@localhost;
+
+--connection con1
+
+--error ER_TABLEACCESS_DENIED_ERROR
+with cte as (select * from t1 where i < 4)
+ select * from cte;
+
+# Cleanup
+--disconnect con1
+
+--connection default
+drop database db;
+drop user foo@localhost;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 555865804f9..74f06e7654d 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -7557,6 +7557,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
tl->correspondent_table ? tl->correspondent_table : tl;
sctx= t_ref->security_ctx ? t_ref->security_ctx : thd->security_ctx;
+ if (tl->with ||
+ (tl->with= tl->select_lex->find_table_def_in_with_clauses(tl)))
+ continue;
+
const ACL_internal_table_access *access=
get_cached_table_access(&t_ref->grant.m_internal,
t_ref->get_db_name(),
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index 6fe08e3c0ed..e1bd455830d 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -823,9 +823,10 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
tbl;
tbl= tbl->next_global)
{
- tbl->grant.privilege= with_table->grant.privilege;
spec_tables_tail= tbl;
}
+ if (check_table_access(thd, SELECT_ACL, spec_tables, FALSE, UINT_MAX, FALSE))
+ goto err;
if (spec_tables)
{
if (with_table->next_global)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index bf5144bfda6..fff58427aff 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3443,6 +3443,14 @@ mysql_execute_command(THD *thd)
ulong privileges_requested= lex->exchange ? SELECT_ACL | FILE_ACL :
SELECT_ACL;
+ /*
+ The same function must be called for DML commands
+ when CTEs are supported in DML statements
+ */
+ res= check_dependencies_in_with_clauses(thd->lex->with_clauses_list);
+ if (res)
+ break;
+
if (all_tables)
res= check_table_access(thd,
privileges_requested,