mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
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:
parent
4863e5ceb8
commit
b5559f5305
23 changed files with 751 additions and 235 deletions
|
@ -914,13 +914,13 @@ SHOW CREATE VIEW mysqltest2.v_ny;
|
||||||
View Create View character_set_client collation_connection
|
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
|
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;
|
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;
|
SHOW CREATE VIEW mysqltest3.t_nn;
|
||||||
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't_nn'
|
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't_nn'
|
||||||
SHOW CREATE VIEW mysqltest3.v_nn;
|
SHOW CREATE VIEW mysqltest3.v_nn;
|
||||||
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v_nn'
|
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v_nn'
|
||||||
SHOW CREATE TABLE mysqltest3.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;
|
SHOW CREATE TABLE mysqltest2.t_nn;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t_nn CREATE TABLE `t_nn` (
|
t_nn CREATE TABLE `t_nn` (
|
||||||
|
|
|
@ -391,7 +391,7 @@ grant all on mysqltest_1.* to mysqltest_u1@localhost;
|
||||||
use mysqltest_2;
|
use mysqltest_2;
|
||||||
create table t1 (i int);
|
create table t1 (i int);
|
||||||
show create table mysqltest_2.t1;
|
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;
|
create table t1 like mysqltest_2.t1;
|
||||||
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
|
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
|
||||||
grant select on mysqltest_2.t1 to mysqltest_u1@localhost;
|
grant select on mysqltest_2.t1 to mysqltest_u1@localhost;
|
||||||
|
|
123
mysql-test/r/grant4.result
Normal file
123
mysql-test/r/grant4.result
Normal 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;
|
|
@ -3,7 +3,7 @@ drop view if exists v1,v2;
|
||||||
drop function if exists f1;
|
drop function if exists f1;
|
||||||
drop function if exists f2;
|
drop function if exists f2;
|
||||||
use INFORMATION_SCHEMA;
|
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
|
Tables_in_information_schema
|
||||||
CHARACTER_SETS
|
CHARACTER_SETS
|
||||||
COLLATIONS
|
COLLATIONS
|
||||||
|
@ -119,12 +119,12 @@ create table t1 (f1 char(4));
|
||||||
create view v1 as select f1 from t1;
|
create view v1 as select f1 from t1;
|
||||||
grant insert on v1 to testdb_2@localhost;
|
grant insert on v1 to testdb_2@localhost;
|
||||||
create view v5 as select f1 from t1;
|
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;
|
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
|
ERROR 42000: Access denied; you need the SUPER privilege for this operation
|
||||||
use testdb_1;
|
use testdb_1;
|
||||||
create view v6 as select f1 from t1;
|
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 table t2 (f1 char(4));
|
||||||
create definer=`no_such_user`@`no_such_host` view v7 as select * from t2;
|
create definer=`no_such_user`@`no_such_host` view v7 as select * from t2;
|
||||||
Warnings:
|
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;
|
create view v4 as select f1,f2 from testdb_1.v3;
|
||||||
show fields from testdb_1.v5;
|
show fields from testdb_1.v5;
|
||||||
Field Type Null Key Default Extra
|
Field Type Null Key Default Extra
|
||||||
|
f1 char(4) YES NULL
|
||||||
show create view testdb_1.v5;
|
show create view testdb_1.v5;
|
||||||
View Create View character_set_client collation_connection
|
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
|
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;
|
show fields from testdb_1.v6;
|
||||||
Field Type Null Key Default Extra
|
Field Type Null Key Default Extra
|
||||||
|
f1 char(4) YES NULL
|
||||||
show create view testdb_1.v6;
|
show create view testdb_1.v6;
|
||||||
View Create View character_set_client collation_connection
|
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
|
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:
|
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
|
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 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;
|
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;
|
show fields from testdb_1.v5;
|
||||||
ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v5'
|
ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v5'
|
||||||
show create view testdb_1.v5;
|
show create view testdb_1.v5;
|
||||||
|
@ -202,7 +204,7 @@ show create view v2;
|
||||||
View Create View character_set_client collation_connection
|
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
|
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;
|
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
|
select table_name from information_schema.columns a
|
||||||
where a.table_name = 'v2';
|
where a.table_name = 'v2';
|
||||||
table_name
|
table_name
|
||||||
|
|
Binary file not shown.
|
@ -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 VIEW v1 AS SELECT f1 FROM t1;
|
||||||
CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS
|
CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS
|
||||||
SELECT f1 FROM t1;
|
SELECT f1 FROM t1;
|
||||||
GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
|
GRANT SELECT, 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.v2 TO u29908_1@localhost;
|
||||||
GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost;
|
GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost;
|
||||||
CREATE USER u29908_2@localhost;
|
CREATE USER u29908_2@localhost;
|
||||||
GRANT DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
|
GRANT SELECT, 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, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
|
||||||
GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost;
|
GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost;
|
||||||
ALTER VIEW v1 AS SELECT f2 FROM t1;
|
ALTER VIEW v1 AS SELECT f2 FROM t1;
|
||||||
ERROR 42000: Access denied; you need the SUPER privilege for this operation
|
ERROR 42000: Access denied; you need the SUPER privilege for this operation
|
||||||
|
|
146
mysql-test/t/grant4.test
Normal file
146
mysql-test/t/grant4.test
Normal 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;
|
|
@ -1,5 +1,5 @@
|
||||||
# this test mostly test privilege control (what doesn't work
|
# 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/not_embedded.inc
|
||||||
|
|
||||||
-- source include/testdb_only.inc
|
-- source include/testdb_only.inc
|
||||||
|
@ -13,7 +13,7 @@ drop function if exists f2;
|
||||||
|
|
||||||
use INFORMATION_SCHEMA;
|
use INFORMATION_SCHEMA;
|
||||||
--replace_result Tables_in_INFORMATION_SCHEMA Tables_in_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%)'
|
--replace_result 'Tables_in_INFORMATION_SCHEMA (T%)' 'Tables_in_information_schema (T%)'
|
||||||
show tables from INFORMATION_SCHEMA like 'T%';
|
show tables from INFORMATION_SCHEMA like 'T%';
|
||||||
create database `inf%`;
|
create database `inf%`;
|
||||||
|
@ -123,7 +123,7 @@ create view v1 as select f1 from t1;
|
||||||
grant insert on v1 to testdb_2@localhost;
|
grant insert on v1 to testdb_2@localhost;
|
||||||
|
|
||||||
create view v5 as select f1 from t1;
|
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
|
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||||
create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1;
|
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;
|
connection default;
|
||||||
use testdb_1;
|
use testdb_1;
|
||||||
create view v6 as select f1 from t1;
|
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 table t2 (f1 char(4));
|
||||||
create definer=`no_such_user`@`no_such_host` view v7 as select * from t2;
|
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;
|
show create view testdb_1.v7;
|
||||||
|
|
||||||
revoke insert(f1) on v3 from testdb_2@localhost;
|
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;
|
connection default;
|
||||||
use testdb_1;
|
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;
|
connection testdb_2;
|
||||||
|
|
||||||
--error ER_TABLEACCESS_DENIED_ERROR
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
|
|
@ -109,7 +109,7 @@ create user user_1@localhost;
|
||||||
grant all on mysqltest.* to user_1@localhost;
|
grant all on mysqltest.* to user_1@localhost;
|
||||||
connect (con28181_1,localhost,user_1,,mysqltest);
|
connect (con28181_1,localhost,user_1,,mysqltest);
|
||||||
|
|
||||||
--error ER_DBACCESS_DENIED_ERROR
|
--error ER_ACCESS_DENIED_ERROR
|
||||||
eval select schema_name
|
eval select schema_name
|
||||||
into outfile "../../tmp/outfile-test.4"
|
into outfile "../../tmp/outfile-test.4"
|
||||||
fields terminated by ',' optionally enclosed by '"'
|
fields terminated by ',' optionally enclosed by '"'
|
||||||
|
|
|
@ -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 VIEW v1 AS SELECT f1 FROM t1;
|
||||||
CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS
|
CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS
|
||||||
SELECT f1 FROM t1;
|
SELECT f1 FROM t1;
|
||||||
GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
|
GRANT SELECT, 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.v2 TO u29908_1@localhost;
|
||||||
GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost;
|
GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost;
|
||||||
CREATE USER u29908_2@localhost;
|
CREATE USER u29908_2@localhost;
|
||||||
GRANT DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
|
GRANT SELECT, 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, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
|
||||||
GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost;
|
GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost;
|
||||||
|
|
||||||
connect (u2,localhost,u29908_2,,mysqltest_29908);
|
connect (u2,localhost,u29908_2,,mysqltest_29908);
|
||||||
|
|
|
@ -1120,9 +1120,11 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
||||||
bool *write_to_binlog);
|
bool *write_to_binlog);
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv,
|
bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv,
|
||||||
bool no_grant, bool no_errors, bool schema_db);
|
bool no_grant, bool no_errors, bool schema_db);
|
||||||
bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
|
bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
|
||||||
uint number, bool no_errors);
|
bool any_combination_of_privileges_will_do,
|
||||||
|
uint number,
|
||||||
|
bool no_errors);
|
||||||
#else
|
#else
|
||||||
inline bool check_access(THD *thd, ulong access, const char *db,
|
inline bool check_access(THD *thd, ulong access, const char *db,
|
||||||
ulong *save_priv, bool no_grant, bool no_errors,
|
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;
|
*save_priv= GLOBAL_ACLS;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
|
inline bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
|
||||||
uint number, bool no_errors)
|
bool no_errors,
|
||||||
|
bool any_combination_of_privileges_will_do,
|
||||||
|
uint number)
|
||||||
{ return false; }
|
{ return false; }
|
||||||
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
|
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
|
||||||
|
|
||||||
|
|
|
@ -2362,7 +2362,8 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access)
|
||||||
bzero((char*) &tables,sizeof(tables));
|
bzero((char*) &tables,sizeof(tables));
|
||||||
tables.db= (char*) "mysql";
|
tables.db= (char*) "mysql";
|
||||||
tables.table_name= tables.alias= (char*) "proc";
|
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,
|
(!strcmp(sp->m_definer_user.str,
|
||||||
thd->security_ctx->priv_user) &&
|
thd->security_ctx->priv_user) &&
|
||||||
!strcmp(sp->m_definer_host.str,
|
!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
|
Check whenever we have access to tables for this statement
|
||||||
and open and lock them before executing instructions core function.
|
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))
|
|| open_and_lock_tables(thd, tables))
|
||||||
result= -1;
|
result= -1;
|
||||||
else
|
else
|
||||||
|
|
165
sql/sql_acl.cc
165
sql/sql_acl.cc
|
@ -1879,7 +1879,7 @@ static bool test_if_create_new_users(THD *thd)
|
||||||
sctx->priv_user, tl.db, 0);
|
sctx->priv_user, tl.db, 0);
|
||||||
if (!(db_access & INSERT_ACL))
|
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;
|
create_new_users=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3835,40 +3835,52 @@ end:
|
||||||
DBUG_RETURN(return_val);
|
DBUG_RETURN(return_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Check table level grants
|
|
||||||
|
|
||||||
SYNOPSIS
|
/**
|
||||||
bool check_grant()
|
@brief Check table level grants
|
||||||
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
|
|
||||||
|
|
||||||
RETURN
|
@param thd Thread handler
|
||||||
0 ok
|
@param want_access Bits of privileges user needs to have.
|
||||||
1 Error: User did not have the requested privileges
|
@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
|
If table->grant.want_privilege != 0 then the requested privileges where
|
||||||
This functions assumes that either number of tables to be inspected
|
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
|
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
|
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
|
other (the latter should be either 0 or point to next_global member
|
||||||
of one of elements of this table list).
|
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,
|
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();
|
TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table();
|
||||||
Security_context *sctx= thd->security_ctx;
|
Security_context *sctx= thd->security_ctx;
|
||||||
uint i;
|
uint i;
|
||||||
ulong orig_want_access= want_access;
|
|
||||||
DBUG_ENTER("check_grant");
|
DBUG_ENTER("check_grant");
|
||||||
DBUG_ASSERT(number > 0);
|
DBUG_ASSERT(number > 0);
|
||||||
|
|
||||||
|
@ -3886,7 +3898,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
||||||
i < number && table != first_not_own_table;
|
i < number && table != first_not_own_table;
|
||||||
table= table->next_global, i++)
|
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);
|
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) ?
|
sctx = test(table->security_ctx) ?
|
||||||
table->security_ctx : thd->security_ctx;
|
table->security_ctx : thd->security_ctx;
|
||||||
|
|
||||||
want_access= orig_want_access;
|
|
||||||
want_access&= ~sctx->master_access;
|
want_access&= ~sctx->master_access;
|
||||||
if (!want_access)
|
if (!want_access)
|
||||||
continue; // ok
|
continue; // ok
|
||||||
|
@ -3929,8 +3943,13 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
||||||
want_access &= ~table->grant.privilege;
|
want_access &= ~table->grant.privilege;
|
||||||
goto err; // No grants
|
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.grant_table=grant_table; // Remember for column test
|
||||||
table->grant.version=grant_version;
|
table->grant.version=grant_version;
|
||||||
|
@ -3948,7 +3967,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rw_unlock(&LOCK_grant);
|
rw_unlock(&LOCK_grant);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
rw_unlock(&LOCK_grant);
|
rw_unlock(&LOCK_grant);
|
||||||
|
@ -3962,7 +3981,97 @@ err:
|
||||||
sctx->host_or_ip,
|
sctx->host_or_ip,
|
||||||
table ? table->get_table_name() : "unknown");
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@
|
||||||
4. acl_init() or whatever - to define behaviour for old privilege tables
|
4. acl_init() or whatever - to define behaviour for old privilege tables
|
||||||
5. sql_yacc.yy - for GRANT/REVOKE to work
|
5. sql_yacc.yy - for GRANT/REVOKE to work
|
||||||
*/
|
*/
|
||||||
#define EXTRA_ACL (1L << 29)
|
|
||||||
#define NO_ACCESS (1L << 30)
|
#define NO_ACCESS (1L << 30)
|
||||||
#define DB_ACLS \
|
#define DB_ACLS \
|
||||||
(UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
|
(UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
|
||||||
|
@ -238,7 +237,7 @@ my_bool grant_init();
|
||||||
void grant_free(void);
|
void grant_free(void);
|
||||||
my_bool grant_reload(THD *thd);
|
my_bool grant_reload(THD *thd);
|
||||||
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
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,
|
bool check_grant_column (THD *thd, GRANT_INFO *grant,
|
||||||
const char *db_name, const char *table_name,
|
const char *db_name, const char *table_name,
|
||||||
const char *name, uint length, Security_context *sctx);
|
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 check_routine_level_acl(THD *thd, const char *db, const char *name,
|
||||||
bool is_proc);
|
bool is_proc);
|
||||||
bool is_acl_user(const char *host, const char *user);
|
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
|
#ifdef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
#define check_grant(A,B,C,D,E,F) 0
|
#define check_grant(A,B,C,D,E,F) 0
|
||||||
#define check_grant_db(A,B) 0
|
#define check_grant_db(A,B) 0
|
||||||
|
|
|
@ -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.table_name= share->table_name.str;
|
||||||
table_list.grant.privilege=0;
|
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;
|
continue;
|
||||||
/* need to check if we haven't already listed it */
|
/* need to check if we haven't already listed it */
|
||||||
for (table= open_list ; table ; table=table->next)
|
for (table= open_list ; table ; table=table->next)
|
||||||
|
|
|
@ -1545,7 +1545,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
||||||
table_list.db = table->db();
|
table_list.db = table->db();
|
||||||
table_list.alias= table_list.table_name= table->table();
|
table_list.alias= table_list.table_name= table->table();
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#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",
|
DBUG_PRINT("qcache",
|
||||||
("probably no SELECT access to %s.%s => return to normal processing",
|
("probably no SELECT access to %s.%s => return to normal processing",
|
||||||
|
|
427
sql/sql_parse.cc
427
sql/sql_parse.cc
|
@ -45,7 +45,6 @@
|
||||||
"FUNCTION" : "PROCEDURE")
|
"FUNCTION" : "PROCEDURE")
|
||||||
|
|
||||||
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
|
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
|
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 */
|
tlist->db= db; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
error= check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
|
error= check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
|
||||||
table_list, UINT_MAX, FALSE);
|
table_list, FALSE, UINT_MAX, FALSE);
|
||||||
}
|
}
|
||||||
return error;
|
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,
|
if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
|
||||||
0, 0, test(table_list.schema_table)))
|
0, 0, test(table_list.schema_table)))
|
||||||
break;
|
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;
|
break;
|
||||||
/* init structures for VIEW processing */
|
/* init structures for VIEW processing */
|
||||||
table_list.select_lex= &(thd->lex->select_lex);
|
table_list.select_lex= &(thd->lex->select_lex);
|
||||||
|
@ -2193,14 +2192,16 @@ mysql_execute_command(THD *thd)
|
||||||
#endif
|
#endif
|
||||||
case SQLCOM_SHOW_STATUS_PROC:
|
case SQLCOM_SHOW_STATUS_PROC:
|
||||||
case SQLCOM_SHOW_STATUS_FUNC:
|
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);
|
res= execute_sqlcom_select(thd, all_tables);
|
||||||
break;
|
break;
|
||||||
case SQLCOM_SHOW_STATUS:
|
case SQLCOM_SHOW_STATUS:
|
||||||
{
|
{
|
||||||
system_status_var old_status_var= thd->status_var;
|
system_status_var old_status_var= thd->status_var;
|
||||||
thd->initial_status_var= &old_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);
|
res= execute_sqlcom_select(thd, all_tables);
|
||||||
/* Don't log SHOW STATUS commands to slow query log */
|
/* Don't log SHOW STATUS commands to slow query log */
|
||||||
thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
|
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_STORAGE_ENGINES:
|
||||||
case SQLCOM_SHOW_PROFILE:
|
case SQLCOM_SHOW_PROFILE:
|
||||||
case SQLCOM_SELECT:
|
case SQLCOM_SELECT:
|
||||||
|
{
|
||||||
thd->status_var.last_query_cost= 0.0;
|
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)
|
if (all_tables)
|
||||||
{
|
|
||||||
res= check_table_access(thd,
|
res= check_table_access(thd,
|
||||||
lex->exchange ? SELECT_ACL | FILE_ACL :
|
privileges_requested,
|
||||||
SELECT_ACL,
|
all_tables, FALSE, UINT_MAX, FALSE);
|
||||||
all_tables, UINT_MAX, FALSE);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
res= check_access(thd,
|
res= check_access(thd, privileges_requested, any_db, 0, 0, 0, UINT_MAX);
|
||||||
lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
|
|
||||||
any_db, 0, 0, 0, 0);
|
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
break;
|
break;
|
||||||
|
@ -2252,7 +2257,8 @@ mysql_execute_command(THD *thd)
|
||||||
|
|
||||||
res= execute_sqlcom_select(thd, all_tables);
|
res= execute_sqlcom_select(thd, all_tables);
|
||||||
break;
|
break;
|
||||||
case SQLCOM_PREPARE:
|
}
|
||||||
|
case SQLCOM_PREPARE:
|
||||||
{
|
{
|
||||||
mysql_sql_stmt_prepare(thd);
|
mysql_sql_stmt_prepare(thd);
|
||||||
break;
|
break;
|
||||||
|
@ -2268,8 +2274,8 @@ mysql_execute_command(THD *thd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_DO:
|
case SQLCOM_DO:
|
||||||
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))
|
|| open_and_lock_tables(thd, all_tables))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
res= mysql_do(thd, *lex->insert_list);
|
res= mysql_do(thd, *lex->insert_list);
|
||||||
|
@ -2378,8 +2384,8 @@ mysql_execute_command(THD *thd)
|
||||||
case SQLCOM_BACKUP_TABLE:
|
case SQLCOM_BACKUP_TABLE:
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
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)
|
||||||
check_global_access(thd, FILE_ACL))
|
|| check_global_access(thd, FILE_ACL))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res = mysql_backup_table(thd, first_table);
|
res = mysql_backup_table(thd, first_table);
|
||||||
|
@ -2390,8 +2396,8 @@ mysql_execute_command(THD *thd)
|
||||||
case SQLCOM_RESTORE_TABLE:
|
case SQLCOM_RESTORE_TABLE:
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if (check_table_access(thd, INSERT_ACL, all_tables, UINT_MAX, FALSE) ||
|
if (check_table_access(thd, INSERT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
|
||||||
check_global_access(thd, FILE_ACL))
|
|| check_global_access(thd, FILE_ACL))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res = mysql_restore_table(thd, first_table);
|
res = mysql_restore_table(thd, first_table);
|
||||||
|
@ -2490,7 +2496,7 @@ mysql_execute_command(THD *thd)
|
||||||
test(first_table->schema_table)))
|
test(first_table->schema_table)))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
/* Check that the first table has CREATE privilege */
|
/* 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;
|
goto error;
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_active_mi);
|
pthread_mutex_lock(&LOCK_active_mi);
|
||||||
|
@ -2860,7 +2866,7 @@ end_with_restore_list:
|
||||||
(TABLE_LIST *)
|
(TABLE_LIST *)
|
||||||
create_info.merge_list.first))
|
create_info.merge_list.first))
|
||||||
goto error; /* purecov: inspected */
|
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;
|
goto error;
|
||||||
if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
|
if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
|
||||||
{ // Rename of table
|
{ // Rename of table
|
||||||
|
@ -2869,8 +2875,8 @@ end_with_restore_list:
|
||||||
tmp_table.table_name= lex->name.str;
|
tmp_table.table_name= lex->name.str;
|
||||||
tmp_table.db=select_lex->db;
|
tmp_table.db=select_lex->db;
|
||||||
tmp_table.grant.privilege=priv;
|
tmp_table.grant.privilege=priv;
|
||||||
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
|
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, FALSE,
|
||||||
UINT_MAX, 0))
|
UINT_MAX, FALSE))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2924,10 +2930,11 @@ end_with_restore_list:
|
||||||
*/
|
*/
|
||||||
old_list= table[0];
|
old_list= table[0];
|
||||||
new_list= table->next_local[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,
|
(!test_all_bits(table->next_local->grant.privilege,
|
||||||
INSERT_ACL | CREATE_ACL) &&
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2958,11 +2965,54 @@ end_with_restore_list:
|
||||||
goto error;
|
goto error;
|
||||||
#else
|
#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 (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;
|
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);
|
res= mysqld_show_create(thd, first_table);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2970,8 +3020,8 @@ end_with_restore_list:
|
||||||
case SQLCOM_CHECKSUM:
|
case SQLCOM_CHECKSUM:
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if (check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables,
|
if (check_table_access(thd, SELECT_ACL, all_tables,
|
||||||
UINT_MAX, FALSE))
|
FALSE, UINT_MAX, FALSE))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
res = mysql_checksum_table(thd, first_table, &lex->check_opt);
|
res = mysql_checksum_table(thd, first_table, &lex->check_opt);
|
||||||
break;
|
break;
|
||||||
|
@ -2980,7 +3030,7 @@ end_with_restore_list:
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
|
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
|
||||||
UINT_MAX, FALSE))
|
FALSE, UINT_MAX, FALSE))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res= mysql_repair_table(thd, first_table, &lex->check_opt);
|
res= mysql_repair_table(thd, first_table, &lex->check_opt);
|
||||||
|
@ -2999,8 +3049,8 @@ end_with_restore_list:
|
||||||
case SQLCOM_CHECK:
|
case SQLCOM_CHECK:
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if (check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables,
|
if (check_table_access(thd, SELECT_ACL, all_tables,
|
||||||
UINT_MAX, FALSE))
|
TRUE, UINT_MAX, FALSE))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res = mysql_check_table(thd, first_table, &lex->check_opt);
|
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);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
|
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
|
||||||
UINT_MAX, FALSE))
|
FALSE, UINT_MAX, FALSE))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res= mysql_analyze_table(thd, first_table, &lex->check_opt);
|
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);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
|
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
|
||||||
UINT_MAX, FALSE))
|
FALSE, UINT_MAX, FALSE))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
|
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);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if (!lex->drop_temporary)
|
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 */
|
goto error; /* purecov: inspected */
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -3514,8 +3564,8 @@ end_with_restore_list:
|
||||||
if (lex->autocommit && end_active_trans(thd))
|
if (lex->autocommit && end_active_trans(thd))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
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)))
|
|| open_and_lock_tables(thd, all_tables)))
|
||||||
goto error;
|
goto error;
|
||||||
if (lex->one_shot_set && not_all_support_one_shot(lex_var_list))
|
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))
|
if (end_active_trans(thd))
|
||||||
goto error;
|
goto error;
|
||||||
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
|
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
|
||||||
UINT_MAX, FALSE))
|
FALSE, UINT_MAX, FALSE))
|
||||||
goto error;
|
goto error;
|
||||||
if (lex->protect_against_global_read_lock &&
|
if (lex->protect_against_global_read_lock &&
|
||||||
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
|
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
|
||||||
|
@ -3965,7 +4015,7 @@ end_with_restore_list:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL),
|
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;
|
goto error;
|
||||||
/* Conditionally writes to binlog */
|
/* Conditionally writes to binlog */
|
||||||
res= mysql_table_grant(thd, all_tables, lex->users_list,
|
res= mysql_table_grant(thd, all_tables, lex->users_list,
|
||||||
|
@ -4074,7 +4124,7 @@ end_with_restore_list:
|
||||||
#endif
|
#endif
|
||||||
case SQLCOM_HA_OPEN:
|
case SQLCOM_HA_OPEN:
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
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;
|
goto error;
|
||||||
res= mysql_ha_open(thd, first_table, 0);
|
res= mysql_ha_open(thd, first_table, 0);
|
||||||
break;
|
break;
|
||||||
|
@ -4360,7 +4410,8 @@ create_sp_error:
|
||||||
This will cache all SP and SF and open and lock all tables
|
This will cache all SP and SF and open and lock all tables
|
||||||
required for execution.
|
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))
|
open_and_lock_tables(thd, all_tables))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -4688,8 +4739,8 @@ create_sp_error:
|
||||||
}
|
}
|
||||||
case SQLCOM_DROP_VIEW:
|
case SQLCOM_DROP_VIEW:
|
||||||
{
|
{
|
||||||
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)
|
||||||
end_active_trans(thd))
|
|| end_active_trans(thd))
|
||||||
goto error;
|
goto error;
|
||||||
/* Conditionally writes to binlog. */
|
/* Conditionally writes to binlog. */
|
||||||
res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
|
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)) &&
|
(thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) &&
|
||||||
!(all_tables->view &&
|
!(all_tables->view &&
|
||||||
all_tables->effective_algorithm == VIEW_ALGORITHM_TMPTABLE) &&
|
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;
|
goto deny;
|
||||||
|
|
||||||
thd->security_ctx= backup_ctx;
|
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;
|
subselects_tables= subselects_tables->next_global;
|
||||||
}
|
}
|
||||||
if (subselects_tables &&
|
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 1;
|
||||||
}
|
}
|
||||||
return 0;
|
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
|
'save_priv' is used to save the User-table (global) and Db-table grants for
|
||||||
table. Note that we don't store db level grants if the
|
the supplied db name. Note that we don't store db level grants if the global
|
||||||
global grants is enough to satisfy the request and the
|
grants is enough to satisfy the request AND the global grants contains a
|
||||||
global grants contains a SELECT grant.
|
SELECT grant.
|
||||||
|
|
||||||
@note
|
A meta data table (from INFORMATION_SCHEMA) can always be accessed with
|
||||||
The idea of EXTRA_ACL is that one will be granted access to the table if
|
a SELECT_ACL.
|
||||||
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.
|
|
||||||
|
|
||||||
@retval
|
@see check_grant
|
||||||
0 ok
|
|
||||||
@retval
|
@return Status of denial of access by exclusive ACLs.
|
||||||
1 If we can't get the privileges and we don't use table/column
|
@retval FALSE Access can't exclusively be denied by Db- and User-table
|
||||||
grants.
|
access unless Column- and Table-grants are checked too.
|
||||||
|
@retval TRUE Access denied.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
|
check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
|
||||||
bool dont_check_global_grants, bool no_errors, bool schema_db)
|
bool dont_check_global_grants, bool no_errors, bool schema_db)
|
||||||
{
|
{
|
||||||
Security_context *sctx= thd->security_ctx;
|
Security_context *sctx= thd->security_ctx;
|
||||||
ulong db_access;
|
ulong db_access;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GRANT command:
|
GRANT command:
|
||||||
In case of database level grant the database name may be a pattern,
|
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.
|
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
|
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
|
(see SQLCOM_GRANT case, mysql_execute_command() function) and
|
||||||
set db_is_pattern according to 'dont_check_global_grants' value.
|
set db_is_pattern according to 'dont_check_global_grants' value.
|
||||||
*/
|
*/
|
||||||
bool db_is_pattern= (test(want_access & GRANT_ACL) &&
|
bool db_is_pattern= ((want_access & GRANT_ACL) && dont_check_global_grants);
|
||||||
dont_check_global_grants);
|
|
||||||
ulong dummy;
|
ulong dummy;
|
||||||
DBUG_ENTER("check_access");
|
DBUG_ENTER("check_access");
|
||||||
DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu",
|
DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu",
|
||||||
db ? db : "", want_access, sctx->master_access));
|
db ? db : "", want_access, sctx->master_access));
|
||||||
|
|
||||||
if (save_priv)
|
if (save_priv)
|
||||||
*save_priv=0;
|
*save_priv=0;
|
||||||
else
|
else
|
||||||
|
@ -5248,8 +5308,12 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
|
||||||
|
|
||||||
if (schema_db)
|
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)
|
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),
|
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
||||||
sctx->priv_user, sctx->priv_host, db_name);
|
sctx->priv_user, sctx->priv_host, db_name);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Access denied;
|
||||||
|
[out] *save_privileges= 0
|
||||||
|
*/
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Access granted */
|
||||||
*save_priv= SELECT_ACL;
|
*save_priv= SELECT_ACL;
|
||||||
DBUG_RETURN(FALSE);
|
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 ((sctx->master_access & want_access) == want_access)
|
||||||
{
|
{
|
||||||
/*
|
/* get access for current db */
|
||||||
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
|
|
||||||
*/
|
|
||||||
db_access= sctx->db_access;
|
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) &&
|
if (!(sctx->master_access & SELECT_ACL) &&
|
||||||
(db && (!thd->db || db_is_pattern || strcmp(db,thd->db))))
|
(db && (!thd->db || db_is_pattern || strcmp(db,thd->db))))
|
||||||
db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
|
db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
|
||||||
db_is_pattern);
|
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;
|
*save_priv=sctx->master_access | db_access;
|
||||||
DBUG_RETURN(FALSE);
|
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))
|
(! db && dont_check_global_grants))
|
||||||
{ // We can never grant this
|
{ // We can never grant this
|
||||||
DBUG_PRINT("error",("No possible access"));
|
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)
|
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)))
|
if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))
|
||||||
db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
|
db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
|
||||||
db_is_pattern);
|
db_is_pattern);
|
||||||
else
|
else
|
||||||
db_access= sctx->db_access;
|
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",
|
DBUG_PRINT("info",("db_access: %lu want_access: %lu",
|
||||||
db_access, want_access));
|
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 &&
|
(!dont_check_global_grants &&
|
||||||
!(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS))))
|
need_table_or_column_check))
|
||||||
DBUG_RETURN(FALSE); /* Ok */
|
{
|
||||||
|
/*
|
||||||
|
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"));
|
DBUG_PRINT("error",("Access denied"));
|
||||||
if (!no_errors)
|
if (!no_errors)
|
||||||
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
||||||
sctx->priv_user, sctx->priv_host,
|
sctx->priv_user, sctx->priv_host,
|
||||||
(db ? db : (thd->db ?
|
(db ? db : (thd->db ?
|
||||||
thd->db :
|
thd->db :
|
||||||
"unknown"))); /* purecov: tested */
|
"unknown")));
|
||||||
DBUG_RETURN(TRUE); /* purecov: tested */
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5368,14 +5477,20 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
|
||||||
|
|
||||||
DBUG_ASSERT(dst_table);
|
DBUG_ASSERT(dst_table);
|
||||||
|
|
||||||
if (check_access(thd, SELECT_ACL | EXTRA_ACL,
|
if (check_access(thd, SELECT_ACL, dst_table->db,
|
||||||
dst_table->db,
|
&dst_table->grant.privilege, FALSE, FALSE,
|
||||||
&dst_table->grant.privilege,
|
|
||||||
FALSE, FALSE,
|
|
||||||
test(dst_table->schema_table)))
|
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:
|
default:
|
||||||
break;
|
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
|
The suppled table list contains cached privileges. This functions calls the
|
||||||
@param want_access Privileges requested
|
help functions check_access and check_grant to verify the first three steps
|
||||||
@param tables List of tables to be checked
|
in the privileges check queue:
|
||||||
@param number Check at most this number of tables.
|
1. Global privileges
|
||||||
@param no_errors FALSE/TRUE - report/don't report error to
|
2. OR (db privileges AND host privileges)
|
||||||
the client (using my_error() call).
|
3. OR table privileges
|
||||||
|
4. OR column privileges (not checked by this function!)
|
||||||
|
5. OR routine privileges (not checked by this function!)
|
||||||
|
|
||||||
@note
|
@see check_access
|
||||||
Table privileges are cached in the table list for GRANT checking.
|
@see check_grant
|
||||||
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).
|
|
||||||
|
|
||||||
@retval FALSE OK
|
@note This functions assumes that table list used and
|
||||||
@retval TRUE Access denied
|
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
|
bool
|
||||||
check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
|
check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
|
||||||
uint number, bool no_errors)
|
bool any_combination_of_privileges_will_do,
|
||||||
|
uint number, bool no_errors)
|
||||||
{
|
{
|
||||||
TABLE_LIST *org_tables= tables;
|
TABLE_LIST *org_tables= tables;
|
||||||
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
|
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
|
||||||
|
@ -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
|
the given table list refers to the list for prelocking (contains tables
|
||||||
of other queries). For simple queries first_not_own_table is 0.
|
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++)
|
tables= tables->next_global, i++)
|
||||||
{
|
{
|
||||||
|
ulong want_access= requirements;
|
||||||
if (tables->security_ctx)
|
if (tables->security_ctx)
|
||||||
sctx= tables->security_ctx;
|
sctx= tables->security_ctx;
|
||||||
else
|
else
|
||||||
sctx= backup_ctx;
|
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)
|
want_access &= ~SELECT_ACL;
|
||||||
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
if (want_access & DB_ACLS)
|
||||||
sctx->priv_user, sctx->priv_host,
|
{
|
||||||
INFORMATION_SCHEMA_NAME.str);
|
if (!no_errors)
|
||||||
return TRUE;
|
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.
|
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))
|
if (check_show_access(thd, tables))
|
||||||
goto deny;
|
goto deny;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("derived: %d view: %d", tables->derived != 0,
|
||||||
|
tables->view != 0));
|
||||||
if (tables->is_anonymous_derived_table() ||
|
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;
|
continue;
|
||||||
thd->security_ctx= sctx;
|
thd->security_ctx= sctx;
|
||||||
if ((sctx->master_access & want_access) ==
|
if ((sctx->master_access & want_access) == want_access &&
|
||||||
(want_access & ~EXTRA_ACL) &&
|
thd->db)
|
||||||
thd->db)
|
|
||||||
tables->grant.privilege= want_access;
|
tables->grant.privilege= want_access;
|
||||||
else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
|
else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
|
||||||
{
|
{
|
||||||
if (check_access(thd, want_access, tables->get_db_name(),
|
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)))
|
test(tables->schema_table)))
|
||||||
goto deny; // Access denied
|
goto deny; // Access denied
|
||||||
}
|
}
|
||||||
else if (check_access(thd, want_access, tables->get_db_name(),
|
else if (check_access(thd, want_access, tables->get_db_name(),
|
||||||
&tables->grant.privilege, 0, no_errors,
|
&tables->grant.privilege, 0, no_errors, 0))
|
||||||
test(tables->schema_table)))
|
|
||||||
goto deny;
|
goto deny;
|
||||||
}
|
}
|
||||||
thd->security_ctx= backup_ctx;
|
thd->security_ctx= backup_ctx;
|
||||||
return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
|
return check_grant(thd,requirements,org_tables,
|
||||||
test(want_access & EXTRA_ACL), number, no_errors);
|
any_combination_of_privileges_will_do,
|
||||||
|
number, no_errors);
|
||||||
deny:
|
deny:
|
||||||
thd->security_ctx= backup_ctx;
|
thd->security_ctx= backup_ctx;
|
||||||
return TRUE;
|
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,
|
if (!check_access(thd, access, table->db,
|
||||||
&table->grant.privilege, 0, 1,
|
&table->grant.privilege, 0, 1,
|
||||||
test(table->schema_table)) &&
|
test(table->schema_table)) &&
|
||||||
!check_grant(thd, access, table, 0, 1, 1))
|
!check_grant(thd, access, table, FALSE, 1, TRUE))
|
||||||
DBUG_RETURN(0);
|
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,
|
else if ((check_access(thd, UPDATE_ACL, table->db,
|
||||||
&table->grant.privilege, 0, 1,
|
&table->grant.privilege, 0, 1,
|
||||||
test(table->schema_table)) ||
|
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,
|
(check_access(thd, SELECT_ACL, table->db,
|
||||||
&table->grant.privilege, 0, 0,
|
&table->grant.privilege, 0, 0,
|
||||||
test(table->schema_table)) ||
|
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);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
table->table_in_first_from_clause= 1;
|
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,
|
if (check_access(thd, SELECT_ACL, table->db,
|
||||||
&table->grant.privilege, 0, 0,
|
&table->grant.privilege, 0, 0,
|
||||||
test(table->schema_table)) ||
|
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);
|
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 */
|
/* sql_yacc guarantees that tables and aux_tables are not zero */
|
||||||
DBUG_ASSERT(aux_tables != 0);
|
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);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7324,7 +7465,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
|
||||||
call check_table_access() safely.
|
call check_table_access() safely.
|
||||||
*/
|
*/
|
||||||
thd->lex->query_tables_own_last= 0;
|
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;
|
thd->lex->query_tables_own_last= save_query_tables_own_last;
|
||||||
DBUG_RETURN(TRUE);
|
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.
|
CREATE TABLE query pre-check.
|
||||||
|
|
||||||
|
@ -7535,7 +7657,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||||
lex->create_info.merge_list.first))
|
lex->create_info.merge_list.first))
|
||||||
goto err;
|
goto err;
|
||||||
if (want_priv != CREATE_TMP_ACL &&
|
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;
|
goto err;
|
||||||
|
|
||||||
if (select_lex->item_list.elements)
|
if (select_lex->item_list.elements)
|
||||||
|
@ -7563,12 +7685,13 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
goto err;
|
||||||
}
|
}
|
||||||
else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
|
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;
|
goto err;
|
||||||
}
|
}
|
||||||
error= FALSE;
|
error= FALSE;
|
||||||
|
|
|
@ -1660,7 +1660,7 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl
|
||||||
bzero(&tables, sizeof(tables));
|
bzero(&tables, sizeof(tables));
|
||||||
tables.db= (char *)"mysql";
|
tables.db= (char *)"mysql";
|
||||||
tables.table_name= tables.alias= (char *)"plugin";
|
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);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/* need to open before acquiring LOCK_plugin or it will deadlock */
|
/* need to open before acquiring LOCK_plugin or it will deadlock */
|
||||||
|
|
|
@ -1336,7 +1336,7 @@ static int mysql_test_select(Prepared_statement *stmt,
|
||||||
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
|
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
|
||||||
if (tables)
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
else if (check_access(thd, privilege, any_db,0,0,0,0))
|
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;
|
THD *thd= stmt->thd;
|
||||||
|
|
||||||
DBUG_ENTER("mysql_test_do_fields");
|
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);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (open_normal_and_derived_tables(thd, tables, 0))
|
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;
|
THD *thd= stmt->thd;
|
||||||
set_var_base *var;
|
set_var_base *var;
|
||||||
|
|
||||||
if ((tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
|
if ((tables && check_table_access(thd, SELECT_ACL, tables, FALSE,
|
||||||
|| open_normal_and_derived_tables(thd, tables, 0))
|
UINT_MAX, FALSE)) ||
|
||||||
|
open_normal_and_derived_tables(thd, tables, 0))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
while ((var= it++))
|
while ((var= it++))
|
||||||
|
@ -1472,7 +1474,8 @@ static bool mysql_test_call_fields(Prepared_statement *stmt,
|
||||||
THD *thd= stmt->thd;
|
THD *thd= stmt->thd;
|
||||||
Item *item;
|
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))
|
open_normal_and_derived_tables(thd, tables, 0))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
|
@ -560,7 +560,7 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
|
||||||
table_list.table_name= uname;
|
table_list.table_name= uname;
|
||||||
table_list.table_name_length= file_name_len;
|
table_list.table_name_length= file_name_len;
|
||||||
table_list.grant.privilege=col_access;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -3745,8 +3745,9 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
|
||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
uint col_access;
|
uint col_access;
|
||||||
check_access(thd,SELECT_ACL | EXTRA_ACL, db_name->str,
|
check_access(thd,SELECT_ACL, db_name->str,
|
||||||
&tables->grant.privilege, 0, 0, test(tables->schema_table));
|
&tables->grant.privilege, FALSE, FALSE,
|
||||||
|
test(tables->schema_table));
|
||||||
col_access= get_column_grant(thd, &tables->grant,
|
col_access= get_column_grant(thd, &tables->grant,
|
||||||
db_name->str, table_name->str,
|
db_name->str, table_name->str,
|
||||||
field->field_name) & COL_ACLS;
|
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= proc_tables.alias= (char*) "proc";
|
||||||
proc_tables.table_name_length= 4;
|
proc_tables.table_name_length= 4;
|
||||||
proc_tables.lock_type= TL_READ;
|
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)))
|
if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup)))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(1);
|
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;
|
Table_triggers_list *triggers= tables->table->triggers;
|
||||||
int event, timing;
|
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;
|
goto ret;
|
||||||
|
|
||||||
for (event= 0; event < (int)TRG_EVENT_MAX; event++)
|
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)
|
if (!lst)
|
||||||
return TRUE;
|
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");
|
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "TRIGGER");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -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;
|
TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
|
||||||
thd->lex->query_tables_own_last= 0;
|
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;
|
thd->lex->query_tables_own_last= save_query_tables_own_last;
|
||||||
|
|
||||||
|
|
|
@ -1077,7 +1077,7 @@ reopen_tables:
|
||||||
if (check_access(thd, want_privilege,
|
if (check_access(thd, want_privilege,
|
||||||
tl->db, &tl->grant.privilege, 0, 0,
|
tl->db, &tl->grant.privilege, 0, 0,
|
||||||
test(tl->schema_table)) ||
|
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);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege,
|
||||||
0, 0, is_schema_db(view->db)) ||
|
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 &&
|
(mode != VIEW_CREATE_NEW &&
|
||||||
(check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
|
(check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
|
||||||
0, 0, is_schema_db(view->db)) ||
|
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;
|
goto err;
|
||||||
|
|
||||||
for (sl= select_lex; sl; sl= sl->next_select())
|
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,
|
if (check_access(thd, SELECT_ACL, tbl->db,
|
||||||
&tbl->grant.privilege, 0, 0, test(tbl->schema_table)) ||
|
&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;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1233,8 +1233,9 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
||||||
if (!table->prelocking_placeholder &&
|
if (!table->prelocking_placeholder &&
|
||||||
(old_lex->sql_command == SQLCOM_SELECT && old_lex->describe))
|
(old_lex->sql_command == SQLCOM_SELECT && old_lex->describe))
|
||||||
{
|
{
|
||||||
if (check_table_access(thd, SELECT_ACL, view_tables, UINT_MAX, TRUE) &&
|
if (check_table_access(thd, SELECT_ACL, view_tables, FALSE,
|
||||||
check_table_access(thd, SHOW_VIEW_ACL, table, UINT_MAX, TRUE))
|
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));
|
my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0));
|
||||||
goto err;
|
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) &&
|
(old_lex->sql_command == SQLCOM_SHOW_CREATE) &&
|
||||||
!table->belong_to_view)
|
!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;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue