[CONC-469] auth_socket authentication (MySQL 8 Server) not supported Created: 2020-05-22  Updated: 2020-05-25  Resolved: 2020-05-25

Status: Closed
Project: MariaDB Connector/C
Component/s: None
Affects Version/s: 3.1.8
Fix Version/s: 3.1.9

Type: Bug Priority: Major
Reporter: Klaus Keppler Assignee: Georg Richter
Resolution: Fixed Votes: 0
Labels: MySQL8, authentication
Environment:

MySQL 8.0.20, Ubuntu 20.04 LTS



 Description   

Currently it's not possible to connect to a MySQL 8 server using an account configured with auth_socket authentication.
In its default installation, MySQL 8 on Ubuntu 20.04 uses auth_socket for the root account.

I've compiled a minimal test program for the connection:

#include <stdio.h>
#include <stdlib.h>
#include <mysql.h>
int main(int argc, char *argv[]) {
	MYSQL mysql;
	mysql_init(&mysql);
	printf("connecting...\n");
	if (!mysql_real_connect(&mysql,"localhost","root",NULL,NULL, 0, "/var/run/mysqld/mysqld.sock", 0)) {
		fprintf(stderr, "Failed to connect to database: Error: %s\n",
		mysql_error(&mysql));
		return(1);
	}
 
	printf("Connected.\n");
	return(0);

The MariaDB Connector/C is compiled and linked statically:

CFLAGS=-DMYSQL_CLIENT=1 cmake .. -DCLIENT_PLUGIN_DIALOG=OFF -DCLIENT_PLUGIN_CLEARTEXT=STATIC
 -DCLIENT_PLUGIN_AUTH_GSSAPI=STATIC -DCLIENT_PLUGIN_SHA256_PASSWORD=STATIC -DCLIENT_PLUGIN_CACHING_S
HA2_PASSWORD=STATIC -DCLIENT_PLUGIN_MYSQL_CLEAR_PASSWORD=STATIC -DCLIENT_PLUGIN_MYSQL_OLD_PASSWORD=S
TATIC \
 -DCMAKE_BUILD_TYPE=Release \
...

The test program runs fine when connecting to a MariaDB 10.3 server (root account configured with plugin unix_socket).
However, running the same binary when connecting to MySQL 8, it aborts:

connecting...
Failed to connect to database: Error: Error in server handshake

strace output:

[...]
socket(AF_UNIX, SOCK_STREAM, 0)         = 3
fcntl(3, F_SETFL, O_RDONLY|O_NONBLOCK)  = 0
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/mysqld/mysqld.sock"}, 110) = 0
fcntl(3, F_SETFL, O_RDONLY)             = 0
setsockopt(3, SOL_IP, IP_TOS, [8], 4)   = -1 EOPNOTSUPP (Operation not supported)
setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
recvfrom(3, "[\0\0\0\n8.0.20-0ubuntu0.20.04.1\0\335\n\0"..., 16384, MSG_DONTWAIT, NULL, NULL) = 95
sendto(3, "\250\0\0\1\205\242\236\0\0\0\0@\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 172, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 172
recvfrom(3, "\7\0\0\2\0\0\0\2\0\0\0", 16384, MSG_DONTWAIT, NULL, NULL) = 11
close(3)                                = 0
write(2, "Failed to connect to database: E"..., 64Failed to connect to database: Error: Error in server handshake
) = 64
exit_group(1)                           = ?
+++ exited with 1 +++

Log message in MySQL error.log:

2020-05-22T06:28:40.787048Z 2798 [Note] [MY-010914] [Server] Aborted connection 2798 to db: 'mysql' user: 'root' host: 'localhost' (Got an error reading communication packets).

On MySQL 8.0, the plugin column for the root account contains auth_socket, while on MariaDB it is unix_socket:

mysql> select host, user, plugin from mysql.user where user='root';
+-----------+------+-------------+
| host      | user | plugin      |
+-----------+------+-------------+
| localhost | root | auth_socket |
+-----------+------+-------------+
1 row in set (0.01 sec)

Maybe this might be a problem?

Please let me know if I can provide more informations. I've already had a look at the Connector/C source; the error CR_SERVER_HANDSHAKE_ERR looks to be only returned from within the auth-plugins.

Currently the Connector/C can't be used as a "drop-in replacement" in combination with MySQL 8, though the auth code for caching_sha2_pwd already has been included.

Thanks & best regards!

-Klaus



 Comments   
Comment by Klaus Keppler [ 2020-05-22 ]

Just for comparison: this is the strace when connecting to a MariaDB 10.3 server (Debian 10):

socket(AF_UNIX, SOCK_STREAM, 0)         = 3
fcntl(3, F_SETFL, O_RDONLY|O_NONBLOCK)  = 0
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/mysqld/mysqld.sock"}, 110) = 0
fcntl(3, F_SETFL, O_RDONLY)             = 0
setsockopt(3, SOL_IP, IP_TOS, [8], 4)   = -1 EOPNOTSUPP (Operation not supported)
setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
recvfrom(3, 0x55a9fdb2e010, 16384, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "c\0\0\0\n5.5.5-10.3.22-MariaDB-0+deb"..., 16384, MSG_DONTWAIT, NULL, NULL) = 103
sendto(3, "\247\0\0\1\204\242\236\0\0\0\0@\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 171, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 171
recvfrom(3, 0x55a9fdb2e010, 16384, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "\7\0\0\2\0\0\0\2\0\0\0", 16384, MSG_DONTWAIT, NULL, NULL) = 11
setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
write(1, "Connected.\n", 11Connected.
)            = 11
exit_group(0)                           = ?
+++ exited with 0 +++

Comment by Georg Richter [ 2020-05-25 ]

Obviously there seems to be a bug in MySQL 8.0, since MySQL 8.0 requires that the client uses the caching_sha2_password plugin, even if encryption is not used. Instead of sending a change_auth_plugin request the server returns an error if the client uses the default mysql_native_password plugin (which should be sufficient for socket authentication). This can be reproduced also by using an older mysql command line client (I tested it with mysql command line client version 5.6).

A workaround would be to set the default authentication via mysql_options() call:

mysql_options(mysql, MYSQL_DEFAULT_AUTH, "caching_sha2_password");

However the current implementation in Connector/C (but also libmysql) should be improved to avoid sending additional packages:

1) If specified use default authentication method
2) use authentication method in server hello packet, if no default authentication was specified
3) in all other cases use mysql_native_password (or old_password) authentication

Comment by Klaus Keppler [ 2020-05-25 ]

Thank you for your fast & detailed response - that's absolutely great!
The workaround works fine.
For other readers: here's the link to the documentation on client authentication plugins:
https://mariadb.com/kb/en/pluggable-authentication-overview/#default-client-authentication-plugin

Comment by Georg Richter [ 2020-05-25 ]

Fixed rev. f49bb1c2cd40bc343876bcdd43913d5d1ca27d04

Generated at Thu Feb 08 03:05:33 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.