diff --git a/mysql-test/suite/binlog/r/binlog_mdev8628.result b/mysql-test/suite/binlog/r/binlog_mdev8628.result new file mode 100644 index 0000000000000..e684fddfc350e --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_mdev8628.result @@ -0,0 +1,180 @@ +RESET MASTER; +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +connect con1,localhost,u1,,; +# +# Test with lowercase current_user (no parentheses) +# +create database if not exists db; +grant select on db.* to current_user; +revoke select on db.* from current_user; +rename user current_user to u2; +rename user u2 to current_user; +drop user current_user; +Warnings: +Note 4227 Dropped users 'u1'@'%' have active connections. Use KILL CONNECTION if they should not be used anymore. +disconnect con1; +connection default; +# +# Test with CURRENT_USER() (uppercase, with parentheses) +# +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +connect con2,localhost,u1,,; +grant select on db.* to CURRENT_USER(); +revoke select on db.* from CURRENT_USER(); +rename user CURRENT_USER() to u2; +rename user u2 to CURRENT_USER(); +drop user CURRENT_USER(); +Warnings: +Note 4227 Dropped users 'u1'@'%' have active connections. Use KILL CONNECTION if they should not be used anymore. +disconnect con2; +connection default; +# +# Test ALTER USER with CURRENT_USER +# +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +connect con3,localhost,u1,,; +alter user CURRENT_USER PASSWORD EXPIRE NEVER; +disconnect con3; +connection default; +drop user u1@'%'; +# +# Test CURRENT_USER in a multi-user GRANT list +# +create user u1@'%'; +create user u2@'%'; +grant all on *.* to u1@'%' with grant option; +connect con4,localhost,u1,,; +grant select on db.* to u2@'%', CURRENT_USER, u2@'%'; +disconnect con4; +connection default; +drop user u1@'%'; +drop user u2@'%'; +# +# Test RENAME USER with CURRENT_USER on both sides +# +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +connect con5,localhost,u1,,; +rename user CURRENT_USER TO u3; +disconnect con5; +connection default; +rename user u3 to u1; +drop user u1@'%'; +# +# Test case-insensitivity: mixed case cUrReNt_UsEr +# +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +connect con6,localhost,u1,,; +grant select on db.* to cUrReNt_UsEr; +revoke select on db.* from cUrReNt_UsEr; +drop user cUrReNt_UsEr; +Warnings: +Note 4227 Dropped users 'u1'@'%' have active connections. Use KILL CONNECTION if they should not be used anymore. +disconnect con6; +connection default; +# +# Test REVOKE ALL PRIVILEGES with CURRENT_USER (mysql_revoke_all path) +# +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +create database if not exists db; +Warnings: +Note 1007 Can't create database 'db'; database exists +grant select on db.* to u1@'%'; +connect con7,localhost,u1,,; +revoke all privileges, grant option from CURRENT_USER; +disconnect con7; +connection default; +drop user u1@'%'; +# +# Test GRANT ROLE with CURRENT_USER (mysql_grant_role path) +# +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +create role r1; +grant r1 to u1@'%' with admin option; +connect con8,localhost,u1,,; +grant r1 to CURRENT_USER; +revoke r1 from CURRENT_USER; +disconnect con8; +connection default; +drop role r1; +drop user u1@'%'; +# +# Test GRANT ON PROCEDURE with CURRENT_USER (mysql_routine_grant path) +# +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +create database if not exists db; +Warnings: +Note 1007 Can't create database 'db'; database exists +create procedure db.p1() select 1; +connect con9,localhost,u1,,; +grant execute on procedure db.p1 to CURRENT_USER; +revoke execute on procedure db.p1 from CURRENT_USER; +disconnect con9; +connection default; +drop procedure db.p1; +drop user u1@'%'; +# +# Test SET PASSWORD with CURRENT_USER (already correct before this fix, +# regression guard) +# +create user u1@'%' identified by 'old'; +grant all on *.* to u1@'%' with grant option; +connect con11,localhost,u1,old,; +set password for CURRENT_USER() = password('new'); +disconnect con11; +connection default; +drop user u1@'%'; +# +# Test that host is also expanded (user with specific host, not just '%') +# +create user u1@'127.0.0.1'; +grant all on *.* to u1@'127.0.0.1' with grant option; +connect con10,127.0.0.1,u1,,; +grant select on db.* to CURRENT_USER; +drop user CURRENT_USER; +Warnings: +Note 4227 Dropped users 'u1'@'127.0.0.1' have active connections. Use KILL CONNECTION if they should not be used anymore. +disconnect con10; +connection default; +drop database if exists db; +# +# Verify that CURRENT_USER is expanded in binlog output. +# The binlog should contain 'u1'@'%' instead of literal current_user. +# +NOT FOUND /grant select on db\.\* to current_user/ in mdev8628.sql +NOT FOUND /revoke select on db\.\* from current_user/ in mdev8628.sql +NOT FOUND /rename user current_user/ in mdev8628.sql +NOT FOUND /drop user current_user/ in mdev8628.sql +NOT FOUND /drop user CURRENT_USER/ in mdev8628.sql +NOT FOUND /grant select on db\.\* to CURRENT_USER/ in mdev8628.sql +NOT FOUND /revoke select on db\.\* from CURRENT_USER/ in mdev8628.sql +NOT FOUND /rename user CURRENT_USER/ in mdev8628.sql +NOT FOUND /alter user CURRENT_USER/ in mdev8628.sql +NOT FOUND /drop user cUrReNt_UsEr/ in mdev8628.sql +NOT FOUND /grant select on db\.\* to cUrReNt_UsEr/ in mdev8628.sql +NOT FOUND /revoke all privileges.*from CURRENT_USER/ in mdev8628.sql +NOT FOUND /grant r1 to CURRENT_USER/ in mdev8628.sql +NOT FOUND /revoke r1 from CURRENT_USER/ in mdev8628.sql +NOT FOUND /grant execute on procedure.*to CURRENT_USER/ in mdev8628.sql +NOT FOUND /revoke execute on procedure.*from CURRENT_USER/ in mdev8628.sql +NOT FOUND /SET PASSWORD FOR CURRENT_USER/ in mdev8628.sql +FOUND 3 /grant select on db\.\* to 'u1'@'%'/ in mdev8628.sql +FOUND 3 /revoke select on db\.\* from 'u1'@'%'/ in mdev8628.sql +FOUND 2 /rename user 'u1'@'%' to u2/ in mdev8628.sql +FOUND 2 /rename user u2 to 'u1'@'%'/ in mdev8628.sql +FOUND 3 /drop user 'u1'@'%'/ in mdev8628.sql +FOUND 1 /alter user 'u1'@'%'/ in mdev8628.sql +FOUND 1 /SET PASSWORD FOR 'u1'@'%'/ in mdev8628.sql +FOUND 1 /grant select on db\.\* to 'u1'@'127\.0\.0\.1'/ in mdev8628.sql +FOUND 1 /drop user 'u1'@'127\.0\.0\.1'/ in mdev8628.sql +FOUND 1 /grant r1 to 'u1'@'%'/ in mdev8628.sql +FOUND 1 /revoke r1 from 'u1'@'%'/ in mdev8628.sql +FOUND 1 /grant execute on procedure.*to 'u1'@'%'/ in mdev8628.sql +FOUND 1 /revoke execute on procedure.*from 'u1'@'%'/ in mdev8628.sql diff --git a/mysql-test/suite/binlog/t/binlog_mdev8628.test b/mysql-test/suite/binlog/t/binlog_mdev8628.test new file mode 100644 index 0000000000000..c5e6a6dd9306a --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mdev8628.test @@ -0,0 +1,302 @@ +# MDEV-8628 Replication magic for CURRENT_USER in binlog does not work +# when binlog is replayed +# +# CURRENT_USER should be expanded to the actual 'user'@'host' in the binlog +# SQL text for GRANT, REVOKE, RENAME USER, DROP USER, and ALTER USER. +# SET PASSWORD already does this correctly. Without expansion, replaying +# the binlog via mysqlbinlog | mysql produces wrong results. + +--source include/have_log_bin.inc +--source include/have_binlog_format_mixed.inc + +RESET MASTER; + +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; + +--connect(con1,localhost,u1,,) + +--echo # +--echo # Test with lowercase current_user (no parentheses) +--echo # +create database if not exists db; +grant select on db.* to current_user; +revoke select on db.* from current_user; +rename user current_user to u2; +rename user u2 to current_user; +drop user current_user; + +--disconnect con1 +--connection default + +--echo # +--echo # Test with CURRENT_USER() (uppercase, with parentheses) +--echo # +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; + +--connect(con2,localhost,u1,,) + +grant select on db.* to CURRENT_USER(); +revoke select on db.* from CURRENT_USER(); +rename user CURRENT_USER() to u2; +rename user u2 to CURRENT_USER(); +drop user CURRENT_USER(); + +--disconnect con2 +--connection default + +--echo # +--echo # Test ALTER USER with CURRENT_USER +--echo # +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; + +--connect(con3,localhost,u1,,) + +alter user CURRENT_USER PASSWORD EXPIRE NEVER; + +--disconnect con3 +--connection default +drop user u1@'%'; + +--echo # +--echo # Test CURRENT_USER in a multi-user GRANT list +--echo # +create user u1@'%'; +create user u2@'%'; +grant all on *.* to u1@'%' with grant option; + +--connect(con4,localhost,u1,,) + +grant select on db.* to u2@'%', CURRENT_USER, u2@'%'; + +--disconnect con4 +--connection default +drop user u1@'%'; +drop user u2@'%'; + +--echo # +--echo # Test RENAME USER with CURRENT_USER on both sides +--echo # +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; + +--connect(con5,localhost,u1,,) + +rename user CURRENT_USER TO u3; + +--disconnect con5 +--connection default + +rename user u3 to u1; +drop user u1@'%'; + +--echo # +--echo # Test case-insensitivity: mixed case cUrReNt_UsEr +--echo # +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; + +--connect(con6,localhost,u1,,) + +grant select on db.* to cUrReNt_UsEr; +revoke select on db.* from cUrReNt_UsEr; +drop user cUrReNt_UsEr; + +--disconnect con6 +--connection default + +--echo # +--echo # Test REVOKE ALL PRIVILEGES with CURRENT_USER (mysql_revoke_all path) +--echo # +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +create database if not exists db; +grant select on db.* to u1@'%'; + +--connect(con7,localhost,u1,,) + +revoke all privileges, grant option from CURRENT_USER; + +--disconnect con7 +--connection default +drop user u1@'%'; + +--echo # +--echo # Test GRANT ROLE with CURRENT_USER (mysql_grant_role path) +--echo # +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +create role r1; +# WITH ADMIN OPTION lets u1 grant r1 to others (including themselves) +grant r1 to u1@'%' with admin option; + +--connect(con8,localhost,u1,,) + +# u1 grants r1 to CURRENT_USER (u1 itself) - tests mysql_grant_role binlog path +grant r1 to CURRENT_USER; +revoke r1 from CURRENT_USER; + +--disconnect con8 +--connection default +drop role r1; +drop user u1@'%'; + +--echo # +--echo # Test GRANT ON PROCEDURE with CURRENT_USER (mysql_routine_grant path) +--echo # +create user u1@'%'; +grant all on *.* to u1@'%' with grant option; +create database if not exists db; +create procedure db.p1() select 1; + +--connect(con9,localhost,u1,,) + +grant execute on procedure db.p1 to CURRENT_USER; +revoke execute on procedure db.p1 from CURRENT_USER; + +--disconnect con9 +--connection default +drop procedure db.p1; +drop user u1@'%'; + +--echo # +--echo # Test SET PASSWORD with CURRENT_USER (already correct before this fix, +--echo # regression guard) +--echo # +create user u1@'%' identified by 'old'; +grant all on *.* to u1@'%' with grant option; + +--connect(con11,localhost,u1,old,) + +set password for CURRENT_USER() = password('new'); + +--disconnect con11 +--connection default +drop user u1@'%'; + +--echo # +--echo # Test that host is also expanded (user with specific host, not just '%') +--echo # +create user u1@'127.0.0.1'; +grant all on *.* to u1@'127.0.0.1' with grant option; + +--connect(con10,127.0.0.1,u1,,) + +grant select on db.* to CURRENT_USER; +drop user CURRENT_USER; + +--disconnect con10 +--connection default + +drop database if exists db; + +--echo # +--echo # Verify that CURRENT_USER is expanded in binlog output. +--echo # The binlog should contain 'u1'@'%' instead of literal current_user. +--echo # + +--let $MYSQLD_DATADIR= `select @@datadir` +--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mdev8628.sql + +# Check that the binlog SQL does NOT contain unexpanded current_user +# in user positions for GRANT/REVOKE/RENAME/DROP/ALTER statements. + +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mdev8628.sql +--let SEARCH_PATTERN= grant select on db\.\* to current_user +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= revoke select on db\.\* from current_user +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= rename user current_user +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= drop user current_user +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= drop user CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= grant select on db\.\* to CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= revoke select on db\.\* from CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= rename user CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= alter user CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= drop user cUrReNt_UsEr +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= grant select on db\.\* to cUrReNt_UsEr +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= revoke all privileges.*from CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= grant r1 to CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= revoke r1 from CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= grant execute on procedure.*to CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= revoke execute on procedure.*from CURRENT_USER +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= SET PASSWORD FOR CURRENT_USER +--source include/search_pattern_in_file.inc + +# Verify expanded forms ARE present +--let SEARCH_PATTERN= grant select on db\.\* to 'u1'@'%' +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= revoke select on db\.\* from 'u1'@'%' +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= rename user 'u1'@'%' to u2 +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= rename user u2 to 'u1'@'%' +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= drop user 'u1'@'%' +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= alter user 'u1'@'%' +--source include/search_pattern_in_file.inc + +# Verify SET PASSWORD expanded correctly (regression guard) +--let SEARCH_PATTERN= SET PASSWORD FOR 'u1'@'%' +--source include/search_pattern_in_file.inc + +# Verify host-specific user is also expanded correctly +--let SEARCH_PATTERN= grant select on db\.\* to 'u1'@'127\.0\.0\.1' +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= drop user 'u1'@'127\.0\.0\.1' +--source include/search_pattern_in_file.inc + +# Verify role grant/revoke expanded forms +--let SEARCH_PATTERN= grant r1 to 'u1'@'%' +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= revoke r1 from 'u1'@'%' +--source include/search_pattern_in_file.inc + +# Verify routine grant/revoke expanded forms +--let SEARCH_PATTERN= grant execute on procedure.*to 'u1'@'%' +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= revoke execute on procedure.*from 'u1'@'%' +--source include/search_pattern_in_file.inc + +--remove_file $MYSQLTEST_VARDIR/tmp/mdev8628.sql diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 85e8db91c0d7d..d466e4a9b32c1 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7351,6 +7351,10 @@ static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, THD *thd) TRUE error */ +static bool rewrite_query_expanding_current_user(THD *thd, + List &users_list, + String *buf); + int mysql_table_grant(THD *thd, TABLE_LIST *table_list, List &user_list, List &columns, privilege_t rights, @@ -7589,7 +7593,14 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, mysql_mutex_unlock(&acl_cache->lock); if (!result) /* success */ - result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + { + String rewritten_query; + if (rewrite_query_expanding_current_user(thd, user_list, &rewritten_query)) + result= write_bin_log(thd, TRUE, rewritten_query.c_ptr_safe(), + rewritten_query.length()); + else + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + } mysql_rwlock_unlock(&LOCK_grant); @@ -7717,8 +7728,18 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, if (write_to_binlog && !result) { - if (write_bin_log(thd, FALSE, thd->query(), thd->query_length())) - result= TRUE; + String rewritten_query; + if (rewrite_query_expanding_current_user(thd, user_list, &rewritten_query)) + { + if (write_bin_log(thd, FALSE, rewritten_query.c_ptr_safe(), + rewritten_query.length())) + result= TRUE; + } + else + { + if (write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + result= TRUE; + } } mysql_rwlock_unlock(&LOCK_grant); @@ -7751,6 +7772,138 @@ static void append_user(THD *thd, String *str, LEX_USER *user) append_user(thd, str, & user->user, & user->host); } +/** + Rewrite a query string, expanding CURRENT_USER to 'user'@'host'. + + This is needed for GRANT, REVOKE, RENAME USER, and DROP USER so that + when the binlog is replayed via mysqlbinlog | mysql, the statements + reference the correct user rather than the literal CURRENT_USER keyword + (which would resolve to whoever runs the replay). + + @param thd Thread handle + @param users_list List of LEX_USER from the parsed statement (before + get_current_user resolution) + @param[out] buf Output buffer; if rewriting occurred, contains the + rewritten query. Otherwise empty. + + @return true if the query was rewritten (use buf), false otherwise + (use thd->query() as before) + + @note MDEV-8628 +*/ +static bool rewrite_query_expanding_current_user(THD *thd, + List &users_list, + String *buf) +{ + /* Check if any user in the list was specified as CURRENT_USER */ + bool has_current_user= false; + List_iterator it(users_list); + LEX_USER *user; + while ((user= it++)) + { + if (user->user.str == current_user.str) + { + has_current_user= true; + break; + } + } + + if (!has_current_user) + return false; + + /* + Replace all case-insensitive occurrences of "current_user" (with optional + parentheses) in the query with the quoted 'user'@'host' of the session. + */ + Security_context *sctx= thd->security_ctx; + if (!sctx) + return false; + + const char *query= thd->query(); + size_t query_len= thd->query_length(); + + /* + Build the replacement string: 'priv_user'@'priv_host' + Use append_user() so that special characters (single quotes, backslashes) + in the username or hostname are properly escaped, preventing syntax errors + and SQL injection during binlog replay. + */ + String replacement; + LEX_CSTRING user_name= { sctx->priv_user, strlen(sctx->priv_user) }; + LEX_CSTRING host_name= { sctx->priv_host, strlen(sctx->priv_host) }; + append_user(thd, &replacement, &user_name, &host_name); + + buf->length(0); + const char *pos= query; + const char *end= query + query_len; + + while (pos < end) + { + /* Skip quoted strings to avoid replacing inside them */ + if (*pos == '\'' || *pos == '"' || *pos == '`') + { + char quote= *pos; + buf->append(pos, 1); + pos++; + while (pos < end) + { + if (*pos == quote) + { + buf->append(pos, 1); + pos++; + if (pos < end && *pos == quote) + { + /* Escaped quote (doubled) */ + buf->append(pos, 1); + pos++; + } + else + break; + } + else if (*pos == '\\' && quote != '`' && pos + 1 < end) + { + buf->append(pos, 2); + pos+= 2; + } + else + { + buf->append(pos, 1); + pos++; + } + } + continue; + } + + /* Check for "current_user" keyword (case-insensitive) */ + if ((size_t)(end - pos) >= 12 && + strncasecmp(pos, "current_user", 12) == 0) + { + /* Make sure it's not part of a longer identifier */ + if ((pos == query || !my_isvar(system_charset_info, *(pos - 1))) && + (pos + 12 >= end || !my_isvar(system_charset_info, *(pos + 12)))) + { + const char *after= pos + 12; + /* Skip optional "()" */ + if (after < end && *after == '(') + { + after++; + if (after < end && *after == ')') + after++; + } + buf->append(replacement); + pos= after; + continue; + } + } + + buf->append(pos, 1); + pos++; + } + + return true; +} + + /** append a string to a buffer that will be later used as an error message @@ -8053,7 +8206,14 @@ bool mysql_grant_role(THD *thd, List &list, bool revoke) my_error(revoke ? ER_CANNOT_REVOKE_ROLE : ER_CANNOT_GRANT_ROLE, MYF(0), rolename.str, wrong_users.c_ptr_safe()); else - result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + { + String rewritten_query; + if (rewrite_query_expanding_current_user(thd, list, &rewritten_query)) + result= write_bin_log(thd, TRUE, rewritten_query.c_ptr_safe(), + rewritten_query.length()); + else + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + } mysql_rwlock_unlock(&LOCK_grant); @@ -8157,7 +8317,12 @@ bool mysql_grant(THD *thd, LEX_CSTRING db, List &list, if (!result) { - result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + String rewritten_query; + if (rewrite_query_expanding_current_user(thd, list, &rewritten_query)) + result= write_bin_log(thd, TRUE, rewritten_query.c_ptr_safe(), + rewritten_query.length()); + else + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } mysql_rwlock_unlock(&LOCK_grant); @@ -11576,7 +11741,14 @@ bool mysql_drop_user(THD *thd, List &list, bool handle_as_role) wrong_users.c_ptr_safe()); if (binlog) - result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + { + String rewritten_query; + if (rewrite_query_expanding_current_user(thd, list, &rewritten_query)) + result |= write_bin_log(thd, FALSE, rewritten_query.c_ptr_safe(), + rewritten_query.length()); + else + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + } mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(result); @@ -11670,7 +11842,14 @@ bool mysql_rename_user(THD *thd, List &list) my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); if (some_users_renamed && mysql_bin_log.is_open()) - result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + { + String rewritten_query; + if (rewrite_query_expanding_current_user(thd, list, &rewritten_query)) + result |= write_bin_log(thd, FALSE, rewritten_query.c_ptr_safe(), + rewritten_query.length()); + else + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + } mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(result); @@ -11746,8 +11925,15 @@ int mysql_alter_user(THD* thd, List &users_list) } if (some_users_altered) - result|= write_bin_log(thd, FALSE, thd->query(), - thd->query_length()); + { + String rewritten_query; + if (rewrite_query_expanding_current_user(thd, users_list, &rewritten_query)) + result|= write_bin_log(thd, FALSE, rewritten_query.c_ptr_safe(), + rewritten_query.length()); + else + result|= write_bin_log(thd, FALSE, thd->query(), + thd->query_length()); + } DBUG_RETURN(result); } @@ -12002,8 +12188,16 @@ bool mysql_revoke_all(THD *thd, List &list) if (result) my_message(ER_REVOKE_GRANTS, ER_THD(thd, ER_REVOKE_GRANTS), MYF(0)); - result= result | - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + { + String rewritten_query; + if (rewrite_query_expanding_current_user(thd, list, &rewritten_query)) + result= result | + write_bin_log(thd, FALSE, rewritten_query.c_ptr_safe(), + rewritten_query.length()); + else + result= result | + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + } mysql_rwlock_unlock(&LOCK_grant);