-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Add authentication plugin support #353
Conversation
This extracts a plugin name from the server and exposes this as connection.get_plugin_name(). The client side here adds capabilities PLUGIN_AUTH and PLUGIN_AUTH_LENENC_CLIENT_DATA. Because of this the HandshakeResponse response has been altered to use the server_capabilities a bit mroe strictly. The immediate upshot is that plugins like unix_socket are immediately supported where they previously would of returned and error as without PLUGIN_AUTH being advertised on the client side, the server only accepts mysql_native_password and mysql_old_password. To support other plugins some more work is needed to implement these.
Is there some reassurance I can help with the acceptance of this patch? |
@@ -17,3 +17,18 @@ def join_bytes(bs): | |||
for b in bs[1:]: | |||
rv += b | |||
return rv | |||
|
|||
# https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::LengthEncodedInteger | |||
def lenenc_int(i): |
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.
util
module shouldn't know about MySQL protocol.
Please move this function to connections
module.
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.
lenenc-int appears in other places outside connection like https://dev.mysql.com/doc/internals/en/com-query-response.html, https://dev.mysql.com/doc/internals/en/binary-protocol-resultset.html and https://dev.mysql.com/doc/internals/en/table-map-event.html
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.
All of these are protocol related.
And all code relating to protocol is in connections
module for now.
|
@@ -345,7 +353,7 @@ def is_eof_packet(self): | |||
# http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-EOF_Packet | |||
# Caution: \xFE may be LengthEncodedInteger. | |||
# If \xFE is LengthEncodedInteger header, 8bytes followed. | |||
return len(self._data) < 9 and self._data[0:1] == b'\xfe' | |||
return self._data[0:1] == b'\xfe' |
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.
Why? Have you read comment above?
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.
When the auth switch is done the length isn't < 9. http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
I've found the <9 reference here: http://dev.mysql.com/doc/internals/en/packet-OK_Packet.html. I'll see what can be done to avoid changing this bit and support the AuthSwitchRequest.
PyMySQL doesn't have enough test suite about authentication. |
handler = None | ||
if plugin_name == "mysql_native_password": | ||
# https://dev.mysql.com/doc/internals/en/secure-password-authentication.html#packet-Authentication::Native41 | ||
data = _scramble(self.password.encode('latin1'), auth_packet.read_all()) + int2byte(0) |
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.
int2byte(0)
should be b'\0'
Ok. no problem. I can add some more. Might get some code coverage there to identify the bits that need testing a little better.
I've extended the test suite a bit more to cover it.
ok. Hoping adding more tests is a sufficient way to test this. |
5901faf
to
8cc9cdf
Compare
…y plugin name occurs with PLUGIN_AUTH meaning old passwords
Despite appearances this is still passing Travis tests and builds https://travis-ci.org/grooverdan/PyMySQL/builds/77866544 with a significant portion of the code added being covered https://coveralls.io/builds/3435133/source?filename=pymysql%2Fconnections.py . I'll merge the changes with #369. Is a sufficient test coverage of code added a suitable reassurance for merging this PR? Would you prefer this to be broken down into smaller PRs? |
…pam use of that name. Recreate afterwards
I'm finished. Questions/queries or requests for fixing code welcome. |
Just lurking this... And while neither I am not fond of huge PR:s, they aren't atomic but consists of lots of commits, and therefore things can be selectively rolled back. To put it short, please merge this. :-) |
it got quite big quickly in the number of commits. Happy to rebase into a single (or a few basic increments) commits. All of the code adds rigour to the protocol and callouts to where authentication plugins are required. In the mean time @nicklasb , the first commit 2d1da09 of adding PLUGIN_AUTH to the CAPABILITIES is sufficient to get socket_auth working. |
Thanks for your response, @grooverdan . I am not sure that the maintainers have time to tell you how to break it apart..but as a maintainer of other projects myself, and if I were you, I would try to first break out each or all bug fixes in a separate PR, as those could then be released in a minor version. Then add structural changes and new functionality in another PR. As there is not visible develop branch for the new stuff, at least that is the way I'd do it. I can't deploy non-pip-stuff, but I can at least try it. |
Sorry, didn't work with just pasting over the 0.6.7 code, and I don't have time to clone and try with git now, perhaps I can test it tomorrow instead. |
Hi @grooverdan and @methane, I have now tried with this branch, and it works. |
Add authentication plugin support
thanks @methane |
While I've merged this pull request, I couldn't get how |
It's OK. Cool kids use #master. :-) |
Its the next sequence number in the packet protocol (https://dev.mysql.com/doc/internals/en/sequence-id.html). It seems that pkt_nr is cast down to uchar during use (despite being a uint in the code) - most of its use in this file: https://github.com/mysql/mysql-server/blob/5.7/sql/net_serv.cc#L789 |
Thanks for reply. |
This extracts a plugin name from the server and exposes this as
connection.get_plugin_name().
The client side here adds capabilities PLUGIN_AUTH and
PLUGIN_AUTH_LENENC_CLIENT_DATA.
Because of this the HandshakeResponse response has been altered to use
the server_capabilities a bit more strictly.
The immediate upshot is that plugins like unix_socket are immediately
supported where they previously would of returned and error as without
PLUGIN_AUTH being advertised on the client side, the server only accepts
mysql_native_password and mysql_old_password.
To support other plugins some more work is needed to implement these.
I didn't intentionally break 4.X support however I haven't tested it either.