MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:kgeorge Date:May 19 2006 11:11am
Subject:bk commit into 5.0 tree (gkodinov:1.2144) BUG#18681
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of kgeorge. When kgeorge does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2144 06/05/19 14:11:24 gkodinov@stripped +14 -0
  BUG#18681: View privileges are broken
  
  The check for view security was lacking several points :
  1. Check with the right set of permissions : for each table ref that
  participates in a view there were the right credentials to use in it's
  security_ctx member, but these weren't used for checking the credentials.
  This makes hard enforcing the SQL SECURITY DEFINER|INVOKER property
  consistently.
  2. Because of the above the security checking for views was just ruled out
  in explicit ways in several places.
  3. The security was checked only for the columns of the tables that are
  brought into the query from a view. So if there is no column reference
  outside of the view definition it was not detecting the lack of access to
  the tables in the view in SQL SECURITY INVOKER mode.
  
  The fix below tries to fix the above 3 points.

  sql/table.cc
    1.219 06/05/19 14:11:18 gkodinov@stripped +2 -1
    Mask table access to the view error as well.

  sql/sql_update.cc
    1.188 06/05/19 14:11:18 gkodinov@stripped +11 -8
    wrapper called

  sql/sql_select.cc
    1.417 06/05/19 14:11:18 gkodinov@stripped +4 -3
    wrapper called

  sql/sql_parse.cc
    1.546 06/05/19 14:11:18 gkodinov@stripped +29 -8
    wrapper called and artificial check stop removed

  sql/sql_load.cc
    1.95 06/05/19 14:11:18 gkodinov@stripped +5 -4
    wrapper called

  sql/sql_insert.cc
    1.189 06/05/19 14:11:18 gkodinov@stripped +5 -4
    wrapper called

  sql/sql_delete.cc
    1.174 06/05/19 14:11:18 gkodinov@stripped +10 -8
    wrapper called.

  sql/sql_base.cc
    1.337 06/05/19 14:11:18 gkodinov@stripped +52 -0
    a wrapper for setup_tables to check access to the tables

  sql/sql_acl.cc
    1.193 06/05/19 14:11:18 gkodinov@stripped +10 -5
    removed artificial security check stop and used the table ref's credentials.

  sql/mysql_priv.h
    1.390 06/05/19 14:11:18 gkodinov@stripped +7 -0
    A wrapper for setup_tables that also checks access to the tables

  mysql-test/t/view_grant.test
    1.12 06/05/19 14:11:17 gkodinov@stripped +81 -0
    Somewhat extended test case for the bug and similar queries.

  mysql-test/t/grant.test
    1.40 06/05/19 14:11:17 gkodinov@stripped +2 -2
    removed nondeterminism (unspecified order) in some test output

  mysql-test/r/view_grant.result
    1.14 06/05/19 14:11:17 gkodinov@stripped +70 -0
    Somewhat extended test case for the bug and similar queries.

  mysql-test/r/grant.result
    1.51 06/05/19 14:11:17 gkodinov@stripped +3 -10
    removed nondeterminism (unspecified order) in some test output

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	gkodinov
# Host:	rakia.(none)
# Root:	/home/kgeorge/mysql/5.0/B18681

--- 1.389/sql/mysql_priv.h	2006-05-15 20:23:06 +03:00
+++ 1.390/sql/mysql_priv.h	2006-05-19 14:11:18 +03:00
@@ -946,6 +946,13 @@
 bool setup_tables(THD *thd, Name_resolution_context *context,
                   List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
                   Item **conds, TABLE_LIST **leaves, bool select_insert);
+bool setup_tables_and_check_access (THD *thd, 
+                                    Name_resolution_context *context,
+                                    List<TABLE_LIST> *from_clause, 
+                                    TABLE_LIST *tables, Item **conds, 
+                                    TABLE_LIST **leaves, 
+                                    bool select_insert,
+                                    ulong want_access);
 int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
 	       List<Item> *sum_func_list, uint wild_num);
 bool setup_fields(THD *thd, Item** ref_pointer_array,

--- 1.192/sql/sql_acl.cc	2006-05-09 11:44:13 +03:00
+++ 1.193/sql/sql_acl.cc	2006-05-19 14:11:18 +03:00
@@ -3562,6 +3562,7 @@
   TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table();
   Security_context *sctx= thd->security_ctx;
   uint i;
+  ulong orig_want_access= want_access;
   DBUG_ENTER("check_grant");
   DBUG_ASSERT(number > 0);
 
@@ -3583,18 +3584,22 @@
     table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
   }
 
-  want_access&= ~sctx->master_access;
-  if (!want_access)
-    DBUG_RETURN(0);                             // ok
-
   rw_rdlock(&LOCK_grant);
   for (table= tables;
        table && number-- && table != first_not_own_table;
        table= table->next_global)
   {
     GRANT_TABLE *grant_table;
+    sctx = test(table->security_ctx) ?
+      table->security_ctx : thd->security_ctx;
+
+    want_access= orig_want_access;
+    want_access&= ~sctx->master_access;
+    if (!want_access)
+      continue;                                 // ok
+
     if (!(~table->grant.privilege & want_access) || 
-        table->derived || table->schema_table || table->belong_to_view)
+        table->derived || table->schema_table)
     {
       /*
         It is subquery in the FROM clause. VIEW set table->derived after

--- 1.336/sql/sql_base.cc	2006-05-15 20:23:06 +03:00
+++ 1.337/sql/sql_base.cc	2006-05-19 14:11:18 +03:00
@@ -4498,6 +4498,58 @@
 
 
 /*
+  prepare tables and check access for the view tables
+
+  SYNOPSIS
+    setup_tables_and_check_view_access()
+    thd		  Thread handler
+    context       name resolution contest to setup table list there
+    from_clause   Top-level list of table references in the FROM clause
+    tables	  Table list (select_lex->table_list)
+    conds	  Condition of current SELECT (can be changed by VIEW)
+    leaves        List of join table leaves list (select_lex->leaf_tables)
+    refresh       It is onle refresh for subquery
+    select_insert It is SELECT ... INSERT command
+    want_access   what access is needed
+
+  NOTE
+    a wrapper for check_tables that will also check the resulting
+    table leaves list for access to all the tables that belong to a view
+
+  RETURN
+    FALSE ok;  In this case *map will include the chosen index
+    TRUE  error
+*/
+bool setup_tables_and_check_access(THD *thd, 
+                                   Name_resolution_context *context,
+                                   List<TABLE_LIST> *from_clause,
+                                   TABLE_LIST *tables,
+                                   Item **conds, TABLE_LIST **leaves,
+                                   bool select_insert,
+                                   ulong want_access)
+{
+  TABLE_LIST *leaves_tmp = NULL;
+
+  if (setup_tables (thd, context, from_clause, tables, conds, 
+                    &leaves_tmp, select_insert))
+    return TRUE;
+
+  if (leaves)
+    *leaves = leaves_tmp;
+
+  for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf)
+    if (leaves_tmp->belong_to_view && 
+        check_one_table_access(thd, want_access,  leaves_tmp))
+    {
+      tables->hide_view_error(thd);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+/*
    Create a key_map from a list of index names
 
    SYNOPSIS

--- 1.173/sql/sql_delete.cc	2006-04-06 13:18:57 +03:00
+++ 1.174/sql/sql_delete.cc	2006-05-19 14:11:18 +03:00
@@ -334,10 +334,11 @@
   DBUG_ENTER("mysql_prepare_delete");
 
   thd->lex->allow_sum_func= 0;
-  if (setup_tables(thd, &thd->lex->select_lex.context,
-                   &thd->lex->select_lex.top_join_list,
-                   table_list, conds, &select_lex->leaf_tables,
-                   FALSE) ||
+  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
+                                    &thd->lex->select_lex.top_join_list,
+                                    table_list, conds, 
+                                    &select_lex->leaf_tables, FALSE, 
+                                    DELETE_ACL) ||
       setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
       setup_ftfuncs(select_lex))
     DBUG_RETURN(TRUE);
@@ -396,10 +397,11 @@
 
     lex->query_tables also point on local list of DELETE SELECT_LEX
   */
-  if (setup_tables(thd, &thd->lex->select_lex.context,
-                   &thd->lex->select_lex.top_join_list,
-                   lex->query_tables, &lex->select_lex.where,
-                   &lex->select_lex.leaf_tables, FALSE))
+  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
+                                    &thd->lex->select_lex.top_join_list,
+                                    lex->query_tables, &lex->select_lex.where,
+                                    &lex->select_lex.leaf_tables, FALSE, 
+                                    DELETE_ACL))
     DBUG_RETURN(TRUE);
 
 

--- 1.188/sql/sql_insert.cc	2006-05-09 15:41:39 +03:00
+++ 1.189/sql/sql_insert.cc	2006-05-19 14:11:18 +03:00
@@ -743,10 +743,11 @@
   bool insert_into_view= (table_list->view != 0);
   DBUG_ENTER("mysql_prepare_insert_check_table");
 
-  if (setup_tables(thd, &thd->lex->select_lex.context,
-                   &thd->lex->select_lex.top_join_list,
-                   table_list, where, &thd->lex->select_lex.leaf_tables,
-		   select_insert))
+  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
+                                    &thd->lex->select_lex.top_join_list,
+                                    table_list, where, 
+                                    &thd->lex->select_lex.leaf_tables,
+                                    select_insert, INSERT_ACL))
     DBUG_RETURN(TRUE);
 
   if (insert_into_view && !fields.elements)

--- 1.94/sql/sql_load.cc	2006-03-29 19:17:14 +03:00
+++ 1.95/sql/sql_load.cc	2006-05-19 14:11:18 +03:00
@@ -153,10 +153,11 @@
   ha_enable_transaction(thd, FALSE); 
   if (open_and_lock_tables(thd, table_list))
     DBUG_RETURN(TRUE);
-  if (setup_tables(thd, &thd->lex->select_lex.context,
-                   &thd->lex->select_lex.top_join_list,
-                   table_list, &unused_conds,
-		   &thd->lex->select_lex.leaf_tables, FALSE))
+  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
+                                    &thd->lex->select_lex.top_join_list,
+                                    table_list, &unused_conds,
+                                    &thd->lex->select_lex.leaf_tables, FALSE,
+                                    INSERT_ACL | UPDATE_ACL))
      DBUG_RETURN(-1);
   if (!table_list->table ||               // do not suport join view
       !table_list->updatable ||           // and derived tables

--- 1.545/sql/sql_parse.cc	2006-05-14 23:51:01 +03:00
+++ 1.546/sql/sql_parse.cc	2006-05-19 14:11:18 +03:00
@@ -4994,23 +4994,35 @@
 
 bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
 {
+  Security_context * backup_ctx= thd->security_ctx;
+
+  /* we need to switch to the saved context (if any) */
+  if (all_tables->security_ctx)
+    thd->security_ctx= all_tables->security_ctx;
+
   if (check_access(thd, privilege, all_tables->db,
 		   &all_tables->grant.privilege, 0, 0,
                    test(all_tables->schema_table)))
-    return 1;
+    goto deny;
 
   /* Show only 1 table for check_grant */
   if (grant_option && check_grant(thd, privilege, all_tables, 0, 1, 0))
-    return 1;
+    goto deny;
+
+  thd->security_ctx= backup_ctx;
 
   /* Check rights on tables of subselects and implictly opened tables */
   TABLE_LIST *subselects_tables;
   if ((subselects_tables= all_tables->next_global))
   {
     if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
-      return 1;
+      goto deny;
   }
   return 0;
+
+deny:
+  thd->security_ctx= backup_ctx;
+  return 1;
 }
 
 
@@ -5191,6 +5203,7 @@
   ulong found_access=0;
   TABLE_LIST *org_tables= tables;
   TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
+  Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx;
   /*
     The check that first_not_own_table is not reached is for the case when
     the given table list refers to the list for prelocking (contains tables
@@ -5198,12 +5211,15 @@
   */
   for (; tables != first_not_own_table; tables= tables->next_global)
   {
+    if (tables->security_ctx)
+      sctx= tables->security_ctx;
+
     if (tables->schema_table && 
         (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
     {
       if (!no_errors)
         my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
-                 thd->security_ctx->priv_user, thd->security_ctx->priv_host,
+                 sctx->priv_user, sctx->priv_host,
                  information_schema_name.str);
       return TRUE;
     }
@@ -5212,12 +5228,13 @@
        Remove SHOW_VIEW_ACL, because it will be checked during making view
      */
     tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
-    if (tables->derived || tables->schema_table || tables->belong_to_view ||
+    if (tables->derived || tables->schema_table ||
         (tables->table && (int)tables->table->s->tmp_table) ||
         my_tz_check_n_skip_implicit_tables(&tables,
                                            thd->lex->time_zone_tables_used))
       continue;
-    if ((thd->security_ctx->master_access & want_access) ==
+    thd->security_ctx= sctx;
+    if ((sctx->master_access & want_access) ==
         (want_access & ~EXTRA_ACL) &&
 	thd->db)
       tables->grant.privilege= want_access;
@@ -5229,19 +5246,23 @@
       {
 	if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
 			 0, no_errors, test(tables->schema_table)))
-	  return TRUE;				// Access denied
+	  goto deny;                            // Access denied
 	found_access=tables->grant.privilege;
 	found=1;
       }
     }
     else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
 			  0, no_errors, test(tables->schema_table)))
-      return TRUE;
+      goto deny;
   }
+  thd->security_ctx= backup_ctx;
   if (grant_option)
     return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
 		       test(want_access & EXTRA_ACL), UINT_MAX, no_errors);
   return FALSE;
+deny:
+  thd->security_ctx= backup_ctx;
+  return TRUE;
 }
 
 

--- 1.416/sql/sql_select.cc	2006-05-10 16:40:15 +03:00
+++ 1.417/sql/sql_select.cc	2006-05-19 14:11:18 +03:00
@@ -337,9 +337,10 @@
   /* Check that all tables, fields, conds and order are ok */
 
   if ((!(select_options & OPTION_SETUP_TABLES_DONE) &&
-       setup_tables(thd, &select_lex->context, join_list,
-                    tables_list, &conds, &select_lex->leaf_tables,
-                    FALSE)) ||
+       setup_tables_and_check_access(thd, &select_lex->context, join_list,
+                                     tables_list, &conds, 
+                                     &select_lex->leaf_tables, FALSE, 
+                                     SELECT_ACL)) ||
       setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
       select_lex->setup_ref_array(thd, og_num) ||
       setup_fields(thd, (*rref_pointer_array), fields_list, 1,

--- 1.187/sql/sql_update.cc	2006-04-05 12:27:49 +03:00
+++ 1.188/sql/sql_update.cc	2006-05-19 14:11:18 +03:00
@@ -613,9 +613,11 @@
   tables.alias= table_list->alias;
   thd->lex->allow_sum_func= 0;
 
-  if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
-                   table_list, conds, &select_lex->leaf_tables,
-                   FALSE) ||
+  if (setup_tables_and_check_access(thd, &select_lex->context, 
+                                    &select_lex->top_join_list,
+                                    table_list, conds, 
+                                    &select_lex->leaf_tables,
+                                    FALSE, UPDATE_ACL) ||
       setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
       select_lex->setup_ref_array(thd, order_num) ||
       setup_order(thd, select_lex->ref_pointer_array,
@@ -690,7 +692,7 @@
   bool need_reopen= FALSE;
   DBUG_ENTER("mysql_multi_update_prepare");
 
-  /* following need for prepared statements, to run next time multi-update */
+  /* following need for prepared statements, to run next time multi-update */ 
   thd->lex->sql_command= SQLCOM_UPDATE_MULTI;
 
 reopen_tables:
@@ -706,10 +708,11 @@
     call in setup_tables()).
   */
 
-  if (setup_tables(thd, &lex->select_lex.context,
-                   &lex->select_lex.top_join_list,
-                   table_list, &lex->select_lex.where,
-                   &lex->select_lex.leaf_tables, FALSE))
+  if (setup_tables_and_check_access(thd, &lex->select_lex.context,
+                                    &lex->select_lex.top_join_list,
+                                    table_list, &lex->select_lex.where,
+                                    &lex->select_lex.leaf_tables, FALSE,
+                                    UPDATE_ACL))
     DBUG_RETURN(TRUE);
 
   if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0))

--- 1.218/sql/table.cc	2006-03-22 11:11:23 +02:00
+++ 1.219/sql/table.cc	2006-05-19 14:11:18 +03:00
@@ -2068,7 +2068,8 @@
   if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
       thd->net.last_errno == ER_SP_DOES_NOT_EXIST ||
       thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR ||
-      thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR)
+      thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR ||
+      thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR)
   {
     TABLE_LIST *top= top_table();
     thd->clear_error();

--- 1.13/mysql-test/r/view_grant.result	2006-05-12 19:58:51 +03:00
+++ 1.14/mysql-test/r/view_grant.result	2006-05-19 14:11:17 +03:00
@@ -533,3 +533,73 @@
 v2	CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select 1 AS `1`
 drop view v1;
 drop view v2;
+CREATE DATABASE mysqltest1;
+CREATE USER readonly@localhost;
+CREATE TABLE mysqltest1.t1 (x INT);
+INSERT INTO mysqltest1.t1 VALUES (1), (2);
+CREATE SQL SECURITY INVOKER VIEW mysqltest1.v_t1 AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ts AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ti AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tu AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tus AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_td AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tds AS SELECT * FROM mysqltest1.t1;
+GRANT SELECT, INSERT, UPDATE, DELETE ON mysqltest1.v_t1 TO readonly;
+GRANT SELECT ON mysqltest1.v_ts TO readonly;
+GRANT INSERT ON mysqltest1.v_ti TO readonly;
+GRANT UPDATE ON mysqltest1.v_tu TO readonly;
+GRANT UPDATE,SELECT ON mysqltest1.v_tus TO readonly;
+GRANT DELETE ON mysqltest1.v_td TO readonly;
+GRANT DELETE,SELECT ON mysqltest1.v_tds TO readonly;
+SELECT * FROM mysqltest1.v_t1;
+ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+INSERT INTO mysqltest1.v_t1 VALUES(4);
+ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+DELETE FROM mysqltest1.v_t1 WHERE x = 1;
+ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+UPDATE mysqltest1.v_t1 SET x = 3 WHERE x = 2;
+ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+UPDATE mysqltest1.v_t1 SET x = 3;
+ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+DELETE FROM mysqltest1.v_t1;
+ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+SELECT 1 FROM mysqltest1.v_t1;
+ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+SELECT * FROM mysqltest1.t1;
+ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for table 't1'
+SELECT * FROM mysqltest1.v_ts;
+x
+1
+2
+SELECT * FROM mysqltest1.v_ts, mysqltest1.t1 WHERE mysqltest1.t1.x = mysqltest1.v_ts.x;
+ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for table 't1'
+SELECT * FROM mysqltest1.v_ti;
+ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for table 'v_ti'
+INSERT INTO mysqltest1.v_ts VALUES (100);
+ERROR 42000: INSERT command denied to user 'readonly'@'localhost' for table 'v_ts'
+INSERT INTO mysqltest1.v_ti VALUES (100);
+UPDATE mysqltest1.v_ts SET x= 200 WHERE x = 100;
+ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_ts'
+UPDATE mysqltest1.v_ts SET x= 200;
+ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_ts'
+UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
+UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
+UPDATE mysqltest1.v_tu SET x= 200;
+DELETE FROM mysqltest1.v_ts WHERE x= 200;
+ERROR 42000: DELETE command denied to user 'readonly'@'localhost' for table 'v_ts'
+DELETE FROM mysqltest1.v_ts;
+ERROR 42000: DELETE command denied to user 'readonly'@'localhost' for table 'v_ts'
+DELETE FROM mysqltest1.v_td WHERE x= 200;
+ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for column 'x' in table 'v_td'
+DELETE FROM mysqltest1.v_tds WHERE x= 200;
+DELETE FROM mysqltest1.v_td;
+DROP VIEW mysqltest1.v_tds;
+DROP VIEW mysqltest1.v_td;
+DROP VIEW mysqltest1.v_tus;
+DROP VIEW mysqltest1.v_tu;
+DROP VIEW mysqltest1.v_ti;
+DROP VIEW mysqltest1.v_ts;
+DROP VIEW mysqltest1.v_t1;
+DROP TABLE mysqltest1.t1;
+DROP USER readonly@localhost;
+DROP DATABASE mysqltest1;

--- 1.11/mysql-test/t/view_grant.test	2006-03-10 13:40:12 +02:00
+++ 1.12/mysql-test/t/view_grant.test	2006-05-19 14:11:17 +03:00
@@ -712,3 +712,84 @@
 show create view v2;
 drop view v1;
 drop view v2;
+
+#
+# Bug#18681: View privileges are broken
+#
+CREATE DATABASE mysqltest1;
+CREATE USER readonly@localhost;
+CREATE TABLE mysqltest1.t1 (x INT);
+INSERT INTO mysqltest1.t1 VALUES (1), (2);
+CREATE SQL SECURITY INVOKER VIEW mysqltest1.v_t1 AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ts AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ti AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tu AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tus AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_td AS SELECT * FROM mysqltest1.t1;
+CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tds AS SELECT * FROM mysqltest1.t1;
+GRANT SELECT, INSERT, UPDATE, DELETE ON mysqltest1.v_t1 TO readonly;
+GRANT SELECT ON mysqltest1.v_ts TO readonly;
+GRANT INSERT ON mysqltest1.v_ti TO readonly;
+GRANT UPDATE ON mysqltest1.v_tu TO readonly;
+GRANT UPDATE,SELECT ON mysqltest1.v_tus TO readonly;
+GRANT DELETE ON mysqltest1.v_td TO readonly;
+GRANT DELETE,SELECT ON mysqltest1.v_tds TO readonly;
+
+CONNECT (n1,localhost,readonly,,);
+CONNECTION n1;
+
+--error 1356
+SELECT * FROM mysqltest1.v_t1;
+--error 1356
+INSERT INTO mysqltest1.v_t1 VALUES(4);
+--error 1356
+DELETE FROM mysqltest1.v_t1 WHERE x = 1;
+--error 1356
+UPDATE mysqltest1.v_t1 SET x = 3 WHERE x = 2;
+--error 1356
+UPDATE mysqltest1.v_t1 SET x = 3;
+--error 1356
+DELETE FROM mysqltest1.v_t1;
+--error 1356
+SELECT 1 FROM mysqltest1.v_t1;
+--error 1142
+SELECT * FROM mysqltest1.t1;
+
+SELECT * FROM mysqltest1.v_ts;
+--error 1142
+SELECT * FROM mysqltest1.v_ts, mysqltest1.t1 WHERE mysqltest1.t1.x = mysqltest1.v_ts.x;
+--error 1142
+SELECT * FROM mysqltest1.v_ti;
+
+--error 1142
+INSERT INTO mysqltest1.v_ts VALUES (100);
+INSERT INTO mysqltest1.v_ti VALUES (100);
+
+--error 1142
+UPDATE mysqltest1.v_ts SET x= 200 WHERE x = 100;
+--error 1142
+UPDATE mysqltest1.v_ts SET x= 200;
+UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
+UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
+UPDATE mysqltest1.v_tu SET x= 200;
+
+--error 1142
+DELETE FROM mysqltest1.v_ts WHERE x= 200;
+--error 1142
+DELETE FROM mysqltest1.v_ts;
+--error 1143
+DELETE FROM mysqltest1.v_td WHERE x= 200;
+DELETE FROM mysqltest1.v_tds WHERE x= 200;
+DELETE FROM mysqltest1.v_td;
+
+CONNECTION default;
+DROP VIEW mysqltest1.v_tds;
+DROP VIEW mysqltest1.v_td;
+DROP VIEW mysqltest1.v_tus;
+DROP VIEW mysqltest1.v_tu;
+DROP VIEW mysqltest1.v_ti;
+DROP VIEW mysqltest1.v_ts;
+DROP VIEW mysqltest1.v_t1;
+DROP TABLE mysqltest1.t1;
+DROP USER readonly@localhost; 
+DROP DATABASE mysqltest1;

--- 1.50/mysql-test/r/grant.result	2006-03-06 13:14:08 +02:00
+++ 1.51/mysql-test/r/grant.result	2006-05-19 14:11:17 +03:00
@@ -357,12 +357,12 @@
 Grants for grant_user@localhost
 GRANT USAGE ON *.* TO 'grant_user'@'localhost'
 GRANT INSERT (a, d, c, b) ON `test`.`t1` TO 'grant_user'@'localhost'
-select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv;
+select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv order by Column_name;
 Host	Db	User	Table_name	Column_name	Column_priv
-localhost	test	grant_user	t1	b	Insert
-localhost	test	grant_user	t1	d	Insert
 localhost	test	grant_user	t1	a	Insert
+localhost	test	grant_user	t1	b	Insert
 localhost	test	grant_user	t1	c	Insert
+localhost	test	grant_user	t1	d	Insert
 revoke ALL PRIVILEGES on t1 from grant_user@localhost;
 show grants for grant_user@localhost;
 Grants for grant_user@localhost
@@ -381,13 +381,6 @@
 grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost;
 grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost;
 grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost;
-show grants for mysqltest_3@localhost;
-Grants for mysqltest_3@localhost
-GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost'
-GRANT SELECT (b) ON `mysqltest_1`.`t2` TO 'mysqltest_3'@'localhost'
-GRANT UPDATE (a) ON `mysqltest_1`.`t1` TO 'mysqltest_3'@'localhost'
-GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost'
-GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost'
 update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
 ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for column 'q' in table 't1'
 update mysqltest_1.t2, mysqltest_2.t2 set d=20 where d=1;

--- 1.39/mysql-test/t/grant.test	2006-03-06 12:10:20 +02:00
+++ 1.40/mysql-test/t/grant.test	2006-05-19 14:11:17 +03:00
@@ -302,7 +302,7 @@
 create table t1(a int, b int, c int, d int);
 grant insert(b), insert(c), insert(d), insert(a) on t1 to grant_user@localhost;
 show grants for grant_user@localhost;
-select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv;
+select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv order by Column_name;
 revoke ALL PRIVILEGES on t1 from grant_user@localhost;
 show grants for grant_user@localhost;
 select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv;
@@ -326,7 +326,7 @@
 grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost;
 connect (conn1,localhost,mysqltest_3,,);
 connection conn1;
-show grants for mysqltest_3@localhost;
+#FIXME: unsorted grant display order show grants for mysqltest_3@localhost;
 --error 1143
 update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
 --error 1143
Thread
bk commit into 5.0 tree (gkodinov:1.2144) BUG#18681kgeorge19 May