MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Chuck Bell Date:December 21 2009 7:30pm
Subject:bzr commit into mysql-5.6-next-mr branch (charles.bell:3022) Bug#44787
WL#5172
View as plain text  
#At file:///home/cbell/source/bzr/backport-MS04/ based on revid:charles.bell@stripped

 3022 Chuck Bell	2009-12-21
      BUG#44787 : Backup: Check privileges before executing BACKUP/RESTORE
      WL#5172 : MySQL Backup elevation options
      
      There are three problems that have been identified for this bug.
      
      1) Restore can fail in the middle if the user does not have 
      sufficient privileges to create and populate all of the
      objects. This patch implements a privilege precheck step to check
      all objects for proper access. If any object fails the
      privilege check, restore halts with an error. The object-level 
      privileges checked include the following.
      
      RESTORE,CREATE,DROP on db.*
      CREATE              on db.x (if table or view x)
      CREATE_TABLESPACE   on *.*  (if tablespace)
      SUPER               on *.*  (if view, stored routine, 
      				event or trigger)
      CREATE_PROC         on db.* (if stored routine)
      EVENT               on db.* (if event)
      GRANT               on db.* (if privilege)
      TRIGGER             on db.* (if trigger but table not found)
      TRIGGER             on db.t (if trigger on t)
      
      2) The backup system must be changed to permit the
      elevation of privileges for backup if the user has the 
      BACKUP_ACL privilege and elevation of privileges for restore 
      if the user has the RESTORE_ACL on all databases and the
      global SUPER_ACL privilege. This patch implements the privilege 
      elevation change for backup as well as privilege elevation for 
      restore. The restore will fall back to object-level privilege 
      checking if the conditions for restore are not met.
      
      3) The backup system must be changed to allow users to adjust the
      privilege behavior of MySQL Backup by allowing them 
      to turn off backup elevation, restore elevation, and restore
      prechecking using startup options. It shall also permit the user
      to turn restore prechecking on or off via a variable. This patch 
      implements the following:
      
      backup_elevation - startup option, global read only variable   
      ON  = turn on backup elevation
      OFF = turn off backup elevation
      Note: Default is ON
      
      restore_elevation - startup option, global read only variable   
      ON  = turn on restore elevation
      OFF = turn off restore elevation  
      Note: Default is ON
      
      restore_precheck - startup option, global and session variable  
      ON  = turn on restore precheck
      OFF = turn off restore precheck
      Note: Default is ON
      
      original changeset: 2899 (from mysql-6.0-backup)
     @ sql/backup/restore_info.cc
        New code file.
        Implements prechecking method.

    added:
      sql/backup/restore_info.cc
=== added file 'sql/backup/restore_info.cc'
--- a/sql/backup/restore_info.cc	1970-01-01 00:00:00 +0000
+++ b/sql/backup/restore_info.cc	2009-12-21 19:30:16 +0000
@@ -0,0 +1,226 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/**
+  @file
+
+  Implementation of @c Restore_info class methods. 
+  
+  Method @c check_restore_privileges performs privilege checking for restore.
+*/
+
+#include <backup/restore_info.h>
+
+
+/**
+  Perform privilege checking for restore.
+ 
+  This method checks the known minimal privileges needed to restore each
+  object in the backup image. This method is called once for every object in 
+  the catalog. It ensures there are no privilege-based restrictions that would 
+  prohibit a successful restore. 
+  
+  It begins by checking that the user has RESTORE for each database listed in 
+  the backup image. If the user does not have RESTORE for any database in the 
+  list, an error is generated. Next, specific object-level privilege checking 
+  is performed for all of the objects in the database. The object-level 
+  privileges checked include the following.
+
+  RESTORE,CREATE,DROP on db.*  
+  CREATE              on db.x (if table or view x)
+  CREATE_TABLESPACE   on *.*  (if tablespace)
+  SUPER               on *.*  (if view, stored routine, event or trigger)
+  CREATE_PROC         on db.* (if stored routine)
+  EVENT               on db.* (if event)
+  GRANT               on db.* (if privilege)
+  TRIGGER             on db.* (if trigger but table not found)
+  TRIGGER             on db.t (if trigger on t)
+ 
+  @note Object-level prechecking is skipped if restore_prechecking is
+  turned off or it has been determined it is safe to elevate restore. The
+  actual elevation of restore occurs before metadata creation. 
+ 
+  @param[in] item     The item to check.
+ 
+  @returns 
+    @retval  FALSE    User has privileges for the object.
+    @retval  TRUE     User does not have privileges for object.
+*/
+bool 
+Restore_info::check_restore_privileges(struct st_bstream_item_info *item)
+{
+  using namespace backup;
+  int result= 0;
+  THD *thd= ::current_thd;          
+  Image_info::Db *db= NULL;         // Database object
+  st_bstream_dbitem_info *db_item;  // Database item information
+  TABLE_LIST tbl_list;
+  
+
+  backup::String item_name(item->name.begin, item->name.end);
+  const char *name_str= item_name.c_ptr_safe();
+
+  DBUG_ASSERT(item);
+  
+  /*
+    Check privileges for this database. User must have RESTORE
+    privilege in order to execute a restore.
+  */
+  DEBUG_SYNC(thd, "before_restore_privileges");
+  
+  if (item->type == BSTREAM_IT_DB)
+  {
+    if (check_access(thd, RESTORE_ACL, name_str, 0, 1, 1, 0))
+    {
+      m_log.report_error(ER_RESTORE_ACCESS_DENIED_ERROR, name_str);
+      return TRUE;
+    }
+  }
+
+  /*
+    Since restore_elevation is a global read-only variable, we must turn 
+    result of elevation check off via debug to allow debug error insertion 
+    to work below.
+  */
+  DBUG_EXECUTE_IF("ER_RESTORE_DB_ERROR", m_restore_elevation= FALSE;);
+
+  /*
+    If prechecking is turned off or restore elevation is turned on,
+    skip prechecking.
+  */
+  if (!m_thd->variables.restore_precheck || m_restore_elevation)
+    return FALSE;
+
+  /*
+    Get the database for objects that have a database element.
+  */
+  switch (item->type) 
+  {
+  case BSTREAM_IT_TABLE:
+  case BSTREAM_IT_VIEW:
+  case BSTREAM_IT_SPROC:
+  case BSTREAM_IT_SFUNC:
+  case BSTREAM_IT_EVENT:
+  case BSTREAM_IT_TRIGGER:
+  case BSTREAM_IT_PRIVILEGE:
+    {
+      db_item= (st_bstream_dbitem_info*) item;
+
+      db= get_db(db_item->db->base.pos);
+      DBUG_EXECUTE_IF("ER_RESTORE_DB_ERROR", db= NULL;);
+      if (!db)
+      {
+        m_log.report_error(ER_RESTORE_DB_ERROR, name_str);
+        return TRUE;
+      }
+      break;
+    }
+  default:
+    break;
+  } // switch (item->type)
+
+  /*
+    Check privileges for each object based on type of object.
+  */
+  switch (item->type) 
+  {
+  case BSTREAM_IT_TABLESPACE:
+    {
+      result= !(thd->security_ctx->master_access & CREATE_TABLESPACE_ACL);
+      break;        
+    }
+  case BSTREAM_IT_DB:
+    {
+       result= check_access(thd, CREATE_ACL + DROP_ACL, name_str, 0, 1, 1, 0);
+       break;
+    }
+  case BSTREAM_IT_SPROC:
+  case BSTREAM_IT_SFUNC:
+    {
+      result= check_access(thd, CREATE_PROC_ACL, db->name().ptr(), 0, 1, 1, 0); 
+      break;
+    }
+  case BSTREAM_IT_EVENT:
+    {
+      result= check_access(thd, EVENT_ACL, db->name().ptr(), 0, 1, 1, 0); 
+      break;
+    }
+  case BSTREAM_IT_TRIGGER:
+    {
+      /*
+        Get the table reference for this trigger and check access.
+      */
+      Image_info::Table *tbl= get_table(db_item->snap_num, db_item->pos);
+      
+      /*
+        If the table is not found, revert to checking at the database
+        level.
+      */
+      if (!tbl)
+      {
+        result= check_access(thd, TRIGGER_ACL, db->name().ptr(), 0, 1, 1, 0); 
+      }
+      else 
+      {
+        tbl_list.init_one_table(db->name().ptr(), db->name().length(),
+                                tbl->name().ptr(), tbl->name().length(),
+                                tbl->name().ptr(), TL_READ);
+        result= check_table_access(thd, TRIGGER_ACL, &tbl_list, TRUE, TRUE, 1);
+      }
+      break;
+    }
+  case BSTREAM_IT_PRIVILEGE:
+    {
+      result= check_access(thd, GRANT_ACL, db->name().ptr(), 0, 1, 1, 0); 
+      break;
+    }
+  default:
+    break;
+  } // switch (item->type)
+    
+  // Return error if privilege check fails.
+  if (result)
+  {
+    m_log.report_error(ER_RESTORE_ACCESS_OBJS_INCOMPLETE, name_str);
+    return TRUE;
+  }
+
+  /*
+    Check for SUPER_ACL if any objects exist that have a definer clause.
+  */
+  switch (item->type) 
+  {
+  case BSTREAM_IT_VIEW:
+  case BSTREAM_IT_SPROC:
+  case BSTREAM_IT_SFUNC:
+  case BSTREAM_IT_EVENT:
+  case BSTREAM_IT_TRIGGER:
+    {
+      result= !(thd->security_ctx->master_access & SUPER_ACL);
+      break;
+    }
+  default:
+    break;
+  } // switch (item->type)
+  
+  // Return error if privilege check fails.
+  if (result)
+  {
+    m_log.report_error(ER_RESTORE_ACCESS_DEFINER, db->name().ptr(), name_str);
+    return TRUE;
+  }
+  return FALSE;
+}
+


Attachment: [text/bzr-bundle] bzr/charles.bell@sun.com-20091221193016-wujzz7a26av7isdj.bundle
Thread
bzr commit into mysql-5.6-next-mr branch (charles.bell:3022) Bug#44787WL#5172Chuck Bell21 Dec