mirror of
https://github.com/MariaDB/server.git
synced 2025-07-05 12:42:17 +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
134
mysql-test/main/lock_user.result
Normal file
134
mysql-test/main/lock_user.result
Normal file
@ -0,0 +1,134 @@
|
||||
create user user1@localhost;
|
||||
create user user2@localhost;
|
||||
#
|
||||
# Only privileged users should be able to lock/unlock.
|
||||
#
|
||||
alter user user1@localhost account lock;
|
||||
alter user user1@localhost account unlock;
|
||||
create user user3@localhost account lock;
|
||||
drop user user3@localhost;
|
||||
connect con1,localhost,user1;
|
||||
connection con1;
|
||||
alter user user2@localhost account lock;
|
||||
ERROR 42000: Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation
|
||||
disconnect con1;
|
||||
connection default;
|
||||
#
|
||||
# ALTER USER USER1 ACCOUNT LOCK should deny the connection of user1,
|
||||
# but it should allow user2 to connect.
|
||||
#
|
||||
alter user user1@localhost account lock;
|
||||
connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||
connect con1,localhost,user1;
|
||||
ERROR HY000: Access denied, this account is locked
|
||||
connect con2,localhost,user2;
|
||||
disconnect con2;
|
||||
connection default;
|
||||
alter user user1@localhost account unlock;
|
||||
#
|
||||
# Passing an incorrect user should return an error unless
|
||||
# IF EXISTS is used
|
||||
#
|
||||
alter user inexistentUser@localhost account lock;
|
||||
ERROR HY000: Operation ALTER USER failed for 'inexistentUser'@'localhost'
|
||||
alter if exists user inexistentUser@localhost account lock;
|
||||
Warnings:
|
||||
Error 1133 Can't find any matching row in the user table
|
||||
Note 1396 Operation ALTER USER failed for 'inexistentUser'@'localhost'
|
||||
#
|
||||
# Passing an existing user to CREATE should not be allowed
|
||||
# and it should not change the locking state of the current user
|
||||
#
|
||||
show create user user1@localhost;
|
||||
CREATE USER for user1@localhost
|
||||
CREATE USER 'user1'@'localhost'
|
||||
create user user1@localhost account lock;
|
||||
ERROR HY000: Operation CREATE USER failed for 'user1'@'localhost'
|
||||
show create user user1@localhost;
|
||||
CREATE USER for user1@localhost
|
||||
CREATE USER 'user1'@'localhost'
|
||||
#
|
||||
# Passing multiple users should lock them all
|
||||
#
|
||||
alter user user1@localhost, user2@localhost account lock;
|
||||
connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||
connect con1,localhost,user1;
|
||||
ERROR HY000: Access denied, this account is locked
|
||||
connect(localhost,user2,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||
connect con2,localhost,user2;
|
||||
ERROR HY000: Access denied, this account is locked
|
||||
alter user user1@localhost, user2@localhost account unlock;
|
||||
#
|
||||
# The locking state is preserved after acl reload
|
||||
#
|
||||
alter user user1@localhost account lock;
|
||||
flush privileges;
|
||||
connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||
connect con1,localhost,user1;
|
||||
ERROR HY000: Access denied, this account is locked
|
||||
alter user user1@localhost account unlock;
|
||||
#
|
||||
# JSON functions on global_priv reflect the locking state of an account
|
||||
#
|
||||
alter user user1@localhost account lock;
|
||||
select host, user, JSON_VALUE(Priv, '$.account_locked') from mysql.global_priv where user='user1';
|
||||
host user JSON_VALUE(Priv, '$.account_locked')
|
||||
localhost user1 1
|
||||
alter user user1@localhost account unlock;
|
||||
select host, user, JSON_VALUE(Priv, '$.account_locked') from mysql.global_priv where user='user1';
|
||||
host user JSON_VALUE(Priv, '$.account_locked')
|
||||
localhost user1 0
|
||||
#
|
||||
# SHOW CREATE USER correctly displays the locking state of an user
|
||||
#
|
||||
show create user user1@localhost;
|
||||
CREATE USER for user1@localhost
|
||||
CREATE USER 'user1'@'localhost'
|
||||
alter user user1@localhost account lock;
|
||||
show create user user1@localhost;
|
||||
CREATE USER for user1@localhost
|
||||
CREATE USER 'user1'@'localhost' ACCOUNT LOCK
|
||||
alter user user1@localhost account unlock;
|
||||
show create user user1@localhost;
|
||||
CREATE USER for user1@localhost
|
||||
CREATE USER 'user1'@'localhost'
|
||||
create user newuser@localhost account lock;
|
||||
show create user newuser@localhost;
|
||||
CREATE USER for newuser@localhost
|
||||
CREATE USER 'newuser'@'localhost' ACCOUNT LOCK
|
||||
drop user newuser@localhost;
|
||||
#
|
||||
# Users should be able to lock themselves
|
||||
#
|
||||
grant CREATE USER on *.* to user1@localhost;
|
||||
connect con1,localhost,user1;
|
||||
connection con1;
|
||||
alter user user1@localhost account lock;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||
connect con1,localhost,user1;
|
||||
ERROR HY000: Access denied, this account is locked
|
||||
alter user user1@localhost account unlock;
|
||||
#
|
||||
# Users should be able to unlock themselves if the connections
|
||||
# had been established before the accounts were locked
|
||||
#
|
||||
grant CREATE USER on *.* to user1@localhost;
|
||||
connect con1,localhost,user1;
|
||||
alter user user1@localhost account lock;
|
||||
connection con1;
|
||||
alter user user1@localhost account unlock;
|
||||
show create user user1@localhost;
|
||||
CREATE USER for user1@localhost
|
||||
CREATE USER 'user1'@'localhost'
|
||||
disconnect con1;
|
||||
connection default;
|
||||
#
|
||||
# COM_CHANGE_USER should return error if the destination
|
||||
# account is locked
|
||||
#
|
||||
alter user user1@localhost account lock;
|
||||
ERROR HY000: Access denied, this account is locked
|
||||
drop user user1@localhost;
|
||||
drop user user2@localhost;
|
142
mysql-test/main/lock_user.test
Normal file
142
mysql-test/main/lock_user.test
Normal file
@ -0,0 +1,142 @@
|
||||
#
|
||||
# Test user account locking
|
||||
#
|
||||
|
||||
--source include/not_embedded.inc
|
||||
|
||||
create user user1@localhost;
|
||||
create user user2@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Only privileged users should be able to lock/unlock.
|
||||
--echo #
|
||||
alter user user1@localhost account lock;
|
||||
alter user user1@localhost account unlock;
|
||||
create user user3@localhost account lock;
|
||||
drop user user3@localhost;
|
||||
|
||||
connect(con1,localhost,user1);
|
||||
connection con1;
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
alter user user2@localhost account lock;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
--echo #
|
||||
--echo # ALTER USER USER1 ACCOUNT LOCK should deny the connection of user1,
|
||||
--echo # but it should allow user2 to connect.
|
||||
--echo #
|
||||
|
||||
alter user user1@localhost account lock;
|
||||
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||
--error ER_ACCOUNT_HAS_BEEN_LOCKED
|
||||
connect(con1,localhost,user1);
|
||||
connect(con2,localhost,user2);
|
||||
disconnect con2;
|
||||
connection default;
|
||||
alter user user1@localhost account unlock;
|
||||
|
||||
--echo #
|
||||
--echo # Passing an incorrect user should return an error unless
|
||||
--echo # IF EXISTS is used
|
||||
--echo #
|
||||
|
||||
--error ER_CANNOT_USER
|
||||
alter user inexistentUser@localhost account lock;
|
||||
|
||||
alter if exists user inexistentUser@localhost account lock;
|
||||
|
||||
--echo #
|
||||
--echo # Passing an existing user to CREATE should not be allowed
|
||||
--echo # and it should not change the locking state of the current user
|
||||
--echo #
|
||||
|
||||
show create user user1@localhost;
|
||||
--error ER_CANNOT_USER
|
||||
create user user1@localhost account lock;
|
||||
show create user user1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Passing multiple users should lock them all
|
||||
--echo #
|
||||
|
||||
alter user user1@localhost, user2@localhost account lock;
|
||||
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||
--error ER_ACCOUNT_HAS_BEEN_LOCKED
|
||||
connect(con1,localhost,user1);
|
||||
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||
--error ER_ACCOUNT_HAS_BEEN_LOCKED
|
||||
connect(con2,localhost,user2);
|
||||
alter user user1@localhost, user2@localhost account unlock;
|
||||
|
||||
--echo #
|
||||
--echo # The locking state is preserved after acl reload
|
||||
--echo #
|
||||
|
||||
alter user user1@localhost account lock;
|
||||
flush privileges;
|
||||
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||
--error ER_ACCOUNT_HAS_BEEN_LOCKED
|
||||
connect(con1,localhost,user1);
|
||||
alter user user1@localhost account unlock;
|
||||
|
||||
--echo #
|
||||
--echo # JSON functions on global_priv reflect the locking state of an account
|
||||
--echo #
|
||||
|
||||
alter user user1@localhost account lock;
|
||||
select host, user, JSON_VALUE(Priv, '$.account_locked') from mysql.global_priv where user='user1';
|
||||
alter user user1@localhost account unlock;
|
||||
select host, user, JSON_VALUE(Priv, '$.account_locked') from mysql.global_priv where user='user1';
|
||||
|
||||
--echo #
|
||||
--echo # SHOW CREATE USER correctly displays the locking state of an user
|
||||
--echo #
|
||||
|
||||
show create user user1@localhost;
|
||||
alter user user1@localhost account lock;
|
||||
show create user user1@localhost;
|
||||
alter user user1@localhost account unlock;
|
||||
show create user user1@localhost;
|
||||
create user newuser@localhost account lock;
|
||||
show create user newuser@localhost;
|
||||
drop user newuser@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Users should be able to lock themselves
|
||||
--echo #
|
||||
grant CREATE USER on *.* to user1@localhost;
|
||||
connect(con1,localhost,user1);
|
||||
connection con1;
|
||||
alter user user1@localhost account lock;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||
--error ER_ACCOUNT_HAS_BEEN_LOCKED
|
||||
connect(con1,localhost,user1);
|
||||
alter user user1@localhost account unlock;
|
||||
|
||||
--echo #
|
||||
--echo # Users should be able to unlock themselves if the connections
|
||||
--echo # had been established before the accounts were locked
|
||||
--echo #
|
||||
grant CREATE USER on *.* to user1@localhost;
|
||||
connect(con1,localhost,user1);
|
||||
alter user user1@localhost account lock;
|
||||
connection con1;
|
||||
alter user user1@localhost account unlock;
|
||||
show create user user1@localhost;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
--echo #
|
||||
--echo # COM_CHANGE_USER should return error if the destination
|
||||
--echo # account is locked
|
||||
--echo #
|
||||
alter user user1@localhost account lock;
|
||||
--error ER_ACCOUNT_HAS_BEEN_LOCKED
|
||||
--change_user user1
|
||||
|
||||
drop user user1@localhost;
|
||||
drop user user2@localhost;
|
||||
|
@ -165,5 +165,26 @@ foo % Y mysql_native_password *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB
|
||||
goo % Y mysql_native_password *F3A2A51A9B0F2BE2468926B4132313728C250DBF
|
||||
ioo % Y mysql_old_password 7a8f886d28473e85
|
||||
#
|
||||
# Test account locking
|
||||
#
|
||||
create user user1@localhost account lock;
|
||||
connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||
connect con1,localhost,user1;
|
||||
ERROR HY000: Access denied, this account is locked
|
||||
flush privileges;
|
||||
connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||
connect con1,localhost,user1;
|
||||
ERROR HY000: Access denied, this account is locked
|
||||
show create user user1@localhost;
|
||||
CREATE USER for user1@localhost
|
||||
CREATE USER 'user1'@'localhost' ACCOUNT LOCK
|
||||
alter user user1@localhost account unlock;
|
||||
connect con1,localhost,user1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
show create user user1@localhost;
|
||||
CREATE USER for user1@localhost
|
||||
CREATE USER 'user1'@'localhost'
|
||||
#
|
||||
# Reset to final original state.
|
||||
#
|
||||
|
@ -88,6 +88,24 @@ select user, host, select_priv, plugin, authentication_string from mysql.user
|
||||
where user like "%oo"
|
||||
order by user;
|
||||
|
||||
--echo #
|
||||
--echo # Test account locking
|
||||
--echo #
|
||||
create user user1@localhost account lock;
|
||||
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||
--error ER_ACCOUNT_HAS_BEEN_LOCKED
|
||||
connect(con1,localhost,user1);
|
||||
flush privileges;
|
||||
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||
--error ER_ACCOUNT_HAS_BEEN_LOCKED
|
||||
connect(con1,localhost,user1);
|
||||
show create user user1@localhost;
|
||||
alter user user1@localhost account unlock;
|
||||
connect(con1,localhost,user1);
|
||||
disconnect con1;
|
||||
connection default;
|
||||
show create user user1@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # Reset to final original state.
|
||||
--echo #
|
||||
|
@ -643,6 +643,7 @@ ALTER TABLE user ADD plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL,
|
||||
ALTER TABLE user MODIFY plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL,
|
||||
MODIFY authentication_string TEXT NOT NULL;
|
||||
ALTER TABLE user ADD password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL;
|
||||
ALTER TABLE user ADD account_locked enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL after password_expired;
|
||||
ALTER TABLE user ADD is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL;
|
||||
ALTER TABLE user ADD default_role char(80) binary DEFAULT '' NOT NULL;
|
||||
ALTER TABLE user ADD max_statement_time decimal(12,6) DEFAULT 0 NOT NULL;
|
||||
@ -804,6 +805,7 @@ IF 'BASE TABLE' = (select table_type from information_schema.tables where table_
|
||||
'max_statement_time', max_statement_time,
|
||||
'plugin', if(plugin>'',plugin,if(length(password)=16,'mysql_old_password','mysql_native_password')),
|
||||
'authentication_string', if(plugin>'' and authentication_string>'',authentication_string,password),
|
||||
'account_locked', 'Y'=account_locked,
|
||||
'default_role', default_role,
|
||||
'is_role', 'Y'=is_role)) as Priv
|
||||
FROM user;
|
||||
|
@ -55,6 +55,7 @@ static SYMBOL symbols[] = {
|
||||
{ ">>", SYM(SHIFT_RIGHT)},
|
||||
{ "<=>", SYM(EQUAL_SYM)},
|
||||
{ "ACCESSIBLE", SYM(ACCESSIBLE_SYM)},
|
||||
{ "ACCOUNT", SYM(ACCOUNT_SYM)},
|
||||
{ "ACTION", SYM(ACTION)},
|
||||
{ "ADD", SYM(ADD)},
|
||||
{ "ADMIN", SYM(ADMIN_SYM)},
|
||||
|
@ -7933,3 +7933,6 @@ ER_BACKUP_UNKNOWN_STAGE
|
||||
eng "Unknown backup stage: '%s'. Stage should be one of START, FLUSH, BLOCK_DDL, BLOCK_COMMIT or END"
|
||||
ER_USER_IS_BLOCKED
|
||||
eng "User is blocked because of too many credential errors; unblock with 'FLUSH PRIVILEGES'"
|
||||
ER_ACCOUNT_HAS_BEEN_LOCKED
|
||||
eng "Access denied, this account is locked"
|
||||
rum "Acces refuzat, acest cont este blocat"
|
||||
|
@ -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
|
||||
|
@ -2939,6 +2939,27 @@ public:
|
||||
Explain_delete* save_explain_delete_data(MEM_ROOT *mem_root, THD *thd);
|
||||
};
|
||||
|
||||
enum account_lock_type
|
||||
{
|
||||
ACCOUNTLOCK_UNSPECIFIED,
|
||||
ACCOUNTLOCK_LOCKED,
|
||||
ACCOUNTLOCK_UNLOCKED
|
||||
};
|
||||
|
||||
struct Account_options
|
||||
{
|
||||
Account_options()
|
||||
: account_locked(ACCOUNTLOCK_UNSPECIFIED)
|
||||
{ }
|
||||
|
||||
void reset()
|
||||
{
|
||||
account_locked= ACCOUNTLOCK_UNSPECIFIED;
|
||||
}
|
||||
|
||||
account_lock_type account_locked;
|
||||
};
|
||||
|
||||
|
||||
class Query_arena_memroot;
|
||||
/* The state of the lex parsing. This is saved in the THD struct */
|
||||
@ -3030,6 +3051,9 @@ public:
|
||||
*/
|
||||
LEX_USER *definer;
|
||||
|
||||
/* Used in ALTER/CREATE user to store account locking options */
|
||||
Account_options account_options;
|
||||
|
||||
Table_type table_type; /* Used for SHOW CREATE */
|
||||
List<Key_part_spec> ref_list;
|
||||
List<LEX_USER> users_list;
|
||||
|
@ -1151,6 +1151,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
Non-reserved keywords
|
||||
*/
|
||||
|
||||
%token <kwd> ACCOUNT_SYM /* MYSQL */
|
||||
%token <kwd> ACTION /* SQL-2003-N */
|
||||
%token <kwd> ADMIN_SYM /* SQL-2003-N */
|
||||
%token <kwd> ADDDATE_SYM /* MYSQL-FUNC */
|
||||
@ -2911,7 +2912,7 @@ create:
|
||||
Lex->pop_select(); //main select
|
||||
}
|
||||
| create_or_replace USER_SYM opt_if_not_exists clear_privileges
|
||||
grant_list opt_require_clause opt_resource_options
|
||||
grant_list opt_require_clause opt_resource_options opt_account_locking
|
||||
{
|
||||
if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER,
|
||||
$1 | $3)))
|
||||
@ -3318,6 +3319,7 @@ clear_privileges:
|
||||
lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
|
||||
lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
|
||||
bzero((char *)&(lex->mqh),sizeof(lex->mqh));
|
||||
lex->account_options.reset();
|
||||
}
|
||||
;
|
||||
|
||||
@ -7979,7 +7981,7 @@ alter:
|
||||
} OPTIONS_SYM '(' server_options_list ')' { }
|
||||
/* ALTER USER foo is allowed for MySQL compatibility. */
|
||||
| ALTER opt_if_exists USER_SYM clear_privileges grant_list
|
||||
opt_require_clause opt_resource_options
|
||||
opt_require_clause opt_resource_options opt_account_locking
|
||||
{
|
||||
Lex->create_info.set($2);
|
||||
Lex->sql_command= SQLCOM_ALTER_USER;
|
||||
@ -8018,6 +8020,18 @@ alter:
|
||||
}
|
||||
;
|
||||
|
||||
opt_account_locking:
|
||||
/* Nothing */ {}
|
||||
| ACCOUNT_SYM LOCK_SYM
|
||||
{
|
||||
Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED;
|
||||
}
|
||||
| ACCOUNT_SYM UNLOCK_SYM
|
||||
{
|
||||
Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED;
|
||||
}
|
||||
;
|
||||
|
||||
ev_alter_on_schedule_completion:
|
||||
/* empty */ { $$= 0;}
|
||||
| ON SCHEDULE_SYM ev_schedule_time { $$= 1; }
|
||||
@ -15855,6 +15869,7 @@ keyword_data_type:
|
||||
*/
|
||||
keyword_sp_var_and_label:
|
||||
ACTION
|
||||
| ACCOUNT_SYM
|
||||
| ADDDATE_SYM
|
||||
| ADMIN_SYM
|
||||
| AFTER_SYM
|
||||
|
@ -646,6 +646,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
Non-reserved keywords
|
||||
*/
|
||||
|
||||
%token <kwd> ACCOUNT_SYM /* MYSQL */
|
||||
%token <kwd> ACTION /* SQL-2003-N */
|
||||
%token <kwd> ADMIN_SYM /* SQL-2003-N */
|
||||
%token <kwd> ADDDATE_SYM /* MYSQL-FUNC */
|
||||
@ -2417,7 +2418,7 @@ create:
|
||||
Lex->pop_select(); //main select
|
||||
}
|
||||
| create_or_replace USER_SYM opt_if_not_exists clear_privileges
|
||||
grant_list opt_require_clause opt_resource_options
|
||||
grant_list opt_require_clause opt_resource_options opt_account_locking
|
||||
{
|
||||
if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER,
|
||||
$1 | $3)))
|
||||
@ -8009,7 +8010,7 @@ alter:
|
||||
} OPTIONS_SYM '(' server_options_list ')' { }
|
||||
/* ALTER USER foo is allowed for MySQL compatibility. */
|
||||
| ALTER opt_if_exists USER_SYM clear_privileges grant_list
|
||||
opt_require_clause opt_resource_options
|
||||
opt_require_clause opt_resource_options opt_account_locking
|
||||
{
|
||||
Lex->create_info.set($2);
|
||||
Lex->sql_command= SQLCOM_ALTER_USER;
|
||||
@ -8048,6 +8049,18 @@ alter:
|
||||
}
|
||||
;
|
||||
|
||||
opt_account_locking:
|
||||
/* Nothing */ {}
|
||||
| ACCOUNT_SYM LOCK_SYM
|
||||
{
|
||||
Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED;
|
||||
}
|
||||
| ACCOUNT_SYM UNLOCK_SYM
|
||||
{
|
||||
Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED;
|
||||
}
|
||||
;
|
||||
|
||||
ev_alter_on_schedule_completion:
|
||||
/* empty */ { $$= 0;}
|
||||
| ON SCHEDULE_SYM ev_schedule_time { $$= 1; }
|
||||
@ -15943,6 +15956,7 @@ keyword_data_type:
|
||||
*/
|
||||
keyword_sp_var_and_label:
|
||||
ACTION
|
||||
| ACCOUNT_SYM
|
||||
| ADDDATE_SYM
|
||||
| ADMIN_SYM
|
||||
| AFTER_SYM
|
||||
|
Reference in New Issue
Block a user