1 /* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22    02110-1301  USA */
23 
24 
25 /*
26   In here, we rewrite queries (to obfuscate passwords etc.) that need it
27   before we log them.
28 
29   Stored procedures may also rewrite their statements (to show the actual
30   values of their variables etc.). There is currently no scenario where
31   a statement can be eligible for both rewrites. (see sp_instr.cc)
32   Special consideration will need to be taken if this assertion is changed.
33 
34   We also do not intersect with query cache at this time, as QC only
35   caches SELECTs (which we don't rewrite). If and when QC becomes more
36   general, it should probably cache the rewritten query along with the
37   user-submitted one. (see sql_parse.cc)
38 */
39 
40 
41 #include "sql_acl.h"    // append_user
42 #include "sql_parse.h"  // get_current_user
43 #include "sql_show.h"   // append_identifier
44 #include "sp_head.h"    // struct set_var_base
45 #include "rpl_slave.h"  // SLAVE_SQL, SLAVE_IO
46 
47 
48 /**
49   Append a key/value pair to a string, with an optional preceeding comma.
50   For numeric values.
51 
52   @param           str                  The string to append to
53   @param           comma                Prepend a comma?
54   @param           txt                  C-string, must end in a space
55   @param           len                  strlen(txt)
56   @param           val                  numeric value
57   @param           cond                 only append if this evaluates to true
58 
59   @retval          false if any subsequent key/value pair would be the first
60 */
61 
append_int(String * str,bool comma,const char * txt,size_t len,long val,int cond)62 bool append_int(String *str, bool comma, const char *txt, size_t len,
63                 long val, int cond)
64 {
65   if (cond)
66   {
67     String numbuf(42);
68     if (comma)
69       str->append(STRING_WITH_LEN(", "));
70     str->append(txt,len);
71     numbuf.set((longlong)val,&my_charset_bin);
72     str->append(numbuf);
73     return true;
74   }
75   return comma;
76 }
77 
78 
79 /**
80   Append a key/value pair to a string if the value is non-NULL,
81   with an optional preceeding comma.
82 
83   @param           str                  The string to append to
84   @param           comma                Prepend a comma?
85   @param           key                  C-string: the key, must be non-NULL
86   @param           val                  C-string: the value
87 
88   @retval          false if any subsequent key/value pair would be the first
89 */
90 
append_str(String * str,bool comma,const char * key,char * val)91 bool append_str(String *str, bool comma, const char *key, char *val)
92 {
93   if (val)
94   {
95     if (comma)
96       str->append(STRING_WITH_LEN(", "));
97     str->append(key);
98     str->append(STRING_WITH_LEN(" '"));
99     str->append(val);
100     str->append(STRING_WITH_LEN("'"));
101     return true;
102   }
103   return comma;
104 }
105 
106 
107 /**
108   Rewrite a GRANT statement.
109 
110   @param thd      The THD to rewrite for.
111   @param rlb      An empty String object to put the rewritten query in.
112 */
113 
mysql_rewrite_grant(THD * thd,String * rlb)114 static void mysql_rewrite_grant(THD *thd, String *rlb)
115 {
116   LEX        *lex= thd->lex;
117   TABLE_LIST *first_table= (TABLE_LIST*) lex->select_lex.table_list.first;
118   bool        comma= FALSE, comma_inner;
119   bool        proxy_grant= lex->type == TYPE_ENUM_PROXY;
120   String      cols(1024);
121   int         c;
122 
123   rlb->append(STRING_WITH_LEN("GRANT "));
124   if (proxy_grant)
125     rlb->append(STRING_WITH_LEN("PROXY"));
126   else if (lex->all_privileges)
127     rlb->append(STRING_WITH_LEN("ALL PRIVILEGES"));
128   else
129   {
130     ulong priv;
131 
132     for (c= 0, priv= SELECT_ACL; priv <= GLOBAL_ACLS; c++, priv <<= 1)
133     {
134       if (priv == GRANT_ACL)
135         continue;
136 
137       comma_inner= FALSE;
138 
139       if (lex->columns.elements)               // show columns, if any
140       {
141         class LEX_COLUMN *column;
142         List_iterator <LEX_COLUMN> column_iter(lex->columns);
143 
144         cols.length(0);
145         cols.append(STRING_WITH_LEN(" ("));
146 
147         /*
148           If the statement was GRANT SELECT(f2), INSERT(f3), UPDATE(f1,f3, f2),
149           our list cols will contain the order f2, f3, f1, and thus that's
150           the order we'll recreate the privilege: UPDATE (f2, f3, f1)
151         */
152 
153         while ((column= column_iter++))
154         {
155           if (column->rights & priv)
156           {
157             if (comma_inner)
158               cols.append(STRING_WITH_LEN(", "));
159             else
160               comma_inner= TRUE;
161             cols.append(column->column.ptr(),column->column.length());
162           }
163         }
164         cols.append(STRING_WITH_LEN(")"));
165       }
166 
167       if (comma_inner || (lex->grant & priv))  // show privilege name
168       {
169         if (comma)
170           rlb->append(STRING_WITH_LEN(", "));
171         else
172           comma= TRUE;
173         rlb->append(command_array[c],command_lengths[c]);
174         if (!(lex->grant & priv))              // general outranks specific
175           rlb->append(cols);
176       }
177     }
178     if (!comma)                                // no privs, default to USAGE
179       rlb->append(STRING_WITH_LEN("USAGE"));
180   }
181 
182   rlb->append(STRING_WITH_LEN(" ON "));
183   switch(lex->type)
184   {
185   case TYPE_ENUM_PROCEDURE: rlb->append(STRING_WITH_LEN("PROCEDURE ")); break;
186   case TYPE_ENUM_FUNCTION:  rlb->append(STRING_WITH_LEN("FUNCTION "));  break;
187   default:                                                              break;
188   }
189 
190   LEX_USER *user_name, *tmp_user_name;
191   List_iterator <LEX_USER> user_list(lex->users_list);
192   comma= FALSE;
193 
194   if (proxy_grant)
195   {
196     tmp_user_name= user_list++;
197     user_name= get_current_user(thd, tmp_user_name);
198     if (user_name)
199       append_user(thd, rlb, user_name, comma, true);
200   }
201   else if (first_table)
202   {
203     append_identifier(thd, rlb, first_table->db, strlen(first_table->db));
204     rlb->append(STRING_WITH_LEN("."));
205     append_identifier(thd, rlb, first_table->table_name,
206                       strlen(first_table->table_name));
207   }
208   else
209   {
210     if (lex->current_select->db)
211       append_identifier(thd, rlb, lex->current_select->db,
212                         strlen(lex->current_select->db));
213     else
214       rlb->append("*");
215     rlb->append(STRING_WITH_LEN(".*"));
216   }
217 
218   rlb->append(STRING_WITH_LEN(" TO "));
219   {
220     while ((tmp_user_name= user_list++))
221     {
222       if ((user_name= get_current_user(thd, tmp_user_name)))
223       {
224         append_user(thd, rlb, user_name, comma, true);
225         comma= TRUE;
226       }
227     }
228   }
229 
230   if (lex->ssl_type != SSL_TYPE_NOT_SPECIFIED)
231   {
232     rlb->append(STRING_WITH_LEN(" REQUIRE"));
233     switch (lex->ssl_type)
234     {
235     case SSL_TYPE_SPECIFIED:
236       if (lex->x509_subject)
237       {
238         rlb->append(STRING_WITH_LEN(" SUBJECT '"));
239         rlb->append(lex->x509_subject);
240         rlb->append(STRING_WITH_LEN("'"));
241       }
242       if (lex->x509_issuer)
243       {
244         rlb->append(STRING_WITH_LEN(" ISSUER '"));
245         rlb->append(lex->x509_issuer);
246         rlb->append(STRING_WITH_LEN("'"));
247       }
248       if (lex->ssl_cipher)
249       {
250         rlb->append(STRING_WITH_LEN(" CIPHER '"));
251         rlb->append(lex->ssl_cipher);
252         rlb->append(STRING_WITH_LEN("'"));
253       }
254       break;
255     case SSL_TYPE_X509:
256       rlb->append(STRING_WITH_LEN(" X509"));
257       break;
258     case SSL_TYPE_ANY:
259       rlb->append(STRING_WITH_LEN(" SSL"));
260       break;
261     case SSL_TYPE_NOT_SPECIFIED:
262       /* fall-thru */
263     case SSL_TYPE_NONE:
264       rlb->append(STRING_WITH_LEN(" NONE"));
265       break;
266     }
267   }
268 
269   if (lex->mqh.specified_limits || (lex->grant & GRANT_ACL))
270   {
271     rlb->append(STRING_WITH_LEN(" WITH"));
272     if (lex->grant & GRANT_ACL)
273       rlb->append(STRING_WITH_LEN(" GRANT OPTION"));
274 
275     append_int(rlb, false, STRING_WITH_LEN(" MAX_QUERIES_PER_HOUR "),
276                lex->mqh.questions,
277                lex->mqh.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR);
278 
279     append_int(rlb, false, STRING_WITH_LEN(" MAX_UPDATES_PER_HOUR "),
280                lex->mqh.updates,
281                lex->mqh.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR);
282 
283     append_int(rlb, false, STRING_WITH_LEN(" MAX_CONNECTIONS_PER_HOUR "),
284                lex->mqh.conn_per_hour,
285                lex->mqh.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR);
286 
287     append_int(rlb, false, STRING_WITH_LEN(" MAX_USER_CONNECTIONS "),
288                lex->mqh.user_conn,
289                lex->mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS);
290   }
291 }
292 
293 
294 /**
295   Rewrite a SET statement.
296 
297   @param thd      The THD to rewrite for.
298   @param rlb      An empty String object to put the rewritten query in.
299 */
300 
mysql_rewrite_set(THD * thd,String * rlb)301 static void mysql_rewrite_set(THD *thd, String *rlb)
302 {
303   LEX                              *lex= thd->lex;
304   List_iterator_fast<set_var_base>  it(lex->var_list);
305   set_var_base                     *var;
306   bool                              comma= FALSE;
307 
308   rlb->append(STRING_WITH_LEN("SET "));
309 
310   while ((var= it++))
311   {
312     if (comma)
313       rlb->append(STRING_WITH_LEN(","));
314     else
315       comma= TRUE;
316 
317     var->print(thd, rlb);
318   }
319 }
320 
321 
322 /**
323   Rewrite CREATE USER statement.
324 
325   @param thd      The THD to rewrite for.
326   @param rlb      An empty String object to put the rewritten query in.
327 */
328 
mysql_rewrite_create_user(THD * thd,String * rlb)329 static void mysql_rewrite_create_user(THD *thd, String *rlb)
330 {
331   LEX                      *lex= thd->lex;
332   LEX_USER                 *user_name, *tmp_user_name;
333   List_iterator <LEX_USER>  user_list(lex->users_list);
334   bool                      comma= FALSE;
335 
336   rlb->append(STRING_WITH_LEN("CREATE USER "));
337   while ((tmp_user_name= user_list++))
338   {
339     if ((user_name= get_current_user(thd, tmp_user_name)))
340     {
341       append_user(thd, rlb, user_name, comma, TRUE);
342       comma= TRUE;
343     }
344   }
345 }
346 
347 
348 /**
349   Rewrite a CHANGE MASTER statement.
350 
351   @param thd      The THD to rewrite for.
352   @param rlb      An empty String object to put the rewritten query in.
353 */
354 
mysql_rewrite_change_master(THD * thd,String * rlb)355 static void mysql_rewrite_change_master(THD *thd, String *rlb)
356 {
357   LEX *lex= thd->lex;
358 
359   rlb->append(STRING_WITH_LEN("CHANGE MASTER TO"));
360 
361   if (lex->mi.host)
362   {
363     rlb->append(STRING_WITH_LEN(" MASTER_HOST = '"));
364     rlb->append(lex->mi.host);
365     rlb->append(STRING_WITH_LEN("'"));
366   }
367   if (lex->mi.user)
368   {
369     rlb->append(STRING_WITH_LEN(" MASTER_USER = '"));
370     rlb->append(lex->mi.user);
371     rlb->append(STRING_WITH_LEN("'"));
372   }
373   if (lex->mi.password)
374   {
375     rlb->append(STRING_WITH_LEN(" MASTER_PASSWORD = <secret>"));
376   }
377   if (lex->mi.port)
378   {
379     rlb->append(STRING_WITH_LEN(" MASTER_PORT = "));
380     rlb->append_ulonglong(lex->mi.port);
381   }
382   if (lex->mi.connect_retry)
383   {
384     rlb->append(STRING_WITH_LEN(" MASTER_CONNECT_RETRY = "));
385     rlb->append_ulonglong(lex->mi.connect_retry);
386   }
387   if (lex->mi.ssl)
388   {
389     rlb->append(STRING_WITH_LEN(" MASTER_SSL = "));
390     rlb->append(lex->mi.ssl == LEX_MASTER_INFO::LEX_MI_ENABLE ? "1" : "0");
391   }
392   if (lex->mi.ssl_ca)
393   {
394     rlb->append(STRING_WITH_LEN(" MASTER_SSL_CA = '"));
395     rlb->append(lex->mi.ssl_ca);
396     rlb->append(STRING_WITH_LEN("'"));
397   }
398   if (lex->mi.ssl_capath)
399   {
400     rlb->append(STRING_WITH_LEN(" MASTER_SSL_CAPATH = '"));
401     rlb->append(lex->mi.ssl_capath);
402     rlb->append(STRING_WITH_LEN("'"));
403   }
404   if (lex->mi.ssl_cert)
405   {
406     rlb->append(STRING_WITH_LEN(" MASTER_SSL_CERT = '"));
407     rlb->append(lex->mi.ssl_cert);
408     rlb->append(STRING_WITH_LEN("'"));
409   }
410   if (lex->mi.ssl_cipher)
411   {
412     rlb->append(STRING_WITH_LEN(" MASTER_SSL_CIPHER = '"));
413     rlb->append(lex->mi.ssl_cipher);
414     rlb->append(STRING_WITH_LEN("'"));
415   }
416   if (lex->mi.ssl_key)
417   {
418     rlb->append(STRING_WITH_LEN(" MASTER_SSL_KEY = '"));
419     rlb->append(lex->mi.ssl_key);
420     rlb->append(STRING_WITH_LEN("'"));
421   }
422   if (lex->mi.log_file_name)
423   {
424     rlb->append(STRING_WITH_LEN(" MASTER_LOG_FILE = '"));
425     rlb->append(lex->mi.log_file_name);
426     rlb->append(STRING_WITH_LEN("'"));
427   }
428   if (lex->mi.pos)
429   {
430     rlb->append(STRING_WITH_LEN(" MASTER_LOG_POS = "));
431     rlb->append_ulonglong(lex->mi.pos);
432   }
433   if (lex->mi.relay_log_name)
434   {
435     rlb->append(STRING_WITH_LEN(" RELAY_LOG_FILE = '"));
436     rlb->append(lex->mi.relay_log_name);
437     rlb->append(STRING_WITH_LEN("'"));
438   }
439   if (lex->mi.relay_log_pos)
440   {
441     rlb->append(STRING_WITH_LEN(" RELAY_LOG_POS = "));
442     rlb->append_ulonglong(lex->mi.relay_log_pos);
443   }
444 
445   if (lex->mi.ssl_verify_server_cert)
446   {
447     rlb->append(STRING_WITH_LEN(" MASTER_SSL_VERIFY_SERVER_CERT = "));
448     rlb->append(lex->mi.ssl_verify_server_cert == LEX_MASTER_INFO::LEX_MI_ENABLE ? "1" : "0");
449   }
450   if (lex->mi.repl_ignore_server_ids_opt)
451   {
452     bool first= TRUE;
453     rlb->append(STRING_WITH_LEN(" IGNORE_SERVER_IDS = ( "));
454     for (uint i= 0; i < lex->mi.repl_ignore_server_ids.elements; i++)
455     {
456       ulong s_id;
457       get_dynamic(&lex->mi.repl_ignore_server_ids, (uchar*) &s_id, i);
458       if (first)
459         first= FALSE;
460       else
461         rlb->append(STRING_WITH_LEN(", "));
462       rlb->append_ulonglong(s_id);
463     }
464     rlb->append(STRING_WITH_LEN(" )"));
465   }
466   if (lex->mi.heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
467   {
468     rlb->append(STRING_WITH_LEN(" MASTER_HEARTBEAT_PERIOD = "));
469     if (lex->mi.heartbeat_opt == LEX_MASTER_INFO::LEX_MI_DISABLE)
470       rlb->append(STRING_WITH_LEN("0"));
471     else
472     {
473       char buf[64];
474       snprintf(buf, 64, "%f", lex->mi.heartbeat_period);
475       rlb->append(buf);
476     }
477   }
478 }
479 
480 
481 /**
482   Rewrite a START SLAVE statement.
483 
484   @param thd      The THD to rewrite for.
485   @param rlb      An empty String object to put the rewritten query in.
486 */
487 
mysql_rewrite_start_slave(THD * thd,String * rlb)488 static void mysql_rewrite_start_slave(THD *thd, String *rlb)
489 {
490   LEX *lex= thd->lex;
491 
492   if (!lex->slave_connection.password)
493     return;
494 
495   rlb->append(STRING_WITH_LEN("START SLAVE"));
496 
497   if (lex->slave_thd_opt & SLAVE_IO)
498     rlb->append(STRING_WITH_LEN(" IO_THREAD"));
499 
500   /* we have printed the IO THREAD related options */
501   if (lex->slave_thd_opt & SLAVE_IO &&
502       lex->slave_thd_opt & SLAVE_SQL)
503     rlb->append(STRING_WITH_LEN(","));
504 
505   if (lex->slave_thd_opt & SLAVE_SQL)
506     rlb->append(STRING_WITH_LEN(" SQL_THREAD"));
507 
508   /* until options */
509   if (lex->mi.log_file_name || lex->mi.relay_log_name)
510   {
511     rlb->append(STRING_WITH_LEN(" UNTIL"));
512     if (lex->mi.log_file_name)
513     {
514       rlb->append(STRING_WITH_LEN(" MASTER_LOG_FILE = '"));
515       rlb->append(lex->mi.log_file_name);
516       rlb->append(STRING_WITH_LEN("', "));
517       rlb->append(STRING_WITH_LEN("MASTER_LOG_POS = "));
518       rlb->append_ulonglong(lex->mi.pos);
519     }
520 
521     if (lex->mi.relay_log_name)
522     {
523       rlb->append(STRING_WITH_LEN(" RELAY_LOG_FILE = '"));
524       rlb->append(lex->mi.relay_log_name);
525       rlb->append(STRING_WITH_LEN("', "));
526       rlb->append(STRING_WITH_LEN("RELAY_LOG_POS = "));
527       rlb->append_ulonglong(lex->mi.relay_log_pos);
528     }
529   }
530 
531   /* connection options */
532   if (lex->slave_connection.user)
533   {
534     rlb->append(STRING_WITH_LEN(" USER = '"));
535     rlb->append(lex->slave_connection.user);
536     rlb->append(STRING_WITH_LEN("'"));
537   }
538 
539   if (lex->slave_connection.password)
540     rlb->append(STRING_WITH_LEN(" PASSWORD = '<secret>'"));
541 
542   if (lex->slave_connection.plugin_auth)
543   {
544     rlb->append(STRING_WITH_LEN(" DEFAULT_AUTH = '"));
545     rlb->append(lex->slave_connection.plugin_auth);
546     rlb->append(STRING_WITH_LEN("'"));
547   }
548 
549   if (lex->slave_connection.plugin_dir)
550   {
551     rlb->append(STRING_WITH_LEN(" PLUGIN_DIR = '"));
552     rlb->append(lex->slave_connection.plugin_dir);
553     rlb->append(STRING_WITH_LEN("'"));
554   }
555 }
556 
557 
558 /**
559   Rewrite a SERVER OPTIONS clause (for CREATE SERVER and ALTER SERVER).
560 
561   @param thd      The THD to rewrite for.
562   @param rlb      An empty String object to put the rewritten query in.
563 */
564 
mysql_rewrite_server_options(THD * thd,String * rlb)565 static void mysql_rewrite_server_options(THD *thd, String *rlb)
566 {
567   LEX *lex= thd->lex;
568 
569   rlb->append(STRING_WITH_LEN(" OPTIONS ( "));
570 
571   rlb->append(STRING_WITH_LEN("PASSWORD '<secret>'"));
572   append_str(rlb, true, "USER", lex->server_options.username);
573   append_str(rlb, true, "HOST", lex->server_options.host);
574   append_str(rlb, true, "DATABASE", lex->server_options.db);
575   append_str(rlb, true, "OWNER", lex->server_options.owner);
576   append_str(rlb, true, "SOCKET", lex->server_options.socket);
577   append_int(rlb, true, STRING_WITH_LEN("PORT "), lex->server_options.port,
578              lex->server_options.port > 0);
579 
580   rlb->append(STRING_WITH_LEN(" )"));
581 }
582 
583 
584 /**
585   Rewrite a CREATE SERVER statement.
586 
587   @param thd      The THD to rewrite for.
588   @param rlb      An empty String object to put the rewritten query in.
589 */
590 
mysql_rewrite_create_server(THD * thd,String * rlb)591 static void mysql_rewrite_create_server(THD *thd, String *rlb)
592 {
593   LEX *lex= thd->lex;
594 
595   if (!lex->server_options.password)
596     return;
597 
598   rlb->append(STRING_WITH_LEN("CREATE SERVER "));
599 
600   rlb->append(lex->server_options.server_name ?
601               lex->server_options.server_name : "");
602 
603   rlb->append(STRING_WITH_LEN(" FOREIGN DATA WRAPPER '"));
604   rlb->append(lex->server_options.scheme ?
605               lex->server_options.scheme : "");
606   rlb->append(STRING_WITH_LEN("'"));
607 
608   mysql_rewrite_server_options(thd, rlb);
609 }
610 
611 
612 /**
613   Rewrite a ALTER SERVER statement.
614 
615   @param thd      The THD to rewrite for.
616   @param rlb      An empty String object to put the rewritten query in.
617 */
618 
mysql_rewrite_alter_server(THD * thd,String * rlb)619 static void mysql_rewrite_alter_server(THD *thd, String *rlb)
620 {
621   LEX *lex= thd->lex;
622 
623   if (!lex->server_options.password)
624     return;
625 
626   rlb->append(STRING_WITH_LEN("ALTER SERVER "));
627 
628   rlb->append(lex->server_options.server_name ?
629               lex->server_options.server_name : "");
630 
631   mysql_rewrite_server_options(thd, rlb);
632 }
633 
634 
635 
636 
637 /**
638   Rewrite a PREPARE statement.
639 
640   @param thd      The THD to rewrite for.
641   @param rlb      An empty String object to put the rewritten query in.
642 */
643 
mysql_rewrite_prepare(THD * thd,String * rlb)644 static void mysql_rewrite_prepare(THD *thd, String *rlb)
645 {
646   LEX *lex= thd->lex;
647 
648   if (lex->prepared_stmt_code_is_varref)
649     return;
650 
651   rlb->append(STRING_WITH_LEN("PREPARE "));
652   rlb->append(lex->prepared_stmt_name.str,
653               lex->prepared_stmt_name.length);
654   rlb->append(STRING_WITH_LEN(" FROM ..."));
655 }
656 
657 
658 
659 
660 /**
661    Rewrite a query (to obfuscate passwords etc.)
662 
663    Side-effects: thd->rewritten_query will contain a rewritten query,
664    or be cleared if no rewriting took place.
665 
666    @param thd     The THD to rewrite for.
667 */
668 
mysql_rewrite_query(THD * thd)669 void mysql_rewrite_query(THD *thd)
670 {
671   String *rlb= &thd->rewritten_query;
672 
673   rlb->free();
674 
675   if (thd->lex->contains_plaintext_password)
676   {
677     switch(thd->lex->sql_command)
678     {
679     case SQLCOM_GRANT:         mysql_rewrite_grant(thd, rlb);         break;
680     case SQLCOM_SET_OPTION:    mysql_rewrite_set(thd, rlb);           break;
681     case SQLCOM_CREATE_USER:   mysql_rewrite_create_user(thd, rlb);   break;
682     case SQLCOM_CHANGE_MASTER: mysql_rewrite_change_master(thd, rlb); break;
683     case SQLCOM_SLAVE_START:   mysql_rewrite_start_slave(thd, rlb);   break;
684     case SQLCOM_CREATE_SERVER: mysql_rewrite_create_server(thd, rlb); break;
685     case SQLCOM_ALTER_SERVER:  mysql_rewrite_alter_server(thd, rlb);  break;
686 
687     /*
688       PREPARE stmt FROM <string> is rewritten so that <string> is
689       not logged.  The statement in <string> will in turn be logged
690       by the prepare and the execute functions in sql_prepare.cc.
691       They do call rewrite so they can safely log the statement,
692       but when they call us, it'll be with sql_command set to reflect
693       the statement in question, not SQLCOM_PREPARE or SQLCOM_EXECUTE.
694       Therefore, there is no SQLCOM_EXECUTE case here, and all
695       SQLCOM_PREPARE does is remove <string>; the "other half",
696       i.e. printing what string we prepare from happens when the
697       prepare function calls the logger (and comes by here with
698       sql_command set to the command being prepared).
699     */
700     case SQLCOM_PREPARE:       mysql_rewrite_prepare(thd, rlb);       break;
701     default:                   /* unhandled query types are legal. */ break;
702     }
703   }
704 }
705