diff --git a/mysql-test/r/acl_roles_admin.result b/mysql-test/r/acl_roles_admin.result index 40e40909112..d92b1057736 100644 --- a/mysql-test/r/acl_roles_admin.result +++ b/mysql-test/r/acl_roles_admin.result @@ -2,9 +2,14 @@ create user foo@localhost; create role role1; create role role2 with admin current_user; create role role3 with admin current_role; +ERROR 0L000: Invalid definer +create role role3 with admin role1; create role role4 with admin root@localhost; create role role5 with admin foo@localhost; create role role6 with admin foo@bar; +ERROR HY000: The user specified as a definer ('foo'@'bar') does not exist +create user foo@bar; +create role role6 with admin foo@bar; create user bar with admin current_user; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'admin current_user' at line 1 grant role1 to foo@localhost with admin option; @@ -18,11 +23,14 @@ Grants for foo@localhost GRANT USAGE ON *.* TO 'foo'@'localhost' GRANT role1 TO 'foo'@'localhost' WITH ADMIN OPTION GRANT role2 TO 'foo'@'localhost' +GRANT role5 TO 'foo'@'localhost' WITH ADMIN OPTION show grants for role1; Grants for role1 GRANT USAGE ON *.* TO 'role1' GRANT USAGE ON *.* TO 'role2' +GRANT USAGE ON *.* TO 'role3' GRANT role2 TO 'role1' +GRANT role3 TO 'role1' WITH ADMIN OPTION show grants for role4; Grants for role4 GRANT USAGE ON *.* TO 'role3' @@ -31,20 +39,29 @@ GRANT role3 TO 'role4' WITH ADMIN OPTION select * from mysql.roles_mapping; Host User Role Admin_option role1 role2 N + role1 role3 Y role4 role3 Y +bar foo role6 Y localhost foo role1 Y localhost foo role2 N +localhost foo role5 Y +localhost root role1 Y +localhost root role2 Y +localhost root role4 Y flush privileges; show grants for foo@localhost; Grants for foo@localhost GRANT USAGE ON *.* TO 'foo'@'localhost' GRANT role1 TO 'foo'@'localhost' WITH ADMIN OPTION GRANT role2 TO 'foo'@'localhost' +GRANT role5 TO 'foo'@'localhost' WITH ADMIN OPTION show grants for role1; Grants for role1 GRANT USAGE ON *.* TO 'role1' GRANT USAGE ON *.* TO 'role2' +GRANT USAGE ON *.* TO 'role3' GRANT role2 TO 'role1' +GRANT role3 TO 'role1' WITH ADMIN OPTION show grants for role4; Grants for role4 GRANT USAGE ON *.* TO 'role3' @@ -58,11 +75,14 @@ show grants for foo@localhost; Grants for foo@localhost GRANT USAGE ON *.* TO 'foo'@'localhost' GRANT role2 TO 'foo'@'localhost' +GRANT role5 TO 'foo'@'localhost' WITH ADMIN OPTION show grants for role1; Grants for role1 GRANT USAGE ON *.* TO 'role1' GRANT USAGE ON *.* TO 'role2' +GRANT USAGE ON *.* TO 'role3' GRANT role2 TO 'role1' WITH ADMIN OPTION +GRANT role3 TO 'role1' WITH ADMIN OPTION show grants for role4; Grants for role4 GRANT USAGE ON *.* TO 'role3' @@ -71,22 +91,31 @@ GRANT role3 TO 'role4' select * from mysql.roles_mapping; Host User Role Admin_option role1 role2 Y + role1 role3 Y role4 role3 N +bar foo role6 Y localhost foo role2 N +localhost foo role5 Y +localhost root role1 Y +localhost root role2 Y +localhost root role4 Y flush privileges; show grants for foo@localhost; Grants for foo@localhost GRANT USAGE ON *.* TO 'foo'@'localhost' GRANT role2 TO 'foo'@'localhost' +GRANT role5 TO 'foo'@'localhost' WITH ADMIN OPTION show grants for role1; Grants for role1 GRANT USAGE ON *.* TO 'role1' GRANT USAGE ON *.* TO 'role2' +GRANT USAGE ON *.* TO 'role3' GRANT role2 TO 'role1' WITH ADMIN OPTION +GRANT role3 TO 'role1' WITH ADMIN OPTION show grants for role4; Grants for role4 GRANT USAGE ON *.* TO 'role3' GRANT USAGE ON *.* TO 'role4' GRANT role3 TO 'role4' drop role role1, role2, role3, role4, role5, role6; -drop user foo@localhost; +drop user foo@localhost, foo@bar; diff --git a/mysql-test/t/acl_roles_admin.test b/mysql-test/t/acl_roles_admin.test index a73cc0b4944..4be4652dcf8 100644 --- a/mysql-test/t/acl_roles_admin.test +++ b/mysql-test/t/acl_roles_admin.test @@ -6,9 +6,15 @@ create user foo@localhost; create role role1; create role role2 with admin current_user; +--error ER_MALFORMED_DEFINER create role role3 with admin current_role; +create role role3 with admin role1; create role role4 with admin root@localhost; create role role5 with admin foo@localhost; +--error ER_NO_SUCH_USER +create role role6 with admin foo@bar; + +create user foo@bar; create role role6 with admin foo@bar; --error ER_PARSE_ERROR @@ -62,5 +68,5 @@ show grants for role4; # cleanup ######################################## drop role role1, role2, role3, role4, role5, role6; -drop user foo@localhost; +drop user foo@localhost, foo@bar; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a527c2926d6..57063dd4f68 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -5404,9 +5404,6 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) DBUG_RETURN(TRUE); /* purecov: deadcode */ } - MEM_ROOT temp_root; - init_alloc_root(&temp_root, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); - while ((user= user_list++)) { role_as_user= NULL; @@ -5452,9 +5449,9 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) username= user->user.str; } - ROLE_GRANT_PAIR *hash_entry, *mapping= new (&temp_root) ROLE_GRANT_PAIR; + ROLE_GRANT_PAIR *hash_entry, *mapping= new (thd->mem_root) ROLE_GRANT_PAIR; - if (mapping->init(&temp_root, username, hostname, rolename, + if (mapping->init(thd->mem_root, username, hostname, rolename, thd->lex->with_admin_option)) continue; @@ -5549,8 +5546,6 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) } } - free_root(&temp_root, MYF(0)); - mysql_mutex_unlock(&acl_cache->lock); mysql_rwlock_unlock(&LOCK_grant); @@ -8949,7 +8944,7 @@ bool mysql_create_user(THD *thd, List &list, bool handle_as_role) { int result; String wrong_users; - LEX_USER *user_name; + LEX_USER *user_name, *admin; List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; bool some_users_created= FALSE; @@ -8963,6 +8958,32 @@ bool mysql_create_user(THD *thd, List &list, bool handle_as_role) mysql_rwlock_wrlock(&LOCK_grant); mysql_mutex_lock(&acl_cache->lock); + if (handle_as_role) + { + if (thd->lex->definer) + admin= get_current_user(thd, thd->lex->definer, false); + else + admin= create_default_definer(thd, false); + if (!admin) + { + mysql_mutex_unlock(&acl_cache->lock); + mysql_rwlock_unlock(&LOCK_grant); + DBUG_RETURN(TRUE); + } + bool exists; + if (admin->is_role()) + exists= find_acl_role(admin->user.str); + else + exists= find_user_no_anon(admin->host.str, admin->user.str, TRUE); + if (!exists) + { + my_error(ER_NO_SUCH_USER, MYF(0), admin->user.str, admin->host.str); + mysql_mutex_unlock(&acl_cache->lock); + mysql_rwlock_unlock(&LOCK_grant); + DBUG_RETURN(TRUE); + } + } + while ((user_name= user_list++)) { if (!user_name->host.str) @@ -8985,6 +9006,27 @@ bool mysql_create_user(THD *thd, List &list, bool handle_as_role) { append_user(&wrong_users, user_name); result= TRUE; + continue; + } + + // every created role is automatically granted to its creator-admin + if (handle_as_role) + { + ROLE_GRANT_PAIR *pair= new (thd->mem_root) ROLE_GRANT_PAIR; + + if (pair->init(thd->mem_root, admin->user.str, admin->host.str, + user_name->user.str, true)) + { + result= TRUE; + break; + } + add_role_user_mapping(pair); + if (replace_roles_mapping_table(tables[6].table, pair, NULL, false)) + { + append_user(&wrong_users, user_name); + remove_role_user_mapping(pair); + result= TRUE; + } } }