Bug#27145 EXTRA_ACL troubles

The flag EXTRA_ACL is used in conjugation with our access checks, yet it is
not clear what impact this flag has.
This is a code clean up which replaces use of EXTRA_ACL with an explicit
function parameter.
The patch also fixes privilege checks for:
- SHOW CREATE TABLE: The new privilege requirement is any privilege on
  the table-level.
- CHECKSUM TABLE: Requires SELECT on the table level.
- SHOW CREATE VIEW: Requires SHOW_VIEW and SELECT on the table level
  (just as the manual claims)
- SHOW INDEX: Requires any privilege on any column combination.
This commit is contained in:
Kristofer Pettersson 2009-10-19 14:58:13 +02:00
parent 4863e5ceb8
commit b5559f5305
23 changed files with 751 additions and 235 deletions

View file

@ -914,13 +914,13 @@ SHOW CREATE VIEW mysqltest2.v_ny;
View Create View character_set_client collation_connection
v_ny CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v_ny` AS select `mysqltest2`.`t_nn`.`c1` AS `c1` from `mysqltest2`.`t_nn` latin1 latin1_swedish_ci
SHOW CREATE TABLE mysqltest3.t_nn;
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't_nn'
ERROR 42000: SHOW command denied to user 'mysqltest_1'@'localhost' for table 't_nn'
SHOW CREATE VIEW mysqltest3.t_nn;
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't_nn'
SHOW CREATE VIEW mysqltest3.v_nn;
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v_nn'
SHOW CREATE TABLE mysqltest3.v_nn;
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v_nn'
ERROR 42000: SHOW command denied to user 'mysqltest_1'@'localhost' for table 'v_nn'
SHOW CREATE TABLE mysqltest2.t_nn;
Table Create Table
t_nn CREATE TABLE `t_nn` (

View file

@ -391,7 +391,7 @@ grant all on mysqltest_1.* to mysqltest_u1@localhost;
use mysqltest_2;
create table t1 (i int);
show create table mysqltest_2.t1;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
ERROR 42000: SHOW command denied to user 'mysqltest_u1'@'localhost' for table 't1'
create table t1 like mysqltest_2.t1;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
grant select on mysqltest_2.t1 to mysqltest_u1@localhost;

123
mysql-test/r/grant4.result Normal file
View file

@ -0,0 +1,123 @@
drop database if exists mysqltest_db1;
create database mysqltest_db1;
use mysqltest_db1;
create table t_column_priv_only (a int, b int);
create table t_select_priv like t_column_priv_only;
create table t_no_priv like t_column_priv_only;
grant all privileges on test.* to mysqltest_u1@localhost;
grant insert (a) on mysqltest_db1.t_column_priv_only to mysqltest_u1@localhost;
grant select on mysqltest_db1.t_select_priv to mysqltest_u1@localhost;
** Connect as restricted user mysqltest_u1.
** Test column level privileges only. No SELECT privileges on the table.
** INSERT INTO ... VALUES ...
** Attempting to insert values to a table with only column privileges
** should work.
insert into mysqltest_db1.t_column_priv_only (a) VALUES (1);
** SHOW COLUMNS
** Should succeed because we have privileges (any) on at least one of the columns.
select column_name as 'Field',column_type as 'Type',is_nullable as 'Null',column_key as 'Key',column_default as 'Default',extra as 'Extra' from information_schema.columns where table_schema='mysqltest_db1' and table_name='t_column_priv_only';
Field Type Null Key Default Extra
a int(11) YES NULL
show columns from mysqltest_db1.t_column_priv_only;
Field Type Null Key Default Extra
a int(11) YES NULL
** SHOW COLUMNS
** Should fail because there are no privileges on any column combination.
show columns from mysqltest_db1.t_no_priv;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't_no_priv'
** However, select from I_S.COLUMNS will succeed but not show anything:
select column_name as 'Field',column_type as 'Type',is_nullable as 'Null',column_key as 'Key',column_default as 'Default',extra as 'Extra' from information_schema.columns where table_schema='mysqltest_db1' and table_name='t_no_priv';
Field Type Null Key Default Extra
** CREATE TABLE ... LIKE ... require SELECT privleges and will fail.
create table test.t_no_priv like mysqltest_db1.column_priv_only;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 'column_priv_only'
** Just to be sure... SELECT also fails.
select * from mysqltest_db1.t_column_priv_only;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't_column_priv_only'
** SHOW CREATE TABLE ... require any privileges on all columns (the entire table).
** First we try and fail on a table with only one column privilege.
show create table mysqltest_db1.t_column_priv_only;
ERROR 42000: SHOW command denied to user 'mysqltest_u1'@'localhost' for table 't_column_priv_only'
** Now we do the same on a table with SELECT privileges.
** SHOW COLUMNS
** Success because we got some privileges on the table (SELECT_ACL)
show columns from mysqltest_db1.t_select_priv;
Field Type Null Key Default Extra
a int(11) YES NULL
b int(11) YES NULL
** CREATE TABLE ... LIKE ... require SELECT privleges and will SUCCEED.
drop table if exists test.t_duplicated;
create table test.t_duplicated like mysqltest_db1.t_select_priv;
drop table test.t_duplicated;
** SHOW CREATE TABLE will succeed because we have a privilege on all columns in the table (table-level privilege).
show create table mysqltest_db1.t_select_priv;
Table Create Table
t_select_priv CREATE TABLE `t_select_priv` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
** SHOW CREATE TABLE will fail if there is no grants at all:
show create table mysqltest_db1.t_no_priv;
ERROR 42000: SHOW command denied to user 'mysqltest_u1'@'localhost' for table 't_no_priv'
use mysqltest_db1;
CREATE TABLE t5 (s1 INT);
CREATE INDEX i ON t5 (s1);
CREATE TABLE t6 (s1 INT, s2 INT);
CREATE VIEW v5 AS SELECT * FROM t5;
CREATE VIEW v6 AS SELECT * FROM t6;
CREATE VIEW v2 AS SELECT * FROM t_select_priv;
CREATE VIEW v3 AS SELECT * FROM t_select_priv;
CREATE INDEX i ON t6 (s1);
GRANT UPDATE (s2) ON t6 to mysqltest_u1@localhost;
GRANT UPDATE (s2) ON v6 to mysqltest_u1@localhost;
GRANT SHOW VIEW ON v2 to mysqltest_u1@localhost;
GRANT SHOW VIEW, SELECT ON v3 to mysqltest_u1@localhost;
use mysqltest_db1;
** Connect as restricted user mysqltest_u1.
** SELECT FROM INFORMATION_SCHEMA.STATISTICS will succeed because any privileges will do (authentication is enough).
SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name='t5';
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT
NULL mysqltest_db1 t5 1 mysqltest_db1 i 1 s1 A NULL NULL NULL YES BTREE
** SHOW INDEX FROM t5 will fail because we don't have any privileges on any column combination.
SHOW INDEX FROM t5;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't5'
** SHOW INDEX FROM t6 will succeed because there exist a privilege on a column combination on t6.
SHOW INDEX FROM t6;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t6 1 i 1 s1 A NULL NULL NULL YES BTREE
** CHECK TABLE requires any privilege on any column combination and should succeed for t6:
CHECK TABLE t6;
Table Op Msg_type Msg_text
mysqltest_db1.t6 check status OK
** With no privileges access is naturally denied:
CHECK TABLE t5;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't5'
** CHECKSUM TABLE requires SELECT privileges on the table. The following should fail:
CHECKSUM TABLE t6;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't6'
** And this should work:
CHECKSUM TABLE t_select_priv;
Table Checksum
mysqltest_db1.t_select_priv 0
SHOW CREATE VIEW v5;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 'v5'
SHOW CREATE VIEW v6;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 'v6'
SHOW CREATE VIEW v2;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 'v2'
SHOW CREATE VIEW v3;
View Create View character_set_client collation_connection
v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t_select_priv`.`a` AS `a`,`t_select_priv`.`b` AS `b` from `t_select_priv` latin1 latin1_swedish_ci
drop database mysqltest_db1;
drop user mysqltest_u1@localhost;

View file

@ -3,7 +3,7 @@ drop view if exists v1,v2;
drop function if exists f1;
drop function if exists f2;
use INFORMATION_SCHEMA;
show tables where Tables_in_information_schema not like "Innodb%";
show tables where Tables_in_information_schema NOT LIKE 'Innodb%';
Tables_in_information_schema
CHARACTER_SETS
COLLATIONS
@ -119,12 +119,12 @@ create table t1 (f1 char(4));
create view v1 as select f1 from t1;
grant insert on v1 to testdb_2@localhost;
create view v5 as select f1 from t1;
grant show view on v5 to testdb_2@localhost;
grant select, show view on v5 to testdb_2@localhost;
create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1;
ERROR 42000: Access denied; you need the SUPER privilege for this operation
use testdb_1;
create view v6 as select f1 from t1;
grant show view on v6 to testdb_2@localhost;
grant select, show view on v6 to testdb_2@localhost;
create table t2 (f1 char(4));
create definer=`no_such_user`@`no_such_host` view v7 as select * from t2;
Warnings:
@ -152,11 +152,13 @@ create view v2 as select f1 from testdb_1.v1;
create view v4 as select f1,f2 from testdb_1.v3;
show fields from testdb_1.v5;
Field Type Null Key Default Extra
f1 char(4) YES NULL
show create view testdb_1.v5;
View Create View character_set_client collation_connection
v5 CREATE ALGORITHM=UNDEFINED DEFINER=`testdb_1`@`localhost` SQL SECURITY DEFINER VIEW `testdb_1`.`v5` AS select `testdb_1`.`t1`.`f1` AS `f1` from `testdb_1`.`t1` latin1 latin1_swedish_ci
show fields from testdb_1.v6;
Field Type Null Key Default Extra
f1 char(4) YES NULL
show create view testdb_1.v6;
View Create View character_set_client collation_connection
v6 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `testdb_1`.`v6` AS select `testdb_1`.`t1`.`f1` AS `f1` from `testdb_1`.`t1` latin1 latin1_swedish_ci
@ -171,9 +173,9 @@ v7 CREATE ALGORITHM=UNDEFINED DEFINER=`no_such_user`@`no_such_host` SQL SECURITY
Warnings:
Warning 1356 View 'testdb_1.v7' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
revoke insert(f1) on v3 from testdb_2@localhost;
revoke show view on v5 from testdb_2@localhost;
revoke select,show view on v5 from testdb_2@localhost;
use testdb_1;
revoke show view on v6 from testdb_2@localhost;
revoke select,show view on v6 from testdb_2@localhost;
show fields from testdb_1.v5;
ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v5'
show create view testdb_1.v5;
@ -202,7 +204,7 @@ show create view v2;
View Create View character_set_client collation_connection
v2 CREATE ALGORITHM=UNDEFINED DEFINER=`testdb_2`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `v1`.`f1` AS `f1` from `testdb_1`.`v1` latin1 latin1_swedish_ci
show create view testdb_1.v1;
ERROR 42000: SHOW VIEW command denied to user 'testdb_2'@'localhost' for table 'v1'
ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v1'
select table_name from information_schema.columns a
where a.table_name = 'v2';
table_name

Binary file not shown.

View file

@ -799,12 +799,12 @@ CREATE USER u29908_1@localhost;
CREATE DEFINER = u29908_1@localhost VIEW v1 AS SELECT f1 FROM t1;
CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS
SELECT f1 FROM t1;
GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost;
GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost;
GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost;
CREATE USER u29908_2@localhost;
GRANT DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
GRANT SELECT, DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost;
ALTER VIEW v1 AS SELECT f2 FROM t1;
ERROR 42000: Access denied; you need the SUPER privilege for this operation

146
mysql-test/t/grant4.test Normal file
View file

@ -0,0 +1,146 @@
--source include/not_embedded.inc
# Setup database, tables and user accounts
--disable_warnings
drop database if exists mysqltest_db1;
--enable_warnings
create database mysqltest_db1;
use mysqltest_db1;
create table t_column_priv_only (a int, b int);
create table t_select_priv like t_column_priv_only;
create table t_no_priv like t_column_priv_only;
grant all privileges on test.* to mysqltest_u1@localhost;
grant insert (a) on mysqltest_db1.t_column_priv_only to mysqltest_u1@localhost;
grant select on mysqltest_db1.t_select_priv to mysqltest_u1@localhost;
--echo ** Connect as restricted user mysqltest_u1.
--echo
connect (con1,localhost,mysqltest_u1,,);
connection con1;
########################################################################
--echo ** Test column level privileges only. No SELECT privileges on the table.
--echo ** INSERT INTO ... VALUES ...
--echo ** Attempting to insert values to a table with only column privileges
--echo ** should work.
insert into mysqltest_db1.t_column_priv_only (a) VALUES (1);
--echo
#########################################################################
--echo ** SHOW COLUMNS
--echo ** Should succeed because we have privileges (any) on at least one of the columns.
select column_name as 'Field',column_type as 'Type',is_nullable as 'Null',column_key as 'Key',column_default as 'Default',extra as 'Extra' from information_schema.columns where table_schema='mysqltest_db1' and table_name='t_column_priv_only';
show columns from mysqltest_db1.t_column_priv_only;
#########################################################################
--echo ** SHOW COLUMNS
--echo ** Should fail because there are no privileges on any column combination.
--error 1142
show columns from mysqltest_db1.t_no_priv;
--echo ** However, select from I_S.COLUMNS will succeed but not show anything:
select column_name as 'Field',column_type as 'Type',is_nullable as 'Null',column_key as 'Key',column_default as 'Default',extra as 'Extra' from information_schema.columns where table_schema='mysqltest_db1' and table_name='t_no_priv';
--echo
#########################################################################
--echo ** CREATE TABLE ... LIKE ... require SELECT privleges and will fail.
--error 1142
create table test.t_no_priv like mysqltest_db1.column_priv_only;
--echo
#########################################################################
--echo ** Just to be sure... SELECT also fails.
--error 1142
select * from mysqltest_db1.t_column_priv_only;
--echo
#########################################################################
--echo ** SHOW CREATE TABLE ... require any privileges on all columns (the entire table).
--echo ** First we try and fail on a table with only one column privilege.
--error 1142
show create table mysqltest_db1.t_column_priv_only;
--echo
#########################################################################
--echo ** Now we do the same on a table with SELECT privileges.
--echo
#########################################################################
--echo ** SHOW COLUMNS
--echo ** Success because we got some privileges on the table (SELECT_ACL)
show columns from mysqltest_db1.t_select_priv;
--echo
#########################################################################
--echo ** CREATE TABLE ... LIKE ... require SELECT privleges and will SUCCEED.
--disable_warnings
drop table if exists test.t_duplicated;
--enable_warnings
create table test.t_duplicated like mysqltest_db1.t_select_priv;
drop table test.t_duplicated;
--echo
#########################################################################
--echo ** SHOW CREATE TABLE will succeed because we have a privilege on all columns in the table (table-level privilege).
show create table mysqltest_db1.t_select_priv;
--echo
#########################################################################
--echo ** SHOW CREATE TABLE will fail if there is no grants at all:
--error 1142
show create table mysqltest_db1.t_no_priv;
--echo
connection default;
#
# SHOW INDEX
#
use mysqltest_db1;
CREATE TABLE t5 (s1 INT);
CREATE INDEX i ON t5 (s1);
CREATE TABLE t6 (s1 INT, s2 INT);
CREATE VIEW v5 AS SELECT * FROM t5;
CREATE VIEW v6 AS SELECT * FROM t6;
CREATE VIEW v2 AS SELECT * FROM t_select_priv;
CREATE VIEW v3 AS SELECT * FROM t_select_priv;
CREATE INDEX i ON t6 (s1);
GRANT UPDATE (s2) ON t6 to mysqltest_u1@localhost;
GRANT UPDATE (s2) ON v6 to mysqltest_u1@localhost;
GRANT SHOW VIEW ON v2 to mysqltest_u1@localhost;
GRANT SHOW VIEW, SELECT ON v3 to mysqltest_u1@localhost;
connection con1;
use mysqltest_db1;
--echo ** Connect as restricted user mysqltest_u1.
--echo ** SELECT FROM INFORMATION_SCHEMA.STATISTICS will succeed because any privileges will do (authentication is enough).
#
# this result is wrong. reported as bug#34104
#
SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name='t5';
#
# Bug27145 EXTRA_ACL trouble
#
--echo ** SHOW INDEX FROM t5 will fail because we don't have any privileges on any column combination.
--error 1142
SHOW INDEX FROM t5;
--echo ** SHOW INDEX FROM t6 will succeed because there exist a privilege on a column combination on t6.
SHOW INDEX FROM t6;
# CHECK TABLE
--echo ** CHECK TABLE requires any privilege on any column combination and should succeed for t6:
CHECK TABLE t6;
--echo ** With no privileges access is naturally denied:
--error 1142
CHECK TABLE t5;
# CHECKSUM
--echo ** CHECKSUM TABLE requires SELECT privileges on the table. The following should fail:
--error 1142
CHECKSUM TABLE t6;
--echo ** And this should work:
CHECKSUM TABLE t_select_priv;
# SHOW CREATE VIEW
--error 1142
SHOW CREATE VIEW v5;
--error 1142
SHOW CREATE VIEW v6;
--error 1142
SHOW CREATE VIEW v2;
SHOW CREATE VIEW v3;
connection default;
disconnect con1;
drop database mysqltest_db1;
drop user mysqltest_u1@localhost;

View file

@ -1,5 +1,5 @@
# this test mostly test privilege control (what doesn't work
# in the embedded server by default). So disabled in embedded-server mode
# in the embedded server by default). So skip the test in embedded-server mode.
-- source include/not_embedded.inc
-- source include/testdb_only.inc
@ -13,7 +13,7 @@ drop function if exists f2;
use INFORMATION_SCHEMA;
--replace_result Tables_in_INFORMATION_SCHEMA Tables_in_information_schema
show tables where Tables_in_information_schema not like "Innodb%";
show tables where Tables_in_INFORMATION_SCHEMA NOT LIKE 'Innodb%';
--replace_result 'Tables_in_INFORMATION_SCHEMA (T%)' 'Tables_in_information_schema (T%)'
show tables from INFORMATION_SCHEMA like 'T%';
create database `inf%`;
@ -123,7 +123,7 @@ create view v1 as select f1 from t1;
grant insert on v1 to testdb_2@localhost;
create view v5 as select f1 from t1;
grant show view on v5 to testdb_2@localhost;
grant select, show view on v5 to testdb_2@localhost;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1;
@ -131,7 +131,7 @@ create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1;
connection default;
use testdb_1;
create view v6 as select f1 from t1;
grant show view on v6 to testdb_2@localhost;
grant select, show view on v6 to testdb_2@localhost;
create table t2 (f1 char(4));
create definer=`no_such_user`@`no_such_host` view v7 as select * from t2;
@ -163,10 +163,10 @@ show fields from testdb_1.v7;
show create view testdb_1.v7;
revoke insert(f1) on v3 from testdb_2@localhost;
revoke show view on v5 from testdb_2@localhost;
revoke select,show view on v5 from testdb_2@localhost;
connection default;
use testdb_1;
revoke show view on v6 from testdb_2@localhost;
revoke select,show view on v6 from testdb_2@localhost;
connection testdb_2;
--error ER_TABLEACCESS_DENIED_ERROR

View file

@ -109,7 +109,7 @@ create user user_1@localhost;
grant all on mysqltest.* to user_1@localhost;
connect (con28181_1,localhost,user_1,,mysqltest);
--error ER_DBACCESS_DENIED_ERROR
--error ER_ACCESS_DENIED_ERROR
eval select schema_name
into outfile "../../tmp/outfile-test.4"
fields terminated by ',' optionally enclosed by '"'

View file

@ -1072,12 +1072,12 @@ CREATE USER u29908_1@localhost;
CREATE DEFINER = u29908_1@localhost VIEW v1 AS SELECT f1 FROM t1;
CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS
SELECT f1 FROM t1;
GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost;
GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost;
GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost;
CREATE USER u29908_2@localhost;
GRANT DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
GRANT SELECT, DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost;
connect (u2,localhost,u29908_2,,mysqltest_29908);

View file

@ -1120,9 +1120,11 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv,
bool no_grant, bool no_errors, bool schema_db);
bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
uint number, bool no_errors);
bool no_grant, bool no_errors, bool schema_db);
bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
bool any_combination_of_privileges_will_do,
uint number,
bool no_errors);
#else
inline bool check_access(THD *thd, ulong access, const char *db,
ulong *save_priv, bool no_grant, bool no_errors,
@ -1132,8 +1134,10 @@ inline bool check_access(THD *thd, ulong access, const char *db,
*save_priv= GLOBAL_ACLS;
return false;
}
inline bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
uint number, bool no_errors)
inline bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
bool no_errors,
bool any_combination_of_privileges_will_do,
uint number)
{ return false; }
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/

View file

@ -2362,7 +2362,8 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access)
bzero((char*) &tables,sizeof(tables));
tables.db= (char*) "mysql";
tables.table_name= tables.alias= (char*) "proc";
*full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1, TRUE) ||
*full_access= (!check_table_access(thd, SELECT_ACL, &tables, FALSE,
1, TRUE) ||
(!strcmp(sp->m_definer_user.str,
thd->security_ctx->priv_user) &&
!strcmp(sp->m_definer_host.str,
@ -2808,7 +2809,7 @@ int sp_instr::exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables)
Check whenever we have access to tables for this statement
and open and lock them before executing instructions core function.
*/
if (check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE)
if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE)
|| open_and_lock_tables(thd, tables))
result= -1;
else

View file

@ -1879,7 +1879,7 @@ static bool test_if_create_new_users(THD *thd)
sctx->priv_user, tl.db, 0);
if (!(db_access & INSERT_ACL))
{
if (check_grant(thd, INSERT_ACL, &tl, 0, UINT_MAX, 1))
if (check_grant(thd, INSERT_ACL, &tl, FALSE, UINT_MAX, TRUE))
create_new_users=0;
}
}
@ -3835,40 +3835,52 @@ end:
DBUG_RETURN(return_val);
}
/****************************************************************************
Check table level grants
SYNOPSIS
bool check_grant()
thd Thread handler
want_access Bits of privileges user needs to have
tables List of tables to check. The user should have 'want_access'
to all tables in list.
show_table <> 0 if we are in show table. In this case it's enough to have
any privilege for the table
number Check at most this number of tables.
no_errors If 0 then we write an error. The error is sent directly to
the client
/**
@brief Check table level grants
RETURN
0 ok
1 Error: User did not have the requested privileges
@param thd Thread handler
@param want_access Bits of privileges user needs to have.
@param tables List of tables to check. The user should have
'want_access' to all tables in list.
@param any_combination_will_do TRUE if it's enough to have any privilege for
any combination of the table columns.
@param number Check at most this number of tables.
@param no_errors TRUE if no error should be sent directly to the client.
NOTE
This functions assumes that either number of tables to be inspected
If table->grant.want_privilege != 0 then the requested privileges where
in the set of COL_ACLS but access was not granted on the table level. As
a consequence an extra check of column privileges is required.
Specifically if this function returns FALSE the user has some kind of
privilege on a combination of columns in each table.
This function is usually preceeded by check_access which establish the
User-, Db- and Host access rights.
@see check_access
@see check_table_access
@note This functions assumes that either number of tables to be inspected
by it is limited explicitly (i.e. is is not UINT_MAX) or table list
used and thd->lex->query_tables_own_last value correspond to each
other (the latter should be either 0 or point to next_global member
of one of elements of this table list).
****************************************************************************/
@return Access status
@retval FALSE Access granted; But column privileges might need to be
checked.
@retval TRUE The user did not have the requested privileges on any of the
tables.
*/
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_table, uint number, bool no_errors)
bool any_combination_will_do, uint number, bool no_errors)
{
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);
@ -3886,7 +3898,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
i < number && table != first_not_own_table;
table= table->next_global, i++)
{
/* Remove SHOW_VIEW_ACL, because it will be checked during making view */
/*
Save a copy of the privileges without the SHOW_VIEW_ACL attribute.
It will be checked during making view.
*/
table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
}
@ -3899,7 +3914,6 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
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
@ -3929,8 +3943,13 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
want_access &= ~table->grant.privilege;
goto err; // No grants
}
if (show_table)
continue; // We have some priv on this
/*
For SHOW COLUMNS, SHOW INDEX it is enough to have some
privileges on any column combination on the table.
*/
if (any_combination_will_do)
continue;
table->grant.grant_table=grant_table; // Remember for column test
table->grant.version=grant_version;
@ -3948,7 +3967,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
}
}
rw_unlock(&LOCK_grant);
DBUG_RETURN(0);
DBUG_RETURN(FALSE);
err:
rw_unlock(&LOCK_grant);
@ -3962,7 +3981,97 @@ err:
sctx->host_or_ip,
table ? table->get_table_name() : "unknown");
}
DBUG_RETURN(1);
DBUG_RETURN(TRUE);
}
/**
Check if all tables in the table list has any of the requested table level
privileges matching the current user.
@param thd A pointer to the thread context.
@param required_access Set of privileges to compare against.
@param tables[in,out] A list of tables to be checked.
@note If the table grant hash contains any grant table, this table will be
attached to the corresponding TABLE_LIST object in 'tables'.
@return
@retval TRUE There is a privilege on the table level granted to the
current user.
@retval FALSE There are no privileges on the table level granted to the
current user.
*/
bool has_any_table_level_privileges(THD *thd, ulong required_access,
TABLE_LIST *tables)
{
Security_context *sctx;
GRANT_TABLE *grant_table;
TABLE_LIST *table;
/* For each table in tables */
for (table= tables; table; table= table->next_global)
{
/*
If this table is a VIEW, then it will supply its own security context.
This is because VIEWs can have a DEFINER or an INVOKER security role.
*/
sctx= table->security_ctx ? table->security_ctx : thd->security_ctx;
/*
Get privileges from table_priv and column_priv tables by searching
the cache.
*/
rw_rdlock(&LOCK_grant);
grant_table= table_hash_search(sctx->host, sctx->ip,
table->db, sctx->priv_user,
table->table_name,0);
rw_unlock(&LOCK_grant);
/* Stop if there are no grants for the current user */
if (!grant_table)
return FALSE;
/*
Save a pointer to the found grant_table in the table object.
This pointer can later be used to verify other access requirements
without having to look up the grant table in the hash.
*/
table->grant.grant_table= grant_table;
table->grant.version= grant_version;
table->grant.privilege|= grant_table->privs;
/*
Save all privileges which might be subject to column privileges
but not which aren't yet granted by table level ACLs.
This is can later be used for column privilege checks.
*/
table->grant.want_privilege= ((required_access & COL_ACLS)
& ~table->grant.privilege);
/*
If the requested privileges share any intersection with the current
table privileges we have found at least one common privilege on the
table level.
*/
if (grant_table->privs & required_access)
continue; /* Check next table */
/*
There are no table level privileges which satisfies any of the
requested privileges. There might still be column privileges which
does though.
*/
return FALSE;
}
/*
All tables in TABLE_LIST satisfy the requirement of having any
privilege on the table level.
*/
return TRUE;
}

View file

@ -51,7 +51,6 @@
4. acl_init() or whatever - to define behaviour for old privilege tables
5. sql_yacc.yy - for GRANT/REVOKE to work
*/
#define EXTRA_ACL (1L << 29)
#define NO_ACCESS (1L << 30)
#define DB_ACLS \
(UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
@ -238,7 +237,7 @@ my_bool grant_init();
void grant_free(void);
my_bool grant_reload(THD *thd);
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_command, uint number, bool dont_print_error);
bool any_combination_will_do, uint number, bool no_errors);
bool check_grant_column (THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name,
const char *name, uint length, Security_context *sctx);
@ -269,6 +268,9 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
bool check_routine_level_acl(THD *thd, const char *db, const char *name,
bool is_proc);
bool is_acl_user(const char *host, const char *user);
bool has_any_table_level_privileges(THD *thd, ulong required_access,
TABLE_LIST *tables);
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define check_grant(A,B,C,D,E,F) 0
#define check_grant_db(A,B) 0

View file

@ -731,7 +731,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild)
table_list.table_name= share->table_name.str;
table_list.grant.privilege=0;
if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list, 1, TRUE))
if (check_table_access(thd,SELECT_ACL,&table_list, TRUE, 1, TRUE))
continue;
/* need to check if we haven't already listed it */
for (table= open_list ; table ; table=table->next)

View file

@ -1545,7 +1545,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
table_list.db = table->db();
table_list.alias= table_list.table_name= table->table();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_table_access(thd,SELECT_ACL,&table_list, 1, TRUE))
if (check_table_access(thd,SELECT_ACL,&table_list, FALSE, 1,TRUE))
{
DBUG_PRINT("qcache",
("probably no SELECT access to %s.%s => return to normal processing",

View file

@ -45,7 +45,6 @@
"FUNCTION" : "PROCEDURE")
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
static bool check_show_create_table_access(THD *thd, TABLE_LIST *table);
const char *any_db="*any*"; // Special symbol for check_access
@ -589,7 +588,7 @@ static bool check_merge_table_access(THD *thd, char *db,
tlist->db= db; /* purecov: inspected */
}
error= check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
table_list, UINT_MAX, FALSE);
table_list, FALSE, UINT_MAX, FALSE);
}
return error;
}
@ -1334,7 +1333,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
0, 0, test(table_list.schema_table)))
break;
if (check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0))
if (check_grant(thd, SELECT_ACL, &table_list, TRUE, UINT_MAX, FALSE))
break;
/* init structures for VIEW processing */
table_list.select_lex= &(thd->lex->select_lex);
@ -2193,14 +2192,16 @@ mysql_execute_command(THD *thd)
#endif
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
if (!(res= check_table_access(thd, SELECT_ACL, all_tables, FALSE,
UINT_MAX, FALSE)))
res= execute_sqlcom_select(thd, all_tables);
break;
case SQLCOM_SHOW_STATUS:
{
system_status_var old_status_var= thd->status_var;
thd->initial_status_var= &old_status_var;
if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
if (!(res= check_table_access(thd, SELECT_ACL, all_tables, FALSE,
UINT_MAX, FALSE)))
res= execute_sqlcom_select(thd, all_tables);
/* Don't log SHOW STATUS commands to slow query log */
thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
@ -2230,18 +2231,22 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_STORAGE_ENGINES:
case SQLCOM_SHOW_PROFILE:
case SQLCOM_SELECT:
{
thd->status_var.last_query_cost= 0.0;
/*
lex->exchange != NULL implies SELECT .. INTO OUTFILE and this
requires FILE_ACL access.
*/
ulong privileges_requested= lex->exchange ? SELECT_ACL | FILE_ACL :
SELECT_ACL;
if (all_tables)
{
res= check_table_access(thd,
lex->exchange ? SELECT_ACL | FILE_ACL :
SELECT_ACL,
all_tables, UINT_MAX, FALSE);
}
privileges_requested,
all_tables, FALSE, UINT_MAX, FALSE);
else
res= check_access(thd,
lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
any_db, 0, 0, 0, 0);
res= check_access(thd, privileges_requested, any_db, 0, 0, 0, UINT_MAX);
if (res)
break;
@ -2252,7 +2257,8 @@ mysql_execute_command(THD *thd)
res= execute_sqlcom_select(thd, all_tables);
break;
case SQLCOM_PREPARE:
}
case SQLCOM_PREPARE:
{
mysql_sql_stmt_prepare(thd);
break;
@ -2268,8 +2274,8 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_DO:
if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
open_and_lock_tables(thd, all_tables))
if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
|| open_and_lock_tables(thd, all_tables))
goto error;
res= mysql_do(thd, *lex->insert_list);
@ -2378,8 +2384,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_BACKUP_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
check_global_access(thd, FILE_ACL))
if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
|| check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_backup_table(thd, first_table);
@ -2390,8 +2396,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_RESTORE_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, INSERT_ACL, all_tables, UINT_MAX, FALSE) ||
check_global_access(thd, FILE_ACL))
if (check_table_access(thd, INSERT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
|| check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_restore_table(thd, first_table);
@ -2490,7 +2496,7 @@ mysql_execute_command(THD *thd)
test(first_table->schema_table)))
goto error; /* purecov: inspected */
/* Check that the first table has CREATE privilege */
if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0))
if (check_grant(thd, CREATE_ACL, all_tables, FALSE, 1, FALSE))
goto error;
pthread_mutex_lock(&LOCK_active_mi);
@ -2860,7 +2866,7 @@ end_with_restore_list:
(TABLE_LIST *)
create_info.merge_list.first))
goto error; /* purecov: inspected */
if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0))
if (check_grant(thd, priv_needed, all_tables, FALSE, UINT_MAX, FALSE))
goto error;
if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
{ // Rename of table
@ -2869,8 +2875,8 @@ end_with_restore_list:
tmp_table.table_name= lex->name.str;
tmp_table.db=select_lex->db;
tmp_table.grant.privilege=priv;
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
UINT_MAX, 0))
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, FALSE,
UINT_MAX, FALSE))
goto error;
}
@ -2924,10 +2930,11 @@ end_with_restore_list:
*/
old_list= table[0];
new_list= table->next_local[0];
if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, 0, 1, 0) ||
if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, FALSE, 1, FALSE) ||
(!test_all_bits(table->next_local->grant.privilege,
INSERT_ACL | CREATE_ACL) &&
check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0)))
check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, FALSE, 1,
FALSE)))
goto error;
}
@ -2958,11 +2965,54 @@ end_with_restore_list:
goto error;
#else
{
/* Ignore temporary tables if this is "SHOW CREATE VIEW" */
/*
Access check:
SHOW CREATE TABLE require any privileges on the table level (ie
effecting all columns in the table).
SHOW CREATE VIEW require the SHOW_VIEW and SELECT ACLs on the table
level.
NOTE: SHOW_VIEW ACL is checked when the view is created.
*/
if (lex->only_view)
{
if (check_table_access(thd, SELECT_ACL, first_table, FALSE, 1, FALSE))
{
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
"SHOW", thd->security_ctx->priv_user,
thd->security_ctx->host_or_ip, first_table->alias);
goto error;
}
/* Ignore temporary tables if this is "SHOW CREATE VIEW" */
first_table->skip_temporary= 1;
if (check_show_create_table_access(thd, first_table))
goto error;
}
else
{
ulong save_priv;
if (check_access(thd, SELECT_ACL, first_table->db,
&save_priv, FALSE, FALSE,
test(first_table->schema_table)))
goto error;
/*
save_priv contains any privileges actually granted by check_access.
If there are no global privileges (save_priv == 0) and no table level
privileges, access is denied.
*/
if (!save_priv &&
!has_any_table_level_privileges(thd, TABLE_ACLS,
first_table))
{
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
"SHOW", thd->security_ctx->priv_user,
thd->security_ctx->host_or_ip, first_table->alias);
goto error;
}
}
/*
Access is granted. Execute command.
*/
res= mysqld_show_create(thd, first_table);
break;
}
@ -2970,8 +3020,8 @@ end_with_restore_list:
case SQLCOM_CHECKSUM:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables,
UINT_MAX, FALSE))
if (check_table_access(thd, SELECT_ACL, all_tables,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
res = mysql_checksum_table(thd, first_table, &lex->check_opt);
break;
@ -2980,7 +3030,7 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
UINT_MAX, FALSE))
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_repair_table(thd, first_table, &lex->check_opt);
@ -2999,8 +3049,8 @@ end_with_restore_list:
case SQLCOM_CHECK:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables,
UINT_MAX, FALSE))
if (check_table_access(thd, SELECT_ACL, all_tables,
TRUE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_check_table(thd, first_table, &lex->check_opt);
@ -3012,7 +3062,7 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
UINT_MAX, FALSE))
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_analyze_table(thd, first_table, &lex->check_opt);
@ -3033,7 +3083,7 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
UINT_MAX, FALSE))
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
@ -3406,7 +3456,7 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (!lex->drop_temporary)
{
if (check_table_access(thd, DROP_ACL, all_tables, UINT_MAX, FALSE))
if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
goto error;
@ -3514,8 +3564,8 @@ end_with_restore_list:
if (lex->autocommit && end_active_trans(thd))
goto error;
if ((check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
open_and_lock_tables(thd, all_tables)))
if ((check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
|| open_and_lock_tables(thd, all_tables)))
goto error;
if (lex->one_shot_set && not_all_support_one_shot(lex_var_list))
{
@ -3569,7 +3619,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
UINT_MAX, FALSE))
FALSE, UINT_MAX, FALSE))
goto error;
if (lex->protect_against_global_read_lock &&
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
@ -3965,7 +4015,7 @@ end_with_restore_list:
else
{
if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL),
all_tables, 0, UINT_MAX, 0))
all_tables, FALSE, UINT_MAX, FALSE))
goto error;
/* Conditionally writes to binlog */
res= mysql_table_grant(thd, all_tables, lex->users_list,
@ -4074,7 +4124,7 @@ end_with_restore_list:
#endif
case SQLCOM_HA_OPEN:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE))
if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE))
goto error;
res= mysql_ha_open(thd, first_table, 0);
break;
@ -4360,7 +4410,8 @@ create_sp_error:
This will cache all SP and SF and open and lock all tables
required for execution.
*/
if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
if (check_table_access(thd, SELECT_ACL, all_tables, FALSE,
UINT_MAX, FALSE) ||
open_and_lock_tables(thd, all_tables))
goto error;
@ -4688,8 +4739,8 @@ create_sp_error:
}
case SQLCOM_DROP_VIEW:
{
if (check_table_access(thd, DROP_ACL, all_tables, UINT_MAX, FALSE) ||
end_active_trans(thd))
if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE)
|| end_active_trans(thd))
goto error;
/* Conditionally writes to binlog. */
res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
@ -5138,7 +5189,7 @@ bool check_single_table_access(THD *thd, ulong privilege,
(thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) &&
!(all_tables->view &&
all_tables->effective_algorithm == VIEW_ALGORITHM_TMPTABLE) &&
check_grant(thd, privilege, all_tables, 0, 1, no_errors))
check_grant(thd, privilege, all_tables, FALSE, 1, no_errors))
goto deny;
thd->security_ctx= backup_ctx;
@ -5183,7 +5234,8 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
subselects_tables= subselects_tables->next_global;
}
if (subselects_tables &&
(check_table_access(thd, SELECT_ACL, subselects_tables, UINT_MAX, FALSE)))
(check_table_access(thd, SELECT_ACL, subselects_tables, FALSE,
UINT_MAX, FALSE)))
return 1;
}
return 0;
@ -5191,46 +5243,54 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
/**
Get the user (global) and database privileges for all used tables.
@brief Compare requested privileges with the privileges acquired from the
User- and Db-tables.
@param thd Thread handler
@param want_access The requested access privileges.
@param db A pointer to the Db name.
@param[out] save_priv A pointer to the granted privileges will be stored.
@param dont_check_global_grants True if no global grants are checked.
@param no_error True if no errors should be sent to the client.
@param schema_db True if the db specified belongs to the meta data tables.
@param save_priv In this we store global and db level grants for the
table. Note that we don't store db level grants if the
global grants is enough to satisfy the request and the
global grants contains a SELECT grant.
'save_priv' is used to save the User-table (global) and Db-table grants for
the supplied db name. Note that we don't store db level grants if the global
grants is enough to satisfy the request AND the global grants contains a
SELECT grant.
@note
The idea of EXTRA_ACL is that one will be granted access to the table if
one has the asked privilege on any column combination of the table; For
example to be able to check a table one needs to have SELECT privilege on
any column of the table.
A meta data table (from INFORMATION_SCHEMA) can always be accessed with
a SELECT_ACL.
@retval
0 ok
@retval
1 If we can't get the privileges and we don't use table/column
grants.
@see check_grant
@return Status of denial of access by exclusive ACLs.
@retval FALSE Access can't exclusively be denied by Db- and User-table
access unless Column- and Table-grants are checked too.
@retval TRUE Access denied.
*/
bool
check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
bool dont_check_global_grants, bool no_errors, bool schema_db)
{
Security_context *sctx= thd->security_ctx;
ulong db_access;
/*
GRANT command:
In case of database level grant the database name may be a pattern,
in case of table|column level grant the database name can not be a pattern.
We use 'dont_check_global_grants' as a flag to determine
if it's database level grant command
if it's database level grant command
(see SQLCOM_GRANT case, mysql_execute_command() function) and
set db_is_pattern according to 'dont_check_global_grants' value.
*/
bool db_is_pattern= (test(want_access & GRANT_ACL) &&
dont_check_global_grants);
bool db_is_pattern= ((want_access & GRANT_ACL) && dont_check_global_grants);
ulong dummy;
DBUG_ENTER("check_access");
DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu",
db ? db : "", want_access, sctx->master_access));
if (save_priv)
*save_priv=0;
else
@ -5248,8 +5308,12 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (schema_db)
{
if ((!(sctx->master_access & FILE_ACL) && (want_access & FILE_ACL)) ||
(want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
/*
We don't allow any simple privileges but SELECT_ACL or CREATE_VIEW_ACL
on the information_schema database.
*/
want_access &= ~SELECT_ACL;
if (want_access & DB_ACLS)
{
if (!no_errors)
{
@ -5257,10 +5321,15 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->priv_host, db_name);
}
/*
Access denied;
[out] *save_privileges= 0
*/
DBUG_RETURN(TRUE);
}
else
{
/* Access granted */
*save_priv= SELECT_ACL;
DBUG_RETURN(FALSE);
}
@ -5268,20 +5337,27 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if ((sctx->master_access & want_access) == want_access)
{
/*
If we don't have a global SELECT privilege, we have to get the database
specific access rights to be able to handle queries of type
UPDATE t1 SET a=1 WHERE b > 0
*/
/* get access for current db */
db_access= sctx->db_access;
/*
1. If we don't have a global SELECT privilege, we have to get the
database specific access rights to be able to handle queries of type
UPDATE t1 SET a=1 WHERE b > 0
2. Change db access if it isn't current db which is being addressed
*/
if (!(sctx->master_access & SELECT_ACL) &&
(db && (!thd->db || db_is_pattern || strcmp(db,thd->db))))
db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
db_is_pattern);
/*
The effective privileges are the union of the global privileges
and the the intersection of db- and host-privileges.
*/
*save_priv=sctx->master_access | db_access;
DBUG_RETURN(FALSE);
}
if (((want_access & ~sctx->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
if (((want_access & ~sctx->master_access) & ~DB_ACLS) ||
(! db && dont_check_global_grants))
{ // We can never grant this
DBUG_PRINT("error",("No possible access"));
@ -5296,33 +5372,66 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
}
if (db == any_db)
DBUG_RETURN(FALSE); // Allow select on anything
{
/*
Access granted; Allow select on *any* db.
[out] *save_privileges= 0
*/
DBUG_RETURN(FALSE);
}
if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))
db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
db_is_pattern);
else
db_access= sctx->db_access;
DBUG_PRINT("info",("db_access: %lu", db_access));
/* Remove SHOW attribute and access rights we already have */
want_access &= ~(sctx->master_access | EXTRA_ACL);
DBUG_PRINT("info",("db_access: %lu want_access: %lu",
db_access, want_access));
db_access= ((*save_priv=(db_access | sctx->master_access)) & want_access);
if (db_access == want_access ||
/*
Save the union of User-table and the intersection between Db-table and
Host-table privileges.
*/
db_access= (db_access | sctx->master_access);
*save_priv= db_access;
/*
We need to investigate column- and table access if all requested privileges
belongs to the bit set of .
*/
bool need_table_or_column_check=
(want_access & (TABLE_ACLS | PROC_ACLS | db_access)) == want_access;
/*
Grant access if the requested access is in the intersection of
host- and db-privileges (as retrieved from the acl cache),
also grant access if all the requested privileges are in the union of
TABLES_ACLS and PROC_ACLS; see check_grant.
*/
if ( (db_access & want_access) == want_access ||
(!dont_check_global_grants &&
!(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS))))
DBUG_RETURN(FALSE); /* Ok */
need_table_or_column_check))
{
/*
Ok; but need to check table- and column privileges.
[out] *save_privileges is (User-priv | (Db-priv & Host-priv))
*/
DBUG_RETURN(FALSE);
}
/*
Access is denied;
[out] *save_privileges is (User-priv | (Db-priv & Host-priv))
*/
DBUG_PRINT("error",("Access denied"));
if (!no_errors)
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->priv_host,
(db ? db : (thd->db ?
thd->db :
"unknown"))); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
"unknown")));
DBUG_RETURN(TRUE);
}
@ -5368,14 +5477,20 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
DBUG_ASSERT(dst_table);
if (check_access(thd, SELECT_ACL | EXTRA_ACL,
dst_table->db,
&dst_table->grant.privilege,
FALSE, FALSE,
if (check_access(thd, SELECT_ACL, dst_table->db,
&dst_table->grant.privilege, FALSE, FALSE,
test(dst_table->schema_table)))
return FALSE;
return TRUE; /* Access denied */
return (check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE));
/*
Check_grant will grant access if there is any column privileges on
all of the tables thanks to the fourth parameter (bool show_table).
*/
if (check_grant(thd, SELECT_ACL, dst_table, TRUE, UINT_MAX, FALSE))
return TRUE; /* Access denied */
/* Access granted */
return FALSE;
}
default:
break;
@ -5385,30 +5500,46 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
}
/**
Check the privilege for all used tables.
@brief Check if the requested privileges exists in either User-, Host- or
Db-tables.
@param thd Thread context
@param want_access Privileges requested
@param tables List of tables to be compared against
@param no_errors Don't report error to the client (using my_error() call).
@param any_combination_of_privileges_will_do TRUE if any privileges on any
column combination is enough.
@param number Only the first 'number' tables in the linked list are
relevant.
@param thd Thread context
@param want_access Privileges requested
@param tables List of tables to be checked
@param number Check at most this number of tables.
@param no_errors FALSE/TRUE - report/don't report error to
the client (using my_error() call).
The suppled table list contains cached privileges. This functions calls the
help functions check_access and check_grant to verify the first three steps
in the privileges check queue:
1. Global privileges
2. OR (db privileges AND host privileges)
3. OR table privileges
4. OR column privileges (not checked by this function!)
5. OR routine privileges (not checked by this function!)
@note
Table privileges are cached in the table list for GRANT checking.
This functions assumes that table list used and
thd->lex->query_tables_own_last value correspond to each other
(the latter should be either 0 or point to next_global member
of one of elements of this table list).
@see check_access
@see check_grant
@retval FALSE OK
@retval TRUE Access denied
@note This functions assumes that table list used and
thd->lex->query_tables_own_last value correspond to each other
(the latter should be either 0 or point to next_global member
of one of elements of this table list).
@return
@retval FALSE OK
@retval TRUE Access denied; But column or routine privileges might need to
be checked also.
*/
bool
check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
uint number, bool no_errors)
check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
bool any_combination_of_privileges_will_do,
uint number, bool no_errors)
{
TABLE_LIST *org_tables= tables;
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
@ -5419,22 +5550,31 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
the given table list refers to the list for prelocking (contains tables
of other queries). For simple queries first_not_own_table is 0.
*/
for (; i < number && tables != first_not_own_table;
for (; i < number && tables != first_not_own_table && tables;
tables= tables->next_global, i++)
{
ulong want_access= requirements;
if (tables->security_ctx)
sctx= tables->security_ctx;
else
sctx= backup_ctx;
if (tables->schema_table &&
(want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
/*
Always allow SELECT on schema tables. This is done by removing the
required SELECT_ACL privilege in the want_access parameter.
Disallow any other DDL or DML operation on any schema table.
*/
if (tables->schema_table)
{
if (!no_errors)
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->priv_host,
INFORMATION_SCHEMA_NAME.str);
return TRUE;
want_access &= ~SELECT_ACL;
if (want_access & DB_ACLS)
{
if (!no_errors)
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->priv_host,
INFORMATION_SCHEMA_NAME.str);
goto deny;
}
}
/*
Register access for view underlying table.
@ -5446,33 +5586,34 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
{
if (check_show_access(thd, tables))
goto deny;
continue;
}
DBUG_PRINT("info", ("derived: %d view: %d", tables->derived != 0,
tables->view != 0));
if (tables->is_anonymous_derived_table() ||
(tables->table && (int)tables->table->s->tmp_table))
(tables->table && tables->table->s &&
(int)tables->table->s->tmp_table))
continue;
thd->security_ctx= sctx;
if ((sctx->master_access & want_access) ==
(want_access & ~EXTRA_ACL) &&
thd->db)
if ((sctx->master_access & want_access) == want_access &&
thd->db)
tables->grant.privilege= want_access;
else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
{
if (check_access(thd, want_access, tables->get_db_name(),
&tables->grant.privilege, 0, no_errors,
&tables->grant.privilege, 0, no_errors,
test(tables->schema_table)))
goto deny; // Access denied
}
else if (check_access(thd, want_access, tables->get_db_name(),
&tables->grant.privilege, 0, no_errors,
test(tables->schema_table)))
&tables->grant.privilege, 0, no_errors, 0))
goto deny;
}
thd->security_ctx= backup_ctx;
return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
test(want_access & EXTRA_ACL), number, no_errors);
return check_grant(thd,requirements,org_tables,
any_combination_of_privileges_will_do,
number, no_errors);
deny:
thd->security_ctx= backup_ctx;
return TRUE;
@ -5560,7 +5701,7 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
if (!check_access(thd, access, table->db,
&table->grant.privilege, 0, 1,
test(table->schema_table)) &&
!check_grant(thd, access, table, 0, 1, 1))
!check_grant(thd, access, table, FALSE, 1, TRUE))
DBUG_RETURN(0);
}
}
@ -7253,11 +7394,11 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
else if ((check_access(thd, UPDATE_ACL, table->db,
&table->grant.privilege, 0, 1,
test(table->schema_table)) ||
check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) &&
check_grant(thd, UPDATE_ACL, table, FALSE, 1, TRUE)) &&
(check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0,
test(table->schema_table)) ||
check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
check_grant(thd, SELECT_ACL, table, FALSE, 1, FALSE)))
DBUG_RETURN(TRUE);
table->table_in_first_from_clause= 1;
@ -7275,7 +7416,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0,
test(table->schema_table)) ||
check_grant(thd, SELECT_ACL, table, 0, 1, 0))
check_grant(thd, SELECT_ACL, table, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
}
}
@ -7315,7 +7456,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
/* sql_yacc guarantees that tables and aux_tables are not zero */
DBUG_ASSERT(aux_tables != 0);
if (check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE))
DBUG_RETURN(TRUE);
/*
@ -7324,7 +7465,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
call check_table_access() safely.
*/
thd->lex->query_tables_own_last= 0;
if (check_table_access(thd, DELETE_ACL, aux_tables, UINT_MAX, FALSE))
if (check_table_access(thd, DELETE_ACL, aux_tables, FALSE, UINT_MAX, FALSE))
{
thd->lex->query_tables_own_last= save_query_tables_own_last;
DBUG_RETURN(TRUE);
@ -7477,25 +7618,6 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables)
}
/**
@brief Check privileges for SHOW CREATE TABLE statement.
@param thd Thread context
@param table Target table
@retval TRUE Failure
@retval FALSE Success
*/
static bool check_show_create_table_access(THD *thd, TABLE_LIST *table)
{
return check_access(thd, SELECT_ACL | EXTRA_ACL, table->db,
&table->grant.privilege, 0, 0,
test(table->schema_table)) ||
check_grant(thd, SELECT_ACL, table, 2, UINT_MAX, 0);
}
/**
CREATE TABLE query pre-check.
@ -7535,7 +7657,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
lex->create_info.merge_list.first))
goto err;
if (want_priv != CREATE_TMP_ACL &&
check_grant(thd, want_priv, create_table, 0, 1, 0))
check_grant(thd, want_priv, create_table, FALSE, 1, FALSE))
goto err;
if (select_lex->item_list.elements)
@ -7563,12 +7685,13 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
}
}
#endif
if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
if (tables && check_table_access(thd, SELECT_ACL, tables, FALSE,
UINT_MAX, FALSE))
goto err;
}
else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
{
if (check_show_create_table_access(thd, tables))
if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE))
goto err;
}
error= FALSE;

View file

@ -1660,7 +1660,7 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl
bzero(&tables, sizeof(tables));
tables.db= (char *)"mysql";
tables.table_name= tables.alias= (char *)"plugin";
if (check_table_access(thd, INSERT_ACL, &tables, 1, FALSE))
if (check_table_access(thd, INSERT_ACL, &tables, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
/* need to open before acquiring LOCK_plugin or it will deadlock */

View file

@ -1336,7 +1336,7 @@ static int mysql_test_select(Prepared_statement *stmt,
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
if (tables)
{
if (check_table_access(thd, privilege, tables, UINT_MAX, FALSE))
if (check_table_access(thd, privilege, tables, FALSE, UINT_MAX, FALSE))
goto error;
}
else if (check_access(thd, privilege, any_db,0,0,0,0))
@ -1405,7 +1405,8 @@ static bool mysql_test_do_fields(Prepared_statement *stmt,
THD *thd= stmt->thd;
DBUG_ENTER("mysql_test_do_fields");
if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
if (tables && check_table_access(thd, SELECT_ACL, tables, FALSE,
UINT_MAX, FALSE))
DBUG_RETURN(TRUE);
if (open_normal_and_derived_tables(thd, tables, 0))
@ -1436,8 +1437,9 @@ static bool mysql_test_set_fields(Prepared_statement *stmt,
THD *thd= stmt->thd;
set_var_base *var;
if ((tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
|| open_normal_and_derived_tables(thd, tables, 0))
if ((tables && check_table_access(thd, SELECT_ACL, tables, FALSE,
UINT_MAX, FALSE)) ||
open_normal_and_derived_tables(thd, tables, 0))
goto error;
while ((var= it++))
@ -1472,7 +1474,8 @@ static bool mysql_test_call_fields(Prepared_statement *stmt,
THD *thd= stmt->thd;
Item *item;
if ((tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE)) ||
if ((tables && check_table_access(thd, SELECT_ACL, tables, FALSE,
UINT_MAX, FALSE)) ||
open_normal_and_derived_tables(thd, tables, 0))
goto err;

View file

@ -560,7 +560,7 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
table_list.table_name= uname;
table_list.table_name_length= file_name_len;
table_list.grant.privilege=col_access;
if (check_grant(thd, TABLE_ACLS, &table_list, 1, 1, 1))
if (check_grant(thd, TABLE_ACLS, &table_list, TRUE, 1, TRUE))
continue;
}
#endif
@ -3745,8 +3745,9 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint col_access;
check_access(thd,SELECT_ACL | EXTRA_ACL, db_name->str,
&tables->grant.privilege, 0, 0, test(tables->schema_table));
check_access(thd,SELECT_ACL, db_name->str,
&tables->grant.privilege, FALSE, FALSE,
test(tables->schema_table));
col_access= get_column_grant(thd, &tables->grant,
db_name->str, table_name->str,
field->field_name) & COL_ACLS;
@ -4174,7 +4175,8 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
proc_tables.table_name= proc_tables.alias= (char*) "proc";
proc_tables.table_name_length= 4;
proc_tables.lock_type= TL_READ;
full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1, TRUE);
full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, FALSE,
1, TRUE);
if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup)))
{
DBUG_RETURN(1);
@ -4583,7 +4585,7 @@ static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables,
Table_triggers_list *triggers= tables->table->triggers;
int event, timing;
if (check_table_access(thd, TRIGGER_ACL, tables, 1, TRUE))
if (check_table_access(thd, TRIGGER_ACL, tables, FALSE, 1, TRUE))
goto ret;
for (event= 0; event < (int)TRG_EVENT_MAX; event++)
@ -7044,7 +7046,7 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name)
if (!lst)
return TRUE;
if (check_table_access(thd, TRIGGER_ACL, lst, 1, TRUE))
if (check_table_access(thd, TRIGGER_ACL, lst, FALSE, 1, TRUE))
{
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "TRIGGER");
return TRUE;

View file

@ -422,7 +422,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
thd->lex->query_tables_own_last= 0;
err_status= check_table_access(thd, TRIGGER_ACL, tables, 1, FALSE);
err_status= check_table_access(thd, TRIGGER_ACL, tables, FALSE, 1, FALSE);
thd->lex->query_tables_own_last= save_query_tables_own_last;

View file

@ -1077,7 +1077,7 @@ reopen_tables:
if (check_access(thd, want_privilege,
tl->db, &tl->grant.privilege, 0, 0,
test(tl->schema_table)) ||
check_grant(thd, want_privilege, tl, 0, 1, 0))
check_grant(thd, want_privilege, tl, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
}
}

View file

@ -269,11 +269,11 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
*/
if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege,
0, 0, is_schema_db(view->db)) ||
check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) ||
check_grant(thd, CREATE_VIEW_ACL, view, FALSE, 1, FALSE)) ||
(mode != VIEW_CREATE_NEW &&
(check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
0, 0, is_schema_db(view->db)) ||
check_grant(thd, DROP_ACL, view, 0, 1, 0))))
check_grant(thd, DROP_ACL, view, FALSE, 1, FALSE))))
goto err;
for (sl= select_lex; sl; sl= sl->next_select())
@ -323,7 +323,7 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
{
if (check_access(thd, SELECT_ACL, tbl->db,
&tbl->grant.privilege, 0, 0, test(tbl->schema_table)) ||
check_grant(thd, SELECT_ACL, tbl, 0, 1, 0))
check_grant(thd, SELECT_ACL, tbl, FALSE, 1, FALSE))
goto err;
}
}
@ -1233,8 +1233,9 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
if (!table->prelocking_placeholder &&
(old_lex->sql_command == SQLCOM_SELECT && old_lex->describe))
{
if (check_table_access(thd, SELECT_ACL, view_tables, UINT_MAX, TRUE) &&
check_table_access(thd, SHOW_VIEW_ACL, table, UINT_MAX, TRUE))
if (check_table_access(thd, SELECT_ACL, view_tables, FALSE,
UINT_MAX, TRUE) &&
check_table_access(thd, SHOW_VIEW_ACL, table, FALSE, UINT_MAX, TRUE))
{
my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0));
goto err;
@ -1244,7 +1245,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
(old_lex->sql_command == SQLCOM_SHOW_CREATE) &&
!table->belong_to_view)
{
if (check_table_access(thd, SHOW_VIEW_ACL, table, UINT_MAX, FALSE))
if (check_table_access(thd, SHOW_VIEW_ACL, table, FALSE, UINT_MAX, FALSE))
goto err;
}