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

Add authentication plugin support #353

Merged
merged 33 commits into from
Jan 3, 2016

Conversation

grooverdan
Copy link
Contributor

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.

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.
@grooverdan
Copy link
Contributor Author

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):
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

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.

@methane
Copy link
Member

methane commented Aug 23, 2015

Is there some reassurance I can help with the acceptance of this patch?

  • This PR is large.
  • I don't have time to test authentication plugins.

@@ -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'
Copy link
Member

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?

Copy link
Contributor Author

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.

@methane
Copy link
Member

methane commented Aug 23, 2015

PyMySQL doesn't have enough test suite about authentication.
So I'm afraid of merging such large PR.

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)
Copy link
Member

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'

@grooverdan
Copy link
Contributor Author

PyMySQL doesn't have enough test suite about authentication.

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 don't have time to test authentication plugins.

I've extended the test suite a bit more to cover it.

So I'm afraid of merging such large PR.

ok. Hoping adding more tests is a sufficient way to test this.

@grooverdan grooverdan force-pushed the expose_auth_plugin_name branch from 5901faf to 8cc9cdf Compare August 25, 2015 12:10
@grooverdan grooverdan changed the title Add basic authentication plugin support Add authentication plugin support Aug 30, 2015
@grooverdan
Copy link
Contributor Author

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?

@grooverdan
Copy link
Contributor Author

I'm finished. Questions/queries or requests for fixing code welcome.

@nicklasb
Copy link

Just lurking this...
In my understanding, it is currently not possible to authenticate over sockets, which seems like a really severe problem(at least it is for me), which this PR seems to address.

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. :-)

@grooverdan
Copy link
Contributor Author

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.

@nicklasb
Copy link

Thanks for your response, @grooverdan .
Well, sometime that happens, especially if one continues to improve it.

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.

@nicklasb
Copy link

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.

@nicklasb
Copy link

Hi @grooverdan and @methane, I have now tried with this branch, and it works.
However, it says that the MariaDB issue(#243) is resolved by this, but as this isn't merged, that isn't strictly true, and should as such be reopended.

methane added a commit that referenced this pull request Jan 3, 2016
@methane methane merged commit 1893637 into PyMySQL:master Jan 3, 2016
@grooverdan
Copy link
Contributor Author

thanks @methane

@grooverdan grooverdan deleted the expose_auth_plugin_name branch January 3, 2016 05:48
@methane
Copy link
Member

methane commented Jan 3, 2016

While I've merged this pull request, I couldn't get how connection.next_packet works.
Until I understand it and refactoring it for future maintenance, I won't release next version.

@nicklasb
Copy link

nicklasb commented Jan 3, 2016

It's OK. Cool kids use #master. :-)

@grooverdan
Copy link
Contributor Author

I couldn't get how connection.next_packet works.

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

@methane
Copy link
Member

methane commented Jan 4, 2016

Thanks for reply.
But I have researched it already and refactoring it now.
See #405.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 4, 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.

3 participants