diff --git a/mysql-test/suite/roles/create_and_drop_current.result b/mysql-test/suite/roles/create_and_drop_current.result new file mode 100644 index 00000000000..fa319440080 --- /dev/null +++ b/mysql-test/suite/roles/create_and_drop_current.result @@ -0,0 +1,39 @@ +grant create user on *.* to foo@localhost; +create user current_user; +ERROR HY000: Operation CREATE USER failed for CURRENT_USER +create user current_role; +ERROR HY000: Operation CREATE USER failed for CURRENT_ROLE +create role 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 'current_user' at line 1 +create role current_role; +ERROR HY000: Operation CREATE ROLE failed for CURRENT_ROLE +drop user current_user; +drop user current_role; +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 'current_role' at line 1 +drop role 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 'current_user' at line 1 +drop role current_role; +ERROR HY000: Operation DROP ROLE failed for CURRENT_ROLE +show warnings; +Level Code Message +Error 1446 Invalid definer +Error 1396 Operation DROP ROLE failed for CURRENT_ROLE +create role r1; +grant r1 to current_user; +set role r1; +select current_role(); +current_role() +r1 +create user current_role; +ERROR HY000: Operation CREATE USER failed for CURRENT_ROLE +create role current_role; +ERROR HY000: Operation CREATE ROLE failed for CURRENT_ROLE +drop user current_role; +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 'current_role' at line 1 +drop role current_role; +select user,host,is_role from mysql.user; +user host is_role +root localhost N +root meddwl N +root 127.0.0.1 N +root ::1 N diff --git a/mysql-test/suite/roles/create_and_drop_current.test b/mysql-test/suite/roles/create_and_drop_current.test new file mode 100644 index 00000000000..ad606376615 --- /dev/null +++ b/mysql-test/suite/roles/create_and_drop_current.test @@ -0,0 +1,52 @@ +# +# MDEV-5225 Server crashes on CREATE USER|ROLE CURRENT_ROLE or DROP ROLE CURRENT_ROLE +# + +# Where CURRENT_USER/CURRENT_ROLE is explicitly allowed by the grammar +# the error (if any) should be ER_CANNOT_USER +# +# Where it's not explicitly allowed, the error is ER_PARSE_ERROR, +# because CURRENT_USER/CURRENT_ROLE are reserved words and cannot be +# accepted as an identifier. +# + +--source include/not_embedded.inc + +grant create user on *.* to foo@localhost; +--change_user foo + +--error ER_CANNOT_USER +create user current_user; +--error ER_CANNOT_USER +create user current_role; +--error ER_PARSE_ERROR +create role current_user; +--error ER_CANNOT_USER +create role current_role; +# this works +drop user current_user; +--error ER_PARSE_ERROR +drop user current_role; +--error ER_PARSE_ERROR +drop role current_user; +--error ER_CANNOT_USER +drop role current_role; +show warnings; + +--change_user root + +create role r1; +grant r1 to current_user; +set role r1; +select current_role(); + +--error ER_CANNOT_USER +create user current_role; +--error ER_CANNOT_USER +create role current_role; +--error ER_PARSE_ERROR +drop user current_role; +drop role current_role; + +select user,host,is_role from mysql.user; + diff --git a/mysql-test/suite/roles/grant_revoke_current.result b/mysql-test/suite/roles/grant_revoke_current.result new file mode 100644 index 00000000000..644454685b4 --- /dev/null +++ b/mysql-test/suite/roles/grant_revoke_current.result @@ -0,0 +1,27 @@ +grant select on *.* to current_role; +ERROR 0L000: Invalid definer +revoke select on *.* from current_role; +ERROR 0L000: Invalid definer +revoke all, grant option from current_role; +ERROR 0L000: Invalid definer +create role r1; +grant insert on test.* to r1; +grant r1 to current_user; +set role r1; +select current_role(); +current_role() +r1 +grant select on *.* to current_role; +show grants for current_role; +Grants for r1 +GRANT SELECT ON *.* TO 'r1' +GRANT INSERT ON `test`.* TO 'r1' +revoke insert on test.* from current_role; +show grants for current_role; +Grants for r1 +GRANT SELECT ON *.* TO 'r1' +revoke all, grant option from current_role; +show grants for current_role; +Grants for r1 +GRANT USAGE ON *.* TO 'r1' +drop role r1; diff --git a/mysql-test/suite/roles/grant_revoke_current.test b/mysql-test/suite/roles/grant_revoke_current.test new file mode 100644 index 00000000000..96a27fd5697 --- /dev/null +++ b/mysql-test/suite/roles/grant_revoke_current.test @@ -0,0 +1,24 @@ +--source include/not_embedded.inc + +--error ER_MALFORMED_DEFINER +grant select on *.* to current_role; +--error ER_MALFORMED_DEFINER +revoke select on *.* from current_role; +--error ER_MALFORMED_DEFINER +revoke all, grant option from current_role; + +create role r1; +grant insert on test.* to r1; +grant r1 to current_user; +set role r1; +select current_role(); + +grant select on *.* to current_role; +show grants for current_role; +revoke insert on test.* from current_role; +show grants for current_role; +revoke all, grant option from current_role; +show grants for current_role; + +drop role r1; + diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1643161d5d6..7abe3899a2a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9065,6 +9065,13 @@ static void append_user(String *str, LEX_USER *user) str->append('\''); } +static void append_str(String *str, const char *s, size_t l) +{ + if (str->length()) + str->append(','); + str->append(s, l); +} + /* Create a list of users. @@ -9102,6 +9109,20 @@ bool mysql_create_user(THD *thd, List &list, bool handle_as_role) while ((user_name= user_list++)) { + if (user_name->user.str == current_user.str) + { + append_str(&wrong_users, STRING_WITH_LEN("CURRENT_USER")); + result= TRUE; + continue; + } + + if (user_name->user.str == current_role.str) + { + append_str(&wrong_users, STRING_WITH_LEN("CURRENT_ROLE")); + result= TRUE; + continue; + } + if (handle_as_role && is_invalid_role_name(user_name->user.str)) { append_user(&wrong_users, user_name); @@ -9211,7 +9232,15 @@ bool mysql_drop_user(THD *thd, List &list, bool handle_as_role) while ((tmp_user_name= user_list++)) { user_name= get_current_user(thd, tmp_user_name, false); - if (!user_name || handle_as_role != user_name->is_role()) + if (!user_name) + { + thd->clear_error(); + append_str(&wrong_users, STRING_WITH_LEN("CURRENT_ROLE")); + result= TRUE; + continue; + } + + if (handle_as_role != user_name->is_role()) { append_user(&wrong_users, tmp_user_name); result= TRUE; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0e81fee0056..e6c2b09cb3d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -15126,9 +15126,11 @@ role_list: current_role: CURRENT_ROLE optional_braces { - if (!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER)))) + if (!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER)))) MYSQL_YYABORT; $$->user= current_role; + $$->plugin= empty_lex_str; + $$->auth= empty_lex_str; } ;