mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-14443 DENY statement
Implements DENY/REVOKE DENY and associated tasks.
This commit is contained in:
@@ -787,7 +787,7 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
|
||||
strmake_buf(sctx->priv_user, mysql->user);
|
||||
sctx->user= my_strdup(PSI_NOT_INSTRUMENTED, mysql->user, MYF(0));
|
||||
sctx->proxy_user[0]= 0;
|
||||
sctx->master_access= GLOBAL_ACLS; // Full rights
|
||||
sctx->master_access= access_t(GLOBAL_ACLS); // Full rights
|
||||
emb_transfer_connect_attrs(mysql);
|
||||
|
||||
/* Change database if necessary */
|
||||
|
||||
71
mysql-test/main/deny_admin.result
Normal file
71
mysql-test/main/deny_admin.result
Normal file
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# Test DENY for global administrative privileges
|
||||
#
|
||||
CREATE USER user1@localhost;
|
||||
CREATE USER user2@localhost;
|
||||
# Test RELOAD privilege
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
|
||||
DENY RELOAD ON *.* TO user1@localhost;
|
||||
connect con1, localhost, user1,,;
|
||||
FLUSH TABLES;
|
||||
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation
|
||||
FLUSH LOGS;
|
||||
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation
|
||||
connection default;
|
||||
disconnect con1;
|
||||
# Test SHUTDOWN privilege
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
|
||||
DENY SHUTDOWN ON *.* TO user1@localhost;
|
||||
connect con1, localhost, user1,,;
|
||||
SHUTDOWN;
|
||||
ERROR 42000: Access denied; you need (at least one of) the SHUTDOWN privilege(s) for this operation
|
||||
connection default;
|
||||
disconnect con1;
|
||||
# Test PROCESS privilege
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
|
||||
DENY PROCESS ON *.* TO user1@localhost;
|
||||
connect con1, localhost, user1,,;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER <> 'user1';
|
||||
COUNT(*)
|
||||
0
|
||||
connection default;
|
||||
disconnect con1;
|
||||
# Test FILE privilege
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
|
||||
DENY FILE ON *.* TO user1@localhost;
|
||||
connect con1, localhost, user1,,;
|
||||
SELECT 'test' INTO OUTFILE 'test.txt';
|
||||
ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
|
||||
connection default;
|
||||
disconnect con1;
|
||||
# Test combination of DENY on multiple global privileges
|
||||
GRANT ALL PRIVILEGES ON *.* TO user2@localhost;
|
||||
DENY RELOAD, SHUTDOWN ON *.* TO user2@localhost;
|
||||
connect con2, localhost, user2,,;
|
||||
FLUSH TABLES;
|
||||
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation
|
||||
SHUTDOWN;
|
||||
ERROR 42000: Access denied; you need (at least one of) the SHUTDOWN privilege(s) for this operation
|
||||
connection default;
|
||||
disconnect con2;
|
||||
# Cleanup
|
||||
DROP USER user1@localhost;
|
||||
DROP USER user2@localhost;
|
||||
#
|
||||
# Test CONNECTION ADMIN privilege behaviors with DENY
|
||||
#
|
||||
CREATE USER user_super@localhost;
|
||||
GRANT ALL PRIVILEGES ON *.* TO user_super@localhost;
|
||||
DENY CONNECTION ADMIN ON *.* TO user_super@localhost;
|
||||
connect con_super, localhost, user_super,,;
|
||||
# Should not be able to kill other connections
|
||||
connection default;
|
||||
connection con_super;
|
||||
KILL ID;
|
||||
ERROR HY000: You are not owner of thread ID
|
||||
# Should not be able to set global variables
|
||||
SET GLOBAL max_connections = 200;
|
||||
ERROR 42000: Access denied; you need (at least one of) the CONNECTION ADMIN privilege(s) for this operation
|
||||
connection default;
|
||||
disconnect con_super;
|
||||
DROP USER user_super@localhost;
|
||||
105
mysql-test/main/deny_admin.test
Normal file
105
mysql-test/main/deny_admin.test
Normal file
@@ -0,0 +1,105 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/no_protocol.inc
|
||||
|
||||
--echo #
|
||||
--echo # Test DENY for global administrative privileges
|
||||
--echo #
|
||||
|
||||
CREATE USER user1@localhost;
|
||||
CREATE USER user2@localhost;
|
||||
|
||||
--echo # Test RELOAD privilege
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
|
||||
DENY RELOAD ON *.* TO user1@localhost;
|
||||
|
||||
connect (con1, localhost, user1,,);
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
FLUSH TABLES;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
FLUSH LOGS;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
--echo # Test SHUTDOWN privilege
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
|
||||
DENY SHUTDOWN ON *.* TO user1@localhost;
|
||||
|
||||
connect (con1, localhost, user1,,);
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
SHUTDOWN;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
--echo # Test PROCESS privilege
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
|
||||
DENY PROCESS ON *.* TO user1@localhost;
|
||||
|
||||
let $count_sessions= 1;
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
||||
connect (con1, localhost, user1,,);
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER <> 'user1';
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
|
||||
--echo # Test FILE privilege
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
|
||||
DENY FILE ON *.* TO user1@localhost;
|
||||
|
||||
connect (con1, localhost, user1,,);
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
SELECT 'test' INTO OUTFILE 'test.txt';
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
--echo # Test combination of DENY on multiple global privileges
|
||||
GRANT ALL PRIVILEGES ON *.* TO user2@localhost;
|
||||
DENY RELOAD, SHUTDOWN ON *.* TO user2@localhost;
|
||||
|
||||
connect (con2, localhost, user2,,);
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
FLUSH TABLES;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
SHUTDOWN;
|
||||
|
||||
connection default;
|
||||
disconnect con2;
|
||||
|
||||
--echo # Cleanup
|
||||
DROP USER user1@localhost;
|
||||
DROP USER user2@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Test CONNECTION ADMIN privilege behaviors with DENY
|
||||
--echo #
|
||||
CREATE USER user_super@localhost;
|
||||
GRANT ALL PRIVILEGES ON *.* TO user_super@localhost;
|
||||
DENY CONNECTION ADMIN ON *.* TO user_super@localhost;
|
||||
|
||||
connect (con_super, localhost, user_super,,);
|
||||
|
||||
--echo # Should not be able to kill other connections
|
||||
connection default;
|
||||
let $default_id = `SELECT CONNECTION_ID()`;
|
||||
|
||||
connection con_super;
|
||||
--replace_result $default_id ID
|
||||
--error ER_KILL_DENIED_ERROR
|
||||
eval KILL $default_id;
|
||||
|
||||
--echo # Should not be able to set global variables
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
SET GLOBAL max_connections = 200;
|
||||
|
||||
|
||||
connection default;
|
||||
disconnect con_super;
|
||||
DROP USER user_super@localhost;
|
||||
166
mysql-test/main/deny_bugs.result
Normal file
166
mysql-test/main/deny_bugs.result
Normal file
@@ -0,0 +1,166 @@
|
||||
#
|
||||
# MDEV-40014 Access to freed/poisoned memory in SHOW GRANTS
|
||||
# after REVOKE DENY, if only negative grants are present
|
||||
#
|
||||
CREATE TABLE t1(val int);
|
||||
CREATE USER u;
|
||||
DENY EXECUTE ON test.* TO u;
|
||||
DENY UPDATE (val) ON t1 TO u;
|
||||
REVOKE DENY EXECUTE ON test.* FROM u;
|
||||
SHOW GRANTS FOR u;
|
||||
Grants for u@%
|
||||
GRANT USAGE ON *.* TO `u`@`%`
|
||||
DENY UPDATE (`val`) ON `test`.`t1` TO `u`@`%`
|
||||
DROP USER u;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-40028 Assertion `rights.allow_bits() == merged->cols' failed in int update_role_columns
|
||||
#
|
||||
CREATE TABLE t (c1 INT, c2 INT, c3 int);
|
||||
CREATE ROLE r;
|
||||
DENY SELECT (c2) ON t TO r;
|
||||
SHOW GRANTS FOR r;
|
||||
Grants for r
|
||||
GRANT USAGE ON *.* TO `r`
|
||||
DENY SELECT (`c2`) ON `test`.`t` TO `r`
|
||||
REVOKE DENY SELECT (c2) ON t FROM r;
|
||||
SHOW GRANTS FOR r;
|
||||
Grants for r
|
||||
GRANT USAGE ON *.* TO `r`
|
||||
DROP ROLE r;
|
||||
DROP TABLE t;
|
||||
#
|
||||
# MDEV-36503 Single routine-level DENY EXECUTE hides other routine metadata in the database
|
||||
#
|
||||
CREATE DATABASE d1;
|
||||
CREATE DEFINER=root@localhost PROCEDURE d1.p1() BEGIN SELECT 1; END$$
|
||||
CREATE DEFINER=root@localhost PROCEDURE d1.p2() BEGIN SELECT 2; END$$
|
||||
CREATE USER u@localhost;
|
||||
GRANT EXECUTE ON d1.* TO u@localhost;
|
||||
DENY EXECUTE ON PROCEDURE d1.p1 TO u@localhost;
|
||||
DENY ALTER ROUTINE ON PROCEDURE d1.p2 TO u@localhost;
|
||||
FLUSH PRIVILEGES;
|
||||
connect con_bug36503, localhost, u,,d1;
|
||||
# p2 must be callable and both p1, p2 must appear in INFORMATION_SCHEMA.ROUTINES
|
||||
CALL p2();
|
||||
2
|
||||
2
|
||||
SELECT ROUTINE_NAME FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA='d1' ORDER BY ROUTINE_NAME;
|
||||
ROUTINE_NAME
|
||||
p2
|
||||
# p1 is denied, calling it must fail
|
||||
CALL p1();
|
||||
ERROR 42000: execute command denied to user 'u'@'localhost' for routine 'd1.p1'
|
||||
disconnect con_bug36503;
|
||||
connection default;
|
||||
DROP DATABASE d1;
|
||||
DROP USER u@localhost;
|
||||
#
|
||||
# MDEV-40116 Column-level DENY SELECT hides accessible columns and table metadata
|
||||
#
|
||||
CREATE DATABASE d1;
|
||||
CREATE TABLE d1.t1 (a INT, b INT, c INT, KEY(a));
|
||||
INSERT INTO d1.t1 VALUES (1,2,3);
|
||||
CREATE USER u@localhost;
|
||||
GRANT SELECT ON d1.t1 TO u@localhost;
|
||||
DENY SELECT (b) ON d1.t1 TO u@localhost;
|
||||
FLUSH PRIVILEGES;
|
||||
connect con_bug40116, localhost, u,,d1;
|
||||
# a and c are accessible, b is denied
|
||||
SELECT a, c FROM d1.t1;
|
||||
a c
|
||||
1 3
|
||||
SELECT * FROM d1.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u'@'localhost' for column 'b' in table 't1'
|
||||
# metadata commands must work and show a, c (not b)
|
||||
SHOW COLUMNS FROM d1.t1;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) YES MUL NULL
|
||||
c int(11) YES NULL
|
||||
SHOW INDEX FROM d1.t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored
|
||||
t1 1 a 1 a A NULL NULL NULL YES BTREE NO
|
||||
SHOW CREATE TABLE d1.t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`c` int(11) DEFAULT NULL,
|
||||
KEY `a` (`a`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
|
||||
SELECT COLUMN_NAME FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA='d1' AND TABLE_NAME='t1' ORDER BY COLUMN_NAME;
|
||||
COLUMN_NAME
|
||||
a
|
||||
c
|
||||
disconnect con_bug40116;
|
||||
connection default;
|
||||
DROP DATABASE d1;
|
||||
DROP USER u@localhost;
|
||||
#
|
||||
# MDEV-40026 SIGSEGV in acl_insert_db on FLUSH PRIVILEGES with overlong DENY names
|
||||
#
|
||||
CREATE USER u@localhost;
|
||||
CALL mtr.add_suppression('.*Malformed DENY entry in mysql\\.global_priv at array position [0-2] for ''u''@''localhost'' ignored');
|
||||
UPDATE mysql.global_priv SET Priv= json_set(Priv, '$.denies', json_array(
|
||||
json_object('type','db', 'db',REPEAT('a',300),'bits',1),
|
||||
json_object('type','table','db','d1','table',REPEAT('b',300),'bits',1),
|
||||
json_object('type','column','db','d1','table','t1','column',REPEAT('c',300),'bits',1)
|
||||
)) WHERE User='u' AND Host='localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
FOUND 1 /Malformed DENY entry in mysql.global_priv at array position 0 for 'u'@'localhost' ignored/ in mysqld.1.err
|
||||
FOUND 1 /Malformed DENY entry in mysql.global_priv at array position 1 for 'u'@'localhost' ignored/ in mysqld.1.err
|
||||
FOUND 1 /Malformed DENY entry in mysql.global_priv at array position 2 for 'u'@'localhost' ignored/ in mysqld.1.err
|
||||
DROP USER u@localhost;
|
||||
#
|
||||
# MDEV-40131 DENY not reloaded, granted to a ROLEs exclusively
|
||||
#
|
||||
CREATE DATABASE d1;
|
||||
CREATE TABLE d1.t1 (a INT);
|
||||
INSERT INTO d1.t1 VALUES (1);
|
||||
CREATE ROLE r;
|
||||
GRANT SELECT ON d1.* TO r;
|
||||
DENY SELECT ON d1.t1 TO r;
|
||||
CREATE USER u@localhost;
|
||||
GRANT r TO u@localhost;
|
||||
SET DEFAULT ROLE r FOR u@localhost;
|
||||
# BEFORE reload: role DENY correctly enforced
|
||||
connect p, localhost, u,, d1;
|
||||
SELECT * FROM d1.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u'@'localhost' for table `d1`.`t1`
|
||||
connection default;
|
||||
disconnect p;
|
||||
FLUSH PRIVILEGES;
|
||||
# role DENY must survive the reload
|
||||
SHOW GRANTS FOR r;
|
||||
Grants for r
|
||||
GRANT USAGE ON *.* TO `r`
|
||||
GRANT SELECT ON `d1`.* TO `r`
|
||||
DENY SELECT ON `d1`.`t1` TO `r`
|
||||
# AFTER reload: role DENY must still be enforced
|
||||
connect p, localhost, u,, d1;
|
||||
SELECT * FROM d1.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u'@'localhost' for table `d1`.`t1`
|
||||
connection default;
|
||||
disconnect p;
|
||||
DROP ROLE r;
|
||||
DROP DATABASE d1;
|
||||
DROP USER u@localhost;
|
||||
#
|
||||
# MDEV-40300 Assertion in update_role_columns on DROP ROLE
|
||||
#
|
||||
CREATE TABLE t1 (c1 INT,c2 INT,c3 INT);
|
||||
CREATE ROLE r1;
|
||||
CREATE ROLE r2;
|
||||
GRANT r2 TO r1;
|
||||
DENY DELETE ON t1 TO r1;
|
||||
DENY SELECT (c2) ON t1 TO r1;
|
||||
GRANT SELECT (c3) ON t1 TO r2;
|
||||
REVOKE DENY ALL PRIVILEGES ON t1 FROM r1;
|
||||
DROP ROLE IF EXISTS r2;
|
||||
SHOW GRANTS FOR r1;
|
||||
Grants for r1
|
||||
GRANT USAGE ON *.* TO `r1`
|
||||
DENY SELECT (`c2`) ON `test`.`t1` TO `r1`
|
||||
DROP ROLE r1;
|
||||
DROP TABLE t1;
|
||||
159
mysql-test/main/deny_bugs.test
Normal file
159
mysql-test/main/deny_bugs.test
Normal file
@@ -0,0 +1,159 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40014 Access to freed/poisoned memory in SHOW GRANTS
|
||||
--echo # after REVOKE DENY, if only negative grants are present
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1(val int);
|
||||
CREATE USER u;
|
||||
DENY EXECUTE ON test.* TO u;
|
||||
DENY UPDATE (val) ON t1 TO u;
|
||||
REVOKE DENY EXECUTE ON test.* FROM u;
|
||||
SHOW GRANTS FOR u;
|
||||
|
||||
DROP USER u;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40028 Assertion `rights.allow_bits() == merged->cols' failed in int update_role_columns
|
||||
--echo #
|
||||
CREATE TABLE t (c1 INT, c2 INT, c3 int);
|
||||
CREATE ROLE r;
|
||||
DENY SELECT (c2) ON t TO r;
|
||||
SHOW GRANTS FOR r;
|
||||
REVOKE DENY SELECT (c2) ON t FROM r;
|
||||
SHOW GRANTS FOR r;
|
||||
DROP ROLE r;
|
||||
DROP TABLE t;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36503 Single routine-level DENY EXECUTE hides other routine metadata in the database
|
||||
--echo #
|
||||
CREATE DATABASE d1;
|
||||
DELIMITER $$;
|
||||
CREATE DEFINER=root@localhost PROCEDURE d1.p1() BEGIN SELECT 1; END$$
|
||||
CREATE DEFINER=root@localhost PROCEDURE d1.p2() BEGIN SELECT 2; END$$
|
||||
DELIMITER ;$$
|
||||
CREATE USER u@localhost;
|
||||
GRANT EXECUTE ON d1.* TO u@localhost;
|
||||
DENY EXECUTE ON PROCEDURE d1.p1 TO u@localhost;
|
||||
DENY ALTER ROUTINE ON PROCEDURE d1.p2 TO u@localhost;
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
connect (con_bug36503, localhost, u,,d1);
|
||||
--echo # p2 must be callable and both p1, p2 must appear in INFORMATION_SCHEMA.ROUTINES
|
||||
CALL p2();
|
||||
SELECT ROUTINE_NAME FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA='d1' ORDER BY ROUTINE_NAME;
|
||||
--echo # p1 is denied, calling it must fail
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL p1();
|
||||
|
||||
disconnect con_bug36503;
|
||||
connection default;
|
||||
DROP DATABASE d1;
|
||||
DROP USER u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40116 Column-level DENY SELECT hides accessible columns and table metadata
|
||||
--echo #
|
||||
CREATE DATABASE d1;
|
||||
CREATE TABLE d1.t1 (a INT, b INT, c INT, KEY(a));
|
||||
INSERT INTO d1.t1 VALUES (1,2,3);
|
||||
CREATE USER u@localhost;
|
||||
GRANT SELECT ON d1.t1 TO u@localhost;
|
||||
DENY SELECT (b) ON d1.t1 TO u@localhost;
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
connect (con_bug40116, localhost, u,,d1);
|
||||
--echo # a and c are accessible, b is denied
|
||||
SELECT a, c FROM d1.t1;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT * FROM d1.t1;
|
||||
--echo # metadata commands must work and show a, c (not b)
|
||||
SHOW COLUMNS FROM d1.t1;
|
||||
SHOW INDEX FROM d1.t1;
|
||||
SHOW CREATE TABLE d1.t1;
|
||||
SELECT COLUMN_NAME FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA='d1' AND TABLE_NAME='t1' ORDER BY COLUMN_NAME;
|
||||
|
||||
disconnect con_bug40116;
|
||||
connection default;
|
||||
DROP DATABASE d1;
|
||||
DROP USER u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40026 SIGSEGV in acl_insert_db on FLUSH PRIVILEGES with overlong DENY names
|
||||
--echo #
|
||||
CREATE USER u@localhost;
|
||||
|
||||
CALL mtr.add_suppression('.*Malformed DENY entry in mysql\\.global_priv at array position [0-2] for ''u''@''localhost'' ignored');
|
||||
|
||||
UPDATE mysql.global_priv SET Priv= json_set(Priv, '$.denies', json_array(
|
||||
json_object('type','db', 'db',REPEAT('a',300),'bits',1),
|
||||
json_object('type','table','db','d1','table',REPEAT('b',300),'bits',1),
|
||||
json_object('type','column','db','d1','table','t1','column',REPEAT('c',300),'bits',1)
|
||||
)) WHERE User='u' AND Host='localhost';
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
--let SEARCH_FILE= `SELECT @@log_error`
|
||||
--let SEARCH_PATTERN= Malformed DENY entry in mysql.global_priv at array position 0 for 'u'@'localhost' ignored
|
||||
--source include/search_pattern_in_file.inc
|
||||
--let SEARCH_PATTERN= Malformed DENY entry in mysql.global_priv at array position 1 for 'u'@'localhost' ignored
|
||||
--source include/search_pattern_in_file.inc
|
||||
--let SEARCH_PATTERN= Malformed DENY entry in mysql.global_priv at array position 2 for 'u'@'localhost' ignored
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
DROP USER u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40131 DENY not reloaded, granted to a ROLEs exclusively
|
||||
--echo #
|
||||
CREATE DATABASE d1;
|
||||
CREATE TABLE d1.t1 (a INT);
|
||||
INSERT INTO d1.t1 VALUES (1);
|
||||
CREATE ROLE r;
|
||||
GRANT SELECT ON d1.* TO r;
|
||||
DENY SELECT ON d1.t1 TO r;
|
||||
CREATE USER u@localhost;
|
||||
GRANT r TO u@localhost;
|
||||
SET DEFAULT ROLE r FOR u@localhost;
|
||||
|
||||
--echo # BEFORE reload: role DENY correctly enforced
|
||||
connect (p, localhost, u,, d1);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM d1.t1;
|
||||
connection default;
|
||||
disconnect p;
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
--echo # role DENY must survive the reload
|
||||
SHOW GRANTS FOR r;
|
||||
|
||||
--echo # AFTER reload: role DENY must still be enforced
|
||||
connect (p, localhost, u,, d1);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM d1.t1;
|
||||
connection default;
|
||||
disconnect p;
|
||||
DROP ROLE r;
|
||||
DROP DATABASE d1;
|
||||
DROP USER u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40300 Assertion in update_role_columns on DROP ROLE
|
||||
--echo #
|
||||
CREATE TABLE t1 (c1 INT,c2 INT,c3 INT);
|
||||
CREATE ROLE r1;
|
||||
CREATE ROLE r2;
|
||||
GRANT r2 TO r1;
|
||||
DENY DELETE ON t1 TO r1;
|
||||
DENY SELECT (c2) ON t1 TO r1;
|
||||
GRANT SELECT (c3) ON t1 TO r2;
|
||||
REVOKE DENY ALL PRIVILEGES ON t1 FROM r1;
|
||||
DROP ROLE IF EXISTS r2;
|
||||
SHOW GRANTS FOR r1;
|
||||
DROP ROLE r1;
|
||||
DROP TABLE t1;
|
||||
160
mysql-test/main/deny_column.result
Normal file
160
mysql-test/main/deny_column.result
Normal file
@@ -0,0 +1,160 @@
|
||||
#
|
||||
# Column-level DENY privilege test
|
||||
#
|
||||
CREATE DATABASE deny_col_db;
|
||||
CREATE TABLE deny_col_db.sensitive_data (
|
||||
id INT,
|
||||
public_info VARCHAR(50),
|
||||
salary DECIMAL(10,2),
|
||||
ssn VARCHAR(11),
|
||||
address VARCHAR(100)
|
||||
);
|
||||
INSERT INTO deny_col_db.sensitive_data VALUES
|
||||
(1, 'John Doe', 75000.00, '123-45-6789', '123 Main St'),
|
||||
(2, 'Jane Smith', 85000.00, '987-65-4321', '456 Oak Ave');
|
||||
CREATE USER col_user1@localhost;
|
||||
CREATE USER col_user2@localhost;
|
||||
#
|
||||
# Basic column-level DENY
|
||||
#
|
||||
GRANT SELECT ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY SELECT (salary, ssn) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
connect con1, localhost, col_user1,,deny_col_db;
|
||||
SELECT id, public_info FROM sensitive_data;
|
||||
id public_info
|
||||
1 John Doe
|
||||
2 Jane Smith
|
||||
SELECT salary FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user1'@'localhost' for column 'salary' in table 'sensitive_data'
|
||||
SELECT ssn FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user1'@'localhost' for column 'ssn' in table 'sensitive_data'
|
||||
SELECT * FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user1'@'localhost' for column 'salary' in table 'sensitive_data'
|
||||
SELECT id, salary FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user1'@'localhost' for column 'salary' in table 'sensitive_data'
|
||||
disconnect con1;
|
||||
connection default;
|
||||
REVOKE SELECT ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
REVOKE DENY SELECT (salary, ssn) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
#
|
||||
# Column DENY takes precedence over explicit column GRANT
|
||||
#
|
||||
GRANT SELECT (salary,id,public_info) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY SELECT (salary) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
connect con3, localhost, col_user1,,deny_col_db;
|
||||
SELECT id, public_info FROM sensitive_data;
|
||||
id public_info
|
||||
1 John Doe
|
||||
2 Jane Smith
|
||||
SELECT salary FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user1'@'localhost' for column 'salary' in table 'sensitive_data'
|
||||
disconnect con3;
|
||||
connection default;
|
||||
REVOKE SELECT (salary,id,public_info) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
REVOKE DENY SELECT (salary) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
#
|
||||
# REVOKE DENY on a column
|
||||
#
|
||||
GRANT SELECT (salary) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY SELECT (salary,ssn) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
REVOKE DENY SELECT (salary) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
connect con4, localhost, col_user1,,deny_col_db;
|
||||
SELECT salary FROM sensitive_data;
|
||||
salary
|
||||
75000.00
|
||||
85000.00
|
||||
SELECT ssn FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user1'@'localhost' for column 'ssn' in table 'sensitive_data'
|
||||
disconnect con4;
|
||||
connection default;
|
||||
REVOKE DENY SELECT (ssn) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
#
|
||||
# Multiple column DENYs
|
||||
#
|
||||
GRANT SELECT ON deny_col_db.sensitive_data TO col_user2@localhost;
|
||||
DENY SELECT (salary, ssn, address) ON deny_col_db.sensitive_data TO col_user2@localhost;
|
||||
connect con5, localhost, col_user2,,deny_col_db;
|
||||
SELECT id, public_info FROM sensitive_data;
|
||||
id public_info
|
||||
1 John Doe
|
||||
2 Jane Smith
|
||||
SELECT salary FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user2'@'localhost' for column 'salary' in table 'sensitive_data'
|
||||
SELECT address FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user2'@'localhost' for column 'address' in table 'sensitive_data'
|
||||
SELECT * FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user2'@'localhost' for column 'salary' in table 'sensitive_data'
|
||||
disconnect con5;
|
||||
connection default;
|
||||
REVOKE DENY SELECT (salary, ssn, address) ON deny_col_db.sensitive_data FROM col_user2@localhost;
|
||||
REVOKE SELECT ON deny_col_db.sensitive_data FROM col_user2@localhost;
|
||||
#
|
||||
# Column DENY with INSERT/UPDATE operations
|
||||
#
|
||||
CREATE TABLE deny_col_db.audit_log (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
action VARCHAR(50),
|
||||
modified_by VARCHAR(50),
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
GRANT SELECT, INSERT ON deny_col_db.audit_log TO col_user1@localhost;
|
||||
DENY INSERT (modified_by) ON deny_col_db.audit_log TO col_user1@localhost;
|
||||
connect con8, localhost, col_user1,,deny_col_db;
|
||||
INSERT INTO audit_log (action) VALUES ('test_action');
|
||||
INSERT INTO audit_log (action, modified_by) VALUES ('test', 'hacker');
|
||||
ERROR 42000: INSERT command denied to user 'col_user1'@'localhost' for column 'modified_by' in table 'audit_log'
|
||||
SELECT * FROM audit_log;
|
||||
id action modified_by timestamp
|
||||
1 test_action NULL TIMESTAMP
|
||||
disconnect con8;
|
||||
connection default;
|
||||
#
|
||||
# Column DENY with UPDATE
|
||||
#
|
||||
GRANT UPDATE ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY UPDATE (salary) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
GRANT SELECT(id,public_info) on deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
connect con9, localhost, col_user1,,deny_col_db;
|
||||
UPDATE sensitive_data SET public_info = 'Updated' WHERE id = 1;
|
||||
UPDATE sensitive_data SET salary = 100000 WHERE id = 1;
|
||||
ERROR 42000: UPDATE command denied to user 'col_user1'@'localhost' for column 'salary' in table 'sensitive_data'
|
||||
UPDATE sensitive_data SET public_info = 'X', salary = 90000 WHERE id = 2;
|
||||
ERROR 42000: UPDATE command denied to user 'col_user1'@'localhost' for column 'salary' in table 'sensitive_data'
|
||||
disconnect con9;
|
||||
connection default;
|
||||
REVOKE SELECT (id,public_info) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
#
|
||||
# Table-level DENY SELECT: UPDATE without WHERE must succeed (no read needed)
|
||||
#
|
||||
DENY SELECT ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
connect con9b, localhost, col_user1,,deny_col_db;
|
||||
# UPDATE with WHERE reads id -> SELECT needed -> DENY fires
|
||||
UPDATE sensitive_data SET public_info = 'ps_test' WHERE id = 1;
|
||||
ERROR 42000: SELECT command denied to user 'col_user1'@'localhost' for column 'id' in table 'sensitive_data'
|
||||
# UPDATE without WHERE: no SELECT needed, must succeed
|
||||
UPDATE sensitive_data SET public_info = 'ps_test';
|
||||
disconnect con9b;
|
||||
connection default;
|
||||
REVOKE DENY SELECT ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
REVOKE UPDATE ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
#
|
||||
# Column DENY is case-insensitive
|
||||
#
|
||||
GRANT SELECT ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY SELECT (SaLaRy) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
connect con10, localhost, col_user1,,deny_col_db;
|
||||
SELECT salary FROM sensitive_data;
|
||||
ERROR 42000: SELECT command denied to user 'col_user1'@'localhost' for column 'salary' in table 'sensitive_data'
|
||||
disconnect con10;
|
||||
connection default;
|
||||
REVOKE DENY SELECT (SaLaRy) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
REVOKE SELECT ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
#
|
||||
# Cleanup
|
||||
#
|
||||
DROP USER col_user1@localhost;
|
||||
DROP USER col_user2@localhost;
|
||||
DROP DATABASE deny_col_db;
|
||||
#
|
||||
# End of column-level DENY tests
|
||||
#
|
||||
180
mysql-test/main/deny_column.test
Normal file
180
mysql-test/main/deny_column.test
Normal file
@@ -0,0 +1,180 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # Column-level DENY privilege test
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE deny_col_db;
|
||||
CREATE TABLE deny_col_db.sensitive_data (
|
||||
id INT,
|
||||
public_info VARCHAR(50),
|
||||
salary DECIMAL(10,2),
|
||||
ssn VARCHAR(11),
|
||||
address VARCHAR(100)
|
||||
);
|
||||
|
||||
INSERT INTO deny_col_db.sensitive_data VALUES
|
||||
(1, 'John Doe', 75000.00, '123-45-6789', '123 Main St'),
|
||||
(2, 'Jane Smith', 85000.00, '987-65-4321', '456 Oak Ave');
|
||||
|
||||
CREATE USER col_user1@localhost;
|
||||
CREATE USER col_user2@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Basic column-level DENY
|
||||
--echo #
|
||||
|
||||
GRANT SELECT ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY SELECT (salary, ssn) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
|
||||
connect (con1, localhost, col_user1,,deny_col_db);
|
||||
SELECT id, public_info FROM sensitive_data;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT salary FROM sensitive_data;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT ssn FROM sensitive_data;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT * FROM sensitive_data;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT id, salary FROM sensitive_data;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
REVOKE SELECT ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
REVOKE DENY SELECT (salary, ssn) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Column DENY takes precedence over explicit column GRANT
|
||||
--echo #
|
||||
|
||||
GRANT SELECT (salary,id,public_info) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY SELECT (salary) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
connect (con3, localhost, col_user1,,deny_col_db);
|
||||
SELECT id, public_info FROM sensitive_data;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT salary FROM sensitive_data;
|
||||
disconnect con3;
|
||||
connection default;
|
||||
REVOKE SELECT (salary,id,public_info) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
REVOKE DENY SELECT (salary) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # REVOKE DENY on a column
|
||||
--echo #
|
||||
GRANT SELECT (salary) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY SELECT (salary,ssn) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
REVOKE DENY SELECT (salary) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
|
||||
connect (con4, localhost, col_user1,,deny_col_db);
|
||||
SELECT salary FROM sensitive_data;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT ssn FROM sensitive_data;
|
||||
disconnect con4;
|
||||
connection default;
|
||||
REVOKE DENY SELECT (ssn) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Multiple column DENYs
|
||||
--echo #
|
||||
GRANT SELECT ON deny_col_db.sensitive_data TO col_user2@localhost;
|
||||
DENY SELECT (salary, ssn, address) ON deny_col_db.sensitive_data TO col_user2@localhost;
|
||||
|
||||
connect (con5, localhost, col_user2,,deny_col_db);
|
||||
SELECT id, public_info FROM sensitive_data;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT salary FROM sensitive_data;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT address FROM sensitive_data;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT * FROM sensitive_data;
|
||||
disconnect con5;
|
||||
connection default;
|
||||
REVOKE DENY SELECT (salary, ssn, address) ON deny_col_db.sensitive_data FROM col_user2@localhost;
|
||||
REVOKE SELECT ON deny_col_db.sensitive_data FROM col_user2@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Column DENY with INSERT/UPDATE operations
|
||||
--echo #
|
||||
|
||||
CREATE TABLE deny_col_db.audit_log (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
action VARCHAR(50),
|
||||
modified_by VARCHAR(50),
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
GRANT SELECT, INSERT ON deny_col_db.audit_log TO col_user1@localhost;
|
||||
DENY INSERT (modified_by) ON deny_col_db.audit_log TO col_user1@localhost;
|
||||
|
||||
connect (con8, localhost, col_user1,,deny_col_db);
|
||||
INSERT INTO audit_log (action) VALUES ('test_action');
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
INSERT INTO audit_log (action, modified_by) VALUES ('test', 'hacker');
|
||||
--replace_column 4 TIMESTAMP
|
||||
SELECT * FROM audit_log;
|
||||
disconnect con8;
|
||||
connection default;
|
||||
|
||||
--echo #
|
||||
--echo # Column DENY with UPDATE
|
||||
--echo #
|
||||
|
||||
GRANT UPDATE ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY UPDATE (salary) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
GRANT SELECT(id,public_info) on deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
|
||||
connect (con9, localhost, col_user1,,deny_col_db);
|
||||
UPDATE sensitive_data SET public_info = 'Updated' WHERE id = 1;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
UPDATE sensitive_data SET salary = 100000 WHERE id = 1;
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
UPDATE sensitive_data SET public_info = 'X', salary = 90000 WHERE id = 2;
|
||||
disconnect con9;
|
||||
connection default;
|
||||
REVOKE SELECT (id,public_info) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Table-level DENY SELECT: UPDATE without WHERE must succeed (no read needed)
|
||||
--echo #
|
||||
|
||||
DENY SELECT ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
|
||||
connect (con9b, localhost, col_user1,,deny_col_db);
|
||||
--echo # UPDATE with WHERE reads id -> SELECT needed -> DENY fires
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
UPDATE sensitive_data SET public_info = 'ps_test' WHERE id = 1;
|
||||
--echo # UPDATE without WHERE: no SELECT needed, must succeed
|
||||
UPDATE sensitive_data SET public_info = 'ps_test';
|
||||
disconnect con9b;
|
||||
connection default;
|
||||
|
||||
REVOKE DENY SELECT ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
REVOKE UPDATE ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Column DENY is case-insensitive
|
||||
--echo #
|
||||
|
||||
GRANT SELECT ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
DENY SELECT (SaLaRy) ON deny_col_db.sensitive_data TO col_user1@localhost;
|
||||
|
||||
connect (con10, localhost, col_user1,,deny_col_db);
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
SELECT salary FROM sensitive_data;
|
||||
disconnect con10;
|
||||
connection default;
|
||||
|
||||
REVOKE DENY SELECT (SaLaRy) ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
REVOKE SELECT ON deny_col_db.sensitive_data FROM col_user1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Cleanup
|
||||
--echo #
|
||||
|
||||
DROP USER col_user1@localhost;
|
||||
DROP USER col_user2@localhost;
|
||||
DROP DATABASE deny_col_db;
|
||||
|
||||
--echo #
|
||||
--echo # End of column-level DENY tests
|
||||
--echo #
|
||||
17
mysql-test/main/deny_event.result
Normal file
17
mysql-test/main/deny_event.result
Normal file
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# DENY EVENT privilege tests
|
||||
#
|
||||
CREATE DATABASE ev_db;
|
||||
CREATE USER ev_user@localhost;
|
||||
GRANT ALL PRIVILEGES ON ev_db.* TO ev_user@localhost;
|
||||
#
|
||||
# DENY EVENT: blocks CREATE EVENT in database ev_db
|
||||
#
|
||||
DENY EVENT ON ev_db.* TO ev_user@localhost;
|
||||
connect con1, localhost, ev_user,,ev_db;
|
||||
CREATE EVENT e1 ON SCHEDULE EVERY 1 HOUR DO SELECT 1;
|
||||
ERROR 42000: Access denied for user 'ev_user'@'localhost' to database 'ev_db'
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP DATABASE ev_db;
|
||||
DROP USER ev_user@localhost;
|
||||
23
mysql-test/main/deny_event.test
Normal file
23
mysql-test/main/deny_event.test
Normal file
@@ -0,0 +1,23 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # DENY EVENT privilege tests
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE ev_db;
|
||||
CREATE USER ev_user@localhost;
|
||||
GRANT ALL PRIVILEGES ON ev_db.* TO ev_user@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # DENY EVENT: blocks CREATE EVENT in database ev_db
|
||||
--echo #
|
||||
DENY EVENT ON ev_db.* TO ev_user@localhost;
|
||||
|
||||
connect (con1, localhost, ev_user,,ev_db);
|
||||
--error ER_DBACCESS_DENIED_ERROR
|
||||
CREATE EVENT e1 ON SCHEDULE EVERY 1 HOUR DO SELECT 1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
DROP DATABASE ev_db;
|
||||
DROP USER ev_user@localhost;
|
||||
151
mysql-test/main/deny_global.result
Normal file
151
mysql-test/main/deny_global.result
Normal file
@@ -0,0 +1,151 @@
|
||||
#
|
||||
# Test for Global DENY
|
||||
#
|
||||
USE test;
|
||||
CREATE TABLE t1 (id INT, data VARCHAR(50));
|
||||
CREATE TABLE t2 (id INT, info VARCHAR(50));
|
||||
INSERT INTO t1 VALUES (1, 'data1'), (2, 'data2');
|
||||
INSERT INTO t2 VALUES (1, 'info1'), (2, 'info2');
|
||||
#
|
||||
# Global DENY SELECT - Direct access
|
||||
#
|
||||
CREATE USER user1;
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1;
|
||||
DENY SELECT ON *.* TO user1;
|
||||
connect con1, localhost, user1,,test;
|
||||
# Should FAIL - global DENY SELECT
|
||||
SELECT * FROM t1;
|
||||
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table `test`.`t1`
|
||||
# Should FAIL - in any database
|
||||
SELECT * FROM mysql.user;
|
||||
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table `mysql`.`user`
|
||||
# Should SUCCEED - INSERT not denied
|
||||
INSERT INTO t1 VALUES (3, 'data3');
|
||||
INSERT INTO t1 VALUES (1, 'data1'), (2, 'data2');
|
||||
# Should SUCCEED, no db objects used
|
||||
SELECT 1;
|
||||
1
|
||||
1
|
||||
# Should SUCCEED, I_S tables are not GRANT/DENYable
|
||||
SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE 0;
|
||||
VARIABLE_NAME
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER user1;
|
||||
#
|
||||
# Global DENY with VIEW - DEFINER is denied
|
||||
#
|
||||
CREATE USER denied_definer;
|
||||
CREATE USER normal_user;
|
||||
GRANT ALL PRIVILEGES ON test.* TO denied_definer;
|
||||
DENY SELECT ON *.* TO denied_definer;
|
||||
GRANT SELECT ON test.* TO normal_user;
|
||||
connect con1, localhost, denied_definer,,test;
|
||||
# Can create view (doesn't require SELECT at CREATE time)
|
||||
CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT * FROM t2;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
GRANT SELECT ON test.v2 TO normal_user;
|
||||
connect con1, localhost, normal_user,,test;
|
||||
# Should FAIL - view uses denied_definer's context (which is denied)
|
||||
SELECT * FROM v2;
|
||||
ERROR HY000: View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
# Should SUCCEED - direct table access works for normal_user
|
||||
SELECT * FROM t2;
|
||||
id info
|
||||
1 info1
|
||||
2 info2
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP VIEW v2;
|
||||
DROP USER denied_definer;
|
||||
DROP USER normal_user;
|
||||
#
|
||||
# SHOW COLUMNS with global DENY (any_combination_will_do)
|
||||
#
|
||||
CREATE USER show_user;
|
||||
GRANT ALL PRIVILEGES ON test.* TO show_user;
|
||||
DENY ALL PRIVILEGES ON *.* TO show_user;
|
||||
REVOKE DENY EXECUTE ON *.* FROM show_user;
|
||||
connect con1, localhost, show_user,,test;
|
||||
# Should FAIL - SHOW COLUMNS requires column privileges
|
||||
SHOW COLUMNS FROM t1;
|
||||
ERROR 42000: SELECT command denied to user 'show_user'@'localhost' for table `test`.`t1`
|
||||
# Should FAIL - DESCRIBE is same as SHOW COLUMNS
|
||||
DESCRIBE t1;
|
||||
ERROR 42000: SELECT command denied to user 'show_user'@'localhost' for table `test`.`t1`
|
||||
# Should FAIL - SHOW INDEX
|
||||
SHOW INDEX FROM t1;
|
||||
ERROR 42000: SELECT command denied to user 'show_user'@'localhost' for table `test`.`t1`
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER show_user;
|
||||
#
|
||||
# DENY precedence - DENY overrides GRANT
|
||||
#
|
||||
CREATE USER prec_user;
|
||||
# First GRANT, then DENY
|
||||
GRANT SELECT,INSERT ON *.* TO prec_user;
|
||||
DENY SELECT ON *.* TO prec_user;
|
||||
connect con1, localhost, prec_user,,test;
|
||||
SELECT * FROM t1;
|
||||
ERROR 42000: SELECT command denied to user 'prec_user'@'localhost' for table `test`.`t1`
|
||||
connection default;
|
||||
disconnect con1;
|
||||
# Reverse order: DENY first, then GRANT
|
||||
REVOKE SELECT ON *.* FROM prec_user;
|
||||
DENY SELECT ON *.* TO prec_user;
|
||||
GRANT SELECT ON *.* TO prec_user;
|
||||
connect con1, localhost, prec_user,,test;
|
||||
# Should STILL FAIL - DENY takes precedence
|
||||
SELECT * FROM t1;
|
||||
ERROR 42000: SELECT command denied to user 'prec_user'@'localhost' for table `test`.`t1`
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER prec_user;
|
||||
#
|
||||
# Mixed operations - some denied, some allowed
|
||||
#
|
||||
CREATE USER mixed_user;
|
||||
GRANT ALL PRIVILEGES ON test.* TO mixed_user;
|
||||
DENY SELECT, DELETE ON *.* TO mixed_user;
|
||||
connect con1, localhost, mixed_user,,test;
|
||||
SELECT * FROM t1;
|
||||
ERROR 42000: SELECT command denied to user 'mixed_user'@'localhost' for table `test`.`t1`
|
||||
DELETE FROM t1 WHERE id=1;
|
||||
ERROR 42000: DELETE command denied to user 'mixed_user'@'localhost' for table `test`.`t1`
|
||||
# Should SUCCEED
|
||||
INSERT INTO t1 VALUES (4, 'data4');
|
||||
# Denied because of WHERE clause in UPDATE
|
||||
UPDATE t1 SET data='modified' WHERE id=4;
|
||||
ERROR 42000: SELECT command denied to user 'mixed_user'@'localhost' for column 'id' in table 't1'
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER mixed_user;
|
||||
#
|
||||
# DENY with subquery
|
||||
#
|
||||
CREATE USER sub_user;
|
||||
GRANT ALL PRIVILEGES ON test.* TO sub_user;
|
||||
DENY SELECT ON *.* TO sub_user;
|
||||
connect con1, localhost, sub_user,,test;
|
||||
SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);
|
||||
ERROR 42000: SELECT command denied to user 'sub_user'@'localhost' for table `test`.`t1`
|
||||
SELECT * FROM (SELECT * FROM t1) AS dt;
|
||||
ERROR 42000: SELECT command denied to user 'sub_user'@'localhost' for table `test`.`t1`
|
||||
disconnect con1;
|
||||
connection default;
|
||||
#
|
||||
# Check that FLUSH PRIVILEGES retains DENYs
|
||||
#
|
||||
FLUSH PRIVILEGES;
|
||||
connect con1, localhost, sub_user,,test;
|
||||
SELECT * FROM (SELECT * FROM t1) AS dt;
|
||||
ERROR 42000: SELECT command denied to user 'sub_user'@'localhost' for table `test`.`t1`
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP USER sub_user;
|
||||
#
|
||||
# Cleanup
|
||||
#
|
||||
DROP TABLE t1, t2;
|
||||
207
mysql-test/main/deny_global.test
Normal file
207
mysql-test/main/deny_global.test
Normal file
@@ -0,0 +1,207 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/no_protocol.inc
|
||||
|
||||
--echo #
|
||||
--echo # Test for Global DENY
|
||||
--echo #
|
||||
|
||||
USE test;
|
||||
CREATE TABLE t1 (id INT, data VARCHAR(50));
|
||||
CREATE TABLE t2 (id INT, info VARCHAR(50));
|
||||
INSERT INTO t1 VALUES (1, 'data1'), (2, 'data2');
|
||||
INSERT INTO t2 VALUES (1, 'info1'), (2, 'info2');
|
||||
|
||||
--echo #
|
||||
--echo # Global DENY SELECT - Direct access
|
||||
--echo #
|
||||
|
||||
CREATE USER user1;
|
||||
GRANT ALL PRIVILEGES ON *.* TO user1;
|
||||
DENY SELECT ON *.* TO user1;
|
||||
|
||||
connect (con1, localhost, user1,,test);
|
||||
|
||||
--echo # Should FAIL - global DENY SELECT
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM t1;
|
||||
|
||||
--echo # Should FAIL - in any database
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM mysql.user;
|
||||
|
||||
--echo # Should SUCCEED - INSERT not denied
|
||||
INSERT INTO t1 VALUES (3, 'data3');
|
||||
INSERT INTO t1 VALUES (1, 'data1'), (2, 'data2');
|
||||
|
||||
--echo # Should SUCCEED, no db objects used
|
||||
SELECT 1;
|
||||
|
||||
--echo # Should SUCCEED, I_S tables are not GRANT/DENYable
|
||||
SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE 0;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER user1;
|
||||
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Global DENY with VIEW - DEFINER is denied
|
||||
--echo #
|
||||
|
||||
CREATE USER denied_definer;
|
||||
CREATE USER normal_user;
|
||||
|
||||
GRANT ALL PRIVILEGES ON test.* TO denied_definer;
|
||||
DENY SELECT ON *.* TO denied_definer;
|
||||
GRANT SELECT ON test.* TO normal_user;
|
||||
|
||||
connect (con1, localhost, denied_definer,,test);
|
||||
--echo # Can create view (doesn't require SELECT at CREATE time)
|
||||
CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT * FROM t2;
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
GRANT SELECT ON test.v2 TO normal_user;
|
||||
|
||||
connect (con1, localhost, normal_user,,test);
|
||||
|
||||
--echo # Should FAIL - view uses denied_definer's context (which is denied)
|
||||
--error ER_VIEW_INVALID
|
||||
SELECT * FROM v2;
|
||||
|
||||
--echo # Should SUCCEED - direct table access works for normal_user
|
||||
SELECT * FROM t2;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP VIEW v2;
|
||||
DROP USER denied_definer;
|
||||
DROP USER normal_user;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # SHOW COLUMNS with global DENY (any_combination_will_do)
|
||||
--echo #
|
||||
|
||||
CREATE USER show_user;
|
||||
GRANT ALL PRIVILEGES ON test.* TO show_user;
|
||||
DENY ALL PRIVILEGES ON *.* TO show_user;
|
||||
# For connect to db
|
||||
REVOKE DENY EXECUTE ON *.* FROM show_user;
|
||||
|
||||
connect (con1, localhost, show_user,,test);
|
||||
|
||||
--echo # Should FAIL - SHOW COLUMNS requires column privileges
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW COLUMNS FROM t1;
|
||||
|
||||
--echo # Should FAIL - DESCRIBE is same as SHOW COLUMNS
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
DESCRIBE t1;
|
||||
|
||||
--echo # Should FAIL - SHOW INDEX
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW INDEX FROM t1;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER show_user;
|
||||
|
||||
--echo #
|
||||
--echo # DENY precedence - DENY overrides GRANT
|
||||
--echo #
|
||||
|
||||
CREATE USER prec_user;
|
||||
|
||||
--echo # First GRANT, then DENY
|
||||
GRANT SELECT,INSERT ON *.* TO prec_user;
|
||||
DENY SELECT ON *.* TO prec_user;
|
||||
|
||||
connect (con1, localhost, prec_user,,test);
|
||||
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM t1;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
--echo # Reverse order: DENY first, then GRANT
|
||||
REVOKE SELECT ON *.* FROM prec_user;
|
||||
DENY SELECT ON *.* TO prec_user;
|
||||
GRANT SELECT ON *.* TO prec_user;
|
||||
|
||||
connect (con1, localhost, prec_user,,test);
|
||||
|
||||
--echo # Should STILL FAIL - DENY takes precedence
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM t1;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER prec_user;
|
||||
|
||||
--echo #
|
||||
--echo # Mixed operations - some denied, some allowed
|
||||
--echo #
|
||||
|
||||
CREATE USER mixed_user;
|
||||
GRANT ALL PRIVILEGES ON test.* TO mixed_user;
|
||||
DENY SELECT, DELETE ON *.* TO mixed_user;
|
||||
|
||||
connect (con1, localhost, mixed_user,,test);
|
||||
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM t1;
|
||||
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
DELETE FROM t1 WHERE id=1;
|
||||
|
||||
--echo # Should SUCCEED
|
||||
INSERT INTO t1 VALUES (4, 'data4');
|
||||
|
||||
|
||||
--echo # Denied because of WHERE clause in UPDATE
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
UPDATE t1 SET data='modified' WHERE id=4;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER mixed_user;
|
||||
|
||||
--echo #
|
||||
--echo # DENY with subquery
|
||||
--echo #
|
||||
|
||||
CREATE USER sub_user;
|
||||
GRANT ALL PRIVILEGES ON test.* TO sub_user;
|
||||
DENY SELECT ON *.* TO sub_user;
|
||||
|
||||
connect (con1, localhost, sub_user,,test);
|
||||
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);
|
||||
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM (SELECT * FROM t1) AS dt;
|
||||
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
--echo #
|
||||
--echo # Check that FLUSH PRIVILEGES retains DENYs
|
||||
--echo #
|
||||
FLUSH PRIVILEGES;
|
||||
connect (con1, localhost, sub_user,,test);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM (SELECT * FROM t1) AS dt;
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
DROP USER sub_user;
|
||||
|
||||
--echo #
|
||||
--echo # Cleanup
|
||||
--echo #
|
||||
|
||||
DROP TABLE t1, t2;
|
||||
136
mysql-test/main/deny_hierarchy.result
Normal file
136
mysql-test/main/deny_hierarchy.result
Normal file
@@ -0,0 +1,136 @@
|
||||
#
|
||||
# Test DENY privilege hierarchy: GLOBAL > DB > TABLE > COLUMN
|
||||
#
|
||||
CREATE DATABASE testdb;
|
||||
USE testdb;
|
||||
CREATE TABLE t1 (id INT, name VARCHAR(50), salary INT);
|
||||
CREATE USER 'u1'@'localhost';
|
||||
#
|
||||
# DB-level DENY blocks TABLE-level GRANT
|
||||
#
|
||||
DENY SELECT ON testdb.* TO 'u1'@'localhost';
|
||||
GRANT SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
connect con1, localhost, u1,,;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
connection default;
|
||||
disconnect con1;
|
||||
REVOKE DENY SELECT ON testdb.* FROM 'u1'@'localhost';
|
||||
REVOKE SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
#
|
||||
# GLOBAL DENY blocks DB and TABLE grants
|
||||
#
|
||||
DENY UPDATE ON *.* TO 'u1'@'localhost';
|
||||
GRANT UPDATE ON testdb.* TO 'u1'@'localhost';
|
||||
GRANT UPDATE ON testdb.t1 TO 'u1'@'localhost';
|
||||
connect con1, localhost, u1,,;
|
||||
UPDATE testdb.t1 SET name='test' WHERE id=1;
|
||||
ERROR 42000: UPDATE command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
connection default;
|
||||
disconnect con1;
|
||||
REVOKE DENY UPDATE ON *.* FROM 'u1'@'localhost';
|
||||
REVOKE UPDATE ON testdb.* FROM 'u1'@'localhost';
|
||||
REVOKE UPDATE ON testdb.t1 FROM 'u1'@'localhost';
|
||||
#
|
||||
# TABLE DENY blocks COLUMN grants
|
||||
#
|
||||
DENY SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
GRANT SELECT (name) ON testdb.t1 TO 'u1'@'localhost';
|
||||
connect con1, localhost, u1,,;
|
||||
SELECT name FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
connection default;
|
||||
disconnect con1;
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
REVOKE SELECT (name) ON testdb.t1 FROM 'u1'@'localhost';
|
||||
#
|
||||
# DENY on same table masks only denied privilege
|
||||
#
|
||||
GRANT SELECT, INSERT ON testdb.t1 TO 'u1'@'localhost';
|
||||
DENY SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
connect con1, localhost, u1,,;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
INSERT INTO testdb.t1 VALUES (1, 'test', 1000);
|
||||
connection default;
|
||||
disconnect con1;
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
REVOKE SELECT, INSERT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
DELETE FROM testdb.t1;
|
||||
#
|
||||
# Multiple DENY levels cumulative
|
||||
#
|
||||
DENY SELECT ON *.* TO 'u1'@'localhost';
|
||||
DENY INSERT ON testdb.* TO 'u1'@'localhost';
|
||||
DENY UPDATE ON testdb.t1 TO 'u1'@'localhost';
|
||||
GRANT ALL PRIVILEGES ON testdb.t1 TO 'u1'@'localhost';
|
||||
connect con1, localhost, u1,,;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
INSERT INTO testdb.t1 VALUES (1, 'test', 1000);
|
||||
ERROR 42000: INSERT command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
UPDATE testdb.t1 SET name='test';
|
||||
ERROR 42000: UPDATE command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
DELETE FROM testdb.t1 WHERE id=999;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for column 'id' in table 't1'
|
||||
DELETE FROM testdb.t1;
|
||||
connection default;
|
||||
disconnect con1;
|
||||
REVOKE DENY SELECT ON *.* FROM 'u1'@'localhost';
|
||||
REVOKE DENY INSERT ON testdb.* FROM 'u1'@'localhost';
|
||||
REVOKE DENY UPDATE ON testdb.t1 FROM 'u1'@'localhost';
|
||||
REVOKE ALL PRIVILEGES ON testdb.t1 FROM 'u1'@'localhost';
|
||||
#
|
||||
# REVOKE DENY restores access
|
||||
#
|
||||
DENY SELECT ON testdb.* TO 'u1'@'localhost';
|
||||
GRANT SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
connect con1, localhost, u1,,;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
connection default;
|
||||
disconnect con1;
|
||||
REVOKE DENY SELECT ON testdb.* FROM 'u1'@'localhost';
|
||||
connect con1, localhost, u1,,;
|
||||
SELECT * FROM testdb.t1;
|
||||
id name salary
|
||||
connection default;
|
||||
disconnect con1;
|
||||
REVOKE SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
#
|
||||
# Cache invalidation on DENY change
|
||||
#
|
||||
GRANT SELECT ON testdb.* TO 'u1'@'localhost';
|
||||
connect con1, localhost, u1,,;
|
||||
SELECT * FROM testdb.t1;
|
||||
id name salary
|
||||
connection default;
|
||||
DENY SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
connection con1;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
connection default;
|
||||
disconnect con1;
|
||||
REVOKE SELECT ON testdb.* FROM 'u1'@'localhost';
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
#
|
||||
# DENY on one table, GRANT on another
|
||||
#
|
||||
CREATE TABLE t2 (dept_id INT);
|
||||
DENY SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
GRANT SELECT ON testdb.t2 TO 'u1'@'localhost';
|
||||
connect con1, localhost, u1,,;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
SELECT * FROM testdb.t2;
|
||||
dept_id
|
||||
connection default;
|
||||
disconnect con1;
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
REVOKE SELECT ON testdb.t2 FROM 'u1'@'localhost';
|
||||
#
|
||||
# Cleanup
|
||||
#
|
||||
DROP USER 'u1'@'localhost';
|
||||
DROP TABLE t1, t2;
|
||||
DROP DATABASE testdb;
|
||||
167
mysql-test/main/deny_hierarchy.test
Normal file
167
mysql-test/main/deny_hierarchy.test
Normal file
@@ -0,0 +1,167 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/no_protocol.inc
|
||||
|
||||
--echo #
|
||||
--echo # Test DENY privilege hierarchy: GLOBAL > DB > TABLE > COLUMN
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE testdb;
|
||||
USE testdb;
|
||||
CREATE TABLE t1 (id INT, name VARCHAR(50), salary INT);
|
||||
|
||||
CREATE USER 'u1'@'localhost';
|
||||
|
||||
--echo #
|
||||
--echo # DB-level DENY blocks TABLE-level GRANT
|
||||
--echo #
|
||||
DENY SELECT ON testdb.* TO 'u1'@'localhost';
|
||||
GRANT SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1;
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
REVOKE DENY SELECT ON testdb.* FROM 'u1'@'localhost';
|
||||
REVOKE SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
|
||||
--echo #
|
||||
--echo # GLOBAL DENY blocks DB and TABLE grants
|
||||
--echo #
|
||||
DENY UPDATE ON *.* TO 'u1'@'localhost';
|
||||
GRANT UPDATE ON testdb.* TO 'u1'@'localhost';
|
||||
GRANT UPDATE ON testdb.t1 TO 'u1'@'localhost';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
UPDATE testdb.t1 SET name='test' WHERE id=1;
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
REVOKE DENY UPDATE ON *.* FROM 'u1'@'localhost';
|
||||
REVOKE UPDATE ON testdb.* FROM 'u1'@'localhost';
|
||||
REVOKE UPDATE ON testdb.t1 FROM 'u1'@'localhost';
|
||||
|
||||
--echo #
|
||||
--echo # TABLE DENY blocks COLUMN grants
|
||||
--echo #
|
||||
DENY SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
GRANT SELECT (name) ON testdb.t1 TO 'u1'@'localhost';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT name FROM testdb.t1;
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
REVOKE SELECT (name) ON testdb.t1 FROM 'u1'@'localhost';
|
||||
|
||||
--echo #
|
||||
--echo # DENY on same table masks only denied privilege
|
||||
--echo #
|
||||
GRANT SELECT, INSERT ON testdb.t1 TO 'u1'@'localhost';
|
||||
DENY SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1;
|
||||
INSERT INTO testdb.t1 VALUES (1, 'test', 1000);
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
REVOKE SELECT, INSERT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
DELETE FROM testdb.t1;
|
||||
|
||||
--echo #
|
||||
--echo # Multiple DENY levels cumulative
|
||||
--echo #
|
||||
DENY SELECT ON *.* TO 'u1'@'localhost';
|
||||
DENY INSERT ON testdb.* TO 'u1'@'localhost';
|
||||
DENY UPDATE ON testdb.t1 TO 'u1'@'localhost';
|
||||
GRANT ALL PRIVILEGES ON testdb.t1 TO 'u1'@'localhost';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
INSERT INTO testdb.t1 VALUES (1, 'test', 1000);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
UPDATE testdb.t1 SET name='test';
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
DELETE FROM testdb.t1 WHERE id=999; # select required
|
||||
DELETE FROM testdb.t1; # Should work
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
REVOKE DENY SELECT ON *.* FROM 'u1'@'localhost';
|
||||
REVOKE DENY INSERT ON testdb.* FROM 'u1'@'localhost';
|
||||
REVOKE DENY UPDATE ON testdb.t1 FROM 'u1'@'localhost';
|
||||
REVOKE ALL PRIVILEGES ON testdb.t1 FROM 'u1'@'localhost';
|
||||
|
||||
--echo #
|
||||
--echo # REVOKE DENY restores access
|
||||
--echo #
|
||||
DENY SELECT ON testdb.* TO 'u1'@'localhost';
|
||||
GRANT SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1;
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
REVOKE DENY SELECT ON testdb.* FROM 'u1'@'localhost';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
SELECT * FROM testdb.t1; # Now works
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
REVOKE SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
|
||||
--echo #
|
||||
--echo # Cache invalidation on DENY change
|
||||
--echo #
|
||||
GRANT SELECT ON testdb.* TO 'u1'@'localhost';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
SELECT * FROM testdb.t1; # Works
|
||||
connection default;
|
||||
|
||||
DENY SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
|
||||
connection con1;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1; # Now fails (cache cleared)
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
REVOKE SELECT ON testdb.* FROM 'u1'@'localhost';
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
|
||||
--echo #
|
||||
--echo # DENY on one table, GRANT on another
|
||||
--echo #
|
||||
CREATE TABLE t2 (dept_id INT);
|
||||
DENY SELECT ON testdb.t1 TO 'u1'@'localhost';
|
||||
GRANT SELECT ON testdb.t2 TO 'u1'@'localhost';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1;
|
||||
SELECT * FROM testdb.t2; # Works
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM 'u1'@'localhost';
|
||||
REVOKE SELECT ON testdb.t2 FROM 'u1'@'localhost';
|
||||
|
||||
--echo #
|
||||
--echo # Cleanup
|
||||
--echo #
|
||||
DROP USER 'u1'@'localhost';
|
||||
DROP TABLE t1, t2;
|
||||
DROP DATABASE testdb;
|
||||
15
mysql-test/main/deny_json_invalid.result
Normal file
15
mysql-test/main/deny_json_invalid.result
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Malformed DENY JSON entry should warn
|
||||
#
|
||||
CREATE USER u@localhost;
|
||||
CALL mtr.add_suppression('.*Malformed DENY entry in mysql\.global_priv at array position 0 for ''u''@''localhost'' ignored');
|
||||
UPDATE mysql.global_priv
|
||||
SET Priv= json_set(Priv, '$.denies',
|
||||
json_array(json_object('type','column',
|
||||
'db','test',
|
||||
'table','t',
|
||||
'bits',1)))
|
||||
WHERE User='u' AND Host='localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
DROP USER u@localhost;
|
||||
FOUND 1 /Malformed DENY entry in mysql.global_priv at array position 0 for 'u'@'localhost' ignored/ in mysqld.1.err
|
||||
25
mysql-test/main/deny_json_invalid.test
Normal file
25
mysql-test/main/deny_json_invalid.test
Normal file
@@ -0,0 +1,25 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # Malformed DENY JSON entry should warn
|
||||
--echo #
|
||||
|
||||
CREATE USER u@localhost;
|
||||
|
||||
--eval CALL mtr.add_suppression('.*Malformed DENY entry in mysql\\.global_priv at array position 0 for ''u''@''localhost'' ignored')
|
||||
|
||||
UPDATE mysql.global_priv
|
||||
SET Priv= json_set(Priv, '$.denies',
|
||||
json_array(json_object('type','column',
|
||||
'db','test',
|
||||
'table','t',
|
||||
'bits',1)))
|
||||
WHERE User='u' AND Host='localhost';
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
DROP USER u@localhost;
|
||||
|
||||
--let SEARCH_FILE= `SELECT @@log_error`
|
||||
--let SEARCH_PATTERN= Malformed DENY entry in mysql.global_priv at array position 0 for 'u'@'localhost' ignored
|
||||
--source include/search_pattern_in_file.inc
|
||||
23
mysql-test/main/deny_lowercase0.result
Normal file
23
mysql-test/main/deny_lowercase0.result
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# DENY case-sensitive matching (lower_case_table_names=0)
|
||||
#
|
||||
CREATE USER u_deny@localhost;
|
||||
CREATE DATABASE DbCase;
|
||||
CREATE DATABASE dbcase;
|
||||
CREATE TABLE DbCase.T (a int);
|
||||
CREATE TABLE DbCase.t (a int);
|
||||
CREATE TABLE dbcase.t (a int);
|
||||
DENY SELECT ON DbCase.T TO u_deny@localhost;
|
||||
DENY SELECT ON DbCase.t TO u_deny@localhost;
|
||||
DENY INSERT, UPDATE ON dbcase.t TO u_deny@localhost;
|
||||
# SHOW GRANTS should list distinct denies for case-different objects
|
||||
SHOW GRANTS FOR u_deny@localhost;
|
||||
Grants for u_deny@localhost
|
||||
DENY INSERT, UPDATE ON `dbcase`.`t` TO `u_deny`@`localhost`
|
||||
DENY SELECT ON `DbCase`.`T` TO `u_deny`@`localhost`
|
||||
DENY SELECT ON `DbCase`.`t` TO `u_deny`@`localhost`
|
||||
GRANT USAGE ON *.* TO `u_deny`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
DROP USER u_deny@localhost;
|
||||
DROP DATABASE DbCase;
|
||||
DROP DATABASE dbcase;
|
||||
26
mysql-test/main/deny_lowercase0.test
Normal file
26
mysql-test/main/deny_lowercase0.test
Normal file
@@ -0,0 +1,26 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/have_lowercase0.inc
|
||||
|
||||
--echo #
|
||||
--echo # DENY case-sensitive matching (lower_case_table_names=0)
|
||||
--echo #
|
||||
|
||||
CREATE USER u_deny@localhost;
|
||||
CREATE DATABASE DbCase;
|
||||
CREATE DATABASE dbcase;
|
||||
CREATE TABLE DbCase.T (a int);
|
||||
CREATE TABLE DbCase.t (a int);
|
||||
CREATE TABLE dbcase.t (a int);
|
||||
|
||||
DENY SELECT ON DbCase.T TO u_deny@localhost;
|
||||
DENY SELECT ON DbCase.t TO u_deny@localhost;
|
||||
DENY INSERT, UPDATE ON dbcase.t TO u_deny@localhost;
|
||||
|
||||
--echo # SHOW GRANTS should list distinct denies for case-different objects
|
||||
--sorted_result
|
||||
SHOW GRANTS FOR u_deny@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
|
||||
DROP USER u_deny@localhost;
|
||||
DROP DATABASE DbCase;
|
||||
DROP DATABASE dbcase;
|
||||
1
mysql-test/main/deny_lowercase1.opt
Normal file
1
mysql-test/main/deny_lowercase1.opt
Normal file
@@ -0,0 +1 @@
|
||||
--lower-case-table-names=1
|
||||
54
mysql-test/main/deny_lowercase1.result
Normal file
54
mysql-test/main/deny_lowercase1.result
Normal file
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# DENY case-insensitive matching (lower_case_table_names=1)
|
||||
#
|
||||
CREATE USER u_deny@localhost;
|
||||
CREATE DATABASE DbCase;
|
||||
CREATE TABLE DbCase.T (a int);
|
||||
DENY SELECT ON DbCase.T TO u_deny@localhost;
|
||||
DENY INSERT, UPDATE ON dbcase.t TO u_deny@localhost;
|
||||
GRANT SELECT, INSERT, UPDATE ON DbCase.T TO u_deny@localhost;
|
||||
# DENY entry in mysql.global_priv should be lowercased
|
||||
SELECT JSON_UNQUOTE(JSON_EXTRACT(Priv, '$.denies[0].db')) AS db,
|
||||
JSON_UNQUOTE(JSON_EXTRACT(Priv, '$.denies[0].table')) AS tbl,
|
||||
JSON_EXTRACT(Priv, '$.denies[0].bits') AS bits
|
||||
FROM mysql.global_priv
|
||||
WHERE User='u_deny' AND Host='localhost';
|
||||
db tbl bits
|
||||
dbcase t 7
|
||||
# Force mixed-case JSON to simulate migration from case-sensitive to lowercase=1
|
||||
UPDATE mysql.global_priv
|
||||
SET Priv=JSON_SET(Priv, '$.denies[0].db','DbCase', '$.denies[0].table','T')
|
||||
WHERE User='u_deny' AND Host='localhost';
|
||||
SELECT JSON_UNQUOTE(JSON_EXTRACT(Priv, '$.denies[0].db')) AS db,
|
||||
JSON_UNQUOTE(JSON_EXTRACT(Priv, '$.denies[0].table')) AS tbl,
|
||||
JSON_EXTRACT(Priv, '$.denies[0].bits') AS bits
|
||||
FROM mysql.global_priv
|
||||
WHERE User='u_deny' AND Host='localhost';
|
||||
db tbl bits
|
||||
DbCase T 7
|
||||
FLUSH PRIVILEGES;
|
||||
connect con1,localhost,u_deny,,DbCase;
|
||||
SELECT * FROM T;
|
||||
ERROR 42000: SELECT command denied to user 'u_deny'@'localhost' for table `dbcase`.`t`
|
||||
INSERT INTO T VALUES (1);
|
||||
ERROR 42000: INSERT command denied to user 'u_deny'@'localhost' for table `dbcase`.`t`
|
||||
UPDATE T SET a=2 WHERE a=1;
|
||||
ERROR 42000: UPDATE command denied to user 'u_deny'@'localhost' for table `dbcase`.`t`
|
||||
disconnect con1;
|
||||
connection default;
|
||||
# SHOW GRANTS should collapse to a single deny entry
|
||||
SHOW GRANTS FOR u_deny@localhost;
|
||||
Grants for u_deny@localhost
|
||||
DENY SELECT, INSERT, UPDATE ON `dbcase`.`t` TO `u_deny`@`localhost`
|
||||
GRANT SELECT, INSERT, UPDATE ON `dbcase`.`t` TO `u_deny`@`localhost`
|
||||
GRANT USAGE ON *.* TO `u_deny`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
REVOKE DENY SELECT, INSERT, UPDATE ON DBCASE.T FROM u_deny@localhost;
|
||||
# SHOW GRANTS should no longer list a DENY entry
|
||||
SHOW GRANTS FOR u_deny@localhost;
|
||||
Grants for u_deny@localhost
|
||||
GRANT SELECT, INSERT, UPDATE ON `dbcase`.`t` TO `u_deny`@`localhost`
|
||||
GRANT USAGE ON *.* TO `u_deny`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
DROP USER u_deny@localhost;
|
||||
DROP DATABASE DbCase;
|
||||
59
mysql-test/main/deny_lowercase1.test
Normal file
59
mysql-test/main/deny_lowercase1.test
Normal file
@@ -0,0 +1,59 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/have_lowercase1.inc
|
||||
|
||||
--echo #
|
||||
--echo # DENY case-insensitive matching (lower_case_table_names=1)
|
||||
--echo #
|
||||
|
||||
CREATE USER u_deny@localhost;
|
||||
CREATE DATABASE DbCase;
|
||||
CREATE TABLE DbCase.T (a int);
|
||||
|
||||
DENY SELECT ON DbCase.T TO u_deny@localhost;
|
||||
DENY INSERT, UPDATE ON dbcase.t TO u_deny@localhost;
|
||||
GRANT SELECT, INSERT, UPDATE ON DbCase.T TO u_deny@localhost;
|
||||
|
||||
--echo # DENY entry in mysql.global_priv should be lowercased
|
||||
SELECT JSON_UNQUOTE(JSON_EXTRACT(Priv, '$.denies[0].db')) AS db,
|
||||
JSON_UNQUOTE(JSON_EXTRACT(Priv, '$.denies[0].table')) AS tbl,
|
||||
JSON_EXTRACT(Priv, '$.denies[0].bits') AS bits
|
||||
FROM mysql.global_priv
|
||||
WHERE User='u_deny' AND Host='localhost';
|
||||
|
||||
--echo # Force mixed-case JSON to simulate migration from case-sensitive to lowercase=1
|
||||
UPDATE mysql.global_priv
|
||||
SET Priv=JSON_SET(Priv, '$.denies[0].db','DbCase', '$.denies[0].table','T')
|
||||
WHERE User='u_deny' AND Host='localhost';
|
||||
|
||||
SELECT JSON_UNQUOTE(JSON_EXTRACT(Priv, '$.denies[0].db')) AS db,
|
||||
JSON_UNQUOTE(JSON_EXTRACT(Priv, '$.denies[0].table')) AS tbl,
|
||||
JSON_EXTRACT(Priv, '$.denies[0].bits') AS bits
|
||||
FROM mysql.global_priv
|
||||
WHERE User='u_deny' AND Host='localhost';
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
--connect (con1,localhost,u_deny,,DbCase)
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM T;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
INSERT INTO T VALUES (1);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
UPDATE T SET a=2 WHERE a=1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
--echo # SHOW GRANTS should collapse to a single deny entry
|
||||
--sorted_result
|
||||
SHOW GRANTS FOR u_deny@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
|
||||
REVOKE DENY SELECT, INSERT, UPDATE ON DBCASE.T FROM u_deny@localhost;
|
||||
|
||||
--echo # SHOW GRANTS should no longer list a DENY entry
|
||||
--sorted_result
|
||||
SHOW GRANTS FOR u_deny@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
|
||||
DROP USER u_deny@localhost;
|
||||
DROP DATABASE DbCase;
|
||||
78
mysql-test/main/deny_metadata.result
Normal file
78
mysql-test/main/deny_metadata.result
Normal file
@@ -0,0 +1,78 @@
|
||||
#
|
||||
# DENY metadata behavior
|
||||
#
|
||||
#
|
||||
# Direct DENY should affect SHOW COLUMNS
|
||||
#
|
||||
CREATE TABLE t1 (id INT);
|
||||
CREATE TABLE t2 (c1 INT);
|
||||
CREATE USER u@localhost;
|
||||
CREATE ROLE r;
|
||||
GRANT SELECT ON test.t1 TO r;
|
||||
GRANT SELECT ON test.t2 TO r;
|
||||
DENY SELECT ON test.t1 TO r;
|
||||
GRANT r TO u@localhost;
|
||||
connect con1, localhost, u,,;
|
||||
SET ROLE r;
|
||||
SHOW COLUMNS FROM test.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u'@'localhost' for table `test`.`t1`
|
||||
SHOW COLUMNS FROM test.t2;
|
||||
Field Type Null Key Default Extra
|
||||
c1 int(11) YES NULL
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP ROLE r;
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Column-level GRANT+DENY should block SHOW COLUMNS
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
CREATE USER u@localhost;
|
||||
GRANT SELECT (a) ON test.t1 TO u@localhost;
|
||||
DENY SELECT (a) ON test.t1 TO u@localhost;
|
||||
connect con2, localhost, u,,;
|
||||
SHOW COLUMNS FROM test.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u'@'localhost' for table `test`.`t1`
|
||||
disconnect con2;
|
||||
connection default;
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Mixed column GRANT+DENY should allow SHOW COLUMNS
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
CREATE USER u@localhost;
|
||||
GRANT SELECT (a) ON test.t1 TO u@localhost;
|
||||
DENY SELECT (b) ON test.t1 TO u@localhost;
|
||||
connect con2, localhost, u,,;
|
||||
SHOW COLUMNS FROM test.t1;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) YES NULL
|
||||
disconnect con2;
|
||||
connection default;
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Higher level DENY should block SHOW COLUMNS
|
||||
#
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE USER u@localhost;
|
||||
CREATE ROLE r;
|
||||
GRANT SELECT ON test.t1 TO r;
|
||||
GRANT r TO u@localhost;
|
||||
#
|
||||
# Database-level DENY
|
||||
#
|
||||
DENY SELECT ON test.* TO r;
|
||||
connect con3, localhost, u,,;
|
||||
SET ROLE r;
|
||||
SHOW COLUMNS FROM test.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u'@'localhost' for table `test`.`t1`
|
||||
disconnect con3;
|
||||
connection default;
|
||||
REVOKE DENY SELECT ON test.* FROM r;
|
||||
DROP ROLE r;
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
89
mysql-test/main/deny_metadata.test
Normal file
89
mysql-test/main/deny_metadata.test
Normal file
@@ -0,0 +1,89 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # DENY metadata behavior
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Direct DENY should affect SHOW COLUMNS
|
||||
--echo #
|
||||
CREATE TABLE t1 (id INT);
|
||||
CREATE TABLE t2 (c1 INT);
|
||||
CREATE USER u@localhost;
|
||||
CREATE ROLE r;
|
||||
GRANT SELECT ON test.t1 TO r;
|
||||
GRANT SELECT ON test.t2 TO r;
|
||||
DENY SELECT ON test.t1 TO r;
|
||||
GRANT r TO u@localhost;
|
||||
|
||||
connect (con1, localhost, u,,);
|
||||
SET ROLE r;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW COLUMNS FROM test.t1;
|
||||
SHOW COLUMNS FROM test.t2;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
DROP ROLE r;
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Column-level GRANT+DENY should block SHOW COLUMNS
|
||||
--echo #
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
CREATE USER u@localhost;
|
||||
GRANT SELECT (a) ON test.t1 TO u@localhost;
|
||||
DENY SELECT (a) ON test.t1 TO u@localhost;
|
||||
|
||||
connect (con2, localhost, u,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW COLUMNS FROM test.t1;
|
||||
disconnect con2;
|
||||
connection default;
|
||||
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Mixed column GRANT+DENY should allow SHOW COLUMNS
|
||||
--echo #
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
CREATE USER u@localhost;
|
||||
GRANT SELECT (a) ON test.t1 TO u@localhost;
|
||||
DENY SELECT (b) ON test.t1 TO u@localhost;
|
||||
|
||||
connect (con2, localhost, u,,);
|
||||
SHOW COLUMNS FROM test.t1;
|
||||
disconnect con2;
|
||||
connection default;
|
||||
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Higher level DENY should block SHOW COLUMNS
|
||||
--echo #
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE USER u@localhost;
|
||||
CREATE ROLE r;
|
||||
GRANT SELECT ON test.t1 TO r;
|
||||
GRANT r TO u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Database-level DENY
|
||||
--echo #
|
||||
DENY SELECT ON test.* TO r;
|
||||
connect (con3, localhost, u,,);
|
||||
SET ROLE r;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW COLUMNS FROM test.t1;
|
||||
disconnect con3;
|
||||
connection default;
|
||||
|
||||
REVOKE DENY SELECT ON test.* FROM r;
|
||||
|
||||
DROP ROLE r;
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
34
mysql-test/main/deny_restart.result
Normal file
34
mysql-test/main/deny_restart.result
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# Check that privilege hashes are populated with DENY entries on startup
|
||||
#
|
||||
USE test;
|
||||
CREATE TABLE t1 (id INT);
|
||||
CREATE USER u@localhost;
|
||||
GRANT SELECT ON test.t1 TO u@localhost;
|
||||
DENY SELECT ON test.t1 TO u@localhost;
|
||||
# Before restart: DENY is enforced
|
||||
connect con1, localhost, u,,;
|
||||
SELECT * FROM test.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u'@'localhost' for table `test`.`t1`
|
||||
disconnect con1;
|
||||
connection default;
|
||||
# Before restart: DENY is visible and persisted
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
GRANT SELECT ON `test`.`t1` TO `u`@`localhost`
|
||||
DENY SELECT ON `test`.`t1` TO `u`@`localhost`
|
||||
# Restart and verify again
|
||||
# restart
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
GRANT SELECT ON `test`.`t1` TO `u`@`localhost`
|
||||
DENY SELECT ON `test`.`t1` TO `u`@`localhost`
|
||||
connect con1, localhost, u,,;
|
||||
SELECT * FROM test.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u'@'localhost' for table `test`.`t1`
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE test.t1;
|
||||
36
mysql-test/main/deny_restart.test
Normal file
36
mysql-test/main/deny_restart.test
Normal file
@@ -0,0 +1,36 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # Check that privilege hashes are populated with DENY entries on startup
|
||||
--echo #
|
||||
|
||||
USE test;
|
||||
CREATE TABLE t1 (id INT);
|
||||
|
||||
CREATE USER u@localhost;
|
||||
GRANT SELECT ON test.t1 TO u@localhost;
|
||||
DENY SELECT ON test.t1 TO u@localhost;
|
||||
|
||||
--echo # Before restart: DENY is enforced
|
||||
connect (con1, localhost, u,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM test.t1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
--echo # Before restart: DENY is visible and persisted
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
|
||||
--echo # Restart and verify again
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
|
||||
connect (con1, localhost, u,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM test.t1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE test.t1;
|
||||
162
mysql-test/main/deny_revoke.result
Normal file
162
mysql-test/main/deny_revoke.result
Normal file
@@ -0,0 +1,162 @@
|
||||
#
|
||||
# REVOKE DENY tests
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
CREATE PROCEDURE p1() BEGIN SET @x=1; END;
|
||||
$$
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN 1;
|
||||
$$
|
||||
CREATE PACKAGE pkg1
|
||||
PROCEDURE p1();
|
||||
FUNCTION f1() RETURNS INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1
|
||||
PROCEDURE p1() BEGIN SET @pkg=2; END;
|
||||
FUNCTION f1() RETURNS INT BEGIN RETURN 2; END;
|
||||
END;
|
||||
$$
|
||||
CREATE USER u@localhost;
|
||||
GRANT ALL PRIVILEGES ON *.* to u@localhost;
|
||||
PREPARE show_denies FROM "SELECT IF(JSON_EXTRACT(Priv, '$.denies') IS NULL OR JSON_LENGTH(JSON_EXTRACT(Priv, '$.denies')) = 0, 'no entries', JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies'))) AS denies FROM mysql.global_priv WHERE User='u' AND Host='localhost'";
|
||||
#
|
||||
# Global
|
||||
#
|
||||
DENY SELECT ON *.* TO u@localhost;
|
||||
REVOKE DENY SELECT ON *.* FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
denies
|
||||
no entries
|
||||
#
|
||||
# Database
|
||||
#
|
||||
DENY INSERT ON test.* TO u@localhost;
|
||||
REVOKE DENY INSERT ON test.* FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
denies
|
||||
no entries
|
||||
# Second revoke should error
|
||||
REVOKE DENY INSERT ON test.* FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost'
|
||||
# Revoke with existing GRANT without existing DENY
|
||||
GRANT INSERT ON test.* TO u@localhost;
|
||||
REVOKE DENY INSERT ON test.* FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost'
|
||||
REVOKE INSERT ON test.* FROM u@localhost;
|
||||
#
|
||||
# Table
|
||||
#
|
||||
DENY UPDATE ON test.t1 TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT ALL PRIVILEGES ON *.* TO `u`@`localhost`
|
||||
DENY UPDATE ON `test`.`t1` TO `u`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
REVOKE DENY UPDATE ON test.t1 FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
denies
|
||||
no entries
|
||||
# Second revoke should error
|
||||
REVOKE DENY UPDATE ON test.t1 FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost' on table 't1'
|
||||
# Revoke with existing GRANT without existing DENY
|
||||
GRANT UPDATE ON test.t1 TO u@localhost;
|
||||
REVOKE DENY UPDATE ON test.t1 FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost' on table 't1'
|
||||
REVOKE UPDATE ON test.t1 FROM u@localhost;
|
||||
#
|
||||
# Column
|
||||
#
|
||||
DENY SELECT (a) ON test.t1 TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT ALL PRIVILEGES ON *.* TO `u`@`localhost`
|
||||
DENY SELECT (`a`) ON `test`.`t1` TO `u`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
REVOKE DENY SELECT (a) ON test.t1 FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
denies
|
||||
no entries
|
||||
# Second revoke should error
|
||||
REVOKE DENY SELECT (a) ON test.t1 FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost' on table 't1'
|
||||
# Revoke with existing GRANT without existing DENY
|
||||
GRANT SELECT(a) ON test.t1 TO u@localhost;
|
||||
REVOKE DENY SELECT (a) ON test.t1 FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost' on table 't1'
|
||||
REVOKE SELECT(a) ON test.t1 FROM u@localhost;
|
||||
#
|
||||
# Procedure
|
||||
#
|
||||
DENY EXECUTE ON PROCEDURE test.p1 TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT ALL PRIVILEGES ON *.* TO `u`@`localhost`
|
||||
DENY EXECUTE ON PROCEDURE `test`.`p1` TO `u`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
REVOKE DENY EXECUTE ON PROCEDURE test.p1 FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
denies
|
||||
no entries
|
||||
# Second revoke should error
|
||||
REVOKE DENY EXECUTE ON PROCEDURE test.p1 FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost' on routine 'p1'
|
||||
# Revoke with existing GRANT without existing DENY
|
||||
GRANT EXECUTE ON PROCEDURE test.p1 TO u@localhost;
|
||||
REVOKE DENY EXECUTE ON PROCEDURE test.p1 FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost' on routine 'p1'
|
||||
REVOKE EXECUTE ON PROCEDURE test.p1 FROM u@localhost;
|
||||
#
|
||||
# Function
|
||||
#
|
||||
DENY EXECUTE ON FUNCTION test.f1 TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT ALL PRIVILEGES ON *.* TO `u`@`localhost`
|
||||
DENY EXECUTE ON FUNCTION `test`.`f1` TO `u`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
REVOKE DENY EXECUTE ON FUNCTION test.f1 FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
denies
|
||||
no entries
|
||||
# Second revoke should error
|
||||
REVOKE DENY EXECUTE ON FUNCTION test.f1 FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost' on routine 'f1'
|
||||
# Revoke with existing GRANT without existing DENY
|
||||
GRANT EXECUTE ON FUNCTION test.f1 TO u@localhost;
|
||||
REVOKE DENY EXECUTE ON FUNCTION test.f1 FROM u@localhost;
|
||||
ERROR 42000: There is no such grant defined for user 'u' on host 'localhost' on routine 'f1'
|
||||
REVOKE EXECUTE ON FUNCTION test.f1 FROM u@localhost;
|
||||
#
|
||||
# REVOKE ALL, GRANT OPTION clears grants and denies
|
||||
#
|
||||
DENY SELECT ON test.* TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT ALL PRIVILEGES ON *.* TO `u`@`localhost`
|
||||
DENY SELECT ON `test`.* TO `u`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
EXECUTE show_denies;
|
||||
denies
|
||||
[
|
||||
{
|
||||
"type": "db",
|
||||
"db": "test",
|
||||
"bits": 1
|
||||
}
|
||||
]
|
||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
EXECUTE show_denies;
|
||||
denies
|
||||
no entries
|
||||
DEALLOCATE PREPARE show_denies;
|
||||
DROP USER u@localhost;
|
||||
DROP PACKAGE BODY pkg1;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP FUNCTION f1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
140
mysql-test/main/deny_revoke.test
Normal file
140
mysql-test/main/deny_revoke.test
Normal file
@@ -0,0 +1,140 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # REVOKE DENY tests
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1() BEGIN SET @x=1; END;
|
||||
$$
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN 1;
|
||||
$$
|
||||
CREATE PACKAGE pkg1
|
||||
PROCEDURE p1();
|
||||
FUNCTION f1() RETURNS INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1
|
||||
PROCEDURE p1() BEGIN SET @pkg=2; END;
|
||||
FUNCTION f1() RETURNS INT BEGIN RETURN 2; END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE USER u@localhost;
|
||||
GRANT ALL PRIVILEGES ON *.* to u@localhost;
|
||||
|
||||
PREPARE show_denies FROM "SELECT IF(JSON_EXTRACT(Priv, '$.denies') IS NULL OR JSON_LENGTH(JSON_EXTRACT(Priv, '$.denies')) = 0, 'no entries', JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies'))) AS denies FROM mysql.global_priv WHERE User='u' AND Host='localhost'";
|
||||
|
||||
--echo #
|
||||
--echo # Global
|
||||
--echo #
|
||||
DENY SELECT ON *.* TO u@localhost;
|
||||
REVOKE DENY SELECT ON *.* FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
|
||||
--echo #
|
||||
--echo # Database
|
||||
--echo #
|
||||
DENY INSERT ON test.* TO u@localhost;
|
||||
REVOKE DENY INSERT ON test.* FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
--echo # Second revoke should error
|
||||
--error ER_NONEXISTING_GRANT
|
||||
REVOKE DENY INSERT ON test.* FROM u@localhost;
|
||||
|
||||
--echo # Revoke with existing GRANT without existing DENY
|
||||
GRANT INSERT ON test.* TO u@localhost;
|
||||
--error ER_NONEXISTING_GRANT
|
||||
REVOKE DENY INSERT ON test.* FROM u@localhost;
|
||||
REVOKE INSERT ON test.* FROM u@localhost;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Table
|
||||
--echo #
|
||||
DENY UPDATE ON test.t1 TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
REVOKE DENY UPDATE ON test.t1 FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
--echo # Second revoke should error
|
||||
--error ER_NONEXISTING_TABLE_GRANT
|
||||
REVOKE DENY UPDATE ON test.t1 FROM u@localhost;
|
||||
--echo # Revoke with existing GRANT without existing DENY
|
||||
GRANT UPDATE ON test.t1 TO u@localhost;
|
||||
--error ER_NONEXISTING_TABLE_GRANT
|
||||
REVOKE DENY UPDATE ON test.t1 FROM u@localhost;
|
||||
REVOKE UPDATE ON test.t1 FROM u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Column
|
||||
--echo #
|
||||
DENY SELECT (a) ON test.t1 TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
REVOKE DENY SELECT (a) ON test.t1 FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
--echo # Second revoke should error
|
||||
--error ER_NONEXISTING_TABLE_GRANT
|
||||
REVOKE DENY SELECT (a) ON test.t1 FROM u@localhost;
|
||||
--echo # Revoke with existing GRANT without existing DENY
|
||||
GRANT SELECT(a) ON test.t1 TO u@localhost;
|
||||
--error ER_NONEXISTING_TABLE_GRANT
|
||||
REVOKE DENY SELECT (a) ON test.t1 FROM u@localhost;
|
||||
REVOKE SELECT(a) ON test.t1 FROM u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Procedure
|
||||
--echo #
|
||||
DENY EXECUTE ON PROCEDURE test.p1 TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
REVOKE DENY EXECUTE ON PROCEDURE test.p1 FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
--echo # Second revoke should error
|
||||
--error ER_NONEXISTING_PROC_GRANT
|
||||
REVOKE DENY EXECUTE ON PROCEDURE test.p1 FROM u@localhost;
|
||||
--echo # Revoke with existing GRANT without existing DENY
|
||||
GRANT EXECUTE ON PROCEDURE test.p1 TO u@localhost;
|
||||
--error ER_NONEXISTING_PROC_GRANT
|
||||
REVOKE DENY EXECUTE ON PROCEDURE test.p1 FROM u@localhost;
|
||||
REVOKE EXECUTE ON PROCEDURE test.p1 FROM u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Function
|
||||
--echo #
|
||||
DENY EXECUTE ON FUNCTION test.f1 TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
REVOKE DENY EXECUTE ON FUNCTION test.f1 FROM u@localhost;
|
||||
EXECUTE show_denies;
|
||||
--echo # Second revoke should error
|
||||
--error ER_NONEXISTING_PROC_GRANT
|
||||
REVOKE DENY EXECUTE ON FUNCTION test.f1 FROM u@localhost;
|
||||
--echo # Revoke with existing GRANT without existing DENY
|
||||
GRANT EXECUTE ON FUNCTION test.f1 TO u@localhost;
|
||||
--error ER_NONEXISTING_PROC_GRANT
|
||||
REVOKE DENY EXECUTE ON FUNCTION test.f1 FROM u@localhost;
|
||||
REVOKE EXECUTE ON FUNCTION test.f1 FROM u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # REVOKE ALL, GRANT OPTION clears grants and denies
|
||||
--echo #
|
||||
DENY SELECT ON test.* TO u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
EXECUTE show_denies;
|
||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM u@localhost;
|
||||
SHOW GRANTS FOR u@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
EXECUTE show_denies;
|
||||
|
||||
DEALLOCATE PREPARE show_denies;
|
||||
DROP USER u@localhost;
|
||||
DROP PACKAGE BODY pkg1;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP FUNCTION f1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
99
mysql-test/main/deny_role_inherit.result
Normal file
99
mysql-test/main/deny_role_inherit.result
Normal file
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# Test DENY + role inheritance: denies on a role propagate
|
||||
# through the role graph to users and other roles.
|
||||
#
|
||||
CREATE DATABASE testdb;
|
||||
USE testdb;
|
||||
CREATE TABLE t1 (id INT, val VARCHAR(50));
|
||||
INSERT INTO t1 VALUES (1,'a'), (2,'b');
|
||||
CREATE USER u1@localhost;
|
||||
CREATE ROLE r_grant, r_deny, r_combined;
|
||||
#
|
||||
# Setup: r_grant has SELECT, r_deny has DENY SELECT,
|
||||
# r_combined inherits both. User u1 gets r_combined.
|
||||
#
|
||||
GRANT SELECT ON testdb.t1 TO r_grant;
|
||||
DENY SELECT ON testdb.t1 TO r_deny;
|
||||
GRANT r_grant TO r_combined;
|
||||
GRANT r_deny TO r_combined;
|
||||
GRANT r_combined TO u1@localhost;
|
||||
#
|
||||
# DENY from r_deny should win over GRANT from r_grant
|
||||
#
|
||||
connect con1, localhost, u1,,;
|
||||
SET ROLE r_combined;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `testdb`.`t1`
|
||||
disconnect con1;
|
||||
connection default;
|
||||
#
|
||||
# After revoking the deny, SELECT should work again
|
||||
#
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM r_deny;
|
||||
connect con1, localhost, u1,,;
|
||||
SET ROLE r_combined;
|
||||
SELECT * FROM testdb.t1;
|
||||
id val
|
||||
1 a
|
||||
2 b
|
||||
disconnect con1;
|
||||
connection default;
|
||||
# Cleanup scenario 1
|
||||
REVOKE SELECT ON testdb.t1 FROM r_grant;
|
||||
DROP ROLE r_grant, r_deny, r_combined;
|
||||
DROP USER u1@localhost;
|
||||
#
|
||||
# DB-level DENY on a role blocks table-level GRANT
|
||||
# inherited through a different role in the DAG.
|
||||
#
|
||||
CREATE USER u2@localhost;
|
||||
CREATE ROLE r_db_deny, r_tbl_grant, r_top;
|
||||
DENY SELECT ON testdb.* TO r_db_deny;
|
||||
GRANT SELECT ON testdb.t1 TO r_tbl_grant;
|
||||
GRANT r_db_deny TO r_top;
|
||||
GRANT r_tbl_grant TO r_top;
|
||||
GRANT r_top TO u2@localhost;
|
||||
connect con2, localhost, u2,,;
|
||||
SET ROLE r_top;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u2'@'localhost' for table `testdb`.`t1`
|
||||
disconnect con2;
|
||||
connection default;
|
||||
# Cleanup scenario 2
|
||||
DROP ROLE r_db_deny, r_tbl_grant, r_top;
|
||||
DROP USER u2@localhost;
|
||||
#
|
||||
# DENY on a leaf role, grant on a higher role:
|
||||
# deny should still win (deny always wins over grant).
|
||||
#
|
||||
CREATE USER u3@localhost;
|
||||
CREATE ROLE r_child, r_parent;
|
||||
GRANT r_child TO r_parent;
|
||||
GRANT r_parent TO u3@localhost;
|
||||
GRANT SELECT ON testdb.t1 TO r_parent;
|
||||
DENY SELECT ON testdb.t1 TO r_child;
|
||||
connect con3, localhost, u3,,;
|
||||
SET ROLE r_parent;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u3'@'localhost' for table `testdb`.`t1`
|
||||
disconnect con3;
|
||||
connection default;
|
||||
#
|
||||
# Reverse: deny on parent, grant on child — deny still wins.
|
||||
#
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM r_child;
|
||||
REVOKE SELECT ON testdb.t1 FROM r_parent;
|
||||
GRANT SELECT ON testdb.t1 TO r_child;
|
||||
DENY SELECT ON testdb.t1 TO r_parent;
|
||||
connect con3, localhost, u3,,;
|
||||
SET ROLE r_parent;
|
||||
SELECT * FROM testdb.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u3'@'localhost' for table `testdb`.`t1`
|
||||
disconnect con3;
|
||||
connection default;
|
||||
# Cleanup scenario 3
|
||||
DROP ROLE r_child, r_parent;
|
||||
DROP USER u3@localhost;
|
||||
# Final cleanup
|
||||
DROP TABLE testdb.t1;
|
||||
DROP DATABASE testdb;
|
||||
115
mysql-test/main/deny_role_inherit.test
Normal file
115
mysql-test/main/deny_role_inherit.test
Normal file
@@ -0,0 +1,115 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/no_protocol.inc
|
||||
|
||||
--echo #
|
||||
--echo # Test DENY + role inheritance: denies on a role propagate
|
||||
--echo # through the role graph to users and other roles.
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE testdb;
|
||||
USE testdb;
|
||||
CREATE TABLE t1 (id INT, val VARCHAR(50));
|
||||
INSERT INTO t1 VALUES (1,'a'), (2,'b');
|
||||
|
||||
CREATE USER u1@localhost;
|
||||
CREATE ROLE r_grant, r_deny, r_combined;
|
||||
|
||||
--echo #
|
||||
--echo # Setup: r_grant has SELECT, r_deny has DENY SELECT,
|
||||
--echo # r_combined inherits both. User u1 gets r_combined.
|
||||
--echo #
|
||||
GRANT SELECT ON testdb.t1 TO r_grant;
|
||||
DENY SELECT ON testdb.t1 TO r_deny;
|
||||
GRANT r_grant TO r_combined;
|
||||
GRANT r_deny TO r_combined;
|
||||
GRANT r_combined TO u1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # DENY from r_deny should win over GRANT from r_grant
|
||||
--echo #
|
||||
connect (con1, localhost, u1,,);
|
||||
SET ROLE r_combined;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
--echo #
|
||||
--echo # After revoking the deny, SELECT should work again
|
||||
--echo #
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM r_deny;
|
||||
connect (con1, localhost, u1,,);
|
||||
SET ROLE r_combined;
|
||||
SELECT * FROM testdb.t1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
--echo # Cleanup scenario 1
|
||||
REVOKE SELECT ON testdb.t1 FROM r_grant;
|
||||
DROP ROLE r_grant, r_deny, r_combined;
|
||||
DROP USER u1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # DB-level DENY on a role blocks table-level GRANT
|
||||
--echo # inherited through a different role in the DAG.
|
||||
--echo #
|
||||
CREATE USER u2@localhost;
|
||||
CREATE ROLE r_db_deny, r_tbl_grant, r_top;
|
||||
DENY SELECT ON testdb.* TO r_db_deny;
|
||||
GRANT SELECT ON testdb.t1 TO r_tbl_grant;
|
||||
GRANT r_db_deny TO r_top;
|
||||
GRANT r_tbl_grant TO r_top;
|
||||
GRANT r_top TO u2@localhost;
|
||||
|
||||
connect (con2, localhost, u2,,);
|
||||
SET ROLE r_top;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1;
|
||||
disconnect con2;
|
||||
connection default;
|
||||
|
||||
--echo # Cleanup scenario 2
|
||||
DROP ROLE r_db_deny, r_tbl_grant, r_top;
|
||||
DROP USER u2@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # DENY on a leaf role, grant on a higher role:
|
||||
--echo # deny should still win (deny always wins over grant).
|
||||
--echo #
|
||||
CREATE USER u3@localhost;
|
||||
CREATE ROLE r_child, r_parent;
|
||||
GRANT r_child TO r_parent;
|
||||
GRANT r_parent TO u3@localhost;
|
||||
|
||||
GRANT SELECT ON testdb.t1 TO r_parent;
|
||||
DENY SELECT ON testdb.t1 TO r_child;
|
||||
|
||||
connect (con3, localhost, u3,,);
|
||||
SET ROLE r_parent;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1;
|
||||
disconnect con3;
|
||||
connection default;
|
||||
|
||||
--echo #
|
||||
--echo # Reverse: deny on parent, grant on child — deny still wins.
|
||||
--echo #
|
||||
REVOKE DENY SELECT ON testdb.t1 FROM r_child;
|
||||
REVOKE SELECT ON testdb.t1 FROM r_parent;
|
||||
GRANT SELECT ON testdb.t1 TO r_child;
|
||||
DENY SELECT ON testdb.t1 TO r_parent;
|
||||
|
||||
connect (con3, localhost, u3,,);
|
||||
SET ROLE r_parent;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM testdb.t1;
|
||||
disconnect con3;
|
||||
connection default;
|
||||
|
||||
--echo # Cleanup scenario 3
|
||||
DROP ROLE r_child, r_parent;
|
||||
DROP USER u3@localhost;
|
||||
|
||||
--echo # Final cleanup
|
||||
DROP TABLE testdb.t1;
|
||||
DROP DATABASE testdb;
|
||||
106
mysql-test/main/deny_role_public.result
Normal file
106
mysql-test/main/deny_role_public.result
Normal file
@@ -0,0 +1,106 @@
|
||||
#
|
||||
# DENY with roles of roles and PUBLIC
|
||||
#
|
||||
CREATE TABLE test.t1 (id INT);
|
||||
INSERT INTO test.t1 VALUES (1);
|
||||
#
|
||||
# DENY on base role should block through role inheritance
|
||||
#
|
||||
CREATE USER u1@localhost;
|
||||
CREATE ROLE r_base, r_mid, r_top;
|
||||
GRANT SELECT ON test.t1 TO r_base;
|
||||
DENY SELECT ON test.t1 TO r_base;
|
||||
GRANT r_base TO r_mid;
|
||||
GRANT r_mid TO r_top;
|
||||
GRANT r_top TO u1@localhost;
|
||||
#
|
||||
# SHOW GRANTS for roles and JSON storage
|
||||
#
|
||||
SHOW GRANTS FOR r_base;
|
||||
Grants for r_base
|
||||
GRANT USAGE ON *.* TO `r_base`
|
||||
GRANT SELECT ON `test`.`t1` TO `r_base`
|
||||
DENY SELECT ON `test`.`t1` TO `r_base`
|
||||
# END SHOW GRANTS
|
||||
SHOW GRANTS FOR r_mid;
|
||||
Grants for r_mid
|
||||
GRANT `r_base` TO `r_mid`
|
||||
GRANT USAGE ON *.* TO `r_mid`
|
||||
GRANT USAGE ON *.* TO `r_base`
|
||||
GRANT SELECT ON `test`.`t1` TO `r_base`
|
||||
DENY SELECT ON `test`.`t1` TO `r_base`
|
||||
# END SHOW GRANTS
|
||||
SHOW GRANTS FOR r_top;
|
||||
Grants for r_top
|
||||
GRANT `r_mid` TO `r_top`
|
||||
GRANT USAGE ON *.* TO `r_top`
|
||||
GRANT `r_base` TO `r_mid`
|
||||
GRANT USAGE ON *.* TO `r_mid`
|
||||
GRANT USAGE ON *.* TO `r_base`
|
||||
GRANT SELECT ON `test`.`t1` TO `r_base`
|
||||
DENY SELECT ON `test`.`t1` TO `r_base`
|
||||
# END SHOW GRANTS
|
||||
SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE User='r_base';
|
||||
User Host denies_pretty
|
||||
r_base [
|
||||
{
|
||||
"type": "table",
|
||||
"db": "test",
|
||||
"table": "t1",
|
||||
"bits": 1
|
||||
}
|
||||
]
|
||||
connect con1, localhost, u1,,;
|
||||
SET ROLE r_top;
|
||||
SELECT * FROM test.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `test`.`t1`
|
||||
disconnect con1;
|
||||
connection default;
|
||||
REVOKE DENY SELECT ON test.t1 FROM r_base;
|
||||
connect con1, localhost, u1,,;
|
||||
SET ROLE r_top;
|
||||
SELECT * FROM test.t1;
|
||||
id
|
||||
1
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP ROLE r_top;
|
||||
DROP ROLE r_mid;
|
||||
DROP ROLE r_base;
|
||||
DROP USER u1@localhost;
|
||||
#
|
||||
# PUBLIC DENY should affect users
|
||||
#
|
||||
CREATE USER u2@localhost;
|
||||
GRANT SELECT ON test.t1 TO u2@localhost;
|
||||
DENY SELECT ON test.t1 TO PUBLIC;
|
||||
SHOW GRANTS FOR PUBLIC;
|
||||
Grants for PUBLIC
|
||||
DENY SELECT ON `test`.`t1` TO PUBLIC
|
||||
# END SHOW GRANTS
|
||||
SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE User='PUBLIC';
|
||||
User Host denies_pretty
|
||||
PUBLIC [
|
||||
{
|
||||
"type": "table",
|
||||
"db": "test",
|
||||
"table": "t1",
|
||||
"bits": 1
|
||||
}
|
||||
]
|
||||
connect con2, localhost, u2,,;
|
||||
SELECT * FROM test.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u2'@'localhost' for table `test`.`t1`
|
||||
disconnect con2;
|
||||
connection default;
|
||||
REVOKE DENY SELECT ON test.t1 FROM PUBLIC;
|
||||
DROP USER u2@localhost;
|
||||
DROP TABLE test.t1;
|
||||
DELETE FROM mysql.global_priv WHERE User='PUBLIC';
|
||||
FLUSH PRIVILEGES;
|
||||
79
mysql-test/main/deny_role_public.test
Normal file
79
mysql-test/main/deny_role_public.test
Normal file
@@ -0,0 +1,79 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # DENY with roles of roles and PUBLIC
|
||||
--echo #
|
||||
|
||||
CREATE TABLE test.t1 (id INT);
|
||||
INSERT INTO test.t1 VALUES (1);
|
||||
|
||||
--echo #
|
||||
--echo # DENY on base role should block through role inheritance
|
||||
--echo #
|
||||
CREATE USER u1@localhost;
|
||||
CREATE ROLE r_base, r_mid, r_top;
|
||||
GRANT SELECT ON test.t1 TO r_base;
|
||||
DENY SELECT ON test.t1 TO r_base;
|
||||
GRANT r_base TO r_mid;
|
||||
GRANT r_mid TO r_top;
|
||||
GRANT r_top TO u1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # SHOW GRANTS for roles and JSON storage
|
||||
--echo #
|
||||
SHOW GRANTS FOR r_base;
|
||||
--echo # END SHOW GRANTS
|
||||
SHOW GRANTS FOR r_mid;
|
||||
--echo # END SHOW GRANTS
|
||||
SHOW GRANTS FOR r_top;
|
||||
--echo # END SHOW GRANTS
|
||||
SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE User='r_base';
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
SET ROLE r_top;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM test.t1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
REVOKE DENY SELECT ON test.t1 FROM r_base;
|
||||
connect (con1, localhost, u1,,);
|
||||
SET ROLE r_top;
|
||||
SELECT * FROM test.t1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
DROP ROLE r_top;
|
||||
DROP ROLE r_mid;
|
||||
DROP ROLE r_base;
|
||||
DROP USER u1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # PUBLIC DENY should affect users
|
||||
--echo #
|
||||
CREATE USER u2@localhost;
|
||||
GRANT SELECT ON test.t1 TO u2@localhost;
|
||||
DENY SELECT ON test.t1 TO PUBLIC;
|
||||
|
||||
SHOW GRANTS FOR PUBLIC;
|
||||
--echo # END SHOW GRANTS
|
||||
SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE User='PUBLIC';
|
||||
|
||||
connect (con2, localhost, u2,,);
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SELECT * FROM test.t1;
|
||||
disconnect con2;
|
||||
connection default;
|
||||
|
||||
REVOKE DENY SELECT ON test.t1 FROM PUBLIC;
|
||||
DROP USER u2@localhost;
|
||||
|
||||
DROP TABLE test.t1;
|
||||
DELETE FROM mysql.global_priv WHERE User='PUBLIC';
|
||||
FLUSH PRIVILEGES;
|
||||
168
mysql-test/main/deny_routine.result
Normal file
168
mysql-test/main/deny_routine.result
Normal file
@@ -0,0 +1,168 @@
|
||||
#
|
||||
# DENY routine privileges
|
||||
#
|
||||
CREATE PROCEDURE proc1() BEGIN SET @p=1; END;
|
||||
$$
|
||||
CREATE FUNCTION func1() RETURNS INT RETURN 1;
|
||||
$$
|
||||
CREATE PACKAGE pkg1
|
||||
PROCEDURE p1();
|
||||
FUNCTION f1() RETURNS INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1
|
||||
PROCEDURE p1() BEGIN SET @pkg=2; END;
|
||||
FUNCTION f1() RETURNS INT BEGIN RETURN 2; END;
|
||||
END;
|
||||
$$
|
||||
#
|
||||
# Routine-level DENY for different privileges
|
||||
#
|
||||
CREATE USER u@localhost;
|
||||
#
|
||||
# Illegal routine DENY statements
|
||||
#
|
||||
# Missing routine type (treated as table-level grant target)
|
||||
DENY EXECUTE ON test.proc1 TO u@localhost;
|
||||
ERROR 42000: Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used
|
||||
# SELECT is not a routine privilege (procedure target)
|
||||
DENY SELECT ON PROCEDURE test.proc1 TO u@localhost;
|
||||
ERROR 42000: Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used
|
||||
GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE test.proc1 TO u@localhost;
|
||||
GRANT EXECUTE, ALTER ROUTINE ON FUNCTION test.func1 TO u@localhost;
|
||||
DENY ALTER ROUTINE ON PROCEDURE test.proc1 TO u@localhost;
|
||||
DENY EXECUTE ON FUNCTION test.func1 TO u@localhost;
|
||||
connect con1, localhost, u,,test;
|
||||
CALL proc1();
|
||||
SELECT @p;
|
||||
@p
|
||||
1
|
||||
ALTER PROCEDURE proc1 COMMENT 'x';
|
||||
ERROR 42000: alter routine command denied to user 'u'@'localhost' for routine 'test.proc1'
|
||||
SELECT func1();
|
||||
ERROR 42000: execute command denied to user 'u'@'localhost' for routine 'test.func1'
|
||||
ALTER FUNCTION func1 COMMENT 'x';
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u@localhost;
|
||||
#
|
||||
# Routine-level DENY ALL
|
||||
#
|
||||
CREATE USER u_all@localhost;
|
||||
GRANT ALL ON PROCEDURE test.proc1 TO u_all@localhost;
|
||||
GRANT ALL ON FUNCTION test.func1 TO u_all@localhost;
|
||||
DENY ALL PRIVILEGES ON PROCEDURE test.proc1 TO u_all@localhost;
|
||||
DENY ALL PRIVILEGES ON FUNCTION test.func1 TO u_all@localhost;
|
||||
connect con1, localhost, u_all,,;
|
||||
CALL test.proc1();
|
||||
ERROR 42000: execute command denied to user 'u_all'@'localhost' for routine 'test.proc1'
|
||||
SELECT test.func1();
|
||||
ERROR 42000: execute command denied to user 'u_all'@'localhost' for routine 'test.func1'
|
||||
ALTER PROCEDURE test.proc1 COMMENT 'x';
|
||||
ERROR 42000: alter routine command denied to user 'u_all'@'localhost' for routine 'test.proc1'
|
||||
ALTER FUNCTION test.func1 COMMENT 'x';
|
||||
ERROR 42000: alter routine command denied to user 'u_all'@'localhost' for routine 'test.func1'
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u_all@localhost;
|
||||
#
|
||||
# DB-level DENY overrides routine grants
|
||||
#
|
||||
CREATE USER u@localhost;
|
||||
GRANT EXECUTE ON PROCEDURE test.proc1 TO u@localhost;
|
||||
GRANT EXECUTE ON PACKAGE BODY test.pkg1 TO u@localhost;
|
||||
DENY EXECUTE ON test.* TO u@localhost;
|
||||
connect con1, localhost, u,,test;
|
||||
CALL proc1();
|
||||
ERROR 42000: execute command denied to user 'u'@'localhost' for routine 'test.proc1'
|
||||
CALL pkg1.p1();
|
||||
ERROR 42000: execute command denied to user 'u'@'localhost' for routine 'test.pkg1'
|
||||
SELECT pkg1.f1();
|
||||
ERROR 42000: execute command denied to user 'u'@'localhost' for routine 'test.pkg1'
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u@localhost;
|
||||
#
|
||||
# Global DENY overrides routine grants
|
||||
#
|
||||
CREATE USER u@localhost;
|
||||
GRANT EXECUTE ON FUNCTION test.func1 TO u@localhost;
|
||||
DENY EXECUTE ON *.* TO u@localhost;
|
||||
connect con1, localhost, u,,test;
|
||||
SELECT func1();
|
||||
ERROR 42000: execute command denied to user 'u'@'localhost' for routine 'test.func1'
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u@localhost;
|
||||
#
|
||||
# Routine DENY is case-insensitive
|
||||
#
|
||||
CREATE USER u_case@localhost;
|
||||
GRANT EXECUTE ON PROCEDURE test.proc1 TO u_case@localhost;
|
||||
GRANT EXECUTE ON FUNCTION test.func1 TO u_case@localhost;
|
||||
DENY EXECUTE ON PROCEDURE test.ProC1 TO u_case@localhost;
|
||||
DENY EXECUTE ON FUNCTION test.FUNC1 TO u_case@localhost;
|
||||
connect con_case, localhost, u_case,,;
|
||||
CALL test.proc1();
|
||||
ERROR 42000: execute command denied to user 'u_case'@'localhost' for routine 'test.proc1'
|
||||
SELECT test.func1();
|
||||
ERROR 42000: execute command denied to user 'u_case'@'localhost' for routine 'test.func1'
|
||||
connection default;
|
||||
disconnect con_case;
|
||||
DROP USER u_case@localhost;
|
||||
#
|
||||
# Package / package body DENY
|
||||
#
|
||||
CREATE USER u@localhost;
|
||||
GRANT EXECUTE,GRANT OPTION ON PACKAGE BODY test.pkg1 TO u@localhost;
|
||||
DENY EXECUTE ON PACKAGE BODY test.pkg1 TO u@localhost;
|
||||
connect con1, localhost, u,,test;
|
||||
CALL pkg1.p1();
|
||||
ERROR 42000: execute command denied to user 'u'@'localhost' for routine 'test.pkg1'
|
||||
SELECT pkg1.f1();
|
||||
ERROR 42000: execute command denied to user 'u'@'localhost' for routine 'test.pkg1'
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u@localhost;
|
||||
#
|
||||
# DROP SP clears denies for user
|
||||
#
|
||||
CREATE USER u@localhost;
|
||||
CREATE PROCEDURE proc2() BEGIN SET @p=1; END;
|
||||
$$
|
||||
DENY EXECUTE ON PROCEDURE proc2 TO u@localhost;
|
||||
SHOW GRANTS for u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
DENY EXECUTE ON PROCEDURE `test`.`proc2` TO `u`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
# show that deny entry exists in json
|
||||
SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE User='u';
|
||||
User Host denies_pretty
|
||||
u localhost [
|
||||
{
|
||||
"type": "procedure",
|
||||
"db": "test",
|
||||
"procedure": "proc2",
|
||||
"bits": 262144
|
||||
}
|
||||
]
|
||||
DROP PROCEDURE proc2;
|
||||
SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE User='u';
|
||||
User Host denies_pretty
|
||||
u localhost []
|
||||
SHOW GRANTS for u@localhost;
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
DROP USER u@localhost;
|
||||
DROP PACKAGE BODY pkg1;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP PROCEDURE proc1;
|
||||
DROP FUNCTION func1;
|
||||
199
mysql-test/main/deny_routine.test
Normal file
199
mysql-test/main/deny_routine.test
Normal file
@@ -0,0 +1,199 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # DENY routine privileges
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE proc1() BEGIN SET @p=1; END;
|
||||
$$
|
||||
CREATE FUNCTION func1() RETURNS INT RETURN 1;
|
||||
$$
|
||||
CREATE PACKAGE pkg1
|
||||
PROCEDURE p1();
|
||||
FUNCTION f1() RETURNS INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1
|
||||
PROCEDURE p1() BEGIN SET @pkg=2; END;
|
||||
FUNCTION f1() RETURNS INT BEGIN RETURN 2; END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo #
|
||||
--echo # Routine-level DENY for different privileges
|
||||
--echo #
|
||||
|
||||
CREATE USER u@localhost;
|
||||
--echo #
|
||||
--echo # Illegal routine DENY statements
|
||||
--echo #
|
||||
--echo # Missing routine type (treated as table-level grant target)
|
||||
--error ER_ILLEGAL_GRANT_FOR_TABLE
|
||||
DENY EXECUTE ON test.proc1 TO u@localhost;
|
||||
--echo # SELECT is not a routine privilege (procedure target)
|
||||
--error ER_ILLEGAL_GRANT_FOR_TABLE
|
||||
DENY SELECT ON PROCEDURE test.proc1 TO u@localhost;
|
||||
|
||||
GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE test.proc1 TO u@localhost;
|
||||
GRANT EXECUTE, ALTER ROUTINE ON FUNCTION test.func1 TO u@localhost;
|
||||
DENY ALTER ROUTINE ON PROCEDURE test.proc1 TO u@localhost;
|
||||
DENY EXECUTE ON FUNCTION test.func1 TO u@localhost;
|
||||
|
||||
connect (con1, localhost, u,,test);
|
||||
|
||||
CALL proc1();
|
||||
SELECT @p;
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
ALTER PROCEDURE proc1 COMMENT 'x';
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
SELECT func1();
|
||||
|
||||
ALTER FUNCTION func1 COMMENT 'x';
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Routine-level DENY ALL
|
||||
--echo #
|
||||
CREATE USER u_all@localhost;
|
||||
GRANT ALL ON PROCEDURE test.proc1 TO u_all@localhost;
|
||||
GRANT ALL ON FUNCTION test.func1 TO u_all@localhost;
|
||||
DENY ALL PRIVILEGES ON PROCEDURE test.proc1 TO u_all@localhost;
|
||||
DENY ALL PRIVILEGES ON FUNCTION test.func1 TO u_all@localhost;
|
||||
|
||||
connect (con1, localhost, u_all,,);
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL test.proc1();
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
SELECT test.func1();
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
ALTER PROCEDURE test.proc1 COMMENT 'x';
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
ALTER FUNCTION test.func1 COMMENT 'x';
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u_all@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # DB-level DENY overrides routine grants
|
||||
--echo #
|
||||
|
||||
CREATE USER u@localhost;
|
||||
GRANT EXECUTE ON PROCEDURE test.proc1 TO u@localhost;
|
||||
GRANT EXECUTE ON PACKAGE BODY test.pkg1 TO u@localhost;
|
||||
DENY EXECUTE ON test.* TO u@localhost;
|
||||
|
||||
connect (con1, localhost, u,,test);
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL proc1();
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL pkg1.p1();
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
SELECT pkg1.f1();
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Global DENY overrides routine grants
|
||||
--echo #
|
||||
|
||||
CREATE USER u@localhost;
|
||||
GRANT EXECUTE ON FUNCTION test.func1 TO u@localhost;
|
||||
DENY EXECUTE ON *.* TO u@localhost;
|
||||
|
||||
connect (con1, localhost, u,,test);
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
SELECT func1();
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Routine DENY is case-insensitive
|
||||
--echo #
|
||||
|
||||
CREATE USER u_case@localhost;
|
||||
GRANT EXECUTE ON PROCEDURE test.proc1 TO u_case@localhost;
|
||||
GRANT EXECUTE ON FUNCTION test.func1 TO u_case@localhost;
|
||||
DENY EXECUTE ON PROCEDURE test.ProC1 TO u_case@localhost;
|
||||
DENY EXECUTE ON FUNCTION test.FUNC1 TO u_case@localhost;
|
||||
|
||||
connect (con_case, localhost, u_case,,);
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL test.proc1();
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
SELECT test.func1();
|
||||
|
||||
connection default;
|
||||
disconnect con_case;
|
||||
DROP USER u_case@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Package / package body DENY
|
||||
--echo #
|
||||
|
||||
CREATE USER u@localhost;
|
||||
GRANT EXECUTE,GRANT OPTION ON PACKAGE BODY test.pkg1 TO u@localhost;
|
||||
DENY EXECUTE ON PACKAGE BODY test.pkg1 TO u@localhost;
|
||||
|
||||
connect (con1, localhost, u,,test);
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL pkg1.p1();
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
SELECT pkg1.f1();
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # DROP SP clears denies for user
|
||||
--echo #
|
||||
CREATE USER u@localhost;
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE proc2() BEGIN SET @p=1; END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DENY EXECUTE ON PROCEDURE proc2 TO u@localhost;
|
||||
SHOW GRANTS for u@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
|
||||
--echo # show that deny entry exists in json
|
||||
SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE User='u';
|
||||
DROP PROCEDURE proc2;
|
||||
SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, '$.denies')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE User='u';
|
||||
SHOW GRANTS for u@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
DROP USER u@localhost;
|
||||
|
||||
|
||||
DROP PACKAGE BODY pkg1;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP PROCEDURE proc1;
|
||||
DROP FUNCTION func1;
|
||||
349
mysql-test/main/deny_show.result
Normal file
349
mysql-test/main/deny_show.result
Normal file
@@ -0,0 +1,349 @@
|
||||
#
|
||||
# SHOW commands with DENY
|
||||
#
|
||||
# SHOW DATABASES visibility
|
||||
CREATE USER u_show@localhost;
|
||||
CREATE DATABASE db1;
|
||||
CREATE TABLE db1.t1 (a int);
|
||||
GRANT SELECT ON *.* TO u_show@localhost;
|
||||
connect con1,localhost,u_show,,;
|
||||
# db1 should be visible (global SELECT granted)
|
||||
SHOW DATABASES LIKE 'db1';
|
||||
Database (db1)
|
||||
db1
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DENY SELECT ON *.* TO u_show@localhost;
|
||||
connect con1,localhost,u_show,,;
|
||||
# db1 should be hidden (global SELECT denied)
|
||||
SHOW DATABASES LIKE 'db1';
|
||||
Database (db1)
|
||||
disconnect con1;
|
||||
connection default;
|
||||
GRANT INSERT ON db1.t1 TO u_show@localhost;
|
||||
connect con1,localhost,u_show,,;
|
||||
# db1 should be visible (table INSERT grant not denied)
|
||||
SHOW DATABASES LIKE 'db1';
|
||||
Database (db1)
|
||||
db1
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DENY INSERT ON *.* TO u_show@localhost;
|
||||
connect con1,localhost,u_show,,;
|
||||
# db1 should be hidden (table INSERT masked by global DENY)
|
||||
SHOW DATABASES LIKE 'db1';
|
||||
Database (db1)
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP USER u_show@localhost;
|
||||
DROP DATABASE db1;
|
||||
# SHOW CREATE VIEW visibility
|
||||
CREATE USER u_view@localhost;
|
||||
CREATE DATABASE db2;
|
||||
CREATE TABLE db2.t1 (a int);
|
||||
CREATE VIEW db2.v1 AS SELECT * FROM db2.t1;
|
||||
GRANT SELECT, SHOW VIEW ON db2.* TO u_view@localhost;
|
||||
connect con2,localhost,u_view,,;
|
||||
# SHOW CREATE VIEW should be allowed (SELECT + SHOW VIEW granted)
|
||||
SHOW CREATE VIEW db2.v1;
|
||||
View Create View character_set_client collation_connection
|
||||
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `db2`.`v1` AS select `db2`.`t1`.`a` AS `a` from `db2`.`t1` <charset> <collation>
|
||||
# information_schema.views always shows the name; definition is visible here
|
||||
SELECT table_name, view_definition
|
||||
FROM information_schema.views
|
||||
WHERE table_schema='db2' ORDER BY table_name;
|
||||
table_name view_definition
|
||||
v1 select `db2`.`t1`.`a` AS `a` from `db2`.`t1`
|
||||
disconnect con2;
|
||||
connection default;
|
||||
DENY SELECT ON db2.* TO u_view@localhost;
|
||||
connect con2,localhost,u_view,,;
|
||||
# SHOW CREATE VIEW should be denied (SELECT denied)
|
||||
SHOW CREATE VIEW db2.v1;
|
||||
ERROR 42000: SELECT command denied to user 'u_view'@'localhost' for table `db2`.`v1`
|
||||
# information_schema.views always shows the name; definition is hidden here
|
||||
SELECT table_name, view_definition
|
||||
FROM information_schema.views
|
||||
WHERE table_schema='db2' ORDER BY table_name;
|
||||
table_name view_definition
|
||||
v1
|
||||
disconnect con2;
|
||||
connection default;
|
||||
REVOKE DENY SELECT ON db2.* FROM u_view@localhost;
|
||||
DENY SHOW VIEW ON db2.* TO u_view@localhost;
|
||||
connect con2,localhost,u_view,,;
|
||||
# SHOW CREATE VIEW should be denied (SHOW VIEW denied)
|
||||
SHOW CREATE VIEW db2.v1;
|
||||
ERROR 42000: SHOW VIEW command denied to user 'u_view'@'localhost' for table `db2`.`v1`
|
||||
# information_schema.views always shows the name; definition is hidden here
|
||||
SELECT table_name, view_definition
|
||||
FROM information_schema.views
|
||||
WHERE table_schema='db2' ORDER BY table_name;
|
||||
table_name view_definition
|
||||
v1
|
||||
disconnect con2;
|
||||
connection default;
|
||||
DROP USER u_view@localhost;
|
||||
DROP DATABASE db2;
|
||||
# SHOW FIELDS / SHOW INDEX visibility
|
||||
CREATE USER u_idx@localhost;
|
||||
CREATE DATABASE db3;
|
||||
CREATE TABLE db3.t1 (a int, b int, KEY k1(a));
|
||||
CREATE TABLE db3.t2 (a int, b int, KEY k2(b));
|
||||
GRANT SELECT ON db3.* TO u_idx@localhost;
|
||||
connect con3,localhost,u_idx,,;
|
||||
# SHOW FIELDS on db3.t1 should be allowed (SELECT granted)
|
||||
SHOW FIELDS FROM db3.t1;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) YES MUL NULL
|
||||
b int(11) YES NULL
|
||||
# SHOW INDEX on db3.t1 should be allowed (SELECT granted)
|
||||
SHOW INDEX FROM db3.t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored
|
||||
t1 1 k1 1 a A <cardinality> NULL NULL YES BTREE NO
|
||||
# SHOW FIELDS on db3.t2 should be allowed (SELECT granted)
|
||||
SHOW FIELDS FROM db3.t2;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) YES NULL
|
||||
b int(11) YES MUL NULL
|
||||
# SHOW INDEX on db3.t2 should be allowed (SELECT granted)
|
||||
SHOW INDEX FROM db3.t2;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored
|
||||
t2 1 k2 1 b A <cardinality> NULL NULL YES BTREE NO
|
||||
disconnect con3;
|
||||
connection default;
|
||||
DENY SELECT ON db3.t1 TO u_idx@localhost;
|
||||
connect con3,localhost,u_idx,,;
|
||||
# SHOW FIELDS/INDEX on t1 should be denied (table DENY)
|
||||
SHOW FIELDS FROM db3.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u_idx'@'localhost' for table `db3`.`t1`
|
||||
# SHOW INDEX on db3.t1 should be denied (table DENY)
|
||||
SHOW INDEX FROM db3.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u_idx'@'localhost' for table `db3`.`t1`
|
||||
# SHOW FIELDS on db3.t2 should be allowed
|
||||
SHOW FIELDS FROM db3.t2;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) YES NULL
|
||||
b int(11) YES MUL NULL
|
||||
# SHOW INDEX on db3.t2 should be allowed
|
||||
SHOW INDEX FROM db3.t2;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored
|
||||
disconnect con3;
|
||||
connection default;
|
||||
DROP USER u_idx@localhost;
|
||||
DROP DATABASE db3;
|
||||
# SHOW CREATE DATABASE visibility
|
||||
CREATE USER u_scdb@localhost;
|
||||
CREATE DATABASE db4;
|
||||
GRANT REFERENCES ON db4.* TO u_scdb@localhost;
|
||||
connect con4,localhost,u_scdb,,;
|
||||
# SHOW CREATE DATABASE should be allowed (REFERENCES granted)
|
||||
SHOW CREATE DATABASE db4;
|
||||
Database Create Database
|
||||
db4 <create_database>
|
||||
disconnect con4;
|
||||
connection default;
|
||||
DENY REFERENCES ON db4.* TO u_scdb@localhost;
|
||||
connect con4,localhost,u_scdb,,;
|
||||
# SHOW CREATE DATABASE should be denied (REFERENCES denied)
|
||||
SHOW CREATE DATABASE db4;
|
||||
ERROR 42000: Access denied for user 'u_scdb'@'localhost' to database 'db4'
|
||||
disconnect con4;
|
||||
connection default;
|
||||
DROP USER u_scdb@localhost;
|
||||
DROP DATABASE db4;
|
||||
# SHOW TABLES / SHOW TABLE STATUS / I_S visibility
|
||||
CREATE USER u_tbl@localhost;
|
||||
CREATE DATABASE db5;
|
||||
CREATE TABLE db5.t1 (a int);
|
||||
CREATE TABLE db5.t2 (a int, b int);
|
||||
GRANT SELECT ON db5.* TO u_tbl@localhost;
|
||||
connect con5,localhost,u_tbl,,;
|
||||
# SHOW TABLES should list t1 and t2 (SELECT granted)
|
||||
SHOW TABLES FROM db5;
|
||||
Tables_in_db5
|
||||
t1
|
||||
t2
|
||||
# SHOW TABLE STATUS should list t1 and t2 (SELECT granted)
|
||||
SHOW TABLE STATUS FROM db5;
|
||||
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
|
||||
t1 <engine> 10 <row_format> <rows> <avg_row_length> <data_length> <max_data_length> <index_length> <data_free> NULL <auto_increment> <created> <updated> <checked> <collation> 17179868160 <max_index_length>
|
||||
t2 <engine> 10 <row_format> <rows> <avg_row_length> <data_length> <max_data_length> <index_length> <data_free> NULL <auto_increment> <created> <updated> <checked> <collation> 17179868160 <max_index_length>
|
||||
# I_S.TABLES should list t1 and t2 (SELECT granted)
|
||||
SELECT table_name FROM information_schema.tables
|
||||
WHERE table_schema='db5' ORDER BY table_name;
|
||||
table_name
|
||||
t1
|
||||
t2
|
||||
# I_S.COLUMNS should list columns for t1 and t2 (SELECT granted)
|
||||
SELECT table_name, column_name FROM information_schema.columns
|
||||
WHERE table_schema='db5' ORDER BY table_name, column_name;
|
||||
table_name column_name
|
||||
t1 a
|
||||
t2 a
|
||||
t2 b
|
||||
# SHOW CREATE TABLE should be allowed for t1 (SELECT granted)
|
||||
SHOW CREATE TABLE db5.t1;
|
||||
Table Create Table
|
||||
t1 <create_table>
|
||||
# SHOW CREATE TABLE should be allowed for t2 (SELECT granted)
|
||||
SHOW CREATE TABLE db5.t2;
|
||||
Table Create Table
|
||||
t2 <create_table>
|
||||
disconnect con5;
|
||||
connection default;
|
||||
DENY SELECT ON db5.t1 TO u_tbl@localhost;
|
||||
connect con5,localhost,u_tbl,,;
|
||||
# SHOW TABLES should hide t1 (table DENY)
|
||||
SHOW TABLES FROM db5;
|
||||
Tables_in_db5
|
||||
t2
|
||||
# SHOW TABLE STATUS should hide t1 (table DENY)
|
||||
SHOW TABLE STATUS FROM db5;
|
||||
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
|
||||
t2 <engine> 10 <row_format> <rows> <avg_row_length> <data_length> <max_data_length> <index_length> <data_free> NULL <auto_increment> <created> <updated> <checked> <collation> 17179868160 <max_index_length>
|
||||
# I_S.TABLES should hide t1 (table DENY)
|
||||
SELECT table_name FROM information_schema.tables
|
||||
WHERE table_schema='db5' ORDER BY table_name;
|
||||
table_name
|
||||
t2
|
||||
# I_S.COLUMNS should hide t1 columns (table DENY)
|
||||
SELECT table_name, column_name FROM information_schema.columns
|
||||
WHERE table_schema='db5' ORDER BY table_name, column_name;
|
||||
table_name column_name
|
||||
t2 a
|
||||
t2 b
|
||||
# SHOW CREATE TABLE on t1 should be denied (table DENY)
|
||||
SHOW CREATE TABLE db5.t1;
|
||||
ERROR 42000: SHOW command denied to user 'u_tbl'@'localhost' for table `db5`.`t1`
|
||||
# SHOW CREATE TABLE on t2 should be allowed (SELECT allowed on table level)
|
||||
SHOW CREATE TABLE db5.t2;
|
||||
Table Create Table
|
||||
t2 <create_table>
|
||||
disconnect con5;
|
||||
connection default;
|
||||
REVOKE SELECT ON db5.* FROM u_tbl@localhost;
|
||||
REVOKE DENY SELECT ON db5.t1 FROM u_tbl@localhost;
|
||||
GRANT INSERT ON db5.t2 TO u_tbl@localhost;
|
||||
DENY INSERT ON *.* TO u_tbl@localhost;
|
||||
connect con5,localhost,u_tbl,,;
|
||||
# SHOW TABLES should be denied (table INSERT masked by global DENY)
|
||||
SHOW TABLES FROM db5;
|
||||
ERROR 42000: Access denied for user 'u_tbl'@'localhost' to database 'db5'
|
||||
# I_S.TABLES should be empty (table INSERT masked by global DENY)
|
||||
SELECT table_name FROM information_schema.tables
|
||||
WHERE table_schema='db5' ORDER BY table_name;
|
||||
table_name
|
||||
disconnect con5;
|
||||
connection default;
|
||||
GRANT SHOW VIEW ON db5.* TO u_tbl@localhost;
|
||||
connect con5,localhost,u_tbl,,;
|
||||
# SHOW CREATE TABLE on t2 should be allowed after SHOW VIEW grant
|
||||
SHOW CREATE TABLE db5.t2;
|
||||
Table Create Table
|
||||
t2 <create_table>
|
||||
disconnect con5;
|
||||
connection default;
|
||||
DROP USER u_tbl@localhost;
|
||||
DROP DATABASE db5;
|
||||
# I_S.STATISTICS + I_S.KEY_COLUMN_USAGE with column-level DENY
|
||||
# 1) With SELECT on indexed columns, I_S.STATISTICS shows composite index.
|
||||
# 2) DENY on one indexed column hides the index rows.
|
||||
# 3) With SELECT on PK column, I_S.KEY_COLUMN_USAGE shows PK row.
|
||||
# 4) DENY on PK column hides the PK row.
|
||||
CREATE USER u_stat@localhost;
|
||||
CREATE DATABASE db_stat;
|
||||
CREATE TABLE db_stat.t (a int, b int, PRIMARY KEY (a), KEY k1(a,b));
|
||||
GRANT SELECT (a,b) ON db_stat.t TO u_stat@localhost;
|
||||
connect con_stat,localhost,u_stat,,;
|
||||
# I_S.STATISTICS should show index (column SELECT granted)
|
||||
SELECT table_schema, table_name, index_name, seq_in_index, column_name
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema='db_stat' AND table_name='t' AND index_name='k1'
|
||||
ORDER BY seq_in_index;
|
||||
table_schema table_name index_name seq_in_index column_name
|
||||
db_stat t k1 1 a
|
||||
db_stat t k1 2 b
|
||||
disconnect con_stat;
|
||||
connection default;
|
||||
DENY SELECT (b) ON db_stat.t TO u_stat@localhost;
|
||||
connect con_stat,localhost,u_stat,,;
|
||||
# I_S.STATISTICS should be empty (column SELECT denied)
|
||||
SELECT table_schema, table_name, index_name, seq_in_index, column_name
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema='db_stat' AND table_name='t' AND index_name='k1'
|
||||
ORDER BY seq_in_index;
|
||||
table_schema table_name index_name seq_in_index column_name
|
||||
disconnect con_stat;
|
||||
connection default;
|
||||
connect con_stat,localhost,u_stat,,;
|
||||
# I_S.KEY_COLUMN_USAGE should show PK (column SELECT granted)
|
||||
SELECT table_schema, table_name, constraint_name, column_name
|
||||
FROM information_schema.key_column_usage
|
||||
WHERE table_schema='db_stat' AND table_name='t' AND constraint_name='PRIMARY'
|
||||
ORDER BY constraint_name, column_name;
|
||||
table_schema table_name constraint_name column_name
|
||||
db_stat t PRIMARY a
|
||||
disconnect con_stat;
|
||||
connection default;
|
||||
DENY SELECT (a) ON db_stat.t TO u_stat@localhost;
|
||||
connect con_stat,localhost,u_stat,,;
|
||||
# I_S.KEY_COLUMN_USAGE should be empty (column SELECT denied)
|
||||
SELECT table_schema, table_name, constraint_name, column_name
|
||||
FROM information_schema.key_column_usage
|
||||
WHERE table_schema='db_stat' AND table_name='t' AND constraint_name='PRIMARY'
|
||||
ORDER BY constraint_name, column_name;
|
||||
table_schema table_name constraint_name column_name
|
||||
disconnect con_stat;
|
||||
connection default;
|
||||
DROP USER u_stat@localhost;
|
||||
DROP DATABASE db_stat;
|
||||
# SHOW PROCEDURE/FUNCTION visibility
|
||||
CREATE USER u_rtn@localhost;
|
||||
CREATE DATABASE db6;
|
||||
CREATE PROCEDURE db6.p1() BEGIN SELECT 1; END//
|
||||
CREATE FUNCTION db6.f1() RETURNS INT RETURN 1//
|
||||
GRANT EXECUTE, SHOW CREATE ROUTINE ON db6.* TO u_rtn@localhost;
|
||||
connect con6,localhost,u_rtn,,;
|
||||
# SHOW PROCEDURE STATUS should show p1 (EXECUTE + SHOW CREATE ROUTINE granted)
|
||||
SHOW PROCEDURE STATUS WHERE Db='db6';
|
||||
Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
|
||||
db6 p1 PROCEDURE root@localhost <modified> <created> DEFINER <charset> <collation> <db_collation>
|
||||
# SHOW FUNCTION STATUS should show f1 (EXECUTE + SHOW CREATE ROUTINE granted)
|
||||
SHOW FUNCTION STATUS WHERE Db='db6';
|
||||
Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
|
||||
db6 f1 FUNCTION root@localhost <modified> <created> DEFINER <charset> <collation> <db_collation>
|
||||
# SHOW CREATE PROCEDURE should be allowed
|
||||
SHOW CREATE PROCEDURE db6.p1;
|
||||
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
|
||||
p1 <sql_mode> CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
|
||||
BEGIN SELECT 1; END <charset> <collation> <db_collation>
|
||||
# SHOW CREATE FUNCTION should be allowed
|
||||
SHOW CREATE FUNCTION db6.f1;
|
||||
Function sql_mode Create Function character_set_client collation_connection Database Collation
|
||||
f1 <sql_mode> CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11)
|
||||
RETURN 1 <charset> <collation> <db_collation>
|
||||
disconnect con6;
|
||||
connection default;
|
||||
DENY SHOW CREATE ROUTINE ON db6.* TO u_rtn@localhost;
|
||||
connect con6,localhost,u_rtn,,;
|
||||
# SHOW PROCEDURE STATUS should still show p1 (SHOW CREATE ROUTINE denied)
|
||||
SHOW PROCEDURE STATUS WHERE Db='db6';
|
||||
Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
|
||||
db6 p1 PROCEDURE root@localhost <modified> <created> DEFINER <charset> <collation> <db_collation>
|
||||
# SHOW FUNCTION STATUS should still show f1 (SHOW CREATE ROUTINE denied)
|
||||
SHOW FUNCTION STATUS WHERE Db='db6';
|
||||
Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
|
||||
db6 f1 FUNCTION root@localhost <modified> <created> DEFINER <charset> <collation> <db_collation>
|
||||
# SHOW CREATE PROCEDURE should be allowed but definition hidden
|
||||
SHOW CREATE PROCEDURE db6.p1;
|
||||
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
|
||||
p1 <sql_mode> NULL <charset> <collation> <db_collation>
|
||||
# SHOW CREATE FUNCTION should be allowed but definition hidden
|
||||
SHOW CREATE FUNCTION db6.f1;
|
||||
Function sql_mode Create Function character_set_client collation_connection Database Collation
|
||||
f1 <sql_mode> NULL <charset> <collation> <db_collation>
|
||||
disconnect con6;
|
||||
connection default;
|
||||
DROP USER u_rtn@localhost;
|
||||
DROP DATABASE db6;
|
||||
347
mysql-test/main/deny_show.test
Normal file
347
mysql-test/main/deny_show.test
Normal file
@@ -0,0 +1,347 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # SHOW commands with DENY
|
||||
--echo #
|
||||
|
||||
--echo # SHOW DATABASES visibility
|
||||
CREATE USER u_show@localhost;
|
||||
CREATE DATABASE db1;
|
||||
CREATE TABLE db1.t1 (a int);
|
||||
|
||||
GRANT SELECT ON *.* TO u_show@localhost;
|
||||
|
||||
--connect (con1,localhost,u_show,,)
|
||||
--echo # db1 should be visible (global SELECT granted)
|
||||
SHOW DATABASES LIKE 'db1';
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
DENY SELECT ON *.* TO u_show@localhost;
|
||||
|
||||
--connect (con1,localhost,u_show,,)
|
||||
--echo # db1 should be hidden (global SELECT denied)
|
||||
SHOW DATABASES LIKE 'db1';
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
GRANT INSERT ON db1.t1 TO u_show@localhost;
|
||||
|
||||
--connect (con1,localhost,u_show,,)
|
||||
--echo # db1 should be visible (table INSERT grant not denied)
|
||||
SHOW DATABASES LIKE 'db1';
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
DENY INSERT ON *.* TO u_show@localhost;
|
||||
|
||||
--connect (con1,localhost,u_show,,)
|
||||
--echo # db1 should be hidden (table INSERT masked by global DENY)
|
||||
SHOW DATABASES LIKE 'db1';
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
DROP USER u_show@localhost;
|
||||
DROP DATABASE db1;
|
||||
|
||||
--echo # SHOW CREATE VIEW visibility
|
||||
CREATE USER u_view@localhost;
|
||||
CREATE DATABASE db2;
|
||||
CREATE TABLE db2.t1 (a int);
|
||||
CREATE VIEW db2.v1 AS SELECT * FROM db2.t1;
|
||||
|
||||
GRANT SELECT, SHOW VIEW ON db2.* TO u_view@localhost;
|
||||
|
||||
--connect (con2,localhost,u_view,,)
|
||||
--echo # SHOW CREATE VIEW should be allowed (SELECT + SHOW VIEW granted)
|
||||
--replace_column 3 <charset> 4 <collation>
|
||||
SHOW CREATE VIEW db2.v1;
|
||||
--echo # information_schema.views always shows the name; definition is visible here
|
||||
SELECT table_name, view_definition
|
||||
FROM information_schema.views
|
||||
WHERE table_schema='db2' ORDER BY table_name;
|
||||
disconnect con2;
|
||||
connection default;
|
||||
|
||||
DENY SELECT ON db2.* TO u_view@localhost;
|
||||
|
||||
--connect (con2,localhost,u_view,,)
|
||||
--echo # SHOW CREATE VIEW should be denied (SELECT denied)
|
||||
--replace_column 3 <charset> 4 <collation>
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW CREATE VIEW db2.v1;
|
||||
--echo # information_schema.views always shows the name; definition is hidden here
|
||||
SELECT table_name, view_definition
|
||||
FROM information_schema.views
|
||||
WHERE table_schema='db2' ORDER BY table_name;
|
||||
disconnect con2;
|
||||
connection default;
|
||||
|
||||
REVOKE DENY SELECT ON db2.* FROM u_view@localhost;
|
||||
DENY SHOW VIEW ON db2.* TO u_view@localhost;
|
||||
|
||||
--connect (con2,localhost,u_view,,)
|
||||
--echo # SHOW CREATE VIEW should be denied (SHOW VIEW denied)
|
||||
--replace_column 3 <charset> 4 <collation>
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW CREATE VIEW db2.v1;
|
||||
--echo # information_schema.views always shows the name; definition is hidden here
|
||||
SELECT table_name, view_definition
|
||||
FROM information_schema.views
|
||||
WHERE table_schema='db2' ORDER BY table_name;
|
||||
disconnect con2;
|
||||
connection default;
|
||||
|
||||
DROP USER u_view@localhost;
|
||||
DROP DATABASE db2;
|
||||
|
||||
--echo # SHOW FIELDS / SHOW INDEX visibility
|
||||
CREATE USER u_idx@localhost;
|
||||
CREATE DATABASE db3;
|
||||
CREATE TABLE db3.t1 (a int, b int, KEY k1(a));
|
||||
CREATE TABLE db3.t2 (a int, b int, KEY k2(b));
|
||||
|
||||
GRANT SELECT ON db3.* TO u_idx@localhost;
|
||||
|
||||
--connect (con3,localhost,u_idx,,)
|
||||
--echo # SHOW FIELDS on db3.t1 should be allowed (SELECT granted)
|
||||
SHOW FIELDS FROM db3.t1;
|
||||
--echo # SHOW INDEX on db3.t1 should be allowed (SELECT granted)
|
||||
--replace_column 7 <cardinality>
|
||||
SHOW INDEX FROM db3.t1;
|
||||
--echo # SHOW FIELDS on db3.t2 should be allowed (SELECT granted)
|
||||
SHOW FIELDS FROM db3.t2;
|
||||
--echo # SHOW INDEX on db3.t2 should be allowed (SELECT granted)
|
||||
--replace_column 7 <cardinality>
|
||||
SHOW INDEX FROM db3.t2;
|
||||
disconnect con3;
|
||||
connection default;
|
||||
|
||||
DENY SELECT ON db3.t1 TO u_idx@localhost;
|
||||
|
||||
--connect (con3,localhost,u_idx,,)
|
||||
--echo # SHOW FIELDS/INDEX on t1 should be denied (table DENY)
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW FIELDS FROM db3.t1;
|
||||
--echo # SHOW INDEX on db3.t1 should be denied (table DENY)
|
||||
--replace_column 7 <cardinality>
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW INDEX FROM db3.t1;
|
||||
--echo # SHOW FIELDS on db3.t2 should be allowed
|
||||
SHOW FIELDS FROM db3.t2;
|
||||
--echo # SHOW INDEX on db3.t2 should be allowed
|
||||
--replace_column 7 <cardinality>
|
||||
SHOW INDEX FROM db3.t2;
|
||||
disconnect con3;
|
||||
connection default;
|
||||
|
||||
DROP USER u_idx@localhost;
|
||||
DROP DATABASE db3;
|
||||
|
||||
--echo # SHOW CREATE DATABASE visibility
|
||||
CREATE USER u_scdb@localhost;
|
||||
CREATE DATABASE db4;
|
||||
|
||||
GRANT REFERENCES ON db4.* TO u_scdb@localhost;
|
||||
|
||||
--connect (con4,localhost,u_scdb,,)
|
||||
--echo # SHOW CREATE DATABASE should be allowed (REFERENCES granted)
|
||||
--replace_column 2 <create_database>
|
||||
SHOW CREATE DATABASE db4;
|
||||
disconnect con4;
|
||||
connection default;
|
||||
|
||||
DENY REFERENCES ON db4.* TO u_scdb@localhost;
|
||||
|
||||
--connect (con4,localhost,u_scdb,,)
|
||||
--echo # SHOW CREATE DATABASE should be denied (REFERENCES denied)
|
||||
--replace_column 2 <create_database>
|
||||
--error ER_DBACCESS_DENIED_ERROR
|
||||
SHOW CREATE DATABASE db4;
|
||||
disconnect con4;
|
||||
connection default;
|
||||
|
||||
DROP USER u_scdb@localhost;
|
||||
DROP DATABASE db4;
|
||||
|
||||
--echo # SHOW TABLES / SHOW TABLE STATUS / I_S visibility
|
||||
CREATE USER u_tbl@localhost;
|
||||
CREATE DATABASE db5;
|
||||
CREATE TABLE db5.t1 (a int);
|
||||
CREATE TABLE db5.t2 (a int, b int);
|
||||
|
||||
GRANT SELECT ON db5.* TO u_tbl@localhost;
|
||||
|
||||
--connect (con5,localhost,u_tbl,,)
|
||||
--echo # SHOW TABLES should list t1 and t2 (SELECT granted)
|
||||
SHOW TABLES FROM db5;
|
||||
--echo # SHOW TABLE STATUS should list t1 and t2 (SELECT granted)
|
||||
--replace_column 2 <engine> 4 <row_format> 5 <rows> 6 <avg_row_length> 7 <data_length> 8 <max_data_length> 9 <index_length> 10 <data_free> 12 <auto_increment> 13 <created> 14 <updated> 15 <checked> 16 <collation> 20 <max_index_length>
|
||||
SHOW TABLE STATUS FROM db5;
|
||||
--echo # I_S.TABLES should list t1 and t2 (SELECT granted)
|
||||
SELECT table_name FROM information_schema.tables
|
||||
WHERE table_schema='db5' ORDER BY table_name;
|
||||
--echo # I_S.COLUMNS should list columns for t1 and t2 (SELECT granted)
|
||||
SELECT table_name, column_name FROM information_schema.columns
|
||||
WHERE table_schema='db5' ORDER BY table_name, column_name;
|
||||
--echo # SHOW CREATE TABLE should be allowed for t1 (SELECT granted)
|
||||
--replace_column 2 <create_table>
|
||||
SHOW CREATE TABLE db5.t1;
|
||||
--echo # SHOW CREATE TABLE should be allowed for t2 (SELECT granted)
|
||||
--replace_column 2 <create_table>
|
||||
SHOW CREATE TABLE db5.t2;
|
||||
disconnect con5;
|
||||
connection default;
|
||||
|
||||
DENY SELECT ON db5.t1 TO u_tbl@localhost;
|
||||
|
||||
--connect (con5,localhost,u_tbl,,)
|
||||
--echo # SHOW TABLES should hide t1 (table DENY)
|
||||
SHOW TABLES FROM db5;
|
||||
--echo # SHOW TABLE STATUS should hide t1 (table DENY)
|
||||
--replace_column 2 <engine> 4 <row_format> 5 <rows> 6 <avg_row_length> 7 <data_length> 8 <max_data_length> 9 <index_length> 10 <data_free> 12 <auto_increment> 13 <created> 14 <updated> 15 <checked> 16 <collation> 20 <max_index_length>
|
||||
SHOW TABLE STATUS FROM db5;
|
||||
--echo # I_S.TABLES should hide t1 (table DENY)
|
||||
SELECT table_name FROM information_schema.tables
|
||||
WHERE table_schema='db5' ORDER BY table_name;
|
||||
--echo # I_S.COLUMNS should hide t1 columns (table DENY)
|
||||
SELECT table_name, column_name FROM information_schema.columns
|
||||
WHERE table_schema='db5' ORDER BY table_name, column_name;
|
||||
--echo # SHOW CREATE TABLE on t1 should be denied (table DENY)
|
||||
--replace_column 2 <create_table>
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
SHOW CREATE TABLE db5.t1;
|
||||
--echo # SHOW CREATE TABLE on t2 should be allowed (SELECT allowed on table level)
|
||||
--replace_column 2 <create_table>
|
||||
SHOW CREATE TABLE db5.t2;
|
||||
disconnect con5;
|
||||
connection default;
|
||||
|
||||
REVOKE SELECT ON db5.* FROM u_tbl@localhost;
|
||||
REVOKE DENY SELECT ON db5.t1 FROM u_tbl@localhost;
|
||||
GRANT INSERT ON db5.t2 TO u_tbl@localhost;
|
||||
DENY INSERT ON *.* TO u_tbl@localhost;
|
||||
|
||||
--connect (con5,localhost,u_tbl,,)
|
||||
--echo # SHOW TABLES should be denied (table INSERT masked by global DENY)
|
||||
--error ER_DBACCESS_DENIED_ERROR
|
||||
SHOW TABLES FROM db5;
|
||||
--echo # I_S.TABLES should be empty (table INSERT masked by global DENY)
|
||||
SELECT table_name FROM information_schema.tables
|
||||
WHERE table_schema='db5' ORDER BY table_name;
|
||||
disconnect con5;
|
||||
connection default;
|
||||
|
||||
GRANT SHOW VIEW ON db5.* TO u_tbl@localhost;
|
||||
|
||||
--connect (con5,localhost,u_tbl,,)
|
||||
--echo # SHOW CREATE TABLE on t2 should be allowed after SHOW VIEW grant
|
||||
--replace_column 2 <create_table>
|
||||
SHOW CREATE TABLE db5.t2;
|
||||
disconnect con5;
|
||||
connection default;
|
||||
|
||||
DROP USER u_tbl@localhost;
|
||||
DROP DATABASE db5;
|
||||
|
||||
--echo # I_S.STATISTICS + I_S.KEY_COLUMN_USAGE with column-level DENY
|
||||
--echo # 1) With SELECT on indexed columns, I_S.STATISTICS shows composite index.
|
||||
--echo # 2) DENY on one indexed column hides the index rows.
|
||||
--echo # 3) With SELECT on PK column, I_S.KEY_COLUMN_USAGE shows PK row.
|
||||
--echo # 4) DENY on PK column hides the PK row.
|
||||
CREATE USER u_stat@localhost;
|
||||
CREATE DATABASE db_stat;
|
||||
CREATE TABLE db_stat.t (a int, b int, PRIMARY KEY (a), KEY k1(a,b));
|
||||
|
||||
GRANT SELECT (a,b) ON db_stat.t TO u_stat@localhost;
|
||||
|
||||
--connect (con_stat,localhost,u_stat,,)
|
||||
--echo # I_S.STATISTICS should show index (column SELECT granted)
|
||||
SELECT table_schema, table_name, index_name, seq_in_index, column_name
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema='db_stat' AND table_name='t' AND index_name='k1'
|
||||
ORDER BY seq_in_index;
|
||||
disconnect con_stat;
|
||||
connection default;
|
||||
|
||||
DENY SELECT (b) ON db_stat.t TO u_stat@localhost;
|
||||
|
||||
--connect (con_stat,localhost,u_stat,,)
|
||||
--echo # I_S.STATISTICS should be empty (column SELECT denied)
|
||||
SELECT table_schema, table_name, index_name, seq_in_index, column_name
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema='db_stat' AND table_name='t' AND index_name='k1'
|
||||
ORDER BY seq_in_index;
|
||||
disconnect con_stat;
|
||||
connection default;
|
||||
|
||||
--connect (con_stat,localhost,u_stat,,)
|
||||
--echo # I_S.KEY_COLUMN_USAGE should show PK (column SELECT granted)
|
||||
SELECT table_schema, table_name, constraint_name, column_name
|
||||
FROM information_schema.key_column_usage
|
||||
WHERE table_schema='db_stat' AND table_name='t' AND constraint_name='PRIMARY'
|
||||
ORDER BY constraint_name, column_name;
|
||||
disconnect con_stat;
|
||||
connection default;
|
||||
|
||||
DENY SELECT (a) ON db_stat.t TO u_stat@localhost;
|
||||
|
||||
--connect (con_stat,localhost,u_stat,,)
|
||||
--echo # I_S.KEY_COLUMN_USAGE should be empty (column SELECT denied)
|
||||
SELECT table_schema, table_name, constraint_name, column_name
|
||||
FROM information_schema.key_column_usage
|
||||
WHERE table_schema='db_stat' AND table_name='t' AND constraint_name='PRIMARY'
|
||||
ORDER BY constraint_name, column_name;
|
||||
disconnect con_stat;
|
||||
connection default;
|
||||
|
||||
DROP USER u_stat@localhost;
|
||||
DROP DATABASE db_stat;
|
||||
|
||||
--echo # SHOW PROCEDURE/FUNCTION visibility
|
||||
CREATE USER u_rtn@localhost;
|
||||
CREATE DATABASE db6;
|
||||
|
||||
DELIMITER //;
|
||||
CREATE PROCEDURE db6.p1() BEGIN SELECT 1; END//
|
||||
CREATE FUNCTION db6.f1() RETURNS INT RETURN 1//
|
||||
DELIMITER ;//
|
||||
|
||||
GRANT EXECUTE, SHOW CREATE ROUTINE ON db6.* TO u_rtn@localhost;
|
||||
|
||||
--connect (con6,localhost,u_rtn,,)
|
||||
--echo # SHOW PROCEDURE STATUS should show p1 (EXECUTE + SHOW CREATE ROUTINE granted)
|
||||
--replace_column 5 <modified> 6 <created> 9 <charset> 10 <collation> 11 <db_collation>
|
||||
SHOW PROCEDURE STATUS WHERE Db='db6';
|
||||
--echo # SHOW FUNCTION STATUS should show f1 (EXECUTE + SHOW CREATE ROUTINE granted)
|
||||
--replace_column 5 <modified> 6 <created> 9 <charset> 10 <collation> 11 <db_collation>
|
||||
SHOW FUNCTION STATUS WHERE Db='db6';
|
||||
--echo # SHOW CREATE PROCEDURE should be allowed
|
||||
--replace_column 2 <sql_mode> 4 <charset> 5 <collation> 6 <db_collation>
|
||||
SHOW CREATE PROCEDURE db6.p1;
|
||||
--echo # SHOW CREATE FUNCTION should be allowed
|
||||
--replace_column 2 <sql_mode> 4 <charset> 5 <collation> 6 <db_collation>
|
||||
SHOW CREATE FUNCTION db6.f1;
|
||||
disconnect con6;
|
||||
connection default;
|
||||
|
||||
DENY SHOW CREATE ROUTINE ON db6.* TO u_rtn@localhost;
|
||||
|
||||
--connect (con6,localhost,u_rtn,,)
|
||||
--echo # SHOW PROCEDURE STATUS should still show p1 (SHOW CREATE ROUTINE denied)
|
||||
--replace_column 5 <modified> 6 <created> 9 <charset> 10 <collation> 11 <db_collation>
|
||||
SHOW PROCEDURE STATUS WHERE Db='db6';
|
||||
--echo # SHOW FUNCTION STATUS should still show f1 (SHOW CREATE ROUTINE denied)
|
||||
--replace_column 5 <modified> 6 <created> 9 <charset> 10 <collation> 11 <db_collation>
|
||||
SHOW FUNCTION STATUS WHERE Db='db6';
|
||||
--echo # SHOW CREATE PROCEDURE should be allowed but definition hidden
|
||||
--replace_column 2 <sql_mode> 4 <charset> 5 <collation> 6 <db_collation>
|
||||
SHOW CREATE PROCEDURE db6.p1;
|
||||
--echo # SHOW CREATE FUNCTION should be allowed but definition hidden
|
||||
--replace_column 2 <sql_mode> 4 <charset> 5 <collation> 6 <db_collation>
|
||||
SHOW CREATE FUNCTION db6.f1;
|
||||
disconnect con6;
|
||||
connection default;
|
||||
|
||||
DROP USER u_rtn@localhost;
|
||||
DROP DATABASE db6;
|
||||
213
mysql-test/main/deny_show_grants.result
Normal file
213
mysql-test/main/deny_show_grants.result
Normal file
@@ -0,0 +1,213 @@
|
||||
#
|
||||
# SHOW GRANTS with DENY output
|
||||
#
|
||||
CREATE DATABASE sg_db;
|
||||
USE sg_db;
|
||||
CREATE TABLE t1 (c1 INT, c2 INT);
|
||||
CREATE PROCEDURE p1() BEGIN SET @x=1; END;
|
||||
$$
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN 1;
|
||||
$$
|
||||
CREATE PACKAGE pkg1
|
||||
PROCEDURE p1();
|
||||
FUNCTION f1() RETURNS INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1
|
||||
PROCEDURE p1() BEGIN SET @pkg=2; END;
|
||||
FUNCTION f1() RETURNS INT BEGIN RETURN 2; END;
|
||||
END;
|
||||
$$
|
||||
CREATE USER u1@localhost;
|
||||
#
|
||||
# Miscellaneous GRANT/DENY mix, different levels
|
||||
#
|
||||
GRANT SELECT ON sg_db.t1 TO u1@localhost;
|
||||
GRANT UPDATE (c1) ON sg_db.t1 TO u1@localhost;
|
||||
GRANT EXECUTE ON PROCEDURE sg_db.p1 TO u1@localhost;
|
||||
GRANT EXECUTE ON PACKAGE sg_db.pkg1 TO u1@localhost;
|
||||
DENY SELECT ON *.* TO u1@localhost;
|
||||
DENY INSERT ON sg_db.* TO u1@localhost;
|
||||
DENY UPDATE (c2) ON sg_db.t1 TO u1@localhost;
|
||||
DENY EXECUTE ON FUNCTION sg_db.f1 TO u1@localhost;
|
||||
DENY EXECUTE ON PACKAGE BODY sg_db.pkg1 TO u1@localhost;
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
Grants for u1@localhost
|
||||
GRANT USAGE ON *.* TO `u1`@`localhost`
|
||||
DENY SELECT ON *.* TO `u1`@`localhost`
|
||||
DENY INSERT ON `sg_db`.* TO `u1`@`localhost`
|
||||
GRANT SELECT, UPDATE (`c1`) ON `sg_db`.`t1` TO `u1`@`localhost`
|
||||
DENY UPDATE (`c2`) ON `sg_db`.`t1` TO `u1`@`localhost`
|
||||
GRANT EXECUTE ON PROCEDURE `sg_db`.`p1` TO `u1`@`localhost`
|
||||
DENY EXECUTE ON FUNCTION `sg_db`.`f1` TO `u1`@`localhost`
|
||||
GRANT EXECUTE ON PACKAGE `sg_db`.`pkg1` TO `u1`@`localhost`
|
||||
DENY EXECUTE ON PACKAGE BODY `sg_db`.`pkg1` TO `u1`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
DROP USER u1@localhost;
|
||||
#
|
||||
# ALL PRIVILEGES, GRANT OPTION
|
||||
#
|
||||
CREATE USER u1@localhost;
|
||||
DENY ALL PRIVILEGES ON sg_db.* TO u1@localhost;
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
Grants for u1@localhost
|
||||
GRANT USAGE ON *.* TO `u1`@`localhost`
|
||||
DENY ALL PRIVILEGES ON `sg_db`.* TO `u1`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
DENY ALL PRIVILEGES ON sg_db.* TO u1@localhost WITH GRANT OPTION;
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
Grants for u1@localhost
|
||||
GRANT USAGE ON *.* TO `u1`@`localhost`
|
||||
DENY ALL PRIVILEGES ON `sg_db`.* TO `u1`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
REVOKE DENY ALL ON sg_db.* FROM u1@localhost;
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
Grants for u1@localhost
|
||||
GRANT USAGE ON *.* TO `u1`@`localhost`
|
||||
DENY USAGE ON `sg_db`.* TO `u1`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
DENY GRANT OPTION ON sg_db.* to u1@localhost;
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
Grants for u1@localhost
|
||||
GRANT USAGE ON *.* TO `u1`@`localhost`
|
||||
DENY USAGE ON `sg_db`.* TO `u1`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
#
|
||||
# Do not show (own) DENY for non-privileged users
|
||||
#
|
||||
connect con1, localhost, u1,,;
|
||||
SHOW GRANTS;
|
||||
Grants for u1@localhost
|
||||
GRANT USAGE ON *.* TO `u1`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
disconnect con1;
|
||||
connection default;
|
||||
GRANT SELECT ON mysql.* TO u1@localhost;
|
||||
connect con1, localhost, u1,,;
|
||||
SHOW GRANTS;
|
||||
Grants for u1@localhost
|
||||
GRANT USAGE ON *.* TO `u1`@`localhost`
|
||||
GRANT SELECT ON `mysql`.* TO `u1`@`localhost`
|
||||
DENY USAGE ON `sg_db`.* TO `u1`@`localhost`
|
||||
# END SHOW GRANTS
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP USER u1@localhost;
|
||||
DROP PACKAGE BODY pkg1;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP FUNCTION f1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
DROP DATABASE sg_db;
|
||||
#
|
||||
# SHOW GRANTS FOR role: non-privileged vs privileged user
|
||||
# Without SELECT on mysql.*, a user must NOT see their own active role's DENY.
|
||||
# With SELECT on mysql.* (privileged), the DENY must be visible.
|
||||
# SHOW GRANTS FOR CURRENT_ROLE and SHOW GRANTS FOR <role_name> must be consistent.
|
||||
#
|
||||
CREATE ROLE r1;
|
||||
DENY SELECT ON test.* TO r1;
|
||||
CREATE USER u1@localhost;
|
||||
GRANT r1 TO u1@localhost;
|
||||
connect con1, localhost, u1,,;
|
||||
SET ROLE r1;
|
||||
# non-privileged: SHOW GRANTS FOR CURRENT_ROLE
|
||||
SHOW GRANTS FOR CURRENT_ROLE;
|
||||
Grants for r1
|
||||
GRANT USAGE ON *.* TO `r1`
|
||||
# END SHOW GRANTS
|
||||
# non-privileged: SHOW GRANTS FOR r1 (same role, by name)
|
||||
SHOW GRANTS FOR r1;
|
||||
Grants for r1
|
||||
GRANT USAGE ON *.* TO `r1`
|
||||
# END SHOW GRANTS
|
||||
disconnect con1;
|
||||
connection default;
|
||||
GRANT SELECT ON mysql.* TO u1@localhost;
|
||||
connect con1, localhost, u1,,;
|
||||
SET ROLE r1;
|
||||
# privileged: SHOW GRANTS FOR CURRENT_ROLE
|
||||
SHOW GRANTS FOR CURRENT_ROLE;
|
||||
Grants for r1
|
||||
GRANT USAGE ON *.* TO `r1`
|
||||
DENY SELECT ON `test`.* TO `r1`
|
||||
# END SHOW GRANTS
|
||||
# privileged: SHOW GRANTS FOR r1 (same role, by name)
|
||||
SHOW GRANTS FOR r1;
|
||||
Grants for r1
|
||||
GRANT USAGE ON *.* TO `r1`
|
||||
DENY SELECT ON `test`.* TO `r1`
|
||||
# END SHOW GRANTS
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP USER u1@localhost;
|
||||
DROP ROLE r1;
|
||||
#
|
||||
# SHOW GRANTS FOR PUBLIC: non-privileged vs privileged user
|
||||
# Without SELECT on mysql.*, a user must NOT see DENYs on PUBLIC.
|
||||
# With SELECT on mysql.* (privileged), the DENY must be visible.
|
||||
#
|
||||
CREATE USER u1@localhost;
|
||||
DENY SELECT ON test.* TO PUBLIC;
|
||||
connect con1, localhost, u1,,;
|
||||
# non-privileged: SHOW GRANTS FOR PUBLIC
|
||||
SHOW GRANTS FOR PUBLIC;
|
||||
Grants for PUBLIC
|
||||
# END SHOW GRANTS
|
||||
disconnect con1;
|
||||
connection default;
|
||||
GRANT SELECT ON mysql.* TO u1@localhost;
|
||||
connect con1, localhost, u1,,;
|
||||
# privileged: SHOW GRANTS FOR PUBLIC
|
||||
SHOW GRANTS FOR PUBLIC;
|
||||
Grants for PUBLIC
|
||||
DENY SELECT ON `test`.* TO PUBLIC
|
||||
# END SHOW GRANTS
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP USER u1@localhost;
|
||||
REVOKE DENY SELECT ON test.* FROM PUBLIC;
|
||||
DELETE FROM mysql.global_priv WHERE User='PUBLIC';
|
||||
FLUSH PRIVILEGES;
|
||||
#
|
||||
# SHOW GRANTS: user with SELECT on mysql.* but DENY on mysql.global_priv
|
||||
# That user must neither see own DENIES, not should he be able to
|
||||
# SHOW GRANTS for a another user
|
||||
#
|
||||
CREATE USER u1@localhost;
|
||||
GRANT SELECT ON mysql.* TO u1@localhost;
|
||||
DENY SELECT ON mysql.global_priv TO u1@localhost;
|
||||
DENY SELECT ON test.* to u1@localhost;
|
||||
CREATE USER u2@localhost;
|
||||
GRANT SELECT ON test.* TO u2@localhost;
|
||||
connect con1, localhost, u1,,;
|
||||
# SHOW GRANTS should succeed and must not contain own DENY
|
||||
SHOW GRANTS;
|
||||
Grants for u1@localhost
|
||||
GRANT USAGE ON *.* TO `u1`@`localhost`
|
||||
GRANT SELECT ON `mysql`.* TO `u1`@`localhost`
|
||||
# END SHOW GRANTS;
|
||||
SHOW GRANTS FOR u2@localhost;
|
||||
ERROR 42000: Access denied for user 'u1'@'localhost' to database 'mysql'
|
||||
disconnect con1;
|
||||
connection default;
|
||||
# Now allow access to mysql.global_priv and verify own DENY are visible
|
||||
REVOKE DENY SELECT ON mysql.global_priv FROM u1@localhost;
|
||||
connect con1, localhost, u1,,;
|
||||
# SHOW GRANTS should succeed and must contain own DENY
|
||||
SHOW GRANTS;
|
||||
Grants for u1@localhost
|
||||
GRANT USAGE ON *.* TO `u1`@`localhost`
|
||||
GRANT SELECT ON `mysql`.* TO `u1`@`localhost`
|
||||
DENY SELECT ON `test`.* TO `u1`@`localhost`
|
||||
# END SHOW GRANTS;
|
||||
# SHOW GRANTS for another user
|
||||
SHOW GRANTS FOR u2@localhost;
|
||||
Grants for u2@localhost
|
||||
GRANT USAGE ON *.* TO `u2`@`localhost`
|
||||
GRANT SELECT ON `test`.* TO `u2`@`localhost`
|
||||
# END SHOW GRANTS;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP USER u1@localhost;
|
||||
DROP USER u2@localhost;
|
||||
197
mysql-test/main/deny_show_grants.test
Normal file
197
mysql-test/main/deny_show_grants.test
Normal file
@@ -0,0 +1,197 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/no_protocol.inc
|
||||
|
||||
--echo #
|
||||
--echo # SHOW GRANTS with DENY output
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE sg_db;
|
||||
USE sg_db;
|
||||
|
||||
CREATE TABLE t1 (c1 INT, c2 INT);
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1() BEGIN SET @x=1; END;
|
||||
$$
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN 1;
|
||||
$$
|
||||
CREATE PACKAGE pkg1
|
||||
PROCEDURE p1();
|
||||
FUNCTION f1() RETURNS INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1
|
||||
PROCEDURE p1() BEGIN SET @pkg=2; END;
|
||||
FUNCTION f1() RETURNS INT BEGIN RETURN 2; END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE USER u1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Miscellaneous GRANT/DENY mix, different levels
|
||||
--echo #
|
||||
GRANT SELECT ON sg_db.t1 TO u1@localhost;
|
||||
GRANT UPDATE (c1) ON sg_db.t1 TO u1@localhost;
|
||||
GRANT EXECUTE ON PROCEDURE sg_db.p1 TO u1@localhost;
|
||||
GRANT EXECUTE ON PACKAGE sg_db.pkg1 TO u1@localhost;
|
||||
|
||||
DENY SELECT ON *.* TO u1@localhost;
|
||||
DENY INSERT ON sg_db.* TO u1@localhost;
|
||||
DENY UPDATE (c2) ON sg_db.t1 TO u1@localhost;
|
||||
DENY EXECUTE ON FUNCTION sg_db.f1 TO u1@localhost;
|
||||
DENY EXECUTE ON PACKAGE BODY sg_db.pkg1 TO u1@localhost;
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
|
||||
DROP USER u1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # ALL PRIVILEGES, GRANT OPTION
|
||||
--echo #
|
||||
CREATE USER u1@localhost;
|
||||
DENY ALL PRIVILEGES ON sg_db.* TO u1@localhost;
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
DENY ALL PRIVILEGES ON sg_db.* TO u1@localhost WITH GRANT OPTION;
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
REVOKE DENY ALL ON sg_db.* FROM u1@localhost;
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
|
||||
DENY GRANT OPTION ON sg_db.* to u1@localhost;
|
||||
# slightly ugly DENY USAGE .. WITH GRANT OPTION
|
||||
SHOW GRANTS FOR u1@localhost;
|
||||
--echo # END SHOW GRANTS
|
||||
|
||||
--echo #
|
||||
--echo # Do not show (own) DENY for non-privileged users
|
||||
--echo #
|
||||
connect(con1, localhost, u1,,);
|
||||
SHOW GRANTS; # should only show USAGE
|
||||
--echo # END SHOW GRANTS
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
GRANT SELECT ON mysql.* TO u1@localhost;
|
||||
|
||||
connect(con1, localhost, u1,,);
|
||||
SHOW GRANTS; # should show more
|
||||
--echo # END SHOW GRANTS
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
DROP USER u1@localhost;
|
||||
DROP PACKAGE BODY pkg1;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP FUNCTION f1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
DROP DATABASE sg_db;
|
||||
|
||||
--echo #
|
||||
--echo # SHOW GRANTS FOR role: non-privileged vs privileged user
|
||||
--echo # Without SELECT on mysql.*, a user must NOT see their own active role's DENY.
|
||||
--echo # With SELECT on mysql.* (privileged), the DENY must be visible.
|
||||
--echo # SHOW GRANTS FOR CURRENT_ROLE and SHOW GRANTS FOR <role_name> must be consistent.
|
||||
--echo #
|
||||
CREATE ROLE r1;
|
||||
DENY SELECT ON test.* TO r1;
|
||||
CREATE USER u1@localhost;
|
||||
GRANT r1 TO u1@localhost;
|
||||
|
||||
connect(con1, localhost, u1,,);
|
||||
SET ROLE r1;
|
||||
--echo # non-privileged: SHOW GRANTS FOR CURRENT_ROLE
|
||||
SHOW GRANTS FOR CURRENT_ROLE;
|
||||
--echo # END SHOW GRANTS
|
||||
--echo # non-privileged: SHOW GRANTS FOR r1 (same role, by name)
|
||||
SHOW GRANTS FOR r1;
|
||||
--echo # END SHOW GRANTS
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
GRANT SELECT ON mysql.* TO u1@localhost;
|
||||
|
||||
connect(con1, localhost, u1,,);
|
||||
SET ROLE r1;
|
||||
--echo # privileged: SHOW GRANTS FOR CURRENT_ROLE
|
||||
SHOW GRANTS FOR CURRENT_ROLE;
|
||||
--echo # END SHOW GRANTS
|
||||
--echo # privileged: SHOW GRANTS FOR r1 (same role, by name)
|
||||
SHOW GRANTS FOR r1;
|
||||
--echo # END SHOW GRANTS
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
DROP USER u1@localhost;
|
||||
DROP ROLE r1;
|
||||
|
||||
--echo #
|
||||
--echo # SHOW GRANTS FOR PUBLIC: non-privileged vs privileged user
|
||||
--echo # Without SELECT on mysql.*, a user must NOT see DENYs on PUBLIC.
|
||||
--echo # With SELECT on mysql.* (privileged), the DENY must be visible.
|
||||
--echo #
|
||||
CREATE USER u1@localhost;
|
||||
DENY SELECT ON test.* TO PUBLIC;
|
||||
|
||||
connect(con1, localhost, u1,,);
|
||||
--echo # non-privileged: SHOW GRANTS FOR PUBLIC
|
||||
SHOW GRANTS FOR PUBLIC;
|
||||
--echo # END SHOW GRANTS
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
GRANT SELECT ON mysql.* TO u1@localhost;
|
||||
|
||||
connect(con1, localhost, u1,,);
|
||||
--echo # privileged: SHOW GRANTS FOR PUBLIC
|
||||
SHOW GRANTS FOR PUBLIC;
|
||||
--echo # END SHOW GRANTS
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
DROP USER u1@localhost;
|
||||
REVOKE DENY SELECT ON test.* FROM PUBLIC;
|
||||
DELETE FROM mysql.global_priv WHERE User='PUBLIC';
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
--echo #
|
||||
--echo # SHOW GRANTS: user with SELECT on mysql.* but DENY on mysql.global_priv
|
||||
--echo # That user must neither see own DENIES, not should he be able to
|
||||
--echo # SHOW GRANTS for a another user
|
||||
--echo #
|
||||
CREATE USER u1@localhost;
|
||||
GRANT SELECT ON mysql.* TO u1@localhost;
|
||||
DENY SELECT ON mysql.global_priv TO u1@localhost;
|
||||
DENY SELECT ON test.* to u1@localhost;
|
||||
CREATE USER u2@localhost;
|
||||
GRANT SELECT ON test.* TO u2@localhost;
|
||||
|
||||
connect(con1, localhost, u1,,);
|
||||
--echo # SHOW GRANTS should succeed and must not contain own DENY
|
||||
SHOW GRANTS;
|
||||
--echo # END SHOW GRANTS;
|
||||
--error ER_DBACCESS_DENIED_ERROR
|
||||
SHOW GRANTS FOR u2@localhost;
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
--echo # Now allow access to mysql.global_priv and verify own DENY are visible
|
||||
REVOKE DENY SELECT ON mysql.global_priv FROM u1@localhost;
|
||||
|
||||
connect(con1, localhost, u1,,);
|
||||
--echo # SHOW GRANTS should succeed and must contain own DENY
|
||||
SHOW GRANTS;
|
||||
--echo # END SHOW GRANTS;
|
||||
--echo # SHOW GRANTS for another user
|
||||
SHOW GRANTS FOR u2@localhost;
|
||||
--echo # END SHOW GRANTS;
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
DROP USER u1@localhost;
|
||||
DROP USER u2@localhost;
|
||||
|
||||
247
mysql-test/main/deny_storage.result
Normal file
247
mysql-test/main/deny_storage.result
Normal file
@@ -0,0 +1,247 @@
|
||||
#
|
||||
# Test DENY representation as JSON in mysql.global_priv table
|
||||
#
|
||||
SET @q_show_denies =
|
||||
'SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, ''$.denies'')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE JSON_LENGTH(JSON_EXTRACT(Priv, ''$.denies'')) > 0
|
||||
ORDER BY User, Host';
|
||||
PREPARE show_denies FROM @q_show_denies;
|
||||
CREATE USER u;
|
||||
CREATE DATABASE d;
|
||||
DENY SELECT,INSERT ON mysql.* TO u;
|
||||
DENY UPDATE ON d.* TO u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "db",
|
||||
"db": "mysql",
|
||||
"bits": 3
|
||||
},
|
||||
{
|
||||
"type": "db",
|
||||
"db": "d",
|
||||
"bits": 4
|
||||
}
|
||||
]
|
||||
REVOKE DENY SELECT ON mysql.* FROM u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "db",
|
||||
"db": "mysql",
|
||||
"bits": 2
|
||||
},
|
||||
{
|
||||
"type": "db",
|
||||
"db": "d",
|
||||
"bits": 4
|
||||
}
|
||||
]
|
||||
REVOKE DENY INSERT ON mysql.* FROM u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "db",
|
||||
"db": "d",
|
||||
"bits": 4
|
||||
}
|
||||
]
|
||||
REVOKE DENY UPDATE ON d.* FROM u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
# Table level
|
||||
DENY SELECT,INSERT ON mysql.global_priv TO u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "table",
|
||||
"db": "mysql",
|
||||
"table": "global_priv",
|
||||
"bits": 3
|
||||
}
|
||||
]
|
||||
REVOKE DENY INSERT,SELECT ON mysql.global_priv FROM u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
DENY SELECT(USER) ON mysql.global_priv TO u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "column",
|
||||
"db": "mysql",
|
||||
"table": "global_priv",
|
||||
"column": "USER",
|
||||
"bits": 1
|
||||
}
|
||||
]
|
||||
DENY UPDATE(USER) ON mysql.global_priv TO u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "column",
|
||||
"db": "mysql",
|
||||
"table": "global_priv",
|
||||
"column": "USER",
|
||||
"bits": 5
|
||||
}
|
||||
]
|
||||
DENY SELECT ON *.* TO u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "column",
|
||||
"db": "mysql",
|
||||
"table": "global_priv",
|
||||
"column": "USER",
|
||||
"bits": 5
|
||||
},
|
||||
{
|
||||
"type": "global",
|
||||
"bits": 1
|
||||
}
|
||||
]
|
||||
CREATE TABLE sensitive_data (
|
||||
id INT,
|
||||
public_info VARCHAR(50),
|
||||
salary DECIMAL(10,2),
|
||||
ssn VARCHAR(11),
|
||||
address VARCHAR(100)
|
||||
);
|
||||
DENY SELECT(salary,ssn) ON sensitive_data TO u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "column",
|
||||
"db": "mysql",
|
||||
"table": "global_priv",
|
||||
"column": "USER",
|
||||
"bits": 5
|
||||
},
|
||||
{
|
||||
"type": "global",
|
||||
"bits": 1
|
||||
},
|
||||
{
|
||||
"type": "column",
|
||||
"db": "test",
|
||||
"table": "sensitive_data",
|
||||
"column": "salary",
|
||||
"bits": 1
|
||||
},
|
||||
{
|
||||
"type": "column",
|
||||
"db": "test",
|
||||
"table": "sensitive_data",
|
||||
"column": "ssn",
|
||||
"bits": 1
|
||||
}
|
||||
]
|
||||
GRANT ALL PRIVILEGES on *.* TO u WITH GRANT OPTION;
|
||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM u;
|
||||
# REVOKE ALL PRIVILEGES clears DENY entries
|
||||
SHOW GRANTS FOR u;
|
||||
Grants for u@%
|
||||
GRANT USAGE ON *.* TO `u`@`%`
|
||||
# END SHOW GRANTS
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
#
|
||||
# Identifiers that require JSON escaping (double-quotes, backslash, etc.)
|
||||
#
|
||||
CREATE DATABASE `a"b\c`;
|
||||
CREATE TABLE `a"b\c`.`t"1` (
|
||||
`col"x` INT,
|
||||
normal_col INT
|
||||
);
|
||||
DENY SELECT ON `a"b\c`.* TO u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "db",
|
||||
"db": "a\"b\\c",
|
||||
"bits": 1
|
||||
}
|
||||
]
|
||||
DENY INSERT ON `a"b\c`.`t"1` TO u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "db",
|
||||
"db": "a\"b\\c",
|
||||
"bits": 1
|
||||
},
|
||||
{
|
||||
"type": "table",
|
||||
"db": "a\"b\\c",
|
||||
"table": "t\"1",
|
||||
"bits": 2
|
||||
}
|
||||
]
|
||||
DENY UPDATE(`col"x`) ON `a"b\c`.`t"1` TO u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "db",
|
||||
"db": "a\"b\\c",
|
||||
"bits": 1
|
||||
},
|
||||
{
|
||||
"type": "table",
|
||||
"db": "a\"b\\c",
|
||||
"table": "t\"1",
|
||||
"bits": 2
|
||||
},
|
||||
{
|
||||
"type": "column",
|
||||
"db": "a\"b\\c",
|
||||
"table": "t\"1",
|
||||
"column": "col\"x",
|
||||
"bits": 4
|
||||
}
|
||||
]
|
||||
# Verify SHOW GRANTS round-trips the special names
|
||||
SHOW GRANTS FOR u;
|
||||
Grants for u@%
|
||||
GRANT USAGE ON *.* TO `u`@`%`
|
||||
DENY SELECT ON `a"b\c`.* TO `u`@`%`
|
||||
DENY INSERT, UPDATE (`col"x`) ON `a"b\c`.`t"1` TO `u`@`%`
|
||||
# Verify REVOKE works with the special names
|
||||
REVOKE DENY UPDATE(`col"x`) ON `a"b\c`.`t"1` FROM u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
u % [
|
||||
{
|
||||
"type": "db",
|
||||
"db": "a\"b\\c",
|
||||
"bits": 1
|
||||
},
|
||||
{
|
||||
"type": "table",
|
||||
"db": "a\"b\\c",
|
||||
"table": "t\"1",
|
||||
"bits": 2
|
||||
}
|
||||
]
|
||||
REVOKE DENY INSERT ON `a"b\c`.`t"1` FROM u;
|
||||
REVOKE DENY SELECT ON `a"b\c`.* FROM u;
|
||||
EXECUTE show_denies;
|
||||
User Host denies_pretty
|
||||
DROP TABLE `a"b\c`.`t"1`;
|
||||
DROP DATABASE `a"b\c`;
|
||||
DEALLOCATE PREPARE show_denies;
|
||||
DROP USER u;
|
||||
DROP DATABASE d;
|
||||
DROP TABLE sensitive_data;
|
||||
106
mysql-test/main/deny_storage.test
Normal file
106
mysql-test/main/deny_storage.test
Normal file
@@ -0,0 +1,106 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # Test DENY representation as JSON in mysql.global_priv table
|
||||
--echo #
|
||||
|
||||
SET @q_show_denies =
|
||||
'SELECT User, Host,
|
||||
JSON_PRETTY(JSON_EXTRACT(Priv, ''$.denies'')) AS denies_pretty
|
||||
FROM mysql.global_priv
|
||||
WHERE JSON_LENGTH(JSON_EXTRACT(Priv, ''$.denies'')) > 0
|
||||
ORDER BY User, Host';
|
||||
|
||||
PREPARE show_denies FROM @q_show_denies;
|
||||
|
||||
CREATE USER u;
|
||||
CREATE DATABASE d;
|
||||
|
||||
DENY SELECT,INSERT ON mysql.* TO u;
|
||||
DENY UPDATE ON d.* TO u;
|
||||
|
||||
EXECUTE show_denies;
|
||||
|
||||
REVOKE DENY SELECT ON mysql.* FROM u;
|
||||
|
||||
EXECUTE show_denies;
|
||||
|
||||
REVOKE DENY INSERT ON mysql.* FROM u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
REVOKE DENY UPDATE ON d.* FROM u;
|
||||
|
||||
EXECUTE show_denies;
|
||||
|
||||
--echo # Table level
|
||||
DENY SELECT,INSERT ON mysql.global_priv TO u;
|
||||
EXECUTE show_denies;
|
||||
REVOKE DENY INSERT,SELECT ON mysql.global_priv FROM u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
DENY SELECT(USER) ON mysql.global_priv TO u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
DENY UPDATE(USER) ON mysql.global_priv TO u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
DENY SELECT ON *.* TO u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
CREATE TABLE sensitive_data (
|
||||
id INT,
|
||||
public_info VARCHAR(50),
|
||||
salary DECIMAL(10,2),
|
||||
ssn VARCHAR(11),
|
||||
address VARCHAR(100)
|
||||
);
|
||||
|
||||
DENY SELECT(salary,ssn) ON sensitive_data TO u;
|
||||
|
||||
EXECUTE show_denies;
|
||||
|
||||
GRANT ALL PRIVILEGES on *.* TO u WITH GRANT OPTION;
|
||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM u;
|
||||
|
||||
--echo # REVOKE ALL PRIVILEGES clears DENY entries
|
||||
SHOW GRANTS FOR u;
|
||||
--echo # END SHOW GRANTS
|
||||
EXECUTE show_denies;
|
||||
|
||||
--echo #
|
||||
--echo # Identifiers that require JSON escaping (double-quotes, backslash, etc.)
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE `a"b\c`;
|
||||
CREATE TABLE `a"b\c`.`t"1` (
|
||||
`col"x` INT,
|
||||
normal_col INT
|
||||
);
|
||||
|
||||
DENY SELECT ON `a"b\c`.* TO u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
DENY INSERT ON `a"b\c`.`t"1` TO u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
DENY UPDATE(`col"x`) ON `a"b\c`.`t"1` TO u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
--echo # Verify SHOW GRANTS round-trips the special names
|
||||
SHOW GRANTS FOR u;
|
||||
|
||||
--echo # Verify REVOKE works with the special names
|
||||
REVOKE DENY UPDATE(`col"x`) ON `a"b\c`.`t"1` FROM u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
REVOKE DENY INSERT ON `a"b\c`.`t"1` FROM u;
|
||||
REVOKE DENY SELECT ON `a"b\c`.* FROM u;
|
||||
EXECUTE show_denies;
|
||||
|
||||
DROP TABLE `a"b\c`.`t"1`;
|
||||
DROP DATABASE `a"b\c`;
|
||||
|
||||
DEALLOCATE PREPARE show_denies;
|
||||
DROP USER u;
|
||||
DROP DATABASE d;
|
||||
DROP TABLE sensitive_data;
|
||||
43
mysql-test/main/deny_use_db.result
Normal file
43
mysql-test/main/deny_use_db.result
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# check_grant_db with DENY-only entries
|
||||
#
|
||||
CREATE DATABASE db1;
|
||||
CREATE TABLE db1.t1 (c1 INT, c2 INT);
|
||||
CREATE USER u1@localhost;
|
||||
DENY INSERT ON db1.t1 TO u1@localhost;
|
||||
connect con1, localhost, u1,,;
|
||||
USE db1;
|
||||
ERROR 42000: Access denied for user 'u1'@'localhost' to database 'db1'
|
||||
connection default;
|
||||
GRANT SELECT (c1) ON db1.t1 TO u1@localhost;
|
||||
connection con1;
|
||||
USE db1;
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u1@localhost;
|
||||
#
|
||||
# global DENY ALL prevents USE, even with table grants
|
||||
#
|
||||
CREATE USER u2@localhost;
|
||||
GRANT SELECT ON db1.t1 TO u2@localhost;
|
||||
DENY ALL PRIVILEGES ON *.* TO u2@localhost;
|
||||
connect con1, localhost, u2,,;
|
||||
USE db1;
|
||||
ERROR 42000: Access denied for user 'u2'@'localhost' to database 'db1'
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u2@localhost;
|
||||
#
|
||||
# db-level DENY ALL prevents USE, even with table grants
|
||||
#
|
||||
CREATE USER u3@localhost;
|
||||
GRANT SELECT ON db1.t1 TO u3@localhost;
|
||||
DENY ALL PRIVILEGES ON db1.* TO u3@localhost;
|
||||
connect con1, localhost, u3,,;
|
||||
USE db1;
|
||||
ERROR 42000: Access denied for user 'u3'@'localhost' to database 'db1'
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u3@localhost;
|
||||
DROP TABLE db1.t1;
|
||||
DROP DATABASE db1;
|
||||
63
mysql-test/main/deny_use_db.test
Normal file
63
mysql-test/main/deny_use_db.test
Normal file
@@ -0,0 +1,63 @@
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # check_grant_db with DENY-only entries
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE db1;
|
||||
CREATE TABLE db1.t1 (c1 INT, c2 INT);
|
||||
|
||||
CREATE USER u1@localhost;
|
||||
DENY INSERT ON db1.t1 TO u1@localhost;
|
||||
|
||||
connect (con1, localhost, u1,,);
|
||||
|
||||
# Deny-only entries should not satisfy check_grant_db().
|
||||
--error ER_DBACCESS_DENIED_ERROR
|
||||
USE db1;
|
||||
|
||||
connection default;
|
||||
GRANT SELECT (c1) ON db1.t1 TO u1@localhost;
|
||||
|
||||
connection con1;
|
||||
# Column-level grant allows USE.
|
||||
USE db1;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
DROP USER u1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # global DENY ALL prevents USE, even with table grants
|
||||
--echo #
|
||||
|
||||
CREATE USER u2@localhost;
|
||||
GRANT SELECT ON db1.t1 TO u2@localhost;
|
||||
DENY ALL PRIVILEGES ON *.* TO u2@localhost;
|
||||
|
||||
connect (con1, localhost, u2,,);
|
||||
--error ER_DBACCESS_DENIED_ERROR
|
||||
USE db1;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u2@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # db-level DENY ALL prevents USE, even with table grants
|
||||
--echo #
|
||||
|
||||
CREATE USER u3@localhost;
|
||||
GRANT SELECT ON db1.t1 TO u3@localhost;
|
||||
DENY ALL PRIVILEGES ON db1.* TO u3@localhost;
|
||||
|
||||
connect (con1, localhost, u3,,);
|
||||
--error ER_DBACCESS_DENIED_ERROR
|
||||
USE db1;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER u3@localhost;
|
||||
DROP TABLE db1.t1;
|
||||
DROP DATABASE db1;
|
||||
@@ -191,17 +191,17 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR
|
||||
FROM performance_schema.events_statements_summary_by_digest
|
||||
ORDER BY DIGEST_TEXT;
|
||||
SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR
|
||||
test 7f807b8cf301913b61deb32c6cab1e1b EXPLAIN SELECT * FROM `test` . `v1` 1
|
||||
test e17dbf6fd40651ae8bd34f6a3e8ef24e EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1
|
||||
test 602c8a82b325449790d331768979c6b9 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1
|
||||
test e261dc01764c5f2708df66fa22884459 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1
|
||||
test d63272115b72b81871327666eaeea38b EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1
|
||||
test 2885c2680299873f350feba04eeafaf8 SELECT * FROM `test` . `v1` 1
|
||||
test 311ba3c50a8a7360e6667ad134607fab SELECT * FROM `test` . `v1` WHERE `a` = ? 1
|
||||
test 5587d23d7fa7acabd8e15b0b9526a3c9 SELECT * FROM `test` . `v1` WHERE `b` > ? 1
|
||||
test dd24f2a9de5abbd2f9e8db1d5eaf615c SELECT `a` , `b` FROM `test` . `v1` 1
|
||||
test f15dd457d598d7befe8cf8047bed0927 SELECT `b` , `a` FROM `test` . `v1` 1
|
||||
test 750d4101ef2bcc9061debad4690a80d9 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1
|
||||
test 6f321f4e40122b391c5f21aa427ed78f EXPLAIN SELECT * FROM `test` . `v1` 1
|
||||
test 28dad445d0e04be3fd88734d6b5092d1 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1
|
||||
test 23f674bf310451decac56222b65e8970 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1
|
||||
test 0f1961b7d219d57f146da8fde77d2a81 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1
|
||||
test b1515277e9f6c1edbed0289707048f13 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1
|
||||
test 9260e4a28f4b5613948ed2c3adb3ed3d SELECT * FROM `test` . `v1` 1
|
||||
test 8a2f81fd93e3244896a9b1e48f4bbd7e SELECT * FROM `test` . `v1` WHERE `a` = ? 1
|
||||
test c49d3c36f8f9c96678a9076399b55a9f SELECT * FROM `test` . `v1` WHERE `b` > ? 1
|
||||
test 425ddae2c8b389172ba32cdbc3caa8fa SELECT `a` , `b` FROM `test` . `v1` 1
|
||||
test 8b843c81f1f063fe9560fd61e921418e SELECT `b` , `a` FROM `test` . `v1` 1
|
||||
test ee83a5ec5cb9651bffe18ae1e3a5315d TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1
|
||||
DROP TABLE test.v1;
|
||||
CREATE VIEW test.v1 AS SELECT * FROM test.t1;
|
||||
EXPLAIN SELECT * from test.v1;
|
||||
@@ -248,19 +248,19 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR
|
||||
FROM performance_schema.events_statements_summary_by_digest
|
||||
ORDER BY DIGEST_TEXT;
|
||||
SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR
|
||||
test 2977c8beffabf7bebac017c7b95aefe3 CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1
|
||||
test fd8390bb0d24a48e871d95b5b0758269 DROP TABLE `test` . `v1` 1
|
||||
test 7f807b8cf301913b61deb32c6cab1e1b EXPLAIN SELECT * FROM `test` . `v1` 2
|
||||
test e17dbf6fd40651ae8bd34f6a3e8ef24e EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2
|
||||
test 602c8a82b325449790d331768979c6b9 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2
|
||||
test e261dc01764c5f2708df66fa22884459 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2
|
||||
test d63272115b72b81871327666eaeea38b EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2
|
||||
test 2885c2680299873f350feba04eeafaf8 SELECT * FROM `test` . `v1` 2
|
||||
test 311ba3c50a8a7360e6667ad134607fab SELECT * FROM `test` . `v1` WHERE `a` = ? 2
|
||||
test 5587d23d7fa7acabd8e15b0b9526a3c9 SELECT * FROM `test` . `v1` WHERE `b` > ? 2
|
||||
test d885cf933b5d3317333a02003dee7b48 SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1
|
||||
test dd24f2a9de5abbd2f9e8db1d5eaf615c SELECT `a` , `b` FROM `test` . `v1` 2
|
||||
test f15dd457d598d7befe8cf8047bed0927 SELECT `b` , `a` FROM `test` . `v1` 2
|
||||
test 750d4101ef2bcc9061debad4690a80d9 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1
|
||||
test 784ad71c451db220c8b53cd84d696252 CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1
|
||||
test 3a6acea315a53efa1c8f8786622ea867 DROP TABLE `test` . `v1` 1
|
||||
test 6f321f4e40122b391c5f21aa427ed78f EXPLAIN SELECT * FROM `test` . `v1` 2
|
||||
test 28dad445d0e04be3fd88734d6b5092d1 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2
|
||||
test 23f674bf310451decac56222b65e8970 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2
|
||||
test 0f1961b7d219d57f146da8fde77d2a81 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2
|
||||
test b1515277e9f6c1edbed0289707048f13 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2
|
||||
test 9260e4a28f4b5613948ed2c3adb3ed3d SELECT * FROM `test` . `v1` 2
|
||||
test 8a2f81fd93e3244896a9b1e48f4bbd7e SELECT * FROM `test` . `v1` WHERE `a` = ? 2
|
||||
test c49d3c36f8f9c96678a9076399b55a9f SELECT * FROM `test` . `v1` WHERE `b` > ? 2
|
||||
test 12e528310fc145b4a866d8fbaac5e519 SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1
|
||||
test 425ddae2c8b389172ba32cdbc3caa8fa SELECT `a` , `b` FROM `test` . `v1` 2
|
||||
test 8b843c81f1f063fe9560fd61e921418e SELECT `b` , `a` FROM `test` . `v1` 2
|
||||
test ee83a5ec5cb9651bffe18ae1e3a5315d TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1
|
||||
DROP VIEW test.v1;
|
||||
DROP TABLE test.t1;
|
||||
|
||||
@@ -8,5 +8,5 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1
|
||||
####################################
|
||||
SELECT event_name, digest, digest_text, sql_text FROM events_statements_history_long;
|
||||
event_name digest digest_text sql_text
|
||||
statement/sql/select bc85fb4e8188bed1c842f764ec9fb06a SELECT ? + ? + SELECT ...
|
||||
statement/sql/truncate 208418d9203df0b1b2cadb4d7196ea77 TRUNCATE TABLE truncat...
|
||||
statement/sql/select 2490fb0602b2ad29d2adc5923c6be917 SELECT ? + ? + SELECT ...
|
||||
statement/sql/truncate 8460b8b5a83d4357fcb94a1ccbb54817 TRUNCATE TABLE truncat...
|
||||
|
||||
61
mysql-test/suite/rpl/r/rpl_deny.result
Normal file
61
mysql-test/suite/rpl/r/rpl_deny.result
Normal file
@@ -0,0 +1,61 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
connection master;
|
||||
CREATE USER 'u'@'localhost';
|
||||
GRANT SELECT, INSERT, UPDATE ON test.* TO 'u'@'localhost';
|
||||
connection slave;
|
||||
# Verify baseline GRANT replicated
|
||||
connection slave;
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
GRANT SELECT, INSERT, UPDATE ON `test`.* TO `u`@`localhost`
|
||||
# DENY SELECT and verify replication
|
||||
connection master;
|
||||
DENY SELECT ON test.* TO 'u'@'localhost';
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
GRANT SELECT, INSERT, UPDATE ON `test`.* TO `u`@`localhost`
|
||||
DENY SELECT ON `test`.* TO `u`@`localhost`
|
||||
connection slave;
|
||||
connection slave;
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
GRANT SELECT, INSERT, UPDATE ON `test`.* TO `u`@`localhost`
|
||||
DENY SELECT ON `test`.* TO `u`@`localhost`
|
||||
# DENY INSERT and verify replication
|
||||
connection master;
|
||||
DENY INSERT ON test.* TO 'u'@'localhost';
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
GRANT SELECT, INSERT, UPDATE ON `test`.* TO `u`@`localhost`
|
||||
DENY SELECT, INSERT ON `test`.* TO `u`@`localhost`
|
||||
connection slave;
|
||||
connection slave;
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
GRANT SELECT, INSERT, UPDATE ON `test`.* TO `u`@`localhost`
|
||||
DENY SELECT, INSERT ON `test`.* TO `u`@`localhost`
|
||||
# REVOKE DENY SELECT and verify replication
|
||||
connection master;
|
||||
REVOKE DENY SELECT ON test.* FROM 'u'@'localhost';
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
GRANT SELECT, INSERT, UPDATE ON `test`.* TO `u`@`localhost`
|
||||
DENY INSERT ON `test`.* TO `u`@`localhost`
|
||||
connection slave;
|
||||
connection slave;
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
Grants for u@localhost
|
||||
GRANT USAGE ON *.* TO `u`@`localhost`
|
||||
GRANT SELECT, INSERT, UPDATE ON `test`.* TO `u`@`localhost`
|
||||
DENY INSERT ON `test`.* TO `u`@`localhost`
|
||||
connection master;
|
||||
DROP USER 'u'@'localhost';
|
||||
connection slave;
|
||||
include/rpl_end.inc
|
||||
49
mysql-test/suite/rpl/t/rpl_deny.test
Normal file
49
mysql-test/suite/rpl/t/rpl_deny.test
Normal file
@@ -0,0 +1,49 @@
|
||||
#
|
||||
# Verify that DENY statements are replicated correctly to the slave.
|
||||
#
|
||||
|
||||
--source include/not_embedded.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
connection master;
|
||||
CREATE USER 'u'@'localhost';
|
||||
GRANT SELECT, INSERT, UPDATE ON test.* TO 'u'@'localhost';
|
||||
sync_slave_with_master;
|
||||
|
||||
--echo # Verify baseline GRANT replicated
|
||||
connection slave;
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
|
||||
--echo # DENY SELECT and verify replication
|
||||
connection master;
|
||||
DENY SELECT ON test.* TO 'u'@'localhost';
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
sync_slave_with_master;
|
||||
|
||||
connection slave;
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
|
||||
--echo # DENY INSERT and verify replication
|
||||
connection master;
|
||||
DENY INSERT ON test.* TO 'u'@'localhost';
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
sync_slave_with_master;
|
||||
|
||||
connection slave;
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
|
||||
--echo # REVOKE DENY SELECT and verify replication
|
||||
connection master;
|
||||
REVOKE DENY SELECT ON test.* FROM 'u'@'localhost';
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
sync_slave_with_master;
|
||||
|
||||
connection slave;
|
||||
SHOW GRANTS FOR 'u'@'localhost';
|
||||
|
||||
# Cleanup
|
||||
connection master;
|
||||
DROP USER 'u'@'localhost';
|
||||
sync_slave_with_master;
|
||||
|
||||
--source include/rpl_end.inc
|
||||
@@ -104,8 +104,8 @@ static int prepare_for_fill(TABLE_LIST *tables)
|
||||
thd->real_id= pthread_self();
|
||||
thd->db= null_clex_str;
|
||||
thd->security_ctx->host_or_ip= "";
|
||||
thd->security_ctx->db_access= DB_ACLS;
|
||||
thd->security_ctx->master_access= ALL_KNOWN_ACL;
|
||||
thd->security_ctx->db_access= access_t(DB_ACLS);
|
||||
thd->security_ctx->master_access= access_t(ALL_KNOWN_ACL);
|
||||
bzero((char*) &thd->net, sizeof(thd->net));
|
||||
lex_start(thd);
|
||||
thd->lex->init_select();
|
||||
|
||||
@@ -30,7 +30,7 @@ static int index_stats_fill(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
tmp_table.db.length= strlen(index_stats->index);
|
||||
tmp_table.table_name.str= index_stats->index + tmp_table.db.length + 1;
|
||||
tmp_table.table_name.length= strlen(tmp_table.table_name.str);
|
||||
tmp_table.grant.privilege= NO_ACL;
|
||||
tmp_table.grant.privilege= access_t(NO_ACL);
|
||||
if (check_access(thd, SELECT_ACL, tmp_table.db.str,
|
||||
&tmp_table.grant.privilege, NULL, 0, 1) ||
|
||||
check_grant(thd, SELECT_ACL, &tmp_table, 1, 1, 1))
|
||||
|
||||
@@ -43,7 +43,7 @@ static int table_stats_fill(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
tmp_table.db.length= schema_length;
|
||||
tmp_table.table_name.str= end_of_schema+1;
|
||||
tmp_table.table_name.length= table_name_length;
|
||||
tmp_table.grant.privilege= NO_ACL;
|
||||
tmp_table.grant.privilege= access_t(NO_ACL);
|
||||
if (check_access(thd, SELECT_ACL, tmp_table.db.str,
|
||||
&tmp_table.grant.privilege, NULL, 0, 1) ||
|
||||
check_grant(thd, SELECT_ACL, &tmp_table, 1, 1, 1))
|
||||
|
||||
@@ -1496,8 +1496,8 @@ end:
|
||||
Temporarily reset it to read-write.
|
||||
*/
|
||||
|
||||
privilege_t saved_master_access(thd->security_ctx->master_access);
|
||||
thd->security_ctx->master_access |= PRIV_IGNORE_READ_ONLY;
|
||||
access_t saved_master_access(thd->security_ctx->master_access);
|
||||
thd->security_ctx->master_access.force_allow(PRIV_IGNORE_READ_ONLY, true);
|
||||
bool save_tx_read_only= thd->tx_read_only;
|
||||
thd->tx_read_only= false;
|
||||
|
||||
|
||||
@@ -179,8 +179,8 @@ pre_init_event_thread(THD* thd)
|
||||
|
||||
set_current_thd(thd);
|
||||
thd->client_capabilities= 0;
|
||||
thd->security_ctx->master_access= NO_ACL;
|
||||
thd->security_ctx->db_access= NO_ACL;
|
||||
thd->security_ctx->master_access= access_t(NO_ACL);
|
||||
thd->security_ctx->db_access= access_t(NO_ACL);
|
||||
thd->security_ctx->host_or_ip= (char*)my_localhost;
|
||||
my_net_init(&thd->net, NULL, thd, MYF(MY_THREAD_SPECIFIC));
|
||||
thd->security_ctx->set_user((char*)"event_scheduler");
|
||||
@@ -415,7 +415,7 @@ Event_scheduler::start(int *err_no)
|
||||
|
||||
Same goes for transaction access mode. Set it to read-write for this thd.
|
||||
*/
|
||||
new_thd->security_ctx->master_access |= PRIV_IGNORE_READ_ONLY;
|
||||
new_thd->security_ctx->master_access.force_allow(PRIV_IGNORE_READ_ONLY);
|
||||
new_thd->variables.tx_read_only= false;
|
||||
new_thd->tx_read_only= false;
|
||||
|
||||
|
||||
@@ -1173,8 +1173,8 @@ Events::load_events_from_db(THD *thd)
|
||||
Temporarily reset it to read-write.
|
||||
*/
|
||||
|
||||
privilege_t saved_master_access(thd->security_ctx->master_access);
|
||||
thd->security_ctx->master_access |= PRIV_IGNORE_READ_ONLY;
|
||||
access_t saved_master_access(thd->security_ctx->master_access);
|
||||
thd->security_ctx->master_access.force_allow(PRIV_IGNORE_READ_ONLY, true);
|
||||
bool save_tx_read_only= thd->tx_read_only;
|
||||
thd->tx_read_only= false;
|
||||
|
||||
|
||||
@@ -923,7 +923,7 @@ TABLE *create_table_for_function(THD *thd, TABLE_LIST *sql_table)
|
||||
table->next= thd->derived_tables;
|
||||
thd->derived_tables= table;
|
||||
table->s->tmp_table= INTERNAL_TMP_TABLE;
|
||||
table->grant.privilege= SELECT_ACL;
|
||||
table->grant.privilege= access_t(SELECT_ACL);
|
||||
|
||||
sql_table->table= table;
|
||||
|
||||
|
||||
@@ -188,6 +188,7 @@ SYMBOL symbols[] = {
|
||||
{ "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM)},
|
||||
{ "DELETE", SYM(DELETE_SYM)},
|
||||
{ "DELETE_DOMAIN_ID", SYM(DELETE_DOMAIN_ID_SYM)},
|
||||
{ "DENY", SYM(DENY)},
|
||||
{ "DESC", SYM(DESC)},
|
||||
{ "DESCRIBE", SYM(DESCRIBE)},
|
||||
{ "DETERMINISTIC", SYM(DETERMINISTIC_SYM)},
|
||||
|
||||
186
sql/privilege.h
186
sql/privilege.h
@@ -17,7 +17,7 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
#include "my_global.h" // ulonglong
|
||||
|
||||
#include "my_bit.h" //my_bit_log2_uint64
|
||||
|
||||
/*
|
||||
A strict enum to store privilege bits.
|
||||
@@ -670,6 +670,190 @@ constexpr privilege_t PRIV_STMT_SHOW_ENGINE_MUTEX= PROCESS_ACL;
|
||||
constexpr privilege_t PRIV_STMT_SHOW_PROCESSLIST= PROCESS_ACL;
|
||||
|
||||
|
||||
/*
|
||||
access_t represents effective privileges at a given scope.
|
||||
|
||||
It bundles:
|
||||
- allow bits (positive grants at this scope)
|
||||
- deny bits (explicit DENY at this scope)
|
||||
- deny_subtree (summary of DENY from lower scopes, used for fast checks)
|
||||
|
||||
access_t is what privilege checks cache and combine (roles, parents, etc.)
|
||||
to decide whether a requested privilege is allowed, denied, or unknown.
|
||||
*/
|
||||
class access_t
|
||||
{
|
||||
private:
|
||||
privilege_t m_allow_bits;
|
||||
privilege_t m_deny_bits;
|
||||
privilege_t m_deny_subtree;
|
||||
|
||||
public:
|
||||
explicit access_t(privilege_t allow, privilege_t deny= NO_ACL,
|
||||
privilege_t deny_subtree= NO_ACL)
|
||||
: m_allow_bits(allow), m_deny_bits(deny), m_deny_subtree(deny_subtree)
|
||||
{
|
||||
}
|
||||
/* True if no allow/deny information is present. */
|
||||
bool is_empty() const
|
||||
{
|
||||
return m_allow_bits == NO_ACL && m_deny_bits == NO_ACL &&
|
||||
m_deny_subtree == NO_ACL;
|
||||
}
|
||||
void set_deny_bits(privilege_t deny) { m_deny_bits= deny; }
|
||||
/* Set explicit denies and subtree denies in one shot. */
|
||||
void set_deny(privilege_t deny, privilege_t deny_subtree)
|
||||
{
|
||||
m_deny_bits= deny;
|
||||
m_deny_subtree= deny_subtree;
|
||||
}
|
||||
/* Set subtree deny summary (denies from lower scopes). */
|
||||
void set_deny_subtree(privilege_t deny_subtree)
|
||||
{
|
||||
m_deny_subtree= deny_subtree;
|
||||
}
|
||||
/* Replace allow bits at this scope. */
|
||||
void set_allow_bits(privilege_t allow)
|
||||
{
|
||||
m_allow_bits= allow;
|
||||
}
|
||||
|
||||
/* Force allow bits; optionally clear matching denies at this scope. */
|
||||
void force_allow(privilege_t bits, bool overwrite_deny=false)
|
||||
{
|
||||
m_allow_bits|= bits;
|
||||
if (overwrite_deny)
|
||||
m_deny_bits&= ~bits ;
|
||||
}
|
||||
|
||||
/*
|
||||
Disallow implicit conversions from privilege
|
||||
(potential source of bugs)
|
||||
*/
|
||||
access_t &operator=(const privilege_t &)= delete;
|
||||
|
||||
/*
|
||||
Merge another access_t into this one (bitwise OR of all components).
|
||||
Used for: accumulating privileges from multiple roles, or from PUBLIC +
|
||||
user, etc.
|
||||
*/
|
||||
access_t &merge_same_level(const access_t &other)
|
||||
{
|
||||
m_allow_bits= privilege_t(m_allow_bits | other.m_allow_bits);
|
||||
m_deny_bits= privilege_t(m_deny_bits | other.m_deny_bits);
|
||||
m_deny_subtree= privilege_t(m_deny_subtree | other.m_deny_subtree);
|
||||
return *this;
|
||||
}
|
||||
|
||||
access_t &operator|=(const access_t &)= delete;
|
||||
|
||||
/*
|
||||
Intersect allow bits; keep union of denies and subtree denies.
|
||||
Used for: intersecting access from db and host.
|
||||
*/
|
||||
access_t intersect(const access_t &other) const
|
||||
{
|
||||
return access_t((privilege_t) (m_allow_bits & other.m_allow_bits),
|
||||
(privilege_t) (m_deny_bits | other.m_deny_bits),
|
||||
(privilege_t) (m_deny_subtree | other.m_deny_subtree));
|
||||
}
|
||||
|
||||
/*
|
||||
Combine child-level access with parent-level access (vertical hierarchy).
|
||||
Used for: global -> database -> table -> column traversal
|
||||
|
||||
Rules:
|
||||
- Allow bits accumulate (union), but an explicit deny always wins over an allow.
|
||||
- Deny bits accumulate (once denied at any scope, always denied).
|
||||
- deny_subtree is taken from *this* (the child), not from the parent.
|
||||
The difference between this and merge_same_level() is the handling of
|
||||
deny_subtree. merge_same_level() is for same-level access for user+role+PUBLIC,
|
||||
while this one is hierarchical, used when going from global to db etc until
|
||||
column level. If merged correctly, on the "leaf level" of hierarchy,
|
||||
the deny_subtree should always be zero.
|
||||
*/
|
||||
access_t &merge_with_parent(const access_t &parent)
|
||||
{
|
||||
m_allow_bits= privilege_t(m_allow_bits | parent.m_allow_bits);
|
||||
m_deny_bits= privilege_t(m_deny_bits | parent.m_deny_bits);
|
||||
/* Keep current deny_subtree (child scope). */
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const access_t &x, const access_t &y)
|
||||
{
|
||||
return x.m_allow_bits == y.m_allow_bits &&
|
||||
x.m_deny_bits == y.m_deny_bits &&
|
||||
x.m_deny_subtree == y.m_deny_subtree;
|
||||
}
|
||||
friend bool operator!=(const access_t &x, const access_t &y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
/* Bitwise OR merge is intentionally avoided for access_t. */
|
||||
|
||||
/* Return bits that are granted and not denied here or below. */
|
||||
privilege_t certainly_allowed(privilege_t priv) const
|
||||
{
|
||||
return (privilege_t) (priv & m_allow_bits & ~m_deny_bits &
|
||||
~m_deny_subtree);
|
||||
}
|
||||
|
||||
/* Used for quick checks in USE db / SHOW */
|
||||
privilege_t maybe_allowed(privilege_t priv) const
|
||||
{
|
||||
return (privilege_t) (priv & m_allow_bits & ~m_deny_bits);
|
||||
}
|
||||
|
||||
/*
|
||||
Intersect with a privilege mask.
|
||||
deny bits are "sticky", i.e. won't be cleared by
|
||||
frequently used "priv &=~ access" patterns
|
||||
*/
|
||||
friend privilege_t operator&(const access_t &x, const privilege_t &y)
|
||||
{
|
||||
return x.certainly_allowed(y);
|
||||
}
|
||||
|
||||
/*
|
||||
Complement of certainly_allowed across all known privilege bits.
|
||||
Used in popular "want_privilege &=~ access" pattern to clear known
|
||||
allowed bits.
|
||||
*/
|
||||
ulonglong operator~() const { return ~certainly_allowed(ALL_KNOWN_ACL); };
|
||||
|
||||
/* Return bits that are requested and denied. */
|
||||
privilege_t denied_privs(privilege_t priv) const
|
||||
{
|
||||
return (privilege_t) (m_deny_bits & priv);
|
||||
}
|
||||
|
||||
/* Raw accessors. */
|
||||
privilege_t allow_bits() const { return m_allow_bits; }
|
||||
privilege_t deny_bits() const { return m_deny_bits; }
|
||||
privilege_t deny_subtree() const { return m_deny_subtree; }
|
||||
};
|
||||
|
||||
inline access_t merge_same_level(const access_t& first, const access_t& second)
|
||||
{
|
||||
access_t res(first);
|
||||
return res.merge_same_level(second);
|
||||
}
|
||||
|
||||
inline access_t merge_same_level(const access_t &first, const access_t &second,
|
||||
const access_t& third)
|
||||
{
|
||||
return merge_same_level(first, merge_same_level(second,third));
|
||||
}
|
||||
|
||||
inline access_t merge_with_parent(const access_t &child, const access_t &parent)
|
||||
{
|
||||
access_t res(child);
|
||||
res.merge_with_parent(parent);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Defines to change the above bits to how things are stored in tables
|
||||
This is needed as the 'host' and 'db' table is missing a few privileges
|
||||
|
||||
@@ -387,7 +387,7 @@ public:
|
||||
class set_var_role: public set_var_base
|
||||
{
|
||||
LEX_CSTRING role;
|
||||
privilege_t access;
|
||||
access_t access;
|
||||
public:
|
||||
set_var_role(LEX_CSTRING role_arg) : role(role_arg), access(NO_ACL) {}
|
||||
int check(THD *thd) override;
|
||||
|
||||
@@ -6928,12 +6928,12 @@ ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR
|
||||
spa "No puedo cargar valor desde fichero/archivo con filas de tamaño fijo en variable"
|
||||
sw "Haiwezi kupakia thamani kutoka kwa faili iliyo na safu za saizi maalum hadi kutofautisha"
|
||||
ER_CANT_CREATE_USER_WITH_GRANT 42000
|
||||
chi "您不允许使用创建用户时给予GRANT"
|
||||
eng "You are not allowed to create a user with GRANT"
|
||||
ger "Sie dürfen keinen Benutzer mit GRANT anlegen"
|
||||
geo "GRANT-ით მომხმარებლის შექმნის უფლება არ გაქვთ"
|
||||
spa "No está autorizado a crear un usuario con GRANT"
|
||||
sw "Hauruhusiwi kuunda mtumiaji na GRANT"
|
||||
chi "您不允许使用创建用户时给予%s"
|
||||
eng "You are not allowed to create a user with %s"
|
||||
ger "Sie dürfen keinen Benutzer mit %s anlegen"
|
||||
geo "%s-ით მომხმარებლის შექმნის უფლება არ გაქვთ"
|
||||
spa "No está autorizado a crear un usuario con %s"
|
||||
sw "Hauruhusiwi kuunda mtumiaji na %s"
|
||||
ER_WRONG_VALUE_FOR_TYPE
|
||||
chi "不正确的%-.32s值:'%-.128sT' 函数:%-.32s"
|
||||
eng "Incorrect %-.32s value: '%-.128sT' for function %-.32s"
|
||||
|
||||
@@ -2983,15 +2983,12 @@ bool check_db_routine_access(THD *thd, privilege_t privilege,
|
||||
const Sp_handler *sph,
|
||||
bool no_errors)
|
||||
{
|
||||
privilege_t db_priv;
|
||||
access_t db_priv(NO_ACL);
|
||||
if (check_access(thd, privilege, db,
|
||||
&db_priv, NULL, 0, no_errors))
|
||||
return 1;
|
||||
if ((db_priv & privilege) == privilege)
|
||||
return 0;
|
||||
|
||||
return check_routine_level_acl(thd, (privilege & ~db_priv),
|
||||
db, name, sph);
|
||||
return check_routine_level_acl(thd, privilege,
|
||||
db, name, sph, db_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
2744
sql/sql_acl.cc
2744
sql/sql_acl.cc
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,19 @@ enum mysql_db_table_field
|
||||
MYSQL_DB_FIELD_COUNT
|
||||
};
|
||||
|
||||
enum ACL_PRIV_TYPE
|
||||
{
|
||||
PRIV_TYPE_GLOBAL,
|
||||
PRIV_TYPE_DB,
|
||||
PRIV_TYPE_TABLE,
|
||||
PRIV_TYPE_COLUMN,
|
||||
PRIV_TYPE_FUNCTION,
|
||||
PRIV_TYPE_PROCEDURE,
|
||||
PRIV_TYPE_PACKAGE,
|
||||
PRIV_TYPE_PACKAGE_BODY,
|
||||
PRIV_TYPE_MAX
|
||||
};
|
||||
|
||||
extern const TABLE_FIELD_DEF mysql_db_table_def;
|
||||
|
||||
extern LEX_CSTRING host_not_specified;
|
||||
@@ -77,7 +90,7 @@ bool hostname_requires_resolving(const char *hostname);
|
||||
bool acl_init(bool dont_read_acl_tables);
|
||||
bool acl_reload(THD *thd);
|
||||
void acl_free(bool end=0);
|
||||
privilege_t acl_get_all3(Security_context *sctx, const char *db,
|
||||
access_t acl_get_all3(Security_context *sctx, const char *db,
|
||||
bool db_is_patern);
|
||||
bool acl_authenticate(THD *thd, uint com_change_user_pkt_len);
|
||||
bool acl_getroot(Security_context *sctx,
|
||||
@@ -90,10 +103,10 @@ bool change_password(THD *thd, LEX_USER *user);
|
||||
bool mysql_grant_role(THD *thd, List<LEX_USER> &user_list, bool revoke);
|
||||
int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
|
||||
List <LEX_COLUMN> &column_list, privilege_t rights,
|
||||
bool revoke);
|
||||
bool revoke, bool is_deny);
|
||||
bool mysql_routine_grant(THD *thd, TABLE_LIST *table, const Sp_handler *sph,
|
||||
List <LEX_USER> &user_list, privilege_t rights,
|
||||
bool revoke, bool write_to_binlog);
|
||||
bool revoke, bool write_to_binlog, bool deny);
|
||||
bool grant_init();
|
||||
void grant_free(void);
|
||||
bool grant_reload(THD *thd);
|
||||
@@ -110,18 +123,18 @@ bool check_grant_all_columns(THD *thd, privilege_t want_access,
|
||||
bool check_grant_routine(THD *thd, privilege_t want_access,
|
||||
TABLE_LIST *procs, const Sp_handler *sph,
|
||||
bool no_error);
|
||||
bool check_grant_db(THD *thd,const char *db);
|
||||
bool check_grant_db(THD *thd,const access_t& priv, const char *db);
|
||||
bool check_global_access(THD *thd, const privilege_t want_access, bool no_errors= false);
|
||||
bool check_access(THD *thd, privilege_t want_access,
|
||||
const char *db, privilege_t *save_priv,
|
||||
const char *db, access_t *save_priv,
|
||||
GRANT_INTERNAL_INFO *grant_internal_info,
|
||||
bool dont_check_global_grants, bool no_errors);
|
||||
privilege_t get_table_grant(THD *thd, TABLE_LIST *table);
|
||||
privilege_t get_column_grant(THD *thd, GRANT_INFO *grant,
|
||||
access_t get_table_grant(THD *thd, TABLE_LIST *table);
|
||||
access_t get_column_grant(THD *thd, GRANT_INFO *grant,
|
||||
const char *db_name, const char *table_name,
|
||||
const Lex_ident_column &field_name);
|
||||
bool get_show_user(THD *thd, LEX_USER *lex_user, const char **username,
|
||||
const char **hostname, const char **rolename);
|
||||
const char **hostname, const char **rolename, bool *show_denies);
|
||||
void mysql_show_grants_get_fields(THD *thd, List<Item> *fields,
|
||||
const char *name, size_t length);
|
||||
bool mysql_show_grants(THD *thd, LEX_USER *user);
|
||||
@@ -147,7 +160,8 @@ bool sp_grant_privileges(THD *thd,
|
||||
const Sp_handler *sph);
|
||||
bool check_routine_level_acl(THD *thd, privilege_t acl,
|
||||
const char *db, const char *name,
|
||||
const Sp_handler *sph);
|
||||
const Sp_handler *sph,
|
||||
const access_t &db_access);
|
||||
bool is_acl_user(const LEX_CSTRING &host, const LEX_CSTRING &user);
|
||||
int fill_users_schema_table(THD *thd, TABLE_LIST *tables, COND *cond);
|
||||
int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
|
||||
@@ -284,10 +298,10 @@ bool acl_check_proxy_grant_access (THD *thd,
|
||||
const LEX_CSTRING &user,
|
||||
bool with_grant);
|
||||
int acl_setauthorization(THD *thd, const LEX_USER *user);
|
||||
int acl_setrole(THD *thd, const LEX_CSTRING &rolename, privilege_t access);
|
||||
int acl_setrole(THD *thd, const LEX_CSTRING &rolename, const access_t& access);
|
||||
int acl_check_setrole(THD *thd,
|
||||
const LEX_CSTRING &rolename,
|
||||
privilege_t *access);
|
||||
access_t *access);
|
||||
int acl_check_set_default_role(THD *thd,
|
||||
const LEX_CSTRING &host,
|
||||
const LEX_CSTRING &user,
|
||||
@@ -317,6 +331,7 @@ class Sql_cmd_grant: public Sql_cmd
|
||||
{
|
||||
protected:
|
||||
enum_sql_command m_command;
|
||||
bool m_deny;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
void warn_hostname_requires_resolving(THD *thd, List<LEX_USER> &list);
|
||||
bool user_list_reset_mqh(THD *thd, List<LEX_USER> &list);
|
||||
@@ -324,10 +339,11 @@ protected:
|
||||
#endif
|
||||
public:
|
||||
Sql_cmd_grant(enum_sql_command command)
|
||||
:m_command(command)
|
||||
:m_command(command),m_deny(false)
|
||||
{ }
|
||||
bool is_revoke() const { return m_command == SQLCOM_REVOKE; }
|
||||
enum_sql_command sql_command_code() const override { return m_command; }
|
||||
void set_deny() { m_deny= true; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -540,7 +540,7 @@ bool Sql_cmd_alter_table::execute(THD *thd)
|
||||
Table_specification_st create_info(lex->create_info);
|
||||
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||
create_info.alter_info= &alter_info;
|
||||
privilege_t priv(NO_ACL);
|
||||
access_t priv(NO_ACL);
|
||||
privilege_t priv_needed(ALTER_ACL);
|
||||
bool result;
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ static my_bool list_open_tables_callback(void *el, void *a)
|
||||
/* Check if user has SELECT privilege for any column in the table */
|
||||
arg->table_list.db= db;
|
||||
arg->table_list.table_name= Lex_cstring_strlen(table_name);
|
||||
arg->table_list.grant.privilege= NO_ACL;
|
||||
arg->table_list.grant.privilege= access_t(NO_ACL);
|
||||
|
||||
if (check_table_access(arg->thd, SELECT_ACL, &arg->table_list, TRUE, 1, TRUE))
|
||||
return FALSE;
|
||||
|
||||
@@ -4935,10 +4935,10 @@ void Security_context::init()
|
||||
host= user= ip= external_user= 0;
|
||||
host_or_ip= "connecting host";
|
||||
priv_user[0]= priv_host[0]= proxy_user[0]= priv_role[0]= '\0';
|
||||
master_access= NO_ACL;
|
||||
master_access= access_t(NO_ACL);
|
||||
password_expired= false;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
db_access= NO_ACL;
|
||||
db_access= access_t(NO_ACL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4973,7 +4973,7 @@ void Security_context::skip_grants()
|
||||
{
|
||||
/* privileges for the user are unknown everything is allowed */
|
||||
host_or_ip= (char *)"";
|
||||
master_access= ALL_KNOWN_ACL;
|
||||
master_access= access_t(ALL_KNOWN_ACL);
|
||||
*priv_user= *priv_host= '\0';
|
||||
password_expired= false;
|
||||
}
|
||||
|
||||
@@ -2096,8 +2096,8 @@ public:
|
||||
char *external_user;
|
||||
/* points to host if host is available, otherwise points to ip */
|
||||
const char *host_or_ip;
|
||||
privilege_t master_access; /* Global privileges from mysql.user */
|
||||
privilege_t db_access; /* Privileges for current db */
|
||||
access_t master_access; /* Global privileges from mysql.user */
|
||||
access_t db_access; /* Privileges for current db */
|
||||
|
||||
bool password_expired;
|
||||
|
||||
@@ -4320,7 +4320,7 @@ public:
|
||||
update auto-updatable fields (like auto_increment and timestamp).
|
||||
*/
|
||||
query_id_t query_id;
|
||||
privilege_t col_access;
|
||||
access_t col_access{NO_ACL};
|
||||
|
||||
/* Statement id is thread-wide. This counter is used to generate ids */
|
||||
ulong statement_id_counter;
|
||||
|
||||
@@ -60,7 +60,7 @@ static bool find_db_tables_and_rm_known_files(THD *, MY_DIR *,
|
||||
|
||||
long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path);
|
||||
my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error);
|
||||
static void mysql_change_db_impl(THD *, LEX_CSTRING *, privilege_t,
|
||||
static void mysql_change_db_impl(THD *, LEX_CSTRING *, const access_t&,
|
||||
CHARSET_INFO *);
|
||||
static bool mysql_rm_db_internal(THD *thd, const Lex_ident_db &db,
|
||||
bool if_exists, bool silent);
|
||||
@@ -1308,7 +1308,7 @@ exit:
|
||||
if (unlikely(thd->db.str &&
|
||||
cmp_db_names(Lex_ident_db(thd->db), db) && !error))
|
||||
{
|
||||
mysql_change_db_impl(thd, NULL, NO_ACL, thd->variables.collation_server);
|
||||
mysql_change_db_impl(thd, NULL, access_t(NO_ACL), thd->variables.collation_server);
|
||||
thd->session_tracker.current_schema.mark_as_changed(thd);
|
||||
}
|
||||
end:
|
||||
@@ -1563,8 +1563,9 @@ err:
|
||||
@param new_db_charset Character set of the new database.
|
||||
*/
|
||||
|
||||
static void mysql_change_db_impl(THD *thd, LEX_CSTRING *new_db_name,
|
||||
privilege_t new_db_access,
|
||||
static void mysql_change_db_impl(THD *thd,
|
||||
LEX_CSTRING *new_db_name,
|
||||
const access_t& new_db_access,
|
||||
CHARSET_INFO *new_db_charset)
|
||||
{
|
||||
/* 1. Change current database in THD. */
|
||||
@@ -1713,7 +1714,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING &new_db_name, bool force)
|
||||
LEX_CSTRING new_db_file_name;
|
||||
|
||||
Security_context *sctx= thd->security_ctx;
|
||||
privilege_t db_access(sctx->db_access);
|
||||
access_t db_access(sctx->db_access);
|
||||
CHARSET_INFO *db_default_cl;
|
||||
DBUG_ENTER("mysql_change_db");
|
||||
|
||||
@@ -1730,7 +1731,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING &new_db_name, bool force)
|
||||
new_db_name->length == 0.
|
||||
*/
|
||||
|
||||
mysql_change_db_impl(thd, NULL, NO_ACL, thd->variables.collation_server);
|
||||
mysql_change_db_impl(thd, NULL, access_t(NO_ACL), thd->variables.collation_server);
|
||||
|
||||
goto done;
|
||||
}
|
||||
@@ -1747,7 +1748,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING &new_db_name, bool force)
|
||||
{
|
||||
/* Switch the current database to INFORMATION_SCHEMA. */
|
||||
|
||||
mysql_change_db_impl(thd, &INFORMATION_SCHEMA_NAME, SELECT_ACL,
|
||||
mysql_change_db_impl(thd, &INFORMATION_SCHEMA_NAME, access_t(SELECT_ACL),
|
||||
system_charset_info);
|
||||
goto done;
|
||||
}
|
||||
@@ -1771,7 +1772,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING &new_db_name, bool force)
|
||||
if (Lex_ident_db::check_name_with_error(new_db_file_name))
|
||||
{
|
||||
if (force)
|
||||
mysql_change_db_impl(thd, NULL, NO_ACL, thd->variables.collation_server);
|
||||
mysql_change_db_impl(thd, NULL, access_t(NO_ACL), thd->variables.collation_server);
|
||||
|
||||
DBUG_RETURN(ER_WRONG_DB_NAME);
|
||||
}
|
||||
@@ -1781,16 +1782,16 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING &new_db_name, bool force)
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (test_all_bits(sctx->master_access, DB_ACLS))
|
||||
{
|
||||
db_access= DB_ACLS;
|
||||
db_access= access_t(DB_ACLS);
|
||||
}
|
||||
else
|
||||
{
|
||||
db_access= acl_get_all3(sctx, new_db_file_name.str, FALSE);
|
||||
db_access|= sctx->master_access;
|
||||
db_access.merge_with_parent(sctx->master_access);
|
||||
}
|
||||
|
||||
if (!force&& !(db_access & DB_ACLS) &&
|
||||
check_grant_db(thd, new_db_file_name.str))
|
||||
check_grant_db(thd, db_access, new_db_file_name.str))
|
||||
{
|
||||
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
||||
sctx->priv_user,
|
||||
@@ -1816,7 +1817,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING &new_db_name, bool force)
|
||||
|
||||
/* Change db to NULL. */
|
||||
|
||||
mysql_change_db_impl(thd, NULL, NO_ACL, thd->variables.collation_server);
|
||||
mysql_change_db_impl(thd, NULL, access_t(NO_ACL), thd->variables.collation_server);
|
||||
|
||||
/* The operation succeed. */
|
||||
goto done;
|
||||
|
||||
@@ -980,8 +980,8 @@ exit:
|
||||
{
|
||||
DBUG_ASSERT(derived->is_derived());
|
||||
DBUG_ASSERT(derived->is_anonymous_derived_table());
|
||||
table->grant.privilege= SELECT_ACL;
|
||||
derived->grant.privilege= SELECT_ACL;
|
||||
table->grant.privilege= access_t(SELECT_ACL);
|
||||
derived->grant.privilege= access_t(SELECT_ACL);
|
||||
}
|
||||
#endif
|
||||
/* Add new temporary table to list of open derived tables */
|
||||
|
||||
@@ -999,7 +999,7 @@ int bootstrap(MYSQL_FILE *file)
|
||||
thd->bootstrap=1;
|
||||
my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0));
|
||||
thd->max_client_packet_length= thd->net.max_packet;
|
||||
thd->security_ctx->master_access= ALL_KNOWN_ACL;
|
||||
thd->security_ctx->master_access= access_t(ALL_KNOWN_ACL);
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
mysql_thread_set_psi_id(thd->thread_id);
|
||||
@@ -6625,17 +6625,17 @@ wsrep_error_label:
|
||||
|
||||
bool
|
||||
check_access(THD *thd, privilege_t want_access,
|
||||
const char *db, privilege_t *save_priv,
|
||||
const char *db, access_t *save_priv,
|
||||
GRANT_INTERNAL_INFO *grant_internal_info,
|
||||
bool dont_check_global_grants, bool no_errors)
|
||||
{
|
||||
#ifdef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (save_priv)
|
||||
*save_priv= GLOBAL_ACLS;
|
||||
*save_priv= access_t(GLOBAL_ACLS);
|
||||
return false;
|
||||
#else
|
||||
Security_context *sctx= thd->security_ctx;
|
||||
privilege_t db_access(NO_ACL);
|
||||
access_t db_access(NO_ACL);
|
||||
|
||||
/*
|
||||
GRANT command:
|
||||
@@ -6647,19 +6647,19 @@ check_access(THD *thd, privilege_t want_access,
|
||||
set db_is_pattern according to 'dont_check_global_grants' value.
|
||||
*/
|
||||
bool db_is_pattern= ((want_access & GRANT_ACL) && dont_check_global_grants);
|
||||
privilege_t dummy(NO_ACL);
|
||||
access_t dummy(NO_ACL);
|
||||
DBUG_ENTER("check_access");
|
||||
DBUG_PRINT("enter",("db: %s want_access: %llx master_access: %llx",
|
||||
db ? db : "",
|
||||
(longlong) want_access,
|
||||
(longlong) sctx->master_access));
|
||||
db ? db : "",
|
||||
(longlong) want_access,
|
||||
(longlong) sctx->master_access.allow_bits()));
|
||||
|
||||
if (save_priv)
|
||||
*save_priv= NO_ACL;
|
||||
*save_priv= access_t(NO_ACL);
|
||||
else
|
||||
{
|
||||
save_priv= &dummy;
|
||||
dummy= NO_ACL;
|
||||
dummy= access_t(NO_ACL);
|
||||
}
|
||||
|
||||
/* check access may be called twice in a row. Don't change to same stage */
|
||||
@@ -6680,7 +6680,10 @@ check_access(THD *thd, privilege_t want_access,
|
||||
access= get_cached_schema_access(grant_internal_info, db);
|
||||
if (access)
|
||||
{
|
||||
switch (access->check(want_access, save_priv))
|
||||
privilege_t p(save_priv->allow_bits());
|
||||
auto res= access->check(want_access, &p);
|
||||
save_priv->set_allow_bits(p);
|
||||
switch (res)
|
||||
{
|
||||
case ACL_INTERNAL_ACCESS_GRANTED:
|
||||
/*
|
||||
@@ -6731,10 +6734,11 @@ check_access(THD *thd, privilege_t want_access,
|
||||
and the intersection of db- and host-privileges,
|
||||
plus the internal privileges.
|
||||
*/
|
||||
*save_priv|= sctx->master_access | db_access;
|
||||
db_access.merge_with_parent(sctx->master_access);
|
||||
save_priv->merge_same_level(db_access);
|
||||
}
|
||||
else
|
||||
*save_priv|= sctx->master_access;
|
||||
save_priv->merge_same_level(sctx->master_access);
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
if (unlikely(((want_access & ~sctx->master_access) & ~DB_ACLS) ||
|
||||
@@ -6768,21 +6772,30 @@ check_access(THD *thd, privilege_t want_access,
|
||||
else
|
||||
db_access= sctx->db_access;
|
||||
DBUG_PRINT("info",("db_access: %llx want_access: %llx",
|
||||
(longlong) db_access, (longlong) want_access));
|
||||
(longlong) db_access.allow_bits(), (longlong) want_access));
|
||||
|
||||
/*
|
||||
Save the union of User-table and the intersection between Db-table and
|
||||
Host-table privileges, with the already saved internal privileges.
|
||||
*/
|
||||
db_access= (db_access | sctx->master_access);
|
||||
*save_priv|= db_access;
|
||||
db_access.merge_with_parent(sctx->master_access);
|
||||
save_priv->merge_same_level(db_access);
|
||||
|
||||
/*
|
||||
We could check for DENYs here, and do early return, if we find any.
|
||||
But we do not, for the sake of better/more natural error reporting
|
||||
|
||||
ER_TABLEACCESS_DENIED_ERROR and ER_COLUMNACCESS_DENIED_ERROR contain
|
||||
better info.
|
||||
*/
|
||||
|
||||
/*
|
||||
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;
|
||||
(want_access & (TABLE_ACLS | PROC_ACLS |
|
||||
db_access.maybe_allowed(want_access))) == want_access;
|
||||
|
||||
/*
|
||||
Grant access if the requested access is in the intersection of
|
||||
@@ -6918,7 +6931,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
|
||||
not always automatically grant SELECT but use the grant tables.
|
||||
See Bug#38837 need a way to disable information_schema for security
|
||||
*/
|
||||
table->grant.privilege= SELECT_ACL;
|
||||
table->grant.privilege=access_t(SELECT_ACL);
|
||||
|
||||
switch (get_schema_table_idx(table->schema_table)) {
|
||||
case SCH_SCHEMATA:
|
||||
@@ -6939,7 +6952,8 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
|
||||
&thd->col_access, NULL, FALSE, FALSE))
|
||||
return TRUE;
|
||||
|
||||
if (!thd->col_access && check_grant_db(thd, dst_db_name))
|
||||
if (!thd->col_access.maybe_allowed(DB_ACLS | SHOW_DB_ACL) &&
|
||||
check_grant_db(thd, thd->col_access, dst_db_name))
|
||||
{
|
||||
status_var_increment(thd->status_var.access_denied_errors);
|
||||
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
||||
@@ -7108,7 +7122,7 @@ check_routine_access(THD *thd, privilege_t want_access, const LEX_CSTRING *db,
|
||||
*/
|
||||
DBUG_ASSERT((want_access & CREATE_PROC_ACL) == NO_ACL);
|
||||
if ((thd->security_ctx->master_access & want_access) == want_access)
|
||||
tables->grant.privilege= want_access;
|
||||
tables->grant.privilege= access_t(want_access);
|
||||
else if (check_access(thd, want_access, db->str,
|
||||
&tables->grant.privilege,
|
||||
&tables->grant.m_internal,
|
||||
@@ -7135,7 +7149,7 @@ check_routine_access(THD *thd, privilege_t want_access, const LEX_CSTRING *db,
|
||||
bool check_some_routine_access(THD *thd, const char *db, const char *name,
|
||||
const Sp_handler *sph)
|
||||
{
|
||||
privilege_t save_priv(NO_ACL);
|
||||
access_t save_priv(NO_ACL);
|
||||
/*
|
||||
The following test is just a shortcut for check_access() (to avoid
|
||||
calculating db_access)
|
||||
@@ -7148,11 +7162,10 @@ bool check_some_routine_access(THD *thd, const char *db, const char *name,
|
||||
if (thd->security_ctx->master_access & SHOW_PROC_WITHOUT_DEFINITION_ACLS)
|
||||
return FALSE;
|
||||
if (!check_access(thd, SHOW_PROC_WITHOUT_DEFINITION_ACLS,
|
||||
db, &save_priv, NULL, 0, 1) ||
|
||||
(save_priv & SHOW_PROC_WITHOUT_DEFINITION_ACLS))
|
||||
db, &save_priv, NULL, 0, 1))
|
||||
return FALSE;
|
||||
return check_routine_level_acl(thd, SHOW_PROC_WITHOUT_DEFINITION_ACLS,
|
||||
db, name, sph);
|
||||
db, name, sph, save_priv);
|
||||
}
|
||||
|
||||
|
||||
@@ -9519,7 +9532,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
|
||||
if (table->is_jtbm())
|
||||
continue;
|
||||
if (table->derived)
|
||||
table->grant.privilege= SELECT_ACL;
|
||||
table->grant.privilege= access_t(SELECT_ACL);
|
||||
else if ((check_access(thd, UPDATE_ACL, table->db.str,
|
||||
&table->grant.privilege,
|
||||
&table->grant.m_internal,
|
||||
|
||||
@@ -174,7 +174,7 @@ inline bool check_routine_access(THD *thd, privilege_t want_access,
|
||||
{ return false; }
|
||||
inline bool check_some_access(THD *thd, privilege_t want_access, TABLE_LIST *table)
|
||||
{
|
||||
table->grant.privilege= want_access;
|
||||
table->grant.privilege= access_t(want_access);
|
||||
return false;
|
||||
}
|
||||
inline bool check_some_routine_access(THD *thd, const char *db,
|
||||
|
||||
@@ -1969,7 +1969,7 @@ static int mysql_test_show_grants(Prepared_statement *stmt)
|
||||
char buff[1024];
|
||||
const char *username= NULL, *hostname= NULL, *rolename= NULL, *end;
|
||||
|
||||
if (get_show_user(thd, thd->lex->grant_user, &username, &hostname, &rolename))
|
||||
if (get_show_user(thd, thd->lex->grant_user, &username, &hostname, &rolename, NULL))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (username)
|
||||
|
||||
@@ -1244,9 +1244,9 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list,
|
||||
contains any table-specific privilege.
|
||||
*/
|
||||
DBUG_PRINT("debug", ("table_list->grant.privilege: %llx",
|
||||
(longlong) (table_list->grant.privilege)));
|
||||
(longlong) (table_list->grant.privilege.allow_bits())));
|
||||
if (check_some_access(thd, SHOW_CREATE_TABLE_ACLS, table_list) ||
|
||||
(table_list->grant.privilege & SHOW_CREATE_TABLE_ACLS) == NO_ACL)
|
||||
table_list->grant.privilege.maybe_allowed(SHOW_CREATE_TABLE_ACLS) == NO_ACL)
|
||||
{
|
||||
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
|
||||
"SHOW", thd->security_ctx->priv_user,
|
||||
@@ -1449,7 +1449,7 @@ bool mysqld_show_create_db(THD *thd, LEX_CSTRING *dbname,
|
||||
String buffer(buff, sizeof(buff), system_charset_info);
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
Security_context *sctx= thd->security_ctx;
|
||||
privilege_t db_access(NO_ACL);
|
||||
access_t db_access(NO_ACL);
|
||||
#endif
|
||||
Schema_specification_st create;
|
||||
Protocol *protocol=thd->protocol;
|
||||
@@ -1458,12 +1458,14 @@ bool mysqld_show_create_db(THD *thd, LEX_CSTRING *dbname,
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (test_all_bits(sctx->master_access, DB_ACLS))
|
||||
db_access=DB_ACLS;
|
||||
db_access= access_t(DB_ACLS);
|
||||
else
|
||||
db_access= acl_get_all3(sctx, dbname->str, FALSE) |
|
||||
sctx->master_access;
|
||||
{
|
||||
db_access= acl_get_all3(sctx, dbname->str, FALSE);
|
||||
db_access.merge_with_parent(sctx->master_access);
|
||||
}
|
||||
|
||||
if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname->str))
|
||||
if (!(db_access & DB_ACLS) && check_grant_db(thd, db_access, dbname->str))
|
||||
{
|
||||
status_var_increment(thd->status_var.access_denied_errors);
|
||||
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
||||
@@ -5433,9 +5435,11 @@ static privilege_t get_schema_privileges_for_show(THD *thd, TABLE_LIST *tables,
|
||||
if (thd->col_access & need)
|
||||
return thd->col_access & need;
|
||||
|
||||
privilege_t all3= acl_get_all3(thd->security_ctx, tables->db.str, 0);
|
||||
if (all3 & need)
|
||||
return all3 & need;
|
||||
access_t dbacc=
|
||||
merge_with_parent(acl_get_all3(thd->security_ctx, tables->db.str, 0),
|
||||
thd->security_ctx->master_access);
|
||||
if (dbacc & need)
|
||||
return dbacc & need;
|
||||
|
||||
check_grant(thd, need, tables, 0, 1, true);
|
||||
return (on_any_column ? tables->grant.all_privilege()
|
||||
@@ -5635,9 +5639,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
LEX_CSTRING *db_name= db_names.at(i);
|
||||
DBUG_ASSERT(db_name->length <= NAME_LEN);
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
access_t acc= acl_get_all3(sctx, db_name->str, 0).
|
||||
merge_with_parent(sctx->master_access);
|
||||
if (!check_access(thd, SELECT_ACL, db_name->str, &thd->col_access, 0,0,1) ||
|
||||
sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
|
||||
acl_get_all3(sctx, db_name->str, 0))
|
||||
(acc.maybe_allowed(DB_ACLS | SHOW_DB_ACL)))
|
||||
#endif
|
||||
{
|
||||
Dynamic_array<LEX_CSTRING*> table_names(PSI_INSTRUMENT_MEM);
|
||||
@@ -5835,9 +5840,10 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
continue;
|
||||
}
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
|
||||
acl_get_all3(sctx, db_name->str, false) ||
|
||||
!check_grant_db(thd, db_name->str))
|
||||
access_t acc= acl_get_all3(sctx, db_name->str, false)
|
||||
.merge_with_parent(sctx->master_access);
|
||||
if (acc.maybe_allowed(DB_ACLS | SHOW_DB_ACL) ||
|
||||
!check_grant_db(thd, acc ,db_name->str))
|
||||
#endif
|
||||
{
|
||||
load_db_opt_by_name(thd, db_name->str, &create);
|
||||
@@ -6565,7 +6571,7 @@ int get_schema_column_record(THD *thd, TABLE_LIST *tables,
|
||||
&tables->grant.privilege, 0, 0, MY_TEST(tables->schema_table));
|
||||
if (is_temporary_table(tables))
|
||||
{
|
||||
tables->grant.privilege|= TMP_TABLE_ACLS;
|
||||
tables->grant.privilege.force_allow(TMP_TABLE_ACLS, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7461,11 +7467,11 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, TABLE *table,
|
||||
uint j;
|
||||
for (j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
|
||||
{
|
||||
auto access= get_column_grant(thd, &tables->grant, db_name->str,
|
||||
access_t access= get_column_grant(thd, &tables->grant, db_name->str,
|
||||
table_name->str,
|
||||
key_part->field->field_name);
|
||||
|
||||
if (!access)
|
||||
if (!(access & COL_ACLS))
|
||||
break;
|
||||
}
|
||||
if (j != key_info->user_defined_key_parts)
|
||||
@@ -7605,7 +7611,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
|
||||
table_list.db= tables->db;
|
||||
table_list.table_name= tables->table_name;
|
||||
table_list.grant.privilege= thd->col_access;
|
||||
privilege_t view_access(get_table_grant(thd, &table_list));
|
||||
access_t view_access(get_table_grant(thd, &table_list));
|
||||
if ((view_access & (SHOW_VIEW_ACL|SELECT_ACL)) ==
|
||||
(SHOW_VIEW_ACL|SELECT_ACL))
|
||||
tables->allowed_show= TRUE;
|
||||
@@ -8110,7 +8116,7 @@ get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables,
|
||||
table_name->str,
|
||||
key_part->field->field_name);
|
||||
|
||||
if (!access)
|
||||
if (!(access & COL_ACLS))
|
||||
break;
|
||||
}
|
||||
if (j != key_info->user_defined_key_parts)
|
||||
@@ -8148,11 +8154,11 @@ get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables,
|
||||
{
|
||||
while ((r_info= it1++))
|
||||
{
|
||||
auto access= get_column_grant(thd, &tables->grant, db_name->str,
|
||||
access_t access= get_column_grant(thd, &tables->grant, db_name->str,
|
||||
table_name->str,
|
||||
Lex_ident_column(*r_info));
|
||||
|
||||
if (!access)
|
||||
if (!(access & COL_ACLS))
|
||||
break;
|
||||
}
|
||||
if (!it1.at_end())
|
||||
@@ -9518,7 +9524,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
|
||||
if (!(table= create_schema_table(thd, table_list)))
|
||||
DBUG_RETURN(1);
|
||||
table->s->tmp_table= SYSTEM_TMP_TABLE;
|
||||
table->grant.privilege= SELECT_ACL;
|
||||
table->grant.privilege= access_t(SELECT_ACL);
|
||||
/*
|
||||
This test is necessary to make
|
||||
case insensitive file systems +
|
||||
|
||||
@@ -541,6 +541,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
%token <kwd> DELETE_DOMAIN_ID_SYM
|
||||
%token <kwd> DELETE_SYM /* SQL-2003-R */
|
||||
%token <kwd> DENSE_RANK_SYM
|
||||
%token <kwd> DENY
|
||||
%token <kwd> DESCRIBE /* SQL-2003-R */
|
||||
%token <kwd> DESC /* SQL-2003-N */
|
||||
%token <kwd> DETERMINISTIC_SYM /* SQL-2003-R */
|
||||
@@ -1879,7 +1880,7 @@ rule:
|
||||
procedure_list procedure_list2 procedure_item
|
||||
handler opt_generated_always
|
||||
opt_ignore opt_column opt_restrict
|
||||
grant revoke set lock unlock string_list
|
||||
deny grant revoke set lock unlock string_list
|
||||
table_lock_list table_lock
|
||||
ref_list opt_match_clause opt_on_update_delete use
|
||||
opt_delete_options opt_delete_option varchar nchar nvarchar
|
||||
@@ -2191,6 +2192,7 @@ verb_clause:
|
||||
| create
|
||||
| deallocate
|
||||
| delete
|
||||
| deny
|
||||
| describe
|
||||
| do
|
||||
| drop
|
||||
@@ -18359,11 +18361,41 @@ handler_rkey_mode:
|
||||
/* GRANT / REVOKE */
|
||||
|
||||
revoke:
|
||||
REVOKE clear_privileges revoke_command
|
||||
REVOKE clear_privileges revoke_privileges_or_proxy
|
||||
{
|
||||
}
|
||||
|
|
||||
REVOKE DENY clear_privileges revoke_privileges
|
||||
{
|
||||
static_cast<Sql_cmd_grant*>(Lex->m_sql_cmd)->set_deny();
|
||||
}
|
||||
| REVOKE clear_privileges ALL opt_privileges ',' GRANT OPTION FROM user_and_role_list
|
||||
{
|
||||
Lex->sql_command = SQLCOM_REVOKE_ALL;
|
||||
}
|
||||
| REVOKE clear_privileges revoke_role
|
||||
{}
|
||||
;
|
||||
|
||||
revoke_command:
|
||||
revoke_role:
|
||||
admin_option_for_role FROM user_and_role_list
|
||||
{
|
||||
Lex->sql_command= SQLCOM_REVOKE_ROLE;
|
||||
if (unlikely(Lex->users_list.push_front($1, thd->mem_root)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
revoke_privileges_or_proxy:
|
||||
revoke_privileges
|
||||
| PROXY_SYM ON user FROM user_list
|
||||
{
|
||||
if (Lex->stmt_revoke_proxy(thd, $3))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
revoke_privileges:
|
||||
grant_privileges ON opt_table grant_ident FROM user_and_role_list
|
||||
{
|
||||
if (Lex->stmt_revoke_table(thd, $1, *$4))
|
||||
@@ -18374,21 +18406,6 @@ revoke_command:
|
||||
if (Lex->stmt_revoke_sp(thd, $1, *$4, *$3))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| ALL opt_privileges ',' GRANT OPTION FROM user_and_role_list
|
||||
{
|
||||
Lex->sql_command = SQLCOM_REVOKE_ALL;
|
||||
}
|
||||
| PROXY_SYM ON user FROM user_list
|
||||
{
|
||||
if (Lex->stmt_revoke_proxy(thd, $3))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| admin_option_for_role FROM user_and_role_list
|
||||
{
|
||||
Lex->sql_command= SQLCOM_REVOKE_ROLE;
|
||||
if (unlikely(Lex->users_list.push_front($1, thd->mem_root)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
admin_option_for_role:
|
||||
@@ -18398,12 +18415,37 @@ admin_option_for_role:
|
||||
{ Lex->with_admin_option= false; $$= $1; }
|
||||
;
|
||||
|
||||
deny:
|
||||
DENY clear_privileges grant_privileges_command
|
||||
{
|
||||
static_cast<Sql_cmd_grant*>(Lex->m_sql_cmd)->set_deny();
|
||||
}
|
||||
;
|
||||
grant:
|
||||
GRANT clear_privileges grant_command
|
||||
{}
|
||||
{
|
||||
}
|
||||
| GRANT clear_privileges grant_role_command
|
||||
{
|
||||
/*
|
||||
TODO(cvicentiu) grant_role_command should use the Sql_cmd_grant
|
||||
interface. This will allow moving Lex->stmt_grant_xxx calls
|
||||
at this level instead of having them within grant_command
|
||||
rule.
|
||||
*/
|
||||
}
|
||||
;
|
||||
|
||||
grant_command:
|
||||
grant_privileges_command
|
||||
| PROXY_SYM ON user TO_SYM grant_list opt_grant_option
|
||||
{
|
||||
if (Lex->stmt_grant_proxy(thd, $3, $6))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
grant_privileges_command:
|
||||
grant_privileges ON opt_table grant_ident TO_SYM grant_list
|
||||
opt_require_clause opt_grant_options
|
||||
{
|
||||
@@ -18416,12 +18458,10 @@ grant_command:
|
||||
if (Lex->stmt_grant_sp(thd, $1, *$4, *$3, $8))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| PROXY_SYM ON user TO_SYM grant_list opt_grant_option
|
||||
{
|
||||
if (Lex->stmt_grant_proxy(thd, $3, $6))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| grant_role TO_SYM grant_list opt_with_admin_option
|
||||
;
|
||||
|
||||
grant_role_command:
|
||||
grant_role TO_SYM grant_list opt_with_admin_option
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
lex->sql_command= SQLCOM_GRANT_ROLE;
|
||||
@@ -18429,7 +18469,6 @@ grant_command:
|
||||
if (unlikely(Lex->users_list.push_front($1, thd->mem_root)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
opt_with_admin:
|
||||
|
||||
@@ -7123,7 +7123,7 @@ bool TABLE_LIST::prepare_security(THD *thd)
|
||||
/* REPAIR needs SELECT_ACL */
|
||||
while ((tbl= tb++))
|
||||
{
|
||||
tbl->grant.privilege= SELECT_ACL;
|
||||
tbl->grant.privilege= access_t(SELECT_ACL);
|
||||
tbl->security_ctx= save_security_ctx;
|
||||
}
|
||||
DBUG_RETURN(FALSE);
|
||||
@@ -7154,7 +7154,7 @@ bool TABLE_LIST::prepare_security(THD *thd)
|
||||
thd->security_ctx= save_security_ctx;
|
||||
#else
|
||||
while ((tbl= tb++))
|
||||
tbl->grant.privilege= ALL_KNOWN_ACL;
|
||||
tbl->grant.privilege= access_t(ALL_KNOWN_ACL);
|
||||
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
@@ -8952,6 +8952,11 @@ void TABLE_LIST::reinit_before_use(THD *thd)
|
||||
table= 0;
|
||||
/* Reset is_schema_table_processed value(needed for I_S tables */
|
||||
schema_table_state= NOT_PROCESSED;
|
||||
/*
|
||||
Reset want_privilege: a previous prepare/execute may have left
|
||||
something here.
|
||||
*/
|
||||
grant.want_privilege= NO_ACL;
|
||||
|
||||
TABLE_LIST *embedded; /* The table at the current level of nesting. */
|
||||
TABLE_LIST *parent_embedding= this; /* The parent nested table reference. */
|
||||
|
||||
@@ -355,10 +355,8 @@ typedef struct st_grant_info
|
||||
process. In each step the "wanted privilege" is checked against the
|
||||
fulfilled privileges. When/if the intersection of these sets is empty,
|
||||
access is granted.
|
||||
|
||||
The set is implemented as a bitmap, with the bits defined in sql_acl.h.
|
||||
*/
|
||||
privilege_t privilege;
|
||||
access_t privilege;
|
||||
/**
|
||||
@brief the set of privileges that the current user needs to fulfil in
|
||||
order to carry out the requested operation.
|
||||
@@ -383,11 +381,11 @@ typedef struct st_grant_info
|
||||
|
||||
inline void refresh(const Security_context *sctx, const char *db,
|
||||
const char *table);
|
||||
inline privilege_t aggregate_privs();
|
||||
inline access_t aggregate_privs();
|
||||
inline privilege_t aggregate_cols();
|
||||
|
||||
/* OR table and all column privileges */
|
||||
privilege_t all_privilege();
|
||||
access_t all_privilege();
|
||||
} GRANT_INFO;
|
||||
|
||||
enum tmp_table_type
|
||||
|
||||
@@ -1238,7 +1238,7 @@ TABLE *THD::open_temporary_table(TMP_TABLE_SHARE *share,
|
||||
}
|
||||
|
||||
table->reginfo.lock_type= TL_WRITE; /* Simulate locked */
|
||||
table->grant.privilege= TMP_TABLE_ACLS;
|
||||
table->grant.privilege= access_t(TMP_TABLE_ACLS);
|
||||
table->query_id= query_id;
|
||||
share->tmp_table= (table->file->has_transaction_manager() ?
|
||||
TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
|
||||
|
||||
@@ -4092,7 +4092,7 @@ void* start_wsrep_THD(void *arg)
|
||||
/* from bootstrap()... */
|
||||
thd->bootstrap=1;
|
||||
thd->max_client_packet_length= thd->net.max_packet;
|
||||
thd->security_ctx->master_access= ALL_KNOWN_ACL;
|
||||
thd->security_ctx->master_access= access_t(ALL_KNOWN_ACL);
|
||||
|
||||
/* from handle_one_connection... */
|
||||
pthread_detach_this_thread();
|
||||
|
||||
@@ -522,7 +522,7 @@ thd::thd (my_bool ini, bool system_thread)
|
||||
{
|
||||
ptr->system_thread= SYSTEM_THREAD_GENERIC;
|
||||
}
|
||||
ptr->security_ctx->master_access= ALL_KNOWN_ACL;
|
||||
ptr->security_ctx->master_access= access_t(ALL_KNOWN_ACL);
|
||||
lex_start(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ int FiberScanState::init(TABLE *tbl,
|
||||
}
|
||||
|
||||
/* Grant full privileges so the fiber can open any table */
|
||||
fiber_thd->security_ctx->master_access= ALL_KNOWN_ACL;
|
||||
fiber_thd->security_ctx->master_access= access_t(ALL_KNOWN_ACL);
|
||||
|
||||
/* Disable query cache — fiber queries are internal, not cacheable */
|
||||
fiber_thd->query_cache_is_applicable= 0;
|
||||
|
||||
Reference in New Issue
Block a user