diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2021-11-26 18:41:35 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2021-12-15 19:13:57 +0100 |
commit | 71966c7306d6ae24bc052d5433e6d97cc81a436a (patch) | |
tree | a922986274d3bdd70f3640c27a5b251f337facc3 | |
parent | 9ea83f7fbd6fe3f76ba0304851cfe96cd4cc1071 (diff) | |
download | mariadb-git-preview-10.8-MDEV-26713-windows-i18-support.tar.gz |
MDEV-26713 allow users with non-UTF8 passwords to login after upgrade.preview-10.8-MDEV-26713-windows-i18-support
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.
-rw-r--r-- | client/mysql.cc | 44 | ||||
-rw-r--r-- | mysql-test/main/charset_client_win_utf8mb4.result | 4 | ||||
-rw-r--r-- | mysql-test/main/charset_client_win_utf8mb4.test | 19 |
3 files changed, 67 insertions, 0 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index d15a5ebdb40..49e6d29e964 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1442,6 +1442,46 @@ sig_handler mysql_end(int sig) 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 */ @@ -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_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysql"); +#ifdef _WIN32 + maybe_convert_charset(&user, &password, &database,default_charset); +#endif + return mysql_real_connect(mysql, host, user, password, database, opt_mysql_port, opt_mysql_unix_port, flags); } diff --git a/mysql-test/main/charset_client_win_utf8mb4.result b/mysql-test/main/charset_client_win_utf8mb4.result index f7b5d376f9a..9bbf751e45c 100644 --- a/mysql-test/main/charset_client_win_utf8mb4.result +++ b/mysql-test/main/charset_client_win_utf8mb4.result @@ -1,2 +1,6 @@ @@character_set_client utf8mb4 +ERROR 1045 (28000): Access denied for user 'u'@'localhost' (using password: YES) +2 +2 +DROP user u; diff --git a/mysql-test/main/charset_client_win_utf8mb4.test b/mysql-test/main/charset_client_win_utf8mb4.test index 2baf0d7c050..e08afa250bd 100644 --- a/mysql-test/main/charset_client_win_utf8mb4.test +++ b/mysql-test/main/charset_client_win_utf8mb4.test @@ -1,3 +1,22 @@ --source include/windows.inc --source include/check_utf8_cli.inc --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; + |