Commit b6025841 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-21957 Bind BINLOG ADMIN to @@binlog_format, @@binlog_direct_.., @@sql_log_bin

parent c7ba9237
......@@ -162,7 +162,7 @@ connection con10;
set sql_log_off = 1;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
set sql_log_bin = 0;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
disconnect con10;
connection default;
delete from mysql.user where user like 'mysqltest\_1';
......
......@@ -14,7 +14,7 @@ set session sql_log_bin = 1;
connection plain;
[plain]
set session sql_log_bin = 1;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
**** Variable BINLOG_FORMAT ****
connection root;
[root]
......@@ -23,9 +23,9 @@ set session binlog_format = row;
connection plain;
[plain]
set global binlog_format = row;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
set session binlog_format = row;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
**** Clean up ****
disconnect plain;
disconnect root;
......
......@@ -45,7 +45,7 @@ SELECT @@session.sql_select_limit = @save_select_limit;
@@session.sql_select_limit = @save_select_limit
1
SET @@session.sql_select_limit=10, @@session.sql_log_bin=0;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
SELECT @@session.sql_select_limit = @save_select_limit;
@@session.sql_select_limit = @save_select_limit
1
......
SET @global= @@global.binlog_direct_non_transactional_updates;
SET @session= @@global.binlog_direct_non_transactional_updates;
#
#
#
# Test that "SET binlog_direct_non_transactional_updates" is not allowed without BINLOG ADMIN or SUPER
CREATE USER user1@localhost;
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
REVOKE BINLOG ADMIN, SUPER ON *.* FROM user1@localhost;
connect user1,localhost,user1,,;
connection user1;
SET binlog_direct_non_transactional_updates=0;
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
SET GLOBAL binlog_direct_non_transactional_updates=0;
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
SET SESSION binlog_direct_non_transactional_updates=0;
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
disconnect user1;
connection default;
DROP USER user1@localhost;
# Test that "SET binlog_direct_non_transactional_updates" is allowed with BINLOG ADMIN
CREATE USER user1@localhost;
GRANT BINLOG ADMIN ON *.* TO user1@localhost;
connect user1,localhost,user1,,;
connection user1;
SET binlog_direct_non_transactional_updates=0;
SET GLOBAL binlog_direct_non_transactional_updates=0;
SET SESSION binlog_direct_non_transactional_updates=0;
disconnect user1;
connection default;
DROP USER user1@localhost;
# Test that "SET binlog_direct_non_transactional_updates" is allowed with SUPER
CREATE USER user1@localhost;
GRANT SUPER ON *.* TO user1@localhost;
connect user1,localhost,user1,,;
connection user1;
SET binlog_direct_non_transactional_updates=0;
SET GLOBAL binlog_direct_non_transactional_updates=0;
SET SESSION binlog_direct_non_transactional_updates=0;
disconnect user1;
connection default;
DROP USER user1@localhost;
SET GLOBAL binlog_direct_non_transactional_updates=@global;
SET SESSION binlog_direct_non_transactional_updates=@session;
#
#
#
# Test that "SET binlog_format" is not allowed without BINLOG ADMIN or SUPER
CREATE USER user1@localhost;
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
REVOKE BINLOG ADMIN, SUPER ON *.* FROM user1@localhost;
connect user1,localhost,user1,,;
connection user1;
SET binlog_format=mixed;
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
SET GLOBAL binlog_format=mixed;
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
SET SESSION binlog_format=mixed;
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
disconnect user1;
connection default;
DROP USER user1@localhost;
# Test that "SET binlog_format" is allowed with BINLOG ADMIN
CREATE USER user1@localhost;
GRANT BINLOG ADMIN ON *.* TO user1@localhost;
connect user1,localhost,user1,,;
connection user1;
SET binlog_format=mixed;
SET GLOBAL binlog_format=mixed;
SET SESSION binlog_format=mixed;
disconnect user1;
connection default;
DROP USER user1@localhost;
# Test that "SET binlog_format" is allowed with SUPER
CREATE USER user1@localhost;
GRANT SUPER ON *.* TO user1@localhost;
connect user1,localhost,user1,,;
connection user1;
SET binlog_format=mixed;
SET GLOBAL binlog_format=mixed;
SET SESSION binlog_format=mixed;
disconnect user1;
connection default;
DROP USER user1@localhost;
#
#
#
# Test that "SET sql_log_bin" is not allowed without BINLOG ADMIN or SUPER
CREATE USER user1@localhost;
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
REVOKE BINLOG ADMIN, SUPER ON *.* FROM user1@localhost;
connect user1,localhost,user1,,;
connection user1;
SET sql_log_bin=1;
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
SET GLOBAL sql_log_bin=1;
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
SET SESSION sql_log_bin=1;
ERROR 42000: Access denied; you need (at least one of) the SUPER, BINLOG ADMIN privilege(s) for this operation
disconnect user1;
connection default;
DROP USER user1@localhost;
# Test that "SET sql_log_bin" is allowed with BINLOG ADMIN
CREATE USER user1@localhost;
GRANT BINLOG ADMIN ON *.* TO user1@localhost;
connect user1,localhost,user1,,;
connection user1;
SET sql_log_bin=1;
SET GLOBAL sql_log_bin=1;
ERROR HY000: Variable 'sql_log_bin' is a SESSION variable
SET SESSION sql_log_bin=1;
disconnect user1;
connection default;
DROP USER user1@localhost;
# Test that "SET sql_log_bin" is allowed with SUPER
CREATE USER user1@localhost;
GRANT SUPER ON *.* TO user1@localhost;
connect user1,localhost,user1,,;
connection user1;
SET sql_log_bin=1;
SET GLOBAL sql_log_bin=1;
ERROR HY000: Variable 'sql_log_bin' is a SESSION variable
SET SESSION sql_log_bin=1;
disconnect user1;
connection default;
DROP USER user1@localhost;
source include/have_log_bin.inc;
SET @global= @@global.binlog_direct_non_transactional_updates;
SET @session= @@global.binlog_direct_non_transactional_updates;
--echo #
--echo #
--echo #
--echo # Test that "SET binlog_direct_non_transactional_updates" is not allowed without BINLOG ADMIN or SUPER
CREATE USER user1@localhost;
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
REVOKE BINLOG ADMIN, SUPER ON *.* FROM user1@localhost;
--connect(user1,localhost,user1,,)
--connection user1
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET binlog_direct_non_transactional_updates=0;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET GLOBAL binlog_direct_non_transactional_updates=0;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET SESSION binlog_direct_non_transactional_updates=0;
--disconnect user1
--connection default
DROP USER user1@localhost;
--echo # Test that "SET binlog_direct_non_transactional_updates" is allowed with BINLOG ADMIN
CREATE USER user1@localhost;
GRANT BINLOG ADMIN ON *.* TO user1@localhost;
--connect(user1,localhost,user1,,)
--connection user1
SET binlog_direct_non_transactional_updates=0;
SET GLOBAL binlog_direct_non_transactional_updates=0;
SET SESSION binlog_direct_non_transactional_updates=0;
--disconnect user1
--connection default
DROP USER user1@localhost;
--echo # Test that "SET binlog_direct_non_transactional_updates" is allowed with SUPER
CREATE USER user1@localhost;
GRANT SUPER ON *.* TO user1@localhost;
--connect(user1,localhost,user1,,)
--connection user1
SET binlog_direct_non_transactional_updates=0;
SET GLOBAL binlog_direct_non_transactional_updates=0;
SET SESSION binlog_direct_non_transactional_updates=0;
--disconnect user1
--connection default
DROP USER user1@localhost;
SET GLOBAL binlog_direct_non_transactional_updates=@global;
SET SESSION binlog_direct_non_transactional_updates=@session;
source include/have_log_bin.inc;
--echo #
--echo #
--echo #
--echo # Test that "SET binlog_format" is not allowed without BINLOG ADMIN or SUPER
CREATE USER user1@localhost;
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
REVOKE BINLOG ADMIN, SUPER ON *.* FROM user1@localhost;
--connect(user1,localhost,user1,,)
--connection user1
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET binlog_format=mixed;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET GLOBAL binlog_format=mixed;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET SESSION binlog_format=mixed;
--disconnect user1
--connection default
DROP USER user1@localhost;
--echo # Test that "SET binlog_format" is allowed with BINLOG ADMIN
CREATE USER user1@localhost;
GRANT BINLOG ADMIN ON *.* TO user1@localhost;
--connect(user1,localhost,user1,,)
--connection user1
SET binlog_format=mixed;
SET GLOBAL binlog_format=mixed;
SET SESSION binlog_format=mixed;
--disconnect user1
--connection default
DROP USER user1@localhost;
--echo # Test that "SET binlog_format" is allowed with SUPER
CREATE USER user1@localhost;
GRANT SUPER ON *.* TO user1@localhost;
--connect(user1,localhost,user1,,)
--connection user1
SET binlog_format=mixed;
SET GLOBAL binlog_format=mixed;
SET SESSION binlog_format=mixed;
--disconnect user1
--connection default
DROP USER user1@localhost;
source include/have_log_bin.inc;
--echo #
--echo #
--echo #
--echo # Test that "SET sql_log_bin" is not allowed without BINLOG ADMIN or SUPER
CREATE USER user1@localhost;
GRANT ALL PRIVILEGES ON *.* TO user1@localhost;
REVOKE BINLOG ADMIN, SUPER ON *.* FROM user1@localhost;
--connect(user1,localhost,user1,,)
--connection user1
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET sql_log_bin=1;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET GLOBAL sql_log_bin=1;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET SESSION sql_log_bin=1;
--disconnect user1
--connection default
DROP USER user1@localhost;
--echo # Test that "SET sql_log_bin" is allowed with BINLOG ADMIN
CREATE USER user1@localhost;
GRANT BINLOG ADMIN ON *.* TO user1@localhost;
--connect(user1,localhost,user1,,)
--connection user1
SET sql_log_bin=1;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SET GLOBAL sql_log_bin=1;
SET SESSION sql_log_bin=1;
--disconnect user1
--connection default
DROP USER user1@localhost;
--echo # Test that "SET sql_log_bin" is allowed with SUPER
CREATE USER user1@localhost;
GRANT SUPER ON *.* TO user1@localhost;
--connect(user1,localhost,user1,,)
--connection user1
SET sql_log_bin=1;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SET GLOBAL sql_log_bin=1;
SET SESSION sql_log_bin=1;
--disconnect user1
--connection default
DROP USER user1@localhost;
......@@ -315,6 +315,15 @@ constexpr privilege_t PRIV_DEBUG= SUPER_ACL;
constexpr privilege_t PRIV_SET_GLOBAL_SYSTEM_VARIABLE= SUPER_ACL;
constexpr privilege_t PRIV_SET_RESTRICTED_SESSION_SYSTEM_VARIABLE= SUPER_ACL;
/* The following variables respected only SUPER_ACL prior to 10.5.2 */
constexpr privilege_t PRIV_SET_SYSTEM_VAR_BINLOG_FORMAT=
SUPER_ACL | BINLOG_ADMIN_ACL;
constexpr privilege_t PRIV_SET_SYSTEM_VAR_BINLOG_DIRECT_NON_TRANSACTIONAL_UPDATES=
SUPER_ACL | BINLOG_ADMIN_ACL;
constexpr privilege_t PRIV_SET_SYSTEM_VAR_SQL_LOG_BIN=
SUPER_ACL | BINLOG_ADMIN_ACL;
/* Privileges related to --read-only */
constexpr privilege_t PRIV_IGNORE_READ_ONLY= READ_ONLY_ADMIN_ACL | SUPER_ACL;
......
......@@ -756,6 +756,11 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free)
Functions to handle SET mysql_internal_variable=const_expr
*****************************************************************************/
bool sys_var::on_check_access_global(THD *thd) const
{
return check_global_access(thd, PRIV_SET_GLOBAL_SYSTEM_VARIABLE);
}
/**
Verify that the supplied value is correct.
......@@ -780,8 +785,7 @@ int set_var::check(THD *thd)
my_error(err, MYF(0), var->name.str);
return -1;
}
if (type == OPT_GLOBAL &&
check_global_access(thd, PRIV_SET_GLOBAL_SYSTEM_VARIABLE))
if (type == OPT_GLOBAL && var->on_check_access_global(thd))
return 1;
/* value is a NULL pointer if we are using SET ... = DEFAULT */
if (!value)
......@@ -794,6 +798,16 @@ int set_var::check(THD *thd)
my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name.str);
return -1;
}
switch (type) {
case SHOW_OPT_DEFAULT:
case SHOW_OPT_SESSION:
DBUG_ASSERT(var->scope() != sys_var::GLOBAL);
if (var->on_check_access_session(thd))
return -1;
break;
case SHOW_OPT_GLOBAL: // Checked earlier
break;
}
return var->check(thd, this) ? -1 : 0;
}
......
......@@ -214,6 +214,12 @@ class sys_var: protected Value_source // for double_from_string_with_check
virtual uchar *default_value_ptr(THD *thd)
{ return (uchar*)&option.def_value; }
virtual bool on_check_access_global(THD *thd) const;
virtual bool on_check_access_session(THD *thd) const
{
return false;
}
private:
virtual bool do_check(THD *thd, set_var *var) = 0;
/**
......
......@@ -601,9 +601,6 @@ static Sys_var_bit Sys_core_file("core_file", "write a core-file on crashes",
static bool binlog_format_check(sys_var *self, THD *thd, set_var *var)
{
if (check_has_super(self, thd, var))
return true;
/*
MariaDB Galera does not support STATEMENT or MIXED binlog format currently.
*/
......@@ -674,7 +671,10 @@ static bool fix_binlog_format_after_update(sys_var *self, THD *thd,
return false;
}
static Sys_var_enum Sys_binlog_format(
static Sys_var_on_access<Sys_var_enum,
PRIV_SET_SYSTEM_VAR_BINLOG_FORMAT,
PRIV_SET_SYSTEM_VAR_BINLOG_FORMAT>
Sys_binlog_format(
"binlog_format", "What form of binary logging the master will "
"use: either ROW for row-based binary logging, STATEMENT "
"for statement-based binary logging, or MIXED. MIXED is statement-"
......@@ -689,9 +689,6 @@ static Sys_var_enum Sys_binlog_format(
static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var)
{
if (check_has_super(self, thd, var))
return true;
if (var->type == OPT_GLOBAL)
return false;
......@@ -703,7 +700,10 @@ static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var)
return false;
}
static Sys_var_mybool Sys_binlog_direct(
static Sys_var_on_access<Sys_var_mybool,
PRIV_SET_SYSTEM_VAR_BINLOG_DIRECT_NON_TRANSACTIONAL_UPDATES,
PRIV_SET_SYSTEM_VAR_BINLOG_DIRECT_NON_TRANSACTIONAL_UPDATES>
Sys_binlog_direct(
"binlog_direct_non_transactional_updates",
"Causes updates to non-transactional engines using statement format to "
"be written directly to binary log. Before using this option make sure "
......@@ -4297,9 +4297,6 @@ static bool check_session_only_variable(sys_var *self, THD *,set_var *var)
*/
static bool check_sql_log_bin(sys_var *self, THD *thd, set_var *var)
{
if (check_has_super(self, thd, var))
return true;
if (check_session_only_variable(self, thd, var))
return true;
......@@ -4311,7 +4308,10 @@ static bool check_sql_log_bin(sys_var *self, THD *thd, set_var *var)
return false;
}
static Sys_var_mybool Sys_log_binlog(
static Sys_var_on_access<Sys_var_mybool,
PRIV_SET_SYSTEM_VAR_SQL_LOG_BIN,
PRIV_SET_SYSTEM_VAR_SQL_LOG_BIN>
Sys_sql_log_bin(
"sql_log_bin", "If set to 0 (1 is the default), no logging to the binary "
"log is done for the client. Only clients with the SUPER privilege can "
"update this variable. Can have unintended consequences if set globally, "
......
......@@ -31,6 +31,7 @@
#include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone
#include "rpl_mi.h" // For Multi-Source Replication
#include "debug_sync.h"
#include "sql_acl.h" // check_global_access()
/*
a set of mostly trivial (as in f(X)=X) defines below to make system variable
......@@ -101,6 +102,22 @@
static const char *bool_values[3]= {"OFF", "ON", 0};
TYPELIB bool_typelib={ array_elements(bool_values)-1, "", bool_values, 0 };
template<class BASE, privilege_t GLOBAL_PRIV, privilege_t SESSION_PRIV>
class Sys_var_on_access: public BASE
{
using BASE::BASE;
bool on_check_access_global(THD *thd) const override
{
return check_global_access(thd, GLOBAL_PRIV);
}
bool on_check_access_session(THD *thd) const override
{
return check_global_access(thd, SESSION_PRIV);
}
};
/**
A small wrapper class to pass getopt arguments as a pair
to the Sys_var_* constructors. It improves type safety and helps
......
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