Commit cf539a5a authored by unknown's avatar unknown

Additional fix for BUG#16777: Can not create trigger nor view

w/o definer if --skip-grant-tables specified.
  
The previous patch does not allow to specify empty host name in
DEFINER-clause explicitly.


mysql-test/r/skip_grants.result:
  Updated the result file.
mysql-test/r/view_grant.result:
  Updated the result file.
mysql-test/t/skip_grants.test:
  Added test cases for BUG#16777; re-organized tests.
mysql-test/t/view_grant.test:
  Updated after final fix of BUG#16777.
sql/sql_parse.cc:
  The final part of fixing BUG#16777: allow empty host name in explicitly
  specified DEFINER-clause.
sql/sql_show.cc:
  Quote an identifier if it is empty.
parent 50c8c206
drop table if exists t1,v1;
drop view if exists t1,v1;
drop procedure if exists f1;
use test; use test;
create procedure f1() select 1;
drop procedure f1;
create table t1 (a int);
create definer='user'@'host' sql security definer view v1 as select * from t1;
drop view v1;
drop table t1;
drop function if exists f1;
Warnings:
Note 1305 FUNCTION f1 does not exist
DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v2; DROP VIEW IF EXISTS v2;
DROP VIEW IF EXISTS v3;
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1;
DROP PROCEDURE IF EXISTS p1;
DROP PROCEDURE IF EXISTS p2;
DROP PROCEDURE IF EXISTS p3;
DROP FUNCTION IF EXISTS f1;
DROP FUNCTION IF EXISTS f2;
DROP FUNCTION IF EXISTS f3;
CREATE TABLE t1(c INT); CREATE TABLE t1(c INT);
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 CREATE TRIGGER t1_bi BEFORE INSERT ON t1
FOR EACH ROW FOR EACH ROW
SET @a = 1; SET @a = 1;
CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v1 AS SELECT * FROM t1;
CREATE PROCEDURE p1()
SELECT 1;
CREATE FUNCTION f1() RETURNS INT
RETURN 1;
CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1 CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1
FOR EACH ROW FOR EACH ROW
SET @b = 1; SET @b = 1;
CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1; CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1;
CREATE DEFINER=a@b PROCEDURE p2()
SELECT 2;
CREATE DEFINER=a@b FUNCTION f2() RETURNS INT
RETURN 2;
CREATE DEFINER=a@'' TRIGGER ti_bu BEFORE UPDATE ON t1
FOR EACH ROW
SET @c = 1;
CREATE DEFINER=a@'' VIEW v3 AS SELECT * FROM t1;
CREATE DEFINER=a@'' PROCEDURE p3()
SELECT 3;
CREATE DEFINER=a@'' FUNCTION f3() RETURNS INT
RETURN 3;
SHOW CREATE VIEW v3;
View Create View
v3 CREATE ALGORITHM=UNDEFINED DEFINER=`a`@`` SQL SECURITY DEFINER VIEW `v3` AS select `t1`.`c` AS `c` from `t1`
SHOW CREATE PROCEDURE p3;
Procedure sql_mode Create Procedure
p3 CREATE DEFINER=`a`@`` PROCEDURE `p3`()
SELECT 3
SHOW CREATE FUNCTION f3;
Function sql_mode Create Function
f3 CREATE DEFINER=`a`@`` FUNCTION `f3`() RETURNS int(11)
RETURN 3
DROP TRIGGER t1_bi; DROP TRIGGER t1_bi;
DROP TRIGGER ti_ai; DROP TRIGGER ti_ai;
DROP TRIGGER ti_bu;
DROP VIEW v1; DROP VIEW v1;
DROP VIEW v2; DROP VIEW v2;
DROP VIEW v3;
DROP TABLE t1; DROP TABLE t1;
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP PROCEDURE p3;
DROP FUNCTION f1;
DROP FUNCTION f2;
DROP FUNCTION f3;
...@@ -520,11 +520,16 @@ use test; ...@@ -520,11 +520,16 @@ use test;
drop user mysqltest_1@localhost; drop user mysqltest_1@localhost;
drop database mysqltest; drop database mysqltest;
create definer=some_user@`` sql security invoker view v1 as select 1; create definer=some_user@`` sql security invoker view v1 as select 1;
ERROR HY000: Definer is not fully qualified Warnings:
create definer=some_user@localhost sql security invoker view v1 as select 1; Note 1449 There is no 'some_user'@'' registered
create definer=some_user@localhost sql security invoker view v2 as select 1;
Warnings: Warnings:
Note 1449 There is no 'some_user'@'localhost' registered Note 1449 There is no 'some_user'@'localhost' registered
show create view v1; show create view v1;
View Create View View Create View
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1` v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1`
show create view v2;
View Create View
v2 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select 1 AS `1`
drop view v1; drop view v1;
drop view v2;
# This tests not performed with embedded server # This tests not performed with embedded server
-- source include/not_embedded.inc -- source include/not_embedded.inc
--disable_warnings
drop table if exists t1,v1;
drop view if exists t1,v1;
drop procedure if exists f1;
--enable_warnings
use test; use test;
#
# Test that we can create and drop procedure without warnings
# see bug#9993
#
create procedure f1() select 1;
drop procedure f1;
#
# BUG#13504: creation view with DEFINER clause if --skip-grant-tables
#
create table t1 (a int);
create definer='user'@'host' sql security definer view v1 as select * from t1;
drop view v1;
drop table t1;
# BUG#17595: DROP FUNCTION IF EXISTS f1 crashes server
drop function if exists f1;
# #
# BUG#16777: Can not create trigger nor view w/o definer if --skip-grant-tables # BUG#16777: Can not create trigger nor view w/o definer if --skip-grant-tables
# specified # specified
# #
# Also, a test that we can create VIEW if privileges check switched off has # Also, the following test cases have been moved here:
# been moved here. # - test that we can create VIEW if privileges check switched off has been
# moved here;
# - test that we can create and drop procedure without warnings (BUG#9993);
# - BUG#17595: "DROP FUNCTION IF EXISTS" crashes server;
# - BUG#13504: creation view with DEFINER clause if --skip-grant-tables
# #
# Prepare. # Prepare.
...@@ -40,33 +21,90 @@ drop function if exists f1; ...@@ -40,33 +21,90 @@ drop function if exists f1;
DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v2; DROP VIEW IF EXISTS v2;
DROP VIEW IF EXISTS v3;
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1;
DROP PROCEDURE IF EXISTS p1;
DROP PROCEDURE IF EXISTS p2;
DROP PROCEDURE IF EXISTS p3;
DROP FUNCTION IF EXISTS f1;
DROP FUNCTION IF EXISTS f2;
DROP FUNCTION IF EXISTS f3;
--enable_warnings --enable_warnings
# Test case. # Test case.
CREATE TABLE t1(c INT); CREATE TABLE t1(c INT);
# - try to create with implicit definer (definer would be ''@'');
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 CREATE TRIGGER t1_bi BEFORE INSERT ON t1
FOR EACH ROW FOR EACH ROW
SET @a = 1; SET @a = 1;
CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v1 AS SELECT * FROM t1;
CREATE PROCEDURE p1()
SELECT 1;
CREATE FUNCTION f1() RETURNS INT
RETURN 1;
# - try to create with explicit definer;
CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1 CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1
FOR EACH ROW FOR EACH ROW
SET @b = 1; SET @b = 1;
CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1; CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1;
CREATE DEFINER=a@b PROCEDURE p2()
SELECT 2;
CREATE DEFINER=a@b FUNCTION f2() RETURNS INT
RETURN 2;
# - try to create with explicit definer with empty host;
CREATE DEFINER=a@'' TRIGGER ti_bu BEFORE UPDATE ON t1
FOR EACH ROW
SET @c = 1;
CREATE DEFINER=a@'' VIEW v3 AS SELECT * FROM t1;
CREATE DEFINER=a@'' PROCEDURE p3()
SELECT 3;
CREATE DEFINER=a@'' FUNCTION f3() RETURNS INT
RETURN 3;
# - check that empty host name is treated correctly;
SHOW CREATE VIEW v3;
SHOW CREATE PROCEDURE p3;
SHOW CREATE FUNCTION f3;
# Cleanup. # Cleanup.
DROP TRIGGER t1_bi; DROP TRIGGER t1_bi;
DROP TRIGGER ti_ai; DROP TRIGGER ti_ai;
DROP TRIGGER ti_bu;
DROP VIEW v1; DROP VIEW v1;
DROP VIEW v2; DROP VIEW v2;
DROP VIEW v3;
DROP TABLE t1; DROP TABLE t1;
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP PROCEDURE p3;
DROP FUNCTION f1;
DROP FUNCTION f2;
DROP FUNCTION f3;
...@@ -706,10 +706,9 @@ connection default; ...@@ -706,10 +706,9 @@ connection default;
# #
# DEFINER information check # DEFINER information check
# #
-- error ER_MALFORMED_DEFINER
create definer=some_user@`` sql security invoker view v1 as select 1; create definer=some_user@`` sql security invoker view v1 as select 1;
create definer=some_user@localhost sql security invoker view v1 as select 1; create definer=some_user@localhost sql security invoker view v2 as select 1;
show create view v1; show create view v1;
show create view v2;
drop view v1; drop view v1;
drop view v2;
...@@ -7300,8 +7300,7 @@ LEX_USER *create_default_definer(THD *thd) ...@@ -7300,8 +7300,7 @@ LEX_USER *create_default_definer(THD *thd)
/* /*
Create definer with the given user and host names. Also check that the user Create definer with the given user and host names.
and host names satisfy definers requirements.
SYNOPSIS SYNOPSIS
create_definer() create_definer()
...@@ -7319,14 +7318,6 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) ...@@ -7319,14 +7318,6 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
{ {
LEX_USER *definer; LEX_USER *definer;
/* Check that specified host name is valid. */
if (host_name->length == 0)
{
my_error(ER_MALFORMED_DEFINER, MYF(0));
return 0;
}
/* Create and initialize. */ /* Create and initialize. */
if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
......
...@@ -648,6 +648,18 @@ static const char *require_quotes(const char *name, uint name_length) ...@@ -648,6 +648,18 @@ static const char *require_quotes(const char *name, uint name_length)
} }
/*
Quote the given identifier if needed and append it to the target string.
If the given identifier is empty, it will be quoted.
SYNOPSIS
append_identifier()
thd thread handler
packet target string
name the identifier to be appended
name_length length of the appending identifier
*/
void void
append_identifier(THD *thd, String *packet, const char *name, uint length) append_identifier(THD *thd, String *packet, const char *name, uint length)
{ {
...@@ -701,8 +713,11 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) ...@@ -701,8 +713,11 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
length length of name length length of name
IMPLEMENTATION IMPLEMENTATION
If name is a keyword or includes a special character, then force Force quoting in the following cases:
quoting. - name is empty (for one, it is possible when we use this function for
quoting user and host names for DEFINER clause);
- name is a keyword;
- name includes a special character;
Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE
is set. is set.
...@@ -713,7 +728,7 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) ...@@ -713,7 +728,7 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
int get_quote_char_for_identifier(THD *thd, const char *name, uint length) int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
{ {
if (!length || if (length &&
!is_keyword(name,length) && !is_keyword(name,length) &&
!require_quotes(name, length) && !require_quotes(name, length) &&
!(thd->options & OPTION_QUOTE_SHOW_CREATE)) !(thd->options & OPTION_QUOTE_SHOW_CREATE))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment