sp-security.test 8.02 KB
#
# Testing SQL SECURITY of stored procedures
#

# Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc

connect (con1root,localhost,root,,);

connection con1root;
use test;

# Create user user1 with no particular access rights
grant usage on *.* to user1@localhost;
flush privileges;

--disable_warnings
drop table if exists t1;
drop database if exists db1_secret;
--enable_warnings
# Create our secret database
create database db1_secret;

# Can create a procedure in other db
create procedure db1_secret.dummy() begin end;
drop procedure db1_secret.dummy;

use db1_secret;

create table t1 ( u varchar(64), i int );

# A test procedure and function
create procedure stamp(i int)
  insert into db1_secret.t1 values (user(), i);
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like 'stamp';

create function db() returns varchar(64) return database();
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show function status like 'db';

# root can, of course
call stamp(1);
select * from t1;
select db();

grant execute on procedure db1_secret.stamp to user1@'%';
grant execute on function db1_secret.db to user1@'%';
grant execute on procedure db1_secret.stamp to ''@'%';
grant execute on function db1_secret.db to ''@'%';

connect (con2user1,localhost,user1,,);
connect (con3anon,localhost,anon,,);


#
# User1 can
#
connection con2user1;

# This should work...
call db1_secret.stamp(2);
select db1_secret.db();

# ...but not this
--error 1142
select * from db1_secret.t1;

# ...and not this
--error 1044
create procedure db1_secret.dummy() begin end;
--error 1305
drop procedure db1_secret.dummy;


#
# Anonymous can
#
connection con3anon;

# This should work...
call db1_secret.stamp(3);
select db1_secret.db();

# ...but not this
--error 1142
select * from db1_secret.t1;

# ...and not this
--error 1044
create procedure db1_secret.dummy() begin end;
--error 1305
drop procedure db1_secret.dummy;


#
# Check it out
#
connection con1root;
select * from t1;

#
# Change to invoker's rights
#
alter procedure stamp sql security invoker;
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like 'stamp';

alter function db sql security invoker;
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show function status like 'db';

# root still can
call stamp(4);
select * from t1;
select db();

#
# User1 cannot
#
connection con2user1;

# This should not work
--error 1044
call db1_secret.stamp(5);
--error 1044
select db1_secret.db();

#
# Anonymous cannot
#
connection con3anon;

# This should not work
--error 1044
call db1_secret.stamp(6);
--error 1044
select db1_secret.db();

#
# BUG#2777
#

connection con1root;
--disable_warnings
drop database if exists db2;
--enable_warnings
create database db2;

use db2;

create table t2 (s1 int);
insert into t2 values (0);

grant usage on db2.* to user1@localhost;
grant select on db2.* to user1@localhost;
grant usage on db2.* to user2@localhost;
grant select,insert,update,delete,create routine on db2.* to user2@localhost;
grant create routine on db2.* to user1@localhost;
flush privileges;

connection con2user1;
use db2;

create procedure p () insert into t2 values (1);

# Check that this doesn't work.
--error 1142
call p();

connect (con4user2,localhost,user2,,);

connection con4user2;
use db2;

# This should not work, since p is executed with definer's (user1's) rights.
--error 1370
call p();
select * from t2;

create procedure q () insert into t2 values (2);

call q();
select * from t2;

connection con1root;
grant usage on procedure db2.q to user2@localhost with grant option;

connection con4user2;
grant execute on procedure db2.q to user1@localhost;

connection con2user1;
use db2;

# This should work
call q();
select * from t2;


#
# BUG#6030: Stored procedure has no appropriate DROP privilege
# (or ALTER for that matter)

# still connection con2user1 in db2

# This should work:
alter procedure p modifies sql data;
drop procedure p;

# This should NOT work
--error 1370
alter procedure q modifies sql data;
--error 1370
drop procedure q;

connection con1root;
use db2;
# But root always can
alter procedure q modifies sql data;
drop procedure q;


# Clean up
#Still connection con1root;
disconnect con2user1;
disconnect con3anon;
disconnect con4user2;
use test;
select type,db,name from mysql.proc;
drop database db1_secret;
drop database db2;
# Make sure the routines are gone
select type,db,name from mysql.proc;
# Get rid of the users
delete from mysql.user where user='user1' or user='user2';
# And any routine privileges
delete from mysql.procs_priv where user='user1' or user='user2';

#
# Test the new security acls
#
grant usage on *.* to usera@localhost;
grant usage on *.* to userb@localhost;
grant usage on *.* to userc@localhost;
create database sptest;
create table t1 ( u varchar(64), i int );
create procedure sptest.p1(i int) insert into test.t1 values (user(), i);
grant insert on t1 to usera@localhost;
grant execute on procedure sptest.p1 to usera@localhost;
show grants for usera@localhost;
grant execute on procedure sptest.p1 to userc@localhost with grant option;
show grants for userc@localhost;

connect (con2usera,localhost,usera,,);
connect (con3userb,localhost,userb,,);
connect (con4userc,localhost,userc,,);

connection con2usera;
call sptest.p1(1);
--error 1370
grant execute on procedure sptest.p1 to userb@localhost;
--error 1370
drop procedure sptest.p1;

connection con3userb;
--error 1370
call sptest.p1(2);
--error 1370
grant execute on procedure sptest.p1 to userb@localhost;
--error 1370
drop procedure sptest.p1;

connection con4userc;
call sptest.p1(3);
grant execute on procedure sptest.p1 to userb@localhost;
--error 1370
drop procedure sptest.p1;

connection con3userb;
call sptest.p1(4);
--error 1370
grant execute on procedure sptest.p1 to userb@localhost;
--error 1370
drop procedure sptest.p1;

connection con1root;
select * from t1;

grant all privileges on procedure sptest.p1 to userc@localhost;
show grants for userc@localhost;
show grants for userb@localhost;

connection con4userc;
revoke all privileges on procedure sptest.p1 from userb@localhost;

connection con1root;
show grants for userb@localhost;

#cleanup
disconnect con4userc;
disconnect con3userb;
disconnect con2usera;
use test;
drop database sptest;
delete from mysql.user where user='usera' or user='userb' or user='userc';
delete from mysql.procs_priv where user='usera' or user='userb' or user='userc';

#
# BUG#9503: reseting correct parameters of thread after error in SP function
#
connect (root,localhost,root,,test);
connection root;

--disable_warnings
drop function if exists bug_9503;
--enable_warnings
delimiter //;
create database mysqltest//
use mysqltest//
create table t1 (s1 int)//
grant select on t1 to user1@localhost//
create function bug_9503 () returns int sql security invoker begin declare v int;
select min(s1) into v from t1; return v; end//
delimiter ;//

connect (user1,localhost,user1,,test);
connection user1;
use mysqltest;
-- error 1370
select bug_9503();

connection root;
grant execute on function bug_9503 to user1@localhost;

connection user1;
do 1;
use test;

connection root;
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost;
drop function bug_9503;
use test;
drop database mysqltest;

#
# correct value from current_user() in function run from "security definer"
# (BUG#7291)
#
connection con1root;
use test;

select current_user();
select user();
create procedure bug7291_0 () sql security invoker select current_user(), user();
create procedure bug7291_1 () sql security definer call bug7291_0();
create procedure bug7291_2 () sql security invoker call bug7291_0();
grant execute on procedure bug7291_0 to user1@localhost;
grant execute on procedure bug7291_1 to user1@localhost;
grant execute on procedure bug7291_2 to user1@localhost;

connect (user1,localhost,user1,,);
connection user1;

call bug7291_2();
call bug7291_1();

connection con1root;
drop procedure bug7291_1;
drop procedure bug7291_2;
drop procedure bug7291_0;
disconnect user1;
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost;
drop user user1@localhost;