Commit 77c63823 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-21689 Add Sql_cmd for GRANT/REVOKE statements

Rewriting GRANT/REVOKE grammar to use more bison stack and use Sql_cmd_ style

1. Removing a few members from LEX:
   - uint grant, grant_to_col, which_columns
   - List<LEX_COLUMN> columns
   - bool all_privileges
2. Adding classes Grand_object_name, Lex_grant_object_name
3. Adding classes Grand_privilege, Lex_grand_privilege
4. Adding struct Lex_column_list_privilege_st, class Lex_column_list_privilege
5. Rewriting the GRANT/REVOKE grammar to use new classes and pass them through
   bison stack (rather than directly access LEX members)
6. Adding classes Sql_cmd_grant* and Sql_cmd_revoke*,
   changing GRANT/REVOKE to use LEX::m_sql_cmd.
7. Adding the "sp_handler" grammar rule and removing some duplicate grammar
   for GRANT/REVOKE for different kinds of SP objects.
8. Adding a new rule comma_separated_ident_list, reusing it in:
   - with_column_list
   - colum_list_privilege
parent 06b0623a
......@@ -47,7 +47,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/password.c ../sql/discover.cc ../sql/derror.cc
../sql/field.cc ../sql/field_conv.cc ../sql/field_comp.cc
../sql/filesort_utils.cc ../sql/sql_digest.cc
../sql/filesort.cc ../sql/gstream.cc ../sql/slave.cc
../sql/filesort.cc ../sql/grant.cc
../sql/gstream.cc ../sql/slave.cc
../sql/signal_handler.cc
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
../sql/init.cc ../sql/item_buff.cc ../sql/item_cmpfunc.cc
......
......@@ -129,6 +129,7 @@ SET (SQL_SOURCE
sql_reload.cc
# added in MariaDB:
grant.cc
sql_explain.cc
sql_analyze_stmt.cc
sql_join_cache.cc
......
/*
Copyright (c) 2009, 2020, MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#include "mariadb.h"
#include "sql_acl.h"
bool Grant_privilege::add_column_privilege(THD *thd,
const Lex_ident_sys &name,
uint which_grant)
{
String *new_str= new (thd->mem_root) String((const char*) name.str,
name.length,
system_charset_info);
if (unlikely(new_str == NULL))
return true;
List_iterator <LEX_COLUMN> iter(m_columns);
class LEX_COLUMN *point;
while ((point=iter++))
{
if (!my_strcasecmp(system_charset_info,
point->column.c_ptr(), new_str->c_ptr()))
break;
}
m_column_privilege_total|= which_grant;
if (point)
{
point->rights |= which_grant;
return false;
}
LEX_COLUMN *col= new (thd->mem_root) LEX_COLUMN(*new_str, which_grant);
if (unlikely(col == NULL))
return true;
return m_columns.push_back(col, thd->mem_root);
}
bool Grant_privilege::add_column_list_privilege(THD *thd,
List<Lex_ident_sys> &list,
uint privilege)
{
Lex_ident_sys *col;
List_iterator<Lex_ident_sys> it(list);
while ((col= it++))
{
if (add_column_privilege(thd, *col, privilege))
return true;
}
return false;
}
uint Grant_object_name::all_privileges_by_type() const
{
switch (m_type) {
case STAR: return DB_ACLS & ~GRANT_ACL;
case IDENT_STAR: return DB_ACLS & ~GRANT_ACL;
case STAR_STAR: return GLOBAL_ACLS & ~GRANT_ACL;
case TABLE_IDENT: return TABLE_ACLS & ~GRANT_ACL;
}
return 0;
}
bool Grant_privilege::set_object_name(THD *thd,
const Grant_object_name &ident,
SELECT_LEX *sel,
uint with_grant_option)
{
DBUG_ASSERT(!m_all_privileges || !m_columns.elements);
m_db= ident.m_db;
if (m_all_privileges)
m_object_privilege= ident.all_privileges_by_type();
m_object_privilege|= with_grant_option;
switch (ident.m_type)
{
case Lex_grant_object_name::STAR:
case Lex_grant_object_name::IDENT_STAR:
case Lex_grant_object_name::STAR_STAR:
if (!m_all_privileges && m_columns.elements)
{
// e.g. GRANT SELECT (a) ON db.*
my_error(ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0));
return true;
}
return false;
case Lex_grant_object_name::TABLE_IDENT:
m_db= ident.m_table_ident->db;
return !sel->add_table_to_list(thd, ident.m_table_ident,
NULL, TL_OPTION_UPDATING);
}
return false; // Make gcc happy
}
/*
Copyright (c) 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#ifndef SQL_GRANT_INCLUDED
#define SQL_GRANT_INCLUDED
#include "lex_string.h"
class LEX_COLUMN;
class Lex_ident_sys;
class Table_ident;
/*
Represents the object name in this standard SQL grammar:
GRANT <object privileges> ON <object name>
*/
class Grant_object_name
{
public:
enum Type
{
STAR, // ON *
IDENT_STAR, // ON db.*
STAR_STAR, // ON *.*
TABLE_IDENT // ON db.name
};
Lex_cstring m_db;
Table_ident *m_table_ident;
Type m_type;
public:
Grant_object_name(Table_ident *table_ident)
:m_table_ident(table_ident),
m_type(TABLE_IDENT)
{ }
Grant_object_name(const LEX_CSTRING &db, Type type)
:m_db(db),
m_table_ident(NULL),
m_type(type)
{ }
uint all_privileges_by_type() const;
};
/*
Represents standard SQL statements described by:
- <grant privilege statement>
- <revoke privilege statement>
*/
class Grant_privilege
{
protected:
List<LEX_COLUMN> m_columns;
Lex_cstring m_db;
uint m_object_privilege;
uint m_column_privilege_total;
bool m_all_privileges;
public:
Grant_privilege()
:m_object_privilege(0), m_column_privilege_total(0), m_all_privileges(false)
{ }
Grant_privilege(uint privilege, bool all_privileges)
:m_object_privilege(privilege),
m_column_privilege_total(0),
m_all_privileges(all_privileges)
{ }
void add_object_privilege(uint privilege)
{
m_object_privilege|= privilege;
}
bool add_column_privilege(THD *thd, const Lex_ident_sys &col,
uint privilege);
bool add_column_list_privilege(THD *thd, List<Lex_ident_sys> &list,
uint privilege);
bool set_object_name(THD *thd,
const Grant_object_name &ident,
SELECT_LEX *sel,
uint with_grant_option);
const List<LEX_COLUMN> & columns() const { return m_columns; }
};
#endif // SQL_GRANT_INCLUDED
......@@ -30,6 +30,10 @@ class Lex_cstring : public LEX_CSTRING
str= NULL;
length= 0;
}
Lex_cstring(const LEX_CSTRING &str)
{
LEX_CSTRING::operator=(str);
}
Lex_cstring(const char *_str, size_t _len)
{
str= _str;
......
......@@ -11656,6 +11656,227 @@ bool check_grant(THD *, ulong, TABLE_LIST *, bool, uint, bool)
{ return 0; }
#endif /*NO_EMBEDDED_ACCESS_CHECKS */
#ifdef NO_EMBEDDED_ACCESS_CHECKS
bool Sql_cmd_grant_proxy::execute(THD *thd)
{
my_ok(thd);
return false;
}
bool Sql_cmd_grant_table::execute(THD *thd)
{
my_ok(thd);
return false;
}
bool Sql_cmd_grant_sp::execute(THD *thd)
{
my_ok(thd);
return false;
}
#else // not NO_EMBEDDED_ACCESS_CHECKS
void Sql_cmd_grant::warn_hostname_requires_resolving(THD *thd,
List<LEX_USER> &users)
{
LEX_USER *user;
List_iterator <LEX_USER> it(users);
while ((user= it++))
{
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_THD(thd, ER_WARN_HOSTNAME_WONT_WORK));
}
}
void Sql_cmd_grant::grant_stage0(THD *thd)
{
thd->binlog_invoker(false); // Replicate current user as grantor
if (thd->security_ctx->user) // If not replication
warn_hostname_requires_resolving(thd, thd->lex->users_list);
}
bool Sql_cmd_grant::user_list_reset_mqh(THD *thd, List<LEX_USER> &users)
{
List_iterator <LEX_USER> it(users);
LEX_USER *user, *tmp_user;
while ((tmp_user= it++))
{
if (!(user= get_current_user(thd, tmp_user)))
return true;
reset_mqh(user, 0);
}
return false;
}
bool Sql_cmd_grant_proxy::check_access_proxy(THD *thd, List<LEX_USER> &users)
{
LEX_USER *user;
List_iterator <LEX_USER> it(users);
if ((user= it++))
{
// GRANT/REVOKE PROXY has the target user as a first entry in the list
if (!(user= get_current_user(thd, user)) || !user->host.str)
return true;
if (acl_check_proxy_grant_access(thd, user->host.str, user->user.str,
m_grant_option & GRANT_ACL))
return true;
}
return false;
}
bool Sql_cmd_grant_proxy::execute(THD *thd)
{
LEX *lex= thd->lex;
DBUG_ASSERT(lex->first_select_lex()->table_list.first == NULL);
DBUG_ASSERT((m_grant_option & ~GRANT_ACL) == 0); // only WITH GRANT OPTION
grant_stage0(thd);
if (thd->security_ctx->user /* If not replication */ &&
check_access_proxy(thd, lex->users_list))
return true;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
if (mysql_grant(thd, NULL/*db*/, lex->users_list, m_grant_option,
is_revoke(), true/*proxy*/))
return true;
return !is_revoke() && user_list_reset_mqh(thd, lex->users_list);
#ifdef WITH_WSREP
wsrep_error_label:
return true;
#endif // WITH_WSREP
}
bool Sql_cmd_grant_object::grant_stage0_exact_object(THD *thd,
TABLE_LIST *table)
{
uint priv= m_object_privilege | m_column_privilege_total | GRANT_ACL;
if (check_access(thd, priv, table->db.str,
&table->grant.privilege, &table->grant.m_internal,
0, 0))
return true;
grant_stage0(thd);
return false;
}
bool Sql_cmd_grant_table::execute_exact_table(THD *thd, TABLE_LIST *table)
{
LEX *lex= thd->lex;
if (grant_stage0_exact_object(thd, table) ||
check_grant(thd, m_object_privilege | m_column_privilege_total | GRANT_ACL,
lex->query_tables, FALSE, UINT_MAX, FALSE))
return true;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
return mysql_table_grant(thd, lex->query_tables, lex->users_list,
m_columns, m_object_privilege,
is_revoke());
#ifdef WITH_WSREP
wsrep_error_label:
return true;
#endif // WITH_WSREP
}
bool Sql_cmd_grant_sp::execute(THD *thd)
{
DBUG_ASSERT(!m_columns.elements);
DBUG_ASSERT(!m_column_privilege_total);
LEX *lex= thd->lex;
TABLE_LIST *table= lex->first_select_lex()->table_list.first;
uint grants= m_all_privileges
? (PROC_ACLS & ~GRANT_ACL) | (m_object_privilege & GRANT_ACL)
: m_object_privilege;
if (!table) // e.g: GRANT EXECUTE ON PROCEDURE *.*
{
my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE),
MYF(0));
return true;
}
if (grant_stage0_exact_object(thd, table) ||
check_grant_routine(thd, grants|GRANT_ACL, lex->query_tables, &m_sph, 0))
return true;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (mysql_routine_grant(thd, lex->query_tables, &m_sph,
lex->users_list, grants,
is_revoke(), true))
return true;
my_ok(thd);
return false;
#ifdef WITH_WSREP
wsrep_error_label:
return true;
#endif // WITH_WSREP
}
bool Sql_cmd_grant_table::execute_table_mask(THD *thd)
{
LEX *lex= thd->lex;
DBUG_ASSERT(lex->first_select_lex()->table_list.first == NULL);
if (check_access(thd, m_object_privilege | m_column_privilege_total | GRANT_ACL,
m_db.str, NULL, NULL, 1, 0))
return true;
grant_stage0(thd);
if (m_columns.elements) // e.g. GRANT SELECT (a) ON *.*
{
my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE),
MYF(0));
return true;
}
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
if (mysql_grant(thd, m_db.str, lex->users_list, m_object_privilege,
is_revoke(), false/*not proxy*/))
return true;
return !is_revoke() && user_list_reset_mqh(thd, lex->users_list);
#ifdef WITH_WSREP
wsrep_error_label:
return true;
#endif // WITH_WSREP
}
bool Sql_cmd_grant_table::execute(THD *thd)
{
TABLE_LIST *table= thd->lex->first_select_lex()->table_list.first;
return table ? execute_exact_table(thd, table) :
execute_table_mask(thd);
}
#endif // NO_EMBEDDED_ACCESS_CHECKS
SHOW_VAR acl_statistics[] = {
#ifndef NO_EMBEDDED_ACCESS_CHECKS
{"column_grants", (char*)show_column_grants, SHOW_SIMPLE_FUNC},
......
......@@ -19,6 +19,8 @@
#include "violite.h" /* SSL_type */
#include "sql_class.h" /* LEX_COLUMN */
#include "grant.h"
#include "sql_cmd.h" /* Sql_cmd */
#define SELECT_ACL (1UL << 0)
#define INSERT_ACL (1UL << 1)
......@@ -435,4 +437,78 @@ bool check_role_is_granted(const char *username,
extern ulong role_global_merges, role_db_merges, role_table_merges,
role_column_merges, role_routine_merges;
#endif
class Sql_cmd_grant: public Sql_cmd
{
protected:
enum_sql_command m_command;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
void warn_hostname_requires_resolving(THD *thd, List<LEX_USER> &list);
bool user_list_reset_mqh(THD *thd, List<LEX_USER> &list);
void grant_stage0(THD *thd);
#endif
public:
Sql_cmd_grant(enum_sql_command command)
:m_command(command)
{ }
bool is_revoke() const { return m_command == SQLCOM_REVOKE; }
enum_sql_command sql_command_code() const { return m_command; }
};
class Sql_cmd_grant_proxy: public Sql_cmd_grant
{
uint m_grant_option;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool check_access_proxy(THD *thd, List<LEX_USER> &list);
#endif
public:
Sql_cmd_grant_proxy(enum_sql_command command, uint grant_option)
:Sql_cmd_grant(command), m_grant_option(grant_option)
{ }
bool execute(THD *thd);
};
class Sql_cmd_grant_object: public Sql_cmd_grant, public Grant_privilege
{
protected:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool grant_stage0_exact_object(THD *thd, TABLE_LIST *table);
#endif
public:
Sql_cmd_grant_object(enum_sql_command command, const Grant_privilege &grant)
:Sql_cmd_grant(command), Grant_privilege(grant)
{ }
};
class Sql_cmd_grant_table: public Sql_cmd_grant_object
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool execute_table_mask(THD *thd);
bool execute_exact_table(THD *thd, TABLE_LIST *table);
#endif
public:
Sql_cmd_grant_table(enum_sql_command command, const Grant_privilege &grant)
:Sql_cmd_grant_object(command, grant)
{ }
bool execute(THD *thd);
};
class Sql_cmd_grant_sp: public Sql_cmd_grant_object
{
const Sp_handler &m_sph;
public:
Sql_cmd_grant_sp(enum_sql_command command, const Grant_privilege &grant,
const Sp_handler &sph)
:Sql_cmd_grant_object(command, grant),
m_sph(sph)
{ }
bool execute(THD *thd);
};
#endif /* SQL_ACL_INCLUDED */
......@@ -956,7 +956,7 @@ With_element::rename_columns_of_derived_unit(THD *thd,
if (column_list.elements) // The column list is optional
{
List_iterator_fast<Item> it(select->item_list);
List_iterator_fast<LEX_CSTRING> nm(column_list);
List_iterator_fast<Lex_ident_sys> nm(column_list);
Item *item;
LEX_CSTRING *name;
......@@ -1442,7 +1442,7 @@ void With_element::print(String *str, enum_query_type query_type)
str->append(query_name);
if (column_list.elements)
{
List_iterator_fast<LEX_CSTRING> li(column_list);
List_iterator_fast<Lex_ident_sys> li(column_list);
str->append('(');
for (LEX_CSTRING *col_name= li++; ; )
{
......
......@@ -111,7 +111,7 @@ class With_element : public Sql_alloc
inherited from the query that specified the table. Otherwise the list is
always empty.
*/
List <LEX_CSTRING> column_list;
List <Lex_ident_sys> column_list;
/* The query that specifies the table introduced by this with element */
st_select_lex_unit *spec;
/*
......@@ -163,7 +163,7 @@ class With_element : public Sql_alloc
SQL_I_List<TABLE_LIST> derived_with_rec_ref;
With_element(LEX_CSTRING *name,
List <LEX_CSTRING> list,
List <Lex_ident_sys> list,
st_select_lex_unit *unit)
: next(NULL), base_dep_map(0), derived_dep_map(0),
sq_dep_map(0), work_dep_map(0), mutually_recursive(0),
......
......@@ -9009,16 +9009,13 @@ bool LEX::create_package_finalize(THD *thd,
}
bool LEX::add_grant_command(THD *thd, enum_sql_command sql_command_arg,
stored_procedure_type type_arg)
bool LEX::add_grant_command(THD *thd, const List<LEX_COLUMN> &columns)
{
if (columns.elements)
{
thd->parse_error();
return true;
}
sql_command= sql_command_arg,
type= type_arg;
return false;
}
......@@ -11239,3 +11236,72 @@ bool LEX::add_column_foreign_key(const LEX_CSTRING *name,
return false;
}
bool LEX::stmt_grant_table(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
uint grant_option)
{
sql_command= SQLCOM_GRANT;
return
grant->set_object_name(thd, ident, current_select, grant_option) ||
!(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_table(sql_command, *grant));
}
bool LEX::stmt_revoke_table(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident)
{
sql_command= SQLCOM_REVOKE;
return
grant->set_object_name(thd, ident, current_select, 0) ||
!(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_table(sql_command, *grant));
}
bool LEX::stmt_grant_sp(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
const Sp_handler &sph,
uint grant_option)
{
sql_command= SQLCOM_GRANT;
return
grant->set_object_name(thd, ident, current_select, grant_option) ||
add_grant_command(thd, grant->columns()) ||
!(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_sp(sql_command,
*grant, sph));
}
bool LEX::stmt_revoke_sp(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
const Sp_handler &sph)
{
sql_command= SQLCOM_REVOKE;
return
grant->set_object_name(thd, ident, current_select, 0) ||
add_grant_command(thd, grant->columns()) ||
!(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_sp(sql_command,
*grant, sph));
}
bool LEX::stmt_grant_proxy(THD *thd, LEX_USER *user, uint grant_option)
{
users_list.push_front(user);
sql_command= SQLCOM_GRANT;
return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_proxy(sql_command,
grant_option));
}
bool LEX::stmt_revoke_proxy(THD *thd, LEX_USER *user)
{
users_list.push_front(user);
sql_command= SQLCOM_REVOKE;
return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_proxy(sql_command, 0));
}
......@@ -25,6 +25,7 @@
#include "sql_trigger.h"
#include "thr_lock.h" /* thr_lock_type, TL_UNLOCK */
#include "mem_root_array.h"
#include "grant.h"
#include "sql_cmd.h"
#include "sql_alter.h" // Alter_info
#include "sql_window.h"
......@@ -183,6 +184,24 @@ class Lex_ident_sys: public Lex_ident_sys_st
};
struct Lex_column_list_privilege_st
{
List<Lex_ident_sys> *m_columns;
uint m_privilege;
};
class Lex_column_list_privilege: public Lex_column_list_privilege_st
{
public:
Lex_column_list_privilege(List<Lex_ident_sys> *columns, uint privilege)
{
m_columns= columns;
m_privilege= privilege;
}
};
/**
ORDER BY ... LIMIT parameters;
*/
......@@ -3091,6 +3110,28 @@ class Lex_prepared_stmt
};
class Lex_grant_object_name: public Grant_object_name, public Sql_alloc
{
public:
Lex_grant_object_name(Table_ident *table_ident)
:Grant_object_name(table_ident)
{ }
Lex_grant_object_name(const LEX_CSTRING &db, Type type)
:Grant_object_name(db, type)
{ }
};
class Lex_grant_privilege: public Grant_privilege, public Sql_alloc
{
public:
Lex_grant_privilege() {}
Lex_grant_privilege(uint grant, bool all_privileges= false)
:Grant_privilege(grant, all_privileges)
{ }
};
struct LEX: public Query_tables_list
{
SELECT_LEX_UNIT unit; /* most upper unit */
......@@ -3187,7 +3228,6 @@ struct LEX: public Query_tables_list
Table_type table_type; /* Used for SHOW CREATE */
List<Key_part_spec> ref_list;
List<LEX_USER> users_list;
List<LEX_COLUMN> columns;
List<Item> *insert_list,field_list,value_list,update_list;
List<List_item> many_values;
List<set_var_base> var_list;
......@@ -3309,7 +3349,6 @@ struct LEX: public Query_tables_list
uint profile_query_id;
uint profile_options;
uint grant, grant_tot_col, which_columns;
enum backup_stages backup_stage;
enum Foreign_key::fk_match_opt fk_match_option;
enum_fk_option fk_update_opt;
......@@ -3362,7 +3401,6 @@ struct LEX: public Query_tables_list
sp_head *sphead;
sp_name *spname;
bool sp_lex_in_use; // Keep track on lex usage in SPs for error handling
bool all_privileges;
sp_pcontext *spcont;
......@@ -4374,8 +4412,30 @@ struct LEX: public Query_tables_list
bool add_create_view(THD *thd, DDL_options_st ddl,
uint16 algorithm, enum_view_suid suid,
Table_ident *table_ident);
bool add_grant_command(THD *thd, enum_sql_command sql_command_arg,
stored_procedure_type type_arg);
bool add_grant_command(THD *thd, const List<LEX_COLUMN> &columns);
bool stmt_grant_table(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
uint grant_option);
bool stmt_revoke_table(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident);
bool stmt_grant_sp(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
const Sp_handler &sph,
uint grant_option);
bool stmt_revoke_sp(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
const Sp_handler &sph);
bool stmt_grant_proxy(THD *thd, LEX_USER *user, uint grant_option);
bool stmt_revoke_proxy(THD *thd, LEX_USER *user);
Vers_parse_info &vers_get_info()
{
......
......@@ -5261,113 +5261,6 @@ mysql_execute_command(THD *thd)
my_ok(thd);
break;
}
case SQLCOM_REVOKE:
case SQLCOM_GRANT:
{
if (lex->type != TYPE_ENUM_PROXY &&
check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
first_table ? first_table->db.str : select_lex->db.str,
first_table ? &first_table->grant.privilege : NULL,
first_table ? &first_table->grant.m_internal : NULL,
first_table ? 0 : 1, 0))
goto error;
/* Replicate current user as grantor */
thd->binlog_invoker(false);
if (thd->security_ctx->user) // If not replication
{
LEX_USER *user;
bool first_user= TRUE;
List_iterator <LEX_USER> user_list(lex->users_list);
while ((user= user_list++))
{
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_THD(thd, ER_WARN_HOSTNAME_WONT_WORK));
/*
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;
}
}
}
if (first_table)
{
const Sp_handler *sph= Sp_handler::handler((stored_procedure_type)
lex->type);
if (sph)
{
uint grants= lex->all_privileges
? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
: lex->grant;
if (check_grant_routine(thd, grants | GRANT_ACL, all_tables, sph, 0))
goto error;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_routine_grant(thd, all_tables, sph,
lex->users_list, grants,
lex->sql_command == SQLCOM_REVOKE, TRUE);
if (!res)
my_ok(thd);
}
else
{
if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL),
all_tables, FALSE, UINT_MAX, FALSE))
goto error;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_table_grant(thd, all_tables, lex->users_list,
lex->columns, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
}
}
else
{
if (lex->columns.elements || (lex->type && lex->type != TYPE_ENUM_PROXY))
{
my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE),
MYF(0));
goto error;
}
else
{
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
res= mysql_grant(thd, select_lex->db.str, lex->users_list, lex->grant,
lex->sql_command == SQLCOM_REVOKE,
lex->type == TYPE_ENUM_PROXY);
}
if (!res)
{
if (lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
LEX_USER *user, *tmp_user;
while ((tmp_user=str_list++))
{
if (!(user= get_current_user(thd, tmp_user)))
goto error;
reset_mqh(user, 0);
}
}
}
}
break;
}
case SQLCOM_REVOKE_ROLE:
case SQLCOM_GRANT_ROLE:
{
......@@ -5955,6 +5848,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_RESIGNAL:
case SQLCOM_GET_DIAGNOSTICS:
case SQLCOM_CALL:
case SQLCOM_REVOKE:
case SQLCOM_GRANT:
DBUG_ASSERT(lex->m_sql_cmd != NULL);
res= lex->m_sql_cmd->execute(thd);
DBUG_PRINT("result", ("res: %d killed: %d is_error: %d",
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment