diff options
-rw-r--r-- | mysql-test/r/grant.result | 34 | ||||
-rw-r--r-- | mysql-test/r/view_grant.result | 70 | ||||
-rw-r--r-- | mysql-test/t/grant.test | 15 | ||||
-rw-r--r-- | mysql-test/t/view_grant.test | 81 | ||||
-rw-r--r-- | sql/mysql_priv.h | 7 | ||||
-rw-r--r-- | sql/sql_acl.cc | 15 | ||||
-rw-r--r-- | sql/sql_base.cc | 52 | ||||
-rw-r--r-- | sql/sql_delete.cc | 18 | ||||
-rw-r--r-- | sql/sql_insert.cc | 9 | ||||
-rw-r--r-- | sql/sql_load.cc | 9 | ||||
-rw-r--r-- | sql/sql_parse.cc | 39 | ||||
-rw-r--r-- | sql/sql_select.cc | 7 | ||||
-rw-r--r-- | sql/sql_update.cc | 17 | ||||
-rw-r--r-- | sql/table.cc | 3 |
14 files changed, 324 insertions, 52 deletions
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 3432de5179a..07fc120da93 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -357,12 +357,12 @@ show grants for grant_user@localhost; Grants for grant_user@localhost GRANT USAGE ON *.* 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 -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 b Insert localhost test grant_user t1 c Insert +localhost test grant_user t1 d Insert revoke ALL PRIVILEGES on t1 from grant_user@localhost; show 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; grant select (b) on mysqltest_1.t2 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; -show grants for mysqltest_3@localhost; -Grants for mysqltest_3@localhost -GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost' -GRANT SELECT (b) ON `mysqltest_1`.`t2` TO 'mysqltest_3'@'localhost' -GRANT UPDATE (a) ON `mysqltest_1`.`t1` TO 'mysqltest_3'@'localhost' -GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost' -GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost' +SELECT * FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES +WHERE GRANTEE = '''mysqltest_3''@''localhost''' +ORDER BY TABLE_NAME,COLUMN_NAME,PRIVILEGE_TYPE; +GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE +'mysqltest_3'@'localhost' NULL mysqltest_1 t1 a UPDATE NO +'mysqltest_3'@'localhost' NULL mysqltest_2 t1 c SELECT NO +'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; 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; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 29b3e710573..f6559e6f838 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -533,6 +533,76 @@ View Create View v2 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select 1 AS `1` drop view v1; 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; CREATE TABLE t1 (a INT PRIMARY KEY); INSERT INTO t1 VALUES (1), (2), (3); CREATE DEFINER = 'no-such-user'@localhost VIEW v AS SELECT a from t1; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 97f13381557..3db38d93ee1 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -302,7 +302,7 @@ DROP DATABASE testdb10; 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; 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; show grants for grant_user@localhost; 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; grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; connect (conn1,localhost,mysqltest_3,,); 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 update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; --error 1143 diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index e7148418ac5..4663a667d25 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -714,6 +714,87 @@ drop view v1; 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; + +# # BUG#14875: Bad view DEFINER makes SHOW CREATE VIEW fail # CREATE TABLE t1 (a INT PRIMARY KEY); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index f300c72c4ac..6d39f2f7440 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -947,6 +947,13 @@ bool insert_fields(THD *thd, Name_resolution_context *context, bool setup_tables(THD *thd, Name_resolution_context *context, List<TABLE_LIST> *from_clause, TABLE_LIST *tables, 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, List<Item> *sum_func_list, uint wild_num); bool setup_fields(THD *thd, Item** ref_pointer_array, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 197c703ece3..46b1b8795b6 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3564,6 +3564,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(); Security_context *sctx= thd->security_ctx; uint i; + ulong orig_want_access= want_access; DBUG_ENTER("check_grant"); DBUG_ASSERT(number > 0); @@ -3585,18 +3586,22 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, 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); for (table= tables; table && number-- && table != first_not_own_table; table= table->next_global) { 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) || - 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 diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9bc4ac8dc83..75b69c91846 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4504,6 +4504,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 SYNOPSIS diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 37c4f9a3256..af20b770c56 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -334,10 +334,11 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) DBUG_ENTER("mysql_prepare_delete"); thd->lex->allow_sum_func= 0; - if (setup_tables(thd, &thd->lex->select_lex.context, - &thd->lex->select_lex.top_join_list, - table_list, conds, &select_lex->leaf_tables, - FALSE) || + if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, + &thd->lex->select_lex.top_join_list, + table_list, conds, + &select_lex->leaf_tables, FALSE, + DELETE_ACL) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); @@ -396,10 +397,11 @@ bool mysql_multi_delete_prepare(THD *thd) lex->query_tables also point on local list of DELETE SELECT_LEX */ - if (setup_tables(thd, &thd->lex->select_lex.context, - &thd->lex->select_lex.top_join_list, - lex->query_tables, &lex->select_lex.where, - &lex->select_lex.leaf_tables, FALSE)) + if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, + &thd->lex->select_lex.top_join_list, + lex->query_tables, &lex->select_lex.where, + &lex->select_lex.leaf_tables, FALSE, + DELETE_ACL)) DBUG_RETURN(TRUE); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f57856dc4b3..26f3b6f5faa 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -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); DBUG_ENTER("mysql_prepare_insert_check_table"); - if (setup_tables(thd, &thd->lex->select_lex.context, - &thd->lex->select_lex.top_join_list, - table_list, where, &thd->lex->select_lex.leaf_tables, - select_insert)) + if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, + &thd->lex->select_lex.top_join_list, + table_list, where, + &thd->lex->select_lex.leaf_tables, + select_insert, INSERT_ACL)) DBUG_RETURN(TRUE); if (insert_into_view && !fields.elements) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 0a667c887ef..eaee5edf9f1 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -153,10 +153,11 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ha_enable_transaction(thd, FALSE); if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(TRUE); - if (setup_tables(thd, &thd->lex->select_lex.context, - &thd->lex->select_lex.top_join_list, - table_list, &unused_conds, - &thd->lex->select_lex.leaf_tables, FALSE)) + if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, + &thd->lex->select_lex.top_join_list, + table_list, &unused_conds, + &thd->lex->select_lex.leaf_tables, FALSE, + INSERT_ACL | UPDATE_ACL)) DBUG_RETURN(-1); if (!table_list->table || // do not suport join view !table_list->updatable || // and derived tables diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7d62e5bb405..37e45e999b3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4994,23 +4994,35 @@ error: 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, &all_tables->grant.privilege, 0, 0, test(all_tables->schema_table))) - return 1; + goto deny; /* Show only 1 table for check_grant */ 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 */ TABLE_LIST *subselects_tables; if ((subselects_tables= all_tables->next_global)) { if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0))) - return 1; + goto deny; } 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, ulong found_access=0; TABLE_LIST *org_tables= tables; 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 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, */ 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 && (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL))) { if (!no_errors) 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); return TRUE; } @@ -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 */ 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) || my_tz_check_n_skip_implicit_tables(&tables, thd->lex->time_zone_tables_used)) continue; - if ((thd->security_ctx->master_access & want_access) == + thd->security_ctx= sctx; + if ((sctx->master_access & want_access) == (want_access & ~EXTRA_ACL) && thd->db) tables->grant.privilege= want_access; @@ -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, 0, no_errors, test(tables->schema_table))) - return TRUE; // Access denied + goto deny; // Access denied found_access=tables->grant.privilege; found=1; } } else if (check_access(thd,want_access,tables->db,&tables->grant.privilege, 0, no_errors, test(tables->schema_table))) - return TRUE; + goto deny; } + thd->security_ctx= backup_ctx; if (grant_option) return check_grant(thd,want_access & ~EXTRA_ACL,org_tables, test(want_access & EXTRA_ACL), UINT_MAX, no_errors); return FALSE; +deny: + thd->security_ctx= backup_ctx; + return TRUE; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e5cf69f399b..505beedac3e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -337,9 +337,10 @@ JOIN::prepare(Item ***rref_pointer_array, /* Check that all tables, fields, conds and order are ok */ if ((!(select_options & OPTION_SETUP_TABLES_DONE) && - setup_tables(thd, &select_lex->context, join_list, - tables_list, &conds, &select_lex->leaf_tables, - FALSE)) || + setup_tables_and_check_access(thd, &select_lex->context, join_list, + tables_list, &conds, + &select_lex->leaf_tables, FALSE, + SELECT_ACL)) || setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || select_lex->setup_ref_array(thd, og_num) || setup_fields(thd, (*rref_pointer_array), fields_list, 1, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index dfe23c9a503..b4ae779f9e2 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -613,9 +613,11 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, tables.alias= table_list->alias; thd->lex->allow_sum_func= 0; - if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, - table_list, conds, &select_lex->leaf_tables, - FALSE) || + if (setup_tables_and_check_access(thd, &select_lex->context, + &select_lex->top_join_list, + table_list, conds, + &select_lex->leaf_tables, + FALSE, UPDATE_ACL) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) || select_lex->setup_ref_array(thd, order_num) || setup_order(thd, select_lex->ref_pointer_array, @@ -706,10 +708,11 @@ reopen_tables: call in setup_tables()). */ - if (setup_tables(thd, &lex->select_lex.context, - &lex->select_lex.top_join_list, - table_list, &lex->select_lex.where, - &lex->select_lex.leaf_tables, FALSE)) + if (setup_tables_and_check_access(thd, &lex->select_lex.context, + &lex->select_lex.top_join_list, + table_list, &lex->select_lex.where, + &lex->select_lex.leaf_tables, FALSE, + UPDATE_ACL)) DBUG_RETURN(TRUE); if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0)) diff --git a/sql/table.cc b/sql/table.cc index 4390c67c77d..cfdb9bd93aa 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2068,7 +2068,8 @@ void st_table_list::hide_view_error(THD *thd) if (thd->net.last_errno == ER_BAD_FIELD_ERROR || thd->net.last_errno == ER_SP_DOES_NOT_EXIST || 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(); thd->clear_error(); |