The backend didn't expect AuthSwitchRequest packets in response to the
handshake response packets. This is allowed by the protocol and appears to
happen with at least MySQL 8.0.
The Connector-C was changed to always return only the client's charset,
not the actual charset that the connection ends up using. To cope with
this, the code has to use SQL to join the default character set name to
the default collation for it which can be used to extract the numeric ID
of the charset.
The default database was not exposed in the warning that was logged when
authentication failed. The authentication uses the username, host and the
default database to find the user entry and the lack of the default
database made it hard to know for sure which user entry a client should've
matched against.
The SQL for the second recursive CTE table can be optimized by adding a
where condition on the recursive part that rules out users that are not
roles. The functionality remains the same as only roles can be granted to
users.
Because of how the user-data was read, the same service name could be
found multiple times if the user-search query matched multiple rows. Now
the service names are read to a set, which ignores duplicates. The same
service may be attempted again if the authentication fails and user-data
is fetched again.
The new server pam plugin does not always send the first password prompt with the
AuthSwitchRequest-packet. In this case the server expects the client (MaxScale) to
just send the password immediately. MaxScale now checks the length of the packet,
sending the password if the packet is short. This works with both old and new server
versions.
MySQLAuth now logs the server where the users were loaded from. As only
the initial loading of users causes a log message, it is still possible
for the source server to change without any indication of it.
Older clients assume the plugin used for authentication is
mysql_native_password. If the client doesn't request plugin
authentication, don't treat it as an error.
Plugins may send additional messages during authentication. These messages
often contain notifications such as password expiration dates. Both the client
and backend side authenticators now handle such messages. The messages are not
sent to the user, only the log. The requirement that only "Password: " is queried
still stands.
Some SQL clients may default to a different authentication plugin than
"mysql_native_password". Since this is the only one supported by MySQL-
authenticator, the client is instructed to swap its plugin.
Due to MDEV-15556 and MDEV-15840 recursive CTEs can't be reliably used
with older 10.2 versions. To prevent problems, only use the query that
extracts composite roles with newer versions.
The authentication code did not initialize one of the buffers used to
calculate the password hashes. This resulted in the use of uninitialized
memory when the user provided no password.
If a 10.2.11 or older server without a grant on all mysql tables is found,
the authenticator now falls back to the 10.1 behavior that uses subqueries
instead of CTEs. This is a more user friendly way of working around
MDEV-13453 that causes the problem as all functionality except the support
for composite roles is retained.
If the password field in mysql.user is empty, it is possible that the
actual password is stored in the authentication_string field. Most of the
time this happens due to MDEV-16774 which causes the password to be stored
in the authentication_string field.
Also added a test case that verifies the problem and that it is fixed by
this commit.
Instead of looking at the server version, the actual error message should
be inspected. This guarantees that the correct error message is logged
even with custom builds.