1 # Test that trace does not show information forbidden
2 # by lack of privileges.
4 --source include/have_optimizer_trace.inc
5 # Grant tests not performed with embedded server
6 -- source include/not_embedded.inc
9 let $DEFAULT_TRACE_MEM_SIZE=1048576; # 1MB
10 set @old_size = @@global.optimizer_trace_max_mem_size;
11 eval
set global optimizer_trace_max_mem_size=$DEFAULT_TRACE_MEM_SIZE;
15 create database somedb;
17 create
table t1(a varchar(100));
18 insert into t1 values(
"first");
19 create
table t2(a varchar(100));
20 insert into t2 values(
"first");
21 create
table t3(a varchar(100));
22 insert into t3 values(
"first");
24 create procedure p1() sql security definer
27 if (select count(*) from t1)
29 select 22 into b from dual;
31 select a into b from t1
limit 1;
32 insert into t1 values(current_user());
34 create function f1() returns
int sql security definer
37 select 48 into b from dual;
38 select a into b from t1 limit 1;
39 insert into t1 values(current_user());
42 create trigger trg2 before insert on t2 for each row
44 insert into t3 select * from t3;
47 create sql security definer
view v1 as select * from t1;
48 create user user1@localhost identified by '';
49 grant all on *.*
to user1@localhost with grant
option;
50 connect (con_user1, localhost, user1,, somedb);
55 set optimizer_trace="enabled=on";
56 # SHOW GRANTS scans a hash, which gives a random order
61 --echo # ==========================================================
63 --echo #
Test that security context changes are allowed when, and only
64 --echo # when, invoker has all global privileges.
65 --echo # ==========================================================
68 --echo # Because invoker has all global privileges, all traces are visible:
69 set optimizer_trace_offset=0,optimizer_trace_limit=100;
71 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
72 --echo #
this SET always purges all remembered traces
73 set optimizer_trace_offset=0,optimizer_trace_limit=100;
75 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
76 set optimizer_trace_offset=0,optimizer_trace_limit=100;
78 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
79 set optimizer_trace_offset=0,optimizer_trace_limit=100;
80 insert into t2 values(current_user());
81 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
84 --echo # Show that really all global privileges are needed: let root
85 --echo # revoke just one from user1. Because user1 does not have all global
86 --echo # privileges anymore, security context changes are forbidden,
87 --echo # thus there is no trace.
92 revoke shutdown on *.* from user1@localhost;
93 # removing a global privilege never affects an existing connection:
95 connect (con_user1, localhost, user1,, somedb);
100 set optimizer_trace=
"enabled=on";
104 set optimizer_trace_offset=0,optimizer_trace_limit=100;
106 --echo # In CALL we execute stored procedure and notice a security
107 --echo # context change. The context change is probably only relevant
108 --echo #
for substatements, but we still hide CALL. This is
to be
109 --echo # consistent with what we
do when routine body should not be
110 --echo # exposed. And it also feels safer
to disable I_S output as
111 --echo # soon as possible.
112 --echo # Ps-protocol-specific note: mysqltest uses normal protocol
for CALL
113 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
114 set optimizer_trace_offset=0,optimizer_trace_limit=100;
116 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
117 set optimizer_trace_offset=0,optimizer_trace_limit=100;
119 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
120 set optimizer_trace_offset=0,optimizer_trace_limit=100;
121 insert into t2 values(current_user());
122 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
125 --echo # Verify that user1 cannot circumvent security checks by
126 --echo # setting @@optimizer_trace_offset so that I_S output is disabled
127 --echo # before the object (routine) is checked, and enabled in the
128 --echo
# middle of object usage, when 'offset' is passed.
131 set optimizer_trace_offset=2,optimizer_trace_limit=1;
133 --echo # Even though the routine
's execution started before
134 --echo # 'offset', it detected the security context changes. So the
135 --echo # trace of CALL gets the "missing privilege" mark but we don't
136 --echo # see it as CALL was before
'offset'.
137 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
140 --echo # Finally, verify that
if the routine
's definer does modify
141 --echo # @@optimizer_trace from "enabled=off" to "enabled=on", in the
142 --echo # body of the routine, then tracing works. This is no security
143 --echo # issue, as it was done by the routine's definer.
149 create procedure p2() sql security definer
152 set optimizer_trace="enabled=on";
153 select 22 into b from dual;
158 connection con_user1;
161 set optimizer_trace="enabled=off";
162 set optimizer_trace_offset=0,optimizer_trace_limit=100;
164 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
165 --echo
# Variable is as set by the routine
166 select @@optimizer_trace;
169 --echo # ==========================================================
171 --echo # Do same tests but with SQL SECURITY INVOKER objects,
to verify that
172 --echo # the restriction on security context changes is not present.
173 --echo # ==========================================================
178 alter procedure p1 sql security invoker;
179 alter
function f1 sql security invoker;
180 alter sql security invoker
view v1 as select * from t1;
181 --echo # Triggers cannot be SQL SECURITY INVOKER so we don
't test
183 alter procedure p2 sql security invoker;
184 delete from t1 where a<>"first";
187 connection con_user1;
190 set optimizer_trace_offset=0,optimizer_trace_limit=100;
192 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
193 set optimizer_trace_offset=0,optimizer_trace_limit=100;
195 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
196 set optimizer_trace_offset=0,optimizer_trace_limit=100;
198 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
199 set optimizer_trace_offset=2,optimizer_trace_limit=1;
201 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
202 set optimizer_trace="enabled=off";
203 set optimizer_trace_offset=0,optimizer_trace_limit=100;
205 --echo # SELECT substatement is traced (no security context change)
206 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
207 select @@optimizer_trace;
210 --echo # ==========================================================
212 --echo # User1 got traces. Determine the minimum set of privileges he
213 --echo # needed for that.
214 --echo # ==========================================================
218 drop procedure p2; # p2 is not worth testing more
220 revoke all privileges, grant option from user1@localhost;
221 --echo # Grant minimum privileges to use the routines and views,
222 --echo # without considering optimizer trace:
223 grant execute on procedure p1 to user1@localhost;
224 grant execute on function f1 to user1@localhost;
225 grant select (a) on v1 to user1@localhost;
226 --echo # Objects above are SQL SECURITY INVOKER, so invoker needs
227 --echo # privileges on objects used internally:
228 grant select (a) on t1 to user1@localhost;
229 grant insert (a) on t1 to user1@localhost;
230 delete from t1 where a<>"first";
231 disconnect con_user1;
232 connect (con_user1, localhost, user1,, somedb);
235 connection con_user1;
237 set optimizer_trace="enabled=on";
242 --echo # Those privileges are not enough to see traces:
243 set optimizer_trace_offset=0,optimizer_trace_limit=100;
245 --echo # In CALL we execute stored procedure and notice that body should
246 --echo # not be exposed. The trace of this CALL would not expose the
247 --echo # body. Trace of substatements would. But, due to
248 --echo # implementation, CALL is hidden.
249 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
250 set optimizer_trace_offset=0,optimizer_trace_limit=100;
252 --echo # SELECT is hidden (same reason as for CALL).
253 --echo # Ps-protocol-specific note: preparation of SELECT above does not
254 --echo # execute f1, so does not risk exposing body, so its trace is
256 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
257 set optimizer_trace_offset=0,optimizer_trace_limit=100;
259 --echo # Cannot see anything as it would expose body of view
260 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
263 --echo # C.0) Add more privileges:
268 --echo # - for use of t1 in routines and view:
269 grant select on t1 to user1@localhost;
270 --echo # - for use of routines:
271 grant select on mysql.proc to user1@localhost;
272 --echo # - for use of view:
273 grant select, show view on v1 to user1@localhost;
274 delete from t1 where a<>"first";
277 connection con_user1;
280 set optimizer_trace_offset=0,optimizer_trace_limit=100;
282 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
283 --echo # Trace exposed body of routine, and content of t1, which we
284 --echo # could see anyway:
285 show create procedure p1;
286 select * from t1 limit 1;
287 set optimizer_trace_offset=0,optimizer_trace_limit=100;
289 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
290 --echo # Trace exposed body of routine, and content of t1, which we
291 --echo # could see anyway:
292 show create function f1;
293 set optimizer_trace_offset=0,optimizer_trace_limit=100;
295 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
296 --echo # Trace exposed body of view, and content of t1, which we
297 --echo # could see anyway:
301 --echo # Now remove each privilege to verify that it was needed:
302 --echo # C.1) remove table-level SELECT privilege on t1
306 revoke select on t1 from user1@localhost;
307 grant select (a) on t1 to user1@localhost;
308 delete from t1 where a<>"first";
311 connection con_user1;
314 set optimizer_trace_offset=0,optimizer_trace_limit=100;
316 --echo # Cannot see those substatements which use t1
317 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
318 set optimizer_trace_offset=0,optimizer_trace_limit=100;
320 --echo # Cannot see those substatements which use t1
321 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
322 --echo # Trace exposed body of routine, which we could see anyway:
323 set optimizer_trace="enabled=off";
324 show create function f1;
325 set optimizer_trace="enabled=on";
326 set optimizer_trace_offset=0,optimizer_trace_limit=100;
328 --echo # Cannot see anything as it might expose some data from columns
330 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
333 --echo # C.2) remove table-level SELECT privilege on mysql.proc
338 --echo # Put back privilege removed in C.1
339 grant select on t1 to user1@localhost;
340 --echo # And remove a next one:
341 revoke select on mysql.proc from user1@localhost;
342 delete from t1 where a<>"first";
345 connection con_user1;
348 --echo # We have no right to see routines' bodies:
349 set optimizer_trace=
"enabled=off";
350 show create procedure p1;
351 show create
function f1;
352 --echo # Verify that optimizer trace does not influence the privilege
353 --echo # checking in SHOW CREATE:
354 set optimizer_trace=
"enabled=on";
355 show create procedure p1;
356 show create
function f1;
358 set optimizer_trace_offset=0,optimizer_trace_limit=100;
360 --echo # Cannot see anything as it would expose body of routine
361 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
362 set optimizer_trace_offset=0,optimizer_trace_limit=100;
364 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
372 --echo
# Put back privilege removed in C.2
373 grant select on mysql.proc
to user1@localhost;
374 --echo # And
remove a next one:
375 revoke select on v1 from user1@localhost;
376 grant select (a) on v1
to user1@localhost;
377 delete from t1 where a<>"first";
380 connection con_user1;
383 set optimizer_trace_offset=0,optimizer_trace_limit=100;
385 --echo
# Cannot see anything as it might expose some data from columns
387 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
390 --echo # C.4) remove SHOW VIEW privilege on
view
395 --echo
# Put back privilege removed in C.3
396 grant select on v1
to user1@localhost;
397 --echo # And
remove a next one:
398 revoke show
view on v1 from user1@localhost;
399 delete from t1 where a<>
"first";
402 connection con_user1;
405 set optimizer_trace=
"enabled=off";
406 --echo # We have no right
to see
view's body:
407 --error ER_TABLEACCESS_DENIED_ERROR
409 set optimizer_trace="enabled=on";
410 --echo # Verify that optimizer trace does not influence the privilege
411 --echo # checking in SHOW CREATE:
412 --error ER_TABLEACCESS_DENIED_ERROR
415 set optimizer_trace_offset=0,optimizer_trace_limit=100;
417 --echo # Cannot see anything as it would expose body of view
418 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
421 --echo # ==========================================================
423 --echo # Like Part C, but instead of SQL SECURITY INVOKER objects
424 --echo # created by root and used by User1, let's have SQL SECURITY
425 --echo # DEFINER objects created and used by User1. Determine the
426 --echo # minimum
set of privileges he needs
for that.
427 --echo # ==========================================================
436 revoke all privileges, grant option from user1@localhost;
437 --echo # Grant minimum privileges
to create and use objects,
438 --echo # without considering optimizer trace:
439 grant create routine on somedb.*
to user1@localhost;
440 grant trigger on t2
to user1@localhost;
441 grant create
view on somedb.*
to user1@localhost;
442 grant select (a) on t1
to user1@localhost;
443 grant insert (a) on t1
to user1@localhost;
444 grant insert (a) on t2
to user1@localhost;
445 grant select (a) on t3
to user1@localhost;
446 grant insert (a) on t3
to user1@localhost;
447 delete from t1 where a<>"first";
448 disconnect con_user1;
449 connect (con_user1, localhost, user1,, somedb);
452 connection con_user1;
454 set optimizer_trace="enabled=on";
457 create procedure p1() sql security definer
460 if (select count(*) from t1)
462 select 22 into b from dual;
464 select a into b from t1 limit 1;
465 insert into t1 values(current_user());
467 create function f1() returns
int sql security definer
470 select 48 into b from dual;
471 select a into b from t1 limit 1;
472 insert into t1 values(current_user());
475 create trigger trg2 before insert on t2 for each row
477 insert into t3 select * from t3;
480 create sql security definer
view v1 as select * from t1;
482 --echo
# Creating a view is not enough to be able to SELECT it...
485 grant select (a) on v1
to user1@localhost;
488 connection con_user1;
491 --echo
# Those privileges are not enough to see traces:
492 set optimizer_trace_offset=0,optimizer_trace_limit=100;
494 --echo # Can see body of routine (as definer), but not statements
using t1
495 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
496 set optimizer_trace_offset=0,optimizer_trace_limit=100;
498 --echo # Can see body of routine (as definer), but not statements
using t1
499 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
500 show create
function f1;
501 set optimizer_trace_offset=0,optimizer_trace_limit=100;
503 --echo # Cannot see anything as it might expose some data from columns
505 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
506 set optimizer_trace_offset=0,optimizer_trace_limit=100;
507 insert into t2 values(current_user());
508 --echo # Cannot see anything as it might expose some data from
509 --echo # columns of t2
510 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
511 --echo # Also
test a
query accessing t1 in FROM clause:
512 set optimizer_trace_offset=0,optimizer_trace_limit=100;
513 select a from (select a from t1 where a like
"f%") as tt where a like
"fi%";
514 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
517 --echo # D.0) Add more privileges:
522 --echo
# - for use of t1 in routines and view:
523 grant select on t1
to user1@localhost;
524 --echo # -
for use of
view:
525 grant select, show
view on v1
to user1@localhost;
526 --echo # -
for use of trigger
527 grant select on t2
to user1@localhost;
528 grant select on t3
to user1@localhost;
529 delete from t1 where a<>
"first";
532 connection con_user1;
535 set optimizer_trace_offset=0,optimizer_trace_limit=100;
537 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
538 --echo #
Trace exposed body of routine, and content of t1, which we
539 --echo # could see anyway:
540 show create procedure p1;
541 select * from t1 limit 1;
542 set optimizer_trace_offset=0,optimizer_trace_limit=100;
544 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
545 --echo #
Trace exposed body of routine, and content of t1, which we
546 --echo # could see anyway:
547 show create
function f1;
548 set optimizer_trace_offset=0,optimizer_trace_limit=100;
550 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
551 --echo #
Trace exposed body of
view, and content of t1, which we
552 --echo # could see anyway:
554 set optimizer_trace_offset=0,optimizer_trace_limit=100;
555 insert into t2 values(current_user());
556 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
557 --echo #
Trace exposed body of trigger, and content of t2/t3, which we
558 --echo # could see anyway:
559 show create trigger trg2;
560 select * from t2, t3 limit 1;
561 --echo #
Trace exposed content of t1 which we could see anyway:
562 set optimizer_trace_offset=0,optimizer_trace_limit=100;
563 select a from (select a from t1 where a like
"f%") as tt where a like
"fi%";
564 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
567 --echo # For routines, as they only use t1 and we added only one
568 --echo # privilege on t1, we have nothing
to remove.
570 --echo # Now
remove each privilege
to verify that it was needed
for
572 --echo # D.1) remove
table-
level SELECT privilege on v1
578 revoke select on v1 from user1@localhost;
579 grant select (a) on v1
to user1@localhost;
582 connection con_user1;
585 set optimizer_trace_offset=0,optimizer_trace_limit=100;
587 --echo
# Cannot see anything as it might expose some data from columns
589 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
592 --echo # D.2) remove
table-
level SHOW VIEW privilege on v1
598 --echo
# Put back privilege removed in D.1
599 grant select on v1
to user1@localhost;
600 --echo # And
remove a next one:
601 revoke show view on v1 from user1@localhost;
604 connection con_user1;
607 --echo # We have no right
to see view
's body:
608 --error ER_TABLEACCESS_DENIED_ERROR
610 set optimizer_trace_offset=0,optimizer_trace_limit=100;
612 --echo # Cannot see anything as it would expose body of view
613 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
616 --echo # D.3) remove table-level SELECT privilege on t1
622 --echo # Put back privilege removed in D.2
623 grant show view on v1 to user1@localhost;
624 --echo # And remove a next one:
625 revoke select on t1 from user1@localhost;
626 grant select (a) on t1 to user1@localhost;
629 connection con_user1;
632 set optimizer_trace_offset=0,optimizer_trace_limit=100;
634 --echo # Cannot see anything as it might expose some data from columns
636 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
639 --echo # Now remove each privilege to verify that it was needed for
640 --echo # the trigger:
641 --echo # D.4) remove table-level SELECT privilege on t2
647 revoke select on t2 from user1@localhost;
648 grant select (a) on t2 to user1@localhost;
651 connection con_user1;
654 set optimizer_trace_offset=0,optimizer_trace_limit=100;
655 insert into t2 values(current_user());
656 --echo # Cannot see anything as it might expose some data from
657 --echo # columns of t2
658 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
661 --echo # D.5) remove table-level SELECT privilege on t3
668 --echo # Put back privilege removed in D.4
669 grant select on t2 to user1@localhost;
670 --echo # And remove a next one:
671 revoke select on t3 from user1@localhost;
672 grant select (a) on t3 to user1@localhost;
675 connection con_user1;
678 set optimizer_trace_offset=0,optimizer_trace_limit=100;
679 insert into t2 values(current_user());
680 --echo # Cannot see substatement as it might expose some data from
681 --echo # columns of t3
682 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
688 drop user user1@localhost;
689 disconnect con_user1;
692 --echo # ==========================================================
695 --echo # ==========================================================
701 create sql security definer view v1 as select * from t1 where 'secret
';
702 create user user1@localhost identified by '';
703 grant create, insert, select on somedb.* to user1@localhost;
704 grant create routine on somedb.* to user1@localhost;
705 connect (con_user1, localhost, user1,, somedb);
708 connection con_user1;
711 --echo user1 cannot see view's body:
715 --echo user1 creates a procedure
717 create procedure proc() sql security definer
719 set optimizer_trace="enabled=on";
720 set optimizer_trace_offset=0,optimizer_trace_limit=100;
721 select * from v1 limit 0;
722 create
table leak select * from information_schema.optimizer_trace;
723 set optimizer_trace="enabled=off";
730 --echo root runs procedure, without fear of risk as it is SQL SECURITY DEFINER
734 connection con_user1;
736 --echo user1 cannot see view's body:
743 drop database somedb;
744 drop user user1@localhost;
745 set @@global.optimizer_trace_max_mem_size = @old_size;