MDEV-25197: The statement set password=password('') executed in PS mode fails in case it is run by a user with expired password
A user connected to a server with an expired password can't change password with the statement "SET password=..." if this statement is run in PS mode. In mentioned use case a user gets the error ER_MUST_CHANGE_PASSWORD on attempt to run the statement PREPARE stmt FOR "SET password=..."; The reason of failure to reset password by a locked user using the statement PREPARE stmt FOR "SET password=..." is that PS-related statements are not listed among the commands allowed for execution by a user with expired password. However, simple adding of PS-related statements (PREPARE FOR/EXECUTE/DEALLOCATE PREPARE ) to the list of statements allowed for execution by a locked user is not enough to solve problems, since it opens the opportunity for a locked user to execute any statement in the PS mode. To exclude this opportunity, additional checking that the statement being prepared for execution in PS-mode is the SET statement has to be added. This extra checking has been added by this patch into the method Prepared_statement::prepared() that executed on preparing any statement for execution in PS-mode.
This commit is contained in:
parent
e14b682636
commit
61f84bba60
@ -5536,5 +5536,37 @@ DEALLOCATE PREPARE stmt;
|
|||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-25197: The statement set password=password('') executed in PS mode
|
||||||
|
# fails in case it is run by a user with expired password
|
||||||
|
#
|
||||||
|
CREATE USER user1@localhost PASSWORD EXPIRE;
|
||||||
|
SET @disconnect_on_expired_password_save=@@global.disconnect_on_expired_password;
|
||||||
|
SET GLOBAL disconnect_on_expired_password=OFF;
|
||||||
|
connect con1,localhost,user1;
|
||||||
|
connection con1;
|
||||||
|
# Check that no regular statement like SELECT can be prepared
|
||||||
|
# by a user with an expired password
|
||||||
|
PREPARE stmt FROM "SELECT 1";
|
||||||
|
ERROR HY000: You must SET PASSWORD before executing this statement
|
||||||
|
# Check that the DEALLOCATE PREPARE statement can be run by a user
|
||||||
|
# with an expired password
|
||||||
|
PREPARE stmt FROM "SET password=password('')";
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
# Check that the SET PASSWORD statement can be executed in PS mode by
|
||||||
|
# a user with an expired password
|
||||||
|
PREPARE stmt FROM "SET password=password('')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
PREPARE stmt FROM "SELECT 1";
|
||||||
|
# Check that user's password is not expired anymore
|
||||||
|
EXECUTE stmt;
|
||||||
|
1
|
||||||
|
1
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
# Clean up
|
||||||
|
disconnect con1;
|
||||||
|
connection default;
|
||||||
|
SET GLOBAL disconnect_on_expired_password=@disconnect_on_expired_password_save;
|
||||||
|
DROP USER user1@localhost;
|
||||||
|
#
|
||||||
# End of 10.4 tests
|
# End of 10.4 tests
|
||||||
#
|
#
|
||||||
|
@ -4979,6 +4979,43 @@ DEALLOCATE PREPARE stmt;
|
|||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-25197: The statement set password=password('') executed in PS mode
|
||||||
|
--echo # fails in case it is run by a user with expired password
|
||||||
|
--echo #
|
||||||
|
CREATE USER user1@localhost PASSWORD EXPIRE;
|
||||||
|
|
||||||
|
SET @disconnect_on_expired_password_save=@@global.disconnect_on_expired_password;
|
||||||
|
SET GLOBAL disconnect_on_expired_password=OFF;
|
||||||
|
|
||||||
|
connect(con1,localhost,user1);
|
||||||
|
connection con1;
|
||||||
|
--echo # Check that no regular statement like SELECT can be prepared
|
||||||
|
--echo # by a user with an expired password
|
||||||
|
--error ER_MUST_CHANGE_PASSWORD
|
||||||
|
PREPARE stmt FROM "SELECT 1";
|
||||||
|
|
||||||
|
--echo # Check that the DEALLOCATE PREPARE statement can be run by a user
|
||||||
|
--echo # with an expired password
|
||||||
|
PREPARE stmt FROM "SET password=password('')";
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
--echo # Check that the SET PASSWORD statement can be executed in PS mode by
|
||||||
|
--echo # a user with an expired password
|
||||||
|
PREPARE stmt FROM "SET password=password('')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
PREPARE stmt FROM "SELECT 1";
|
||||||
|
--echo # Check that user's password is not expired anymore
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
--echo # Clean up
|
||||||
|
disconnect con1;
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
SET GLOBAL disconnect_on_expired_password=@disconnect_on_expired_password_save;
|
||||||
|
DROP USER user1@localhost;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.4 tests
|
--echo # End of 10.4 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -1641,7 +1641,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
if (unlikely(thd->security_ctx->password_expired &&
|
if (unlikely(thd->security_ctx->password_expired &&
|
||||||
command != COM_QUERY &&
|
command != COM_QUERY &&
|
||||||
command != COM_PING &&
|
command != COM_PING &&
|
||||||
command != COM_QUIT))
|
command != COM_QUIT &&
|
||||||
|
command != COM_STMT_PREPARE &&
|
||||||
|
command != COM_STMT_EXECUTE))
|
||||||
{
|
{
|
||||||
my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
|
my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
|
||||||
goto dispatch_end;
|
goto dispatch_end;
|
||||||
@ -3490,7 +3492,10 @@ mysql_execute_command(THD *thd)
|
|||||||
first_table->for_insert_data);
|
first_table->for_insert_data);
|
||||||
|
|
||||||
if (thd->security_ctx->password_expired &&
|
if (thd->security_ctx->password_expired &&
|
||||||
lex->sql_command != SQLCOM_SET_OPTION)
|
lex->sql_command != SQLCOM_SET_OPTION &&
|
||||||
|
lex->sql_command != SQLCOM_PREPARE &&
|
||||||
|
lex->sql_command != SQLCOM_EXECUTE &&
|
||||||
|
lex->sql_command != SQLCOM_DEALLOCATE_PREPARE)
|
||||||
{
|
{
|
||||||
my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
|
my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
@ -4217,6 +4217,15 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
|||||||
thd->is_error() ||
|
thd->is_error() ||
|
||||||
init_param_array(this));
|
init_param_array(this));
|
||||||
|
|
||||||
|
if (thd->security_ctx->password_expired &&
|
||||||
|
lex->sql_command != SQLCOM_SET_OPTION)
|
||||||
|
{
|
||||||
|
thd->restore_backup_statement(this, &stmt_backup);
|
||||||
|
thd->restore_active_arena(this, &stmt_backup);
|
||||||
|
thd->stmt_arena= old_stmt_arena;
|
||||||
|
my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
lex->set_trg_event_type_for_tables();
|
lex->set_trg_event_type_for_tables();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user