From 40a0199e77aa5305a6699b0572e8d913eea8d170 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Dec 2004 21:01:11 +0100 Subject: [PATCH 1/2] unsufficient privilege checks in GRANT, when a grantor has column-level privileges --- mysql-test/r/alter_table.result | 2 +- mysql-test/r/grant.result | 2 +- mysql-test/r/grant_cache.result | 6 +- sql/sql_acl.cc | 100 ++++++++++++++++---------------- 4 files changed, 55 insertions(+), 55 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index e7a8d2c7cdf..78925a64e93 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -121,7 +121,7 @@ create database mysqltest; create table mysqltest.t1 (a int,b int,c int); grant all on mysqltest.t1 to mysqltest_1@localhost; alter table t1 rename t2; -insert command denied to user: 'mysqltest_1@localhost' for table 't2' +INSERT,CREATE command denied to user: 'mysqltest_1@localhost' for table 't2' revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user='mysqltest_1'; drop database mysqltest; diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 19d83a95c5e..9df50a242d7 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -198,7 +198,7 @@ GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost' update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; UPDATE command denied to user: 'mysqltest_3@localhost' for column 'q' in table 't1' update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1; -select command denied to user: 'mysqltest_3@localhost' for table 't1' +SELECT command denied to user: 'mysqltest_3@localhost' for table 't1' update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1; UPDATE command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1' update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2; diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result index 96eb9d2bc62..e31294154bb 100644 --- a/mysql-test/r/grant_cache.result +++ b/mysql-test/r/grant_cache.result @@ -121,7 +121,7 @@ a b c a 1 1 1 test.t1 2 2 2 test.t1 select * from t2; -select command denied to user: 'mysqltest_2@localhost' for table 't2' +SELECT command denied to user: 'mysqltest_2@localhost' for table 't2' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 6 @@ -135,7 +135,7 @@ select "user3"; user3 user3 select * from t1; -select command denied to user: 'mysqltest_3@localhost' for column 'b' in table 't1' +SELECT command denied to user: 'mysqltest_3@localhost' for column 'b' in table 't1' select a from t1; a 1 @@ -143,7 +143,7 @@ a select c from t1; SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1' select * from t2; -select command denied to user: 'mysqltest_3@localhost' for table 't2' +SELECT command denied to user: 'mysqltest_3@localhost' for table 't2' select mysqltest.t1.c from test.t1,mysqltest.t1; SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1' show status like "Qcache_queries_in_cache"; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1b55168695b..c883407970a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2134,37 +2134,57 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(-1); } - if (columns.elements && !revoke_grant) + if (!revoke_grant) { - TABLE *table; - class LEX_COLUMN *column; - List_iterator column_iter(columns); + if (columns.elements && !revoke_grant) + { + TABLE *table; + class LEX_COLUMN *column; + List_iterator column_iter(columns); - if (!(table=open_ltable(thd,table_list,TL_READ))) - DBUG_RETURN(-1); - while ((column = column_iter++)) - { - if (!find_field_in_table(thd,table,column->column.ptr(), - column->column.length(),0,0)) + if (!(table=open_ltable(thd,table_list,TL_READ))) + DBUG_RETURN(-1); + while ((column = column_iter++)) { - my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), - column->column.c_ptr(), table_list->alias); - DBUG_RETURN(-1); + Field *f= find_field_in_table(thd,table,column->column.ptr(), + column->column.length(),1,0); + if (!f) + { + my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), + column->column.c_ptr(), table_list->alias); + DBUG_RETURN(-1); + } + if (f == (Field*)-1) + { + DBUG_RETURN(-1); + } + column_priv|= column->rights; } - column_priv|= column->rights; + close_thread_tables(thd); } - close_thread_tables(thd); - } - else if (!(rights & CREATE_ACL) && !revoke_grant) - { - char buf[FN_REFLEN]; - sprintf(buf,"%s/%s/%s.frm",mysql_data_home, table_list->db, - table_list->real_name); - fn_format(buf,buf,"","",4+16+32); - if (access(buf,F_OK)) + else { - my_error(ER_NO_SUCH_TABLE,MYF(0),table_list->db, table_list->alias); - DBUG_RETURN(-1); + if (!(rights & CREATE_ACL)) + { + char buf[FN_REFLEN]; + sprintf(buf,"%s/%s/%s.frm",mysql_data_home, table_list->db, + table_list->real_name); + fn_format(buf,buf,"","",4+16+32); + if (access(buf,F_OK)) + { + my_error(ER_NO_SUCH_TABLE,MYF(0),table_list->db, table_list->alias); + DBUG_RETURN(-1); + } + } + if (table_list->grant.want_privilege) + { + char command[128]; + get_privilege_desc(command, sizeof(command), + table_list->grant.want_privilege); + my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), + command, thd->priv_user, thd->host_or_ip, table_list->alias); + DBUG_RETURN(-1); + } } } @@ -2189,7 +2209,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, */ if (thd->slave_thread && table_rules_on) { - /* + /* The tables must be marked "updating" so that tables_ok() takes them into account in tests. */ @@ -2636,25 +2656,8 @@ err: pthread_mutex_unlock(&LOCK_grant); if (!no_errors) // Not a silent skip of table { - const char *command=""; - if (want_access & SELECT_ACL) - command ="select"; - else if (want_access & INSERT_ACL) - command = "insert"; - else if (want_access & UPDATE_ACL) - command = "update"; - else if (want_access & DELETE_ACL) - command = "delete"; - else if (want_access & DROP_ACL) - command = "drop"; - else if (want_access & CREATE_ACL) - command = "create"; - else if (want_access & ALTER_ACL) - command = "alter"; - else if (want_access & INDEX_ACL) - command = "index"; - else if (want_access & GRANT_ACL) - command = "grant"; + char command[128]; + get_privilege_desc(command, sizeof(command), want_access); net_printf(&thd->net,ER_TABLEACCESS_DENIED_ERROR, command, thd->priv_user, @@ -2767,11 +2770,8 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) err: pthread_mutex_unlock(&LOCK_grant); - const char *command=""; - if (want_access & SELECT_ACL) - command ="select"; - else if (want_access & INSERT_ACL) - command = "insert"; + char command[128]; + get_privilege_desc(command, sizeof(command), want_access); my_printf_error(ER_COLUMNACCESS_DENIED_ERROR, ER(ER_COLUMNACCESS_DENIED_ERROR), MYF(0), From 5eaf65ab4be77911eb03cceefac9ecea48c25f71 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 31 Dec 2004 11:52:14 +0100 Subject: [PATCH 2/2] post-merge mysql-test/r/grant2.result: new test case mysql-test/r/variables.result: don't fail w/o innodb mysql-test/t/grant2.test: new test case mysql-test/t/multi_update.test: don't fail w/o innodb mysql-test/t/variables.test: don't fail w/o innodb sql/sql_acl.cc: cleanup --- mysql-test/r/alter_table.result | 2 +- mysql-test/r/grant2.result | 17 ++++++++++++++--- mysql-test/r/grant_cache.result | 6 +++--- mysql-test/r/ps_1general.result | 4 ++-- mysql-test/r/timezone2.result | 4 ++-- mysql-test/r/variables.result | 6 +++--- mysql-test/t/grant2.test | 28 ++++++++++++++++++++++++---- mysql-test/t/multi_update.test | 2 ++ mysql-test/t/variables.test | 4 ++-- sql/sql_acl.cc | 3 +-- 10 files changed, 54 insertions(+), 22 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 5a47110dda3..a7ae8bc310c 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -121,7 +121,7 @@ create database mysqltest; create table mysqltest.t1 (a int,b int,c int); grant all on mysqltest.t1 to mysqltest_1@localhost; alter table t1 rename t2; -ERROR 42000: INSERT,CREATE command denied to user: 'mysqltest_1@localhost' for table 't2' +ERROR 42000: INSERT,CREATE command denied to user 'mysqltest_1'@'localhost' for table 't2' revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index a31fa2ac3dc..6d8bdbaf8f9 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -37,7 +37,6 @@ show grants for current_user(); Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' GRANT SELECT, INSERT ON `mysqltest`.* TO 'mysqltest_1'@'localhost' -use mysqltest; insert into t1 values (1, 'I can''t change it!'); update t1 set data='I can change it!' where id = 1; ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysqltest' @@ -47,8 +46,20 @@ select * from t1; id data 1 I can't change it! drop table t1; -drop database mysqltest; -use test; delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; flush privileges; +create table t1 (a int, b int); +grant select (a) on t1 to mysqltest_1@localhost with grant option; +grant select (a,b) on t1 to mysqltest_2@localhost; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 't1' +grant select on t1 to mysqltest_3@localhost; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1' +drop table t1; +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; +drop database mysqltest; +use test; diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result index b3e16f1fcf0..d905e9319fd 100644 --- a/mysql-test/r/grant_cache.result +++ b/mysql-test/r/grant_cache.result @@ -134,7 +134,7 @@ a b c a 1 1 1 test.t1 2 2 2 test.t1 select * from t2; -ERROR 42000: SELECT command denied to user: 'mysqltest_2@localhost' for table 't2' +ERROR 42000: SELECT command denied to user 'mysqltest_2'@'localhost' for table 't2' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 6 @@ -148,7 +148,7 @@ select "user3"; user3 user3 select * from t1; -ERROR 42000: SELECT command denied to user: 'mysqltest_3@localhost' for column 'b' in table 't1' +ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'b' in table 't1' select a from t1; a 1 @@ -156,7 +156,7 @@ a select c from t1; ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'c' in table 't1' select * from t2; -ERROR 42000: SELECT command denied to user: 'mysqltest_3@localhost' for table 't2' +ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 't2' select mysqltest.t1.c from test.t1,mysqltest.t1; ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'c' in table 't1' show status like "Qcache_queries_in_cache"; diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 5f8cb2597c6..25b9e2dcda4 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -834,7 +834,7 @@ execute s_t9 ; my_col 1 select a as my_col from t1; -ERROR 42000: select command denied to user 'second_user'@'localhost' for table 't1' +ERROR 42000: SELECT command denied to user 'second_user'@'localhost' for table 't1' grant select on mysqltest.t1 to second_user@localhost identified by 'looser' ; show grants for second_user@localhost ; @@ -873,7 +873,7 @@ Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' execute s_t1 ; -ERROR 42000: select command denied to user 'second_user'@'localhost' for table 't1' +ERROR 42000: SELECT command denied to user 'second_user'@'localhost' for table 't1' revoke all privileges, grant option from second_user@localhost ; show grants for second_user@localhost ; Grants for second_user@localhost diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result index 1c98fd18a08..a1a2fec739f 100644 --- a/mysql-test/r/timezone2.result +++ b/mysql-test/r/timezone2.result @@ -295,9 +295,9 @@ convert_tz(b, 'Europe/Moscow', 'UTC') update t1, t2 set t1.b = convert_tz('2004-11-30 12:00:00', 'Europe/Moscow', 'UTC') where t1.a = t2.c and t2.d = (select max(d) from t2); select * from mysql.time_zone_name; -ERROR 42000: select command denied to user 'mysqltest_1'@'localhost' for table 'time_zone_name' +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'time_zone_name' select Name, convert_tz('2004-11-30 12:00:00', Name, 'UTC') from mysql.time_zone_name; -ERROR 42000: select command denied to user 'mysqltest_1'@'localhost' for table 'time_zone_name' +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'time_zone_name' delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; delete from mysql.tables_priv where user like 'mysqltest\_%'; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 01db98648bd..6b700f7f6a2 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -115,13 +115,13 @@ set global concurrent_insert=DEFAULT; show variables like 'concurrent_insert'; Variable_name Value concurrent_insert ON -set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="INNODB"; +set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="MERGE"; show local variables like 'storage_engine'; Variable_name Value storage_engine HEAP show global variables like 'storage_engine'; Variable_name Value -storage_engine InnoDB +storage_engine MERGE set GLOBAL query_cache_size=100000; set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; @@ -220,7 +220,7 @@ set max_join_size="hello"; ERROR 42000: Incorrect argument type to variable 'max_join_size' set storage_engine=UNKNOWN_TABLE_TYPE; ERROR 42000: Unknown table engine 'UNKNOWN_TABLE_TYPE' -set storage_engine=INNODB, big_tables=2; +set storage_engine=MERGE, big_tables=2; ERROR 42000: Variable 'big_tables' can't be set to the value of '2' show local variables like 'storage_engine'; Variable_name Value diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index f86be0c95b9..7060d35e9a4 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -50,10 +50,9 @@ flush privileges; use mysqltest; create table t1 (id int primary key, data varchar(255)); -connect (mrbad, localhost, mysqltest_1,,); +connect (mrbad, localhost, mysqltest_1,,mysqltest); connection mrbad; show grants for current_user(); -use mysqltest; insert into t1 values (1, 'I can''t change it!'); --error 1044 update t1 set data='I can change it!' where id = 1; @@ -61,11 +60,32 @@ update t1 set data='I can change it!' where id = 1; --error 1044 insert into t1 values (1, 'XXX') on duplicate key update data= 'I can change it!'; select * from t1; +disconnect mrbad; connection default; drop table t1; -drop database mysqltest; -use test; delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; flush privileges; + +create table t1 (a int, b int); +grant select (a) on t1 to mysqltest_1@localhost with grant option; +connect (mrugly, localhost, mysqltest_1,,mysqltest); +connection mrugly; +--error 1143 +grant select (a,b) on t1 to mysqltest_2@localhost; +--error 1142 +grant select on t1 to mysqltest_3@localhost; +disconnect mrugly; + +connection default; +drop table t1; +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; + +drop database mysqltest; +use test; + diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index e90de399500..4035099ec7e 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -433,6 +433,7 @@ delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2 drop table t1,t2; # Test for BUG#5837 - delete with outer join and const tables +--disable_warnings create table t1 ( aclid bigint not null primary key, status tinyint(1) not null @@ -442,6 +443,7 @@ create table t2 ( refid bigint not null primary key, aclid bigint, index idx_acl(aclid) ) engine = innodb; +--enable_warnings insert into t2 values(1,null); delete t2, t1 from t2 left join t1 on (t2.aclid=t1.aclid) where t2.refid='1'; drop table t1, t2; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 7dc07f9313e..3a76ae5136e 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -71,7 +71,7 @@ show variables like 'concurrent_insert'; set global concurrent_insert=DEFAULT; show variables like 'concurrent_insert'; -set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="INNODB"; +set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="MERGE"; show local variables like 'storage_engine'; show global variables like 'storage_engine'; set GLOBAL query_cache_size=100000; @@ -128,7 +128,7 @@ set max_join_size="hello"; --error 1286 set storage_engine=UNKNOWN_TABLE_TYPE; --error 1231 -set storage_engine=INNODB, big_tables=2; +set storage_engine=MERGE, big_tables=2; show local variables like 'storage_engine'; --error 1229 set SESSION query_cache_size=10000; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 5579aa9b3f5..2c11d1c87ad 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -964,9 +964,8 @@ static void acl_insert_db(const char *user, const char *host, const char *db, ulong acl_get(const char *host, const char *ip, const char *user, const char *db, my_bool db_is_pattern) { - ulong host_access,db_access; + ulong host_access= ~0,db_access= 0; uint i,key_length; - db_access=0; host_access= ~0; char key[ACL_KEY_LENGTH],*tmp_db,*end; acl_entry *entry; DBUG_ENTER("acl_get");