summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <vicentiu@mariadb.org>2020-05-15 14:04:43 +0300
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2020-05-15 14:04:43 +0300
commit14d5dccd7bfd315a33ba4bacd0878e8795b024d9 (patch)
tree893c5d254d30e833c785d14a93179789034d8095
parent9a792dea7bdba4f3cd80215213c2e83a8b404563 (diff)
downloadmariadb-git-for-anel.tar.gz
Cleanup and othersfor-anel
-rw-r--r--mysql-test/suite/roles/set_default_role_invalid.test9
-rw-r--r--mysql-test/suite/roles/set_role-recursive.result2
-rw-r--r--sql/set_var.cc17
-rw-r--r--sql/set_var.h1
-rw-r--r--sql/sql_acl.cc167
-rw-r--r--sql/sql_acl.h2
6 files changed, 79 insertions, 119 deletions
diff --git a/mysql-test/suite/roles/set_default_role_invalid.test b/mysql-test/suite/roles/set_default_role_invalid.test
index 6af59bce95c..a72d035a524 100644
--- a/mysql-test/suite/roles/set_default_role_invalid.test
+++ b/mysql-test/suite/roles/set_default_role_invalid.test
@@ -90,7 +90,7 @@ change_user b;
SELECT CURRENT_ROLE;
SET ROLE r2;
SELECT CURRENT_ROLE;
---error 1044
+--error ER_DBACCESS_DENIED_ERROR
SET DEFAULT ROLE r1 FOR a;
SET ROLE r2;
SELECT CURRENT_ROLE;
@@ -104,7 +104,7 @@ GRANT SELECT ON mysql.* TO b;
change_user b;
SHOW GRANTS FOR b;
--echo # Select_priv is granted
---error ER_INVALID_ROLE
+--error ER_DBACCESS_DENIED_ERROR
SET DEFAULT ROLE r1 FOR a;
# Handling CURRENT_ROLE
SELECT CURRENT_ROLE;
@@ -115,10 +115,10 @@ SET DEFAULT ROLE current_role FOR current_user;
--error ER_INVALID_ROLE
SET DEFAULT ROLE invalid_role;
# Handling of non-existing role for user
---error ER_INVALID_ROLE
+--error ER_DBACCESS_DENIED_ERROR
SET DEFAULT ROLE invalid_role FOR a;
# Special case of handling the none role with select_priv
--- error 1044
+-- error ER_DBACCESS_DENIED_ERROR
SET DEFAULT ROLE none FOR a;
--echo # change user root
@@ -148,6 +148,7 @@ change_user a;
SELECT CURRENT_ROLE;
change_user root;
+--sorted_result
SELECT user, host, default_role FROM mysql.user where user='a' or user='b';
DROP ROLE r1, r2;
DROP USER a, b;
diff --git a/mysql-test/suite/roles/set_role-recursive.result b/mysql-test/suite/roles/set_role-recursive.result
index 1a07ddc9d17..b0d79377183 100644
--- a/mysql-test/suite/roles/set_role-recursive.result
+++ b/mysql-test/suite/roles/set_role-recursive.result
@@ -66,7 +66,7 @@ Grants for test_user@localhost
GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT test_role1 TO 'test_user'@'localhost'
set role test_role2;
-ERROR OP000: User `test_user@localhost` has not been granted a role `test_role2`
+ERROR OP000: User `test_user@localhost` has not been granted role `test_role2`
select current_user(), current_role();
current_user() current_role()
test_user@localhost NULL
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 2e4a3af91d4..4b1ef63c5f3 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -923,9 +923,17 @@ int set_var_default_role::check(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
real_user= get_current_user(thd, user);
- int status= acl_check_set_default_role(thd, real_user->host.str,
- real_user->user.str, role.str);
- return status;
+ real_role= role.str;
+ if (role.str == current_role.str)
+ {
+ if (!thd->security_ctx->priv_role[0])
+ real_role= "NONE";
+ else
+ real_role= thd->security_ctx->priv_role;
+ }
+
+ return acl_check_set_default_role(thd, real_user->host.str,
+ real_user->user.str, real_role);
#else
return 0;
#endif
@@ -936,7 +944,8 @@ int set_var_default_role::update(THD *thd)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
thd->m_reprepare_observer= 0;
- int res= acl_set_default_role(thd, real_user->host.str, real_user->user.str, role.str);
+ int res= acl_set_default_role(thd, real_user->host.str, real_user->user.str,
+ real_role);
thd->m_reprepare_observer= save_reprepare_observer;
return res;
#else
diff --git a/sql/set_var.h b/sql/set_var.h
index fc79e906270..572ff9fe60a 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -339,6 +339,7 @@ class set_var_default_role: public set_var_base
{
LEX_USER *user, *real_user;
LEX_STRING role;
+ const char *real_role;
public:
set_var_default_role(LEX_USER *user_arg, LEX_STRING role_arg) :
user(user_arg), role(role_arg) {}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index b20dcc82fc2..af8685c458b 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2047,70 +2047,10 @@ static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data)
return 0;
}
-/**
- @brief Helper function to handle the error when using check_user_can_set_role()
- @param type { ER_INVALID_CURRENT_USER - user doesn't exist,
- -1: ER_INVALID_ROLE - role doesn't exist
- 1: ER_INVALID_ROLE - role exist's but we don't know the does the
- current user has access to see the role in
- which case different type of error is generated
- }
- @param curr_user A current user
- @param curr_host A current host
- @param user A user for which we are setting the role
- @param host A host of a user
- @param rolename The name of the role
- @param read_access A read access of mysql.* aquired
-*/
-static void handle_error_set_role(int type, const char *curr_user,
- const char* curr_host, const char *curr_ip,
- const char *user,
- const char *host, const char *rolename,
- bool read_access)
-{
- switch (type)
- {
- case ER_INVALID_CURRENT_USER:
- my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename);
- break;
- case -1:
- /* Role doesn't exist at all */
- my_error(ER_INVALID_ROLE, MYF(0), rolename);
- break;
- case 1:
- StringBuffer<1024> c_usr;
- LEX_CSTRING role_lex;
- role_lex.str= rolename;
- role_lex.length= strlen(rolename);
-
- mysql_mutex_lock(&acl_cache->lock);
- ACL_USER *cur_user= find_user_or_anon(curr_host, curr_user, curr_ip);
-
- if (cur_user && (read_access || traverse_role_graph_down(cur_user, &role_lex,
- check_role_is_granted_callback, NULL) == -1))
- {
- /* Role is not granted but current user can see the role */
- c_usr.append(user, strlen(user));
- c_usr.append('@');
- c_usr.append(host, strlen(host));
- my_printf_error(ER_INVALID_ROLE, "User %`s has not been granted a role %`s",
- MYF(0), c_usr.c_ptr(), rolename);
- }
- else
- {
- /* Role is not granted and current user cannot see the role */
- my_error(ER_INVALID_ROLE, MYF(0), rolename);
- }
- mysql_mutex_unlock(&acl_cache->lock);
- break;
- }
-}
-
-static int check_user_can_set_role(const char *user, const char *host,
- const char *ip, const char *rolename, ulonglong *access,
- ulong read_access= 0, const char *curr_user= NULL,
- const char *curr_host= NULL, const char *curr_ip= NULL)
+static int check_user_can_set_role(THD *thd, const char *user, const char *host,
+ const char *ip, const char *rolename,
+ ulonglong *access)
{
ACL_ROLE *role;
ACL_USER_BASE *acl_user_base;
@@ -2141,7 +2081,7 @@ static int check_user_can_set_role(const char *user, const char *host,
/* According to SQL standard, the same error message must be presented */
if (role == NULL)
{
- result= -1;
+ result= ER_INVALID_ROLE;
goto end;
}
@@ -2170,29 +2110,66 @@ static int check_user_can_set_role(const char *user, const char *host,
{
*access = acl_user->access | role->access;
}
+
end:
mysql_mutex_unlock(&acl_cache->lock);
- if(result)
+
+ /* We present different error messages depending if the user has sufficient
+ privileges to know if the INVALID_ROLE exists. */
+ switch (result)
{
- handle_error_set_role(result, curr_user,
- curr_host, curr_ip, user, host,
- rolename, read_access);
+ case ER_INVALID_CURRENT_USER:
+ my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename);
+ break;
+ case ER_INVALID_ROLE:
+ /* Role doesn't exist at all */
+ my_error(ER_INVALID_ROLE, MYF(0), rolename);
+ break;
+ case 1:
+ StringBuffer<1024> c_usr;
+ LEX_CSTRING role_lex;
+ /* First, check if current user can see mysql database. */
+ bool read_access= !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1);
+
+ role_lex.str= rolename;
+ role_lex.length= strlen(rolename);
+ mysql_mutex_lock(&acl_cache->lock);
+ ACL_USER *cur_user= find_user_or_anon(thd->security_ctx->priv_host,
+ thd->security_ctx->priv_user,
+ thd->security_ctx->ip);
+
+ /* If the current user does not have select priv to mysql database,
+ see if the current user can discover the role if it was granted to him.
+ */
+ if (cur_user && (read_access ||
+ traverse_role_graph_down(cur_user, &role_lex,
+ check_role_is_granted_callback,
+ NULL) == -1))
+ {
+ /* Role is not granted but current user can see the role */
+ c_usr.append(user, strlen(user));
+ c_usr.append('@');
+ c_usr.append(host, strlen(host));
+ my_printf_error(ER_INVALID_ROLE, "User %`s has not been granted role %`s",
+ MYF(0), c_usr.c_ptr(), rolename);
+ }
+ else
+ {
+ /* Role is not granted and current user cannot see the role */
+ my_error(ER_INVALID_ROLE, MYF(0), rolename);
+ }
+ mysql_mutex_unlock(&acl_cache->lock);
+ break;
}
return result;
-
}
+
int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
{
- ulong read_access= acl_get(thd->security_ctx->priv_host, thd->security_ctx->ip,
- thd->security_ctx->priv_user, "mysql", 0);
-
- return check_user_can_set_role(thd->security_ctx->priv_user,
- thd->security_ctx->host, thd->security_ctx->ip, rolename, access,
- read_access, thd->security_ctx->priv_user,
- thd->security_ctx->priv_host, thd->security_ctx->ip);
-
+ return check_user_can_set_role(thd, thd->security_ctx->priv_user,
+ thd->security_ctx->host, thd->security_ctx->ip, rolename, access);
}
@@ -2974,27 +2951,13 @@ WSREP_ERROR_LABEL:
int acl_check_set_default_role(THD *thd, const char *host, const char *user,
const char *role)
{
- /* If the user has a read access on mysql.user table, it can see the roles,
- granted or not and different kind of error may be allowed.
- There is no handling of NONE and PUBLIC roles for read access.
- Make sure role exists and that role is not the same as current_role.
- */
- if (!check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1) &&
- strcasecmp(role, "PUBLIC") && strcasecmp(role, "NONE") &&
- role != current_role.str)
- {
- if(check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1))
- {
- ulong read_access= 1;
- acl_set_default_role(thd, host, user, role, read_access);
- return 1;
- }
- }
- return check_alter_user(thd, host, user);
+ DBUG_ENTER("acl_check_set_default_role");
+ DBUG_RETURN(check_alter_user(thd, host, user) ||
+ check_user_can_set_role(thd, user, host, NULL, role, NULL));
}
int acl_set_default_role(THD *thd, const char *host, const char *user,
- const char *rolename, ulong read_access)
+ const char *rolename)
{
TABLE_LIST tables[TABLES_MAX];
TABLE *table;
@@ -3012,20 +2975,6 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
DBUG_PRINT("enter",("host: '%s' user: '%s' rolename: '%s'",
safe_str(user), safe_str(host), safe_str(rolename)));
- if (rolename == current_role.str) {
- if (!thd->security_ctx->priv_role[0])
- rolename= "NONE";
- else
- rolename= thd->security_ctx->priv_role;
- }
-
- if (check_user_can_set_role(user, host, host, rolename, NULL, read_access,
- thd->security_ctx->priv_user, thd->security_ctx->priv_host,
- thd->security_ctx->ip))
- {
- DBUG_RETURN(result);
- }
-
if (!strcasecmp(rolename, "NONE"))
clear_role= TRUE;
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index dd50cc181b3..3bd896cab79 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -404,7 +404,7 @@ int acl_setrole(THD *thd, char *rolename, ulonglong access);
int acl_check_setrole(THD *thd, char *rolename, ulonglong *access);
int acl_check_set_default_role(THD *thd, const char *host, const char *user, const char *role);
int acl_set_default_role(THD *thd, const char *host, const char *user,
- const char *rolename, ulong read_access= 0);
+ const char *rolename);
extern SHOW_VAR acl_statistics[];