-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
MDEV-38431: [10.6] auth switch with long password corrupts database name #4509
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
gkodinov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your contribution! This is a preliminary review. Once addressed, I will solicit a final review from the developers.
I'd also verify (and add a test for) the COM_CHANGE_USER. It looks like it's missing handling for CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA when dealing with the password.
|
Regarding COM_CHANGE_USER and The MDEV-38431 bug requires user, LENENC-encoded password (>250 bytes), and database to be in the same packet. COM_CHANGE_USER with auth plugin switch is NOT affected because the password is sent in a separate packet after auth switch negotiation. The database pointer is calculated from the initial packet before the password arrives. I verified this by testing COM_CHANGE_USER with 256+ byte cleartext passwords - they work correctly. |
I've tried the following fragment (replace the data as you see fit) : And I get an DBUG_ASSERT calling mysql_change_user() in the above as in: The callstack of this is: the fragment in send_change_user_packet is: So no, mysql_change_user() doesn't work with longer passwords and it's not a separate packet. This however seems to be a separate issue, as the limitation was there to start with. I'd wait for the final review and discuss this with the assigned reviewer. But my 2 cents is that you need to make send_change_user_packet() do similarly to send_client_reply_packet() in that respect. But this will produce backward compatibility issues with the protocol since the server (parse_com_change_user() to be specific) expects a single byte length. So a new client (that might send a longer string) talking to an old server will still fail. The way I see it there are the following options:
I will leave it to the final reviewer to pick one. But I'd vote for the last one. |
gkodinov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please fix the test failure on windows and add a test for mysql_change_user().
Added two tests to cover mysql_change_user() with short and long password. Note that both tests PASSED. Somehow the code path of "long password within single packet" could not be triggered. Update: figured out how to reproduced the bug. Added a test which is commented out since it currently fails. |
|
Added the fix for mysql_change_user() at both server side and libmariadb, enabled the failing test |
|
hi, as the mysql_change_user requires fixing client sdks, I'd propose that we focus the scope of this PR on auth_switch |
|
Yes, absolutely, thank you. I wanted to suggest that, but didn't want to be too picky. It's mainly important to have COM_CHANGE_USER changes in a separate commit (and they were), because after you push PRs won't matter anymore, the history only contains commits, not PRs. Separate PR is better too, but not as critically important. |
|
in your last commit "fix db pointer for old protocol without CLIENT_SECURE_CONNECTION" you only fixed I expected the opposite, that you fix The fix itself is ok, although I suggest to move |
vuvova
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good, thanks. Would you mind squashing all commits into one? Then I'll merge it.
|
Done |
079bb63 to
4b783ae
Compare
When a client connects with CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA capability and a password >= 251 bytes, the server incorrectly calculates the database name pointer. For passwords >= 251 bytes, LENENC uses a 3-byte prefix (0xFC + 2 bytes), but the old code assumed a 1-byte prefix. Fix by using the passwd pointer which has already been advanced past the length prefix by safe_net_field_length_ll(). Also fix db pointer calculation for old protocol (!CLIENT_SECURE_CONNECTION) where the password is null-terminated and needs +1 to skip the terminator.
4b783ae to
4277b25
Compare
Description
Problem: When a client connects with
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATAcapability and a password >= 251 bytes, the server incorrectly calculates the database name pointer, causing "Unknown database" errors with garbage characters.Root cause: In
parse_client_handshake_packet()(sql/sql_acl.cc), the databasepointer was calculated as
db + passwd_len + 1, which assumes a 1-byte password length prefix. However, when password >= 251 bytes, LENENC encoding uses a 3-byte prefix (0xFC+ 2 bytes). Thepasswdpointer has already been advanced past this prefix bysafe_net_field_length_ll(), butdbhas not.Before fix:
(where 'a' is a garbage character from the password buffer)
After fix:
(connects to the correct database)
Side effects: None expected. The fix only affects the specific code path when
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATAis setand password >= 251 bytes.
How can this PR be tested?
Run the included MTR regression test:
The test verifies:
Basing the PR against the correct MariaDB version
based against the latest MariaDB development branch
bug can be reproduced
Bug reproduced on 10.6, 10.11, 11.4, and 11.8. PR is based on 10.6.
Backward compatibility
No backward compatibility concerns: