Commit fad27ebf authored by unknown's avatar unknown

Fix for BUG#16777: Can not create trigger nor view w/o definer

if --skip-grant-tables specified.

The problem is that there is a check that prevents creating a definer
with empty host name.

In --skip-grant-tables mode this check prevents the user from creating a
trigger/view without explicitly specifying its definer. This happens, because
in --skip-grant-tables mode CURRENT_USER is ''@''. According to Sanja this
check was implemented intentionally.

However, according to the MySQL manual it is possible to specify empty host
name (as well as empty user name). Moreover, the behaviour for stored routines
is different in this aspect -- we allow them to be created with implicit
definer.

Based on this, we believe it is OK to change the behaviour for views to be
similar with the behaviour for stored routines.


mysql-test/r/skip_grants.result:
  Added a test case for BUG#16777.
mysql-test/t/skip_grants.test:
  Added a test case for BUG#16777.
sql/mysql_priv.h:
  Do not check that strlen(host) > 0 in get_default_definer().
sql/sql_parse.cc:
  Do not check that strlen(host) > 0 in get_default_definer().
sql/sql_view.cc:
  Do not check that strlen(host) > 0 in get_default_definer().
parent a44a924a
...@@ -2,13 +2,26 @@ drop table if exists t1,v1; ...@@ -2,13 +2,26 @@ drop table if exists t1,v1;
drop view if exists t1,v1; drop view if exists t1,v1;
drop procedure if exists f1; drop procedure if exists f1;
use test; use test;
create table t1 (field1 INT);
CREATE VIEW v1 AS SELECT field1 FROM t1;
ERROR HY000: Definer is not fully qualified
drop table t1;
create procedure f1() select 1; create procedure f1() select 1;
drop procedure f1; drop procedure f1;
create table t1 (a int); create table t1 (a int);
create definer='user'@'host' sql security definer view v1 as select * from t1; create definer='user'@'host' sql security definer view v1 as select * from t1;
drop view v1; drop view v1;
drop table t1; drop table t1;
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v2;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(c INT);
CREATE TRIGGER t1_bi BEFORE INSERT ON t1
FOR EACH ROW
SET @a = 1;
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1
FOR EACH ROW
SET @b = 1;
CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1;
DROP TRIGGER t1_bi;
DROP TRIGGER ti_ai;
DROP VIEW v1;
DROP VIEW v2;
DROP TABLE t1;
...@@ -8,14 +8,6 @@ drop procedure if exists f1; ...@@ -8,14 +8,6 @@ drop procedure if exists f1;
--enable_warnings --enable_warnings
use test; use test;
#
# test that we can create VIEW if privileges check switched off
#
create table t1 (field1 INT);
-- error ER_MALFORMED_DEFINER
CREATE VIEW v1 AS SELECT field1 FROM t1;
drop table t1;
# #
# Test that we can create and drop procedure without warnings # Test that we can create and drop procedure without warnings
# see bug#9993 # see bug#9993
...@@ -30,3 +22,48 @@ create table t1 (a int); ...@@ -30,3 +22,48 @@ create table t1 (a int);
create definer='user'@'host' sql security definer view v1 as select * from t1; create definer='user'@'host' sql security definer view v1 as select * from t1;
drop view v1; drop view v1;
drop table t1; drop table t1;
#
# BUG#16777: Can not create trigger nor view w/o definer if --skip-grant-tables
# specified
#
# Also, a test that we can create VIEW if privileges check switched off has
# been moved here.
#
# Prepare.
--disable_warnings
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v2;
DROP TABLE IF EXISTS t1;
--enable_warnings
# Test case.
CREATE TABLE t1(c INT);
CREATE TRIGGER t1_bi BEFORE INSERT ON t1
FOR EACH ROW
SET @a = 1;
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1
FOR EACH ROW
SET @b = 1;
CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1;
# Cleanup.
DROP TRIGGER t1_bi;
DROP TRIGGER ti_ai;
DROP VIEW v1;
DROP VIEW v2;
DROP TABLE t1;
...@@ -530,7 +530,7 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables); ...@@ -530,7 +530,7 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables);
bool create_table_precheck(THD *thd, TABLE_LIST *tables, bool create_table_precheck(THD *thd, TABLE_LIST *tables,
TABLE_LIST *create_table); TABLE_LIST *create_table);
bool get_default_definer(THD *thd, LEX_USER *definer); void get_default_definer(THD *thd, LEX_USER *definer);
LEX_USER *create_default_definer(THD *thd); LEX_USER *create_default_definer(THD *thd);
LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name); LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
......
...@@ -7168,47 +7168,28 @@ Item *negate_expression(THD *thd, Item *expr) ...@@ -7168,47 +7168,28 @@ Item *negate_expression(THD *thd, Item *expr)
/* /*
Set the specified definer to the default value, which is the current user in Set the specified definer to the default value, which is the current user in
the thread. Also check that the current user satisfies to the definers the thread.
requirements.
SYNOPSIS SYNOPSIS
get_default_definer() get_default_definer()
thd [in] thread handler thd [in] thread handler
definer [out] definer definer [out] definer
RETURN
error status, that is:
- FALSE -- on success;
- TRUE -- on error (current user can not be a definer).
*/ */
bool get_default_definer(THD *thd, LEX_USER *definer) void get_default_definer(THD *thd, LEX_USER *definer)
{ {
/* Check that current user has non-empty host name. */
const Security_context *sctx= thd->security_ctx; const Security_context *sctx= thd->security_ctx;
if (sctx->priv_host[0] == 0)
{
my_error(ER_MALFORMED_DEFINER, MYF(0));
return TRUE;
}
/* Fill in. */
definer->user.str= (char *) sctx->priv_user; definer->user.str= (char *) sctx->priv_user;
definer->user.length= strlen(definer->user.str); definer->user.length= strlen(definer->user.str);
definer->host.str= (char *) sctx->priv_host; definer->host.str= (char *) sctx->priv_host;
definer->host.length= strlen(definer->host.str); definer->host.length= strlen(definer->host.str);
return FALSE;
} }
/* /*
Create default definer for the specified THD. Also check that the current Create default definer for the specified THD.
user is conformed to the definers requirements.
SYNOPSIS SYNOPSIS
create_default_definer() create_default_definer()
...@@ -7227,8 +7208,7 @@ LEX_USER *create_default_definer(THD *thd) ...@@ -7227,8 +7208,7 @@ LEX_USER *create_default_definer(THD *thd)
if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
return 0; return 0;
if (get_default_definer(thd, definer)) get_default_definer(thd, definer);
return 0;
return definer; return definer;
} }
......
...@@ -835,8 +835,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table) ...@@ -835,8 +835,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER), ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER),
table->db, table->table_name); table->db, table->table_name);
if (get_default_definer(thd, &table->definer)) get_default_definer(thd, &table->definer);
goto err;
} }
/* /*
......
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