Fixed two bugs in MySQL ACL.

First one is related to Bug#7905. One should not be allowed to
create new user with password without UPDATE privilege to
MySQL database. Furthermore, executing the same GRANT statement
twice would actually crash the server and corrupt privilege database.

Other bug was that one could update a column, using the existing
value as basis to calculate the new value (e.g. UPDATE t1 SET a=a+1)
without SELECT privilege to the field (a in the above example)

Fixed tests grant.pl and grant2, which were wrong.
parent ddec400e
...@@ -23,6 +23,7 @@ grant select on `my\_1`.* to mysqltest_4@localhost with grant option; ...@@ -23,6 +23,7 @@ grant select on `my\_1`.* to mysqltest_4@localhost with grant option;
ERROR 42000: 'mysqltest_1'@'localhost' is not allowed to create new users ERROR 42000: 'mysqltest_1'@'localhost' is not allowed to create new users
grant select on `my\_1`.* to mysqltest_4@localhost identified by 'mypass' grant select on `my\_1`.* to mysqltest_4@localhost identified by 'mypass'
with grant option; with grant option;
ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysql'
show grants for mysqltest_1@localhost; show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
......
...@@ -36,6 +36,7 @@ set @@sql_mode='NO_AUTO_CREATE_USER'; ...@@ -36,6 +36,7 @@ set @@sql_mode='NO_AUTO_CREATE_USER';
select @@sql_mode; select @@sql_mode;
--error 1211 --error 1211
grant select on `my\_1`.* to mysqltest_4@localhost with grant option; grant select on `my\_1`.* to mysqltest_4@localhost with grant option;
--error 1044
grant select on `my\_1`.* to mysqltest_4@localhost identified by 'mypass' grant select on `my\_1`.* to mysqltest_4@localhost identified by 'mypass'
with grant option; with grant option;
disconnect user1; disconnect user1;
......
...@@ -1642,17 +1642,6 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, ...@@ -1642,17 +1642,6 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
} }
else else
{ {
/*
Check that the user isn't trying to change a password for another
user if he doesn't have UPDATE privilege to the MySQL database
*/
DBUG_ASSERT(combo.host.str != 0);
if (thd->user && combo.password.str &&
(strcmp(thd->user,combo.user.str) ||
my_strcasecmp(system_charset_info,
combo.host.str, thd->host_or_ip)) &&
check_access(thd, UPDATE_ACL, "mysql",0,1,0))
goto end;
old_row_exists = 1; old_row_exists = 1;
store_record(table,record[1]); // Save copy for update store_record(table,record[1]); // Save copy for update
if (combo.password.str) // If password given if (combo.password.str) // If password given
......
...@@ -3626,6 +3626,24 @@ mysql_execute_command(THD *thd) ...@@ -3626,6 +3626,24 @@ mysql_execute_command(THD *thd)
first_table ? 0 : 1, 0)) first_table ? 0 : 1, 0))
goto error; goto error;
if (thd->user) // If not replication
{
LEX_USER *user;
List_iterator <LEX_USER> user_list(lex->users_list);
while ((user=user_list++))
{
if (user->password.str &&
strcmp(thd->user, user->user.str) ||
user->host.str &&
my_strcasecmp(system_charset_info,
user->host.str, thd->host_or_ip))
{
if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 0))
goto error;
break; // We are allowed to do changes
}
}
}
if (specialflag & SPECIAL_NO_RESOLVE) if (specialflag & SPECIAL_NO_RESOLVE)
{ {
LEX_USER *user; LEX_USER *user;
......
...@@ -219,7 +219,7 @@ int mysql_update(THD *thd, ...@@ -219,7 +219,7 @@ int mysql_update(THD *thd,
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */ /* Check values */
table_list->grant.want_privilege= table->grant.want_privilege= table_list->grant.want_privilege= table->grant.want_privilege=
(SELECT_ACL & ~~table->grant.privilege); (SELECT_ACL & ~table->grant.privilege);
#endif #endif
if (setup_fields(thd, 0, table_list, values, 1, 0, 0)) if (setup_fields(thd, 0, table_list, values, 1, 0, 0))
{ {
......
...@@ -201,7 +201,7 @@ safe_query("select * from mysql.db where user = '$opt_user'"); ...@@ -201,7 +201,7 @@ safe_query("select * from mysql.db where user = '$opt_user'");
safe_query("grant CREATE,UPDATE,DROP on $opt_database.* to $user"); safe_query("grant CREATE,UPDATE,DROP on $opt_database.* to $user");
user_connect(0); user_connect(0);
user_query("create table $opt_database.test2 (a int not null)"); user_query("create table $opt_database.test2 (a int not null)");
user_query("update test,test2 SET test.a=1 where 1"); user_query("update test,test2 SET test.a=1 where 1",1);
user_query("update test,test2 SET test.a=test2.a where 1",1); user_query("update test,test2 SET test.a=test2.a where 1",1);
safe_query("grant SELECT on $opt_database.* to $user"); safe_query("grant SELECT on $opt_database.* to $user");
user_connect(0); user_connect(0);
...@@ -375,7 +375,7 @@ user_query("delete from $opt_database.test where a=2"); ...@@ -375,7 +375,7 @@ user_query("delete from $opt_database.test where a=2");
user_query("delete from $opt_database.test where A=2"); user_query("delete from $opt_database.test where A=2");
user_query("update test set b=5 where b>0"); user_query("update test set b=5 where b>0");
user_query("update test set a=11 where b>5",1); user_query("update test set a=11 where b>5",1);
user_query("update test,test2 SET test.b=5 where b>0"); user_query("update test,test2 SET test.b=5 where b>0",1);
user_query("update test,test2 SET test.a=11 where b>0",1); user_query("update test,test2 SET test.a=11 where b>0",1);
user_query("update test,test2 SET test.b=test2.a where b>0",1); user_query("update test,test2 SET test.b=test2.a where b>0",1);
user_query("update test,test2 SET test.b=11 where test2.a>0",1); user_query("update test,test2 SET test.b=11 where test2.a>0",1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment