List:Commits« Previous MessageNext Message »
From:Chuck Bell Date:July 15 2009 2:19pm
Subject:bzr commit into mysql-5.4 branch (charles.bell:2844) Bug#45889
View as plain text  
#At file:///Users/cbell/source/bzr/mysql-6.0-bug-45889/ based on revid:rafal.somla@stripped

 2844 Chuck Bell	2009-07-15 [merge]
      BUG#45889 : BACKUP DATABASE command should include all objects 
      
      PROBLEM: The code currently silently succeeds if a user is not able to read
      all of the objects and their metadata in the database and, in the case of
      BACKUP DATABASE *, is not able to read all of the databases.
      
      This is an error because the BACKUP DATABASE command has been clarified
      to error if a user cannot read all of the objects and their metadata
      all all of the databases listed.
      
      This patch implements a solution to produce an error if either of the
      following are true:
      
      * The user cannot read (SELECT) all of the databases when issuing a
        BACKUP DATABASE * command.
      * The user cannot read (SELECT) all of the objects in a database
        and read their metadata when issuing a BACKUP DATABASE <list> command.
     @ mysql-test/suite/backup/r/backup_security.result
        Updated result file with additional test cases.
     @ mysql-test/suite/backup/r/backup_security_check.result
         New result file.
     @ mysql-test/suite/backup/t/backup_security.test
        Reorganized test file and added new test cases.
     @ mysql-test/suite/backup/t/backup_security_check.test
        New test to check that backup images contain all objects in the backup
        image or fail. This test can detect if a regression has occurred in 
        the object checking (counting) mechanism introduced in this patch.
     @ sql/backup/backup_info.cc
        Added call to check user access for each database to ensure the
        user has visibility to all objects. 
        Added call to check user access for all databases in the event a
        BACKUP DATABASE * command is issued.
     @ sql/share/errmsg.txt
        New error messages.
     @ sql/si_objects.cc
        Added helper methods to check to see if user has visibility on all objects
        for a given database and has visibility for all databases except 
        mysql and information_schema.
     @ sql/si_objects.h
        Declaration for new methods.
        Clarification in comments.

    added:
      mysql-test/suite/backup/r/backup_security_check.result
      mysql-test/suite/backup/t/backup_security_check.test
    modified:
      mysql-test/suite/backup/r/backup_security.result
      mysql-test/suite/backup/t/backup_security.test
      sql/backup/backup_info.cc
      sql/share/errmsg.txt
      sql/si_objects.cc
      sql/si_objects.h
=== modified file 'mysql-test/suite/backup/r/backup_security.result'
--- a/mysql-test/suite/backup/r/backup_security.result	2009-07-02 13:47:21 +0000
+++ b/mysql-test/suite/backup/r/backup_security.result	2009-07-15 14:18:59 +0000
@@ -1,11 +1,7 @@
 DROP DATABASE IF EXISTS backup_test;
+DROP DATABASE IF EXISTS backup_test_alt;
 #
 # Create database and data to test.
-# Create 3 users and grants rights as follows:
-#   bup_no_rights   - denied everything (poor chap)
-#                     except SELECT ON backup_test_alt.*
-#   bup_with_rights - super user account (like root)
-#   bup_some_rights - rights to a database but no BACKUP or RESTORE
 #
 CREATE DATABASE backup_test;
 CREATE TABLE backup_test.t1 (a char(30)) ENGINE=MEMORY;
@@ -16,6 +12,10 @@ INSERT INTO backup_test.t1 VALUES ("04 T
 INSERT INTO backup_test.t1 VALUES ("05 Test #1 - privilege");
 INSERT INTO backup_test.t1 VALUES ("06 Test #1 - privilege");
 INSERT INTO backup_test.t1 VALUES ("07 Test #1 - privilege");
+CREATE TABLE backup_test.t2 (a char(30)) ENGINE=MEMORY;
+INSERT INTO backup_test.t2 VALUES ("01 Test #2 - privilege");
+INSERT INTO backup_test.t2 VALUES ("02 Test #2 - privilege");
+INSERT INTO backup_test.t2 VALUES ("03 Test #2 - privilege");
 CREATE DATABASE backup_test_alt;
 CREATE TABLE backup_test_alt.t1 (a char(30)) ENGINE=MEMORY;
 INSERT INTO backup_test_alt.t1 VALUES ("01 Test #2 - privilege");
@@ -30,21 +30,108 @@ CREATE FUNCTION backup_test.f1() RETURNS
 CREATE VIEW backup_test.v1 as SELECT * FROM backup_test.t1;
 CREATE EVENT backup_test.e1 ON SCHEDULE EVERY 1 YEAR DO
 DELETE FROM backup_test.t1 WHERE a = "not there";
-CREATE USER 'bup_no_rights'@'localhost';
-CREATE USER 'bup_with_rights'@'localhost';
-CREATE USER 'bup_some_rights'@'localhost';
-REVOKE ALL ON *.* FROM 'bup_no_rights'@'localhost';
-REVOKE ALL ON *.* FROM 'bup_with_rights'@'localhost';
-REVOKE ALL ON *.* FROM 'bup_some_rights'@'localhost';
-GRANT SELECT ON backup_test_alt.* TO 'bup_no_rights'@'localhost';
-GRANT ALL ON *.* TO 'bup_with_rights'@'localhost';
-GRANT GRANT OPTION ON *.* TO 'bup_with_rights'@'localhost';
-GRANT ALL ON backup_test.* TO 'bup_some_rights'@'localhost';
-REVOKE BACKUP, RESTORE ON backup_test.* FROM 'bup_some_rights'@'localhost';
-GRANT SELECT ON mysql.* TO 'bup_with_rights'@'localhost';
+#
+# Create users.
+#
+CREATE USER 'bup_no_priv'@'localhost';
+CREATE USER 'bup_root_user'@'localhost';
+CREATE USER 'bup_no_bup_priv'@'localhost';
+CREATE USER 'bup_some_priv'@'localhost';
+CREATE USER 'bup_select_priv'@'localhost';
+CREATE USER 'bup_full_priv'@'localhost';
+CREATE USER 'bup_other_priv'@'localhost';
+#
+# Grants privileges as follows:
+#   bup_no_priv     - denied everything (poor chap)
+#                     except SELECT ON backup_test_alt.*
+#   bup_root_user   - super user account (like root)
+#   bup_no_bup_priv - privileges to a database but no BACKUP or RESTORE
+#   bup_some_priv   - privileges to some database objects 
+#                     and BACKUP and RESTORE
+#   bup_full_priv   - user gets database-level specific grants
+#   bup_other_priv  - user who has privileges other than select
+#
+#
+# Setup grants for bup_no_priv
+#
+REVOKE ALL ON *.* FROM 'bup_no_priv'@'localhost';
+GRANT SELECT ON backup_test_alt.* TO 'bup_no_priv'@'localhost';
+#
+# Setup grants for bup_root_user
+#
+GRANT ALL ON *.* TO 'bup_root_user'@'localhost';
+GRANT GRANT OPTION ON *.* TO 'bup_root_user'@'localhost';
+#
+# Setup grants for bup_no_bup_priv
+#
+REVOKE ALL ON *.* FROM 'bup_no_bup_priv'@'localhost';
+GRANT ALL ON backup_test.* TO 'bup_no_bup_priv'@'localhost';
+REVOKE BACKUP, RESTORE ON backup_test.* FROM 'bup_no_bup_priv'@'localhost';
+#
+# Setup grants for bup_some_priv
+#
+REVOKE ALL ON *.* FROM 'bup_some_priv'@'localhost';
+GRANT BACKUP, RESTORE ON *.* TO 'bup_some_priv'@'localhost';
+GRANT ALL ON backup_test.t1 TO 'bup_some_priv'@'localhost';
+#
+# Setup grants for bup_select_priv
+#
+REVOKE ALL ON *.* FROM 'bup_select_priv'@'localhost';
+GRANT SELECT ON backup_test.* TO 'bup_select_priv'@'localhost';
+GRANT BACKUP, RESTORE ON backup_test.* TO 'bup_select_priv'@'localhost';
+#
+# Setup grants for bup_full_priv
+# Note: test case is setup so that backup should fail until
+# all privileges for each object is specified.
+#
+REVOKE ALL ON *.* FROM 'bup_full_priv'@'localhost';
+GRANT BACKUP, RESTORE ON backup_test.* TO 'bup_full_priv'@'localhost';
+#
+# Setup grants for bup_other_priv
+# Note: test case is setup so that backup should fail if user has other
+# privileges but not seleect.
+#
+REVOKE ALL ON *.* FROM 'bup_full_priv'@'localhost';
+GRANT BACKUP, RESTORE, CREATE, DROP ON backup_test.* TO 'bup_other_priv'@'localhost';
 FLUSH PRIVILEGES;
+# 
+# Show grants for users.
 #
-# root_user: Do backup of database with root user for later tests.
+SHOW GRANTS FOR 'bup_no_priv'@'localhost';
+Grants for bup_no_priv@localhost
+GRANT USAGE ON *.* TO 'bup_no_priv'@'localhost'
+GRANT SELECT ON `backup_test_alt`.* TO 'bup_no_priv'@'localhost'
+# 
+SHOW GRANTS FOR 'bup_root_user'@'localhost';
+Grants for bup_root_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'bup_root_user'@'localhost' WITH GRANT OPTION
+# 
+SHOW GRANTS FOR 'bup_no_bup_priv'@'localhost';
+Grants for bup_no_bup_priv@localhost
+GRANT USAGE ON *.* TO 'bup_no_bup_priv'@'localhost'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `backup_test`.* TO 'bup_no_bup_priv'@'localhost'
+# 
+SHOW GRANTS FOR 'bup_some_priv'@'localhost';
+Grants for bup_some_priv@localhost
+GRANT BACKUP, RESTORE ON *.* TO 'bup_some_priv'@'localhost'
+GRANT ALL PRIVILEGES ON `backup_test`.`t1` TO 'bup_some_priv'@'localhost'
+# 
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+Grants for bup_select_priv@localhost
+GRANT USAGE ON *.* TO 'bup_select_priv'@'localhost'
+GRANT SELECT, BACKUP, RESTORE ON `backup_test`.* TO 'bup_select_priv'@'localhost'
+# 
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+Grants for bup_full_priv@localhost
+GRANT USAGE ON *.* TO 'bup_full_priv'@'localhost'
+GRANT BACKUP, RESTORE ON `backup_test`.* TO 'bup_full_priv'@'localhost'
+# 
+SHOW GRANTS FOR 'bup_other_priv'@'localhost';
+Grants for bup_other_priv@localhost
+GRANT USAGE ON *.* TO 'bup_other_priv'@'localhost'
+GRANT CREATE, DROP, BACKUP, RESTORE ON `backup_test`.* TO 'bup_other_priv'@'localhost'
+#
+# conn_root_user: Do backup of database with root user for later tests.
 #
 BACKUP DATABASE backup_test to 'backup_test_orig.bak';
 backup_id
@@ -55,6 +142,7 @@ backup_id
 SHOW FULL TABLES FROM backup_test;
 Tables_in_backup_test	Table_type
 t1	BASE TABLE
+t2	BASE TABLE
 v1	VIEW
 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
 event_name
@@ -67,38 +155,288 @@ SELECT trigger_name FROM INFORMATION_SCH
 trigger_name
 trg
 #
-# Connect as user with some rights and attempt backup.
+# Test 1 - Ensure the visibility check works for a basic backup and  
+#          restore for each type of object. Also show that user must 
+#          have additional privileges to succesfully backup a database.
+#
+#
+# Step 1, show that root can query IS tables and get correct counts
+# for all objects in the database.
+#
+Get number of tables and views -- should be 3
+SELECT count(*) = 3 FROM INFORMATION_SCHEMA.TABLES 
+WHERE table_schema = 'backup_test';
+count(*) = 3
+1
+Get number of triggers -- should be 1
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.TRIGGERS 
+WHERE trigger_schema = 'backup_test';
+count(*) = 1
+1
+Get number of procedures and functions -- should be 2
+but will be 0 because user does not have SELECT on
+the mysql tables for routines.
+SELECT count(*) = 2 FROM INFORMATION_SCHEMA.ROUTINES 
+WHERE routine_schema = 'backup_test';
+count(*) = 2
+1
+Get number of events -- should be 1
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.EVENTS 
+WHERE event_schema = 'backup_test';
+count(*) = 1
+1
+#
+# Connect as user with limited privileges.
+#
+#
+# Step 2, show that a user with only SELECT cannot query IS tables
+# and get correct counts for all objects in the database.
+#
+Get number of tables and views -- should be 3
+SELECT count(*) = 3 FROM INFORMATION_SCHEMA.TABLES 
+WHERE table_schema = 'backup_test';
+count(*) = 3
+1
+Get number of triggers -- should be 1 but will be 0
+because user needs TRIGGER privilege.
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.TRIGGERS 
+WHERE trigger_schema = 'backup_test';
+count(*) = 1
+0
+Get number of procedures and functions -- should be 2
+but will be 0 because user doesn't have SELECT on
+the mysql routine tables.
+SELECT count(*) = 2 FROM INFORMATION_SCHEMA.ROUTINES 
+WHERE routine_schema = 'backup_test';
+count(*) = 2
+0
+Get number of events -- should be 1 but will be 0
+because user needs EVENT privilege.
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.EVENTS 
+WHERE event_schema = 'backup_test';
+count(*) = 1
+0
 #
+# conn_select_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
 #
-# some_rights: Attempting backup. Should fail with 
-# error ER_BACKUP_ACCESS_DENIED_ERROR
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
 #
-BACKUP DATABASE backup_test to 'bup_some_rights.bak';
-ERROR HY000: Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test'.
+# Connect as root and add privileges.
+#
+# 
+# Step 3, give user EVENT privilege and retry backup.
+#
+GRANT EVENT ON backup_test.* TO 'bup_select_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+Grants for bup_select_priv@localhost
+GRANT USAGE ON *.* TO 'bup_select_priv'@'localhost'
+GRANT SELECT, EVENT, BACKUP, RESTORE ON `backup_test`.* TO 'bup_select_priv'@'localhost'
+#
+# Connect as user with upgraded privileges and attempt backup.
+#
+Get number of events -- should now be 1
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.EVENTS 
+WHERE event_schema = 'backup_test';
+count(*) = 1
+1
+#
+# conn_select_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+#
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
 SHOW ERRORS;
 Level	Code	Message
-Error	####	Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test'.
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
 #
-# some_rights: Attempting backup. Should fail with 
-# error ER_BACKUP_ACCESS_DENIED_ERROR
+# Connect as root and add privileges.
 #
-BACKUP DATABASE * to 'bup_some_rights.bak';
-ERROR HY000: Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test'.
+# 
+# Step 4, give user TRIGGER privilege and retry backup.
+#
+GRANT TRIGGER ON backup_test.* TO 'bup_select_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+Grants for bup_select_priv@localhost
+GRANT USAGE ON *.* TO 'bup_select_priv'@'localhost'
+GRANT SELECT, EVENT, TRIGGER, BACKUP, RESTORE ON `backup_test`.* TO 'bup_select_priv'@'localhost'
+#
+# Connect as user with upgraded privileges and attempt backup.
+#
+Get number of triggers -- should now be 1
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.TRIGGERS 
+WHERE trigger_schema = 'backup_test';
+count(*) = 1
+1
+#
+# conn_select_priv: Attempting backup. Should fail with 
+# error ER_BAD_DB_ERROR
+#
+BACKUP DATABASE not_there_at_all_ever, backup_test to 'backup_test_select.bak';
+ERROR 42000: Unknown database 'not_there_at_all_ever'
 SHOW ERRORS;
 Level	Code	Message
-Error	####	Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test'.
+Error	#	Unknown database 'not_there_at_all_ever'
 #
-# Connect as user with no rights and attempt backup.
+# conn_select_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
 #
+BACKUP DATABASE backup_test, not_there_at_all_ever to 'backup_test_select.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# conn_select_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
 #
-# no_rights: Attempting backup. Should fail with 
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# Connect as root and add privileges.
+#
+# 
+# Step 5, give user SELECT privilege on the mysql tables
+# and retry backup.
+#
+GRANT SELECT ON mysql.* TO 'bup_select_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+Grants for bup_select_priv@localhost
+GRANT USAGE ON *.* TO 'bup_select_priv'@'localhost'
+GRANT SELECT ON `mysql`.* TO 'bup_select_priv'@'localhost'
+GRANT SELECT, EVENT, TRIGGER, BACKUP, RESTORE ON `backup_test`.* TO 'bup_select_priv'@'localhost'
+#
+# Connect as user with upgraded privileges and attempt backup.
+#
+#
+# conn_select_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_GET_META_VIEW
+#
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+ERROR HY000: Failed to obtain meta-data for view `backup_test`.`v1`
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Failed to obtain meta-data for view `backup_test`.`v1`
+#
+# Connect as root and add privileges.
+#
+#
+# Step 6, Give user SHOW VIEW privilege and retry backup.
+#
+GRANT SHOW VIEW ON backup_test.* TO 'bup_select_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+Grants for bup_select_priv@localhost
+GRANT USAGE ON *.* TO 'bup_select_priv'@'localhost'
+GRANT SELECT ON `mysql`.* TO 'bup_select_priv'@'localhost'
+GRANT SELECT, SHOW VIEW, EVENT, TRIGGER, BACKUP, RESTORE ON `backup_test`.* TO 'bup_select_priv'@'localhost'
+#
+# Connect as user with upgraded privileges and attempt backup.
+#
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+backup_id
+#
+# Backup now succeeds.
+#
+# conn_select_priv: Attempting backup. Should fail with 
 # error ER_BAD_DB_ERROR
 #
-BACKUP DATABASE backup_test to 'bup_no_rights.bak';
-ERROR 42000: Unknown database 'backup_test'
+BACKUP DATABASE not_there_at_all_ever to 'backup_test_select1.bak';
+ERROR 42000: Unknown database 'not_there_at_all_ever'
 SHOW ERRORS;
 Level	Code	Message
-Error	####	Unknown database 'backup_test'
+Error	#	Unknown database 'not_there_at_all_ever'
+#
+# Connect as root and do the restore to ensure everything got 
+# restored.
+#
+#
+# Step 7, show that the backup image contains all of the objects
+# and compare that to the original backup made by root.
+#
+RESTORE FROM 'backup_test_select.bak' OVERWRITE;
+backup_id
+#
+#
+# Show list of all objects in the database.
+#
+SHOW FULL TABLES FROM backup_test;
+Tables_in_backup_test	Table_type
+t1	BASE TABLE
+t2	BASE TABLE
+v1	VIEW
+SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
+event_name
+e1
+SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
+routine_name
+f1
+p1
+SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
+trigger_name
+trg
+#
+# Compare to original backup image file.
+#
+RESTORE FROM 'backup_test_orig.bak' OVERWRITE;
+backup_id
+#
+#
+# Show list of all objects in the database.
+#
+SHOW FULL TABLES FROM backup_test;
+Tables_in_backup_test	Table_type
+t1	BASE TABLE
+t2	BASE TABLE
+v1	VIEW
+SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
+event_name
+e1
+SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
+routine_name
+f1
+p1
+SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
+trigger_name
+trg
+#
+# Test 2 - Only users with BACKUP and RESTORE privilege can run backup
+#          and restore.
+#
+#
+# Connect as user with no privileges and attempt backup.
+#
+#
+# conn_no_priv: Attempting restore. Should fail with
+# error ER_RESTORE_ACCESS_DENIED_ERROR
+#
+RESTORE FROM 'backup_test_orig.bak';
+ERROR HY000: Insufficient privileges. You must have the RESTORE privilege to restore database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You must have the RESTORE privilege to restore database 'backup_test'.
 #
 # Show user has not gained rights.
 #
@@ -106,89 +444,89 @@ Error	####	Unknown database 'backup_test
 # Checking privileges for a table.
 #
 SELECT * FROM backup_test.t1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 't1'
 INSERT INTO backup_test.t1 VALUES ("900");
-ERROR 42000: INSERT command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: INSERT command denied to user 'bup_no_priv'@'localhost' for table 't1'
 UPDATE backup_test.t1 SET a = "gotcha!";
-ERROR 42000: UPDATE command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: UPDATE command denied to user 'bup_no_priv'@'localhost' for table 't1'
 DELETE FROM backup_test.t1;
-ERROR 42000: DELETE command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: DELETE command denied to user 'bup_no_priv'@'localhost' for table 't1'
 TRUNCATE TABLE backup_test.t1;
-ERROR 42000: DROP command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: DROP command denied to user 'bup_no_priv'@'localhost' for table 't1'
 ALTER TABLE backup_test.t1 ENGINE=MEMORY;
-ERROR 42000: ALTER command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: ALTER command denied to user 'bup_no_priv'@'localhost' for table 't1'
 DROP TABLE backup_test.t1;
-ERROR 42000: DROP command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: DROP command denied to user 'bup_no_priv'@'localhost' for table 't1'
 CREATE TABLE backup_test.t2 (a int);
-ERROR 42000: CREATE command denied to user 'bup_no_rights'@'localhost' for table 't2'
+ERROR 42000: CREATE command denied to user 'bup_no_priv'@'localhost' for table 't2'
 DESCRIBE backup_test.t1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 't1'
 SHOW CREATE TABLE backup_test.t1;
-ERROR 42000: SHOW command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: SHOW command denied to user 'bup_no_priv'@'localhost' for table 't1'
 #
 # Checking privileges for a view.
 #
 SELECT * FROM backup_test.v1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 INSERT INTO backup_test.v1 VALUES ("800");
-ERROR 42000: INSERT command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: INSERT command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 UPDATE backup_test.v1 SET a = "gotcha again!";
-ERROR 42000: UPDATE command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: UPDATE command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 DELETE FROM backup_test.v1;
-ERROR 42000: DELETE command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: DELETE command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 TRUNCATE TABLE backup_test.v1;
-ERROR 42000: DROP command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: DROP command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 ALTER VIEW backup_test.v1 AS SELECT 1;
-ERROR 42000: CREATE VIEW command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: CREATE VIEW command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 DROP VIEW backup_test.v1;
-ERROR 42000: DROP command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: DROP command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 CREATE VIEW backup_test.v2 AS SELECT 0;
-ERROR 42000: CREATE VIEW command denied to user 'bup_no_rights'@'localhost' for table 'v2'
+ERROR 42000: CREATE VIEW command denied to user 'bup_no_priv'@'localhost' for table 'v2'
 DESCRIBE backup_test.v1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 SHOW CREATE VIEW backup_test.v1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 #
 # Checking privileges for a trigger.
 #
 DROP TRIGGER backup_test.trg;
-ERROR 42000: TRIGGER command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: TRIGGER command denied to user 'bup_no_priv'@'localhost' for table 't1'
 CREATE TRIGGER backup_test.trg2 BEFORE INSERT ON backup_test.t1 FOR EACH ROW
 INSERT INTO backup_test.t1 VALUES('not there at all');
-ERROR 42000: TRIGGER command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: TRIGGER command denied to user 'bup_no_priv'@'localhost' for table 't1'
 #
 # Checking privileges for an event.
 #
 DROP EVENT backup_test.e1;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 ALTER EVENT backup_test.e1 ENABLE;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 CREATE EVENT backup_test.e2 ON SCHEDULE EVERY 1 YEAR DO
 DELETE FROM backup_test.t1;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 SHOW CREATE EVENT backup_test.e1;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 #
 # Checking privileges for a function.
 #
 DROP FUNCTION backup_test.f1;
-ERROR 42000: alter routine command denied to user 'bup_no_rights'@'localhost' for routine 'backup_test.f1'
+ERROR 42000: alter routine command denied to user 'bup_no_priv'@'localhost' for routine 'backup_test.f1'
 ALTER FUNCTION backup_test.f1 COMMENT "Tricky, eh?";
-ERROR 42000: alter routine command denied to user 'bup_no_rights'@'localhost' for routine 'backup_test.f1'
+ERROR 42000: alter routine command denied to user 'bup_no_priv'@'localhost' for routine 'backup_test.f1'
 CREATE FUNCTION backup_test.f2() RETURNS INT RETURN (SELECT 11);
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 SHOW CREATE FUNCTION backup_test.f1;
 ERROR 42000: FUNCTION f1 does not exist
 #
 # Checking privileges for a procedure.
 #
 DROP PROCEDURE backup_test.p1;
-ERROR 42000: alter routine command denied to user 'bup_no_rights'@'localhost' for routine 'backup_test.p1'
+ERROR 42000: alter routine command denied to user 'bup_no_priv'@'localhost' for routine 'backup_test.p1'
 ALTER PROCEDURE backup_test.p1 COMMENT "Tricky, eh?";
-ERROR 42000: alter routine command denied to user 'bup_no_rights'@'localhost' for routine 'backup_test.p1'
+ERROR 42000: alter routine command denied to user 'bup_no_priv'@'localhost' for routine 'backup_test.p1'
 CREATE PROCEDURE backup_test.p1(p1 CHAR(20))
 INSERT INTO backup_test.t1 VALUES ("100");
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 SHOW CREATE PROCEDURE backup_test.p1;
 ERROR 42000: PROCEDURE p1 does not exist
 #
@@ -196,38 +534,20 @@ ERROR 42000: PROCEDURE p1 does not exist
 # existing database.
 #
 DROP DATABASE backup_test;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 CREATE DATABASE x1;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'x1'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'x1'
 ALTER DATABASE backup_test UPGRADE DATA DIRECTORY NAME;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
-#
-# no_rights: Attempting backup. Should fail with 
-# error ER_BACKUP_ACCESS_DENIED_ERROR
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 #
-BACKUP DATABASE backup_test_alt to 'bup_no_rights.bak';
-ERROR HY000: Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test_alt'.
-SHOW ERRORS;
-Level	Code	Message
-Error	####	Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test_alt'.
-#
-# no_rights: Attempting backup. Should fail with 
+# conn_no_priv: Attempting backup. Should fail with 
 # error ER_BACKUP_ACCESS_DENIED_ERROR
 #
-BACKUP DATABASE * to 'bup_no_rights.bak';
+BACKUP DATABASE backup_test_alt to 'bup_no_priv.bak';
 ERROR HY000: Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test_alt'.
 SHOW ERRORS;
 Level	Code	Message
-Error	####	Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test_alt'.
-#
-# no_rights: Attempting restore. Should fail with
-# error ER_RESTORE_ACCESS_DENIED_ERROR
-#
-RESTORE FROM 'backup_test_orig.bak';
-ERROR HY000: Insufficient privileges. You must have the RESTORE privilege to restore database 'backup_test'.
-SHOW ERRORS;
-Level	Code	Message
-Error	####	Insufficient privileges. You must have the RESTORE privilege to restore database 'backup_test'.
+Error	#	Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test_alt'.
 #
 # Show user has not gained rights.
 #
@@ -235,89 +555,89 @@ Error	####	Insufficient privileges. You 
 # Checking privileges for a table.
 #
 SELECT * FROM backup_test.t1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 't1'
 INSERT INTO backup_test.t1 VALUES ("900");
-ERROR 42000: INSERT command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: INSERT command denied to user 'bup_no_priv'@'localhost' for table 't1'
 UPDATE backup_test.t1 SET a = "gotcha!";
-ERROR 42000: UPDATE command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: UPDATE command denied to user 'bup_no_priv'@'localhost' for table 't1'
 DELETE FROM backup_test.t1;
-ERROR 42000: DELETE command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: DELETE command denied to user 'bup_no_priv'@'localhost' for table 't1'
 TRUNCATE TABLE backup_test.t1;
-ERROR 42000: DROP command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: DROP command denied to user 'bup_no_priv'@'localhost' for table 't1'
 ALTER TABLE backup_test.t1 ENGINE=MEMORY;
-ERROR 42000: ALTER command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: ALTER command denied to user 'bup_no_priv'@'localhost' for table 't1'
 DROP TABLE backup_test.t1;
-ERROR 42000: DROP command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: DROP command denied to user 'bup_no_priv'@'localhost' for table 't1'
 CREATE TABLE backup_test.t2 (a int);
-ERROR 42000: CREATE command denied to user 'bup_no_rights'@'localhost' for table 't2'
+ERROR 42000: CREATE command denied to user 'bup_no_priv'@'localhost' for table 't2'
 DESCRIBE backup_test.t1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 't1'
 SHOW CREATE TABLE backup_test.t1;
-ERROR 42000: SHOW command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: SHOW command denied to user 'bup_no_priv'@'localhost' for table 't1'
 #
 # Checking privileges for a view.
 #
 SELECT * FROM backup_test.v1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 INSERT INTO backup_test.v1 VALUES ("800");
-ERROR 42000: INSERT command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: INSERT command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 UPDATE backup_test.v1 SET a = "gotcha again!";
-ERROR 42000: UPDATE command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: UPDATE command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 DELETE FROM backup_test.v1;
-ERROR 42000: DELETE command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: DELETE command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 TRUNCATE TABLE backup_test.v1;
-ERROR 42000: DROP command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: DROP command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 ALTER VIEW backup_test.v1 AS SELECT 1;
-ERROR 42000: CREATE VIEW command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: CREATE VIEW command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 DROP VIEW backup_test.v1;
-ERROR 42000: DROP command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: DROP command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 CREATE VIEW backup_test.v2 AS SELECT 0;
-ERROR 42000: CREATE VIEW command denied to user 'bup_no_rights'@'localhost' for table 'v2'
+ERROR 42000: CREATE VIEW command denied to user 'bup_no_priv'@'localhost' for table 'v2'
 DESCRIBE backup_test.v1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 SHOW CREATE VIEW backup_test.v1;
-ERROR 42000: SELECT command denied to user 'bup_no_rights'@'localhost' for table 'v1'
+ERROR 42000: SELECT command denied to user 'bup_no_priv'@'localhost' for table 'v1'
 #
 # Checking privileges for a trigger.
 #
 DROP TRIGGER backup_test.trg;
-ERROR 42000: TRIGGER command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: TRIGGER command denied to user 'bup_no_priv'@'localhost' for table 't1'
 CREATE TRIGGER backup_test.trg2 BEFORE INSERT ON backup_test.t1 FOR EACH ROW
 INSERT INTO backup_test.t1 VALUES('not there at all');
-ERROR 42000: TRIGGER command denied to user 'bup_no_rights'@'localhost' for table 't1'
+ERROR 42000: TRIGGER command denied to user 'bup_no_priv'@'localhost' for table 't1'
 #
 # Checking privileges for an event.
 #
 DROP EVENT backup_test.e1;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 ALTER EVENT backup_test.e1 ENABLE;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 CREATE EVENT backup_test.e2 ON SCHEDULE EVERY 1 YEAR DO
 DELETE FROM backup_test.t1;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 SHOW CREATE EVENT backup_test.e1;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 #
 # Checking privileges for a function.
 #
 DROP FUNCTION backup_test.f1;
-ERROR 42000: alter routine command denied to user 'bup_no_rights'@'localhost' for routine 'backup_test.f1'
+ERROR 42000: alter routine command denied to user 'bup_no_priv'@'localhost' for routine 'backup_test.f1'
 ALTER FUNCTION backup_test.f1 COMMENT "Tricky, eh?";
-ERROR 42000: alter routine command denied to user 'bup_no_rights'@'localhost' for routine 'backup_test.f1'
+ERROR 42000: alter routine command denied to user 'bup_no_priv'@'localhost' for routine 'backup_test.f1'
 CREATE FUNCTION backup_test.f2() RETURNS INT RETURN (SELECT 11);
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 SHOW CREATE FUNCTION backup_test.f1;
 ERROR 42000: FUNCTION f1 does not exist
 #
 # Checking privileges for a procedure.
 #
 DROP PROCEDURE backup_test.p1;
-ERROR 42000: alter routine command denied to user 'bup_no_rights'@'localhost' for routine 'backup_test.p1'
+ERROR 42000: alter routine command denied to user 'bup_no_priv'@'localhost' for routine 'backup_test.p1'
 ALTER PROCEDURE backup_test.p1 COMMENT "Tricky, eh?";
-ERROR 42000: alter routine command denied to user 'bup_no_rights'@'localhost' for routine 'backup_test.p1'
+ERROR 42000: alter routine command denied to user 'bup_no_priv'@'localhost' for routine 'backup_test.p1'
 CREATE PROCEDURE backup_test.p1(p1 CHAR(20))
 INSERT INTO backup_test.t1 VALUES ("100");
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 SHOW CREATE PROCEDURE backup_test.p1;
 ERROR 42000: PROCEDURE p1 does not exist
 #
@@ -325,41 +645,245 @@ ERROR 42000: PROCEDURE p1 does not exist
 # existing database.
 #
 DROP DATABASE backup_test;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 CREATE DATABASE x1;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'x1'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'x1'
 ALTER DATABASE backup_test UPGRADE DATA DIRECTORY NAME;
-ERROR 42000: Access denied for user 'bup_no_rights'@'localhost' to database 'backup_test'
+ERROR 42000: Access denied for user 'bup_no_priv'@'localhost' to database 'backup_test'
 #
-# Connect as user with rights and attempt backup and restore.
+# Connect as user with privileges and attempt backup and restore.
 #
 #
-# with_rights: Attempting backup. Should succeed
+# conn_root_user: Attempting backup. Should succeed
 #
-BACKUP DATABASE backup_test to 'bup_with_rights.bak';
+BACKUP DATABASE backup_test to 'bup_root_user.bak';
 backup_id
 #
 #
-# with_rights: Attempting backup. Should not fail.
+# conn_root_user: Attempting restore. Should succeed
 #
-BACKUP DATABASE * to 'bup_with_rights_star.bak';
+RESTORE FROM 'bup_root_user.bak' OVERWRITE;
 backup_id
 #
 #
-# with_rights: Attempting restore. Should succeed
+# Show that all objects were recreated after restore.
 #
-RESTORE FROM 'bup_with_rights.bak' OVERWRITE;
-backup_id
+SHOW FULL TABLES FROM backup_test;
+Tables_in_backup_test	Table_type
+t1	BASE TABLE
+t2	BASE TABLE
+v1	VIEW
+SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
+event_name
+e1
+SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
+routine_name
+f1
+p1
+SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
+trigger_name
+trg
+#
+# Connect as user with no backup privileges and attempt backup.
+#
+#
+# conn_no_bup_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_DENIED_ERROR
+#
+BACKUP DATABASE backup_test to 'bup_no_bup_priv.bak';
+ERROR HY000: Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You must have the BACKUP privilege to backup database 'backup_test'.
+#
+# conn_no_bup_priv: Attempting restore. Should fail with 
+# error ER_RESTORE_ACCESS_DENIED_ERROR
+#
+RESTORE FROM 'backup_test_orig.bak';
+ERROR HY000: Insufficient privileges. You must have the RESTORE privilege to restore database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You must have the RESTORE privilege to restore database 'backup_test'.
+#
+# Test 3 - Users must have the ability to read (SELECT) all databases
+#          as well as have BACKUP on *.* to execute 
+#          BACKUP DATABASE * TO <file>.
 #
 #
 # Do restore to ensure it still works with root user.
 #
 #
+# conn_no_priv: Attempting backup *. Should fail with 
+# error ER_BACKUP_ACCESS_DBS_INCOMPLETE
+#
+BACKUP DATABASE * to 'bup_no_priv.bak';
+ERROR HY000: Insufficient privileges. You must have the SELECT privilege on all databases to execute BACKUP DATABASE *.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You must have the SELECT privilege on all databases to execute BACKUP DATABASE *.
+#
+# Connect as user with privileges and attempt backup and restore.
+#
+#
+# conn_root_user: Attempting backup. Should not fail.
+#
+BACKUP DATABASE * to 'bup_root_user_star.bak';
+backup_id
+#
+#
+# Connect as user with no backup privileges and attempt backup.
+#
+#
+# conn_no_bup_priv: Attempting backup *. Should fail with 
+# error ER_BACKUP_ACCESS_DBS_INCOMPLETE
+#
+BACKUP DATABASE * to 'bup_no_bup_priv.bak';
+ERROR HY000: Insufficient privileges. You must have the SELECT privilege on all databases to execute BACKUP DATABASE *.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You must have the SELECT privilege on all databases to execute BACKUP DATABASE *.
+#
+# Connect as root and redo privileges for user with only select.
+#
+DROP DATABASE backup_test_alt;
+REVOKE ALL ON *.* FROM 'bup_select_priv'@'localhost';
+REVOKE ALL ON backup_test.* FROM 'bup_select_priv'@'localhost';
+GRANT SELECT, TRIGGER, EVENT, SHOW VIEW ON *.* TO 'bup_select_priv'@'localhost';
+GRANT BACKUP, RESTORE ON *.* TO 'bup_select_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+Grants for bup_select_priv@localhost
+GRANT SELECT, SHOW VIEW, EVENT, TRIGGER, BACKUP, RESTORE ON *.* TO 'bup_select_priv'@'localhost'
+GRANT SELECT ON `mysql`.* TO 'bup_select_priv'@'localhost'
+#
+# Connect as user with upgraded privileges and attempt backup.
+#
+#
+# conn_select_priv: Attempting backup *. Should succeed.
+#
+BACKUP DATABASE * to 'bup_select_priv.bak';
+backup_id
+#
+#
+# Test 4 - Users must have the ability to read (SELECT) all objects in 
+#          a databsase as well as have BACKUP to execute 
+#          BACKUP DATABASE backup_test TO <file>.
+#
+#
+# Connect as user with no privileges and attempt backup.
+#
+#
+# conn_no_priv: Attempting backup. Should fail with 
+# error ER_BAD_DB_ERROR
+#
+BACKUP DATABASE backup_test to 'bup_no_priv.bak';
+ERROR 42000: Unknown database 'backup_test'
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Unknown database 'backup_test'
+#
+# Connect as user with privileges other than select and attempt backup.
+#
+#
+# conn_other_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+#
+BACKUP DATABASE backup_test to 'bup_other_priv.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# Reconnect as root and change privileges for user.
+#
+#
+# Connect as user with privileges and attempt backup and restore.
+#
+REVOKE ALL ON backup_test.* FROM 'bup_other_priv'@'localhost';
+GRANT SELECT ON mysql.* TO 'bup_other_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_other_priv'@'localhost';
+Grants for bup_other_priv@localhost
+GRANT USAGE ON *.* TO 'bup_other_priv'@'localhost'
+GRANT SELECT ON `mysql`.* TO 'bup_other_priv'@'localhost'
+#
+# Connect as user with SELECT on mysql.* and attempt backup.
+#
+#
+# conn_other_priv: Attempting backup. Should fail with 
+# error ER_BAD_DB_ERROR
+#
+BACKUP DATABASE backup_test to 'bup_other_priv.bak';
+ERROR 42000: Unknown database 'backup_test'
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Unknown database 'backup_test'
+#
+# Reconnect as root and change privileges for user.
+#
+#
+# Connect as user with privileges and attempt backup and restore.
+#
+GRANT BACKUP ON backup_test.* TO 'bup_other_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_other_priv'@'localhost';
+Grants for bup_other_priv@localhost
+GRANT USAGE ON *.* TO 'bup_other_priv'@'localhost'
+GRANT SELECT ON `mysql`.* TO 'bup_other_priv'@'localhost'
+GRANT BACKUP ON `backup_test`.* TO 'bup_other_priv'@'localhost'
+#
+# Connect as user with SELECT on mysql.* and attempt backup.
+#
+#
+# conn_other_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+#
+BACKUP DATABASE backup_test to 'bup_other_priv.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# Test 5 - Users with partial access (SELECT on some objects) cannot
+#          backup the database without errors.
+#
+#
+# Connect as user with some privileges and attempt backup.
+#
+#
+# conn_some_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+#
+BACKUP DATABASE backup_test to 'bup_some_priv.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# Reconnect as root to ensure we can restore correctly.
+#
+#
+# Connect as user with privileges and attempt backup and restore.
+#
+RESTORE FROM 'backup_test_orig.bak' OVERWRITE;
+backup_id
+#
+#
 # Show that all objects were recreated after restore.
 #
 SHOW FULL TABLES FROM backup_test;
 Tables_in_backup_test	Table_type
 t1	BASE TABLE
+t2	BASE TABLE
 v1	VIEW
 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
 event_name
@@ -371,15 +895,208 @@ p1
 SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
 trigger_name
 trg
+#
+# Test 6 -  Users with individual privileges and no database-level except 
+#           EVENT can successfully backup the database. 
+#           In this test case, we add one privilege at a time until
+#           there is a complete set of database-level privileges 
+#           and the backup command succeeds.
+#
+#
+# Connect as user with explicit privileges on specific database objects
+# and attempt backup.
+#
+#
+# conn_conn_full_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+#
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# Connect as root and add another privilege.
+#
+#
+# Add another database-level grant statement.
+#
+GRANT SELECT, TRIGGER ON backup_test.t2 TO 'bup_full_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+Grants for bup_full_priv@localhost
+GRANT USAGE ON *.* TO 'bup_full_priv'@'localhost'
+GRANT BACKUP, RESTORE ON `backup_test`.* TO 'bup_full_priv'@'localhost'
+GRANT SELECT, TRIGGER ON `backup_test`.`t2` TO 'bup_full_priv'@'localhost'
+#
+# Connect as user with explicit on database objects and attempt backup.
+#
+#
+# conn_conn_full_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+#
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# Connect as root and add another privilege.
+#
+#
+# Add another database-level grant statement.
+#
+GRANT SELECT, TRIGGER ON backup_test.t1 TO 'bup_full_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+Grants for bup_full_priv@localhost
+GRANT USAGE ON *.* TO 'bup_full_priv'@'localhost'
+GRANT BACKUP, RESTORE ON `backup_test`.* TO 'bup_full_priv'@'localhost'
+GRANT SELECT, TRIGGER ON `backup_test`.`t2` TO 'bup_full_priv'@'localhost'
+GRANT SELECT, TRIGGER ON `backup_test`.`t1` TO 'bup_full_priv'@'localhost'
+#
+# Connect as user with explicit on database objects and attempt backup.
+#
+#
+# conn_conn_full_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+#
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# Connect as root and add another privilege.
+#
+#
+# Add another database-level grant statement.
+#
+GRANT SELECT, SHOW VIEW ON backup_test.v1 TO 'bup_full_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+Grants for bup_full_priv@localhost
+GRANT USAGE ON *.* TO 'bup_full_priv'@'localhost'
+GRANT BACKUP, RESTORE ON `backup_test`.* TO 'bup_full_priv'@'localhost'
+GRANT SELECT, TRIGGER ON `backup_test`.`t2` TO 'bup_full_priv'@'localhost'
+GRANT SELECT, TRIGGER ON `backup_test`.`t1` TO 'bup_full_priv'@'localhost'
+GRANT SELECT, SHOW VIEW ON `backup_test`.`v1` TO 'bup_full_priv'@'localhost'
+#
+# Connect as user with explicit on database objects and attempt backup.
+#
+#
+# conn_conn_full_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+#
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# Connect as root and add another privilege.
+#
+#
+# Add another database-level grant statement.
+#
+GRANT EVENT ON backup_test.* TO 'bup_full_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+Grants for bup_full_priv@localhost
+GRANT USAGE ON *.* TO 'bup_full_priv'@'localhost'
+GRANT EVENT, BACKUP, RESTORE ON `backup_test`.* TO 'bup_full_priv'@'localhost'
+GRANT SELECT, TRIGGER ON `backup_test`.`t2` TO 'bup_full_priv'@'localhost'
+GRANT SELECT, TRIGGER ON `backup_test`.`t1` TO 'bup_full_priv'@'localhost'
+GRANT SELECT, SHOW VIEW ON `backup_test`.`v1` TO 'bup_full_priv'@'localhost'
+#
+# Connect as user with explicit on database objects and attempt backup.
+#
+#
+# conn_conn_full_priv: Attempting backup. Should fail with 
+# error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+#
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'backup_test'.
+#
+# Connect as root and add another privilege.
+#
+#
+# Add another database-level grant statement.
+#
+GRANT SELECT ON mysql.* TO 'bup_full_priv'@'localhost';
+FLUSH PRIVILEGES;
+# 
+# Show updated privileges.
+#
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+Grants for bup_full_priv@localhost
+GRANT USAGE ON *.* TO 'bup_full_priv'@'localhost'
+GRANT SELECT ON `mysql`.* TO 'bup_full_priv'@'localhost'
+GRANT EVENT, BACKUP, RESTORE ON `backup_test`.* TO 'bup_full_priv'@'localhost'
+GRANT SELECT, TRIGGER ON `backup_test`.`t2` TO 'bup_full_priv'@'localhost'
+GRANT SELECT, TRIGGER ON `backup_test`.`t1` TO 'bup_full_priv'@'localhost'
+GRANT SELECT, SHOW VIEW ON `backup_test`.`v1` TO 'bup_full_priv'@'localhost'
+#
+# Connect as user with explicit on database objects and attempt backup.
+#
+#
+# conn_conn_full_priv: Attempting backup. Should succeed.
+#
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+backup_id
+#
+#
+# Connect as root and check restore then cleanup.
+#
+RESTORE FROM 'backup_test_full.bak' OVERWRITE;
+backup_id
+#
+#
+# Show list of all objects in the database.
+#
+SHOW FULL TABLES FROM backup_test;
+Tables_in_backup_test	Table_type
+t1	BASE TABLE
+t2	BASE TABLE
+v1	VIEW
+SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
+event_name
+e1
+SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
+routine_name
+f1
+p1
+SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
+trigger_name
+trg
+#
+# Compare to original backup image file.
+#
 RESTORE FROM 'backup_test_orig.bak' OVERWRITE;
 backup_id
 #
 #
-# Show that all objects were recreated after restore.
+# Show list of all objects in the database.
 #
 SHOW FULL TABLES FROM backup_test;
 Tables_in_backup_test	Table_type
 t1	BASE TABLE
+t2	BASE TABLE
 v1	VIEW
 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
 event_name
@@ -394,9 +1111,12 @@ trg
 #
 # Cleanup
 #
-DROP USER 'bup_no_rights'@'localhost';
-DROP USER 'bup_with_rights'@'localhost';
-DROP USER 'bup_some_rights'@'localhost';
+DROP USER 'bup_no_priv'@'localhost';
+DROP USER 'bup_root_user'@'localhost';
+DROP USER 'bup_no_bup_priv'@'localhost';
+DROP USER 'bup_some_priv'@'localhost';
+DROP USER 'bup_select_priv'@'localhost';
+DROP USER 'bup_full_priv'@'localhost';
+DROP USER 'bup_other_priv'@'localhost';
 DROP DATABASE backup_test;
-DROP DATABASE backup_test_alt;
 FLUSH PRIVILEGES;

=== added file 'mysql-test/suite/backup/r/backup_security_check.result'
--- a/mysql-test/suite/backup/r/backup_security_check.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_security_check.result	2009-07-15 14:18:59 +0000
@@ -0,0 +1,559 @@
+DROP DATABASE IF EXISTS bup_sec_db1;
+DROP DATABASE IF EXISTS bup_sec_db2;
+#
+# Create some data to test. Includes one of each type of object
+# and two databases.
+#
+CREATE DATABASE bup_sec_db1;
+CREATE TABLE bup_sec_db1.t1 (a char(30)) ENGINE=MEMORY;
+CREATE TABLE bup_sec_db1.t2 (a char(30)) ENGINE=MEMORY;
+CREATE VIEW bup_sec_db1.v1 as SELECT * FROM bup_sec_db1.t1;
+CREATE TRIGGER bup_sec_db1.t1_ai AFTER INSERT ON bup_sec_db1.t1 FOR EACH ROW
+INSERT INTO bup_sec_db1.t1 VALUES('Test objects count');
+CREATE PROCEDURE bup_sec_db1.p1(p1 CHAR(20))
+INSERT INTO bup_sec_db1.t1 VALUES ("50");
+CREATE FUNCTION bup_sec_db1.f1() RETURNS INT RETURN (SELECT 1);
+CREATE EVENT bup_sec_db1.e1 ON SCHEDULE EVERY 1 YEAR DO
+DELETE FROM bup_sec_db1.t1 WHERE a = "not there";
+CREATE DATABASE bup_sec_db2;
+CREATE TABLE bup_sec_db2.t1 (a char(30)) ENGINE=MEMORY;
+CREATE TRIGGER bup_sec_db2.t1_ai AFTER INSERT ON bup_sec_db2.t1 FOR EACH ROW
+INSERT INTO bup_sec_db2.t1 VALUES('Test objects count');
+#
+# Attempt backup as root to capture backup image with all objects.
+#
+BACKUP DATABASE * to 'bup_sec.bak';
+backup_id
+#
+#
+# Dump the backup image to show the metadata using mysqlbackup.
+# 
+# exec $MYSQL_BACKUP
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Server byte order: #
+Server charset:      'utf8'
+
+Catalog details:
+
+  Database  'bup_sec_db1'
+    Table     'bup_sec_db1'.'t1'
+    Table     'bup_sec_db1'.'t2'
+    Sproc     'bup_sec_db1'.'p1'
+    Sfunc     'bup_sec_db1'.'f1'
+    View      'bup_sec_db1'.'v1'
+    Event     'bup_sec_db1'.'e1'
+    Trigger   'bup_sec_db1'.'t1_ai'
+  Database  'bup_sec_db2'
+    Table     'bup_sec_db2'.'t1'
+    Trigger   'bup_sec_db2'.'t1_ai'
+  Database  'mtr'
+    Table     'mtr'.'global_suppressions'
+    Table     'mtr'.'test_suppressions'
+    Sproc     'mtr'.'add_suppression'
+    Sproc     'mtr'.'check_testcase'
+    Sproc     'mtr'.'check_warnings'
+    Sproc     'mtr'.'force_restart'
+    Trigger   'mtr'.'gs_insert'
+    Trigger   'mtr'.'ts_insert'
+  Database  'test'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+    Privilege 'test'.'<empty>'
+
+#
+# Test 1 - Minimum set of privileges for "empty" backup of list
+#
+#
+# Create a new user named bup_sec_user1 and grant the user
+# a minimum set of privileges needed to run a complete or full backup
+# using the BACKUP DATABASE <list> command on an empty list.
+#
+CREATE USER 'bup_sec_user1'@'localhost';
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+#
+# Show grants for user.
+#
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+Grants for bup_sec_user1@localhost
+GRANT USAGE ON *.* TO 'bup_sec_user1'@'localhost'
+GRANT BACKUP ON `bup_sec_db1`.* TO 'bup_sec_user1'@'localhost'
+GRANT BACKUP ON `bup_sec_db2`.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT ON `mysql`.`procs_priv` TO 'bup_sec_user1'@'localhost'
+#
+# Connect as user bup_sec_user1 and attempt backup.
+# Expected result: Pass for non-patched code, ERROR for patched code.
+#
+# connection con_user1
+BACKUP DATABASE bup_sec_db1, bup_sec_db2 to 'bup_sec.bak';
+ERROR HY000: Insufficient privileges. You do not have privileges to backup database 'bup_sec_db1'.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You do not have privileges to backup database 'bup_sec_db1'.
+#
+# Drop the user.
+#
+# connection default
+DROP USER 'bup_sec_user1'@'localhost';
+#
+# Test 2 - Minimum set of specific privileges for "full" backup of list
+#
+#
+# Create a new user named bup_sec_user1 and grant the user
+# a minimum set of the object-specific privileges needed to run a 
+# complete or full backup using the BACKUP DATABASE <list> command.
+#
+CREATE USER 'bup_sec_user1'@'localhost';
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.t1 TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.t2 TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.v1 TO 'bup_sec_user1'@'localhost';
+GRANT SHOW VIEW ON bup_sec_db1.v1 TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON PROCEDURE bup_sec_db1.p1 TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON FUNCTION bup_sec_db1.f1 TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db1.t1 TO 'bup_sec_user1'@'localhost';
+GRANT EVENT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db2.t1 TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db2.t1 TO 'bup_sec_user1'@'localhost';
+#
+# Show grants for user.
+#
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+Grants for bup_sec_user1@localhost
+GRANT USAGE ON *.* TO 'bup_sec_user1'@'localhost'
+GRANT EVENT, BACKUP ON `bup_sec_db1`.* TO 'bup_sec_user1'@'localhost'
+GRANT BACKUP ON `bup_sec_db2`.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT ON `bup_sec_db1`.`t2` TO 'bup_sec_user1'@'localhost'
+GRANT SELECT ON `mysql`.`procs_priv` TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, TRIGGER ON `bup_sec_db2`.`t1` TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, TRIGGER ON `bup_sec_db1`.`t1` TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, SHOW VIEW ON `bup_sec_db1`.`v1` TO 'bup_sec_user1'@'localhost'
+GRANT EXECUTE ON PROCEDURE `bup_sec_db1`.`p1` TO 'bup_sec_user1'@'localhost'
+GRANT EXECUTE ON FUNCTION `bup_sec_db1`.`f1` TO 'bup_sec_user1'@'localhost'
+#
+# Connect as user bup_sec_user1 and attempt backup.
+# Expected result: success.
+#
+# connection con_user1
+BACKUP DATABASE bup_sec_db1, bup_sec_db2 to 'bup_sec.bak';
+backup_id
+#
+#
+# Run mysqlbackup to dump the image and show all objects included.
+#
+# exec $MYSQL_BACKUP
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Server byte order: #
+Server charset:      'utf8'
+
+Catalog details:
+
+  Database  'bup_sec_db1'
+    Table     'bup_sec_db1'.'t1'
+    Table     'bup_sec_db1'.'t2'
+    Sproc     'bup_sec_db1'.'p1'
+    Sfunc     'bup_sec_db1'.'f1'
+    View      'bup_sec_db1'.'v1'
+    Event     'bup_sec_db1'.'e1'
+    Trigger   'bup_sec_db1'.'t1_ai'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+  Database  'bup_sec_db2'
+    Table     'bup_sec_db2'.'t1'
+    Trigger   'bup_sec_db2'.'t1_ai'
+    Privilege 'bup_sec_db2'.'<empty>'
+    Privilege 'bup_sec_db2'.'<empty>'
+    Privilege 'bup_sec_db2'.'<empty>'
+
+#
+# Revoke all privileges and drop the user.
+#
+# connection default
+# Explicit revoke due to Bug#36544
+REVOKE EXECUTE ON FUNCTION bup_sec_db1.f1 FROM 'bup_sec_user1'@'localhost';
+DROP USER 'bup_sec_user1'@'localhost';
+#
+# Test 3 - Minimum set of db-level privileges for "full" backup of list
+#
+#
+# Create a new user named bup_sec_user1 and grant the user
+# a minimum set of privileges needed to run a complete or full backup
+# using the BACKUP DATABASE <list> command.
+#
+CREATE USER 'bup_sec_user1'@'localhost';
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SHOW VIEW ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT EVENT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+#
+# Show grants for user.
+#
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+Grants for bup_sec_user1@localhost
+GRANT USAGE ON *.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, EXECUTE, SHOW VIEW, EVENT, TRIGGER, BACKUP ON `bup_sec_db1`.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, TRIGGER, BACKUP ON `bup_sec_db2`.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT ON `mysql`.`procs_priv` TO 'bup_sec_user1'@'localhost'
+#
+# Connect as user bup_sec_user1 and attempt backup.
+# Expected result: success.
+#
+# connection con_user1
+BACKUP DATABASE bup_sec_db1, bup_sec_db2 to 'bup_sec.bak';
+backup_id
+#
+#
+# Run mysqlbackup to dump the image and show all objects included.
+#
+# exec $MYSQL_BACKUP
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Server byte order: #
+Server charset:      'utf8'
+
+Catalog details:
+
+  Database  'bup_sec_db1'
+    Table     'bup_sec_db1'.'t1'
+    Table     'bup_sec_db1'.'t2'
+    Sproc     'bup_sec_db1'.'p1'
+    Sfunc     'bup_sec_db1'.'f1'
+    View      'bup_sec_db1'.'v1'
+    Event     'bup_sec_db1'.'e1'
+    Trigger   'bup_sec_db1'.'t1_ai'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+  Database  'bup_sec_db2'
+    Table     'bup_sec_db2'.'t1'
+    Trigger   'bup_sec_db2'.'t1_ai'
+    Privilege 'bup_sec_db2'.'<empty>'
+    Privilege 'bup_sec_db2'.'<empty>'
+    Privilege 'bup_sec_db2'.'<empty>'
+
+#
+# Drop the user.
+#
+# connection default
+DROP USER 'bup_sec_user1'@'localhost';
+#
+# Test 4 - Minimum set of privileges for "empty" backup of *
+#
+#
+# Create a new user named bup_sec_user1 and grant the user
+# a minimum set of privileges needed to run a complete or full backup
+# using the BACKUP DATABASE * command.
+#
+CREATE USER 'bup_sec_user1'@'localhost';
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+#
+# Show grants for user.
+#
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+Grants for bup_sec_user1@localhost
+GRANT USAGE ON *.* TO 'bup_sec_user1'@'localhost'
+GRANT BACKUP ON `bup_sec_db1`.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT ON `mysql`.`procs_priv` TO 'bup_sec_user1'@'localhost'
+#
+# Connect as user bup_sec_user1 and attempt backup.
+# Expected result: Pass for non-patched code, ERROR for patched code.
+#
+# connection con_user1
+BACKUP DATABASE * to 'bup_sec.bak';
+ERROR HY000: Insufficient privileges. You must have the SELECT privilege on all databases to execute BACKUP DATABASE *.
+SHOW ERRORS;
+Level	Code	Message
+Error	#	Insufficient privileges. You must have the SELECT privilege on all databases to execute BACKUP DATABASE *.
+#
+# Drop the user.
+#
+# connection default
+DROP USER 'bup_sec_user1'@'localhost';
+#
+# Test 5 - Minimum set of specific privileges for "full" backup of *
+#
+#
+# Create a new user named bup_sec_user1 and grant the user
+# a minimum set of object-specific privileges needed to run a complete 
+# or full backup using the BACKUP DATABASE * command.
+#
+CREATE USER 'bup_sec_user1'@'localhost';
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.t1 TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.t2 TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON PROCEDURE bup_sec_db1.p1 TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON FUNCTION bup_sec_db1.f1 TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db1.t1 TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.v1 TO 'bup_sec_user1'@'localhost';
+GRANT SHOW VIEW ON bup_sec_db1.v1 TO 'bup_sec_user1'@'localhost';
+GRANT EVENT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db2.t1 TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db2.t1 TO 'bup_sec_user1'@'localhost';
+GRANT ALL ON mtr.* TO 'bup_sec_user1'@'localhost';
+#
+# Show grants for user.
+#
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+Grants for bup_sec_user1@localhost
+GRANT USAGE ON *.* TO 'bup_sec_user1'@'localhost'
+GRANT ALL PRIVILEGES ON `mtr`.* TO 'bup_sec_user1'@'localhost'
+GRANT EVENT, BACKUP ON `bup_sec_db1`.* TO 'bup_sec_user1'@'localhost'
+GRANT BACKUP ON `bup_sec_db2`.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT ON `bup_sec_db1`.`t2` TO 'bup_sec_user1'@'localhost'
+GRANT SELECT ON `mysql`.`procs_priv` TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, TRIGGER ON `bup_sec_db2`.`t1` TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, TRIGGER ON `bup_sec_db1`.`t1` TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, SHOW VIEW ON `bup_sec_db1`.`v1` TO 'bup_sec_user1'@'localhost'
+GRANT EXECUTE ON PROCEDURE `bup_sec_db1`.`p1` TO 'bup_sec_user1'@'localhost'
+GRANT EXECUTE ON FUNCTION `bup_sec_db1`.`f1` TO 'bup_sec_user1'@'localhost'
+#
+# Run backup again as user bup_sec_user1 and reattempt backup.
+# Expected result: success.
+#
+# connection con_user1
+BACKUP DATABASE * to 'bup_sec.bak';
+backup_id
+#
+#
+# Run mysqlbackup to dump the image and show all objects included.
+#
+# exec $MYSQL_BACKUP
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Server byte order: #
+Server charset:      'utf8'
+
+Catalog details:
+
+  Database  'bup_sec_db1'
+    Table     'bup_sec_db1'.'t1'
+    Table     'bup_sec_db1'.'t2'
+    Sproc     'bup_sec_db1'.'p1'
+    Sfunc     'bup_sec_db1'.'f1'
+    View      'bup_sec_db1'.'v1'
+    Event     'bup_sec_db1'.'e1'
+    Trigger   'bup_sec_db1'.'t1_ai'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+  Database  'bup_sec_db2'
+    Table     'bup_sec_db2'.'t1'
+    Trigger   'bup_sec_db2'.'t1_ai'
+    Privilege 'bup_sec_db2'.'<empty>'
+    Privilege 'bup_sec_db2'.'<empty>'
+    Privilege 'bup_sec_db2'.'<empty>'
+  Database  'mtr'
+    Table     'mtr'.'global_suppressions'
+    Table     'mtr'.'test_suppressions'
+    Sproc     'mtr'.'add_suppression'
+    Sproc     'mtr'.'check_testcase'
+    Sproc     'mtr'.'check_warnings'
+    Sproc     'mtr'.'force_restart'
+    Trigger   'mtr'.'gs_insert'
+    Trigger   'mtr'.'ts_insert'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+  Database  'test'
+
+#
+# Revoke all privileges and drop the user.
+#
+# connection default
+# Explicit revoke due to Bug#36544
+REVOKE EXECUTE ON FUNCTION bup_sec_db1.f1 FROM 'bup_sec_user1'@'localhost';
+DROP USER 'bup_sec_user1'@'localhost';
+#
+# Test 6 - Minimum set of db-level privileges for "full" backup of *
+#
+#
+# Create a new user named bup_sec_user1 and grant the user
+# a minimum set of privileges needed to run a complete or full backup
+# using the BACKUP DATABASE * command.
+#
+CREATE USER 'bup_sec_user1'@'localhost';
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SHOW VIEW ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT EVENT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT ALL ON mtr.* TO 'bup_sec_user1'@'localhost';
+#
+# Show grants for user.
+#
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+Grants for bup_sec_user1@localhost
+GRANT USAGE ON *.* TO 'bup_sec_user1'@'localhost'
+GRANT ALL PRIVILEGES ON `mtr`.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, EXECUTE, SHOW VIEW, EVENT, TRIGGER, BACKUP ON `bup_sec_db1`.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT, TRIGGER, BACKUP ON `bup_sec_db2`.* TO 'bup_sec_user1'@'localhost'
+GRANT SELECT ON `mysql`.`procs_priv` TO 'bup_sec_user1'@'localhost'
+#
+# Run backup again as user bup_sec_user1 and reattempt backup.
+# Expected result: success.
+#
+# connection con_user1
+BACKUP DATABASE * to 'bup_sec.bak';
+backup_id
+#
+#
+# Run mysqlbackup to dump the image and show all objects included.
+#
+# exec $MYSQL_BACKUP
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Server byte order: #
+Server charset:      'utf8'
+
+Catalog details:
+
+  Database  'bup_sec_db1'
+    Table     'bup_sec_db1'.'t1'
+    Table     'bup_sec_db1'.'t2'
+    Sproc     'bup_sec_db1'.'p1'
+    Sfunc     'bup_sec_db1'.'f1'
+    View      'bup_sec_db1'.'v1'
+    Event     'bup_sec_db1'.'e1'
+    Trigger   'bup_sec_db1'.'t1_ai'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+    Privilege 'bup_sec_db1'.'<empty>'
+  Database  'bup_sec_db2'
+    Table     'bup_sec_db2'.'t1'
+    Trigger   'bup_sec_db2'.'t1_ai'
+    Privilege 'bup_sec_db2'.'<empty>'
+    Privilege 'bup_sec_db2'.'<empty>'
+    Privilege 'bup_sec_db2'.'<empty>'
+  Database  'mtr'
+    Table     'mtr'.'global_suppressions'
+    Table     'mtr'.'test_suppressions'
+    Sproc     'mtr'.'add_suppression'
+    Sproc     'mtr'.'check_testcase'
+    Sproc     'mtr'.'check_warnings'
+    Sproc     'mtr'.'force_restart'
+    Trigger   'mtr'.'gs_insert'
+    Trigger   'mtr'.'ts_insert'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+    Privilege 'mtr'.'<empty>'
+  Database  'test'
+
+# connection default
+DROP USER 'bup_sec_user1'@'localhost';
+#
+# Cleanup
+#
+DROP DATABASE bup_sec_db1;
+DROP DATABASE bup_sec_db2;

=== modified file 'mysql-test/suite/backup/t/backup_security.test'
--- a/mysql-test/suite/backup/t/backup_security.test	2009-07-01 20:42:26 +0000
+++ b/mysql-test/suite/backup/t/backup_security.test	2009-07-15 14:18:59 +0000
@@ -1,8 +1,18 @@
 #
 # This test includes tests for all of the security-related tasks in 
-# Online Backup. These include tests for:
+# MySQL Backup. These include tests for:
 #
-# 1) Only users with BACKUP or RESTORE privilege can run backup or restore.
+# 1) Ensure the visibility check works for a basic backup and restore for
+#    each type of object.
+# 2) Only users with BACKUP or RESTORE privilege can run backup or restore.
+# 3) Users must have the ability to read (SELECT) all databases
+#    as well as have BACKUP on *.* to execute BACKUP DATABASE * TO <file>.
+# 4) Users must have the ability to read (SELECT) all objects in a database
+#    as well as have BACKUP to execute BACKUP DATABASE backup_test TO <file>.
+# 5) Users with partial access (SELECT on some objects) cannot backup
+#    the database without errors.
+# 6) Users with individual privileges and no database-level except EVENT
+#    can successfully backup the database.
 #
 
 --source include/not_embedded.inc
@@ -12,24 +22,15 @@ call mtr.add_suppression("Backup:");
 call mtr.add_suppression("Restore:");
 enable_query_log;
 
-connect (root_user,localhost,root,,);
+connect (conn_root,localhost,root,,);
 
 --disable_warnings
 DROP DATABASE IF EXISTS backup_test;
+DROP DATABASE IF EXISTS backup_test_alt;
 --enable_warnings
 
-#
-# Test 1 - Only users with BACKUP and RESTORE privilege can run backup 
-#          and restore.
-#
-
 --echo #
 --echo # Create database and data to test.
---echo # Create 3 users and grants rights as follows:
---echo #   bup_no_rights   - denied everything (poor chap)
---echo #                     except SELECT ON backup_test_alt.*
---echo #   bup_with_rights - super user account (like root)
---echo #   bup_some_rights - rights to a database but no BACKUP or RESTORE
 --echo #
 CREATE DATABASE backup_test;
 CREATE TABLE backup_test.t1 (a char(30)) ENGINE=MEMORY;
@@ -41,6 +42,11 @@ INSERT INTO backup_test.t1 VALUES ("05 T
 INSERT INTO backup_test.t1 VALUES ("06 Test #1 - privilege"); 
 INSERT INTO backup_test.t1 VALUES ("07 Test #1 - privilege"); 
 
+CREATE TABLE backup_test.t2 (a char(30)) ENGINE=MEMORY;
+INSERT INTO backup_test.t2 VALUES ("01 Test #2 - privilege"); 
+INSERT INTO backup_test.t2 VALUES ("02 Test #2 - privilege"); 
+INSERT INTO backup_test.t2 VALUES ("03 Test #2 - privilege"); 
+
 CREATE DATABASE backup_test_alt;
 CREATE TABLE backup_test_alt.t1 (a char(30)) ENGINE=MEMORY;
 INSERT INTO backup_test_alt.t1 VALUES ("01 Test #2 - privilege"); 
@@ -61,23 +67,99 @@ CREATE VIEW backup_test.v1 as SELECT * F
 CREATE EVENT backup_test.e1 ON SCHEDULE EVERY 1 YEAR DO
   DELETE FROM backup_test.t1 WHERE a = "not there";
 
-CREATE USER 'bup_no_rights'@'localhost';
-CREATE USER 'bup_with_rights'@'localhost';
-CREATE USER 'bup_some_rights'@'localhost';
-
-REVOKE ALL ON *.* FROM 'bup_no_rights'@'localhost';
-REVOKE ALL ON *.* FROM 'bup_with_rights'@'localhost';
-REVOKE ALL ON *.* FROM 'bup_some_rights'@'localhost';
-GRANT SELECT ON backup_test_alt.* TO 'bup_no_rights'@'localhost';
-GRANT ALL ON *.* TO 'bup_with_rights'@'localhost';
-GRANT GRANT OPTION ON *.* TO 'bup_with_rights'@'localhost';
-GRANT ALL ON backup_test.* TO 'bup_some_rights'@'localhost';
-REVOKE BACKUP, RESTORE ON backup_test.* FROM 'bup_some_rights'@'localhost'; 
-GRANT SELECT ON mysql.* TO 'bup_with_rights'@'localhost';
+--echo #
+--echo # Create users.
+--echo #
+CREATE USER 'bup_no_priv'@'localhost';
+CREATE USER 'bup_root_user'@'localhost';
+CREATE USER 'bup_no_bup_priv'@'localhost';
+CREATE USER 'bup_some_priv'@'localhost';
+CREATE USER 'bup_select_priv'@'localhost';
+CREATE USER 'bup_full_priv'@'localhost';
+CREATE USER 'bup_other_priv'@'localhost';
+
+--echo #
+--echo # Grants privileges as follows:
+--echo #   bup_no_priv     - denied everything (poor chap)
+--echo #                     except SELECT ON backup_test_alt.*
+--echo #   bup_root_user   - super user account (like root)
+--echo #   bup_no_bup_priv - privileges to a database but no BACKUP or RESTORE
+--echo #   bup_some_priv   - privileges to some database objects 
+--echo #                     and BACKUP and RESTORE
+--echo #   bup_full_priv   - user gets database-level specific grants
+--echo #   bup_other_priv  - user who has privileges other than select
+--echo #
+
+--echo #
+--echo # Setup grants for bup_no_priv
+--echo #
+REVOKE ALL ON *.* FROM 'bup_no_priv'@'localhost';
+GRANT SELECT ON backup_test_alt.* TO 'bup_no_priv'@'localhost';
+
+--echo #
+--echo # Setup grants for bup_root_user
+--echo #
+GRANT ALL ON *.* TO 'bup_root_user'@'localhost';
+GRANT GRANT OPTION ON *.* TO 'bup_root_user'@'localhost';
+
+--echo #
+--echo # Setup grants for bup_no_bup_priv
+--echo #
+REVOKE ALL ON *.* FROM 'bup_no_bup_priv'@'localhost';
+GRANT ALL ON backup_test.* TO 'bup_no_bup_priv'@'localhost';
+REVOKE BACKUP, RESTORE ON backup_test.* FROM 'bup_no_bup_priv'@'localhost'; 
+
+--echo #
+--echo # Setup grants for bup_some_priv
+--echo #
+REVOKE ALL ON *.* FROM 'bup_some_priv'@'localhost';
+GRANT BACKUP, RESTORE ON *.* TO 'bup_some_priv'@'localhost';
+GRANT ALL ON backup_test.t1 TO 'bup_some_priv'@'localhost';
+
+--echo #
+--echo # Setup grants for bup_select_priv
+--echo #
+REVOKE ALL ON *.* FROM 'bup_select_priv'@'localhost';
+GRANT SELECT ON backup_test.* TO 'bup_select_priv'@'localhost';
+GRANT BACKUP, RESTORE ON backup_test.* TO 'bup_select_priv'@'localhost';
+
+--echo #
+--echo # Setup grants for bup_full_priv
+--echo # Note: test case is setup so that backup should fail until
+--echo # all privileges for each object is specified.
+--echo #
+REVOKE ALL ON *.* FROM 'bup_full_priv'@'localhost';
+GRANT BACKUP, RESTORE ON backup_test.* TO 'bup_full_priv'@'localhost';
+
+--echo #
+--echo # Setup grants for bup_other_priv
+--echo # Note: test case is setup so that backup should fail if user has other
+--echo # privileges but not seleect.
+--echo #
+REVOKE ALL ON *.* FROM 'bup_full_priv'@'localhost';
+GRANT BACKUP, RESTORE, CREATE, DROP ON backup_test.* TO 'bup_other_priv'@'localhost';
+
 FLUSH PRIVILEGES;
 
+--echo # 
+--echo # Show grants for users.
 --echo #
---echo # root_user: Do backup of database with root user for later tests.
+SHOW GRANTS FOR 'bup_no_priv'@'localhost';
+--echo # 
+SHOW GRANTS FOR 'bup_root_user'@'localhost';
+--echo # 
+SHOW GRANTS FOR 'bup_no_bup_priv'@'localhost';
+--echo # 
+SHOW GRANTS FOR 'bup_some_priv'@'localhost';
+--echo # 
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+--echo # 
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+--echo # 
+SHOW GRANTS FOR 'bup_other_priv'@'localhost';
+
+--echo #
+--echo # conn_root_user: Do backup of database with root user for later tests.
 --echo #
 
 --replace_column 1 #
@@ -91,111 +173,598 @@ SELECT event_name FROM INFORMATION_SCHEM
 SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
 SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
 
-disconnect root_user;
 --echo #
---echo # Connect as user with some rights and attempt backup.
+--echo # Test 1 - Ensure the visibility check works for a basic backup and  
+--echo #          restore for each type of object. Also show that user must 
+--echo #          have additional privileges to succesfully backup a database.
 --echo #
-connect (some_rights,localhost,bup_some_rights,,);
 
 --echo #
---echo # some_rights: Attempting backup. Should fail with 
---echo # error ER_BACKUP_ACCESS_DENIED_ERROR
+--echo # Step 1, show that root can query IS tables and get correct counts
+--echo # for all objects in the database.
+--echo #
+
+--echo Get number of tables and views -- should be 3
+SELECT count(*) = 3 FROM INFORMATION_SCHEMA.TABLES 
+WHERE table_schema = 'backup_test';
+
+--echo Get number of triggers -- should be 1
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.TRIGGERS 
+WHERE trigger_schema = 'backup_test';
+
+--echo Get number of procedures and functions -- should be 2
+--echo but will be 0 because user does not have SELECT on
+--echo the mysql tables for routines.
+SELECT count(*) = 2 FROM INFORMATION_SCHEMA.ROUTINES 
+WHERE routine_schema = 'backup_test';
+
+--echo Get number of events -- should be 1
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.EVENTS 
+WHERE event_schema = 'backup_test';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with limited privileges.
+--echo #
+connect (conn_select_priv,localhost,bup_select_priv,,);
+
+--echo #
+--echo # Step 2, show that a user with only SELECT cannot query IS tables
+--echo # and get correct counts for all objects in the database.
+--echo #
+
+--echo Get number of tables and views -- should be 3
+SELECT count(*) = 3 FROM INFORMATION_SCHEMA.TABLES 
+WHERE table_schema = 'backup_test';
+
+--echo Get number of triggers -- should be 1 but will be 0
+--echo because user needs TRIGGER privilege.
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.TRIGGERS 
+WHERE trigger_schema = 'backup_test';
+
+--echo Get number of procedures and functions -- should be 2
+--echo but will be 0 because user doesn't have SELECT on
+--echo the mysql routine tables.
+SELECT count(*) = 2 FROM INFORMATION_SCHEMA.ROUTINES 
+WHERE routine_schema = 'backup_test';
+
+--echo Get number of events -- should be 1 but will be 0
+--echo because user needs EVENT privilege.
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.EVENTS 
+WHERE event_schema = 'backup_test';
+
+--echo #
+--echo # conn_select_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
 --echo #
 --replace_column 1 #
---error ER_BACKUP_ACCESS_DENIED_ERROR
-BACKUP DATABASE backup_test to 'bup_some_rights.bak';
---replace_regex /[0-9]/#/
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+--replace_column 2 #
 SHOW ERRORS;
 
+disconnect conn_select_priv;
 --echo #
---echo # some_rights: Attempting backup. Should fail with 
---echo # error ER_BACKUP_ACCESS_DENIED_ERROR
+--echo # Connect as root and add privileges.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--echo # 
+--echo # Step 3, give user EVENT privilege and retry backup.
+--echo #
+GRANT EVENT ON backup_test.* TO 'bup_select_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with upgraded privileges and attempt backup.
+--echo #
+connect (conn_select_priv,localhost,bup_select_priv,,);
+
+--echo Get number of events -- should now be 1
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.EVENTS 
+WHERE event_schema = 'backup_test';
+
+--echo #
+--echo # conn_select_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
 --echo #
 --replace_column 1 #
---error ER_BACKUP_ACCESS_DENIED_ERROR
-BACKUP DATABASE * to 'bup_some_rights.bak';
---replace_regex /[0-9]/#/
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+disconnect conn_select_priv;
+--echo #
+--echo # Connect as root and add privileges.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--echo # 
+--echo # Step 4, give user TRIGGER privilege and retry backup.
+--echo #
+GRANT TRIGGER ON backup_test.* TO 'bup_select_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with upgraded privileges and attempt backup.
+--echo #
+connect (conn_select_priv,localhost,bup_select_priv,,);
+
+--echo Get number of triggers -- should now be 1
+SELECT count(*) = 1 FROM INFORMATION_SCHEMA.TRIGGERS 
+WHERE trigger_schema = 'backup_test';
+
+--echo #
+--echo # conn_select_priv: Attempting backup. Should fail with 
+--echo # error ER_BAD_DB_ERROR
+--echo #
+--replace_column 1 #
+--error ER_BAD_DB_ERROR
+BACKUP DATABASE not_there_at_all_ever, backup_test to 'backup_test_select.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+--echo #
+--echo # conn_select_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test, not_there_at_all_ever to 'backup_test_select.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+--echo #
+--echo # conn_select_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+disconnect conn_select_priv;
+--echo #
+--echo # Connect as root and add privileges.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--echo # 
+--echo # Step 5, give user SELECT privilege on the mysql tables
+--echo # and retry backup.
+--echo #
+GRANT SELECT ON mysql.* TO 'bup_select_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with upgraded privileges and attempt backup.
+--echo #
+connect (conn_select_priv,localhost,bup_select_priv,,);
+
+--echo #
+--echo # conn_select_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_GET_META_VIEW
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_GET_META_VIEW
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+--replace_column 2 #
 SHOW ERRORS;
 
-disconnect some_rights;
+disconnect conn_select_priv;
 --echo #
---echo # Connect as user with no rights and attempt backup.
+--echo # Connect as root and add privileges.
 --echo #
-connect (no_rights,localhost,bup_no_rights,,);
+connect (conn_root,localhost,root,,);
 
 --echo #
---echo # no_rights: Attempting backup. Should fail with 
+--echo # Step 6, Give user SHOW VIEW privilege and retry backup.
+--echo #
+GRANT SHOW VIEW ON backup_test.* TO 'bup_select_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with upgraded privileges and attempt backup.
+--echo #
+connect (conn_select_priv,localhost,bup_select_priv,,);
+
+--replace_column 1 #
+BACKUP DATABASE backup_test to 'backup_test_select.bak';
+
+--echo # Backup now succeeds.
+
+--echo #
+--echo # conn_select_priv: Attempting backup. Should fail with 
 --echo # error ER_BAD_DB_ERROR
 --echo #
 --replace_column 1 #
 --error ER_BAD_DB_ERROR
-BACKUP DATABASE backup_test to 'bup_no_rights.bak';
---replace_regex /[0-9]/#/
+BACKUP DATABASE not_there_at_all_ever to 'backup_test_select1.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+disconnect conn_select_priv;
+--echo #
+--echo # Connect as root and do the restore to ensure everything got 
+--echo # restored.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--echo #
+--echo # Step 7, show that the backup image contains all of the objects
+--echo # and compare that to the original backup made by root.
+--echo #
+
+--replace_column 1 #
+RESTORE FROM 'backup_test_select.bak' OVERWRITE;
+
+--echo #
+--echo # Show list of all objects in the database.
+--echo #
+SHOW FULL TABLES FROM backup_test;
+SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
+SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
+SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
+
+--echo #
+--echo # Compare to original backup image file.
+--echo #
+
+--replace_column 1 #
+RESTORE FROM 'backup_test_orig.bak' OVERWRITE;
+
+--echo #
+--echo # Show list of all objects in the database.
+--echo #
+SHOW FULL TABLES FROM backup_test;
+SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
+SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
+SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
+
+--echo #
+--echo # Test 2 - Only users with BACKUP and RESTORE privilege can run backup
+--echo #          and restore.
+--echo #
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with no privileges and attempt backup.
+--echo #
+connect (conn_no_priv,localhost,bup_no_priv,,);
+
+--echo #
+--echo # conn_no_priv: Attempting restore. Should fail with
+--echo # error ER_RESTORE_ACCESS_DENIED_ERROR
+--echo #
+--replace_column 1 #
+--error ER_RESTORE_ACCESS_DENIED_ERROR
+RESTORE FROM 'backup_test_orig.bak';
+--replace_column 2 #
 SHOW ERRORS;
 
 source suite/backup/include/backup_check_privileges.inc;
 
 --echo #
---echo # no_rights: Attempting backup. Should fail with 
+--echo # conn_no_priv: Attempting backup. Should fail with 
 --echo # error ER_BACKUP_ACCESS_DENIED_ERROR
 --echo #
 --replace_column 1 #
 --error ER_BACKUP_ACCESS_DENIED_ERROR
-BACKUP DATABASE backup_test_alt to 'bup_no_rights.bak';
---replace_regex /[0-9]/#/
+BACKUP DATABASE backup_test_alt to 'bup_no_priv.bak';
+--replace_column 2 #
 SHOW ERRORS;
 
+source suite/backup/include/backup_check_privileges.inc;
+
+disconnect conn_no_priv;
+--echo #
+--echo # Connect as user with privileges and attempt backup and restore.
+--echo #
+connect (conn_root_user,localhost,bup_root_user,,);
+
+--echo #
+--echo # conn_root_user: Attempting backup. Should succeed
+--echo #
+--replace_column 1 #
+BACKUP DATABASE backup_test to 'bup_root_user.bak';
+
+--echo #
+--echo # conn_root_user: Attempting restore. Should succeed
+--echo #
+--replace_column 1 #
+RESTORE FROM 'bup_root_user.bak' OVERWRITE;
+
 --echo #
---echo # no_rights: Attempting backup. Should fail with 
+--echo # Show that all objects were recreated after restore.
+--echo #
+SHOW FULL TABLES FROM backup_test;
+SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
+SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
+SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
+
+disconnect conn_root_user;
+--echo #
+--echo # Connect as user with no backup privileges and attempt backup.
+--echo #
+connect (conn_no_bup_priv,localhost,bup_no_bup_priv,,);
+
+--echo #
+--echo # conn_no_bup_priv: Attempting backup. Should fail with 
 --echo # error ER_BACKUP_ACCESS_DENIED_ERROR
 --echo #
 --replace_column 1 #
 --error ER_BACKUP_ACCESS_DENIED_ERROR
-BACKUP DATABASE * to 'bup_no_rights.bak';
---replace_regex /[0-9]/#/
+BACKUP DATABASE backup_test to 'bup_no_bup_priv.bak';
+--replace_column 2 #
 SHOW ERRORS;
 
 --echo #
---echo # no_rights: Attempting restore. Should fail with
+--echo # conn_no_bup_priv: Attempting restore. Should fail with 
 --echo # error ER_RESTORE_ACCESS_DENIED_ERROR
 --echo #
 --replace_column 1 #
 --error ER_RESTORE_ACCESS_DENIED_ERROR
 RESTORE FROM 'backup_test_orig.bak';
---replace_regex /[0-9]/#/
+--replace_column 2 #
 SHOW ERRORS;
 
-source suite/backup/include/backup_check_privileges.inc;
+--echo #
+--echo # Test 3 - Users must have the ability to read (SELECT) all databases
+--echo #          as well as have BACKUP on *.* to execute 
+--echo #          BACKUP DATABASE * TO <file>.
+--echo #
 
-disconnect no_rights;
+disconnect conn_no_bup_priv;
 --echo #
---echo # Connect as user with rights and attempt backup and restore.
+--echo # Do restore to ensure it still works with root user.
 --echo #
-connect (with_rights,localhost,bup_with_rights,,);
+connect (conn_no_priv,localhost,bup_no_priv,,);
 
 --echo #
---echo # with_rights: Attempting backup. Should succeed
+--echo # conn_no_priv: Attempting backup *. Should fail with 
+--echo # error ER_BACKUP_ACCESS_DBS_INCOMPLETE
 --echo #
 --replace_column 1 #
-BACKUP DATABASE backup_test to 'bup_with_rights.bak';
+--error ER_BACKUP_ACCESS_DBS_INCOMPLETE
+BACKUP DATABASE * to 'bup_no_priv.bak';
+--replace_column 2 #
+SHOW ERRORS;
 
+disconnect conn_no_priv;
 --echo #
---echo # with_rights: Attempting backup. Should not fail.
+--echo # Connect as user with privileges and attempt backup and restore.
+--echo #
+connect (conn_root_user,localhost,bup_root_user,,);
+
+--echo #
+--echo # conn_root_user: Attempting backup. Should not fail.
 --echo #
 --replace_column 1 #
-BACKUP DATABASE * to 'bup_with_rights_star.bak';
+BACKUP DATABASE * to 'bup_root_user_star.bak';
 
+disconnect conn_root_user;
 --echo #
---echo # with_rights: Attempting restore. Should succeed
+--echo # Connect as user with no backup privileges and attempt backup.
+--echo #
+connect (conn_no_bup_priv,localhost,bup_no_bup_priv,,);
+
+--echo #
+--echo # conn_no_bup_priv: Attempting backup *. Should fail with 
+--echo # error ER_BACKUP_ACCESS_DBS_INCOMPLETE
 --echo #
 --replace_column 1 #
-RESTORE FROM 'bup_with_rights.bak' OVERWRITE;
+--error ER_BACKUP_ACCESS_DBS_INCOMPLETE
+BACKUP DATABASE * to 'bup_no_bup_priv.bak';
+--replace_column 2 #
+SHOW ERRORS;
 
-disconnect with_rights;
+disconnect conn_no_bup_priv;
 --echo #
---echo # Do restore to ensure it still works with root user.
+--echo # Connect as root and redo privileges for user with only select.
+--echo #
+connect (conn_root,localhost,root,,);
+
+# Make sure there is only 1 other database that user has select on.
+# This is needed for deterministic result because a list of 
+# databases are unordered.
+
+DROP DATABASE backup_test_alt;
+REVOKE ALL ON *.* FROM 'bup_select_priv'@'localhost';
+REVOKE ALL ON backup_test.* FROM 'bup_select_priv'@'localhost';
+GRANT SELECT, TRIGGER, EVENT, SHOW VIEW ON *.* TO 'bup_select_priv'@'localhost';
+GRANT BACKUP, RESTORE ON *.* TO 'bup_select_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_select_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with upgraded privileges and attempt backup.
+--echo #
+connect (conn_select_priv,localhost,bup_select_priv,,);
+
+--echo #
+--echo # conn_select_priv: Attempting backup *. Should succeed.
+--echo #
+--replace_column 1 #
+BACKUP DATABASE * to 'bup_select_priv.bak';
+
+--echo #
+--echo # Test 4 - Users must have the ability to read (SELECT) all objects in 
+--echo #          a databsase as well as have BACKUP to execute 
+--echo #          BACKUP DATABASE backup_test TO <file>.
+--echo #
+
+disconnect conn_select_priv;
+--echo #
+--echo # Connect as user with no privileges and attempt backup.
+--echo #
+connect (conn_no_priv,localhost,bup_no_priv,,);
+
+--echo #
+--echo # conn_no_priv: Attempting backup. Should fail with 
+--echo # error ER_BAD_DB_ERROR
+--echo #
+--replace_column 1 #
+--error ER_BAD_DB_ERROR
+BACKUP DATABASE backup_test to 'bup_no_priv.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+disconnect conn_no_priv;
+--echo #
+--echo # Connect as user with privileges other than select and attempt backup.
+--echo #
+connect (conn_other_priv,localhost,bup_other_priv,,);
+
+--echo #
+--echo # conn_other_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE 
+BACKUP DATABASE backup_test to 'bup_other_priv.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+--echo #
+--echo # Reconnect as root and change privileges for user.
+--echo #
+
+disconnect conn_other_priv;
+--echo #
+--echo # Connect as user with privileges and attempt backup and restore.
+--echo #
+connect (conn_root,localhost,root,,);
+
+REVOKE ALL ON backup_test.* FROM 'bup_other_priv'@'localhost';
+GRANT SELECT ON mysql.* TO 'bup_other_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_other_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with SELECT on mysql.* and attempt backup.
+--echo #
+connect (conn_other_priv,localhost,bup_other_priv,,);
+
+--echo #
+--echo # conn_other_priv: Attempting backup. Should fail with 
+--echo # error ER_BAD_DB_ERROR
+--echo #
+--replace_column 1 #
+--error ER_BAD_DB_ERROR 
+BACKUP DATABASE backup_test to 'bup_other_priv.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+--echo #
+--echo # Reconnect as root and change privileges for user.
+--echo #
+
+disconnect conn_other_priv;
+--echo #
+--echo # Connect as user with privileges and attempt backup and restore.
+--echo #
+connect (conn_root,localhost,root,,);
+
+GRANT BACKUP ON backup_test.* TO 'bup_other_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_other_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with SELECT on mysql.* and attempt backup.
 --echo #
-connect (root_user,localhost,root,,);
+connect (conn_other_priv,localhost,bup_other_priv,,);
+
+--echo #
+--echo # conn_other_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE 
+BACKUP DATABASE backup_test to 'bup_other_priv.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+--echo #
+--echo # Test 5 - Users with partial access (SELECT on some objects) cannot
+--echo #          backup the database without errors.
+--echo #
+
+disconnect conn_other_priv;
+--echo #
+--echo # Connect as user with some privileges and attempt backup.
+--echo #
+connect (conn_some_priv,localhost,bup_some_priv,,);
+
+--echo #
+--echo # conn_some_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test to 'bup_some_priv.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+--echo #
+--echo # Reconnect as root to ensure we can restore correctly.
+--echo #
+
+disconnect conn_some_priv;
+--echo #
+--echo # Connect as user with privileges and attempt backup and restore.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--replace_column 1 #
+RESTORE FROM 'backup_test_orig.bak' OVERWRITE;
 
 --echo #
 --echo # Show that all objects were recreated after restore.
@@ -205,11 +774,223 @@ SELECT event_name FROM INFORMATION_SCHEM
 SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
 SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
 
+--echo #
+--echo # Test 6 -  Users with individual privileges and no database-level except 
+--echo #           EVENT can successfully backup the database. 
+--echo #           In this test case, we add one privilege at a time until
+--echo #           there is a complete set of database-level privileges 
+--echo #           and the backup command succeeds.
+--echo #
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with explicit privileges on specific database objects
+--echo # and attempt backup.
+--echo #
+connect (conn_full_priv,localhost,bup_full_priv,,);
+
+--echo #
+--echo # conn_conn_full_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+disconnect conn_full_priv;
+--echo #
+--echo # Connect as root and add another privilege.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--echo #
+--echo # Add another database-level grant statement.
+--echo #
+GRANT SELECT, TRIGGER ON backup_test.t2 TO 'bup_full_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with explicit on database objects and attempt backup.
+--echo #
+connect (conn_full_priv,localhost,bup_full_priv,,);
+
+--echo #
+--echo # conn_conn_full_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+disconnect conn_full_priv;
+--echo #
+--echo # Connect as root and add another privilege.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--echo #
+--echo # Add another database-level grant statement.
+--echo #
+GRANT SELECT, TRIGGER ON backup_test.t1 TO 'bup_full_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with explicit on database objects and attempt backup.
+--echo #
+connect (conn_full_priv,localhost,bup_full_priv,,);
+
+--echo #
+--echo # conn_conn_full_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+disconnect conn_full_priv;
+--echo #
+--echo # Connect as root and add another privilege.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--echo #
+--echo # Add another database-level grant statement.
+--echo #
+GRANT SELECT, SHOW VIEW ON backup_test.v1 TO 'bup_full_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with explicit on database objects and attempt backup.
+--echo #
+connect (conn_full_priv,localhost,bup_full_priv,,);
+
+--echo #
+--echo # conn_conn_full_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+disconnect conn_full_priv;
+--echo #
+--echo # Connect as root and add another privilege.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--echo #
+--echo # Add another database-level grant statement.
+--echo #
+GRANT EVENT ON backup_test.* TO 'bup_full_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with explicit on database objects and attempt backup.
+--echo #
+connect (conn_full_priv,localhost,bup_full_priv,,);
+
+--echo #
+--echo # conn_conn_full_priv: Attempting backup. Should fail with 
+--echo # error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+--echo #
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+disconnect conn_full_priv;
+--echo #
+--echo # Connect as root and add another privilege.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--echo #
+--echo # Add another database-level grant statement.
+--echo #
+GRANT SELECT ON mysql.* TO 'bup_full_priv'@'localhost';
+
+FLUSH PRIVILEGES;
+
+--echo # 
+--echo # Show updated privileges.
+--echo #
+SHOW GRANTS FOR 'bup_full_priv'@'localhost';
+
+disconnect conn_root;
+--echo #
+--echo # Connect as user with explicit on database objects and attempt backup.
+--echo #
+connect (conn_full_priv,localhost,bup_full_priv,,);
+
+--echo #
+--echo # conn_conn_full_priv: Attempting backup. Should succeed.
+--echo #
+--replace_column 1 #
+BACKUP DATABASE backup_test to 'backup_test_full.bak';
+
+disconnect conn_full_priv;
+--echo #
+--echo # Connect as root and check restore then cleanup.
+--echo #
+connect (conn_root,localhost,root,,);
+
+--replace_column 1 #
+RESTORE FROM 'backup_test_full.bak' OVERWRITE;
+
+--echo #
+--echo # Show list of all objects in the database.
+--echo #
+SHOW FULL TABLES FROM backup_test;
+SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
+SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_schema = 'backup_test';
+SELECT trigger_name FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'backup_test';
+
+--echo #
+--echo # Compare to original backup image file.
+--echo #
+
 --replace_column 1 #
 RESTORE FROM 'backup_test_orig.bak' OVERWRITE;
 
 --echo #
---echo # Show that all objects were recreated after restore.
+--echo # Show list of all objects in the database.
 --echo #
 SHOW FULL TABLES FROM backup_test;
 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS WHERE event_schema = 'backup_test';
@@ -220,14 +1001,20 @@ SELECT trigger_name FROM INFORMATION_SCH
 --echo # Cleanup
 --echo #
 
-DROP USER 'bup_no_rights'@'localhost';
-DROP USER 'bup_with_rights'@'localhost';
-DROP USER 'bup_some_rights'@'localhost';
+DROP USER 'bup_no_priv'@'localhost';
+DROP USER 'bup_root_user'@'localhost';
+DROP USER 'bup_no_bup_priv'@'localhost';
+DROP USER 'bup_some_priv'@'localhost';
+DROP USER 'bup_select_priv'@'localhost';
+DROP USER 'bup_full_priv'@'localhost';
+DROP USER 'bup_other_priv'@'localhost';
+
 DROP DATABASE backup_test;
-DROP DATABASE backup_test_alt;
 FLUSH PRIVILEGES;
 
 let $MYSQLD_BACKUPDIR= `select @@backupdir`;
-remove_file $MYSQLD_BACKUPDIR/bup_with_rights.bak;
+remove_file $MYSQLD_BACKUPDIR/bup_root_user.bak;
 remove_file $MYSQLD_BACKUPDIR/backup_test_orig.bak;
-remove_file $MYSQLD_BACKUPDIR/bup_with_rights_star.bak;
+remove_file $MYSQLD_BACKUPDIR/bup_root_user_star.bak;
+remove_file $MYSQLD_BACKUPDIR/backup_test_select.bak;
+remove_file $MYSQLD_BACKUPDIR/backup_test_full.bak;

=== added file 'mysql-test/suite/backup/t/backup_security_check.test'
--- a/mysql-test/suite/backup/t/backup_security_check.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_security_check.test	2009-07-15 14:18:59 +0000
@@ -0,0 +1,388 @@
+#
+# This test includes tests for all of the security-related tasks in 
+# MySQL Backup. This test was created to demonstrate that the problem
+# of skipped objects has been solved by BUG#45889. Specifically, the
+# BACKUP DATABASE command should include all objects or fail with an error.
+# This file includes the following test cases:
+#
+# 1) Minimum set of privileges for "empty" backup of list
+# 2) Minimum set of specific privileges for "full" backup of list
+# 3) Minimum set of db-level privileges for "full" backup of list
+# 4) Minimum set of privileges for "empty" backup of *
+# 5) Minimum set of specific privileges for "full" backup of *
+# 6) Minimum set of db-level privileges for "full" backup of *
+#
+
+--source include/not_embedded.inc
+
+--let $MYSQLD_DATADIR= `SELECT @@datadir`
+--let $MYSQLD_BACKUPDIR= `SELECT @@backupdir`
+
+--disable_warnings
+DROP DATABASE IF EXISTS bup_sec_db1;
+DROP DATABASE IF EXISTS bup_sec_db2;
+--enable_warnings
+
+--echo #
+--echo # Create some data to test. Includes one of each type of object
+--echo # and two databases.
+--echo #
+
+CREATE DATABASE bup_sec_db1;
+CREATE TABLE bup_sec_db1.t1 (a char(30)) ENGINE=MEMORY;
+CREATE TABLE bup_sec_db1.t2 (a char(30)) ENGINE=MEMORY;
+CREATE VIEW bup_sec_db1.v1 as SELECT * FROM bup_sec_db1.t1;
+CREATE TRIGGER bup_sec_db1.t1_ai AFTER INSERT ON bup_sec_db1.t1 FOR EACH ROW
+  INSERT INTO bup_sec_db1.t1 VALUES('Test objects count');
+CREATE PROCEDURE bup_sec_db1.p1(p1 CHAR(20))
+  INSERT INTO bup_sec_db1.t1 VALUES ("50");
+CREATE FUNCTION bup_sec_db1.f1() RETURNS INT RETURN (SELECT 1);
+CREATE EVENT bup_sec_db1.e1 ON SCHEDULE EVERY 1 YEAR DO
+  DELETE FROM bup_sec_db1.t1 WHERE a = "not there";
+
+CREATE DATABASE bup_sec_db2;
+CREATE TABLE bup_sec_db2.t1 (a char(30)) ENGINE=MEMORY;
+CREATE TRIGGER bup_sec_db2.t1_ai AFTER INSERT ON bup_sec_db2.t1 FOR EACH ROW
+  INSERT INTO bup_sec_db2.t1 VALUES('Test objects count');
+
+--echo #
+--echo # Attempt backup as root to capture backup image with all objects.
+--echo #
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+--replace_column 1 #
+BACKUP DATABASE * to 'bup_sec.bak';
+
+--echo #
+--echo # Dump the backup image to show the metadata using mysqlbackup.
+--echo # 
+--echo # exec \$MYSQL_BACKUP
+--source suite/backup/include/backup_client_regex_output.inc
+exec $MYSQL_BACKUP --catalog-details $MYSQLD_BACKUPDIR/bup_sec.bak 2>&1;
+--echo
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+
+--echo #
+--echo # Test 1 - Minimum set of privileges for "empty" backup of list
+--echo #
+
+--echo #
+--echo # Create a new user named bup_sec_user1 and grant the user
+--echo # a minimum set of privileges needed to run a complete or full backup
+--echo # using the BACKUP DATABASE <list> command on an empty list.
+--echo #
+CREATE USER 'bup_sec_user1'@'localhost';
+
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Show grants for user.
+--echo #
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Connect as user bup_sec_user1 and attempt backup.
+--echo # Expected result: Pass for non-patched code, ERROR for patched code.
+--echo #
+--echo # connection con_user1
+connect (con_user1,localhost,bup_sec_user1,,);
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+BACKUP DATABASE bup_sec_db1, bup_sec_db2 to 'bup_sec.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+--echo #
+--echo # Drop the user.
+--echo #
+--echo # connection default
+--connection default
+--disconnect con_user1
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+DROP USER 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Test 2 - Minimum set of specific privileges for "full" backup of list
+--echo #
+
+--echo #
+--echo # Create a new user named bup_sec_user1 and grant the user
+--echo # a minimum set of the object-specific privileges needed to run a 
+--echo # complete or full backup using the BACKUP DATABASE <list> command.
+--echo #
+CREATE USER 'bup_sec_user1'@'localhost';
+
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.t1 TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.t2 TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.v1 TO 'bup_sec_user1'@'localhost';
+GRANT SHOW VIEW ON bup_sec_db1.v1 TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON PROCEDURE bup_sec_db1.p1 TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON FUNCTION bup_sec_db1.f1 TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db1.t1 TO 'bup_sec_user1'@'localhost';
+GRANT EVENT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db2.t1 TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db2.t1 TO 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Show grants for user.
+--echo #
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Connect as user bup_sec_user1 and attempt backup.
+--echo # Expected result: success.
+--echo #
+--echo # connection con_user1
+connect (con_user1,localhost,bup_sec_user1,,);
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+--replace_column 1 #
+BACKUP DATABASE bup_sec_db1, bup_sec_db2 to 'bup_sec.bak';
+
+--echo #
+--echo # Run mysqlbackup to dump the image and show all objects included.
+--echo #
+--echo # exec \$MYSQL_BACKUP
+--source suite/backup/include/backup_client_regex_output.inc
+exec $MYSQL_BACKUP --catalog-details $MYSQLD_BACKUPDIR/bup_sec.bak 2>&1;
+--echo
+
+--echo #
+--echo # Revoke all privileges and drop the user.
+--echo #
+--echo # connection default
+--connection default
+--disconnect con_user1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+--echo # Explicit revoke due to Bug#36544
+REVOKE EXECUTE ON FUNCTION bup_sec_db1.f1 FROM 'bup_sec_user1'@'localhost';
+DROP USER 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Test 3 - Minimum set of db-level privileges for "full" backup of list
+--echo #
+
+--echo #
+--echo # Create a new user named bup_sec_user1 and grant the user
+--echo # a minimum set of privileges needed to run a complete or full backup
+--echo # using the BACKUP DATABASE <list> command.
+--echo #
+CREATE USER 'bup_sec_user1'@'localhost';
+
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SHOW VIEW ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT EVENT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Show grants for user.
+--echo #
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Connect as user bup_sec_user1 and attempt backup.
+--echo # Expected result: success.
+--echo #
+--echo # connection con_user1
+connect (con_user1,localhost,bup_sec_user1,,);
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+--replace_column 1 #
+BACKUP DATABASE bup_sec_db1, bup_sec_db2 to 'bup_sec.bak';
+
+--echo #
+--echo # Run mysqlbackup to dump the image and show all objects included.
+--echo #
+--echo # exec \$MYSQL_BACKUP
+--source suite/backup/include/backup_client_regex_output.inc
+exec $MYSQL_BACKUP --catalog-details $MYSQLD_BACKUPDIR/bup_sec.bak 2>&1;
+--echo
+
+--echo #
+--echo # Drop the user.
+--echo #
+--echo # connection default
+--connection default
+--disconnect con_user1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+DROP USER 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Test 4 - Minimum set of privileges for "empty" backup of *
+--echo #
+
+--echo #
+--echo # Create a new user named bup_sec_user1 and grant the user
+--echo # a minimum set of privileges needed to run a complete or full backup
+--echo # using the BACKUP DATABASE * command.
+--echo #
+CREATE USER 'bup_sec_user1'@'localhost';
+
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Show grants for user.
+--echo #
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Connect as user bup_sec_user1 and attempt backup.
+--echo # Expected result: Pass for non-patched code, ERROR for patched code.
+--echo #
+--echo # connection con_user1
+connect (con_user1,localhost,bup_sec_user1,,);
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+--replace_column 1 #
+--error ER_BACKUP_ACCESS_DBS_INCOMPLETE
+BACKUP DATABASE * to 'bup_sec.bak';
+--replace_column 2 #
+SHOW ERRORS;
+
+--echo #
+--echo # Drop the user.
+--echo #
+--echo # connection default
+--connection default
+--disconnect con_user1
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+DROP USER 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Test 5 - Minimum set of specific privileges for "full" backup of *
+--echo #
+
+--echo #
+--echo # Create a new user named bup_sec_user1 and grant the user
+--echo # a minimum set of object-specific privileges needed to run a complete 
+--echo # or full backup using the BACKUP DATABASE * command.
+--echo #
+CREATE USER 'bup_sec_user1'@'localhost';
+
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.t1 TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.t2 TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON PROCEDURE bup_sec_db1.p1 TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON FUNCTION bup_sec_db1.f1 TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db1.t1 TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.v1 TO 'bup_sec_user1'@'localhost';
+GRANT SHOW VIEW ON bup_sec_db1.v1 TO 'bup_sec_user1'@'localhost';
+GRANT EVENT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db2.t1 TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db2.t1 TO 'bup_sec_user1'@'localhost';
+# Don't care about mtr.
+GRANT ALL ON mtr.* TO 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Show grants for user.
+--echo #
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Run backup again as user bup_sec_user1 and reattempt backup.
+--echo # Expected result: success.
+--echo #
+--echo # connection con_user1
+connect (con_user1,localhost,bup_sec_user1,,);
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+--replace_column 1 #
+BACKUP DATABASE * to 'bup_sec.bak';
+
+--echo #
+--echo # Run mysqlbackup to dump the image and show all objects included.
+--echo #
+--echo # exec \$MYSQL_BACKUP
+--source suite/backup/include/backup_client_regex_output.inc
+exec $MYSQL_BACKUP --catalog-details $MYSQLD_BACKUPDIR/bup_sec.bak 2>&1;
+--echo
+
+--echo #
+--echo # Revoke all privileges and drop the user.
+--echo #
+--echo # connection default
+--connection default
+--disconnect con_user1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+--echo # Explicit revoke due to Bug#36544
+REVOKE EXECUTE ON FUNCTION bup_sec_db1.f1 FROM 'bup_sec_user1'@'localhost';
+DROP USER 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Test 6 - Minimum set of db-level privileges for "full" backup of *
+--echo #
+
+--echo #
+--echo # Create a new user named bup_sec_user1 and grant the user
+--echo # a minimum set of privileges needed to run a complete or full backup
+--echo # using the BACKUP DATABASE * command.
+--echo #
+CREATE USER 'bup_sec_user1'@'localhost';
+
+GRANT SELECT ON mysql.procs_priv TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT SHOW VIEW ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT EXECUTE ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT EVENT ON bup_sec_db1.* TO 'bup_sec_user1'@'localhost';
+GRANT BACKUP ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT SELECT ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+GRANT TRIGGER ON bup_sec_db2.* TO 'bup_sec_user1'@'localhost';
+# Don't care about mtr.
+GRANT ALL ON mtr.* TO 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Show grants for user.
+--echo #
+SHOW GRANTS FOR 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Run backup again as user bup_sec_user1 and reattempt backup.
+--echo # Expected result: success.
+--echo #
+--echo # connection con_user1
+connect (con_user1,localhost,bup_sec_user1,,);
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+--replace_column 1 #
+BACKUP DATABASE * to 'bup_sec.bak';
+
+--echo #
+--echo # Run mysqlbackup to dump the image and show all objects included.
+--echo #
+--echo # exec \$MYSQL_BACKUP
+--source suite/backup/include/backup_client_regex_output.inc
+exec $MYSQL_BACKUP --catalog-details $MYSQLD_BACKUPDIR/bup_sec.bak 2>&1;
+--echo
+
+--echo # connection default
+--connection default
+--disconnect con_user1
+--remove_file $MYSQLD_BACKUPDIR/bup_sec.bak
+DROP USER 'bup_sec_user1'@'localhost';
+
+--echo #
+--echo # Cleanup
+--echo #
+DROP DATABASE bup_sec_db1;
+DROP DATABASE bup_sec_db2;
+

=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc	2009-07-06 07:29:06 +0000
+++ b/sql/backup/backup_info.cc	2009-07-15 14:18:59 +0000
@@ -621,6 +621,15 @@ backup::Image_info::Db* Backup_info::add
     return NULL;
   }
 
+  /*
+    Check to see if the user can see all of the objects in the database.
+  */
+  if (obs::check_user_access(m_thd, name))
+  {
+    m_log.report_error(ER_BACKUP_ACCESS_OBJS_INCOMPLETE, name->ptr());
+    return NULL;
+  }
+
   Db *db= Image_info::add_db(*name, pos);
   
   if (!db)
@@ -739,6 +748,16 @@ int Backup_info::add_all_dbs()
   using namespace obs;
 
   int res= 0;
+
+  /*
+    Check to see if the user can see all of the databases.
+  */
+  if (check_user_access(m_thd, 0))
+  {
+    m_log.report_error(ER_BACKUP_ACCESS_DBS_INCOMPLETE);
+    return ERROR;
+  }
+
   Obj_iterator *dbit= get_databases(m_thd);
   
   if (!dbit)

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2009-07-06 07:29:06 +0000
+++ b/sql/share/errmsg.txt	2009-07-15 14:18:59 +0000
@@ -6550,3 +6550,7 @@ ER_BACKUP_ACCESS_DENIED_ERROR
   eng "Insufficient privileges. You must have the BACKUP privilege to backup database '%s'."
 ER_RESTORE_ACCESS_DENIED_ERROR
   eng "Insufficient privileges. You must have the RESTORE privilege to restore database '%s'."
+ER_BACKUP_ACCESS_DBS_INCOMPLETE
+  eng "Insufficient privileges. You must have the SELECT privilege on all databases to execute BACKUP DATABASE *."
+ER_BACKUP_ACCESS_OBJS_INCOMPLETE
+  eng "Insufficient privileges. You do not have privileges to backup database '%s'."

=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc	2009-06-24 08:05:34 +0000
+++ b/sql/si_objects.cc	2009-07-15 14:18:59 +0000
@@ -2501,6 +2501,144 @@ Obj_iterator *get_databases(THD *thd)
 
 ///////////////////////////////////////////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////
+/**
+  Return a count of databases.
+
+  This method returns the number of databases excluding the internal
+  databases 'mysql' and 'information_schema'.
+
+  @Note This method executes based on the current context of the THD
+        and thus returns a value based on the accessibility of objects
+        by the user context.
+
+  @param[in] THD     Current thread
+  
+  @return uint Number of databases.
+*/
+uint get_num_dbs(THD *thd)
+{
+  Ed_connection ed_connection(thd);
+  Ed_result_set *ed_result_set;
+  String_stream s_stream;
+
+  s_stream << 
+    "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA " <<
+    "WHERE LCASE(schema_name) != 'mysql' AND " <<
+    "LCASE(schema_name) != 'information_schema'";
+
+  if (run_service_interface_sql(thd, &ed_connection, s_stream.lex_string()))
+    /* Query failed with an error */
+    return NULL;
+  else if(ed_connection.get_warn_count())
+    /* Push warnings to BACKUP's error stack. */
+    thd->warning_info->append_warnings(thd, ed_connection.get_warn_list());
+
+  DBUG_ASSERT(ed_connection.get_field_count());
+
+  /* Use store_result to get ownership of result memory */
+  ed_result_set= ed_connection.store_result_set();
+  uint count= ed_result_set->size();
+  delete ed_result_set;
+  return count;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Return a count of objects belonging to a given database.
+
+  This method returns the number of objects that match the database name
+  specified as @c db_name. 
+
+  @Note This method executes based on the current context of the THD
+        and thus returns a value based on the accessibility of objects
+        by the user context.
+
+  @param[in] THD     Current thread
+  @param[in] String  Database name.
+
+  @return uint Number of objects in the database.
+*/
+uint get_num_objects(THD *thd, const String *db_name)
+{
+  Ed_connection ed_connection(thd);
+  Ed_result_set *ed_result_set;
+  String_stream s_stream;
+
+  /*
+    Build query to select all objects from IS tables.
+  */
+  s_stream <<
+    "SELECT TABLE_NAME "
+    "FROM INFORMATION_SCHEMA.TABLES "
+    "WHERE table_schema = '" << db_name << "' UNION " 
+    "SELECT TRIGGER_NAME "
+    "FROM INFORMATION_SCHEMA.TRIGGERS "
+    "WHERE trigger_schema = '" << db_name << "' UNION " 
+    "SELECT ROUTINE_NAME "
+    "FROM INFORMATION_SCHEMA.ROUTINES "
+    "WHERE routine_schema = '" << db_name << "' UNION " 
+    "SELECT EVENT_NAME "
+    "FROM INFORMATION_SCHEMA.EVENTS "
+    "WHERE event_schema = '" << db_name << "'";
+
+  if (run_service_interface_sql(thd, &ed_connection, s_stream.lex_string()))
+    /* Query failed with an error */
+    return NULL;
+  else if(ed_connection.get_warn_count())
+    /* Push warnings to BACKUP's error stack. */
+    thd->warning_info->append_warnings(thd, ed_connection.get_warn_list());
+
+  DBUG_ASSERT(ed_connection.get_field_count());
+
+  /* Use store_result to get ownership of result memory */
+  ed_result_set= ed_connection.store_result_set();
+  uint count= ed_result_set->size();
+  delete ed_result_set;
+  return count;
+}
+
+///////////////////////////////////////////////////////////////////////////
+bool check_user_access(THD *thd, const String *db_name)
+{
+  uint elev_count;
+  uint user_count;
+
+  /*
+    Get value from user context without elevation.
+  */
+  if (!db_name) 
+    user_count= get_num_dbs(thd);
+  else 
+    user_count= get_num_objects(thd, db_name);
+
+  /* 
+    Peform global elevation with SELECT to get value of
+    someone with global SELECT (e.g. root).
+  */
+  ulong saved_master_access= thd->security_ctx->master_access; 
+  ulong saved_db_access= thd->security_ctx->db_access; 
+  thd->security_ctx->master_access |= (SELECT_ACL | TRIGGER_ACL | EVENT_ACL);
+
+  if (!db_name) 
+    elev_count= get_num_dbs(thd);
+  else 
+    elev_count= get_num_objects(thd, db_name);
+
+  /*
+    Turn elevation off and restore user access.
+  */
+  thd->security_ctx->master_access= saved_master_access; 
+  thd->security_ctx->db_access= saved_db_access; 
+
+  /*
+    Compare results and return.
+  */
+  return !(user_count == elev_count);
+}
+
+///////////////////////////////////////////////////////////////////////////
 Obj_iterator *get_db_tables(THD *thd, const String *db_name)
 {
   String_stream s_stream;

=== modified file 'sql/si_objects.h'
--- a/sql/si_objects.h	2009-05-05 17:42:58 +0000
+++ b/sql/si_objects.h	2009-07-15 14:18:59 +0000
@@ -164,7 +164,9 @@ Obj *get_database_stub(THD *thd, const S
 ///////////////////////////////////////////////////////////////////////////
 
 /**
-  Create an iterator over all databases in the server.
+  Create an iterator over the databases in the server that the user
+  can read with his current permissions.
+
   Includes system databases, such as "mysql" and "information_schema".
 
   The client is responsible for destruction of the returned iterator.
@@ -174,6 +176,29 @@ Obj *get_database_stub(THD *thd, const S
 Obj_iterator *get_databases(THD *thd);
 
 /**
+  Check user access to see all databases or objects in a given database.
+
+  This method can be used in two ways. 
+
+  1) If db_name = 0, the method shall check the user's visibility for all
+     databases excluding mysql and information_schema. 
+  2) If db_name != 0, the method shall check the user's visibility for all
+     objects in the database specified. 
+ 
+  @param[in] THD     The current thread.
+  @param[in] String  The database name to check or 0
+
+  @returns Information whether user can see all specified objects
+    @retval TRUE
+      if db_name != 0 : user does not have visibility to the database specified
+      if db_name == 0 : user does not have visibility to all databases
+    @retval FALSE
+      if db_name != 0 : user does have visibility to the database specified
+      if db_name == 0 : user does have visibility to all databases
+*/
+bool check_user_access(THD *thd, const String *db_name);
+
+/**
   Create an iterator over all base tables in a particular database.
   Temporary tables are not included.
 


Attachment: [text/bzr-bundle] bzr/charles.bell@sun.com-20090715141859-rnz1iv2kr9rd14uo.bundle
Thread
bzr commit into mysql-5.4 branch (charles.bell:2844) Bug#45889Chuck Bell15 Jul
  • Re: bzr commit into mysql-5.4 branch (charles.bell:2844) Bug#45889Rafal Somla15 Jul
    • Re: bzr commit into mysql-5.4 branch (charles.bell:2844) Bug#45889Charles Bell15 Jul