From 1f0368658b8992c88e2f6304de80f11be097ba1a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 2 Nov 2013 16:26:01 +0100 Subject: [PATCH] MDEV-5225 Server crashes on CREATE USER|ROLE CURRENT_ROLE or DROP ROLE CURRENT_ROLE --- .../roles/create_and_drop_current.result | 39 ++++++++++++++ .../suite/roles/create_and_drop_current.test | 52 +++++++++++++++++++ sql/sql_acl.cc | 31 ++++++++++- 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/roles/create_and_drop_current.result create mode 100644 mysql-test/suite/roles/create_and_drop_current.test 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/sql/sql_acl.cc b/sql/sql_acl.cc index 28628e313f8..adc073f7117 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9043,6 +9043,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. @@ -9080,6 +9087,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); @@ -9189,7 +9210,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;