Repository navigation
fix(mysql): use the AuthSwitchRequest nonce for caching_sha2_password full auth - #4436
Merged
abonander merged 1 commit intoOct 4, 2026
Merged
Conversation
…change After an AuthSwitchRequest (0xfe) the new nonce was bound with a `let` inside the match arm, so it only lived for the immediate scramble. On the next loop iteration `plugin.handle(..)` still received the nonce from the initial handshake. For caching_sha2_password this breaks full authentication over a non-TLS connection: the password is XORed with the stale nonce before the RSA encryption, and the server rejects it with `1045 (28000): Access denied for user ... (using password: YES)`. This happens whenever the server's default_authentication_plugin is mysql_native_password but the account uses caching_sha2_password (e.g. Cloud SQL for MySQL 8.0 reached through the local Cloud SQL Auth Proxy), so the server switches plugins mid-handshake. Keep a single mutable `nonce` and reassign it on AuthSwitchRequest so every later step of the plugin uses the nonce the server is verifying against.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Does your PR solve an issue?
No existing issue that I could find (closest related work: #979 and #4245, neither touches this path).
After an
AuthSwitchRequest(0xfe),DoHandshakebound the new nonce with aletinside the match arm:So the switch nonce was only used for the immediate scramble. On the next loop iteration
plugin.handle(..)still got the nonce from the initial handshake. Forcaching_sha2_passwordfull authentication over a non-TLS connection, the password is XORed with that stale nonce before RSA encryption, and the server rejects it:It triggers whenever the server's
default_authentication_pluginismysql_native_passwordbut the account usescaching_sha2_password, so the server switches plugins mid-handshake. A common real-world case is Cloud SQL for MySQL 8.0 reached through the local Cloud SQL Auth Proxy (plain TCP on localhost). ThemysqlCLI connects fine with the same credentials.The fix keeps a single mutable
nonceand reassigns it onAuthSwitchRequest.Reproduction
Then, with
mysql-rsa+tls-none, runFLUSH PRIVILEGESas root (to empty the caching_sha2 cache and force full auth) and connect assha2userwith?ssl-mode=disabled:1045 (28000): Access denied ... (using password: YES)on the first attemptVerified against both
mainand0.8.6.Regression test
I didn't add one to the suite because it needs a MySQL 8.0 server started with
--default-authentication-plugin=mysql_native_password(the variable is read-only at runtime), and none of the services intests/docker-compose.ymlrun that way. The existingmysql_8service defaults tocaching_sha2_password, so no plugin switch ever happens there. If you'd like, I can add a dedicated compose service and an isolated test for it.Is this a breaking change?
No. The only behavior change is that the plugin's follow-up exchange uses the nonce the server sent in the
AuthSwitchRequest, which is what the server verifies against. Connections that never switch plugins are unaffected.