1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

MDEV-26713 allow users with non-UTF8 passwords to login after upgrade.

Translate username, password and database from UTF8 into desired charset,
if  non-auto default-character-set was used, on Windows10 1903

This change is implemented only in the command line client, and mainly to
allow users with non-UTF8 passwords to login.

The user is supposed to use the same charset that was used during setting
password (usually, console CP if used in CLI)

Add a test to document the behavior.
This commit is contained in:
Vladislav Vaintroub
2021-11-26 18:41:35 +01:00
committed by Sergei Golubchik
parent 9ea83f7fbd
commit 71966c7306
3 changed files with 67 additions and 0 deletions

View File

@@ -1442,6 +1442,46 @@ sig_handler mysql_end(int sig)
exit(status.exit_status); exit(status.exit_status);
} }
#ifdef _WIN32
#define CNV_BUFSIZE 1024
/**
Convert user,database,and password to requested charset.
This is done in the single case when user connects with non-UTF8
default-character-set, on UTF8 capable Windows.
User, password, and database are UTF8 encoded, prior to the function,
this needs to be fixed, in case they contain non-ASCIIs.
Mostly a workaround, to allow existng users with non-ASCII password
to survive upgrade without losing connectivity.
*/
static void maybe_convert_charset(const char **user, const char **password,
const char **database, const char *csname)
{
if (GetACP() != CP_UTF8 || !strncmp(csname, "utf8", 4))
return;
static char bufs[3][CNV_BUFSIZE];
const char **from[]= {user, password, database};
CHARSET_INFO *cs= get_charset_by_csname(csname, MY_CS_PRIMARY,
MYF(MY_UTF8_IS_UTF8MB3 | MY_WME));
if (!cs)
return;
for (int i= 0; i < 3; i++)
{
const char *str= *from[i];
if (!str)
continue;
uint errors;
uint len= my_convert(bufs[i], CNV_BUFSIZE, cs, str, (uint32) strlen(str),
&my_charset_utf8mb4_bin, &errors);
bufs[i][len]= 0;
*from[i]= bufs[i];
}
}
#endif
/* /*
set connection-specific options and call mysql_real_connect set connection-specific options and call mysql_real_connect
*/ */
@@ -1473,6 +1513,10 @@ static bool do_connect(MYSQL *mysql, const char *host, const char *user,
mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
"program_name", "mysql"); "program_name", "mysql");
#ifdef _WIN32
maybe_convert_charset(&user, &password, &database,default_charset);
#endif
return mysql_real_connect(mysql, host, user, password, database, return mysql_real_connect(mysql, host, user, password, database,
opt_mysql_port, opt_mysql_unix_port, flags); opt_mysql_port, opt_mysql_unix_port, flags);
} }

View File

@@ -1,2 +1,6 @@
@@character_set_client @@character_set_client
utf8mb4 utf8mb4
ERROR 1045 (28000): Access denied for user 'u'@'localhost' (using password: YES)
2
2
DROP user u;

View File

@@ -1,3 +1,22 @@
--source include/windows.inc --source include/windows.inc
--source include/check_utf8_cli.inc --source include/check_utf8_cli.inc
--exec $MYSQL --default-character-set=auto -e "select @@character_set_client" --exec $MYSQL --default-character-set=auto -e "select @@character_set_client"
# Test that a user with old, non-UTF8 password can still connect
# by setting setting non-auto --default-character-set
# This is important for backward compatibility
# Emulate creating password in an interactive client session, with older clients
# which communicates with the server using with something like cp850
exec chcp 850 > NUL && echo CREATE USER 'u' IDENTIFIED by 'ü' | $MYSQL --default-character-set=cp850;
# Can't connect with UTF8
--error 1
exec $MYSQL --default-character-set=auto --user=u --password=ü -e "select 1" 2>&1;
# Can connect with tweaked --default-character-set
exec $MYSQL --default-character-set=cp850 --user=u --password=ü -e "select 2";
DROP user u;