1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

5.2 merge

This commit is contained in:
Sergei Golubchik
2013-01-25 10:20:45 +01:00
12 changed files with 264 additions and 89 deletions

View File

@ -2554,7 +2554,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
verbose_msg("-- Retrieving table structure for table %s...\n", table);
len= my_snprintf(query_buff, sizeof(query_buff),
"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
"SET SQL_QUOTE_SHOW_CREATE=%d",
(opt_quoted || opt_keywords));
if (!create_options)
strmov(query_buff+len,
@ -5133,7 +5133,7 @@ static my_bool get_view_structure(char *table, char* db)
verbose_msg("-- Retrieving view structure for table %s...\n", table);
#ifdef NOT_REALLY_USED_YET
sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
sprintf(insert_pat,"SET SQL_QUOTE_SHOW_CREATE=%d",
(opt_quoted || opt_keywords));
#endif

View File

@ -3927,7 +3927,10 @@ void do_change_user(struct st_command *command)
cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
if (mysql_change_user(mysql, ds_user.str, ds_passwd.str, ds_db.str))
die("change user failed: %s", mysql_error(mysql));
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), &ds_res);
else
handle_no_error(command);
dynstr_free(&ds_user);
dynstr_free(&ds_passwd);

View File

@ -0,0 +1,5 @@
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: YES)
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: NO)
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: YES)
ERROR 08S01: Unknown command
ERROR 08S01: Unknown command

View File

@ -0,0 +1,21 @@
optimize table mysql.user;
Table Op Msg_type Msg_text
mysql.user optimize status OK
insert mysql.user (user,plugin) values ('foo','bar'),('bar','bar'),('baz','bar');
Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
Warning 1364 Field 'auth_string' doesn't have a default value
flush privileges;
connect(localhost,u1,,test,MASTER_PORT,MASTER_SOCKET);
ERROR HY000: Plugin 'bar' is not loaded
connect(localhost,u2,,test,MASTER_PORT,MASTER_SOCKET);
ERROR 28000: Access denied for user 'u2'@'localhost' (using password: NO)
connect(localhost,u2,password,test,MASTER_PORT,MASTER_SOCKET);
ERROR 28000: Access denied for user 'u2'@'localhost' (using password: YES)
ERROR HY000: Plugin 'bar' is not loaded
ERROR 28000: Access denied for user 'u2'@'localhost' (using password: NO)
ERROR 28000: Access denied for user 'u2'@'localhost' (using password: YES)
delete from mysql.user where plugin = 'bar';
flush privileges;

View File

@ -847,9 +847,9 @@ a int(11) YES NULL
b varchar(255) YES NULL
c datetime YES NULL
drop table t1;
mysqltest: At line 1: change user failed: Unknown database 'inexistent'
mysqltest: At line 1: change user failed: Access denied for user 'inexistent'@'localhost' (using password: NO)
mysqltest: At line 1: change user failed: Access denied for user 'root'@'localhost' (using password: YES)
mysqltest: At line 1: query 'change_user root,,inexistent' failed: 1049: Unknown database 'inexistent'
mysqltest: At line 1: query 'change_user inexistent,,test' failed: 1045: Access denied for user 'inexistent'@'localhost' (using password: NO)
mysqltest: At line 1: query 'change_user root,inexistent,test' failed: 1045: Access denied for user 'root'@'localhost' (using password: YES)
REPLACED_FILE1.txt
file1.txt
file2.txt

View File

@ -0,0 +1,24 @@
source include/not_embedded.inc;
#
# MDEV-3915 COM_CHANGE_USER allows fast password brute-forcing
#
# only three failed change_user per connection.
# successful change_user do NOT reset the counter
#
connect (test,localhost,root,,);
connection test;
--error 1045
change_user foo,bar;
--error 1045
change_user foo;
change_user;
--error 1045
change_user foo,bar;
--error 1047
change_user foo,bar;
--error 1047
change_user;
disconnect test;
connection default;

View File

@ -0,0 +1,37 @@
source include/not_embedded.inc;
#
# MDEV-3909 remote user enumeration
#
# verify that for some failed login attemps (with wrong user names)
# the server requests a plugin
#
optimize table mysql.user;
insert mysql.user (user,plugin) values ('foo','bar'),('bar','bar'),('baz','bar');
flush privileges;
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
--error ER_PLUGIN_IS_NOT_LOADED
connect (fail,localhost,u1);
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
--error ER_ACCESS_DENIED_ERROR
connect (fail,localhost,u2);
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
--error ER_ACCESS_DENIED_ERROR
connect (fail,localhost,u2,password);
--error ER_PLUGIN_IS_NOT_LOADED
change_user u1;
--error ER_ACCESS_DENIED_ERROR
change_user u2;
--error ER_ACCESS_DENIED_ERROR
change_user u2,password;
delete from mysql.user where plugin = 'bar';
flush privileges;

View File

@ -7058,6 +7058,7 @@ struct MPVIO_EXT : public MYSQL_PLUGIN_VIO
} cached_server_packet;
int packets_read, packets_written; ///< counters for send/received packets
uint connect_errors; ///< if there were connect errors for this host
bool make_it_fail;
/** when plugin returns a failure this tells us what really happened */
enum { SUCCESS, FAILURE, RESTART } status;
};
@ -7324,14 +7325,14 @@ static bool send_plugin_request_packet(MPVIO_EXT *mpvio,
/**
Finds acl entry in user database for authentication purposes.
Finds a user and copies it into mpvio. Reports an authentication
failure if a user is not found.
Finds a user and copies it into mpvio. Creates a fake user
if no matching user account is found.
@note find_acl_user is not the same, because it doesn't take into
account the case when user is not empty, but acl_user->user is empty
@retval 0 found
@retval 1 not found
@retval 1 error
*/
static bool find_mpvio_user(MPVIO_EXT *mpvio, Security_context *sctx)
@ -7353,8 +7354,27 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio, Security_context *sctx)
if (!mpvio->acl_user)
{
login_failed_error(mpvio->thd);
return 1;
/*
A matching user was not found. Fake it. Take any user, make the
authentication fail later.
This way we get a realistically looking failure, with occasional
"change auth plugin" requests even for nonexistent users. The ratio
of "change auth plugin" request will be the same for real and
nonexistent users.
Note, that we cannot pick any user at random, it must always be
the same user account for the incoming sctx->user name.
*/
ulong nr1=1, nr2=4;
CHARSET_INFO *cs= &my_charset_latin1;
cs->coll->hash_sort(cs, (uchar*) sctx->user, strlen(sctx->user), &nr1, &nr2);
pthread_mutex_lock(&acl_cache->lock);
uint i= nr1 % acl_users.elements;
ACL_USER *acl_user_tmp= dynamic_element(&acl_users, i, ACL_USER*);
mpvio->acl_user= acl_user_tmp->copy(mpvio->thd->mem_root);
pthread_mutex_unlock(&acl_cache->lock);
mpvio->make_it_fail= true;
}
/* user account requires non-default plugin and the client is too old */
@ -7473,6 +7493,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
thd->password= passwd_len > 0;
if (find_mpvio_user(mpvio, sctx))
return 1;
@ -7763,8 +7784,8 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
mpvio->cached_server_packet.pkt_len))
return packet_error;
passwd_len= my_net_read(&mpvio->thd->net);
passwd = (char*)mpvio->thd->net.read_pos;
passwd_len= my_net_read(&thd->net);
passwd= (char*)thd->net.read_pos;
}
*buff= (uchar*)passwd;
@ -7868,6 +7889,10 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf)
*buf= (uchar*)mpvio->cached_client_reply.pkt;
mpvio->cached_client_reply.pkt= 0;
mpvio->packets_read++;
if (mpvio->make_it_fail)
goto err;
return (int)mpvio->cached_client_reply.pkt_len;
}
/*
@ -7901,12 +7926,18 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf)
else
*buf = mpvio->thd->net.read_pos;
if (mpvio->make_it_fail)
goto err;
return (int)pkt_len;
err:
if (mpvio->status == MPVIO_EXT::FAILURE && !mpvio->thd->is_error())
{
inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
if (mpvio->make_it_fail)
login_failed_error(mpvio->thd);
else
my_error(ER_HANDSHAKE_ERROR, MYF(0));
}
return -1;
@ -8116,6 +8147,7 @@ bool acl_authenticate(THD *thd, uint connect_errors,
mpvio.thd= thd;
mpvio.connect_errors= connect_errors;
mpvio.status= MPVIO_EXT::FAILURE;
mpvio.make_it_fail= false;
if (command == COM_CHANGE_USER)
{

View File

@ -678,6 +678,7 @@ THD::THD()
examined_row_count(0),
global_read_lock(0),
global_disable_checkpoint(0),
failed_com_change_user(0),
is_fatal_error(0),
transaction_rollback_request(0),
is_fatal_sub_stmt_error(0),

View File

@ -2032,6 +2032,7 @@ public:
bool no_errors, password;
bool extra_port; /* If extra connection */
uint8 failed_com_change_user;
/**
Set to TRUE if execution of the current compound statement
can not continue. In particular, disables activation of

View File

@ -1138,6 +1138,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
uint save_db_length= thd->db_length;
char *save_db= thd->db;
int rc;
USER_CONN *save_user_connect= thd->user_connect;
Security_context save_security_ctx= *thd->security_ctx;
CHARSET_INFO *save_character_set_client=
@ -1151,7 +1152,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->security_ctx->user= 0;
thd->user_connect= 0;
if (acl_authenticate(thd, 0, packet_length))
/*
to limit COM_CHANGE_USER ability to brute-force passwords,
we only allow three unsuccessful COM_CHANGE_USER per connection.
*/
if (thd->failed_com_change_user >= 3)
{
my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
rc= 1;
}
else
rc= acl_authenticate(thd, 0, packet_length);
if (rc)
{
/* Free user if allocated by acl_authenticate */
x_free(thd->security_ctx->user);
@ -1164,6 +1177,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->variables.collation_connection= save_collation_connection;
thd->variables.character_set_results= save_character_set_results;
thd->update_charset();
thd->failed_com_change_user++;
my_sleep(1000000);
}
else
{

View File

@ -15386,6 +15386,7 @@ static void test_change_user()
const char *pw= "password";
const char *db= "mysqltest_user_test_database";
int rc;
MYSQL* conn;
DBUG_ENTER("test_change_user");
myheader("test_change_user");
@ -15429,149 +15430,173 @@ static void test_change_user()
rc= mysql_query(mysql, buff);
myquery(rc);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
/* Try some combinations */
rc= mysql_change_user(mysql, NULL, NULL, NULL);
rc= mysql_change_user(conn, NULL, NULL, NULL);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, "", NULL, NULL);
rc= mysql_change_user(conn, "", NULL, NULL);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, "", "", NULL);
rc= mysql_change_user(conn, "", "", NULL);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, "", "", "");
mysql_close(conn);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
rc= mysql_change_user(conn, "", "", "");
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, NULL, "", "");
rc= mysql_change_user(conn, NULL, "", "");
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, NULL, NULL, "");
rc= mysql_change_user(conn, NULL, NULL, "");
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, "", NULL, "");
mysql_close(conn);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
rc= mysql_change_user(conn, "", NULL, "");
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_pw, NULL, "");
rc= mysql_change_user(conn, user_pw, NULL, "");
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_pw, "", "");
rc= mysql_change_user(conn, user_pw, "", "");
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_pw, "", NULL);
mysql_close(conn);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
rc= mysql_change_user(conn, user_pw, "", NULL);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_pw, NULL, NULL);
rc= mysql_change_user(conn, user_pw, NULL, NULL);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_pw, "", db);
rc= mysql_change_user(conn, user_pw, "", db);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_pw, NULL, db);
mysql_close(conn);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
rc= mysql_change_user(conn, user_pw, NULL, db);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_pw, pw, db);
rc= mysql_change_user(conn, user_pw, pw, db);
myquery(rc);
rc= mysql_change_user(mysql, user_pw, pw, NULL);
rc= mysql_change_user(conn, user_pw, pw, NULL);
myquery(rc);
rc= mysql_change_user(mysql, user_pw, pw, "");
rc= mysql_change_user(conn, user_pw, pw, "");
myquery(rc);
rc= mysql_change_user(mysql, user_no_pw, pw, db);
rc= mysql_change_user(conn, user_no_pw, pw, db);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_no_pw, pw, "");
rc= mysql_change_user(conn, user_no_pw, pw, "");
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_no_pw, pw, NULL);
mysql_close(conn);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
rc= mysql_change_user(conn, user_no_pw, pw, NULL);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, user_no_pw, "", NULL);
rc= mysql_change_user(conn, user_no_pw, "", NULL);
myquery(rc);
rc= mysql_change_user(mysql, user_no_pw, "", "");
rc= mysql_change_user(conn, user_no_pw, "", "");
myquery(rc);
rc= mysql_change_user(mysql, user_no_pw, "", db);
rc= mysql_change_user(conn, user_no_pw, "", db);
myquery(rc);
rc= mysql_change_user(mysql, user_no_pw, NULL, db);
rc= mysql_change_user(conn, user_no_pw, NULL, db);
myquery(rc);
rc= mysql_change_user(mysql, "", pw, db);
rc= mysql_change_user(conn, "", pw, db);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, "", pw, "");
rc= mysql_change_user(conn, "", pw, "");
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, "", pw, NULL);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
mysql_close(conn);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
rc= mysql_change_user(mysql, NULL, pw, NULL);
rc= mysql_change_user(conn, "", pw, NULL);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, NULL, NULL, db);
rc= mysql_change_user(conn, NULL, pw, NULL);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, NULL, "", db);
rc= mysql_change_user(conn, NULL, NULL, db);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(mysql, "", "", db);
mysql_close(conn);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
rc= mysql_change_user(conn, NULL, "", db);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
printf("Got error (as expected): %s\n", mysql_error(conn));
rc= mysql_change_user(conn, "", "", db);
DIE_UNLESS(rc);
if (! opt_silent)
printf("Got error (as expected): %s\n", mysql_error(conn));
/* Cleanup the environment */
mysql_change_user(mysql, opt_user, opt_password, current_db);
mysql_change_user(conn, opt_user, opt_password, current_db);
mysql_close(conn);
sprintf(buff, "drop database %s", db);
rc= mysql_query(mysql, buff);
@ -16234,29 +16259,35 @@ static void test_bug31669()
static char db[NAME_CHAR_LEN+1];
static char query[LARGE_BUFFER_SIZE*2];
#endif
MYSQL* conn;
DBUG_ENTER("test_bug31669");
myheader("test_bug31669");
rc= mysql_change_user(mysql, NULL, NULL, NULL);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
rc= mysql_change_user(conn, NULL, NULL, NULL);
DIE_UNLESS(rc);
rc= mysql_change_user(mysql, "", "", "");
rc= mysql_change_user(conn, "", "", "");
DIE_UNLESS(rc);
memset(buff, 'a', sizeof(buff));
rc= mysql_change_user(mysql, buff, buff, buff);
mysql_close(conn);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
rc= mysql_change_user(conn, buff, buff, buff);
DIE_UNLESS(rc);
rc = mysql_change_user(mysql, opt_user, opt_password, current_db);
rc = mysql_change_user(conn, opt_user, opt_password, current_db);
DIE_UNLESS(!rc);
#ifndef EMBEDDED_LIBRARY
memset(db, 'a', sizeof(db));
db[NAME_CHAR_LEN]= 0;
strxmov(query, "CREATE DATABASE IF NOT EXISTS ", db, NullS);
rc= mysql_query(mysql, query);
rc= mysql_query(conn, query);
myquery(rc);
memset(user, 'b', sizeof(user));
@ -16265,54 +16296,59 @@ static void test_bug31669()
buff[LARGE_BUFFER_SIZE]= 0;
strxmov(query, "GRANT ALL PRIVILEGES ON *.* TO '", user, "'@'%' IDENTIFIED BY "
"'", buff, "' WITH GRANT OPTION", NullS);
rc= mysql_query(mysql, query);
rc= mysql_query(conn, query);
myquery(rc);
strxmov(query, "GRANT ALL PRIVILEGES ON *.* TO '", user, "'@'localhost' IDENTIFIED BY "
"'", buff, "' WITH GRANT OPTION", NullS);
rc= mysql_query(mysql, query);
rc= mysql_query(conn, query);
myquery(rc);
rc= mysql_query(mysql, "FLUSH PRIVILEGES");
rc= mysql_query(conn, "FLUSH PRIVILEGES");
myquery(rc);
rc= mysql_change_user(mysql, user, buff, db);
rc= mysql_change_user(conn, user, buff, db);
DIE_UNLESS(!rc);
user[USERNAME_CHAR_LENGTH-1]= 'a';
rc= mysql_change_user(mysql, user, buff, db);
rc= mysql_change_user(conn, user, buff, db);
DIE_UNLESS(rc);
user[USERNAME_CHAR_LENGTH-1]= 'b';
buff[LARGE_BUFFER_SIZE-1]= 'd';
rc= mysql_change_user(mysql, user, buff, db);
rc= mysql_change_user(conn, user, buff, db);
DIE_UNLESS(rc);
buff[LARGE_BUFFER_SIZE-1]= 'c';
db[NAME_CHAR_LEN-1]= 'e';
rc= mysql_change_user(mysql, user, buff, db);
rc= mysql_change_user(conn, user, buff, db);
DIE_UNLESS(rc);
mysql_close(conn);
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
db[NAME_CHAR_LEN-1]= 'a';
rc= mysql_change_user(mysql, user, buff, db);
rc= mysql_change_user(conn, user, buff, db);
DIE_UNLESS(!rc);
rc= mysql_change_user(mysql, user + 1, buff + 1, db + 1);
rc= mysql_change_user(conn, user + 1, buff + 1, db + 1);
DIE_UNLESS(rc);
rc = mysql_change_user(mysql, opt_user, opt_password, current_db);
rc = mysql_change_user(conn, opt_user, opt_password, current_db);
DIE_UNLESS(!rc);
strxmov(query, "DROP DATABASE ", db, NullS);
rc= mysql_query(mysql, query);
rc= mysql_query(conn, query);
myquery(rc);
strxmov(query, "DELETE FROM mysql.user WHERE User='", user, "'", NullS);
rc= mysql_query(mysql, query);
rc= mysql_query(conn, query);
myquery(rc);
DIE_UNLESS(mysql_affected_rows(mysql) == 2);
DIE_UNLESS(mysql_affected_rows(conn) == 2);
#endif
mysql_close(conn);
DBUG_VOID_RETURN;
}