mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Merge mysql.com:/home/alik/Documents/AllProgs/MySQL/devel/5.0-tree
into mysql.com:/home/alik/Documents/AllProgs/MySQL/devel/5.1-merged
This commit is contained in:
132
sql/sql_parse.cc
132
sql/sql_parse.cc
@ -4280,6 +4280,90 @@ end_with_restore_list:
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
If the definer is not specified, this means that CREATE-statement missed
|
||||
DEFINER-clause. DEFINER-clause can be missed in two cases:
|
||||
|
||||
- The user submitted a statement w/o the clause. This is a normal
|
||||
case, we should assign CURRENT_USER as definer.
|
||||
|
||||
- Our slave received an updated from the master, that does not
|
||||
replicate definer for stored rountines. We should also assign
|
||||
CURRENT_USER as definer here, but also we should mark this routine
|
||||
as NON-SUID. This is essential for the sake of backward
|
||||
compatibility.
|
||||
|
||||
The problem is the slave thread is running under "special" user (@),
|
||||
that actually does not exist. In the older versions we do not fail
|
||||
execution of a stored routine if its definer does not exist and
|
||||
continue the execution under the authorization of the invoker
|
||||
(BUG#13198). And now if we try to switch to slave-current-user (@),
|
||||
we will fail.
|
||||
|
||||
Actually, this leads to the inconsistent state of master and
|
||||
slave (different definers, different SUID behaviour), but it seems,
|
||||
this is the best we can do.
|
||||
*/
|
||||
|
||||
if (!lex->definer)
|
||||
{
|
||||
bool res= FALSE;
|
||||
Query_arena original_arena;
|
||||
Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
|
||||
|
||||
if (!(lex->definer= create_default_definer(thd)))
|
||||
res= TRUE;
|
||||
|
||||
if (ps_arena)
|
||||
thd->restore_active_arena(ps_arena, &original_arena);
|
||||
|
||||
if (res)
|
||||
{
|
||||
/* Error has been already reported. */
|
||||
delete lex->sphead;
|
||||
lex->sphead= 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (thd->slave_thread)
|
||||
lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
|
||||
}
|
||||
|
||||
/*
|
||||
If the specified definer differs from the current user, 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).
|
||||
*/
|
||||
|
||||
else 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))
|
||||
{
|
||||
if (check_global_access(thd, SUPER_ACL))
|
||||
{
|
||||
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
|
||||
delete lex->sphead;
|
||||
lex->sphead= 0;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the specified definer exists. Emit a warning if not. */
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (!is_acl_user(lex->definer->host.str,
|
||||
lex->definer->user.str))
|
||||
{
|
||||
push_warning_printf(thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_NO_SUCH_USER,
|
||||
ER(ER_NO_SUCH_USER),
|
||||
lex->definer->user.str,
|
||||
lex->definer->host.str);
|
||||
}
|
||||
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
|
||||
|
||||
/*
|
||||
We need to copy name and db in order to use them for
|
||||
check_routine_access which is called after lex->sphead has
|
||||
@ -7344,41 +7428,49 @@ Item *negate_expression(THD *thd, Item *expr)
|
||||
|
||||
/*
|
||||
Set the specified definer to the default value, which is the current user in
|
||||
the thread. Also check that the current user satisfies to the definers
|
||||
requirements.
|
||||
the thread.
|
||||
|
||||
SYNOPSIS
|
||||
get_default_definer()
|
||||
thd [in] thread handler
|
||||
definer [out] definer
|
||||
|
||||
RETURN
|
||||
error status, that is:
|
||||
- FALSE -- on success;
|
||||
- TRUE -- on error (current user can not be a definer).
|
||||
*/
|
||||
|
||||
bool get_default_definer(THD *thd, LEX_USER *definer)
|
||||
void get_default_definer(THD *thd, LEX_USER *definer)
|
||||
{
|
||||
/* Check that current user has non-empty host name. */
|
||||
|
||||
const Security_context *sctx= thd->security_ctx;
|
||||
|
||||
if (sctx->priv_host[0] == 0)
|
||||
{
|
||||
my_error(ER_MALFORMED_DEFINER, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Fill in. */
|
||||
|
||||
definer->user.str= (char *) sctx->priv_user;
|
||||
definer->user.length= strlen(definer->user.str);
|
||||
|
||||
definer->host.str= (char *) sctx->priv_host;
|
||||
definer->host.length= strlen(definer->host.str);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
Create default definer for the specified THD.
|
||||
|
||||
SYNOPSIS
|
||||
create_default_definer()
|
||||
thd [in] thread handler
|
||||
|
||||
RETURN
|
||||
On success, return a valid pointer to the created and initialized
|
||||
LEX_USER, which contains definer information.
|
||||
On error, return 0.
|
||||
*/
|
||||
|
||||
LEX_USER *create_default_definer(THD *thd)
|
||||
{
|
||||
LEX_USER *definer;
|
||||
|
||||
if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
|
||||
return 0;
|
||||
|
||||
get_default_definer(thd, definer);
|
||||
|
||||
return definer;
|
||||
}
|
||||
|
||||
|
||||
@ -7394,7 +7486,7 @@ bool get_default_definer(THD *thd, LEX_USER *definer)
|
||||
|
||||
RETURN
|
||||
On success, return a valid pointer to the created and initialized
|
||||
LEX_STRING, which contains definer information.
|
||||
LEX_USER, which contains definer information.
|
||||
On error, return 0.
|
||||
*/
|
||||
|
||||
|
Reference in New Issue
Block a user