diff options
-rw-r--r-- | client/mysqldump.c | 2 | ||||
-rw-r--r-- | sql/sql_acl.cc | 9 | ||||
-rw-r--r-- | sql/sql_base.cc | 9 | ||||
-rw-r--r-- | sql/sql_parse.cc | 12 | ||||
-rw-r--r-- | tests/grant.pl | 13 | ||||
-rw-r--r-- | tests/grant.res | 15 |
6 files changed, 50 insertions, 10 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c index 3a66e49a795..459cb9fda31 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1454,7 +1454,7 @@ int main(int argc, char **argv) else { row = mysql_fetch_row(master); - if (row[0] && row[1]) + if (row && row[0] && row[1]) { fprintf(md_result_file, "\n--\n-- Position to start replication from\n--\n\n"); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 3332e596146..f01248bb682 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2520,8 +2520,8 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, } -bool check_grant_column (THD *thd,TABLE *table, const char *name, - uint length, uint show_tables) +bool check_grant_column(THD *thd,TABLE *table, const char *name, + uint length, uint show_tables) { GRANT_TABLE *grant_table; GRANT_COLUMN *grant_column; @@ -2529,6 +2529,8 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name, ulong want_access=table->grant.want_privilege; if (!want_access) return 0; // Already checked + if (!grant_option) + goto err2; pthread_mutex_lock(&LOCK_grant); @@ -2560,8 +2562,9 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name, #endif /* We must use my_printf_error() here! */ - err: +err: pthread_mutex_unlock(&LOCK_grant); +err2: if (!show_tables) { char command[128]; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f0aa8e9c351..03a1975b52a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1694,7 +1694,7 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, else thd->dupp_field=field; } - if (check_grants && check_grant_column(thd,table,name,length)) + if (check_grants && check_grant_column(thd,table,name,length)) return WRONG_GRANT; return field; } @@ -1719,8 +1719,8 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) { found_table=1; Field *find=find_field_in_table(thd,tables->table,name,length, - grant_option && - tables->table->grant.want_privilege, + test(tables->table->grant. + want_privilege), 1); if (find) { @@ -1760,8 +1760,7 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) for (; tables ; tables=tables->next) { Field *field=find_field_in_table(thd,tables->table,name,length, - grant_option && - tables->table->grant.want_privilege, + test(tables->table->grant.want_privilege), allow_rowid); if (field) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2b1c05bfaeb..73983bc03b1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2559,7 +2559,17 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if ((thd->master_access & want_access) == want_access) { - *save_priv=thd->master_access | thd->db_access; + /* + If we don't have a global SELECT privilege, we have to get the database + specific access rights to be able to handle queries of type + UPDATE t1 SET a=1 WHERE b > 0 + */ + db_access= thd->db_access; + if (!(thd->master_access & SELECT_ACL) && + (db && (!thd->db || strcmp(db,thd->db)))) + db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, + thd->priv_user, db); /* purecov: inspected */ + *save_priv=thd->master_access | db_access; DBUG_RETURN(FALSE); } if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) || diff --git a/tests/grant.pl b/tests/grant.pl index e32431ad63a..fb73be786b6 100644 --- a/tests/grant.pl +++ b/tests/grant.pl @@ -223,8 +223,21 @@ user_query("update $opt_database.test set b=b+1",1); safe_query("grant SELECT on *.* to $user"); user_connect(0); user_query("update $opt_database.test set b=b+1"); +user_query("update $opt_database.test set b=b+1 where a > 0"); safe_query("revoke SELECT on *.* from $user"); +safe_query("grant SELECT on $opt_database.* to $user"); user_connect(0); +user_query("update $opt_database.test set b=b+1"); +user_query("update $opt_database.test set b=b+1 where a > 0"); +safe_query("grant UPDATE on *.* to $user"); +user_connect(0); +user_query("update $opt_database.test set b=b+1"); +user_query("update $opt_database.test set b=b+1 where a > 0"); +safe_query("revoke UPDATE on *.* from $user"); +safe_query("revoke SELECT on $opt_database.* from $user"); +user_connect(0); +user_query("update $opt_database.test set b=b+1 where a > 0",1); +user_query("update $opt_database.test set b=b+1",1); # Add one privilege at a time until the user has all privileges user_query("select * from test",1); diff --git a/tests/grant.res b/tests/grant.res index a50f73740c6..7947ca692b6 100644 --- a/tests/grant.res +++ b/tests/grant.res @@ -200,8 +200,23 @@ Error in execute: SELECT command denied to user: 'grant_user@localhost' for colu grant SELECT on *.* to grant_user@localhost Connecting grant_user update grant_test.test set b=b+1 +update grant_test.test set b=b+1 where a > 0 revoke SELECT on *.* from grant_user@localhost +grant SELECT on grant_test.* to grant_user@localhost Connecting grant_user +update grant_test.test set b=b+1 +update grant_test.test set b=b+1 where a > 0 +grant UPDATE on *.* to grant_user@localhost +Connecting grant_user +update grant_test.test set b=b+1 +update grant_test.test set b=b+1 where a > 0 +revoke UPDATE on *.* from grant_user@localhost +revoke SELECT on grant_test.* from grant_user@localhost +Connecting grant_user +update grant_test.test set b=b+1 where a > 0 +Error in execute: select command denied to user: 'grant_user@localhost' for column 'a' in table 'test' +update grant_test.test set b=b+1 +Error in execute: select command denied to user: 'grant_user@localhost' for column 'b' in table 'test' select * from test Error in execute: select command denied to user: 'grant_user@localhost' for table 'test' grant select on grant_test.test to grant_user@localhost |