diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index e8c3fbff0e3..7e89867963a 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -647,3 +647,17 @@ ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for r # Connection 'default'. drop user bug12602983_user@localhost; drop database mysqltest_db; +set password=password('foobar'); +create procedure sp1() select 1; +show grants; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*9B500343BC52E2911172EB52AE5CF4847604C6E5' WITH GRANT OPTION +GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION +grant execute on procedure sp1 to current_user() identified by 'barfoo'; +show grants; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*343915A8181B5728EADBDC73E1F7E6B0C3998483' WITH GRANT OPTION +GRANT EXECUTE ON PROCEDURE `test`.`sp1` TO 'root'@'localhost' +GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION +drop procedure sp1; +set password=''; diff --git a/mysql-test/suite/roles/grant_revoke_current.result b/mysql-test/suite/roles/grant_revoke_current.result index 644454685b4..d9798463965 100644 --- a/mysql-test/suite/roles/grant_revoke_current.result +++ b/mysql-test/suite/roles/grant_revoke_current.result @@ -24,4 +24,19 @@ revoke all, grant option from current_role; show grants for current_role; Grants for r1 GRANT USAGE ON *.* TO 'r1' +set password=password('foobar'); +show grants; +Grants for root@localhost +GRANT r1 TO 'root'@'localhost' WITH ADMIN OPTION +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*9B500343BC52E2911172EB52AE5CF4847604C6E5' WITH GRANT OPTION +GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION +GRANT USAGE ON *.* TO 'r1' +grant r1 to current_user() identified by 'barfoo'; +show grants; +Grants for root@localhost +GRANT r1 TO 'root'@'localhost' WITH ADMIN OPTION +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*343915A8181B5728EADBDC73E1F7E6B0C3998483' WITH GRANT OPTION +GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION +GRANT USAGE ON *.* TO 'r1' +set password=''; drop role r1; diff --git a/mysql-test/suite/roles/grant_revoke_current.test b/mysql-test/suite/roles/grant_revoke_current.test index 96a27fd5697..0ebe0170782 100644 --- a/mysql-test/suite/roles/grant_revoke_current.test +++ b/mysql-test/suite/roles/grant_revoke_current.test @@ -20,5 +20,10 @@ show grants for current_role; revoke all, grant option from current_role; show grants for current_role; -drop role r1; +set password=password('foobar'); +show grants; +grant r1 to current_user() identified by 'barfoo'; +show grants; +set password=''; +drop role r1; diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index a2079e91440..0646e727232 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -1040,3 +1040,11 @@ drop database mysqltest_db; # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc +set password=password('foobar'); +create procedure sp1() select 1; +show grants; +grant execute on procedure sp1 to current_user() identified by 'barfoo'; +show grants; +drop procedure sp1; +set password=''; + diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e1e075df6d6..28b6067b32f 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -5596,6 +5596,14 @@ static bool merge_one_role_privileges(ACL_ROLE *grantee) End of the role privilege propagation and graph traversal code ******************************************************************/ +static bool has_auth(LEX_USER *user, LEX *lex) +{ + return user->password.str || user->plugin.length || user->auth.length || + lex->ssl_type != SSL_TYPE_NOT_SPECIFIED || lex->ssl_cipher || + lex->x509_issuer || lex->x509_subject || + lex->mqh.specified_limits; +} + static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, LEX *lex) { if (to != from) @@ -5606,20 +5614,11 @@ static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, LEX *lex) to->auth= from->auth; } - /* - Note, that no password is null_lex_str, while no plugin is empty_lex_str. - See sql_yacc.yy - */ - bool has_auth= to->password.str || to->plugin.length || to->auth.length || - lex->ssl_type != SSL_TYPE_NOT_SPECIFIED || lex->ssl_cipher || - lex->x509_issuer || lex->x509_subject || - lex->mqh.specified_limits; - /* Specifying authentication clauses forces the name to be interpreted as a user, not a role. See also check_change_password() */ - if (to->is_role() && has_auth) + if (to->is_role() && has_auth(to, lex)) { my_error(ER_PASSWORD_NO_MATCH, MYF(0)); return true; @@ -5937,7 +5936,6 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, while ((tmp_Str= str_list++)) { - int error; GRANT_NAME *grant_name; if (!(Str= get_current_user(thd, tmp_Str, false))) { @@ -5945,14 +5943,14 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, continue; } /* Create user if needed */ - error=replace_user_table(thd, tables[USER_TABLE].table, *Str, - 0, revoke_grant, create_new_users, - MY_TEST(thd->variables.sql_mode & - MODE_NO_AUTO_CREATE_USER)); - if (error) + if (copy_and_check_auth(Str, tmp_Str, thd->lex) || + replace_user_table(thd, tables[USER_TABLE].table, *Str, + 0, revoke_grant, create_new_users, + MY_TEST(thd->variables.sql_mode & + MODE_NO_AUTO_CREATE_USER))) { - result= TRUE; // Remember error - continue; // Add next user + result= TRUE; + continue; } db_name= table_list->db; @@ -6210,7 +6208,9 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) &rolename); ACL_USER_BASE *grantee= role_as_user; - if (!grantee) + if (has_auth(user, thd->lex)) + DBUG_ASSERT(!grantee); + else if (!grantee) grantee= find_user_exact(hostname.str, username.str); if (!grantee && !revoke) @@ -6220,7 +6220,8 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) user_combo.user = username; /* create the user if it does not exist */ - if (replace_user_table(thd, tables[USER_TABLE].table, user_combo, 0, + if (copy_and_check_auth(&user_combo, &user_combo, thd->lex) || + replace_user_table(thd, tables[USER_TABLE].table, user_combo, 0, false, create_new_user, no_auto_create_user)) {