diff options
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r-- | sql/sql_acl.cc | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 03e7ca9258e..1e94e75cf75 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -8975,10 +8975,30 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, if (struct_no == ROLES_MAPPINGS_HASH) { const char* role= role_grant_pair->r_uname? role_grant_pair->r_uname: ""; - if (user_from->is_role() ? strcmp(user_from->user.str, role) : - (strcmp(user_from->user.str, user) || - my_strcasecmp(system_charset_info, user_from->host.str, host))) - continue; + if (user_from->is_role()) + { + /* When searching for roles within the ROLES_MAPPINGS_HASH, we have + to check both the user field as well as the role field for a match. + + It is possible to have a role granted to a role. If we are going + to modify the mapping entry, it needs to be done on either on the + "user" end (here represented by a role) or the "role" end. At least + one part must match. + + If the "user" end has a not-empty host string, it can never match + as we are searching for a role here. A role always has an empty host + string. + */ + if ((*host || strcmp(user_from->user.str, user)) && + strcmp(user_from->user.str, role)) + continue; + } + else + { + if (strcmp(user_from->user.str, user) || + my_strcasecmp(system_charset_info, user_from->host.str, host)) + continue; + } } else { |