mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merged fix for bug #58499 "DEFINER-security view selecting from
INVOKER-security view access check wrong" into mysql-5.5 tree.
This commit is contained in:
@ -1248,3 +1248,129 @@ Note 1449 The user specified as a definer ('unknown'@'unknown') does not exist
|
||||
LOCK TABLES v1 READ;
|
||||
ERROR HY000: The user specified as a definer ('unknown'@'unknown') does not exist
|
||||
DROP VIEW v1;
|
||||
#
|
||||
# Bug #58499 "DEFINER-security view selecting from INVOKER-security view
|
||||
# access check wrong".
|
||||
#
|
||||
# Check that we correctly handle privileges for various combinations
|
||||
# of INVOKER and DEFINER-security views using each other.
|
||||
DROP DATABASE IF EXISTS mysqltest1;
|
||||
CREATE DATABASE mysqltest1;
|
||||
USE mysqltest1;
|
||||
CREATE TABLE t1 (i INT);
|
||||
CREATE TABLE t2 (j INT);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
INSERT INTO t2 VALUES (2);
|
||||
#
|
||||
# 1) DEFINER-security view uses INVOKER-security view (covers
|
||||
# scenario originally described in the bug report).
|
||||
CREATE SQL SECURITY INVOKER VIEW v1_uses_t1 AS SELECT * FROM t1;
|
||||
CREATE SQL SECURITY INVOKER VIEW v1_uses_t2 AS SELECT * FROM t2;
|
||||
CREATE USER 'mysqluser1'@'%';
|
||||
GRANT CREATE VIEW ON mysqltest1.* TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON t1 TO 'mysqluser1'@'%';
|
||||
# To be able create 'v2_uses_t2' we also need select on t2.
|
||||
GRANT SELECT ON t2 TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON v1_uses_t1 TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON v1_uses_t2 TO 'mysqluser1'@'%';
|
||||
#
|
||||
# Connection 'mysqluser1'.
|
||||
CREATE SQL SECURITY DEFINER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1;
|
||||
CREATE SQL SECURITY DEFINER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2;
|
||||
#
|
||||
# Connection 'default'.
|
||||
CREATE USER 'mysqluser2'@'%';
|
||||
GRANT SELECT ON v2_uses_t1 TO 'mysqluser2'@'%';
|
||||
GRANT SELECT ON v2_uses_t2 TO 'mysqluser2'@'%';
|
||||
GRANT SELECT ON t2 TO 'mysqluser2'@'%';
|
||||
GRANT CREATE VIEW ON mysqltest1.* TO 'mysqluser2'@'%';
|
||||
# Make 'mysqluser1' unable to access t2.
|
||||
REVOKE SELECT ON t2 FROM 'mysqluser1'@'%';
|
||||
#
|
||||
# Connection 'mysqluser2'.
|
||||
# The below statement should succeed thanks to suid nature of v2_uses_t1.
|
||||
SELECT * FROM v2_uses_t1;
|
||||
i
|
||||
1
|
||||
# The below statement should fail due to suid nature of v2_uses_t2.
|
||||
SELECT * FROM v2_uses_t2;
|
||||
ERROR HY000: View 'mysqltest1.v2_uses_t2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
#
|
||||
# 2) INVOKER-security view uses INVOKER-security view.
|
||||
#
|
||||
# Connection 'default'.
|
||||
DROP VIEW v2_uses_t1, v2_uses_t2;
|
||||
CREATE SQL SECURITY INVOKER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1;
|
||||
CREATE SQL SECURITY INVOKER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2;
|
||||
GRANT SELECT ON v2_uses_t1 TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON v2_uses_t2 TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON v1_uses_t1 TO 'mysqluser2'@'%';
|
||||
GRANT SELECT ON v1_uses_t2 TO 'mysqluser2'@'%';
|
||||
#
|
||||
# Connection 'mysqluser1'.
|
||||
# For both versions of 'v2' 'mysqluser1' privileges should be used.
|
||||
SELECT * FROM v2_uses_t1;
|
||||
i
|
||||
1
|
||||
SELECT * FROM v2_uses_t2;
|
||||
ERROR HY000: View 'mysqltest1.v2_uses_t2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
#
|
||||
# Connection 'mysqluser2'.
|
||||
# And now for both versions of 'v2' 'mysqluser2' privileges should
|
||||
# be used.
|
||||
SELECT * FROM v2_uses_t1;
|
||||
ERROR HY000: View 'mysqltest1.v2_uses_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
SELECT * FROM v2_uses_t2;
|
||||
j
|
||||
2
|
||||
#
|
||||
# 3) INVOKER-security view uses DEFINER-security view.
|
||||
#
|
||||
# Connection 'default'.
|
||||
DROP VIEW v1_uses_t1, v1_uses_t2;
|
||||
# To be able create 'v1_uses_t2' we also need select on t2.
|
||||
GRANT SELECT ON t2 TO 'mysqluser1'@'%';
|
||||
#
|
||||
# Connection 'mysqluser1'.
|
||||
CREATE SQL SECURITY DEFINER VIEW v1_uses_t1 AS SELECT * FROM t1;
|
||||
CREATE SQL SECURITY DEFINER VIEW v1_uses_t2 AS SELECT * FROM t2;
|
||||
#
|
||||
# Connection 'default'.
|
||||
# Make 'mysqluser1' unable to access t2.
|
||||
REVOKE SELECT ON t2 FROM 'mysqluser1'@'%';
|
||||
#
|
||||
# Connection 'mysqluser2'.
|
||||
# Due to suid nature of v1_uses_t1 and v1_uses_t2 the first
|
||||
# select should succeed and the second select should fail.
|
||||
SELECT * FROM v2_uses_t1;
|
||||
i
|
||||
1
|
||||
SELECT * FROM v2_uses_t2;
|
||||
ERROR HY000: View 'mysqltest1.v2_uses_t2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
#
|
||||
# 4) DEFINER-security view uses DEFINER-security view.
|
||||
#
|
||||
# Connection 'default'.
|
||||
DROP VIEW v2_uses_t1, v2_uses_t2;
|
||||
# To be able create 'v2_uses_t2' we also need select on t2.
|
||||
GRANT SELECT ON t2 TO 'mysqluser1'@'%';
|
||||
#
|
||||
# Connection 'mysqluser2'.
|
||||
CREATE SQL SECURITY DEFINER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1;
|
||||
CREATE SQL SECURITY DEFINER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2;
|
||||
#
|
||||
# Connection 'default'.
|
||||
# Make 'mysqluser1' unable to access t2.
|
||||
REVOKE SELECT ON t2 FROM 'mysqluser1'@'%';
|
||||
#
|
||||
# Connection 'mysqluser2'.
|
||||
# Again privileges of creator of innermost views should apply.
|
||||
SELECT * FROM v2_uses_t1;
|
||||
i
|
||||
1
|
||||
SELECT * FROM v2_uses_t2;
|
||||
ERROR HY000: View 'mysqltest1.v2_uses_t2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
USE test;
|
||||
DROP DATABASE mysqltest1;
|
||||
DROP USER 'mysqluser1'@'%';
|
||||
DROP USER 'mysqluser2'@'%';
|
||||
|
@ -1503,8 +1503,6 @@ SHOW CREATE VIEW v1;
|
||||
DROP TABLE t1;
|
||||
DROP VIEW v1;
|
||||
|
||||
# Wait till we reached the initial number of concurrent sessions
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
||||
--echo #
|
||||
--echo # Bug #46019: ERROR 1356 When selecting from within another
|
||||
@ -1546,3 +1544,145 @@ CREATE DEFINER=`unknown`@`unknown` SQL SECURITY DEFINER VIEW v1 AS SELECT 1;
|
||||
--error ER_NO_SUCH_USER
|
||||
LOCK TABLES v1 READ;
|
||||
DROP VIEW v1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Bug #58499 "DEFINER-security view selecting from INVOKER-security view
|
||||
--echo # access check wrong".
|
||||
--echo #
|
||||
--echo # Check that we correctly handle privileges for various combinations
|
||||
--echo # of INVOKER and DEFINER-security views using each other.
|
||||
--disable_warnings
|
||||
DROP DATABASE IF EXISTS mysqltest1;
|
||||
--enable_warnings
|
||||
CREATE DATABASE mysqltest1;
|
||||
USE mysqltest1;
|
||||
CREATE TABLE t1 (i INT);
|
||||
CREATE TABLE t2 (j INT);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
INSERT INTO t2 VALUES (2);
|
||||
--echo #
|
||||
--echo # 1) DEFINER-security view uses INVOKER-security view (covers
|
||||
--echo # scenario originally described in the bug report).
|
||||
CREATE SQL SECURITY INVOKER VIEW v1_uses_t1 AS SELECT * FROM t1;
|
||||
CREATE SQL SECURITY INVOKER VIEW v1_uses_t2 AS SELECT * FROM t2;
|
||||
CREATE USER 'mysqluser1'@'%';
|
||||
GRANT CREATE VIEW ON mysqltest1.* TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON t1 TO 'mysqluser1'@'%';
|
||||
--echo # To be able create 'v2_uses_t2' we also need select on t2.
|
||||
GRANT SELECT ON t2 TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON v1_uses_t1 TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON v1_uses_t2 TO 'mysqluser1'@'%';
|
||||
--echo #
|
||||
--echo # Connection 'mysqluser1'.
|
||||
--connect (mysqluser1, localhost, mysqluser1,,mysqltest1)
|
||||
CREATE SQL SECURITY DEFINER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1;
|
||||
CREATE SQL SECURITY DEFINER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2;
|
||||
--echo #
|
||||
--echo # Connection 'default'.
|
||||
--connection default
|
||||
CREATE USER 'mysqluser2'@'%';
|
||||
GRANT SELECT ON v2_uses_t1 TO 'mysqluser2'@'%';
|
||||
GRANT SELECT ON v2_uses_t2 TO 'mysqluser2'@'%';
|
||||
GRANT SELECT ON t2 TO 'mysqluser2'@'%';
|
||||
GRANT CREATE VIEW ON mysqltest1.* TO 'mysqluser2'@'%';
|
||||
--echo # Make 'mysqluser1' unable to access t2.
|
||||
REVOKE SELECT ON t2 FROM 'mysqluser1'@'%';
|
||||
--echo #
|
||||
--echo # Connection 'mysqluser2'.
|
||||
--connect (mysqluser2, localhost, mysqluser2,,mysqltest1)
|
||||
--echo # The below statement should succeed thanks to suid nature of v2_uses_t1.
|
||||
SELECT * FROM v2_uses_t1;
|
||||
--echo # The below statement should fail due to suid nature of v2_uses_t2.
|
||||
--error ER_VIEW_INVALID
|
||||
SELECT * FROM v2_uses_t2;
|
||||
--echo #
|
||||
--echo # 2) INVOKER-security view uses INVOKER-security view.
|
||||
--echo #
|
||||
--echo # Connection 'default'.
|
||||
--connection default
|
||||
DROP VIEW v2_uses_t1, v2_uses_t2;
|
||||
CREATE SQL SECURITY INVOKER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1;
|
||||
CREATE SQL SECURITY INVOKER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2;
|
||||
GRANT SELECT ON v2_uses_t1 TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON v2_uses_t2 TO 'mysqluser1'@'%';
|
||||
GRANT SELECT ON v1_uses_t1 TO 'mysqluser2'@'%';
|
||||
GRANT SELECT ON v1_uses_t2 TO 'mysqluser2'@'%';
|
||||
--echo #
|
||||
--echo # Connection 'mysqluser1'.
|
||||
--connection mysqluser1
|
||||
--echo # For both versions of 'v2' 'mysqluser1' privileges should be used.
|
||||
SELECT * FROM v2_uses_t1;
|
||||
--error ER_VIEW_INVALID
|
||||
SELECT * FROM v2_uses_t2;
|
||||
--echo #
|
||||
--echo # Connection 'mysqluser2'.
|
||||
--connection mysqluser2
|
||||
--echo # And now for both versions of 'v2' 'mysqluser2' privileges should
|
||||
--echo # be used.
|
||||
--error ER_VIEW_INVALID
|
||||
SELECT * FROM v2_uses_t1;
|
||||
SELECT * FROM v2_uses_t2;
|
||||
--echo #
|
||||
--echo # 3) INVOKER-security view uses DEFINER-security view.
|
||||
--echo #
|
||||
--echo # Connection 'default'.
|
||||
--connection default
|
||||
DROP VIEW v1_uses_t1, v1_uses_t2;
|
||||
--echo # To be able create 'v1_uses_t2' we also need select on t2.
|
||||
GRANT SELECT ON t2 TO 'mysqluser1'@'%';
|
||||
--echo #
|
||||
--echo # Connection 'mysqluser1'.
|
||||
--connection mysqluser1
|
||||
CREATE SQL SECURITY DEFINER VIEW v1_uses_t1 AS SELECT * FROM t1;
|
||||
CREATE SQL SECURITY DEFINER VIEW v1_uses_t2 AS SELECT * FROM t2;
|
||||
--echo #
|
||||
--echo # Connection 'default'.
|
||||
--connection default
|
||||
--echo # Make 'mysqluser1' unable to access t2.
|
||||
REVOKE SELECT ON t2 FROM 'mysqluser1'@'%';
|
||||
--echo #
|
||||
--echo # Connection 'mysqluser2'.
|
||||
--connection mysqluser2
|
||||
--echo # Due to suid nature of v1_uses_t1 and v1_uses_t2 the first
|
||||
--echo # select should succeed and the second select should fail.
|
||||
SELECT * FROM v2_uses_t1;
|
||||
--error ER_VIEW_INVALID
|
||||
SELECT * FROM v2_uses_t2;
|
||||
--echo #
|
||||
--echo # 4) DEFINER-security view uses DEFINER-security view.
|
||||
--echo #
|
||||
--echo # Connection 'default'.
|
||||
--connection default
|
||||
DROP VIEW v2_uses_t1, v2_uses_t2;
|
||||
--echo # To be able create 'v2_uses_t2' we also need select on t2.
|
||||
GRANT SELECT ON t2 TO 'mysqluser1'@'%';
|
||||
--echo #
|
||||
--echo # Connection 'mysqluser2'.
|
||||
--connection mysqluser2
|
||||
CREATE SQL SECURITY DEFINER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1;
|
||||
CREATE SQL SECURITY DEFINER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2;
|
||||
--echo #
|
||||
--echo # Connection 'default'.
|
||||
--connection default
|
||||
--echo # Make 'mysqluser1' unable to access t2.
|
||||
REVOKE SELECT ON t2 FROM 'mysqluser1'@'%';
|
||||
--echo #
|
||||
--echo # Connection 'mysqluser2'.
|
||||
--connection mysqluser2
|
||||
--echo # Again privileges of creator of innermost views should apply.
|
||||
SELECT * FROM v2_uses_t1;
|
||||
--error ER_VIEW_INVALID
|
||||
SELECT * FROM v2_uses_t2;
|
||||
|
||||
--disconnect mysqluser1
|
||||
--disconnect mysqluser2
|
||||
--connection default
|
||||
USE test;
|
||||
DROP DATABASE mysqltest1;
|
||||
DROP USER 'mysqluser1'@'%';
|
||||
DROP USER 'mysqluser2'@'%';
|
||||
|
||||
|
||||
# Wait till we reached the initial number of concurrent sessions
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
@ -1270,6 +1270,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
||||
TABLE_LIST *view_tables= lex->query_tables;
|
||||
TABLE_LIST *view_tables_tail= 0;
|
||||
TABLE_LIST *tbl;
|
||||
Security_context *security_ctx;
|
||||
|
||||
/*
|
||||
Check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show
|
||||
@ -1416,25 +1417,38 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
||||
if (table->view_suid)
|
||||
{
|
||||
/*
|
||||
Prepare a security context to check underlying objects of the view
|
||||
For suid views prepare a security context for checking underlying
|
||||
objects of the view.
|
||||
*/
|
||||
if (!(table->view_sctx= (Security_context *)
|
||||
thd->stmt_arena->alloc(sizeof(Security_context))))
|
||||
goto err;
|
||||
/* Assign the context to the tables referenced in the view */
|
||||
if (view_tables)
|
||||
{
|
||||
DBUG_ASSERT(view_tables_tail);
|
||||
for (tbl= view_tables; tbl != view_tables_tail->next_global;
|
||||
tbl= tbl->next_global)
|
||||
tbl->security_ctx= table->view_sctx;
|
||||
}
|
||||
/* assign security context to SELECT name resolution contexts of view */
|
||||
for(SELECT_LEX *sl= lex->all_selects_list;
|
||||
sl;
|
||||
sl= sl->next_select_in_list())
|
||||
sl->context.security_ctx= table->view_sctx;
|
||||
security_ctx= table->view_sctx;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
For non-suid views inherit security context from view's table list.
|
||||
This allows properly handle situation when non-suid view is used
|
||||
from within suid view.
|
||||
*/
|
||||
security_ctx= table->security_ctx;
|
||||
}
|
||||
|
||||
/* Assign the context to the tables referenced in the view */
|
||||
if (view_tables)
|
||||
{
|
||||
DBUG_ASSERT(view_tables_tail);
|
||||
for (tbl= view_tables; tbl != view_tables_tail->next_global;
|
||||
tbl= tbl->next_global)
|
||||
tbl->security_ctx= security_ctx;
|
||||
}
|
||||
|
||||
/* assign security context to SELECT name resolution contexts of view */
|
||||
for(SELECT_LEX *sl= lex->all_selects_list;
|
||||
sl;
|
||||
sl= sl->next_select_in_list())
|
||||
sl->context.security_ctx= security_ctx;
|
||||
|
||||
/*
|
||||
Setup an error processor to hide error messages issued by stored
|
||||
|
Reference in New Issue
Block a user