summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2021-11-26 18:41:35 +0100
committerSergei Golubchik <serg@mariadb.org>2021-12-15 19:13:57 +0100
commit71966c7306d6ae24bc052d5433e6d97cc81a436a (patch)
treea922986274d3bdd70f3640c27a5b251f337facc3
parent9ea83f7fbd6fe3f76ba0304851cfe96cd4cc1071 (diff)
downloadmariadb-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.cc44
-rw-r--r--mysql-test/main/charset_client_win_utf8mb4.result4
-rw-r--r--mysql-test/main/charset_client_win_utf8mb4.test19
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;
+