diff --git a/mysql-test/main/public_basic.result b/mysql-test/main/public_basic.result index 5832180d2cf..9506fdfff00 100644 --- a/mysql-test/main/public_basic.result +++ b/mysql-test/main/public_basic.result @@ -1,3 +1,6 @@ +# +# MDEV-5215 Granted to PUBLIC +# SHOW GRANTS FOR PUBLIC; Grants for PUBLIC # it is not PUBLIC but an user @@ -7,39 +10,6 @@ create user PUBLIC@localhost; GRANT SELECT on test.* to PUBLIC@localhost; drop user PUBLIC@localhost; drop user PUBLIC; -# preinstalled PUBLIC -GRANT SELECT on test.* to PUBLIC; -GRANT SELECT on mysql.db to PUBLIC; -select * from mysql.global_priv where user="PUBLIC" ; -Host User Priv - PUBLIC {"access":0,"version_id":VERSION,"is_role":true} -SHOW GRANTS FOR PUBLIC; -Grants for PUBLIC -GRANT SELECT ON `test`.* TO `PUBLIC` -GRANT SELECT ON `mysql`.`db` TO `PUBLIC` -GRANT UPDATE on test.* to PUBLIC; -GRANT UPDATE on mysql.db to PUBLIC; -SHOW GRANTS FOR PUBLIC; -Grants for PUBLIC -GRANT SELECT, UPDATE ON `test`.* TO `PUBLIC` -GRANT SELECT, UPDATE ON `mysql`.`db` TO `PUBLIC` -REVOKE SELECT on test.* from PUBLIC; -REVOKE SELECT on mysql.db from PUBLIC; -SHOW GRANTS FOR PUBLIC; -Grants for PUBLIC -GRANT UPDATE ON `test`.* TO `PUBLIC` -GRANT UPDATE ON `mysql`.`db` TO `PUBLIC` -REVOKE UPDATE on test.* from PUBLIC; -REVOKE UPDATE on mysql.db from PUBLIC; -REVOKE UPDATE on test.* from PUBLIC; -ERROR 42000: There is no such grant defined for user 'PUBLIC' on host '' -REVOKE UPDATE on mysql.db from PUBLIC; -ERROR 42000: There is no such grant defined for user 'PUBLIC' on host '' on table 'db' -SHOW GRANTS FOR PUBLIC; -Grants for PUBLIC -# automaticly added PUBLIC -delete from mysql.global_priv where user="PUBLIC"; -flush privileges; select * from mysql.global_priv where user="PUBLIC" ; Host User Priv GRANT SELECT on test.* to PUBLIC; @@ -52,12 +22,12 @@ Grants for PUBLIC GRANT SELECT ON `test`.* TO `PUBLIC` GRANT SELECT ON `mysql`.`db` TO `PUBLIC` GRANT UPDATE on test.* to PUBLIC; -GRANT UPDATE on mysql.db to PUBLIC; -SHOW GRANTS FOR PUBLIC; +grant update on mysql.db to public; +show grants for public; Grants for PUBLIC GRANT SELECT, UPDATE ON `test`.* TO `PUBLIC` GRANT SELECT, UPDATE ON `mysql`.`db` TO `PUBLIC` -REVOKE SELECT on test.* from PUBLIC; +revoke select on test.* from public; REVOKE SELECT on mysql.db from PUBLIC; SHOW GRANTS FOR PUBLIC; Grants for PUBLIC @@ -72,15 +42,15 @@ ERROR OP000: Invalid role specification `XXXXXX` # following should fail with the same error as above GRANT PUBLIC TO CURRENT_USER; ERROR OP000: Invalid role specification `PUBLIC` -REVOKE XXXXXX FROM CURRENT_USER; -ERROR OP000: Invalid role specification `XXXXXX` +revoke xxxxxx from current_user; +ERROR OP000: Invalid role specification `xxxxxx` # following should fail with the same error as above -REVOKE PUBLIC FROM CURRENT_USER; -ERROR OP000: Invalid role specification `PUBLIC` +revoke public from current_user; +ERROR OP000: Invalid role specification `public` drop role XXXXXX; ERROR HY000: Operation DROP ROLE failed for 'XXXXXX' # following should fail with the same error as above -drop role PUBLIC; +drop role public; ERROR HY000: Operation DROP ROLE failed for PUBLIC SET ROLE XXXXXX; ERROR OP000: Invalid role specification `XXXXXX` @@ -92,6 +62,8 @@ ERROR OP000: Invalid role specification `XXXXXX` # following should fail with the same error as above SET DEFAULT ROLE PUBLIC; ERROR OP000: Invalid role specification `PUBLIC` +set default role public; +ERROR OP000: Invalid role specification `public` # # check prohibition of change security context to PUBLIC # @@ -100,39 +72,34 @@ GRANT SELECT on test.* to PUBLIC; # try with a view create table t1( a int); create definer = PUBLIC view v1 as select * from t1; -Warnings: -Note 1449 The user specified as a definer ('PUBLIC'@'') does not exist -show create view v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`PUBLIC` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` latin1 latin1_swedish_ci -Warnings: -Note 1449 The user specified as a definer ('PUBLIC'@'') does not exist -select * from v1; -ERROR HY000: The user specified as a definer ('PUBLIC'@'') does not exist -drop view v1; +ERROR OP000: Invalid role specification `PUBLIC` drop table t1; -# try with a view +# try with a stored procedure create definer='PUBLIC' PROCEDURE p1() SELECT 1; -Warnings: -Note 1449 The user specified as a definer ('PUBLIC'@'') does not exist -show create procedure p1; -Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation -p1 STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`PUBLIC` PROCEDURE `p1`() -SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci -call p1(); -ERROR HY000: The user specified as a definer ('PUBLIC'@'') does not exist -drop procedure p1; +ERROR OP000: Invalid role specification `PUBLIC` # this test cleanup -REVOKE SELECT on test.* from PUBLIC; +revoke select on test.* from public; # -# check autocreation of PUBLIC on GRAND role TO PUBLIC +# check autocreation of PUBLIC on GRANT role TO PUBLIC # # make sure that the privilege will be added automatically delete from mysql.global_priv where user="PUBLIC"; flush privileges; create role roletest; -GRANT roletest TO PUBLIC; +grant roletest to public; drop role roletest; +delete from mysql.global_priv where user="PUBLIC"; +flush privileges; +grant select on mysql.global_priv to public; +revoke select on mysql.global_priv from public; +delete from mysql.global_priv where user="PUBLIC"; +flush privileges; +grant select (user) on mysql.global_priv to public; +revoke select (user) on mysql.global_priv from public; +delete from mysql.global_priv where user="PUBLIC"; +flush privileges; +grant execute on procedure mtr.add_suppression to public; +revoke execute on procedure mtr.add_suppression from public; # clean up delete from mysql.global_priv where user="PUBLIC"; flush privileges; diff --git a/mysql-test/main/public_basic.test b/mysql-test/main/public_basic.test index ddb4e040fce..99952c54e94 100644 --- a/mysql-test/main/public_basic.test +++ b/mysql-test/main/public_basic.test @@ -1,3 +1,8 @@ +--source include/not_embedded.inc +--echo # +--echo # MDEV-5215 Granted to PUBLIC +--echo # + SHOW GRANTS FOR PUBLIC; --echo # it is not PUBLIC but an user @@ -8,37 +13,6 @@ GRANT SELECT on test.* to PUBLIC@localhost; drop user PUBLIC@localhost; drop user PUBLIC; ---echo # preinstalled PUBLIC -GRANT SELECT on test.* to PUBLIC; -GRANT SELECT on mysql.db to PUBLIC; ---replace_regex /"version_id"\:[0-9]+/"version_id":VERSION/ -select * from mysql.global_priv where user="PUBLIC" ; - -SHOW GRANTS FOR PUBLIC; - -GRANT UPDATE on test.* to PUBLIC; -GRANT UPDATE on mysql.db to PUBLIC; - -SHOW GRANTS FOR PUBLIC; - -REVOKE SELECT on test.* from PUBLIC; -REVOKE SELECT on mysql.db from PUBLIC; - -SHOW GRANTS FOR PUBLIC; - -REVOKE UPDATE on test.* from PUBLIC; -REVOKE UPDATE on mysql.db from PUBLIC; - ---error ER_NONEXISTING_GRANT -REVOKE UPDATE on test.* from PUBLIC; ---error ER_NONEXISTING_TABLE_GRANT -REVOKE UPDATE on mysql.db from PUBLIC; - -SHOW GRANTS FOR PUBLIC; - ---echo # automaticly added PUBLIC -delete from mysql.global_priv where user="PUBLIC"; -flush privileges; select * from mysql.global_priv where user="PUBLIC" ; GRANT SELECT on test.* to PUBLIC; GRANT SELECT on mysql.db to PUBLIC; @@ -48,11 +22,11 @@ select * from mysql.global_priv where user="PUBLIC" ; SHOW GRANTS FOR PUBLIC; GRANT UPDATE on test.* to PUBLIC; -GRANT UPDATE on mysql.db to PUBLIC; +grant update on mysql.db to public; -SHOW GRANTS FOR PUBLIC; +show grants for public; -REVOKE SELECT on test.* from PUBLIC; +revoke select on test.* from public; REVOKE SELECT on mysql.db from PUBLIC; SHOW GRANTS FOR PUBLIC; @@ -69,16 +43,16 @@ GRANT XXXXXX TO CURRENT_USER; GRANT PUBLIC TO CURRENT_USER; --error ER_INVALID_ROLE -REVOKE XXXXXX FROM CURRENT_USER; +revoke xxxxxx from current_user; --echo # following should fail with the same error as above --error ER_INVALID_ROLE -REVOKE PUBLIC FROM CURRENT_USER; ---error ER_CANNOT_USER +revoke public from current_user; +--error ER_CANNOT_USER drop role XXXXXX; --echo # following should fail with the same error as above --error ER_CANNOT_USER -drop role PUBLIC; +drop role public; --error ER_INVALID_ROLE SET ROLE XXXXXX; @@ -91,6 +65,8 @@ SET DEFAULT ROLE XXXXXX; --echo # following should fail with the same error as above --error ER_INVALID_ROLE SET DEFAULT ROLE PUBLIC; +--error ER_INVALID_ROLE +set default role public; --echo # --echo # check prohibition of change security context to PUBLIC @@ -99,31 +75,39 @@ SET DEFAULT ROLE PUBLIC; GRANT SELECT on test.* to PUBLIC; --echo # try with a view create table t1( a int); +--error ER_INVALID_ROLE create definer = PUBLIC view v1 as select * from t1; -show create view v1; ---error ER_NO_SUCH_USER -select * from v1; -drop view v1; drop table t1; ---echo # try with a view +--echo # try with a stored procedure +--error ER_INVALID_ROLE create definer='PUBLIC' PROCEDURE p1() SELECT 1; -show create procedure p1; ---error ER_NO_SUCH_USER -call p1(); -drop procedure p1; --echo # this test cleanup -REVOKE SELECT on test.* from PUBLIC; +revoke select on test.* from public; --echo # ---echo # check autocreation of PUBLIC on GRAND role TO PUBLIC +--echo # check autocreation of PUBLIC on GRANT role TO PUBLIC --echo # --echo # make sure that the privilege will be added automatically delete from mysql.global_priv where user="PUBLIC"; flush privileges; create role roletest; -GRANT roletest TO PUBLIC; +grant roletest to public; drop role roletest; +delete from mysql.global_priv where user="PUBLIC"; +flush privileges; +grant select on mysql.global_priv to public; +revoke select on mysql.global_priv from public; + +delete from mysql.global_priv where user="PUBLIC"; +flush privileges; +grant select (user) on mysql.global_priv to public; +revoke select (user) on mysql.global_priv from public; + +delete from mysql.global_priv where user="PUBLIC"; +flush privileges; +grant execute on procedure mtr.add_suppression to public; +revoke execute on procedure mtr.add_suppression from public; -- echo # clean up delete from mysql.global_priv where user="PUBLIC"; diff --git a/mysql-test/main/public_privileges.result b/mysql-test/main/public_privileges.result index ae50ab78553..5f48297e009 100644 --- a/mysql-test/main/public_privileges.result +++ b/mysql-test/main/public_privileges.result @@ -1,4 +1,7 @@ # +# MDEV-5215 Granted to PUBLIC +# +# # Test DB/TABLE/COLUMN privileges in queries # SHOW GRANTS FOR PUBLIC; @@ -15,7 +18,6 @@ insert into t2 values (1,2); create table t3 (a int, b int); insert into t3 values (1,2); connect testuser,localhost,testuser,,; -connection testuser; select * from testdb1.t1; ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table `testdb1`.`t1` select * from testdb2.t2; @@ -28,8 +30,6 @@ connection default; GRANT SELECT ON testdb1.* to PUBLIC; GRANT SELECT ON testdb2.t2 to PUBLIC; GRANT SELECT (b) ON testdb2.t3 to PUBLIC; -disconnect testuser; -connect testuser,localhost,testuser,,; connection testuser; select * from testdb1.t1; a b @@ -42,12 +42,20 @@ b 2 select a from testdb2.t3; ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for column 'a' in table 't3' +show grants; +Grants for testuser@% +GRANT USAGE ON *.* TO `testuser`@`%` +GRANT SELECT ON `testdb1`.* TO `PUBLIC` +GRANT SELECT ON `testdb2`.`t2` TO `PUBLIC` +GRANT SELECT (b) ON `testdb2`.`t3` TO `PUBLIC` +show grants for testuser@'%'; +Grants for testuser@% +GRANT USAGE ON *.* TO `testuser`@`%` connection default; disconnect testuser; -# check that the privilegas correctly read by acl_load +# check that the privileges are correctly read by acl_load flush privileges; connect testuser,localhost,testuser,,; -connection testuser; select * from testdb1.t1; a b 1 2 @@ -76,10 +84,8 @@ create database testdb; use testdb; create procedure p1 () select 1; connect testuser,localhost,testuser,,; -connection testuser; -SHOW PROCESSLIST; -Id User Host db Command Time State Info Progress -# testuser # NULL Query # # SHOW PROCESSLIST 0.000 +select user,db from information_schema.processlist where user='root'; +user db call testdb.p1(); ERROR 42000: execute command denied to user 'testuser'@'%' for routine 'testdb.p1' connection default; @@ -87,33 +93,24 @@ GRANT PROCESS ON *.* to PUBLIC; GRANT EXECUTE ON testdb.* to PUBLIC; disconnect testuser; connect testuser,localhost,testuser,,; -connection testuser; -SHOW PROCESSLIST; -Id User Host db Command Time State Info Progress -# root # testdb Sleep # # NULL 0.000 -# testuser # NULL Query # # SHOW PROCESSLIST 0.000 +select user,db from information_schema.processlist where user='root'; +user db +root testdb call testdb.p1(); 1 1 connection default; disconnect testuser; -# check that the privilegas correctly read by acl_load +# check that the privileges are correctly read by acl_load flush privileges; connect testuser,localhost,testuser,,; -connection testuser; -SHOW PROCESSLIST; -Id User Host db Command Time State Info Progress -# root # testdb Sleep # # NULL 0.000 -# testuser # NULL Query # # SHOW PROCESSLIST 0.000 +select user,db from information_schema.processlist where user='root'; +user db +root testdb call testdb.p1(); 1 1 connection default; -SHOW PROCESSLIST; -Id User Host db Command Time State Info Progress -# root # testdb Query # # SHOW PROCESSLIST 0.000 -# testuser # NULL Sleep # # NULL 0.000 -connection default; use test; disconnect testuser; REVOKE PROCESS ON *.* from PUBLIC; @@ -126,21 +123,17 @@ drop database testdb; create user testuser; create database testdb; connect testuser,localhost,testuser,,; -connection testuser; use testdb; ERROR 42000: Access denied for user 'testuser'@'%' to database 'testdb' connection default; GRANT LOCK TABLES ON testdb.* to PUBLIC; -disconnect testuser; -connect testuser,localhost,testuser,,; connection testuser; use testdb; connection default; disconnect testuser; -# check that the privilegas correctly read by acl_load +# check that the privileges are correctly read by acl_load flush privileges; connect testuser,localhost,testuser,,; -connection testuser; use testdb; connection default; use test; @@ -159,14 +152,11 @@ create table t1 (a int); insert into t1 values (1); GRANT LOCK TABLES ON testdb.* to PUBLIC; connect testuser,localhost,testuser,,; -connection testuser; use testdb; update t1 set a=a+1; ERROR 42000: UPDATE command denied to user 'testuser'@'localhost' for table `testdb`.`t1` connection default; GRANT UPDATE,SELECT ON testdb.* to PUBLIC; -disconnect testuser; -connect testuser,localhost,testuser,,; connection testuser; use testdb; update t1 set a=a+1; @@ -193,7 +183,6 @@ create table t2 (a int, b int); insert into t2 values (1,2); GRANT LOCK TABLES ON testdb.* to PUBLIC; connect testuser,localhost,testuser,,; -connection testuser; use testdb; delete from t1; ERROR 42000: DELETE command denied to user 'testuser'@'localhost' for table `testdb`.`t1` @@ -204,8 +193,6 @@ ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table `tes connection default; GRANT DELETE ON testdb.t1 to PUBLIC; GRANT SELECT (a) ON testdb.t2 to PUBLIC; -disconnect testuser; -connect testuser,localhost,testuser,,; connection testuser; use testdb; delete from t1; @@ -219,10 +206,9 @@ select * from testdb.t1; a insert into t1 values (1); disconnect testuser; -# check that the privilegas correctly read by acl_load +# check that the privileges are correctly read by acl_load flush privileges; connect testuser,localhost,testuser,,; -connection testuser; use testdb; delete from t1; select a from t2; @@ -248,25 +234,21 @@ create database testdb; use testdb; create function f1() returns int return 2; connect testuser,localhost,testuser,,; -connection testuser; alter function testdb.f1 comment "A stupid function"; ERROR 42000: alter routine command denied to user 'testuser'@'%' for routine 'testdb.f1' select testdb.f1(); ERROR 42000: execute command denied to user 'testuser'@'%' for routine 'testdb.f1' connection default; GRANT ALTER ROUTINE ON testdb.* to PUBLIC; -disconnect testuser; -connect testuser,localhost,testuser,,; connection testuser; alter function testdb.f1 comment "A stupid function"; select testdb.f1(); ERROR 42000: execute command denied to user 'testuser'@'%' for routine 'testdb.f1' connection default; disconnect testuser; -# check that the privilegas correctly read by acl_load +# check that the privileges are correctly read by acl_load flush privileges; connect testuser,localhost,testuser,,; -connection testuser; alter function testdb.f1 comment "A stupid function"; select testdb.f1(); ERROR 42000: execute command denied to user 'testuser'@'%' for routine 'testdb.f1' @@ -291,7 +273,6 @@ use testdb1; create table t1 (a int, b int); insert into t1 values (1,2); connect testuser,localhost,testuser,,; -connection testuser; select * from testdb1.t1; ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table `testdb1`.`t1` connection default; @@ -307,33 +288,27 @@ use testdb1; create table t1 (a int, b int); # check that user do not have rights connect testuser,localhost,testuser,,*NO-ONE*; -connection testuser; select * from testdb1.t1; ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table `testdb1`.`t1` connection default; -disconnect testuser; give rights to everyone via assigning the role to public create role roletest; GRANT SELECT ON testdb1.* TO roletest; GRANT roletest TO PUBLIC; -connect testuser,localhost,testuser,,*NO-ONE*; connection testuser; select * from testdb1.t1; a b connection default; disconnect testuser; -# check that the privilegas correctly read by acl_load +# check that the privileges are correctly read by acl_load flush privileges; connect testuser,localhost,testuser,,*NO-ONE*; -connection testuser; select * from testdb1.t1; a b connection default; -disconnect testuser; # drop role... drop role roletest; -# ... and check that user do not have rights again -connect testuser,localhost,testuser,,*NO-ONE*; +# ... and check that user does not have rights again connection testuser; select * from testdb1.t1; ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table `testdb1`.`t1` diff --git a/mysql-test/main/public_privileges.test b/mysql-test/main/public_privileges.test index 2de23b5c81a..e6f803f1038 100644 --- a/mysql-test/main/public_privileges.test +++ b/mysql-test/main/public_privileges.test @@ -1,3 +1,8 @@ +--source include/not_embedded.inc +--echo # +--echo # MDEV-5215 Granted to PUBLIC +--echo # + --echo # --echo # Test DB/TABLE/COLUMN privileges in queries --echo # @@ -17,7 +22,6 @@ create table t3 (a int, b int); insert into t3 values (1,2); connect (testuser,localhost,testuser,,); -connection testuser; --error ER_TABLEACCESS_DENIED_ERROR select * from testdb1.t1; --error ER_TABLEACCESS_DENIED_ERROR @@ -33,8 +37,6 @@ GRANT SELECT ON testdb1.* to PUBLIC; GRANT SELECT ON testdb2.t2 to PUBLIC; GRANT SELECT (b) ON testdb2.t3 to PUBLIC; -disconnect testuser; -connect (testuser,localhost,testuser,,); connection testuser; select * from testdb1.t1; select * from testdb2.t2; @@ -42,14 +44,16 @@ select b from testdb2.t3; --error ER_COLUMNACCESS_DENIED_ERROR select a from testdb2.t3; +show grants; +show grants for testuser@'%'; + connection default; disconnect testuser; ---echo # check that the privilegas correctly read by acl_load +--echo # check that the privileges are correctly read by acl_load flush privileges; connect (testuser,localhost,testuser,,); -connection testuser; select * from testdb1.t1; select * from testdb2.t2; select b from testdb2.t3; @@ -76,10 +80,8 @@ use testdb; create procedure p1 () select 1; connect (testuser,localhost,testuser,,); -connection testuser; ---replace_column 1 # 3 # 6 # 7 # -SHOW PROCESSLIST; +select user,db from information_schema.processlist where user='root'; --error ER_PROCACCESS_DENIED_ERROR call testdb.p1(); @@ -88,34 +90,25 @@ connection default; GRANT PROCESS ON *.* to PUBLIC; GRANT EXECUTE ON testdb.* to PUBLIC; +# need to reconnect because of PROCESS disconnect testuser; connect (testuser,localhost,testuser,,); -connection testuser; ---replace_column 1 # 3 # 6 # 7 # -SHOW PROCESSLIST; +select user,db from information_schema.processlist where user='root'; call testdb.p1(); connection default; disconnect testuser; ---echo # check that the privilegas correctly read by acl_load +--echo # check that the privileges are correctly read by acl_load flush privileges; connect (testuser,localhost,testuser,,); -connection testuser; ---replace_column 1 # 3 # 6 # 7 # -SHOW PROCESSLIST; +select user,db from information_schema.processlist where user='root'; call testdb.p1(); connection default; - ---replace_column 1 # 3 # 6 # 7 # -SHOW PROCESSLIST; - -connection default; - use test; disconnect testuser; REVOKE PROCESS ON *.* from PUBLIC; @@ -131,7 +124,6 @@ create user testuser; create database testdb; connect (testuser,localhost,testuser,,); -connection testuser; --error ER_DBACCESS_DENIED_ERROR use testdb; @@ -140,8 +132,6 @@ connection default; GRANT LOCK TABLES ON testdb.* to PUBLIC; -disconnect testuser; -connect (testuser,localhost,testuser,,); connection testuser; use testdb; @@ -149,11 +139,10 @@ use testdb; connection default; disconnect testuser; ---echo # check that the privilegas correctly read by acl_load +--echo # check that the privileges are correctly read by acl_load flush privileges; connect (testuser,localhost,testuser,,); -connection testuser; use testdb; @@ -179,7 +168,6 @@ insert into t1 values (1); GRANT LOCK TABLES ON testdb.* to PUBLIC; connect (testuser,localhost,testuser,,); -connection testuser; use testdb; --error ER_TABLEACCESS_DENIED_ERROR @@ -189,8 +177,6 @@ connection default; GRANT UPDATE,SELECT ON testdb.* to PUBLIC; -disconnect testuser; -connect (testuser,localhost,testuser,,); connection testuser; use testdb; @@ -222,7 +208,6 @@ insert into t2 values (1,2); GRANT LOCK TABLES ON testdb.* to PUBLIC; connect (testuser,localhost,testuser,,); -connection testuser; use testdb; --error ER_TABLEACCESS_DENIED_ERROR @@ -237,8 +222,6 @@ connection default; GRANT DELETE ON testdb.t1 to PUBLIC; GRANT SELECT (a) ON testdb.t2 to PUBLIC; -disconnect testuser; -connect (testuser,localhost,testuser,,); connection testuser; use testdb; @@ -252,11 +235,10 @@ select * from testdb.t1; insert into t1 values (1); disconnect testuser; ---echo # check that the privilegas correctly read by acl_load +--echo # check that the privileges are correctly read by acl_load flush privileges; connect (testuser,localhost,testuser,,); -connection testuser; use testdb; delete from t1; @@ -286,7 +268,6 @@ use testdb; create function f1() returns int return 2; connect (testuser,localhost,testuser,,); -connection testuser; --error ER_PROCACCESS_DENIED_ERROR alter function testdb.f1 comment "A stupid function"; @@ -297,8 +278,6 @@ connection default; GRANT ALTER ROUTINE ON testdb.* to PUBLIC; -disconnect testuser; -connect (testuser,localhost,testuser,,); connection testuser; alter function testdb.f1 comment "A stupid function"; @@ -308,11 +287,10 @@ select testdb.f1(); connection default; disconnect testuser; ---echo # check that the privilegas correctly read by acl_load +--echo # check that the privileges are correctly read by acl_load flush privileges; connect (testuser,localhost,testuser,,); -connection testuser; alter function testdb.f1 comment "A stupid function"; --error ER_PROCACCESS_DENIED_ERROR @@ -345,7 +323,6 @@ create table t1 (a int, b int); insert into t1 values (1,2); connect (testuser,localhost,testuser,,); -connection testuser; --error ER_TABLEACCESS_DENIED_ERROR select * from testdb1.t1; @@ -365,38 +342,32 @@ create table t1 (a int, b int); --echo # check that user do not have rights connect (testuser,localhost,testuser,,*NO-ONE*); -connection testuser; --error ER_TABLEACCESS_DENIED_ERROR select * from testdb1.t1; connection default; -disconnect testuser; --echo give rights to everyone via assigning the role to public create role roletest; GRANT SELECT ON testdb1.* TO roletest; GRANT roletest TO PUBLIC; -connect (testuser,localhost,testuser,,*NO-ONE*); connection testuser; select * from testdb1.t1; connection default; disconnect testuser; ---echo # check that the privilegas correctly read by acl_load +--echo # check that the privileges are correctly read by acl_load flush privileges; connect (testuser,localhost,testuser,,*NO-ONE*); -connection testuser; select * from testdb1.t1; connection default; -disconnect testuser; --echo # drop role... drop role roletest; ---echo # ... and check that user do not have rights again -connect (testuser,localhost,testuser,,*NO-ONE*); +--echo # ... and check that user does not have rights again connection testuser; --error ER_TABLEACCESS_DENIED_ERROR select * from testdb1.t1; diff --git a/mysql-test/suite/perfschema/r/connection_type_win.result b/mysql-test/suite/perfschema/r/connection_type_win.result index 8dc064babff..c6c8b6cc77b 100644 --- a/mysql-test/suite/perfschema/r/connection_type_win.result +++ b/mysql-test/suite/perfschema/r/connection_type_win.result @@ -55,7 +55,7 @@ select user_host, command_type, argument from mysql.general_log where command_type = "Connect"; user_host [root] @ santa.claus.ipv4.example.com [192.0.2.4] command_type Connect -argument root@santa.claus.ipv4.example.com on test using TCP/IP +argument root@santa.claus.ipv4.example.com on using TCP/IP user_host [root] @ santa.claus.ipv4.example.com [192.0.2.4] command_type Connect argument root@santa.claus.ipv4.example.com on test using TCP/IP @@ -65,7 +65,6 @@ argument rootssl@santa.claus.ipv4.example.com on test using SSL/TLS select substring(argument, locate("Connect", argument)) from test_log where argument like "%Connect%on test%"; substring(argument, locate("Connect", argument)) Connect root@santa.claus.ipv4.example.com on test using TCP/IP -substring(argument, locate("Connect", argument)) Connect root@santa.claus.ipv4.example.com on test using TCP/IP substring(argument, locate("Connect", argument)) Connect rootssl@santa.claus.ipv4.example.com on test using SSL/TLS DROP TABLE test_log; SET GLOBAL general_log_file= @old_general_log_file; diff --git a/mysql-test/suite/roles/none_public.result b/mysql-test/suite/roles/none_public.result index 4acba8bd133..bb8e3c0782a 100644 --- a/mysql-test/suite/roles/none_public.result +++ b/mysql-test/suite/roles/none_public.result @@ -5,6 +5,8 @@ create role public; ERROR OP000: Invalid role specification `public` drop role none; ERROR HY000: Operation DROP ROLE failed for 'none' +drop role public; +ERROR HY000: Operation DROP ROLE failed for PUBLIC grant none to role1; ERROR OP000: Invalid role specification `none` grant role1 to none; @@ -14,6 +16,7 @@ ERROR OP000: Invalid role specification `none` grant public to role1; ERROR OP000: Invalid role specification `public` grant role1 to public; +grant select on *.* to public; grant role1 to current_role; ERROR OP000: Invalid role specification `NONE` revoke none from role1; @@ -25,13 +28,43 @@ ERROR OP000: Invalid role specification `none` revoke public from role1; ERROR OP000: Invalid role specification `public` revoke role1 from public; -ERROR HY000: Cannot revoke role 'role1' from: 'public'@'%' revoke select on *.* from public; show grants for none; ERROR OP000: Invalid role specification `none` +show grants for public; +Grants for PUBLIC create definer=none view test.v1 as select 1; ERROR OP000: Invalid role specification `none` +create definer=public view test.v1 as select 1; +ERROR OP000: Invalid role specification `public` drop role role1; +create user foo@localhost; +connect foo,localhost,foo; +set default role public; +ERROR OP000: Invalid role specification `public` +disconnect foo; +connection default; +update mysql.global_priv set priv=json_insert(priv, '$.default_role', 'none') where user='foo'; +connect foo,localhost,foo; +show grants; +Grants for foo@localhost +GRANT USAGE ON *.* TO `foo`@`localhost` +select * from information_schema.enabled_roles; +ROLE_NAME +NULL +disconnect foo; +connection default; +update mysql.global_priv set priv=json_insert(priv, '$.default_role', 'public') where user='foo'; +connect foo,localhost,foo; +show grants; +Grants for foo@localhost +GRANT USAGE ON *.* TO `foo`@`localhost` +select * from information_schema.enabled_roles; +ROLE_NAME +NULL +disconnect foo; +connection default; +drop user foo@localhost; insert mysql.global_priv values ('', 'none', '{"is_role":true}'); flush privileges; Warnings: diff --git a/mysql-test/suite/roles/none_public.test b/mysql-test/suite/roles/none_public.test index 21e9dacf166..e88ed45c492 100644 --- a/mysql-test/suite/roles/none_public.test +++ b/mysql-test/suite/roles/none_public.test @@ -8,6 +8,8 @@ create role none; create role public; --error ER_CANNOT_USER drop role none; +--error ER_CANNOT_USER +drop role public; --error ER_INVALID_ROLE grant none to role1; @@ -18,9 +20,7 @@ grant select on *.* to none; --error ER_INVALID_ROLE grant public to role1; grant role1 to public; -# PUBLIC is legal role -#--error ER_INVALID_ROLE -#grant select on *.* to public; +grant select on *.* to public; --error ER_INVALID_ROLE grant role1 to current_role; @@ -33,24 +33,43 @@ revoke role1 from none; revoke select on *.* from none; --error ER_INVALID_ROLE revoke public from role1; ---error ER_CANNOT_REVOKE_ROLE revoke role1 from public; revoke select on *.* from public; --error ER_INVALID_ROLE show grants for none; -# PUBLIC is legal role -#--error ER_INVALID_ROLE -#show grants for public; +show grants for public; --error ER_INVALID_ROLE create definer=none view test.v1 as select 1; -# PUBLIC is legal role -#--error ER_INVALID_ROLE -#create definer=public view test.v1 as select 1; +--error ER_INVALID_ROLE +create definer=public view test.v1 as select 1; drop role role1; +create user foo@localhost; +connect foo,localhost,foo; +--error ER_INVALID_ROLE +set default role public; +disconnect foo; + +connection default; +update mysql.global_priv set priv=json_insert(priv, '$.default_role', 'none') where user='foo'; +connect foo,localhost,foo; +show grants; +select * from information_schema.enabled_roles; +disconnect foo; + +connection default; +update mysql.global_priv set priv=json_insert(priv, '$.default_role', 'public') where user='foo'; +connect foo,localhost,foo; +show grants; +select * from information_schema.enabled_roles; +disconnect foo; + +connection default; +drop user foo@localhost; + insert mysql.global_priv values ('', 'none', '{"is_role":true}'); flush privileges; delete from mysql.global_priv where host=''; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 4713787ade8..487f4c5d3dc 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3352,11 +3352,12 @@ static int check_user_can_set_role(THD *thd, const char *user, } if (access) - { *access = acl_user->access | role->access; - } end: + if (acl_public && access) + *access|= acl_public->access; + mysql_mutex_unlock(&acl_cache->lock); /* We present different error messages depending if the user has sufficient @@ -3438,10 +3439,6 @@ int acl_setrole(THD *thd, const char *rolename, privilege_t access) if (thd->db.str) sctx->db_access= acl_get_all3(sctx, thd->db.str, FALSE); - // PUBLIC magic - if (acl_public) - sctx->master_access|= acl_public->access; - return 0; } @@ -3459,8 +3456,7 @@ static void acl_update_role(const char *rolename, const privilege_t privileges) if (role) { role->initial_role_access= role->access= privileges; - if (strcasecmp(rolename, public_name.str) == 0) - acl_public= role; + DBUG_ASSERT(strcasecmp(rolename, public_name.str) || acl_public == role); } } @@ -3716,8 +3712,7 @@ privilege_t acl_get(const char *host, const char *ip, if (acl_db->host.hostname) goto exit; // Fully specified. Take it /* the host table is not used for roles */ - if ((!host || !host[0]) && - !acl_db->host.hostname && + if ((!host || !host[0]) && !acl_db->host.hostname && find_acl_role(user, false)) goto exit; } @@ -4370,7 +4365,7 @@ wsrep_error_label: /* - Find user in ACL + Find user in ACL. Uses to check a definer SYNOPSIS is_acl_user() @@ -4378,8 +4373,8 @@ wsrep_error_label: user user name RETURN - FALSE user not fond - TRUE there is such user + FALSE definer not fond + TRUE there is such definer */ bool is_acl_user(const char *host, const char *user) @@ -4454,17 +4449,17 @@ static ACL_ROLE *find_acl_role(const char *role, bool allow_public) mysql_mutex_assert_owner(&acl_cache->lock); - if (!length || (!allow_public && - length == public_name.length && + if (!length || (!allow_public && length == public_name.length && strcasecmp(role, public_name.str) == 0)) DBUG_RETURN(NULL); - ACL_ROLE *r= (ACL_ROLE *)my_hash_search(&acl_roles, (uchar *)role, - length); + ACL_ROLE *r= (ACL_ROLE *)my_hash_search(&acl_roles, (uchar *)role, length); DBUG_RETURN(r); } - +/* + Finds a grantee - something that privileges or roles can be granted to. +*/ static ACL_USER_BASE *find_acl_user_base(const char *user, const char *host) { if (*host) @@ -5950,9 +5945,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, uchar user_key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_table_table"); DBUG_PRINT("enter", ("User: '%s' Host: '%s' Revoke:'%d'", - (combo.user.length ? combo.user.str : ""), - (combo.host.length ? combo.host.str : ""), - (int) revoke_grant)); + combo.user.str, combo.host.str, (int) revoke_grant)); get_grantor(thd, grantor); /* @@ -7272,10 +7265,10 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, continue; } /* Create user if needed */ - error= copy_and_check_auth(Str, tmp_Str, thd) || + error= copy_and_check_auth(Str, Str, thd) || replace_user_table(thd, tables.user_table(), Str, NO_ACL, revoke_grant, create_new_users, - MY_TEST(tmp_Str->is_public || + MY_TEST(!Str->is_public && (thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER))); if (unlikely(error)) @@ -7461,7 +7454,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, if (copy_and_check_auth(Str, tmp_Str, thd) || replace_user_table(thd, tables.user_table(), Str, NO_ACL, revoke_grant, create_new_users, - MY_TEST(thd->variables.sql_mode & + !Str->is_public && (thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER))) { result= TRUE; @@ -7629,8 +7622,7 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) rolename= granted_role->user; create_new_user= test_if_create_new_users(thd); - no_auto_create_user= MY_TEST(thd->variables.sql_mode & - MODE_NO_AUTO_CREATE_USER); + no_auto_create_user= thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER; Grant_tables tables; if ((result= tables.open_and_lock(thd, Table_user | Table_roles_mapping, TL_WRITE))) @@ -7669,8 +7661,7 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) result= 1; continue; } - if (!(role_as_user= find_acl_role(thd->security_ctx->priv_role, - true))) + if (!(role_as_user= find_acl_role(thd->security_ctx->priv_role, true))) { LEX_CSTRING ls= { thd->security_ctx->priv_role, strlen(thd->security_ctx->priv_role) }; @@ -7707,13 +7698,21 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) hostname= empty_clex_str; else { - if (check_role_name(username.str, true) == ROLE_NAME_INVALID) - { + switch (check_role_name(username.str, true)) { + case ROLE_NAME_INVALID: append_user(thd, &wrong_users, &username, &empty_clex_str); result= 1; continue; + case ROLE_NAME_PUBLIC: + user->user= username= public_name; // fix the letter case + user->host= hostname= empty_clex_str; + user->is_public= true; + role_as_user= acl_public; + break; + case ROLE_NAME_OK: + hostname= host_not_specified; + break; } - hostname= host_not_specified; } } @@ -7730,16 +7729,7 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) { LEX_USER user_combo = *user; user_combo.user = username; - user_combo.is_public= (user->host.length == 0 && - // it is also can be that - // hostname.length= 1 && hostname.str[0] == '%' - // if the PUBLIC was absent - username.length == public_name.length && - (strcasecmp(username.str, public_name.str) == 0)); - if (user_combo.is_public) - user_combo.host= hostname= empty_clex_str; - else - user_combo.host = hostname; + user_combo.host = hostname; if (copy_and_check_auth(&user_combo, &user_combo, thd) || replace_user_table(thd, tables.user_table(), &user_combo, NO_ACL, @@ -9602,6 +9592,12 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) } } + if (username && rolename) // show everything, incl. PUBLIC + { + if (acl_public) + traverse_role_graph_down(acl_public, thd, show_grants_callback, NULL); + } + if (username) { /* Show default role to acl_user */ @@ -11908,6 +11904,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, thd->make_lex_string(&combo->host, combo->host.str, strlen(combo->host.str)); combo->auth= NULL; + combo->is_public= false; if (user_list.push_back(combo, thd->mem_root)) DBUG_RETURN(TRUE); @@ -12420,8 +12417,7 @@ SHOW_VAR acl_statistics[] = { hostname == NULL means we are looking for a role as a starting point, otherwise a user. */ -bool check_role_is_granted(const char *username, - const char *hostname, +bool check_role_is_granted(const char *username, const char *hostname, const char *rolename) { DBUG_ENTER("check_role_is_granted"); @@ -13005,6 +13001,8 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock) if (!dup) return 0; + dup->is_public= false; + #ifndef NO_EMBEDDED_ACCESS_CHECKS if (has_auth(user, thd->lex)) { @@ -13017,11 +13015,16 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock) if (result == ROLE_NAME_INVALID) return 0; if (result == ROLE_NAME_PUBLIC) + { dup->is_public= true; + dup->user= public_name; // fix the letter case + dup->host= empty_clex_str; + return dup; + } if (lock) mysql_mutex_lock(&acl_cache->lock); - if (find_acl_role(dup->user.str, false) || dup->is_public) + if (find_acl_role(dup->user.str, false)) dup->host= empty_clex_str; else dup->host= host_not_specified; @@ -15088,5 +15091,3 @@ extern "C" void maria_update_hostname( *ip_mask= h.ip_mask; #endif } - - diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 68dfa249449..78c2e682af0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -6033,6 +6033,7 @@ void THD::get_definer(LEX_USER *definer, bool role) definer->user= invoker.user; definer->host= invoker.host; definer->auth= NULL; + definer->is_public= false; } else #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7025b7214b3..d3101bf0c13 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2798,9 +2798,15 @@ bool sp_process_definer(THD *thd) } else { - LEX_USER *d= lex->definer= get_current_user(thd, lex->definer); + LEX_USER *d= get_current_user(thd, lex->definer); if (!d) DBUG_RETURN(TRUE); + if (d->is_public) + { + my_error(ER_INVALID_ROLE, MYF(0), lex->definer->user.str); + DBUG_RETURN(TRUE); + } + lex->definer= d; /* If the specified definer differs from the current user or role, we @@ -2823,12 +2829,9 @@ bool sp_process_definer(THD *thd) #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!is_acl_user(lex->definer->host.str, lex->definer->user.str)) { - push_warning_printf(thd, - Sql_condition::WARN_LEVEL_NOTE, - ER_NO_SUCH_USER, - ER_THD(thd, ER_NO_SUCH_USER), - lex->definer->user.str, - lex->definer->host.str); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_NO_SUCH_USER, ER_THD(thd, ER_NO_SUCH_USER), + lex->definer->user.str, lex->definer->host.str); } #endif /* NO_EMBEDDED_ACCESS_CHECKS */ @@ -3120,8 +3123,7 @@ mysql_create_routine(THD *thd, LEX *lex) */ if (thd->slave_thread && is_acl_user(definer->host.str, definer->user.str)) { - security_context.change_security_context(thd, - &thd->lex->definer->user, + security_context.change_security_context(thd, &thd->lex->definer->user, &thd->lex->definer->host, &thd->lex->sphead->m_db, &backup); @@ -10062,6 +10064,7 @@ void get_default_definer(THD *thd, LEX_USER *definer, bool role) } definer->user.length= strlen(definer->user.str); definer->auth= NULL; + definer->is_public= false; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2c36ee5ab2d..5d0a2455228 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -13814,7 +13814,7 @@ show_param: { Lex->sql_command= SQLCOM_SHOW_GRANTS; if (unlikely(!(Lex->grant_user= - (LEX_USER*)thd->alloc(sizeof(LEX_USER))))) + (LEX_USER*)thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; Lex->grant_user->user= current_user_and_current_role; } @@ -13923,7 +13923,7 @@ show_param: { Lex->sql_command= SQLCOM_SHOW_CREATE_USER; if (unlikely(!(Lex->grant_user= - (LEX_USER*)thd->alloc(sizeof(LEX_USER))))) + (LEX_USER*)thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; Lex->grant_user->user= current_user; } @@ -17138,7 +17138,6 @@ current_role: if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user= current_role; - $$->auth= NULL; } ; @@ -17151,12 +17150,10 @@ grant_role: ((char*) $1.str)[$1.length] = '\0'; if (unlikely($1.length == 0)) my_yyabort_error((ER_INVALID_ROLE, MYF(0), "")); - if (unlikely(!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))) + if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user= $1; $$->host= empty_clex_str; - $$->auth= NULL; - $$->is_public= false; if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length,