diff --git a/mysql-test/main/create_drop_user.result b/mysql-test/main/create_drop_user.result index 67717f3e4e05d..71e5843917de9 100644 --- a/mysql-test/main/create_drop_user.result +++ b/mysql-test/main/create_drop_user.result @@ -41,3 +41,10 @@ Warnings: Note 1974 Can't drop user 'u1'@'%'; it doesn't exist DROP USER u2; ERROR HY000: Operation DROP USER failed for 'u2'@'%' +CREATE USER u3@localhost; +CREATE OR REPLACE USER u3@localhost IDENTIFIED VIA no_such_plugin; +ERROR HY000: Plugin 'no_such_plugin' is not loaded +SELECT user FROM mysql.user WHERE user='u3'; +User +u3 +DROP USER u3@localhost; diff --git a/mysql-test/main/create_drop_user.test b/mysql-test/main/create_drop_user.test index 234383fb4ca06..213423a2456e2 100644 --- a/mysql-test/main/create_drop_user.test +++ b/mysql-test/main/create_drop_user.test @@ -44,3 +44,11 @@ DROP USER IF EXISTS u1, u2; --error ER_CANNOT_USER DROP USER u2; + +# MDEV-37214: CREATE OR REPLACE USER with invalid plugin must not drop +# the existing user and must not leave master/replica in diverged state. +CREATE USER u3@localhost; +--error ER_PLUGIN_IS_NOT_LOADED +CREATE OR REPLACE USER u3@localhost IDENTIFIED VIA no_such_plugin; +SELECT user FROM mysql.user WHERE user='u3'; +DROP USER u3@localhost; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f5e8c380c6d41..8570a7ebdc112 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -11206,6 +11206,27 @@ bool mysql_create_user(THD *thd, List &list, bool handle_as_role) { if (thd->lex->create_info.or_replace()) { + /* + MDEV-37214: pre-validate auth plugins before the destructive DROP so + that a missing plugin does not silently drop the user without a binlog + event, causing master/replica divergence. + */ + bool plugin_error= false; + for (USER_AUTH *auth= user_name->auth; auth; auth= auth->next) + { + if (auth->plugin.length && + !plugin_is_ready(&auth->plugin, MYSQL_AUTHENTICATION_PLUGIN)) + { + my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), auth->plugin.str); + append_user(thd, &wrong_users, user_name); + result= true; + plugin_error= true; + break; + } + } + if (plugin_error) + continue; + // Drop the existing user if (handle_grant_data(thd, tables, 1, user_name, NULL) <= 0) {