mirror of
https://github.com/MariaDB/server.git
synced 2025-09-02 09:41:40 +03:00
10.0-base merge (roles)
This commit is contained in:
174
sql/sql_parse.cc
174
sql/sql_parse.cc
@@ -401,8 +401,11 @@ void init_update_queries(void)
|
||||
sql_command_flags[SQLCOM_CREATE_USER]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_RENAME_USER]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_DROP_USER]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_CREATE_ROLE]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_GRANT_ROLE]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_REVOKE]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_REVOKE_ROLE]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_OPTIMIZE]= CF_CHANGES_DATA;
|
||||
/*
|
||||
@todo SQLCOM_CREATE_FUNCTION should have CF_AUTO_COMMIT_TRANS
|
||||
@@ -461,9 +464,13 @@ void init_update_queries(void)
|
||||
sql_command_flags[SQLCOM_CREATE_USER]|= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_RENAME_USER]|= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_ROLE]|= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_ROLE]|= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_REVOKE_ALL]= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_REVOKE]|= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_REVOKE_ROLE]|= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_GRANT]|= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_GRANT_ROLE]|= CF_AUTO_COMMIT_TRANS;
|
||||
|
||||
sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_PRELOAD_KEYS]= CF_AUTO_COMMIT_TRANS;
|
||||
@@ -664,7 +671,8 @@ static void handle_bootstrap_impl(THD *thd)
|
||||
#endif /* EMBEDDED_LIBRARY */
|
||||
|
||||
thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
|
||||
thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=0;
|
||||
thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=
|
||||
thd->security_ctx->priv_role[0]= 0;
|
||||
/*
|
||||
Make the "client" handle multiple results. This is necessary
|
||||
to enable stored procedures with SELECTs and Dynamic SQL
|
||||
@@ -1878,8 +1886,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||
DBUG_RETURN(1);
|
||||
lex->query_tables_last= query_tables_last;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
case SCH_PROFILES:
|
||||
/*
|
||||
Mark this current profiling record to be discarded. We don't
|
||||
@@ -2006,7 +2014,6 @@ static void reset_one_shot_variables(THD *thd)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
bool sp_process_definer(THD *thd)
|
||||
{
|
||||
DBUG_ENTER("sp_process_definer");
|
||||
@@ -2043,7 +2050,7 @@ bool sp_process_definer(THD *thd)
|
||||
Query_arena original_arena;
|
||||
Query_arena *ps_arena= thd->activate_stmt_arena_if_needed(&original_arena);
|
||||
|
||||
lex->definer= create_default_definer(thd);
|
||||
lex->definer= create_default_definer(thd, false);
|
||||
|
||||
if (ps_arena)
|
||||
thd->restore_active_arena(ps_arena, &original_arena);
|
||||
@@ -2057,20 +2064,24 @@ bool sp_process_definer(THD *thd)
|
||||
}
|
||||
else
|
||||
{
|
||||
LEX_USER *d= lex->definer= get_current_user(thd, lex->definer);
|
||||
if (!d)
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/*
|
||||
If the specified definer differs from the current user, we
|
||||
If the specified definer differs from the current user or role, we
|
||||
should check that the current user has SUPER privilege (in order
|
||||
to create a stored routine under another user one must have
|
||||
SUPER privilege).
|
||||
*/
|
||||
if ((strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
|
||||
my_strcasecmp(system_charset_info, lex->definer->host.str,
|
||||
thd->security_ctx->priv_host)) &&
|
||||
check_global_access(thd, SUPER_ACL, true))
|
||||
{
|
||||
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
|
||||
bool curuser= !strcmp(d->user.str, thd->security_ctx->priv_user);
|
||||
bool currole= !curuser && !strcmp(d->user.str, thd->security_ctx->priv_role);
|
||||
bool curuserhost= curuser && d->host.str &&
|
||||
!my_strcasecmp(system_charset_info, d->host.str,
|
||||
thd->security_ctx->priv_host);
|
||||
if (!curuserhost && !currole &&
|
||||
check_global_access(thd, SUPER_ACL, false))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the specified definer exists. Emit a warning if not. */
|
||||
@@ -3991,22 +4002,26 @@ end_with_restore_list:
|
||||
}
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
case SQLCOM_CREATE_USER:
|
||||
case SQLCOM_CREATE_ROLE:
|
||||
{
|
||||
if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 1) &&
|
||||
check_global_access(thd,CREATE_USER_ACL))
|
||||
break;
|
||||
/* Conditionally writes to binlog */
|
||||
if (!(res= mysql_create_user(thd, lex->users_list)))
|
||||
if (!(res= mysql_create_user(thd, lex->users_list,
|
||||
lex->sql_command == SQLCOM_CREATE_ROLE)))
|
||||
my_ok(thd);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_DROP_USER:
|
||||
case SQLCOM_DROP_ROLE:
|
||||
{
|
||||
if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 1) &&
|
||||
check_global_access(thd,CREATE_USER_ACL))
|
||||
break;
|
||||
/* Conditionally writes to binlog */
|
||||
if (!(res= mysql_drop_user(thd, lex->users_list)))
|
||||
if (!(res= mysql_drop_user(thd, lex->users_list,
|
||||
lex->sql_command == SQLCOM_DROP_ROLE)))
|
||||
my_ok(thd);
|
||||
break;
|
||||
}
|
||||
@@ -4026,9 +4041,6 @@ end_with_restore_list:
|
||||
check_global_access(thd,CREATE_USER_ACL))
|
||||
break;
|
||||
|
||||
/* Replicate current user as grantor */
|
||||
thd->binlog_invoker();
|
||||
|
||||
/* Conditionally writes to binlog */
|
||||
if (!(res = mysql_revoke_all(thd, lex->users_list)))
|
||||
my_ok(thd);
|
||||
@@ -4046,42 +4058,58 @@ end_with_restore_list:
|
||||
goto error;
|
||||
|
||||
/* Replicate current user as grantor */
|
||||
thd->binlog_invoker();
|
||||
thd->binlog_invoker(false);
|
||||
|
||||
if (thd->security_ctx->user) // If not replication
|
||||
{
|
||||
LEX_USER *user, *tmp_user;
|
||||
LEX_USER *user;
|
||||
bool first_user= TRUE;
|
||||
|
||||
List_iterator <LEX_USER> user_list(lex->users_list);
|
||||
while ((tmp_user= user_list++))
|
||||
while ((user= user_list++))
|
||||
{
|
||||
if (!(user= get_current_user(thd, tmp_user)))
|
||||
goto error;
|
||||
if (specialflag & SPECIAL_NO_RESOLVE &&
|
||||
hostname_requires_resolving(user->host.str))
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_WARN_HOSTNAME_WONT_WORK,
|
||||
ER(ER_WARN_HOSTNAME_WONT_WORK));
|
||||
// Are we trying to change a password of another user
|
||||
DBUG_ASSERT(user->host.str != 0);
|
||||
|
||||
/*
|
||||
GRANT/REVOKE PROXY has the target user as a first entry in the list.
|
||||
*/
|
||||
if (lex->type == TYPE_ENUM_PROXY && first_user)
|
||||
{
|
||||
if (!(user= get_current_user(thd, user)) || !user->host.str)
|
||||
goto error;
|
||||
|
||||
first_user= FALSE;
|
||||
if (acl_check_proxy_grant_access (thd, user->host.str, user->user.str,
|
||||
lex->grant & GRANT_ACL))
|
||||
goto error;
|
||||
}
|
||||
else if (is_acl_user(user->host.str, user->user.str) &&
|
||||
user->password.str &&
|
||||
check_change_password (thd, user->host.str, user->user.str,
|
||||
user->password.str,
|
||||
user->password.length))
|
||||
goto error;
|
||||
else if (user->password.str)
|
||||
{
|
||||
// Are we trying to change a password of another user?
|
||||
const char *hostname= user->host.str, *username=user->user.str;
|
||||
bool userok;
|
||||
if (username == current_user.str)
|
||||
{
|
||||
username= thd->security_ctx->priv_user;
|
||||
hostname= thd->security_ctx->priv_host;
|
||||
userok= true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!hostname)
|
||||
hostname= host_not_specified.str;
|
||||
userok= is_acl_user(hostname, username);
|
||||
}
|
||||
|
||||
if (userok && check_change_password (thd, hostname, username,
|
||||
user->password.str,
|
||||
user->password.length))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (first_table)
|
||||
@@ -4125,9 +4153,9 @@ end_with_restore_list:
|
||||
else
|
||||
{
|
||||
/* Conditionally writes to binlog */
|
||||
res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
|
||||
lex->sql_command == SQLCOM_REVOKE,
|
||||
lex->type == TYPE_ENUM_PROXY);
|
||||
res= mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
|
||||
lex->sql_command == SQLCOM_REVOKE,
|
||||
lex->type == TYPE_ENUM_PROXY);
|
||||
}
|
||||
if (!res)
|
||||
{
|
||||
@@ -4146,6 +4174,14 @@ end_with_restore_list:
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLCOM_REVOKE_ROLE:
|
||||
case SQLCOM_GRANT_ROLE:
|
||||
{
|
||||
if (!(res= mysql_grant_role(thd, lex->users_list,
|
||||
lex->sql_command != SQLCOM_GRANT_ROLE)))
|
||||
my_ok(thd);
|
||||
break;
|
||||
}
|
||||
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
|
||||
case SQLCOM_RESET:
|
||||
/*
|
||||
@@ -4243,11 +4279,17 @@ end_with_restore_list:
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
case SQLCOM_SHOW_GRANTS:
|
||||
{
|
||||
LEX_USER *grant_user= get_current_user(thd, lex->grant_user);
|
||||
LEX_USER *grant_user= lex->grant_user;
|
||||
if (!grant_user)
|
||||
goto error;
|
||||
if ((thd->security_ctx->priv_user &&
|
||||
!strcmp(thd->security_ctx->priv_user, grant_user->user.str)) ||
|
||||
|
||||
if (grant_user->user.str &&
|
||||
!strcmp(thd->security_ctx->priv_user, grant_user->user.str))
|
||||
grant_user->user= current_user;
|
||||
|
||||
if (grant_user->user.str == current_user.str ||
|
||||
grant_user->user.str == current_role.str ||
|
||||
grant_user->user.str == current_user_and_current_role.str ||
|
||||
!check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0))
|
||||
{
|
||||
res = mysql_show_grants(thd, grant_user);
|
||||
@@ -5363,8 +5405,12 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
|
||||
if (!(sctx->master_access & SELECT_ACL))
|
||||
{
|
||||
if (db && (!thd->db || db_is_pattern || strcmp(db, thd->db)))
|
||||
{
|
||||
db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
|
||||
db_is_pattern);
|
||||
if (sctx->priv_role[0])
|
||||
db_access|= acl_get("", "", sctx->priv_role, db, db_is_pattern);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get access for current db */
|
||||
@@ -5408,8 +5454,14 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
|
||||
}
|
||||
|
||||
if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))
|
||||
{
|
||||
db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
|
||||
db_is_pattern);
|
||||
if (sctx->priv_role[0])
|
||||
{
|
||||
db_access|= acl_get("", "", sctx->priv_role, db, db_is_pattern);
|
||||
}
|
||||
}
|
||||
else
|
||||
db_access= sctx->db_access;
|
||||
DBUG_PRINT("info",("db_access: %lu want_access: %lu",
|
||||
@@ -8016,16 +8068,23 @@ Item *negate_expression(THD *thd, Item *expr)
|
||||
@param[out] definer definer
|
||||
*/
|
||||
|
||||
void get_default_definer(THD *thd, LEX_USER *definer)
|
||||
void get_default_definer(THD *thd, LEX_USER *definer, bool role)
|
||||
{
|
||||
const Security_context *sctx= thd->security_ctx;
|
||||
|
||||
definer->user.str= (char *) sctx->priv_user;
|
||||
if (role)
|
||||
{
|
||||
definer->user.str= const_cast<char*>(sctx->priv_role);
|
||||
definer->host= empty_lex_str;
|
||||
}
|
||||
else
|
||||
{
|
||||
definer->user.str= const_cast<char*>(sctx->priv_user);
|
||||
definer->host.str= const_cast<char*>(sctx->priv_host);
|
||||
definer->host.length= strlen(definer->host.str);
|
||||
}
|
||||
definer->user.length= strlen(definer->user.str);
|
||||
|
||||
definer->host.str= (char *) sctx->priv_host;
|
||||
definer->host.length= strlen(definer->host.str);
|
||||
|
||||
definer->password= null_lex_str;
|
||||
definer->plugin= empty_lex_str;
|
||||
definer->auth= empty_lex_str;
|
||||
@@ -8043,16 +8102,22 @@ void get_default_definer(THD *thd, LEX_USER *definer)
|
||||
- On error, return 0.
|
||||
*/
|
||||
|
||||
LEX_USER *create_default_definer(THD *thd)
|
||||
LEX_USER *create_default_definer(THD *thd, bool role)
|
||||
{
|
||||
LEX_USER *definer;
|
||||
|
||||
if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
|
||||
return 0;
|
||||
|
||||
thd->get_definer(definer);
|
||||
thd->get_definer(definer, role);
|
||||
|
||||
return definer;
|
||||
if (role && definer->user.length == 0)
|
||||
{
|
||||
my_error(ER_MALFORMED_DEFINER, MYF(0));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return definer;
|
||||
}
|
||||
|
||||
|
||||
@@ -8087,27 +8152,6 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Retuns information about user or current user.
|
||||
|
||||
@param[in] thd thread handler
|
||||
@param[in] user user
|
||||
|
||||
@return
|
||||
- On success, return a valid pointer to initialized
|
||||
LEX_USER, which contains user information.
|
||||
- On error, return 0.
|
||||
*/
|
||||
|
||||
LEX_USER *get_current_user(THD *thd, LEX_USER *user)
|
||||
{
|
||||
if (!user->user.str) // current_user
|
||||
return create_default_definer(thd);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check that byte length of a string does not exceed some limit.
|
||||
|
||||
|
Reference in New Issue
Block a user