---
 mysql-test/r/grant2.result |   24 ++++++++++++++++++++++++
 mysql-test/t/grant2.test   |   44 ++++++++++++++++++++++++++++++++++++++++++++
 sql/handler.h              |    1 +
 sql/sql_parse.cc           |   33 +++++++++++++++++++++++++++------
 sql/sql_yacc.yy            |    6 ++++++
 5 files changed, 102 insertions(+), 6 deletions(-)

--- sql/sql_parse.cc.orig
+++ sql/sql_parse.cc
@@ -76,6 +76,7 @@ static bool check_multi_update_lock(THD 
 static void remove_escape(char *name);
 static bool append_file_to_dir(THD *thd, const char **filename_ptr,
 			       const char *table_name);
+static bool check_show_create_table_access(THD *thd, TABLE_LIST *table);
 
 const char *any_db="*any*";	// Special symbol for check_access
 
@@ -2983,7 +2984,7 @@ mysql_execute_command(THD *thd)
     else
     {
       /* regular create */
-      if (lex->name)
+      if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
         res= mysql_create_like_table(thd, create_table, &lex->create_info, 
                                      (Table_ident *)lex->name); 
       else
@@ -3185,11 +3186,7 @@ end_with_restore_list:
         first_table->skip_temporary= 1;
 
       if (check_db_used(thd, all_tables) ||
-	  check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db,
-		       &first_table->grant.privilege, 0, 0, 
-                       test(first_table->schema_table)))
-	goto error;
-      if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0))
+          check_show_create_table_access(thd, first_table))
 	goto error;
       res= mysqld_show_create(thd, first_table);
       break;
@@ -7372,6 +7369,25 @@ bool insert_precheck(THD *thd, TABLE_LIS
 }
 
 
+/**
+   @brief  Check privileges for SHOW CREATE TABLE statement.
+
+   @param  thd    Thread context
+   @param  table  Target table
+
+   @retval TRUE  Failure
+   @retval FALSE Success
+*/
+
+static bool check_show_create_table_access(THD *thd, TABLE_LIST *table)
+{
+  return check_access(thd, SELECT_ACL | EXTRA_ACL, table->db,
+                      &table->grant.privilege, 0, 0,
+                      test(table->schema_table)) ||
+         grant_option && check_grant(thd, SELECT_ACL, table, 2, UINT_MAX, 0);
+}
+
+
 /*
   CREATE TABLE query pre-check
 
@@ -7437,6 +7453,11 @@ bool create_table_precheck(THD *thd, TAB
     if (tables && check_table_access(thd, SELECT_ACL, tables,0))
       goto err;
   }
+  else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
+  {
+    if (check_show_create_table_access(thd, tables))
+      goto err;
+  }
   error= FALSE;
 
 err:
--- mysql-test/r/grant2.result.orig
+++ mysql-test/r/grant2.result
@@ -380,3 +380,27 @@ drop function f2;
 drop table t2;
 REVOKE ALL PRIVILEGES, GRANT OPTION FROM `a@`@localhost;
 drop user `a@`@localhost;
+drop database if exists mysqltest_1;
+drop database if exists mysqltest_2;
+drop user mysqltest_u1@localhost;
+create database mysqltest_1;
+create database mysqltest_2;
+grant all on mysqltest_1.* to mysqltest_u1@localhost;
+use mysqltest_2;
+create table t1 (i int);
+show create table mysqltest_2.t1;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
+create table t1 like mysqltest_2.t1;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
+grant select on mysqltest_2.t1 to mysqltest_u1@localhost;
+show create table mysqltest_2.t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t1 like mysqltest_2.t1;
+use test;
+drop database mysqltest_1;
+drop database mysqltest_2;
+drop user mysqltest_u1@localhost;
+End of 5.0 tests
--- mysql-test/t/grant2.test.orig
+++ mysql-test/t/grant2.test
@@ -509,3 +509,47 @@ disconnect bug13310;
 connection default;
 REVOKE ALL PRIVILEGES, GRANT OPTION FROM `a@`@localhost;
 drop user `a@`@localhost;
+
+
+#
+# Bug#25578 "CREATE TABLE LIKE does not require any privileges on source table"
+#
+--disable_warnings
+drop database if exists mysqltest_1;
+drop database if exists mysqltest_2;
+--enable_warnings
+--error 0,ER_CANNOT_USER
+drop user mysqltest_u1@localhost;
+
+create database mysqltest_1;
+create database mysqltest_2;
+grant all on mysqltest_1.* to mysqltest_u1@localhost;
+use mysqltest_2;
+create table t1 (i int);
+
+# Connect as user with all rights on mysqltest_1 but with no rights on mysqltest_2.
+connect (user1,localhost,mysqltest_u1,,mysqltest_1);
+connection user1;
+# As expected error is emitted
+--error ER_TABLEACCESS_DENIED_ERROR
+show create table mysqltest_2.t1;
+# This should emit error as well
+--error ER_TABLEACCESS_DENIED_ERROR
+create table t1 like mysqltest_2.t1;
+
+# Now let us check that SELECT privilege on the source is enough
+connection default;
+grant select on mysqltest_2.t1 to mysqltest_u1@localhost;
+connection user1;
+show create table mysqltest_2.t1;
+create table t1 like mysqltest_2.t1;
+
+# Clean-up
+connection default;
+use test;
+drop database mysqltest_1;
+drop database mysqltest_2;
+drop user mysqltest_u1@localhost;
+
+--echo End of 5.0 tests
+
--- sql/handler.h.orig
+++ sql/handler.h
@@ -163,6 +163,7 @@
 
 #define HA_LEX_CREATE_TMP_TABLE	1
 #define HA_LEX_CREATE_IF_NOT_EXISTS 2
+#define HA_LEX_CREATE_TABLE_LIKE 4
 #define HA_OPTION_NO_CHECKSUM	(1L << 17)
 #define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18)
 #define HA_MAX_REC_LENGTH	65535
--- sql/sql_yacc.yy.orig
+++ sql/sql_yacc.yy
@@ -2454,6 +2454,9 @@ create2:
           {
             LEX *lex=Lex;
             THD *thd= lex->thd;
+            Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
+            if (!Lex->select_lex.add_table_to_list(YYTHD, $2, NULL, 0, TL_READ))
+              YYABORT;
             if (!(lex->name= (char *)$2))
               YYABORT;
             if ($2->db.str == NULL &&
@@ -2466,6 +2469,9 @@ create2:
           {
             LEX *lex=Lex;
             THD *thd= lex->thd;
+            Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
+            if (!Lex->select_lex.add_table_to_list(YYTHD, $3, NULL, 0, TL_READ))
+              YYABORT;
             if (!(lex->name= (char *)$3))
               YYABORT;
             if ($3->db.str == NULL &&
