support DEFINER=role and DEFINER=current_role

This commit is contained in:
Sergei Golubchik 2013-10-18 12:17:49 -07:00
parent b054700619
commit b2f16628cf
24 changed files with 1467 additions and 387 deletions

View file

@ -26,9 +26,9 @@
C_MODE_START
void parse_user(const char *user_id_str, size_t user_id_len,
char *user_name_str, size_t *user_name_len,
char *host_name_str, size_t *host_name_len);
int parse_user(const char *user_id_str, size_t user_id_len,
char *user_name_str, size_t *user_name_len,
char *host_name_str, size_t *host_name_len);
C_MODE_END

View file

@ -0,0 +1,625 @@
create database mysqltest1;
use mysqltest1;
create table t1 (a int, b int, c int);
insert t1 values (1,10,100),(2,20,200);
create role role1;
grant select (a) on mysqltest1.t1 to role1;
grant event,execute,trigger on mysqltest1.* to role1;
grant role1 to current_user;
create role role2;
grant insert,select on mysqltest1.t1 to role2;
grant event,execute,trigger on mysqltest1.* to role2;
grant create view on mysqltest1.* to foo@localhost;
create role role4;
grant select on mysqltest1.t1 to role4;
grant role4 to foo@localhost;
create definer=current_role view test.v1 as select a+b,c from t1;
ERROR 0L000: Invalid definer
set role role1;
create definer=current_role view test.v1 as select a+b,c from t1;
show create view test.v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`role1` SQL SECURITY DEFINER VIEW `test`.`v1` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` latin1 latin1_swedish_ci
set role none;
create definer=role2 view test.v2 as select a+b,c from t1;
show create view test.v2;
View Create View character_set_client collation_connection
v2 CREATE ALGORITHM=UNDEFINED DEFINER=`role2` SQL SECURITY DEFINER VIEW `test`.`v2` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` latin1 latin1_swedish_ci
create definer=role3 view test.v3 as select a+b,c from t1;
Warnings:
Note 1449 The user specified as a definer ('role3'@'%') does not exist
show create view test.v3;
View Create View character_set_client collation_connection
v3 CREATE ALGORITHM=UNDEFINED DEFINER=`role3`@`%` SQL SECURITY DEFINER VIEW `test`.`v3` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` latin1 latin1_swedish_ci
Warnings:
Note 1449 The user specified as a definer ('role3'@'%') does not exist
show grants;
Grants for foo@localhost
GRANT role4 TO 'foo'@'localhost'
GRANT USAGE ON *.* TO 'foo'@'localhost'
GRANT CREATE VIEW ON `mysqltest1`.* TO 'foo'@'localhost'
select * from test.v1;
ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
select * from test.v2;
a+b c
11 100
22 200
select * from test.v3;
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: NO)
create definer=role4 view test.v4 as select a+b,c from t1;
ERROR 42000: ANY command denied to user 'foo'@'localhost' for table 't1'
select * from t1;
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1'
set role role4;
select * from t1;
a b c
1 10 100
2 20 200
create view test.v4 as select a+b,c from t1;
create definer=role4 view test.v5 as select a+b,c from t1;
select * from test.v4;
ERROR HY000: View 'test.v4' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
select * from test.v5;
a+b c
11 100
22 200
set role none;
select * from test.v4;
ERROR HY000: View 'test.v4' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
select * from test.v5;
a+b c
11 100
22 200
drop role role4;
show create view test.v5;
View Create View character_set_client collation_connection
v5 CREATE ALGORITHM=UNDEFINED DEFINER=`role4` SQL SECURITY DEFINER VIEW `test`.`v5` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` latin1 latin1_swedish_ci
Warnings:
Note 1449 The user specified as a definer ('role4'@'') does not exist
select * from test.v5;
ERROR HY000: The user specified as a definer ('role4'@'') does not exist
grant select on mysqltest1.t1 to role4;
show create view test.v5;
View Create View character_set_client collation_connection
v5 CREATE ALGORITHM=UNDEFINED DEFINER=`role4` SQL SECURITY DEFINER VIEW `test`.`v5` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` latin1 latin1_swedish_ci
Warnings:
Note 1449 The user specified as a definer ('role4'@'') does not exist
select * from test.v5;
ERROR HY000: The user specified as a definer ('role4'@'') does not exist
show create view test.v5;
View Create View character_set_client collation_connection
v5 CREATE ALGORITHM=UNDEFINED DEFINER=`role4`@`%` SQL SECURITY DEFINER VIEW `test`.`v5` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` latin1 latin1_swedish_ci
select * from test.v5;
a+b c
11 100
22 200
drop user role4;
create table t2 select * from t1;
create definer=current_role trigger tr1 before insert on t2 for each row
insert t1 values (111, 222, 333);
ERROR 0L000: Invalid definer
set role role1;
create definer=current_role trigger tr1 before insert on t2 for each row
insert t1 values (111, 222, 333);
show create trigger tr1;
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
tr1 CREATE DEFINER=`role1` trigger tr1 before insert on t2 for each row
insert t1 values (111, 222, 333) latin1 latin1_swedish_ci latin1_swedish_ci
set role none;
insert t2 values (11,22,33);
ERROR 42000: INSERT command denied to user 'role1'@'' for table 't1'
select * from t1;
a b c
1 10 100
2 20 200
select * from t2;
a b c
1 10 100
2 20 200
create definer=role2 trigger tr2 before delete on t2 for each row
insert t1 values (111, 222, 333);
show create trigger tr2;
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
tr2 CREATE DEFINER=`role2` trigger tr2 before delete on t2 for each row
insert t1 values (111, 222, 333) latin1 latin1_swedish_ci latin1_swedish_ci
delete from t2 where a=1;
select * from t1;
a b c
1 10 100
2 20 200
111 222 333
select * from t2;
a b c
2 20 200
delete from t1 where a=111;
create definer=role3 trigger tr3 before update on t2 for each row
insert t1 values (111, 222, 333);
Warnings:
Note 1449 The user specified as a definer ('role3'@'%') does not exist
show create trigger tr3;
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
tr3 CREATE DEFINER=`role3`@`%` trigger tr3 before update on t2 for each row
insert t1 values (111, 222, 333) latin1 latin1_swedish_ci latin1_swedish_ci
update t2 set b=2 where a=2;
ERROR HY000: The user specified as a definer ('role3'@'%') does not exist
select * from t1;
a b c
1 10 100
2 20 200
select * from t2;
a b c
2 20 200
flush tables;
show create trigger tr2;
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
tr2 CREATE DEFINER=`role2`@`` trigger tr2 before delete on t2 for each row
insert t1 values (111, 222, 333) latin1 latin1_swedish_ci latin1_swedish_ci
delete from t2 where a=2;
ERROR HY000: The user specified as a definer ('role2'@'%') does not exist
select * from t1;
a b c
1 10 100
2 20 200
select * from t2;
a b c
2 20 200
create definer=current_role procedure pr1() insert t1 values (111, 222, 333);
ERROR 0L000: Invalid definer
set role role1;
create definer=current_role procedure pr1() insert t1 values (111, 222, 333);
show create procedure pr1;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pr1 CREATE DEFINER=`role1` PROCEDURE `pr1`()
insert t1 values (111, 222, 333) latin1 latin1_swedish_ci latin1_swedish_ci
set role none;
call pr1();
ERROR 42000: INSERT command denied to user 'role1'@'' for table 't1'
select * from t1;
a b c
1 10 100
2 20 200
create definer=role2 procedure pr2() insert t1 values (111, 222, 333);
show create procedure pr2;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pr2 CREATE DEFINER=`role2` PROCEDURE `pr2`()
insert t1 values (111, 222, 333) latin1 latin1_swedish_ci latin1_swedish_ci
call pr2();
select * from t1;
a b c
1 10 100
2 20 200
111 222 333
delete from t1 where a=111;
create definer=role3 procedure pr3() insert t1 values (111, 222, 333);
Warnings:
Note 1449 The user specified as a definer ('role3'@'%') does not exist
show create procedure pr3;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pr3 CREATE DEFINER=`role3`@`%` PROCEDURE `pr3`()
insert t1 values (111, 222, 333) latin1 latin1_swedish_ci latin1_swedish_ci
call pr3();
ERROR HY000: The user specified as a definer ('role3'@'%') does not exist
select * from t1;
a b c
1 10 100
2 20 200
update mysql.proc set definer='role2@' where definer='role2';
call pr2();
ERROR HY000: The user specified as a definer ('role2'@'%') does not exist
create definer=current_role function fn1() returns int return (select sum(a+b) from t1);
ERROR 0L000: Invalid definer
set role role1;
create definer=current_role function fn1() returns int return (select sum(a+b) from t1);
show create function fn1;
Function sql_mode Create Function character_set_client collation_connection Database Collation
fn1 CREATE DEFINER=`role1` FUNCTION `fn1`() RETURNS int(11)
return (select sum(a+b) from t1) latin1 latin1_swedish_ci latin1_swedish_ci
set role none;
select fn1();
ERROR 42000: SELECT command denied to user 'role1'@'' for column 'b' in table 't1'
select * from t1;
a b c
1 10 100
2 20 200
create definer=role2 function fn2() returns int return (select sum(a+b) from t1);
show create function fn2;
Function sql_mode Create Function character_set_client collation_connection Database Collation
fn2 CREATE DEFINER=`role2` FUNCTION `fn2`() RETURNS int(11)
return (select sum(a+b) from t1) latin1 latin1_swedish_ci latin1_swedish_ci
select fn2();
fn2()
33
create definer=role3 function fn3() returns int return (select sum(a+b) from t1);
Warnings:
Note 1449 The user specified as a definer ('role3'@'%') does not exist
show create function fn3;
Function sql_mode Create Function character_set_client collation_connection Database Collation
fn3 CREATE DEFINER=`role3`@`%` FUNCTION `fn3`() RETURNS int(11)
return (select sum(a+b) from t1) latin1 latin1_swedish_ci latin1_swedish_ci
select fn3();
ERROR HY000: The user specified as a definer ('role3'@'%') does not exist
set global event_scheduler=on;
create definer=current_role event e1 on schedule every 1 second starts '2000-01-01' do
insert t1 values (111, 1, 0);
ERROR 0L000: Invalid definer
set role role1;
create definer=current_role event e1 on schedule every 1 second starts '2000-01-01' do
insert t1 values (111, 2, 0);
show create event e1;
Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation
e1 SYSTEM CREATE DEFINER=`role1` EVENT `e1` ON SCHEDULE EVERY 1 SECOND STARTS '2000-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO insert t1 values (111, 2, 0) latin1 latin1_swedish_ci latin1_swedish_ci
set role none;
create definer=role3 event e3 on schedule every 1 second starts '2000-01-01' do
insert t1 values (111, 3, 0);
Warnings:
Note 1449 The user specified as a definer ('role3'@'%') does not exist
show create event e3;
Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation
e3 SYSTEM CREATE DEFINER=`role3`@`%` EVENT `e3` ON SCHEDULE EVERY 1 SECOND STARTS '2000-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO insert t1 values (111, 3, 0) latin1 latin1_swedish_ci latin1_swedish_ci
create definer=role2 event e2 on schedule every 1 second starts '2000-01-01' do
insert t1 values (111, 4, 0);
show create event e2;
Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation
e2 SYSTEM CREATE DEFINER=`role2` EVENT `e2` ON SCHEDULE EVERY 1 SECOND STARTS '2000-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO insert t1 values (111, 4, 0) latin1 latin1_swedish_ci latin1_swedish_ci
set global event_scheduler=off;
select distinct * from t1;
a b c
1 10 100
111 4 0
2 20 200
delete from t1 where a=111;
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `test`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v1` (
`a+b` tinyint NOT NULL,
`c` tinyint NOT NULL
) ENGINE=MyISAM */;
SET character_set_client = @saved_cs_client;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v2` (
`a+b` tinyint NOT NULL,
`c` tinyint NOT NULL
) ENGINE=MyISAM */;
SET character_set_client = @saved_cs_client;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v3` (
`a+b` tinyint NOT NULL,
`c` tinyint NOT NULL
) ENGINE=MyISAM */;
SET character_set_client = @saved_cs_client;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v4` (
`a+b` tinyint NOT NULL,
`c` tinyint NOT NULL
) ENGINE=MyISAM */;
SET character_set_client = @saved_cs_client;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v5` (
`a+b` tinyint NOT NULL,
`c` tinyint NOT NULL
) ENGINE=MyISAM */;
SET character_set_client = @saved_cs_client;
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `mysqltest1`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO `t1` VALUES (1,10,100),(2,20,200);
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO `t2` VALUES (2,20,200);
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = latin1 */ ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`role1`*/ /*!50003 trigger tr1 before insert on t2 for each row
insert t1 values (111, 222, 333) */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = latin1 */ ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`role3`@`%`*/ /*!50003 trigger tr3 before update on t2 for each row
insert t1 values (111, 222, 333) */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = latin1 */ ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`role2`@``*/ /*!50003 trigger tr2 before delete on t2 for each row
insert t1 values (111, 222, 333) */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50106 SET @save_time_zone= @@TIME_ZONE */ ;
DELIMITER ;;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;;
/*!50003 SET character_set_client = latin1 */ ;;
/*!50003 SET character_set_results = latin1 */ ;;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;;
/*!50003 SET sql_mode = '' */ ;;
/*!50003 SET @saved_time_zone = @@time_zone */ ;;
/*!50003 SET time_zone = 'SYSTEM' */ ;;
/*!50106 CREATE*/ /*!50117 DEFINER=`role1`*/ /*!50106 EVENT `e1` ON SCHEDULE EVERY 1 SECOND STARTS '2000-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO insert t1 values (111, 2, 0) */ ;;
/*!50003 SET time_zone = @saved_time_zone */ ;;
/*!50003 SET sql_mode = @saved_sql_mode */ ;;
/*!50003 SET character_set_client = @saved_cs_client */ ;;
/*!50003 SET character_set_results = @saved_cs_results */ ;;
/*!50003 SET collation_connection = @saved_col_connection */ ;;
DELIMITER ;;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;;
/*!50003 SET character_set_client = latin1 */ ;;
/*!50003 SET character_set_results = latin1 */ ;;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;;
/*!50003 SET sql_mode = '' */ ;;
/*!50003 SET @saved_time_zone = @@time_zone */ ;;
/*!50003 SET time_zone = 'SYSTEM' */ ;;
/*!50106 CREATE*/ /*!50117 DEFINER=`role2`*/ /*!50106 EVENT `e2` ON SCHEDULE EVERY 1 SECOND STARTS '2000-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO insert t1 values (111, 4, 0) */ ;;
/*!50003 SET time_zone = @saved_time_zone */ ;;
/*!50003 SET sql_mode = @saved_sql_mode */ ;;
/*!50003 SET character_set_client = @saved_cs_client */ ;;
/*!50003 SET character_set_results = @saved_cs_results */ ;;
/*!50003 SET collation_connection = @saved_col_connection */ ;;
DELIMITER ;;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;;
/*!50003 SET character_set_client = latin1 */ ;;
/*!50003 SET character_set_results = latin1 */ ;;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;;
/*!50003 SET sql_mode = '' */ ;;
/*!50003 SET @saved_time_zone = @@time_zone */ ;;
/*!50003 SET time_zone = 'SYSTEM' */ ;;
/*!50106 CREATE*/ /*!50117 DEFINER=`role3`@`%`*/ /*!50106 EVENT `e3` ON SCHEDULE EVERY 1 SECOND STARTS '2000-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO insert t1 values (111, 3, 0) */ ;;
/*!50003 SET time_zone = @saved_time_zone */ ;;
/*!50003 SET sql_mode = @saved_sql_mode */ ;;
/*!50003 SET character_set_client = @saved_cs_client */ ;;
/*!50003 SET character_set_results = @saved_cs_results */ ;;
/*!50003 SET collation_connection = @saved_col_connection */ ;;
DELIMITER ;
/*!50106 SET TIME_ZONE= @save_time_zone */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = latin1 */ ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
CREATE DEFINER=`role1` FUNCTION `fn1`() RETURNS int(11)
return (select sum(a+b) from t1) ;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = latin1 */ ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
CREATE DEFINER=`role2` FUNCTION `fn2`() RETURNS int(11)
return (select sum(a+b) from t1) ;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = latin1 */ ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
CREATE DEFINER=`role3`@`%` FUNCTION `fn3`() RETURNS int(11)
return (select sum(a+b) from t1) ;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = latin1 */ ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
CREATE DEFINER=`role1` PROCEDURE `pr1`()
insert t1 values (111, 222, 333) ;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = latin1 */ ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
CREATE DEFINER=`role2`@`%` PROCEDURE `pr2`()
insert t1 values (111, 222, 333) ;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = latin1 */ ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = '' */ ;
DELIMITER ;;
CREATE DEFINER=`role3`@`%` PROCEDURE `pr3`()
insert t1 values (111, 222, 333) ;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
USE `test`;
/*!50001 DROP TABLE IF EXISTS `v1`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
/*!50001 SET @saved_cs_results = @@character_set_results */;
/*!50001 SET @saved_col_connection = @@collation_connection */;
/*!50001 SET character_set_client = latin1 */;
/*!50001 SET character_set_results = latin1 */;
/*!50001 SET collation_connection = latin1_swedish_ci */;
/*!50001 CREATE ALGORITHM=UNDEFINED DEFINER=`role1` SQL SECURITY DEFINER VIEW `v1` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` */;
/*!50001 SET character_set_client = @saved_cs_client */;
/*!50001 SET character_set_results = @saved_cs_results */;
/*!50001 SET collation_connection = @saved_col_connection */;
/*!50001 DROP TABLE IF EXISTS `v2`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
/*!50001 SET @saved_cs_results = @@character_set_results */;
/*!50001 SET @saved_col_connection = @@collation_connection */;
/*!50001 SET character_set_client = latin1 */;
/*!50001 SET character_set_results = latin1 */;
/*!50001 SET collation_connection = latin1_swedish_ci */;
/*!50001 CREATE ALGORITHM=UNDEFINED DEFINER=`role2` SQL SECURITY DEFINER VIEW `v2` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` */;
/*!50001 SET character_set_client = @saved_cs_client */;
/*!50001 SET character_set_results = @saved_cs_results */;
/*!50001 SET collation_connection = @saved_col_connection */;
/*!50001 DROP TABLE IF EXISTS `v3`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
/*!50001 SET @saved_cs_results = @@character_set_results */;
/*!50001 SET @saved_col_connection = @@collation_connection */;
/*!50001 SET character_set_client = latin1 */;
/*!50001 SET character_set_results = latin1 */;
/*!50001 SET collation_connection = latin1_swedish_ci */;
/*!50001 CREATE ALGORITHM=UNDEFINED */
/*!50013 DEFINER=`role3`@`%` SQL SECURITY DEFINER */
/*!50001 VIEW `v3` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` */;
/*!50001 SET character_set_client = @saved_cs_client */;
/*!50001 SET character_set_results = @saved_cs_results */;
/*!50001 SET collation_connection = @saved_col_connection */;
/*!50001 DROP TABLE IF EXISTS `v4`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
/*!50001 SET @saved_cs_results = @@character_set_results */;
/*!50001 SET @saved_col_connection = @@collation_connection */;
/*!50001 SET character_set_client = latin1 */;
/*!50001 SET character_set_results = latin1 */;
/*!50001 SET collation_connection = latin1_swedish_ci */;
/*!50001 CREATE ALGORITHM=UNDEFINED */
/*!50013 DEFINER=`foo`@`localhost` SQL SECURITY DEFINER */
/*!50001 VIEW `v4` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` */;
/*!50001 SET character_set_client = @saved_cs_client */;
/*!50001 SET character_set_results = @saved_cs_results */;
/*!50001 SET collation_connection = @saved_col_connection */;
/*!50001 DROP TABLE IF EXISTS `v5`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
/*!50001 SET @saved_cs_results = @@character_set_results */;
/*!50001 SET @saved_col_connection = @@collation_connection */;
/*!50001 SET character_set_client = latin1 */;
/*!50001 SET character_set_results = latin1 */;
/*!50001 SET collation_connection = latin1_swedish_ci */;
/*!50001 CREATE ALGORITHM=UNDEFINED */
/*!50013 DEFINER=`role4`@`%` SQL SECURITY DEFINER */
/*!50001 VIEW `v5` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` */;
/*!50001 SET character_set_client = @saved_cs_client */;
/*!50001 SET character_set_results = @saved_cs_results */;
/*!50001 SET collation_connection = @saved_col_connection */;
USE `mysqltest1`;
drop trigger tr1;
drop trigger tr2;
drop trigger tr3;
drop procedure pr1;
drop procedure pr2;
drop procedure pr3;
drop function fn1;
drop function fn2;
drop function fn3;
drop event e1;
drop event e2;
drop event e3;
drop view test.v1, test.v2, test.v3, test.v4, test.v5;
drop table t1, t2;
drop role role1, role2;
drop user foo@localhost;
drop database mysqltest1;
use test;
create user utest;
prepare stmt1 from 'grant select on *.* to utest';
execute stmt1;
show grants for utest;
Grants for utest@%
GRANT SELECT ON *.* TO 'utest'@'%'
drop user utest;
create role utest;
execute stmt1;
show grants for utest;
Grants for utest
GRANT SELECT ON *.* TO 'utest'
drop role utest;

View file

@ -1,11 +1,9 @@
create user 'test_user'@'localhost';
create user 'test_role1'@'';
update mysql.user set is_role='Y' where user='test_role1';
create user test_user@localhost;
create role test_role1;
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
create user 'test_role2'@'';
update mysql.user set is_role='Y' where user='test_role2';
create role test_role2;
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('',
'test_role1',
'test_role2');
@ -25,26 +23,6 @@ select * from roles_mapping;
HostFk UserFk RoleFk
test_role1 test_role2
newhost test_user_rm test_role1
rename user 'test_role2'@'' to 'test_role2_rm'@'';
select user, host from user where user like 'test%';
user host
test_role1
test_role2_rm
test_user_rm newhost
select * from roles_mapping;
HostFk UserFk RoleFk
test_role1 test_role2_rm
newhost test_user_rm test_role1
rename user 'test_role1'@'' to 'test_role1_rm'@'';
select user, host from user where user like 'test%';
user host
test_role1_rm
test_role2_rm
test_user_rm newhost
select * from roles_mapping;
HostFk UserFk RoleFk
test_role1_rm test_role2_rm
newhost test_user_rm test_role1_rm
delete from mysql.roles_mapping;
delete from mysql.user where user like 'test%';
flush privileges;

View file

@ -0,0 +1,49 @@
include/master-slave.inc
[connection master]
create role role1;
grant execute on test.* to role1;
grant role1 to current_user;
set role role1;
create definer=current_user procedure pcu() select current_user;
create definer=root@localhost procedure pu() select "root@localhost";
create definer=current_role procedure pcr() select current_role;
create definer=role1 procedure pr() select "role1";
show create procedure pcu;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pcu CREATE DEFINER=`root`@`localhost` PROCEDURE `pcu`()
select current_user latin1 latin1_swedish_ci latin1_swedish_ci
show create procedure pu;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pu CREATE DEFINER=`root`@`localhost` PROCEDURE `pu`()
select "root@localhost" latin1 latin1_swedish_ci latin1_swedish_ci
show create procedure pcr;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pcr CREATE DEFINER=`role1` PROCEDURE `pcr`()
select current_role latin1 latin1_swedish_ci latin1_swedish_ci
show create procedure pr;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pr CREATE DEFINER=`role1` PROCEDURE `pr`()
select "role1" latin1 latin1_swedish_ci latin1_swedish_ci
[connection slave]
show create procedure pcu;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pcu CREATE DEFINER=`root`@`localhost` PROCEDURE `pcu`()
select current_user latin1 latin1_swedish_ci latin1_swedish_ci
show create procedure pu;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pu CREATE DEFINER=`root`@`localhost` PROCEDURE `pu`()
select "root@localhost" latin1 latin1_swedish_ci latin1_swedish_ci
show create procedure pcr;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pcr CREATE DEFINER=`role1` PROCEDURE `pcr`()
select current_role latin1 latin1_swedish_ci latin1_swedish_ci
show create procedure pr;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
pr CREATE DEFINER=`role1` PROCEDURE `pr`()
select "role1" latin1 latin1_swedish_ci latin1_swedish_ci
drop procedure pcu;
drop procedure pu;
drop procedure pcr;
drop procedure pr;
drop role role1;
include/rpl_end.inc

View file

@ -27,8 +27,7 @@ Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv D
% test_role1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 Y
select * from mysql.user where user like 'test_role2';
Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string is_role
test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 Y
% test_role2 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 Y
% test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 Y
flush privileges;
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'

View file

@ -162,7 +162,7 @@ SELECT trigger_name, definer FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_n
trigger_name definer
trg1
trg2 @
trg3 @abc@def@@
trg3 @abc@def@@%
trg4 @hostname
trg5 @abcdef@@@hostname
@ -170,7 +170,7 @@ SELECT * FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_name;
TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE DEFINER CHARACTER_SET_CLIENT COLLATION_CONNECTION DATABASE_COLLATION
def mysqltest_db1 trg1 INSERT def mysqltest_db1 t1 0 NULL SET @a = 1 ROW BEFORE NULL NULL OLD NEW NULL latin1 latin1_swedish_ci latin1_swedish_ci
def mysqltest_db1 trg2 INSERT def mysqltest_db1 t1 0 NULL SET @a = 2 ROW AFTER NULL NULL OLD NEW NULL @ latin1 latin1_swedish_ci latin1_swedish_ci
def mysqltest_db1 trg3 UPDATE def mysqltest_db1 t1 0 NULL SET @a = 3 ROW BEFORE NULL NULL OLD NEW NULL @abc@def@@ latin1 latin1_swedish_ci latin1_swedish_ci
def mysqltest_db1 trg3 UPDATE def mysqltest_db1 t1 0 NULL SET @a = 3 ROW BEFORE NULL NULL OLD NEW NULL @abc@def@@% latin1 latin1_swedish_ci latin1_swedish_ci
def mysqltest_db1 trg4 UPDATE def mysqltest_db1 t1 0 NULL SET @a = 4 ROW AFTER NULL NULL OLD NEW NULL @hostname latin1 latin1_swedish_ci latin1_swedish_ci
def mysqltest_db1 trg5 DELETE def mysqltest_db1 t1 0 NULL SET @a = 5 ROW BEFORE NULL NULL OLD NEW NULL @abcdef@@@hostname latin1 latin1_swedish_ci latin1_swedish_ci

View file

@ -0,0 +1,330 @@
# create view
# create trigger
# create procedure
# create event
# mysqldump dumping the definer
let MYSQLD_DATADIR=`select @@datadir`;
create database mysqltest1;
use mysqltest1;
create table t1 (a int, b int, c int);
insert t1 values (1,10,100),(2,20,200);
# non-priv role granted
create role role1;
grant select (a) on mysqltest1.t1 to role1;
grant event,execute,trigger on mysqltest1.* to role1;
grant role1 to current_user;
# priv role
create role role2;
grant insert,select on mysqltest1.t1 to role2;
grant event,execute,trigger on mysqltest1.* to role2;
# create a non-priv user and a priv role granted to him
grant create view on mysqltest1.* to foo@localhost;
create role role4;
grant select on mysqltest1.t1 to role4;
grant role4 to foo@localhost;
##################################################
# views
##################################################
# no curent role = error
--error ER_MALFORMED_DEFINER
create definer=current_role view test.v1 as select a+b,c from t1;
# definer=current_role, but it has doesn't have enough privileges
set role role1;
create definer=current_role view test.v1 as select a+b,c from t1;
show create view test.v1;
set role none;
# definer=role_name, privileges ok
create definer=role2 view test.v2 as select a+b,c from t1;
show create view test.v2;
# definer=non_existent_role
create definer=role3 view test.v3 as select a+b,c from t1;
show create view test.v3;
connect (c1, localhost, foo,,mysqltest1);
connection c1;
show grants;
# role1 doesn't have enough privileges for v1 to work
--error ER_VIEW_INVALID
select * from test.v1;
# role2 is ok, v2 is ok
select * from test.v2;
# role3 is treated as a user name role3@%, doesn't exist, v3 fails
--error ER_ACCESS_DENIED_ERROR
select * from test.v3;
# fails, no SUPER - cannot specify a definer arbitrarily
--error ER_TABLEACCESS_DENIED_ERROR
create definer=role4 view test.v4 as select a+b,c from t1;
--error ER_TABLEACCESS_DENIED_ERROR
select * from t1;
set role role4;
select * from t1;
# can select from t1, but the view won't work, by default definer=current_user
create view test.v4 as select a+b,c from t1;
# now role4 is the current_role, can be specified as a definer
create definer=role4 view test.v5 as select a+b,c from t1;
--error ER_VIEW_INVALID
select * from test.v4;
select * from test.v5;
set role none;
--error ER_VIEW_INVALID
select * from test.v4;
select * from test.v5;
connection default;
drop role role4;
show create view test.v5;
--error ER_NO_SUCH_USER
select * from test.v5;
grant select on mysqltest1.t1 to role4;
show create view test.v5;
--error ER_NO_SUCH_USER
select * from test.v5;
# pretend it's an old view from before 10.0.5
perl;
local $/;
my $f= "$ENV{MYSQLD_DATADIR}/test/v5.frm";
open(F, '<', $f) or die "open(<$f): $!";
$_=<F>;
s/create-version=2/create-version=1/;
open(F, '>', $f) or die "open(>$f): $!";
syswrite F, $_ or die "syswrite($f): $!"
EOF
show create view test.v5;
select * from test.v5;
drop user role4;
##################################################
# trigger
##################################################
create table t2 select * from t1;
# no curent role = error
--error ER_MALFORMED_DEFINER
create definer=current_role trigger tr1 before insert on t2 for each row
insert t1 values (111, 222, 333);
# definer=current_role, but it has doesn't have enough privileges
set role role1;
create definer=current_role trigger tr1 before insert on t2 for each row
insert t1 values (111, 222, 333);
show create trigger tr1;
set role none;
--error ER_TABLEACCESS_DENIED_ERROR
insert t2 values (11,22,33);
select * from t1;
select * from t2;
# definer=role_name, privileges ok
create definer=role2 trigger tr2 before delete on t2 for each row
insert t1 values (111, 222, 333);
show create trigger tr2;
delete from t2 where a=1;
select * from t1;
select * from t2;
delete from t1 where a=111;
# definer=non_existent_role
create definer=role3 trigger tr3 before update on t2 for each row
insert t1 values (111, 222, 333);
show create trigger tr3;
--error ER_NO_SUCH_USER
update t2 set b=2 where a=2;
select * from t1;
select * from t2;
flush tables;
# change triggers to use pre-10.0.5 definer with an empty hostname
perl;
local $/;
my $f= "$ENV{MYSQLD_DATADIR}/mysqltest1/t2.TRG";
open(F, '<', $f) or die "open(<$f): $!";
$_=<F>;
s/'role2'/'role2\@'/;
s/`role2`/$&\@``/;
open(F, '>', $f) or die "open(>$f): $!";
syswrite F, $_ or die "syswrite($f): $!"
EOF
show create trigger tr2;
--error ER_NO_SUCH_USER
delete from t2 where a=2;
select * from t1;
select * from t2;
##################################################
# stored procedures
##################################################
# no curent role = error
--error ER_MALFORMED_DEFINER
create definer=current_role procedure pr1() insert t1 values (111, 222, 333);
# definer=current_role, but it has doesn't have enough privileges
set role role1;
create definer=current_role procedure pr1() insert t1 values (111, 222, 333);
show create procedure pr1;
set role none;
--error ER_TABLEACCESS_DENIED_ERROR
call pr1();
select * from t1;
# definer=role_name, privileges ok
create definer=role2 procedure pr2() insert t1 values (111, 222, 333);
show create procedure pr2;
call pr2();
select * from t1;
delete from t1 where a=111;
# definer=non_existent_role
create definer=role3 procedure pr3() insert t1 values (111, 222, 333);
show create procedure pr3;
--error ER_NO_SUCH_USER
call pr3();
select * from t1;
# change a procedure to use pre-10.0.5 definer with an empty hostname
update mysql.proc set definer='role2@' where definer='role2';
--error ER_NO_SUCH_USER
call pr2();
##################################################
# stored functions
##################################################
# no curent role = error
--error ER_MALFORMED_DEFINER
create definer=current_role function fn1() returns int return (select sum(a+b) from t1);
# definer=current_role, but it has doesn't have enough privileges
set role role1;
create definer=current_role function fn1() returns int return (select sum(a+b) from t1);
show create function fn1;
set role none;
--error ER_COLUMNACCESS_DENIED_ERROR
select fn1();
select * from t1;
# definer=role_name, privileges ok
create definer=role2 function fn2() returns int return (select sum(a+b) from t1);
show create function fn2;
select fn2();
# definer=non_existent_role
create definer=role3 function fn3() returns int return (select sum(a+b) from t1);
show create function fn3;
--error ER_NO_SUCH_USER
select fn3();
##################################################
# events
##################################################
set global event_scheduler=on;
# no curent role = error
--error ER_MALFORMED_DEFINER
create definer=current_role event e1 on schedule every 1 second starts '2000-01-01' do
insert t1 values (111, 1, 0);
# definer=current_role, but it has doesn't have enough privileges
set role role1;
create definer=current_role event e1 on schedule every 1 second starts '2000-01-01' do
insert t1 values (111, 2, 0);
show create event e1;
set role none;
# definer=non_existent_role
create definer=role3 event e3 on schedule every 1 second starts '2000-01-01' do
insert t1 values (111, 3, 0);
show create event e3;
# definer=role_name, privileges ok
create definer=role2 event e2 on schedule every 1 second starts '2000-01-01' do
insert t1 values (111, 4, 0);
show create event e2;
let $wait_condition=select count(*) >= 4 from t1;
--source include/wait_condition.inc
set global event_scheduler=off;
--sorted_result
select distinct * from t1;
delete from t1 where a=111;
##################################################
# mysqldump
##################################################
# note that LOCK TABLES won't work because v3 has invalid definer
--exec $MYSQL_DUMP --compact --events --routines --skip-lock-tables --databases test mysqltest1
##################################################
# cleanup
##################################################
drop trigger tr1;
drop trigger tr2;
drop trigger tr3;
drop procedure pr1;
drop procedure pr2;
drop procedure pr3;
drop function fn1;
drop function fn2;
drop function fn3;
drop event e1;
drop event e2;
drop event e3;
drop view test.v1, test.v2, test.v3, test.v4, test.v5;
drop table t1, t2;
drop role role1, role2;
drop user foo@localhost;
drop database mysqltest1;
use test;
##################################################
# reexecution
##################################################
create user utest;
prepare stmt1 from 'grant select on *.* to utest';
execute stmt1;
show grants for utest;
drop user utest;
create role utest;
execute stmt1;
show grants for utest;
drop role utest;

View file

@ -1,15 +1,11 @@
#create a user with no privileges
create user 'test_user'@'localhost';
create user 'test_role1'@'';
#manualy create role
update mysql.user set is_role='Y' where user='test_role1';
create user test_user@localhost;
create role test_role1;
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
create user 'test_role2'@'';
#manualy create role
update mysql.user set is_role='Y' where user='test_role2';
create role test_role2;
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('',
'test_role1',
'test_role2');
@ -26,19 +22,21 @@ select user, host from user where user like 'test%';
--sorted_result
select * from roles_mapping;
rename user 'test_role2'@'' to 'test_role2_rm'@'';
--sorted_result
select user, host from user where user like 'test%';
--sorted_result
select * from roles_mapping;
#role rename
rename user 'test_role1'@'' to 'test_role1_rm'@'';
--sorted_result
select user, host from user where user like 'test%';
--sorted_result
select * from roles_mapping;
######### role rename does not work yet
#rename user 'test_role2'@'' to 'test_role2_rm'@'';
#--sorted_result
#select user, host from user where user like 'test%';
#--sorted_result
#select * from roles_mapping;
#
##role rename
#rename user 'test_role1'@'' to 'test_role1_rm'@'';
#--sorted_result
#select user, host from user where user like 'test%';
#--sorted_result
#select * from roles_mapping;
delete from mysql.roles_mapping;
delete from mysql.user where user like 'test%';
flush privileges;

View file

@ -0,0 +1,40 @@
#
# replication of the DEFINER=current_role
#
--source include/master-slave.inc
create role role1;
grant execute on test.* to role1;
grant role1 to current_user;
set role role1;
create definer=current_user procedure pcu() select current_user;
create definer=root@localhost procedure pu() select "root@localhost";
create definer=current_role procedure pcr() select current_role;
create definer=role1 procedure pr() select "role1";
show create procedure pcu;
show create procedure pu;
show create procedure pcr;
show create procedure pr;
sync_slave_with_master;
connection slave;
echo [connection slave];
show create procedure pcu;
show create procedure pu;
show create procedure pcr;
show create procedure pr;
connection master;
drop procedure pcu;
drop procedure pu;
drop procedure pcr;
drop procedure pr;
drop role role1;
--source include/rpl_end.inc

View file

@ -30,34 +30,40 @@
host_name_str [OUT] Buffer to store host name part.
Must be not less than HOSTNAME_LENGTH + 1.
host_name_len [OUT] A place to store length of the host name part.
RETURN
0 - if only a user was set, no '@' was found
1 - if both user and host were set
*/
void parse_user(const char *user_id_str, size_t user_id_len,
char *user_name_str, size_t *user_name_len,
char *host_name_str, size_t *host_name_len)
int parse_user(const char *user_id_str, size_t user_id_len,
char *user_name_str, size_t *user_name_len,
char *host_name_str, size_t *host_name_len)
{
char *p= strrchr(user_id_str, '@');
if (!p)
{
*user_name_len= 0;
*user_name_len= user_id_len;
*host_name_len= 0;
}
else
{
*user_name_len= (uint) (p - user_id_str);
*host_name_len= (uint) (user_id_len - *user_name_len - 1);
if (*user_name_len > USERNAME_LENGTH)
*user_name_len= USERNAME_LENGTH;
if (*host_name_len > HOSTNAME_LENGTH)
*host_name_len= HOSTNAME_LENGTH;
memcpy(user_name_str, user_id_str, *user_name_len);
memcpy(host_name_str, p + 1, *host_name_len);
}
if (*user_name_len > USERNAME_LENGTH)
*user_name_len= USERNAME_LENGTH;
if (*host_name_len > HOSTNAME_LENGTH)
*host_name_len= HOSTNAME_LENGTH;
memcpy(user_name_str, user_id_str, *user_name_len);
memcpy(host_name_str, p + 1, *host_name_len);
user_name_str[*user_name_len]= 0;
host_name_str[*host_name_len]= 0;
return p != NULL;
}

View file

@ -2853,17 +2853,22 @@ bool Query_log_event::write(IO_CACHE* file)
user= thd->get_invoker_user();
host= thd->get_invoker_host();
}
else if (thd->security_ctx->priv_user)
else
{
Security_context *ctx= thd->security_ctx;
user.length= strlen(ctx->priv_user);
user.str= ctx->priv_user;
if (ctx->priv_host[0] != '\0')
if (thd->need_binlog_invoker() == THD::INVOKER_USER)
{
user.str= ctx->priv_user;
host.str= ctx->priv_host;
host.length= strlen(ctx->priv_host);
host.length= strlen(host.str);
}
else
{
user.str= ctx->priv_role;
host= null_lex_str; // XXX FIXME or empty_lex_str ?
}
user.length= strlen(user.str);
}
if (user.length > 0)

View file

@ -5489,9 +5489,8 @@ ER_PS_NO_RECURSION
ER_SP_CANT_SET_AUTOCOMMIT
eng "Not allowed to set autocommit from a stored function or trigger"
ger "Es ist nicht erlaubt, innerhalb einer gespeicherten Funktion oder eines Triggers AUTOCOMMIT zu setzen"
ER_MALFORMED_DEFINER
eng "Definer is not fully qualified"
ger "Definierer des View ist nicht vollständig spezifiziert"
ER_MALFORMED_DEFINER 0L000
eng "Invalid definer"
ER_VIEW_FRM_NO_USER
eng "View '%-.192s'.'%-.192s' has no definer information (old table format). Current user is used as definer. Please recreate the view!"
ger "View '%-.192s'.'%-.192s' hat keine Definierer-Information (altes Tabellenformat). Der aktuelle Benutzer wird als Definierer verwendet. Bitte erstellen Sie den View neu"

View file

@ -662,9 +662,14 @@ db_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
close_system_tables(thd, &open_tables_state_backup);
table= 0;
parse_user(definer, strlen(definer),
definer_user_name.str, &definer_user_name.length,
definer_host_name.str, &definer_host_name.length);
if (parse_user(definer, strlen(definer),
definer_user_name.str, &definer_user_name.length,
definer_host_name.str, &definer_host_name.length) &&
definer_user_name.length && !definer_host_name.length)
{
// 'user@' -> 'user@%'
definer_host_name= host_not_specified;
}
ret= db_load_routine(thd, type, name, sphp,
sql_mode, params, returns, body, chistics,
@ -975,7 +980,8 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
{
int ret;
TABLE *table;
char definer[USER_HOST_BUFF_SIZE];
char definer_buf[USER_HOST_BUFF_SIZE];
LEX_STRING definer;
ulonglong saved_mode= thd->variables.sql_mode;
MDL_key::enum_mdl_namespace mdl_type= type == TYPE_ENUM_FUNCTION ?
MDL_key::FUNCTION : MDL_key::PROCEDURE;
@ -1012,8 +1018,7 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
restore_record(table, s->default_values); // Get default values for fields
/* NOTE: all needed privilege checks have been already done. */
strxnmov(definer, sizeof(definer)-1, thd->lex->definer->user.str, "@",
thd->lex->definer->host.str, NullS);
thd->lex->definer->set_lex_string(&definer, definer_buf);
if (table->s->fields < MYSQL_PROC_FIELD_COUNT)
{
@ -1088,7 +1093,7 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_DEFINER]->
store(definer, (uint)strlen(definer), system_charset_info);
store(definer.str, definer.length, system_charset_info);
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();

View file

@ -2549,8 +2549,13 @@ sp_head::set_definer(const char *definer, uint definerlen)
char host_name_holder[HOSTNAME_LENGTH + 1];
LEX_STRING host_name= { host_name_holder, HOSTNAME_LENGTH };
parse_user(definer, definerlen, user_name.str, &user_name.length,
host_name.str, &host_name.length);
if (parse_user(definer, definerlen, user_name.str, &user_name.length,
host_name.str, &host_name.length) &&
user_name.length && !host_name.length)
{
// 'user@' -> 'user@%'
host_name= host_not_specified;
}
set_definer(&user_name, &host_name);
}

View file

@ -314,27 +314,19 @@ public:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
static void update_hostname(acl_host_and_ip *host, const char *hostname);
static ulong get_sort(uint count,...);
static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
const char *ip);
static bool show_proxy_grants (THD *thd,
const char *username, const char *hostname,
char *buff, size_t buffsize);
static bool show_role_grants(THD *thd, const char *username, const char *hostname,
ACL_USER_BASE *acl_entry,
char *buff, size_t buffsize);
static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry,
bool handle_as_role,
char *buff, size_t buffsize);
static bool show_database_privileges(THD *thd,
const char *username,
const char *hostname,
bool handle_as_role,
char *buff, size_t buffsize);
static bool show_table_and_column_privileges(THD *thd,
const char *username,
const char *hostname,
bool handle_as_role,
char *buff, size_t buffsize);
static bool compare_hostname(const acl_host_and_ip *, const char *, const char *);
static bool show_proxy_grants (THD *, const char *, const char *,
char *, size_t);
static bool show_role_grants(THD *, const char *, const char *,
ACL_USER_BASE *, char *, size_t);
static bool show_global_privileges(THD *, ACL_USER_BASE *,
bool, char *, size_t);
static bool show_database_privileges(THD *, const char *, const char *,
char *, size_t);
static bool show_table_and_column_privileges(THD *, const char *, const char *,
char *, size_t);
static int show_routine_grants(THD *, const char *, const char *, HASH *,
const char *, int, char *, int);
class ACL_PROXY_USER :public ACL_ACCESS
{
@ -1757,57 +1749,86 @@ bool acl_getroot(Security_context *sctx, char *user, char *host,
sctx->db_access= 0;
*sctx->priv_user= *sctx->priv_host= *sctx->priv_role= 0;
/*
Find acl entry in user database.
This is specially tailored to suit the check we do for CALL of
a stored procedure; user is set to what is actually a
priv_user, which can be ''.
*/
for (i=0 ; i < acl_users.elements ; i++)
if (host[0]) // User, not Role
{
ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
if ((!acl_user_tmp->user.str && !user[0]) ||
(acl_user_tmp->user.str && strcmp(user, acl_user_tmp->user.str) == 0))
/*
Find acl entry in user database.
This is specially tailored to suit the check we do for CALL of
a stored procedure; user is set to what is actually a
priv_user, which can be ''.
*/
for (i=0 ; i < acl_users.elements ; i++)
{
if (compare_hostname(&acl_user_tmp->host, host, ip))
ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
if ((!acl_user_tmp->user.str && !user[0]) ||
(acl_user_tmp->user.str && strcmp(user, acl_user_tmp->user.str) == 0))
{
acl_user= acl_user_tmp;
res= 0;
break;
if (compare_hostname(&acl_user_tmp->host, host, ip))
{
acl_user= acl_user_tmp;
res= 0;
break;
}
}
}
if (acl_user)
{
for (i=0 ; i < acl_dbs.elements ; i++)
{
ACL_DB *acl_db= dynamic_element(&acl_dbs, i, ACL_DB*);
if (!acl_db->user ||
(user && user[0] && !strcmp(user, acl_db->user)))
{
if (compare_hostname(&acl_db->host, host, ip))
{
if (!acl_db->db || (db && !wild_compare(db, acl_db->db, 0)))
{
sctx->db_access= acl_db->access;
break;
}
}
}
}
sctx->master_access= acl_user->access;
if (acl_user->user.str)
strmake_buf(sctx->priv_user, user);
if (acl_user->host.hostname)
strmake_buf(sctx->priv_host, acl_user->host.hostname);
}
}
else // Role, not User
{
ACL_ROLE *acl_role= find_acl_role(user);
if (acl_role)
{
res= 0;
for (i=0 ; i < acl_dbs.elements ; i++)
{
ACL_DB *acl_db= dynamic_element(&acl_dbs, i, ACL_DB*);
if (!acl_db->user ||
(user && user[0] && !strcmp(user, acl_db->user)))
{
if (compare_hostname(&acl_db->host, "", ""))
{
if (!acl_db->db || (db && !wild_compare(db, acl_db->db, 0)))
{
sctx->db_access= acl_db->access;
break;
}
}
}
}
sctx->master_access= acl_role->access;
if (acl_role->user.str)
strmake_buf(sctx->priv_user, user);
sctx->priv_host[0]= 0;
}
}
if (acl_user)
{
for (i=0 ; i < acl_dbs.elements ; i++)
{
ACL_DB *acl_db= dynamic_element(&acl_dbs, i, ACL_DB*);
if (!acl_db->user ||
(user && user[0] && !strcmp(user, acl_db->user)))
{
if (compare_hostname(&acl_db->host, host, ip))
{
if (!acl_db->db || (db && !wild_compare(db, acl_db->db, 0)))
{
sctx->db_access= acl_db->access;
break;
}
}
}
}
sctx->master_access= acl_user->access;
if (acl_user->user.str)
strmake_buf(sctx->priv_user, user);
else
*sctx->priv_user= 0;
if (acl_user->host.hostname)
strmake_buf(sctx->priv_host, acl_user->host.hostname);
else
*sctx->priv_host= 0;
}
mysql_mutex_unlock(&acl_cache->lock);
DBUG_RETURN(res);
}
@ -3039,7 +3060,12 @@ bool is_acl_user(const char *host, const char *user)
return TRUE;
mysql_mutex_lock(&acl_cache->lock);
res= find_user_no_anon(host, user, TRUE) != NULL;
if (*host) // User
res= find_user_no_anon(host, user, TRUE) != NULL;
else // Role
res= find_acl_role(user) != NULL;
mysql_mutex_unlock(&acl_cache->lock);
return res;
}
@ -3345,13 +3371,13 @@ static bool test_if_create_new_users(THD *thd)
static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo,
ulong rights, bool revoke_grant,
bool can_create_user, bool no_auto_create,
bool handle_as_role)
bool can_create_user, bool no_auto_create)
{
int error = -1;
bool old_row_exists=0;
char what= (revoke_grant) ? 'N' : 'Y';
uchar user_key[MAX_KEY_LENGTH];
bool handle_as_role= combo.is_role();
LEX *lex= thd->lex;
DBUG_ENTER("replace_user_table");
@ -4832,26 +4858,6 @@ table_error:
}
/*
A user name specified without a host can be either a
username@% (where '@%' is added automatically by the parser)
or a role name. Treat it as a role, if such a role exists.
*/
static ACL_ROLE *find_and_mark_as_role(LEX_USER *user)
{
if (user->host.str == host_not_specified.str)
{
ACL_ROLE *role= find_acl_role(user->user.str);
if (role)
{
user->host= empty_lex_str;
return role;
}
}
return NULL;
}
/*
Store table level and column level grants in the privilege tables
@ -5018,21 +5024,16 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
{
int error;
GRANT_TABLE *grant_table;
if (!(Str= get_current_user(thd, tmp_Str)))
if (!(Str= get_current_user(thd, tmp_Str, false)))
{
result= TRUE;
continue;
}
bool handle_as_role= FALSE;
if (find_and_mark_as_role(Str))
handle_as_role= TRUE;
/* Create user if needed */
error=replace_user_table(thd, tables[0].table, *Str,
0, revoke_grant, create_new_users,
test(thd->variables.sql_mode &
MODE_NO_AUTO_CREATE_USER), handle_as_role);
MODE_NO_AUTO_CREATE_USER));
if (error)
{
result= TRUE; // Remember error
@ -5227,21 +5228,16 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
{
int error;
GRANT_NAME *grant_name;
if (!(Str= get_current_user(thd, tmp_Str)))
if (!(Str= get_current_user(thd, tmp_Str, false)))
{
result= TRUE;
continue;
}
bool handle_as_role= FALSE;
if (find_and_mark_as_role(Str))
handle_as_role=TRUE;
/* Create user if needed */
error=replace_user_table(thd, tables[0].table, *Str,
0, revoke_grant, create_new_users,
test(thd->variables.sql_mode &
MODE_NO_AUTO_CREATE_USER), handle_as_role);
MODE_NO_AUTO_CREATE_USER));
if (error)
{
result= TRUE; // Remember error
@ -5297,15 +5293,14 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
DBUG_RETURN(result);
}
static void append_user(String *str, const char *u, const char *h,
bool handle_as_role)
static void append_user(String *str, const char *u, const char *h)
{
if (str->length())
str->append(',');
str->append('\'');
str->append(u);
/* hostname part is not relevant for roles, it is always empty */
if (!handle_as_role)
if (*h)
{
str->append(STRING_WITH_LEN("'@'"));
str->append(h);
@ -5381,13 +5376,13 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
/* current_role is NONE */
if (!thd->security_ctx->priv_role[0])
{
append_user(&wrong_users, "NONE", "", TRUE);
append_user(&wrong_users, "NONE", "");
result= 1;
continue;
}
if (!(role_as_user= find_acl_role(thd->security_ctx->priv_role)))
{
append_user(&wrong_users, thd->security_ctx->priv_role, "", TRUE);
append_user(&wrong_users, thd->security_ctx->priv_role, "");
result= 1;
continue;
}
@ -5395,18 +5390,26 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
/* can not grant current_role to current_role */
if (granted_role->user.str == current_role.str)
{
append_user(&wrong_users, thd->security_ctx->priv_role, "", TRUE);
append_user(&wrong_users, thd->security_ctx->priv_role, "");
result= 1;
continue;
}
username= thd->security_ctx->priv_role;
hostname= (char *)"";
hostname= const_cast<char*>("");
}
else if (user->user.str == current_user.str)
{
role_as_user= NULL;
username= thd->security_ctx->priv_user;
hostname= thd->security_ctx->priv_host;
}
else
{
role_as_user= find_and_mark_as_role(user);
if ((role_as_user= find_acl_role(user->user.str)))
hostname= const_cast<char*>("");
else
hostname= user->host.str ? user->host.str : host_not_specified.str;
username= user->user.str;
hostname= user->host.str;
}
ROLE_GRANT_PAIR *mapping, *hash_entry;
@ -5421,7 +5424,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
/* role or user does not exist*/
if (res == -1)
{
append_user(&wrong_users, username, hostname, role_as_user != NULL);
append_user(&wrong_users, username, hostname);
result= 1;
continue;
}
@ -5434,7 +5437,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
traverse_role_graph(role, NULL, NULL, NULL, role_explore_detect_cycle,
NULL) == 2)
{
append_user(&wrong_users, username, hostname, TRUE);
append_user(&wrong_users, username, "");
result= 1;
/* need to rollback the mapping added previously */
remove_role_user_mapping(mapping);
@ -5450,7 +5453,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
/* grant was already removed or never existed */
if (!hash_entry)
{
append_user(&wrong_users, username, hostname, role_as_user != NULL);
append_user(&wrong_users, username, hostname);
result= 1;
continue;
}
@ -5458,7 +5461,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
int res= remove_role_user_mapping(mapping);
if (res == -1)
{
append_user(&wrong_users, username, hostname, role_as_user != NULL);
append_user(&wrong_users, username, hostname);
result= 1;
continue;
}
@ -5467,7 +5470,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
/* write into the roles_mapping table */
if (replace_roles_mapping_table(tables.table, mapping, revoke))
{
append_user(&wrong_users, username, hostname, TRUE);
append_user(&wrong_users, username, "");
result= 1;
if (!revoke)
{
@ -5599,10 +5602,17 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
mysql_mutex_lock(&acl_cache->lock);
grant_version++;
if (proxied_user)
{
if (!(proxied_user= get_current_user(thd, proxied_user, false)))
DBUG_RETURN(TRUE);
DBUG_ASSERT(proxied_user->host.length); // not a Role
}
int result=0;
while ((tmp_Str = str_list++))
{
if (!(Str= get_current_user(thd, tmp_Str)))
if (!(Str= get_current_user(thd, tmp_Str, false)))
{
result= TRUE;
continue;
@ -5615,14 +5625,10 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
if (tmp_Str->user.str == current_user.str && tmp_Str->password.str)
Str->password= tmp_Str->password;
bool handle_as_role= FALSE;
if (find_and_mark_as_role(Str))
handle_as_role= TRUE;
if (replace_user_table(thd, tables[0].table, *Str,
(!db ? rights : 0), revoke_grant, create_new_users,
test(thd->variables.sql_mode &
MODE_NO_AUTO_CREATE_USER), handle_as_role))
MODE_NO_AUTO_CREATE_USER)))
result= -1;
else if (db)
{
@ -6870,14 +6876,6 @@ static uint command_lengths[]=
};
static int show_routine_grants(THD *thd,
const char *username,
const char *hostname,
HASH *hash,
const char *type, int typelen,
bool handle_as_role,
char *buff, int buffsize);
bool print_grants_for_role(THD *thd, ACL_ROLE * role,
char *buff, size_t buffsize)
{
@ -6887,18 +6885,18 @@ bool print_grants_for_role(THD *thd, ACL_ROLE * role,
if (show_global_privileges(thd, role, TRUE, buff, buffsize))
return TRUE;
if (show_database_privileges(thd, role->user.str, "", TRUE, buff, buffsize))
if (show_database_privileges(thd, role->user.str, "", buff, buffsize))
return TRUE;
if (show_table_and_column_privileges(thd, role->user.str, "", TRUE, buff, buffsize))
if (show_table_and_column_privileges(thd, role->user.str, "", buff, buffsize))
return TRUE;
if (show_routine_grants(thd, role->user.str, "", &proc_priv_hash,
STRING_WITH_LEN("PROCEDURE"), TRUE, buff, buffsize))
STRING_WITH_LEN("PROCEDURE"), buff, buffsize))
return TRUE;
if (show_routine_grants(thd, role->user.str, "", &func_priv_hash,
STRING_WITH_LEN("FUNCTION"), TRUE, buff, buffsize))
STRING_WITH_LEN("FUNCTION"), buff, buffsize))
return TRUE;
return FALSE;
@ -6951,7 +6949,8 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
}
else
{
if (find_and_mark_as_role(lex_user))
lex_user= get_current_user(thd, lex_user, false);
if (lex_user->is_role())
{
rolename= lex_user->user.str;
}
@ -7010,28 +7009,28 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
};
/* Add database access */
if (show_database_privileges(thd, username, hostname, FALSE, buff, sizeof(buff)))
if (show_database_privileges(thd, username, hostname, buff, sizeof(buff)))
{
error= -1;
goto end;
}
/* Add table & column access */
if (show_table_and_column_privileges(thd, username, hostname, FALSE, buff, sizeof(buff)))
if (show_table_and_column_privileges(thd, username, hostname, buff, sizeof(buff)))
{
error= -1;
goto end;
}
if (show_routine_grants(thd, username, hostname, &proc_priv_hash,
STRING_WITH_LEN("PROCEDURE"), FALSE, buff, sizeof(buff)))
STRING_WITH_LEN("PROCEDURE"), buff, sizeof(buff)))
{
error= -1;
goto end;
}
if (show_routine_grants(thd, username, hostname, &func_priv_hash,
STRING_WITH_LEN("FUNCTION"), FALSE, buff, sizeof(buff)))
STRING_WITH_LEN("FUNCTION"), buff, sizeof(buff)))
{
error= -1;
goto end;
@ -7267,7 +7266,6 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry,
static bool show_database_privileges(THD *thd,
const char *username,
const char *hostname,
bool handle_as_role,
char *buff, size_t buffsize)
{
ACL_DB *acl_db;
@ -7295,12 +7293,14 @@ static bool show_database_privileges(THD *thd,
if (!strcmp(username, user) &&
!my_strcasecmp(system_charset_info, hostname, host))
{
/* do not print inherited access bits, the role bits present in the
table are what matters */
if (handle_as_role)
want_access=acl_db->initial_access;
else
/*
do not print inherited access bits for roles,
the role bits present in the table are what matters
*/
if (*hostname) // User
want_access=acl_db->access;
else // Role
want_access=acl_db->initial_access;
if (want_access)
{
String db(buff,sizeof(buff),system_charset_info);
@ -7331,7 +7331,7 @@ static bool show_database_privileges(THD *thd,
db.append (STRING_WITH_LEN(".* TO '"));
db.append(username, strlen(username),
system_charset_info);
if (!handle_as_role)
if (*hostname)
{
db.append (STRING_WITH_LEN("'@'"));
// host and lex_user->host are equal except for case
@ -7356,7 +7356,6 @@ static bool show_database_privileges(THD *thd,
static bool show_table_and_column_privileges(THD *thd,
const char *username,
const char *hostname,
bool handle_as_role,
char *buff, size_t buffsize)
{
uint counter, index;
@ -7385,16 +7384,16 @@ static bool show_table_and_column_privileges(THD *thd,
{
ulong table_access;
ulong cols_access;
if (handle_as_role)
{
table_access= grant_table->init_privs;
cols_access= grant_table->init_cols;
}
else
if (*hostname) // User
{
table_access= grant_table->privs;
cols_access= grant_table->cols;
}
else // Role
{
table_access= grant_table->init_privs;
cols_access= grant_table->init_cols;
}
if ((table_access | cols_access) != 0)
{
@ -7435,8 +7434,8 @@ static bool show_table_and_column_privileges(THD *thd,
{
GRANT_COLUMN *grant_column = (GRANT_COLUMN*)
my_hash_element(hash_columns,col_index);
if ((!handle_as_role && (grant_column->rights & j)) ||
(handle_as_role && (grant_column->init_rights & j)))
if (j & (*hostname ? grant_column->rights // User
: grant_column->init_rights)) // Role
{
if (!found_col)
{
@ -7475,7 +7474,7 @@ static bool show_table_and_column_privileges(THD *thd,
global.append(STRING_WITH_LEN(" TO '"));
global.append(username, strlen(username),
system_charset_info);
if (!handle_as_role)
if (*hostname)
{
global.append(STRING_WITH_LEN("'@'"));
// host and lex_user->host are equal except for case
@ -7499,9 +7498,7 @@ static bool show_table_and_column_privileges(THD *thd,
static int show_routine_grants(THD* thd,
const char *username, const char *hostname,
HASH *hash,
const char *type, int typelen,
bool handle_as_role,
HASH *hash, const char *type, int typelen,
char *buff, int buffsize)
{
uint counter, index;
@ -7529,10 +7526,10 @@ static int show_routine_grants(THD* thd,
!my_strcasecmp(system_charset_info, hostname, host))
{
ulong proc_access;
if (handle_as_role)
proc_access= grant_proc->init_privs;
else
if (*hostname) // User
proc_access= grant_proc->privs;
else // Role
proc_access= grant_proc->init_privs;
if (proc_access != 0)
{
@ -7572,7 +7569,7 @@ static int show_routine_grants(THD* thd,
global.append(STRING_WITH_LEN(" TO '"));
global.append(username, strlen(username),
system_charset_info);
if (!handle_as_role)
if (*hostname)
{
global.append(STRING_WITH_LEN("'@'"));
// host and lex_user->host are equal except for case
@ -8232,9 +8229,15 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
table->key_info->key_part[1].store_length);
key_copy(user_key, table->record[0], table->key_info, key_prefix_length);
if ((error= table->file->ha_index_read_idx_map(table->record[0], 0,
user_key, (key_part_map)3,
HA_READ_KEY_EXACT)))
error= table->file->ha_index_read_idx_map(table->record[0], 0,
user_key, (key_part_map)3,
HA_READ_KEY_EXACT);
if (!error && !*host_str)
{ // verify that we got a role or a user, as needed
if (check_is_role(table) != user_from->is_role())
error= HA_ERR_KEY_NOT_FOUND;
}
if (error)
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
{
@ -8371,7 +8374,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
DBUG_RETURN(0);
/* same. no roles in PROXY_USERS_ACL */
if (struct_no == PROXY_USERS_ACL && !user_from->host.length)
if (struct_no == PROXY_USERS_ACL && user_from->is_role())
DBUG_RETURN(0);
if (struct_no == ROLE_ACL) //no need to scan the structures in this case
@ -8678,8 +8681,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
{
int result= 0;
int found;
bool handle_as_role= user_from->is_role();
DBUG_ENTER("handle_grant_data");
if (user_to)
DBUG_ASSERT(handle_as_role == user_to->is_role());
/* Handle user table. */
if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0)
{
@ -8688,20 +8695,32 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
}
else
{
/* Handle user array. */
if ((handle_grant_struct(USER_ACL, drop, user_from, user_to)) || found)
if (handle_as_role)
{
result= 1; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
if (! drop && ! user_to)
goto end;
if ((handle_grant_struct(ROLE_ACL, drop, user_from, user_to)) || found)
{
result= 1; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
if (! drop && ! user_to)
goto end;
}
else
if (find_user_no_anon(user_from->host.str, user_from->user.str, TRUE))
goto end; // looking for a role, found a user
}
if ((handle_grant_struct(ROLE_ACL, drop, user_from, user_to)) || found)
else
{
result= 1; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
if (! drop && ! user_to)
goto end;
/* Handle user array. */
if ((handle_grant_struct(USER_ACL, drop, user_from, user_to)) || found)
{
result= 1; /* At least one record/element found. */
/* If search is requested, we do not need to search further. */
if (! drop && ! user_to)
goto end;
}
else
if (find_acl_role(user_from->user.str))
goto end; // looking for a user, found a role
}
}
@ -8821,14 +8840,14 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop,
DBUG_RETURN(result);
}
static void append_user(String *str, LEX_USER *user, bool handle_as_role)
static void append_user(String *str, LEX_USER *user)
{
if (str->length())
str->append(',');
str->append('\'');
str->append(user->user.str);
/* hostname part is not relevant for roles, it is always empty */
if (!handle_as_role)
if (!user->is_role())
{
str->append(STRING_WITH_LEN("'@'"));
str->append(user->host.str);
@ -8854,7 +8873,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role)
{
int result;
String wrong_users;
LEX_USER *user_name, *tmp_user_name;
LEX_USER *user_name;
List_iterator <LEX_USER> user_list(list);
TABLE_LIST tables[GRANT_TABLES];
bool some_users_created= FALSE;
@ -8868,30 +8887,8 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role)
mysql_rwlock_wrlock(&LOCK_grant);
mysql_mutex_lock(&acl_cache->lock);
while ((tmp_user_name= user_list++))
while ((user_name= user_list++))
{
if (handle_as_role)
{
user_name= tmp_user_name;
user_name->host.str= (char *)"";
user_name->host.length= 0;
/* role already exists */
if (find_acl_role(user_name->user.str))
{
append_user(&wrong_users, user_name, TRUE);
result = TRUE;
continue;
}
}
else
{
if (!(user_name= get_current_user(thd, tmp_user_name)))
{
result= TRUE;
continue;
}
}
if (!user_name->host.str)
user_name->host= host_not_specified;
@ -8901,17 +8898,16 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role)
*/
if (handle_grant_data(tables, 0, user_name, NULL))
{
append_user(&wrong_users, user_name, handle_as_role);
append_user(&wrong_users, user_name);
result= TRUE;
continue;
}
some_users_created= TRUE;
if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0,
handle_as_role))
if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0))
{
append_user(&wrong_users, user_name, handle_as_role);
append_user(&wrong_users, user_name);
result= TRUE;
}
}
@ -8966,31 +8962,17 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role)
while ((tmp_user_name= user_list++))
{
if (handle_as_role)
user_name= get_current_user(thd, tmp_user_name, false);
if (!user_name || handle_as_role != user_name->is_role())
{
user_name= tmp_user_name;
user_name->host.str= (char *)"";
user_name->host.length= 0;
if (!find_acl_role(user_name->user.str))
{
append_user(&wrong_users, user_name, TRUE);
result= TRUE;
continue;
}
}
else
{
if (!(user_name= get_current_user(thd, tmp_user_name)))
{
result= TRUE;
continue;
}
append_user(&wrong_users, tmp_user_name);
result= TRUE;
continue;
}
if (handle_grant_data(tables, 1, user_name, NULL) <= 0)
{
append_user(&wrong_users, user_name, handle_as_role);
append_user(&wrong_users, user_name);
result= TRUE;
continue;
}
@ -9058,18 +9040,21 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
while ((tmp_user_from= user_list++))
{
if (!(user_from= get_current_user(thd, tmp_user_from)))
{
result= TRUE;
continue;
}
tmp_user_to= user_list++;
if (!(user_to= get_current_user(thd, tmp_user_to)))
if (!(user_from= get_current_user(thd, tmp_user_from, false)) ||
user_from->is_role())
{
append_user(&wrong_users, user_from);
result= TRUE;
continue;
}
if (!(user_to= get_current_user(thd, tmp_user_to, false)) ||
user_to->is_role())
{
append_user(&wrong_users, user_to);
result= TRUE;
continue;
}
DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */
/*
Search all in-memory structures and grant tables
@ -9079,7 +9064,7 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
handle_grant_data(tables, 0, user_from, user_to) <= 0)
{
/* NOTE TODO renaming roles is not yet implemented */
append_user(&wrong_users, user_from, FALSE);
append_user(&wrong_users, user_from);
result= TRUE;
continue;
}
@ -9139,7 +9124,7 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
List_iterator <LEX_USER> user_list(list);
while ((tmp_lex_user= user_list++))
{
if (!(lex_user= get_current_user(thd, tmp_lex_user)))
if (!(lex_user= get_current_user(thd, tmp_lex_user, false)))
{
result= -1;
continue;
@ -9150,8 +9135,7 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
continue;
}
if (replace_user_table(thd, tables[0].table,
*lex_user, ~(ulong)0, 1, 0, 0, 0))
if (replace_user_table(thd, tables[0].table, *lex_user, ~(ulong)0, 1, 0, 0))
{
result= -1;
continue;
@ -10257,6 +10241,47 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name,
#endif
/**
Retuns information about user or current user.
@param[in] thd thread handler
@param[in] user user
@return
- On success, return a valid pointer to initialized
LEX_USER, which contains user information.
- On error, return 0.
*/
LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock)
{
if (user->user.str == current_user.str) // current_user
return create_default_definer(thd, false);
if (user->user.str == current_role.str) // current_role
return create_default_definer(thd, true);
if (user->host.str == NULL) // Possibly a role
{
// to be reexecution friendly we have to make a copy
LEX_USER *dup= (LEX_USER*) thd->memdup(user, sizeof(*user));
if (!dup)
return 0;
if (lock)
mysql_mutex_lock(&acl_cache->lock);
if (find_acl_role(dup->user.str))
dup->host= empty_lex_str;
else
dup->host= host_not_specified;
if (lock)
mysql_mutex_unlock(&acl_cache->lock);
return dup;
}
return user;
}
struct ACL_internal_schema_registry_entry
{
const LEX_STRING *m_name;

View file

@ -938,7 +938,7 @@ THD::THD()
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
m_internal_handler= NULL;
m_binlog_invoker= FALSE;
m_binlog_invoker= INVOKER_NONE;
arena_for_cached_items= 0;
memset(&invoker_user, 0, sizeof(invoker_user));
memset(&invoker_host, 0, sizeof(invoker_host));
@ -1890,7 +1890,7 @@ void THD::cleanup_after_query()
where= THD::DEFAULT_WHERE;
/* reset table map for multi-table update */
table_map_for_update= 0;
m_binlog_invoker= FALSE;
m_binlog_invoker= INVOKER_NONE;
#ifndef EMBEDDED_LIBRARY
if (rli_slave)
@ -4341,9 +4341,9 @@ void THD::leave_locked_tables_mode()
locked_tables_mode= LTM_NONE;
}
void THD::get_definer(LEX_USER *definer)
void THD::get_definer(LEX_USER *definer, bool role)
{
binlog_invoker();
binlog_invoker(role);
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
if (slave_thread && has_invoker())
{
@ -4355,7 +4355,7 @@ void THD::get_definer(LEX_USER *definer)
}
else
#endif
get_default_definer(this, definer);
get_default_definer(this, definer, role);
}

View file

@ -3153,9 +3153,11 @@ public:
}
void leave_locked_tables_mode();
int decide_logging_format(TABLE_LIST *tables);
void binlog_invoker() { m_binlog_invoker= TRUE; }
bool need_binlog_invoker() { return m_binlog_invoker; }
void get_definer(LEX_USER *definer);
enum need_invoker { INVOKER_NONE=0, INVOKER_USER, INVOKER_ROLE};
void binlog_invoker(bool role) { m_binlog_invoker= role ? INVOKER_ROLE : INVOKER_USER; }
enum need_invoker need_binlog_invoker() { return m_binlog_invoker; }
void get_definer(LEX_USER *definer, bool role);
void set_invoker(const LEX_STRING *user, const LEX_STRING *host)
{
invoker_user= *user;
@ -3230,14 +3232,15 @@ private:
Diagnostics_area main_da;
/**
It will be set TURE if CURRENT_USER() is called in account management
statements or default definer is set in CREATE/ALTER SP, SF, Event,
TRIGGER or VIEW statements.
It will be set if CURRENT_USER() or CURRENT_ROLE() is called in account
management statements or default definer is set in CREATE/ALTER SP, SF,
Event, TRIGGER or VIEW statements.
Current user will be binlogged into Query_log_event if m_binlog_invoker
is TRUE; It will be stored into invoker_host and invoker_user by SQL thread.
Current user or role will be binlogged into Query_log_event if
m_binlog_invoker is not NONE; It will be stored into invoker_host and
invoker_user by SQL thread.
*/
bool m_binlog_invoker;
enum need_invoker m_binlog_invoker;
/**
It points to the invoker in the Query_log_event.

View file

@ -1840,7 +1840,7 @@ bool sp_process_definer(THD *thd)
Query_arena original_arena;
Query_arena *ps_arena= thd->activate_stmt_arena_if_needed(&original_arena);
lex->definer= create_default_definer(thd);
lex->definer= create_default_definer(thd, false);
if (ps_arena)
thd->restore_active_arena(ps_arena, &original_arena);
@ -1854,20 +1854,24 @@ bool sp_process_definer(THD *thd)
}
else
{
LEX_USER *d= lex->definer= get_current_user(thd, lex->definer);
if (!d)
DBUG_RETURN(TRUE);
/*
If the specified definer differs from the current user, we
If the specified definer differs from the current user or role, we
should check that the current user has SUPER privilege (in order
to create a stored routine under another user one must have
SUPER privilege).
*/
if ((strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
my_strcasecmp(system_charset_info, lex->definer->host.str,
thd->security_ctx->priv_host)) &&
check_global_access(thd, SUPER_ACL, true))
{
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
bool curuser= !strcmp(d->user.str, thd->security_ctx->priv_user);
bool currole= !curuser && !strcmp(d->user.str, thd->security_ctx->priv_role);
bool curuserhost= curuser && d->host.str &&
!my_strcasecmp(system_charset_info, d->host.str,
thd->security_ctx->priv_host);
if (!curuserhost && !currole &&
check_global_access(thd, SUPER_ACL, false))
DBUG_RETURN(TRUE);
}
}
/* Check that the specified definer exists. Emit a warning if not. */
@ -3783,7 +3787,7 @@ end_with_restore_list:
goto error;
/* Replicate current user as grantor */
thd->binlog_invoker();
thd->binlog_invoker(false);
if (thd->security_ctx->user) // If not replication
{
@ -7686,16 +7690,23 @@ Item *negate_expression(THD *thd, Item *expr)
@param[out] definer definer
*/
void get_default_definer(THD *thd, LEX_USER *definer)
void get_default_definer(THD *thd, LEX_USER *definer, bool role)
{
const Security_context *sctx= thd->security_ctx;
definer->user.str= (char *) sctx->priv_user;
if (role)
{
definer->user.str= const_cast<char*>(sctx->priv_role);
definer->host= empty_lex_str;
}
else
{
definer->user.str= const_cast<char*>(sctx->priv_user);
definer->host.str= const_cast<char*>(sctx->priv_host);
definer->host.length= strlen(definer->host.str);
}
definer->user.length= strlen(definer->user.str);
definer->host.str= (char *) sctx->priv_host;
definer->host.length= strlen(definer->host.str);
definer->password= null_lex_str;
definer->plugin= empty_lex_str;
definer->auth= empty_lex_str;
@ -7713,16 +7724,22 @@ void get_default_definer(THD *thd, LEX_USER *definer)
- On error, return 0.
*/
LEX_USER *create_default_definer(THD *thd)
LEX_USER *create_default_definer(THD *thd, bool role)
{
LEX_USER *definer;
if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
return 0;
thd->get_definer(definer);
thd->get_definer(definer, role);
return definer;
if (role && definer->user.length == 0)
{
my_error(ER_MALFORMED_DEFINER, MYF(0));
return 0;
}
else
return definer;
}
@ -7757,27 +7774,6 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
}
/**
Retuns information about user or current user.
@param[in] thd thread handler
@param[in] user user
@return
- On success, return a valid pointer to initialized
LEX_USER, which contains user information.
- On error, return 0.
*/
LEX_USER *get_current_user(THD *thd, LEX_USER *user)
{
if (user->user.str == current_user.str) // current_user
return create_default_definer(thd);
return user;
}
/**
Check that byte length of a string does not exceed some limit.

View file

@ -63,10 +63,10 @@ Comp_creator *comp_ne_creator(bool invert);
int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
enum enum_schema_tables schema_table_idx);
void get_default_definer(THD *thd, LEX_USER *definer);
LEX_USER *create_default_definer(THD *thd);
void get_default_definer(THD *thd, LEX_USER *definer, bool role);
LEX_USER *create_default_definer(THD *thd, bool role);
LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
LEX_USER *get_current_user(THD *thd, LEX_USER *user);
LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock=true);
bool sp_process_definer(THD *thd);
bool check_string_byte_length(LEX_STRING *str, const char *err_msg,
uint max_byte_length);

View file

@ -2064,8 +2064,11 @@ void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
{
buffer->append(STRING_WITH_LEN("DEFINER="));
append_identifier(thd, buffer, definer_user->str, definer_user->length);
buffer->append('@');
append_identifier(thd, buffer, definer_host->str, definer_host->length);
if (definer_host->str[0])
{
buffer->append('@');
append_identifier(thd, buffer, definer_host->str, definer_host->length);
}
buffer->append(' ');
}

View file

@ -763,9 +763,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
definer_user= lex->definer->user;
definer_host= lex->definer->host;
trg_definer->str= trg_definer_holder;
trg_definer->length= strxmov(trg_definer->str, definer_user.str, "@",
definer_host.str, NullS) - trg_definer->str;
lex->definer->set_lex_string(trg_definer, trg_definer_holder);
}
else
{

View file

@ -822,7 +822,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
goto err;
}
view->file_version= 1;
view->file_version= 2;
view->calc_md5(md5);
if (!(view->md5.str= (char*) thd->memdup(md5, 32)))
{
@ -1113,8 +1113,16 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER),
table->db, table->table_name);
get_default_definer(thd, &table->definer);
get_default_definer(thd, &table->definer, false);
}
/*
since 10.0.5 definer.host can never be "" for a User, but it's
always "" for a Role. Before 10.0.5 it could be "" for a User,
but roles didn't exist. file_version helps.
*/
if (!table->definer.host.str[0] && table->file_version < 2)
table->definer.host= host_not_specified; // User, not Role
/*
Initialize view definition context by character set names loaded from

View file

@ -13173,7 +13173,7 @@ user:
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1;
$$->host= host_not_specified;
$$->host= null_lex_str; // User or Role, see get_current_user()
$$->password= null_lex_str;
$$->plugin= empty_lex_str;
$$->auth= empty_lex_str;
@ -14351,7 +14351,7 @@ grant_role:
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1;
$$->host= host_not_specified;
$$->host= empty_lex_str;
$$->password= null_lex_str;
$$->plugin= empty_lex_str;
$$->auth= empty_lex_str;
@ -15044,9 +15044,9 @@ no_definer:
;
definer:
DEFINER_SYM EQ user
DEFINER_SYM EQ user_or_role
{
thd->lex->definer= get_current_user(thd, $3);
thd->lex->definer= $3;
}
;

View file

@ -190,6 +190,14 @@ typedef int *(*update_var)(THD *, struct st_mysql_show_var *);
typedef struct st_lex_user {
LEX_STRING user, host, password, plugin, auth;
bool is_role() { return user.str[0] && !host.str[0]; }
void set_lex_string(LEX_STRING *l, char *buf)
{
if (is_role())
*l= user;
else
l->length= strxmov(l->str= buf, user.str, "@", host.str, NullS) - buf;
}
} LEX_USER;
/*