Skip to content
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

Fix handle AuthSwitch packet bug. #585

Merged
merged 1 commit into from Jun 29, 2017
Merged

Fix handle AuthSwitch packet bug. #585

merged 1 commit into from Jun 29, 2017

Conversation

elemount
Copy link
Contributor

MySQL documents annouce the AuthSwitch packet is contains with two
component auth_plugin_name and auth_data, which auth_data is
a string[EOF] string. But in fact it will return a string[NUL] string
or can also say the string[EOF] is consist of a 20bytes string and a '\0'
byte. Now we just follow the document which use those 21bytes as salt
and that is not correct.

MySQL documents annouce the AuthSwitch packet is contains with two
component `auth_plugin_name` and `auth_data`, which `auth_data` is
a string[EOF] string. But in fact it will return a string[NUL] string
or can also say the string[EOF] is consist of a 20bytes string and a '\0'
byte. Now we just follow the document which use those 21bytes as salt
and that is not correct.
@elemount
Copy link
Contributor Author

This fix is related with issue #584 . This is the auth switch error.
If you like, you can connect following database and use wireshark to watch the procedure.

conn = pymysql.connect(host='shuodlclient.mysql.database.azure.com', port=3306, user='mysqlaas@shuodlclient', passwd='test_PyMySQL', db='mysql')

@elemount
Copy link
Contributor Author

And this is also captured by mysqljs/mysql#1730 . @bgrainger notice that.

@methane
Copy link
Member

methane commented Jun 29, 2017

Do you mean

  • Azure using buggy MySQL server which sends wrong packet?
  • Azure requires old_password which is deprecated and not secure?
  • All MySQL client library should do such "wrong" fix for Azure?

@methane
Copy link
Member

methane commented Jun 29, 2017

I'm sorry, _scramble is not old_password.

@elemount
Copy link
Contributor Author

elemount commented Jun 29, 2017

Azure using buggy MySQL server which sends wrong packet?

No, Azure just send the packet which MySQL server sent on auth switch stage.

Azure requires old_password which is deprecated and not secure?

No, do not use old_password

All MySQL client library should do such "wrong" fix for Azure?

Not for azure, it is the fix for MySQL. Our PyMySQL do not even response correct AuthSwitch packet. All the default drivers like libmysqlclient and libmariadbclient will response correctly. A node-mysql2 and go-sql-driver/mysql also response correctly.

I provide a Azure MySQL server for test because it is easy to repo by it. I can not just provide my local MySQL for you to repo it. It do something tricky by use native password and auth switch and use native password auth again, so it repo easily, but MySQL native server, start with sha256 and create a user with native password can repo it.

@elemount
Copy link
Contributor Author

Both MySQL and MariaDB has this document and behavior mismatch.
From code, for example
For current version 10.2 of MariaDB, all the auth code is in sq_acl.cc. Change Plugin Packet function send_plugin_request_packet is called by function server_mpvio_write_packet and this function is called by a server authentication plugin, when it wants to send data to the client. All this function are just pass the data of the plugins. native_password_authenticate and old_password_authenticate are both use code looks like

mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1)

So the response will contains string[NUL].

@elemount
Copy link
Contributor Author

elemount commented Jun 29, 2017

I have a way to repo.

  1. Create publick_key.pem and private_key.pem by openssl
openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -pubout -out public_key.pem
chmod 400 private_key.pem
chmod 444 public_key.pem
  1. Install MySQL from source. And initialize it. Add following line to the my.cnf of base folder.
sha256_password_private_key_path = private_key.pem
sha256_password_public_key_path = public_key.pem
default-authentication-plugin=sha256_password
  1. Start mysql, and login it. create a user 'nativeuser'@'localhost' by
CREATE USER 'nativeuser'@'localhost' IDENTIFIED WITH mysql_native_password;
SET old_passwords = 0;
SET PASSWORD FOR 'nativeuser'@'localhost' = PASSWORD('test');
GRANT ALL PRIVILEGES ON *.* TO 'nativeuser'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES
  1. Test the nativeuser with the test password.
    And notice, you may need use the SHA256 pr as the pymysql code.
    Build mysql should include openssl.

@methane
Copy link
Member

methane commented Jun 29, 2017

I don't want to pay my time for test it.
Could you create test using docker on Travis?

@elemount
Copy link
Contributor Author

You can notice old password encrypt use the scream length because it hint the error by auth switch. Or you can remove the length split of old password and run the tests.

@methane
Copy link
Member

methane commented Jun 29, 2017

It's not good evidence, because two are different.
But I confirmed mysql-connector-c's client code use constant SCRAMBLE_LENGTH.

@methane methane merged commit 5298017 into PyMySQL:master Jun 29, 2017
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants