mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-13095 Implement User Account locking
Add server support for user account locking. This patch extends the ALTER/CREATE USER statements for denying a user's subsequent login attempts: ALTER USER user [, user2] ACCOUNT [LOCK | UNLOCK] CREATE USER user [, user2] ACCOUNT [LOCK | UNLOCK] The SHOW CREATE USER statement was updated to display the locking state of an user. Closes #1006
This commit is contained in:
committed by
Sergei Golubchik
parent
d89cdfc229
commit
6c8ce999f8
@ -152,6 +152,7 @@ public:
|
||||
LEX_CSTRING default_rolename;
|
||||
struct AUTH { LEX_CSTRING plugin, auth_string, salt; } *auth;
|
||||
uint nauth;
|
||||
bool account_locked;
|
||||
|
||||
bool alloc_auth(MEM_ROOT *root, uint n)
|
||||
{
|
||||
@ -864,6 +865,8 @@ class User_table: public Grant_table_base
|
||||
virtual int set_is_role (bool x) const = 0;
|
||||
virtual const char* get_default_role (MEM_ROOT *root) const = 0;
|
||||
virtual int set_default_role (const char *s, size_t l) const = 0;
|
||||
virtual bool get_account_locked () const = 0;
|
||||
virtual int set_account_locked (bool x) const = 0;
|
||||
|
||||
virtual ~User_table() {}
|
||||
private:
|
||||
@ -1123,7 +1126,22 @@ class User_table_tabular: public User_table
|
||||
return f->store(s, l, system_charset_info);
|
||||
else
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
/* On a MariaDB 10.3 user table, the account locking accessors will try to
|
||||
get the content of the max_statement_time column, but they will fail due
|
||||
to the typecheck in get_field. */
|
||||
bool get_account_locked () const
|
||||
{
|
||||
Field *f= get_field(end_priv_columns + 13, MYSQL_TYPE_ENUM);
|
||||
return f ? f->val_int()-1 : 0;
|
||||
}
|
||||
int set_account_locked (bool x) const
|
||||
{
|
||||
if (Field *f= get_field(end_priv_columns + 13, MYSQL_TYPE_ENUM))
|
||||
return f->store(x+1, 0);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual ~User_table_tabular() {}
|
||||
private:
|
||||
@ -1416,6 +1434,10 @@ class User_table_json: public User_table
|
||||
{ return get_str_value(root, "default_role"); }
|
||||
int set_default_role (const char *s, size_t l) const
|
||||
{ return set_str_value("default_role", s, l); }
|
||||
bool get_account_locked () const
|
||||
{ return get_bool_value("account_locked"); }
|
||||
int set_account_locked (bool x) const
|
||||
{ return set_bool_value("account_locked", x); }
|
||||
|
||||
~User_table_json() {}
|
||||
private:
|
||||
@ -2260,6 +2282,8 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
|
||||
|
||||
my_init_dynamic_array(&user.role_grants, sizeof(ACL_ROLE *), 0, 8, MYF(0));
|
||||
|
||||
user.account_locked= user_table.get_account_locked();
|
||||
|
||||
if (is_role)
|
||||
{
|
||||
if (is_invalid_role_name(username))
|
||||
@ -4327,6 +4351,13 @@ static int replace_user_table(THD *thd, const User_table &user_table,
|
||||
mqh_used= (mqh_used || lex->mqh.questions || lex->mqh.updates ||
|
||||
lex->mqh.conn_per_hour || lex->mqh.user_conn ||
|
||||
lex->mqh.max_statement_time != 0.0);
|
||||
|
||||
if (lex->account_options.account_locked != ACCOUNTLOCK_UNSPECIFIED)
|
||||
{
|
||||
bool lock_value= lex->account_options.account_locked == ACCOUNTLOCK_LOCKED;
|
||||
user_table.set_account_locked(lock_value);
|
||||
new_acl_user.account_locked= lock_value;
|
||||
}
|
||||
}
|
||||
|
||||
if (old_row_exists)
|
||||
@ -8780,6 +8811,9 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
|
||||
|
||||
add_user_parameters(&result, acl_user, false);
|
||||
|
||||
if (acl_user->account_locked)
|
||||
result.append(STRING_WITH_LEN(" ACCOUNT LOCK"));
|
||||
|
||||
protocol->prepare_for_resend();
|
||||
protocol->store(result.ptr(), result.length(), result.charset());
|
||||
if (protocol->write())
|
||||
@ -13641,6 +13675,12 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (acl_user->account_locked) {
|
||||
status_var_increment(denied_connections);
|
||||
my_error(ER_ACCOUNT_HAS_BEEN_LOCKED, MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/*
|
||||
Don't allow the user to connect if he has done too many queries.
|
||||
As we are testing max_user_connections == 0 here, it means that we
|
||||
|
Reference in New Issue
Block a user