diff options
author | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2020-05-15 14:04:43 +0300 |
---|---|---|
committer | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2020-05-15 14:04:43 +0300 |
commit | 14d5dccd7bfd315a33ba4bacd0878e8795b024d9 (patch) | |
tree | 893c5d254d30e833c785d14a93179789034d8095 | |
parent | 9a792dea7bdba4f3cd80215213c2e83a8b404563 (diff) | |
download | mariadb-git-for-anel.tar.gz |
Cleanup and othersfor-anel
-rw-r--r-- | mysql-test/suite/roles/set_default_role_invalid.test | 9 | ||||
-rw-r--r-- | mysql-test/suite/roles/set_role-recursive.result | 2 | ||||
-rw-r--r-- | sql/set_var.cc | 17 | ||||
-rw-r--r-- | sql/set_var.h | 1 | ||||
-rw-r--r-- | sql/sql_acl.cc | 167 | ||||
-rw-r--r-- | sql/sql_acl.h | 2 |
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[]; |