Commit d7743c41 authored by unknown's avatar unknown

BUG#18681: View privileges are broken

The check for view security was lacking several points :
1. Check with the right set of permissions : for each table ref that
participates in a view there were the right credentials to use in it's
security_ctx member, but these weren't used for checking the credentials.
This makes hard enforcing the SQL SECURITY DEFINER|INVOKER property
consistently.
2. Because of the above the security checking for views was just ruled out
in explicit ways in several places.
3. The security was checked only for the columns of the tables that are
brought into the query from a view. So if there is no column reference
outside of the view definition it was not detecting the lack of access to
the tables in the view in SQL SECURITY INVOKER mode.

The fix below tries to fix the above 3 points.


mysql-test/r/grant.result:
  removed nondeterminism (unspecified order) in some test output
mysql-test/r/view_grant.result:
  Somewhat extended test case for the bug and similar queries.
mysql-test/t/grant.test:
  removed nondeterminism (unspecified order) in some test output
mysql-test/t/view_grant.test:
  Somewhat extended test case for the bug and similar queries.
sql/mysql_priv.h:
  A wrapper for setup_tables that also checks access to the tables
sql/sql_acl.cc:
  removed artificial security check stop and used the table ref's credentials.
sql/sql_base.cc:
  a wrapper for setup_tables to check access to the tables
sql/sql_delete.cc:
  wrapper called.
sql/sql_insert.cc:
  wrapper called
sql/sql_load.cc:
  wrapper called
sql/sql_parse.cc:
  wrapper called and artificial check stop removed
sql/sql_select.cc:
  wrapper called
sql/sql_update.cc:
  wrapper called
sql/table.cc:
  Mask table access to the view error as well.
parent bb1c6bf6
...@@ -357,12 +357,12 @@ show grants for grant_user@localhost; ...@@ -357,12 +357,12 @@ show grants for grant_user@localhost;
Grants for grant_user@localhost Grants for grant_user@localhost
GRANT USAGE ON *.* TO 'grant_user'@'localhost' GRANT USAGE ON *.* TO 'grant_user'@'localhost'
GRANT INSERT (a, d, c, b) ON `test`.`t1` TO 'grant_user'@'localhost' GRANT INSERT (a, d, c, b) ON `test`.`t1` TO 'grant_user'@'localhost'
select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv order by Column_name;
Host Db User Table_name Column_name Column_priv Host Db User Table_name Column_name Column_priv
localhost test grant_user t1 b Insert
localhost test grant_user t1 d Insert
localhost test grant_user t1 a Insert localhost test grant_user t1 a Insert
localhost test grant_user t1 b Insert
localhost test grant_user t1 c Insert localhost test grant_user t1 c Insert
localhost test grant_user t1 d Insert
revoke ALL PRIVILEGES on t1 from grant_user@localhost; revoke ALL PRIVILEGES on t1 from grant_user@localhost;
show grants for grant_user@localhost; show grants for grant_user@localhost;
Grants for grant_user@localhost Grants for grant_user@localhost
...@@ -381,13 +381,27 @@ grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost; ...@@ -381,13 +381,27 @@ grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost;
grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost; grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost;
grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost; grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost;
grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost;
show grants for mysqltest_3@localhost; SELECT * FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES
Grants for mysqltest_3@localhost WHERE GRANTEE = '''mysqltest_3''@''localhost'''
GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost' ORDER BY TABLE_NAME,COLUMN_NAME,PRIVILEGE_TYPE;
GRANT SELECT (b) ON `mysqltest_1`.`t2` TO 'mysqltest_3'@'localhost' GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
GRANT UPDATE (a) ON `mysqltest_1`.`t1` TO 'mysqltest_3'@'localhost' 'mysqltest_3'@'localhost' NULL mysqltest_1 t1 a UPDATE NO
GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost' 'mysqltest_3'@'localhost' NULL mysqltest_2 t1 c SELECT NO
GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost' 'mysqltest_3'@'localhost' NULL mysqltest_1 t2 b SELECT NO
'mysqltest_3'@'localhost' NULL mysqltest_2 t2 d UPDATE NO
SELECT * FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES
WHERE GRANTEE = '''mysqltest_3''@''localhost'''
ORDER BY TABLE_NAME,PRIVILEGE_TYPE;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
SELECT * from INFORMATION_SCHEMA.SCHEMA_PRIVILEGES
WHERE GRANTEE = '''mysqltest_3''@''localhost'''
ORDER BY TABLE_SCHEMA,PRIVILEGE_TYPE;
GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
SELECT * from INFORMATION_SCHEMA.USER_PRIVILEGES
WHERE GRANTEE = '''mysqltest_3''@''localhost'''
ORDER BY TABLE_CATALOG,PRIVILEGE_TYPE;
GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'mysqltest_3'@'localhost' NULL USAGE NO
update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for column 'q' in table 't1' ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for column 'q' in table 't1'
update mysqltest_1.t2, mysqltest_2.t2 set d=20 where d=1; update mysqltest_1.t2, mysqltest_2.t2 set d=20 where d=1;
......
...@@ -533,3 +533,73 @@ View Create View ...@@ -533,3 +533,73 @@ View Create View
v2 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select 1 AS `1` v2 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select 1 AS `1`
drop view v1; drop view v1;
drop view v2; drop view v2;
CREATE DATABASE mysqltest1;
CREATE USER readonly@localhost;
CREATE TABLE mysqltest1.t1 (x INT);
INSERT INTO mysqltest1.t1 VALUES (1), (2);
CREATE SQL SECURITY INVOKER VIEW mysqltest1.v_t1 AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ts AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ti AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tu AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tus AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_td AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tds AS SELECT * FROM mysqltest1.t1;
GRANT SELECT, INSERT, UPDATE, DELETE ON mysqltest1.v_t1 TO readonly;
GRANT SELECT ON mysqltest1.v_ts TO readonly;
GRANT INSERT ON mysqltest1.v_ti TO readonly;
GRANT UPDATE ON mysqltest1.v_tu TO readonly;
GRANT UPDATE,SELECT ON mysqltest1.v_tus TO readonly;
GRANT DELETE ON mysqltest1.v_td TO readonly;
GRANT DELETE,SELECT ON mysqltest1.v_tds TO readonly;
SELECT * FROM mysqltest1.v_t1;
ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
INSERT INTO mysqltest1.v_t1 VALUES(4);
ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
DELETE FROM mysqltest1.v_t1 WHERE x = 1;
ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
UPDATE mysqltest1.v_t1 SET x = 3 WHERE x = 2;
ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
UPDATE mysqltest1.v_t1 SET x = 3;
ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
DELETE FROM mysqltest1.v_t1;
ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
SELECT 1 FROM mysqltest1.v_t1;
ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
SELECT * FROM mysqltest1.t1;
ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for table 't1'
SELECT * FROM mysqltest1.v_ts;
x
1
2
SELECT * FROM mysqltest1.v_ts, mysqltest1.t1 WHERE mysqltest1.t1.x = mysqltest1.v_ts.x;
ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for table 't1'
SELECT * FROM mysqltest1.v_ti;
ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for table 'v_ti'
INSERT INTO mysqltest1.v_ts VALUES (100);
ERROR 42000: INSERT command denied to user 'readonly'@'localhost' for table 'v_ts'
INSERT INTO mysqltest1.v_ti VALUES (100);
UPDATE mysqltest1.v_ts SET x= 200 WHERE x = 100;
ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_ts'
UPDATE mysqltest1.v_ts SET x= 200;
ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_ts'
UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tu SET x= 200;
DELETE FROM mysqltest1.v_ts WHERE x= 200;
ERROR 42000: DELETE command denied to user 'readonly'@'localhost' for table 'v_ts'
DELETE FROM mysqltest1.v_ts;
ERROR 42000: DELETE command denied to user 'readonly'@'localhost' for table 'v_ts'
DELETE FROM mysqltest1.v_td WHERE x= 200;
ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for column 'x' in table 'v_td'
DELETE FROM mysqltest1.v_tds WHERE x= 200;
DELETE FROM mysqltest1.v_td;
DROP VIEW mysqltest1.v_tds;
DROP VIEW mysqltest1.v_td;
DROP VIEW mysqltest1.v_tus;
DROP VIEW mysqltest1.v_tu;
DROP VIEW mysqltest1.v_ti;
DROP VIEW mysqltest1.v_ts;
DROP VIEW mysqltest1.v_t1;
DROP TABLE mysqltest1.t1;
DROP USER readonly@localhost;
DROP DATABASE mysqltest1;
...@@ -302,7 +302,7 @@ DROP DATABASE testdb10; ...@@ -302,7 +302,7 @@ DROP DATABASE testdb10;
create table t1(a int, b int, c int, d int); create table t1(a int, b int, c int, d int);
grant insert(b), insert(c), insert(d), insert(a) on t1 to grant_user@localhost; grant insert(b), insert(c), insert(d), insert(a) on t1 to grant_user@localhost;
show grants for grant_user@localhost; show grants for grant_user@localhost;
select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv order by Column_name;
revoke ALL PRIVILEGES on t1 from grant_user@localhost; revoke ALL PRIVILEGES on t1 from grant_user@localhost;
show grants for grant_user@localhost; show grants for grant_user@localhost;
select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv;
...@@ -326,7 +326,18 @@ grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost; ...@@ -326,7 +326,18 @@ grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost;
grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost;
connect (conn1,localhost,mysqltest_3,,); connect (conn1,localhost,mysqltest_3,,);
connection conn1; connection conn1;
show grants for mysqltest_3@localhost; SELECT * FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES
WHERE GRANTEE = '''mysqltest_3''@''localhost'''
ORDER BY TABLE_NAME,COLUMN_NAME,PRIVILEGE_TYPE;
SELECT * FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES
WHERE GRANTEE = '''mysqltest_3''@''localhost'''
ORDER BY TABLE_NAME,PRIVILEGE_TYPE;
SELECT * from INFORMATION_SCHEMA.SCHEMA_PRIVILEGES
WHERE GRANTEE = '''mysqltest_3''@''localhost'''
ORDER BY TABLE_SCHEMA,PRIVILEGE_TYPE;
SELECT * from INFORMATION_SCHEMA.USER_PRIVILEGES
WHERE GRANTEE = '''mysqltest_3''@''localhost'''
ORDER BY TABLE_CATALOG,PRIVILEGE_TYPE;
--error 1143 --error 1143
update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
--error 1143 --error 1143
......
...@@ -712,3 +712,84 @@ show create view v1; ...@@ -712,3 +712,84 @@ show create view v1;
show create view v2; show create view v2;
drop view v1; drop view v1;
drop view v2; drop view v2;
#
# Bug#18681: View privileges are broken
#
CREATE DATABASE mysqltest1;
CREATE USER readonly@localhost;
CREATE TABLE mysqltest1.t1 (x INT);
INSERT INTO mysqltest1.t1 VALUES (1), (2);
CREATE SQL SECURITY INVOKER VIEW mysqltest1.v_t1 AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ts AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ti AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tu AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tus AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_td AS SELECT * FROM mysqltest1.t1;
CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tds AS SELECT * FROM mysqltest1.t1;
GRANT SELECT, INSERT, UPDATE, DELETE ON mysqltest1.v_t1 TO readonly;
GRANT SELECT ON mysqltest1.v_ts TO readonly;
GRANT INSERT ON mysqltest1.v_ti TO readonly;
GRANT UPDATE ON mysqltest1.v_tu TO readonly;
GRANT UPDATE,SELECT ON mysqltest1.v_tus TO readonly;
GRANT DELETE ON mysqltest1.v_td TO readonly;
GRANT DELETE,SELECT ON mysqltest1.v_tds TO readonly;
CONNECT (n1,localhost,readonly,,);
CONNECTION n1;
--error 1356
SELECT * FROM mysqltest1.v_t1;
--error 1356
INSERT INTO mysqltest1.v_t1 VALUES(4);
--error 1356
DELETE FROM mysqltest1.v_t1 WHERE x = 1;
--error 1356
UPDATE mysqltest1.v_t1 SET x = 3 WHERE x = 2;
--error 1356
UPDATE mysqltest1.v_t1 SET x = 3;
--error 1356
DELETE FROM mysqltest1.v_t1;
--error 1356
SELECT 1 FROM mysqltest1.v_t1;
--error 1142
SELECT * FROM mysqltest1.t1;
SELECT * FROM mysqltest1.v_ts;
--error 1142
SELECT * FROM mysqltest1.v_ts, mysqltest1.t1 WHERE mysqltest1.t1.x = mysqltest1.v_ts.x;
--error 1142
SELECT * FROM mysqltest1.v_ti;
--error 1142
INSERT INTO mysqltest1.v_ts VALUES (100);
INSERT INTO mysqltest1.v_ti VALUES (100);
--error 1142
UPDATE mysqltest1.v_ts SET x= 200 WHERE x = 100;
--error 1142
UPDATE mysqltest1.v_ts SET x= 200;
UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tu SET x= 200;
--error 1142
DELETE FROM mysqltest1.v_ts WHERE x= 200;
--error 1142
DELETE FROM mysqltest1.v_ts;
--error 1143
DELETE FROM mysqltest1.v_td WHERE x= 200;
DELETE FROM mysqltest1.v_tds WHERE x= 200;
DELETE FROM mysqltest1.v_td;
CONNECTION default;
DROP VIEW mysqltest1.v_tds;
DROP VIEW mysqltest1.v_td;
DROP VIEW mysqltest1.v_tus;
DROP VIEW mysqltest1.v_tu;
DROP VIEW mysqltest1.v_ti;
DROP VIEW mysqltest1.v_ts;
DROP VIEW mysqltest1.v_t1;
DROP TABLE mysqltest1.t1;
DROP USER readonly@localhost;
DROP DATABASE mysqltest1;
...@@ -946,6 +946,13 @@ bool insert_fields(THD *thd, Name_resolution_context *context, ...@@ -946,6 +946,13 @@ bool insert_fields(THD *thd, Name_resolution_context *context,
bool setup_tables(THD *thd, Name_resolution_context *context, bool setup_tables(THD *thd, Name_resolution_context *context,
List<TABLE_LIST> *from_clause, TABLE_LIST *tables, List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
Item **conds, TABLE_LIST **leaves, bool select_insert); Item **conds, TABLE_LIST **leaves, bool select_insert);
bool setup_tables_and_check_access (THD *thd,
Name_resolution_context *context,
List<TABLE_LIST> *from_clause,
TABLE_LIST *tables, Item **conds,
TABLE_LIST **leaves,
bool select_insert,
ulong want_access);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num); List<Item> *sum_func_list, uint wild_num);
bool setup_fields(THD *thd, Item** ref_pointer_array, bool setup_fields(THD *thd, Item** ref_pointer_array,
......
...@@ -3562,6 +3562,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -3562,6 +3562,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table(); TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table();
Security_context *sctx= thd->security_ctx; Security_context *sctx= thd->security_ctx;
uint i; uint i;
ulong orig_want_access= want_access;
DBUG_ENTER("check_grant"); DBUG_ENTER("check_grant");
DBUG_ASSERT(number > 0); DBUG_ASSERT(number > 0);
...@@ -3583,18 +3584,22 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -3583,18 +3584,22 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
} }
want_access&= ~sctx->master_access;
if (!want_access)
DBUG_RETURN(0); // ok
rw_rdlock(&LOCK_grant); rw_rdlock(&LOCK_grant);
for (table= tables; for (table= tables;
table && number-- && table != first_not_own_table; table && number-- && table != first_not_own_table;
table= table->next_global) table= table->next_global)
{ {
GRANT_TABLE *grant_table; GRANT_TABLE *grant_table;
sctx = test(table->security_ctx) ?
table->security_ctx : thd->security_ctx;
want_access= orig_want_access;
want_access&= ~sctx->master_access;
if (!want_access)
continue; // ok
if (!(~table->grant.privilege & want_access) || if (!(~table->grant.privilege & want_access) ||
table->derived || table->schema_table || table->belong_to_view) table->derived || table->schema_table)
{ {
/* /*
It is subquery in the FROM clause. VIEW set table->derived after It is subquery in the FROM clause. VIEW set table->derived after
......
...@@ -4497,6 +4497,58 @@ bool setup_tables(THD *thd, Name_resolution_context *context, ...@@ -4497,6 +4497,58 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
} }
/*
prepare tables and check access for the view tables
SYNOPSIS
setup_tables_and_check_view_access()
thd Thread handler
context name resolution contest to setup table list there
from_clause Top-level list of table references in the FROM clause
tables Table list (select_lex->table_list)
conds Condition of current SELECT (can be changed by VIEW)
leaves List of join table leaves list (select_lex->leaf_tables)
refresh It is onle refresh for subquery
select_insert It is SELECT ... INSERT command
want_access what access is needed
NOTE
a wrapper for check_tables that will also check the resulting
table leaves list for access to all the tables that belong to a view
RETURN
FALSE ok; In this case *map will include the chosen index
TRUE error
*/
bool setup_tables_and_check_access(THD *thd,
Name_resolution_context *context,
List<TABLE_LIST> *from_clause,
TABLE_LIST *tables,
Item **conds, TABLE_LIST **leaves,
bool select_insert,
ulong want_access)
{
TABLE_LIST *leaves_tmp = NULL;
if (setup_tables (thd, context, from_clause, tables, conds,
&leaves_tmp, select_insert))
return TRUE;
if (leaves)
*leaves = leaves_tmp;
for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf)
if (leaves_tmp->belong_to_view &&
check_one_table_access(thd, want_access, leaves_tmp))
{
tables->hide_view_error(thd);
return TRUE;
}
return FALSE;
}
/* /*
Create a key_map from a list of index names Create a key_map from a list of index names
......
...@@ -334,10 +334,11 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) ...@@ -334,10 +334,11 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
DBUG_ENTER("mysql_prepare_delete"); DBUG_ENTER("mysql_prepare_delete");
thd->lex->allow_sum_func= 0; thd->lex->allow_sum_func= 0;
if (setup_tables(thd, &thd->lex->select_lex.context, if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
table_list, conds, &select_lex->leaf_tables, table_list, conds,
FALSE) || &select_lex->leaf_tables, FALSE,
DELETE_ACL) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
setup_ftfuncs(select_lex)) setup_ftfuncs(select_lex))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -396,10 +397,11 @@ bool mysql_multi_delete_prepare(THD *thd) ...@@ -396,10 +397,11 @@ bool mysql_multi_delete_prepare(THD *thd)
lex->query_tables also point on local list of DELETE SELECT_LEX lex->query_tables also point on local list of DELETE SELECT_LEX
*/ */
if (setup_tables(thd, &thd->lex->select_lex.context, if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
lex->query_tables, &lex->select_lex.where, lex->query_tables, &lex->select_lex.where,
&lex->select_lex.leaf_tables, FALSE)) &lex->select_lex.leaf_tables, FALSE,
DELETE_ACL))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
......
...@@ -743,10 +743,11 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, ...@@ -743,10 +743,11 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
bool insert_into_view= (table_list->view != 0); bool insert_into_view= (table_list->view != 0);
DBUG_ENTER("mysql_prepare_insert_check_table"); DBUG_ENTER("mysql_prepare_insert_check_table");
if (setup_tables(thd, &thd->lex->select_lex.context, if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
table_list, where, &thd->lex->select_lex.leaf_tables, table_list, where,
select_insert)) &thd->lex->select_lex.leaf_tables,
select_insert, INSERT_ACL))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (insert_into_view && !fields.elements) if (insert_into_view && !fields.elements)
......
...@@ -153,10 +153,11 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -153,10 +153,11 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
ha_enable_transaction(thd, FALSE); ha_enable_transaction(thd, FALSE);
if (open_and_lock_tables(thd, table_list)) if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (setup_tables(thd, &thd->lex->select_lex.context, if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
table_list, &unused_conds, table_list, &unused_conds,
&thd->lex->select_lex.leaf_tables, FALSE)) &thd->lex->select_lex.leaf_tables, FALSE,
INSERT_ACL | UPDATE_ACL))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (!table_list->table || // do not suport join view if (!table_list->table || // do not suport join view
!table_list->updatable || // and derived tables !table_list->updatable || // and derived tables
......
...@@ -4994,23 +4994,35 @@ error: ...@@ -4994,23 +4994,35 @@ error:
bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
{ {
Security_context * backup_ctx= thd->security_ctx;
/* we need to switch to the saved context (if any) */
if (all_tables->security_ctx)
thd->security_ctx= all_tables->security_ctx;
if (check_access(thd, privilege, all_tables->db, if (check_access(thd, privilege, all_tables->db,
&all_tables->grant.privilege, 0, 0, &all_tables->grant.privilege, 0, 0,
test(all_tables->schema_table))) test(all_tables->schema_table)))
return 1; goto deny;
/* Show only 1 table for check_grant */ /* Show only 1 table for check_grant */
if (grant_option && check_grant(thd, privilege, all_tables, 0, 1, 0)) if (grant_option && check_grant(thd, privilege, all_tables, 0, 1, 0))
return 1; goto deny;
thd->security_ctx= backup_ctx;
/* Check rights on tables of subselects and implictly opened tables */ /* Check rights on tables of subselects and implictly opened tables */
TABLE_LIST *subselects_tables; TABLE_LIST *subselects_tables;
if ((subselects_tables= all_tables->next_global)) if ((subselects_tables= all_tables->next_global))
{ {
if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0))) if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
return 1; goto deny;
} }
return 0; return 0;
deny:
thd->security_ctx= backup_ctx;
return 1;
} }
...@@ -5191,6 +5203,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, ...@@ -5191,6 +5203,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
ulong found_access=0; ulong found_access=0;
TABLE_LIST *org_tables= tables; TABLE_LIST *org_tables= tables;
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx;
/* /*
The check that first_not_own_table is not reached is for the case when The check that first_not_own_table is not reached is for the case when
the given table list refers to the list for prelocking (contains tables the given table list refers to the list for prelocking (contains tables
...@@ -5198,12 +5211,17 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, ...@@ -5198,12 +5211,17 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
*/ */
for (; tables != first_not_own_table; tables= tables->next_global) for (; tables != first_not_own_table; tables= tables->next_global)
{ {
if (tables->security_ctx)
sctx= tables->security_ctx;
else
sctx= backup_ctx;
if (tables->schema_table && if (tables->schema_table &&
(want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL))) (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
{ {
if (!no_errors) if (!no_errors)
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
thd->security_ctx->priv_user, thd->security_ctx->priv_host, sctx->priv_user, sctx->priv_host,
information_schema_name.str); information_schema_name.str);
return TRUE; return TRUE;
} }
...@@ -5212,12 +5230,13 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, ...@@ -5212,12 +5230,13 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
Remove SHOW_VIEW_ACL, because it will be checked during making view Remove SHOW_VIEW_ACL, because it will be checked during making view
*/ */
tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
if (tables->derived || tables->schema_table || tables->belong_to_view || if (tables->derived || tables->schema_table ||
(tables->table && (int)tables->table->s->tmp_table) || (tables->table && (int)tables->table->s->tmp_table) ||
my_tz_check_n_skip_implicit_tables(&tables, my_tz_check_n_skip_implicit_tables(&tables,
thd->lex->time_zone_tables_used)) thd->lex->time_zone_tables_used))
continue; continue;
if ((thd->security_ctx->master_access & want_access) == thd->security_ctx= sctx;
if ((sctx->master_access & want_access) ==
(want_access & ~EXTRA_ACL) && (want_access & ~EXTRA_ACL) &&
thd->db) thd->db)
tables->grant.privilege= want_access; tables->grant.privilege= want_access;
...@@ -5229,19 +5248,23 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, ...@@ -5229,19 +5248,23 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
{ {
if (check_access(thd,want_access,tables->db,&tables->grant.privilege, if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
0, no_errors, test(tables->schema_table))) 0, no_errors, test(tables->schema_table)))
return TRUE; // Access denied goto deny; // Access denied
found_access=tables->grant.privilege; found_access=tables->grant.privilege;
found=1; found=1;
} }
} }
else if (check_access(thd,want_access,tables->db,&tables->grant.privilege, else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
0, no_errors, test(tables->schema_table))) 0, no_errors, test(tables->schema_table)))
return TRUE; goto deny;
} }
thd->security_ctx= backup_ctx;
if (grant_option) if (grant_option)
return check_grant(thd,want_access & ~EXTRA_ACL,org_tables, return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
test(want_access & EXTRA_ACL), UINT_MAX, no_errors); test(want_access & EXTRA_ACL), UINT_MAX, no_errors);
return FALSE; return FALSE;
deny:
thd->security_ctx= backup_ctx;
return TRUE;
} }
......
...@@ -337,9 +337,10 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -337,9 +337,10 @@ JOIN::prepare(Item ***rref_pointer_array,
/* Check that all tables, fields, conds and order are ok */ /* Check that all tables, fields, conds and order are ok */
if ((!(select_options & OPTION_SETUP_TABLES_DONE) && if ((!(select_options & OPTION_SETUP_TABLES_DONE) &&
setup_tables(thd, &select_lex->context, join_list, setup_tables_and_check_access(thd, &select_lex->context, join_list,
tables_list, &conds, &select_lex->leaf_tables, tables_list, &conds,
FALSE)) || &select_lex->leaf_tables, FALSE,
SELECT_ACL)) ||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
select_lex->setup_ref_array(thd, og_num) || select_lex->setup_ref_array(thd, og_num) ||
setup_fields(thd, (*rref_pointer_array), fields_list, 1, setup_fields(thd, (*rref_pointer_array), fields_list, 1,
......
...@@ -613,9 +613,11 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, ...@@ -613,9 +613,11 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
tables.alias= table_list->alias; tables.alias= table_list->alias;
thd->lex->allow_sum_func= 0; thd->lex->allow_sum_func= 0;
if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, if (setup_tables_and_check_access(thd, &select_lex->context,
table_list, conds, &select_lex->leaf_tables, &select_lex->top_join_list,
FALSE) || table_list, conds,
&select_lex->leaf_tables,
FALSE, UPDATE_ACL) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
select_lex->setup_ref_array(thd, order_num) || select_lex->setup_ref_array(thd, order_num) ||
setup_order(thd, select_lex->ref_pointer_array, setup_order(thd, select_lex->ref_pointer_array,
...@@ -706,10 +708,11 @@ reopen_tables: ...@@ -706,10 +708,11 @@ reopen_tables:
call in setup_tables()). call in setup_tables()).
*/ */
if (setup_tables(thd, &lex->select_lex.context, if (setup_tables_and_check_access(thd, &lex->select_lex.context,
&lex->select_lex.top_join_list, &lex->select_lex.top_join_list,
table_list, &lex->select_lex.where, table_list, &lex->select_lex.where,
&lex->select_lex.leaf_tables, FALSE)) &lex->select_lex.leaf_tables, FALSE,
UPDATE_ACL))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0)) if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0))
......
...@@ -2068,7 +2068,8 @@ void st_table_list::hide_view_error(THD *thd) ...@@ -2068,7 +2068,8 @@ void st_table_list::hide_view_error(THD *thd)
if (thd->net.last_errno == ER_BAD_FIELD_ERROR || if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
thd->net.last_errno == ER_SP_DOES_NOT_EXIST || thd->net.last_errno == ER_SP_DOES_NOT_EXIST ||
thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR || thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR ||
thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR) thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR ||
thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR)
{ {
TABLE_LIST *top= top_table(); TABLE_LIST *top= top_table();
thd->clear_error(); thd->clear_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