| Bug #102266 | mysql_change_user fails due to COM_CHANGE_USER incorrectly parsed | ||
|---|---|---|---|
| Submitted: | 18 Jan 2021 0:44 | Modified: | 26 May 2021 12:28 |
| Reporter: | Rene' Cannao' | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: C API (client library) | Severity: | S3 (Non-critical) |
| Version: | 5.6 5.7, 5.7.32 , 8.0 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | Contribution | ||
[18 Jan 2021 0:44]
Rene' Cannao'
[18 Jan 2021 7:58]
MySQL Verification Team
Hello Rene, Thank you for the report and test case. Verified as described. Regards, Umesh
[28 Jan 2021 13:11]
Rene' Cannao'
After a lot of debugging, I found the root cause of this and I can say the title is actually wrong: mysql_change_user() doesn't fail because of unknown collation, but because the COM_CHANGE_USER is incorrectly parsed in function parse_com_change_user_packet(). In 5.7 , ptr is not increased by 2 (the size of the field where the collation is specified): https://github.com/mysql/mysql-server/blob/5.7/sql/auth/sql_authentication.cc#L1111-L1113 While in 8.0 ptr is correctly increase by 2: https://github.com/mysql/mysql-server/blob/8.0/sql/auth/sql_authentication.cc#L2191-L2197 For further reference, this bug was fixed in 8.0.1 almost 4 years ago (March 2017) but it never made it into 5.7 Also, please keep in mind that also the implementation in MySQL 8.0 has a bug: ptr is increased by 2 (the size of the collation) *only* if CLIENT_PLUGIN_AUTH capability is set. This implementation is not correct, because charset/collation can be sent also if CLIENT_PLUGIN_AUTH is not set. This can be verified in client.cc file, where charset/collation number is sent: https://github.com/mysql/mysql-server/blob/8.0/sql-common/client.cc#L3970-L3973 Collation number can be sent even if CLIENT_PLUGIN_AUTH is not set, in fact the check for CLIENT_PLUGIN_AUTH is few lines after: https://github.com/mysql/mysql-server/blob/8.0/sql-common/client.cc#L3975-L3976
[28 Jan 2021 13:15]
Rene' Cannao'
I am renaming this bug from "mysql_change_user fails with unknown collation" to "mysql_change_user fails due to COM_CHANGE_USER incorrectly parsed" . Since there is a parsing error also in 8.0 , I am adding 8.0 to the list of affected versions
[28 Jan 2021 13:24]
Rene' Cannao'
New suggested fix: At minimum, port this code from 8.0 to 5.7: https://github.com/mysql/mysql-server/blob/8.0/sql/auth/sql_authentication.cc#L2193-L2197 /* ptr needs to be updated to point to correct position so that connection attributes are read properly. */ ptr = ptr + 2 + strlen(client_plugin) + 1; A more complete fix should be to evaluate if a collation number is sent even if CLIENT_PLUGIN_AUTH is not set, even if probably there are no clients out there that do not have CLIENT_PLUGIN_AUTH capabilities.
[19 May 2021 8:24]
Huqing Yan
my suggested fix for 8.0.34:
diff --git a/sql/auth/sql_authentication.cc b/sql/auth/sql_authentication.cc
index c7c34cc14ab..415b1c7dbc0 100644
--- a/sql/auth/sql_authentication.cc
+++ b/sql/auth/sql_authentication.cc
@@ -2152,6 +2152,7 @@ static bool parse_com_change_user_packet(THD *thd, MPVIO_EXT *mpvio,
if (ptr + 1 < end) {
if (mpvio->charset_adapter->init_client_charset(uint2korr(ptr)))
return true;
+ ptr = ptr + 2;
}
/* Convert database and user names to utf8 */
@@ -2189,17 +2190,17 @@ static bool parse_com_change_user_packet(THD *thd, MPVIO_EXT *mpvio,
const char *client_plugin;
if (protocol->has_client_capability(CLIENT_PLUGIN_AUTH)) {
- client_plugin = ptr + 2;
- /*
- ptr needs to be updated to point to correct position so that
- connection attributes are read properly.
- */
- ptr = ptr + 2 + strlen(client_plugin) + 1;
-
+ client_plugin = ptr;
if (client_plugin >= end) {
my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
return true;
}
+
+ /*
+ ptr needs to be updated to point to correct position so that
+ connection attributes are read properly.
+ */
+ ptr = ptr + strlen(client_plugin) + 1;
} else
client_plugin = Cached_authentication_plugins::get_plugin_name(
PLUGIN_MYSQL_NATIVE_PASSWORD);
[19 May 2021 8:31]
Huqing Yan
patch base on 8.0.25
Attachment: patch8025.diff (application/octet-stream, text), 1.23 KiB.
[19 May 2021 9:49]
Huqing Yan
patch base on 8.0.25 (*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.
Contribution: patch8025.diff (application/octet-stream, text), 1.23 KiB.
[19 May 2021 10:17]
MySQL Verification Team
Bug #103733 marked as duplicate of this one
[26 May 2021 12:28]
Paul DuBois
Posted by developer: Fixed in 5.7.35. The mysql_change_user() C API function did not properly parse the COM_CHANGE_USER packet, which could result in silent failure to process optional query attributes that may have been supplied prior to the mysql_change_user() call. Thanks for René Cannaò for the contribution.
