MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
security.inc
1 # Test that trace does not show information forbidden
2 # by lack of privileges.
3 
4 --source include/have_optimizer_trace.inc
5 # Grant tests not performed with embedded server
6 -- source include/not_embedded.inc
7 
8 connection default;
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;
12 
13 connection default;
14 select user();
15 create database somedb;
16 use 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");
23 delimiter |;
24 create procedure p1() sql security definer
25 begin
26  declare b int;
27  if (select count(*) from t1)
28  then
29  select 22 into b from dual;
30  end if;
31  select a into b from t1 limit 1;
32  insert into t1 values(current_user());
33 end|
34 create function f1() returns int sql security definer
35 begin
36  declare b int;
37  select 48 into b from dual;
38  select a into b from t1 limit 1;
39  insert into t1 values(current_user());
40  return 36;
41 end|
42 create trigger trg2 before insert on t2 for each row
43 begin
44  insert into t3 select * from t3;
45 end|
46 delimiter ;|
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);
51 
52 --echo
53 connection con_user1;
54 select user();
55 set optimizer_trace="enabled=on";
56 # SHOW GRANTS scans a hash, which gives a random order
57 --sorted_result
58 show grants;
59 
60 --echo
61 --echo # ==========================================================
62 --echo # Part A.
63 --echo # Test that security context changes are allowed when, and only
64 --echo # when, invoker has all global privileges.
65 --echo # ==========================================================
66 --echo
67 
68 --echo # Because invoker has all global privileges, all traces are visible:
69 set optimizer_trace_offset=0,optimizer_trace_limit=100;
70 call p1();
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;
74 select f1();
75 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
76 set optimizer_trace_offset=0,optimizer_trace_limit=100;
77 select * from v1;
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;
82 
83 --echo
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.
88 --echo
89 
90 connection default;
91 select user();
92 revoke shutdown on *.* from user1@localhost;
93 # removing a global privilege never affects an existing connection:
94 disconnect con_user1;
95 connect (con_user1, localhost, user1,, somedb);
96 
97 --echo
98 connection con_user1;
99 select user();
100 set optimizer_trace="enabled=on";
101 --sorted_result
102 show grants;
103 
104 set optimizer_trace_offset=0,optimizer_trace_limit=100;
105 call p1();
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;
115 select f1();
116 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
117 set optimizer_trace_offset=0,optimizer_trace_limit=100;
118 select * from v1;
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;
123 
124 --echo
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.
129 --echo
130 
131 set optimizer_trace_offset=2,optimizer_trace_limit=1;
132 call p1();
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;
138 
139 --echo
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.
144 --echo
145 
146 connection default;
147 select user();
148 delimiter |;
149 create procedure p2() sql security definer
150 begin
151  declare b int;
152  set optimizer_trace="enabled=on";
153  select 22 into b from dual;
154 end|
155 delimiter ;|
156 
157 --echo
158 connection con_user1;
159 select user();
160 
161 set optimizer_trace="enabled=off";
162 set optimizer_trace_offset=0,optimizer_trace_limit=100;
163 call p2();
164 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
165 --echo # Variable is as set by the routine
166 select @@optimizer_trace;
167 
168 --echo
169 --echo # ==========================================================
170 --echo # Part B.
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 # ==========================================================
174 --echo
175 
176 connection default;
177 select user();
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
182 --echo # them here.
183 alter procedure p2 sql security invoker;
184 delete from t1 where a<>"first";
185 
186 --echo
187 connection con_user1;
188 select user();
189 
190 set optimizer_trace_offset=0,optimizer_trace_limit=100;
191 call p1();
192 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
193 set optimizer_trace_offset=0,optimizer_trace_limit=100;
194 select f1();
195 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
196 set optimizer_trace_offset=0,optimizer_trace_limit=100;
197 select * from v1;
198 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
199 set optimizer_trace_offset=2,optimizer_trace_limit=1;
200 call p1();
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;
204 call p2();
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;
208 
209 --echo
210 --echo # ==========================================================
211 --echo # Part C.
212 --echo # User1 got traces. Determine the minimum set of privileges he
213 --echo # needed for that.
214 --echo # ==========================================================
215 --echo
216 
217 connection default;
218 drop procedure p2; # p2 is not worth testing more
219 select user();
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);
233 
234 --echo
235 connection con_user1;
236 select user();
237 set optimizer_trace="enabled=on";
238 --sorted_result
239 show grants;
240 
241 --echo
242 --echo # Those privileges are not enough to see traces:
243 set optimizer_trace_offset=0,optimizer_trace_limit=100;
244 call p1();
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;
251 select f1();
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
255 --echo # visible.
256 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
257 set optimizer_trace_offset=0,optimizer_trace_limit=100;
258 select * from v1;
259 --echo # Cannot see anything as it would expose body of view
260 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
261 
262 --echo
263 --echo # C.0) Add more privileges:
264 --echo
265 
266 connection default;
267 select user();
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";
275 
276 --echo
277 connection con_user1;
278 select user();
279 
280 set optimizer_trace_offset=0,optimizer_trace_limit=100;
281 call p1();
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;
288 select f1();
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;
294 select * from v1;
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:
298 show create view v1;
299 
300 --echo
301 --echo # Now remove each privilege to verify that it was needed:
302 --echo # C.1) remove table-level SELECT privilege on t1
303 --echo
304 connection default;
305 select user();
306 revoke select on t1 from user1@localhost;
307 grant select (a) on t1 to user1@localhost;
308 delete from t1 where a<>"first";
309 
310 --echo
311 connection con_user1;
312 select user();
313 
314 set optimizer_trace_offset=0,optimizer_trace_limit=100;
315 call p1();
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;
319 select f1();
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;
327 select * from v1;
328 --echo # Cannot see anything as it might expose some data from columns
329 --echo # of t1
330 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
331 
332 --echo
333 --echo # C.2) remove table-level SELECT privilege on mysql.proc
334 --echo
335 
336 connection default;
337 select user();
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";
343 
344 --echo
345 connection con_user1;
346 select user();
347 
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;
357 
358 set optimizer_trace_offset=0,optimizer_trace_limit=100;
359 call p1();
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;
363 select f1();
364 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
365 
366 --echo
367 --echo # C.3) remove table-level SELECT privilege on view
368 --echo
369 
370 connection default;
371 select user();
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";
378 
379 --echo
380 connection con_user1;
381 select user();
382 
383 set optimizer_trace_offset=0,optimizer_trace_limit=100;
384 select * from v1;
385 --echo # Cannot see anything as it might expose some data from columns
386 --echo # of v1
387 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
388 
389 --echo
390 --echo # C.4) remove SHOW VIEW privilege on view
391 --echo
392 
393 connection default;
394 select user();
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";
400 
401 --echo
402 connection con_user1;
403 select user();
404 
405 set optimizer_trace="enabled=off";
406 --echo # We have no right to see view's body:
407 --error ER_TABLEACCESS_DENIED_ERROR
408 show create view v1;
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
413 show create view v1;
414 
415 set optimizer_trace_offset=0,optimizer_trace_limit=100;
416 select * from v1;
417 --echo # Cannot see anything as it would expose body of view
418 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
419 
420 --echo
421 --echo # ==========================================================
422 --echo # Part D.
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 # ==========================================================
428 --echo
429 
430 connection default;
431 select user();
432 drop procedure p1;
433 drop function f1;
434 drop view v1;
435 drop trigger trg2;
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);
450 
451 --echo
452 connection con_user1;
453 select user();
454 set optimizer_trace="enabled=on";
455 
456 delimiter |;
457 create procedure p1() sql security definer
458 begin
459  declare b int;
460  if (select count(*) from t1)
461  then
462  select 22 into b from dual;
463  end if;
464  select a into b from t1 limit 1;
465  insert into t1 values(current_user());
466 end|
467 create function f1() returns int sql security definer
468 begin
469  declare b int;
470  select 48 into b from dual;
471  select a into b from t1 limit 1;
472  insert into t1 values(current_user());
473  return 36;
474 end|
475 create trigger trg2 before insert on t2 for each row
476 begin
477  insert into t3 select * from t3;
478 end|
479 delimiter ;|
480 create sql security definer view v1 as select * from t1;
481 
482 --echo # Creating a view is not enough to be able to SELECT it...
483 connection default;
484 select user();
485 grant select (a) on v1 to user1@localhost;
486 
487 --echo
488 connection con_user1;
489 select user();
490 
491 --echo # Those privileges are not enough to see traces:
492 set optimizer_trace_offset=0,optimizer_trace_limit=100;
493 call p1();
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;
497 select f1();
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;
502 select * from v1;
503 --echo # Cannot see anything as it might expose some data from columns
504 --echo # of t1
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;
515 
516 --echo
517 --echo # D.0) Add more privileges:
518 --echo
519 
520 connection default;
521 select user();
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";
530 
531 --echo
532 connection con_user1;
533 select user();
534 
535 set optimizer_trace_offset=0,optimizer_trace_limit=100;
536 call p1();
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;
543 select f1();
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;
549 select * from v1;
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:
553 show create view v1;
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;
565 
566 --echo
567 --echo # For routines, as they only use t1 and we added only one
568 --echo # privilege on t1, we have nothing to remove.
569 --echo
570 --echo # Now remove each privilege to verify that it was needed for
571 --echo # the view.
572 --echo # D.1) remove table-level SELECT privilege on v1
573 --echo
574 
575 connection default;
576 select user();
577 
578 revoke select on v1 from user1@localhost;
579 grant select (a) on v1 to user1@localhost;
580 
581 --echo
582 connection con_user1;
583 select user();
584 
585 set optimizer_trace_offset=0,optimizer_trace_limit=100;
586 select * from v1;
587 --echo # Cannot see anything as it might expose some data from columns
588 --echo # of v1
589 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
590 
591 --echo
592 --echo # D.2) remove table-level SHOW VIEW privilege on v1
593 --echo
594 
595 connection default;
596 select user();
597 
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;
602 
603 --echo
604 connection con_user1;
605 select user();
606 
607 --echo # We have no right to see view's body:
608 --error ER_TABLEACCESS_DENIED_ERROR
609 show create view v1;
610 set optimizer_trace_offset=0,optimizer_trace_limit=100;
611 select * from v1;
612 --echo # Cannot see anything as it would expose body of view
613 select QUERY, TRACE, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
614 
615 --echo
616 --echo # D.3) remove table-level SELECT privilege on t1
617 --echo
618 
619 connection default;
620 select user();
621 
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;
627 
628 --echo
629 connection con_user1;
630 select user();
631 
632 set optimizer_trace_offset=0,optimizer_trace_limit=100;
633 select * from v1;
634 --echo # Cannot see anything as it might expose some data from columns
635 --echo # of t1
636 select QUERY, length(TRACE), INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE;
637 
638 --echo
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
642 --echo
643 
644 connection default;
645 select user();
646 
647 revoke select on t2 from user1@localhost;
648 grant select (a) on t2 to user1@localhost;
649 
650 --echo
651 connection con_user1;
652 select user();
653 
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;
659 
660 --echo
661 --echo # D.5) remove table-level SELECT privilege on t3
662 --echo
663 
664 --echo
665 connection default;
666 select user();
667 
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;
673 
674 --echo
675 connection con_user1;
676 select user();
677 
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;
683 
684 --echo
685 --echo # Cleanup
686 connection default;
687 select user();
688 drop user user1@localhost;
689 disconnect con_user1;
690 
691 --echo
692 --echo # ==========================================================
693 --echo # Part E.
694 --echo # Misc tests.
695 --echo # ==========================================================
696 --echo
697 
698 connection default;
699 select user();
700 drop view v1;
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);
706 
707 --echo
708 connection con_user1;
709 select user();
710 
711 --echo user1 cannot see view's body:
712 --error 1142
713 show create view v1;
714 
715 --echo user1 creates a procedure
716 delimiter |;
717 create procedure proc() sql security definer
718 begin
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";
724 end|
725 delimiter ;|
726 
727 connection default;
728 select user();
729 
730 --echo root runs procedure, without fear of risk as it is SQL SECURITY DEFINER
731 call proc();
732 
733 --echo
734 connection con_user1;
735 select user();
736 --echo user1 cannot see view's body:
737 select * from leak;
738 
739 --echo
740 --echo # Cleanup
741 connection default;
742 select user();
743 drop database somedb;
744 drop user user1@localhost;
745 set @@global.optimizer_trace_max_mem_size = @old_size;