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.