Commit ad5ddaff authored by Vicentiu Ciorbaru's avatar Vicentiu Ciorbaru Committed by Sergei Golubchik

Fix for:

MDEV-5221: User auto-creation does not work upon GRANT <role>
parent 1df23d6f
create database db;
create role auto_create;
grant all on db.* to auto_create;
drop user foo@localhost, bar@localhost;
grant auto_create to foo@localhost;
grant auto_create to bar@localhost identified by 'baz';
set role 'auto_create';
use db;
create table t1 (i int);
set role auto_create;
use db;
insert into t1 values (1);
drop user foo@localhost, bar@localhost;
set sql_mode = 'no_auto_create_user';
grant auto_create to foo@localhost;
ERROR 28000: Can't find any matching row in the user table
grant auto_create to bar@localhost identified by 'baz';
select user, host from mysql.user where user = 'bar';
user host
bar localhost
set sql_mode = '';
set role auto_create;
use db;
drop table t1;
create user foo@localhost;
set sql_mode = '';
grant auto_create to bar2@localhost;
ERROR 28000: Access denied for user 'foo'@'localhost'
grant auto_create to foo2@localhost;
ERROR 28000: Access denied for user 'foo'@'localhost'
set sql_mode = 'no_auto_create_user';
grant auto_create to bar2@localhost;
ERROR 28000: Access denied for user 'foo'@'localhost'
grant auto_create to foo2@localhost identified by 'pass';
ERROR 28000: Access denied for user 'foo'@'localhost'
grant auto_create to foo@localhost;
set sql_mode = '';
grant auto_create to bar@localhost;
ERROR 28000: Access denied for user 'foo'@'localhost'
grant auto_create to bar2@localhost;
ERROR 28000: Access denied for user 'foo'@'localhost'
grant auto_create to foo2@localhost identified by 'pass';
ERROR 28000: Access denied for user 'foo'@'localhost'
set sql_mode = 'no_auto_create_user';
grant auto_create to bar2@localhost;
ERROR 28000: Access denied for user 'foo'@'localhost'
grant auto_create to foo2@localhost identified by 'pass';
ERROR 28000: Access denied for user 'foo'@'localhost'
grant auto_create to foo@localhost with admin option;
set sql_mode = '';
grant auto_create to bar@localhost;
grant auto_create to bar2@localhost;
ERROR 42000: You are not allowed to create a user with GRANT
grant auto_create to foo2@localhost identified by 'pass';
ERROR 42000: You are not allowed to create a user with GRANT
set sql_mode = 'no_auto_create_user';
grant auto_create to bar2@localhost;
ERROR 28000: Can't find any matching row in the user table
grant auto_create to foo2@localhost identified by 'pass';
ERROR 42000: You are not allowed to create a user with GRANT
drop user foo@localhost;
drop user bar@localhost;
drop role auto_create;
drop database db;
create database db;
create role auto_create;
grant all on db.* to auto_create;
--error 0,ER_CANNOT_USER
drop user foo@localhost, bar@localhost;
grant auto_create to foo@localhost;
grant auto_create to bar@localhost identified by 'baz';
# Test if the users have been created and the role has been granted to them
--connect (con1,localhost,foo,,)
set role 'auto_create';
use db;
create table t1 (i int);
--disconnect con1
--connect (con1,localhost,bar,baz,)
set role auto_create;
use db;
insert into t1 values (1);
--disconnect con1
--connection default
drop user foo@localhost, bar@localhost;
set sql_mode = 'no_auto_create_user';
--error ER_PASSWORD_NO_MATCH
grant auto_create to foo@localhost;
grant auto_create to bar@localhost identified by 'baz';
select user, host from mysql.user where user = 'bar';
set sql_mode = '';
--connect (con1,localhost,bar,baz,)
set role auto_create;
use db;
drop table t1;
--disconnect con1
--connection default
create user foo@localhost;
# test all possible cases with a user who has no rights to grant the role
--connect (con1, localhost, foo,,)
set sql_mode = '';
#try and grant roles, no rights however
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
grant auto_create to bar2@localhost;
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
grant auto_create to foo2@localhost;
set sql_mode = 'no_auto_create_user';
#try and grant roles, no rights however
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
grant auto_create to bar2@localhost;
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
grant auto_create to foo2@localhost identified by 'pass';
--disconnect con1
--connection default
grant auto_create to foo@localhost;
--connect (con1, localhost, foo,,)
#we now have the role granted to us, but we don't have insert privileges,
#we should not be able to create a new user
set sql_mode = '';
#also test that we can not grant a role without admin option
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
grant auto_create to bar@localhost;
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
grant auto_create to bar2@localhost;
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
grant auto_create to foo2@localhost identified by 'pass';
set sql_mode = 'no_auto_create_user';
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
grant auto_create to bar2@localhost;
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
grant auto_create to foo2@localhost identified by 'pass';
#test that we can grant a role with admin option to an existing user, but not
#create one
--connection default
grant auto_create to foo@localhost with admin option;
--disconnect con1
--connect (con1, localhost, foo,,)
#we now have the role granted to us, but we don't have insert privileges,
#we should not be able to create a new user
set sql_mode = '';
#also test that we can grant a role with admin option
grant auto_create to bar@localhost;
#test that we don't create users if we don't have insert privileges
--error ER_CANT_CREATE_USER_WITH_GRANT
grant auto_create to bar2@localhost;
--error ER_CANT_CREATE_USER_WITH_GRANT
grant auto_create to foo2@localhost identified by 'pass';
set sql_mode = 'no_auto_create_user';
--error ER_PASSWORD_NO_MATCH
grant auto_create to bar2@localhost;
--error ER_CANT_CREATE_USER_WITH_GRANT
grant auto_create to foo2@localhost identified by 'pass';
--connection default
drop user foo@localhost;
drop user bar@localhost;
drop role auto_create;
drop database db;
......@@ -5844,6 +5844,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
*/
DBUG_ASSERT(list.elements >= 2);
bool result= 0;
bool create_new_user, no_auto_create_user;
String wrong_users;
LEX_USER *user, *granted_role;
LEX_STRING rolename;
......@@ -5859,12 +5860,18 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
DBUG_ASSERT(granted_role->is_role());
rolename= granted_role->user;
TABLE_LIST tables;
tables.init_one_table(C_STRING_WITH_LEN("mysql"),
create_new_user= test_if_create_new_users(thd);
no_auto_create_user= test(thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER);
TABLE_LIST tables[2];
tables[0].init_one_table(C_STRING_WITH_LEN("mysql"),
C_STRING_WITH_LEN("roles_mapping"),
"roles_mapping", TL_WRITE);
tables[1].init_one_table(C_STRING_WITH_LEN("mysql"),
C_STRING_WITH_LEN("user"), "user", TL_WRITE);
tables[0].next_local= tables[0].next_global= tables+1;
if (open_and_lock_tables(thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
if (open_and_lock_tables(thd, tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
DBUG_RETURN(TRUE); /* purecov: deadcode */
mysql_rwlock_wrlock(&LOCK_grant);
......@@ -5952,6 +5959,27 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
if (!grantee)
grantee= find_user_exact(hostname.str, username.str);
if (!grantee && !revoke)
{
LEX_USER user_combo = *user;
user_combo.host = hostname;
user_combo.user = username;
/* create the user if it does not exist */
if (replace_user_table(thd, tables[1].table, user_combo, 0,
false, create_new_user,
no_auto_create_user))
{
append_user(&wrong_users, username.str, hostname.str);
result= 1;
continue;
}
grantee= find_user_exact(hostname.str, username.str);
/* either replace_user_table failed, or we've added the user */
DBUG_ASSERT(grantee);
}
if (!grantee)
{
append_user(&wrong_users, username.str, hostname.str);
......@@ -6004,7 +6032,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
}
/* write into the roles_mapping table */
if (replace_roles_mapping_table(tables.table,
if (replace_roles_mapping_table(tables[0].table,
&username, &hostname, &rolename,
thd->lex->with_admin_option,
hash_entry, revoke))
......
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