MDEV-5215 post-review fixes

* "public" should work in any letter case
* PUBLIC is not a valid definer
* granting to public should auto-create an entry in mysql.global_priv
* SHOW GRANTS should show privileges obtained via PUBLIC
* LEX_USER::is_public was often uninitialized
* comments, whitespaces, typos, etc
This commit is contained in:
Sergei Golubchik 2022-11-01 21:52:23 +01:00
parent b0325bd6d6
commit b4e7803a6f
11 changed files with 238 additions and 288 deletions

View file

@ -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;

View file

@ -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";

View file

@ -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`

View file

@ -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;

View file

@ -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;

View file

@ -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:

View file

@ -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='';

View file

@ -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 <LEX_USER> &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 <LEX_USER> &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 <LEX_USER> &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 <LEX_USER> &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
}

View file

@ -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

View file

@ -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;
}

View file

@ -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,