MINOR: checks: mysql-check: Add support for v4.1+ authentication

MySQL will in stop supporting pre-4.1 authentication packets in the future
and is already giving us a hard time regarding non-silencable warnings
which are logged on each health check. Warnings look like the following:

"[Warning] Client failed to provide its character set. 'latin1' will be used
as client character set."

This patch adds basic support for post-4.1 authentication by sending the proper
authentication packet with the character set, along with the QUIT command.
This commit is contained in:
Nenad Merdanovic 2014-05-30 14:26:32 +02:00 committed by Willy Tarreau
parent 1592d1e72a
commit 6639a7cf0d
2 changed files with 66 additions and 18 deletions

View File

@ -4458,13 +4458,14 @@ no option logasap
logging. logging.
option mysql-check [ user <username> ] option mysql-check [ user <username> [ post-41 ] ]
Use MySQL health checks for server testing Use MySQL health checks for server testing
May be used in sections : defaults | frontend | listen | backend May be used in sections : defaults | frontend | listen | backend
yes | no | yes | yes yes | no | yes | yes
Arguments : Arguments :
<username> This is the username which will be used when connecting to MySQL <username> This is the username which will be used when connecting to MySQL
server. server.
post-41 Send post v4.1 client compatible checks
If you specify a username, the check consists of sending two MySQL packet, If you specify a username, the check consists of sending two MySQL packet,
one Client Authentication packet, and one QUIT packet, to correctly close one Client Authentication packet, and one QUIT packet, to correctly close

View File

@ -3869,7 +3869,7 @@ stats_error_parsing:
curproxy->options2 &= ~PR_O2_CHK_ANY; curproxy->options2 &= ~PR_O2_CHK_ANY;
curproxy->options2 |= PR_O2_MYSQL_CHK; curproxy->options2 |= PR_O2_MYSQL_CHK;
/* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte. /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
* const char mysql40_client_auth_pkt[] = { * const char mysql40_client_auth_pkt[] = {
* "\x0e\x00\x00" // packet length * "\x0e\x00\x00" // packet length
* "\x01" // packet number * "\x01" // packet number
@ -3883,6 +3883,23 @@ stats_error_parsing:
* }; * };
*/ */
/* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
* const char mysql41_client_auth_pkt[] = {
* "\x0e\x00\x00\" // packet length
* "\x01" // packet number
* "\x00\x00\x00\x00" // client capabilities
* "\x00\x00\x00\x01" // max packet
* "\x21" // character set (UTF-8)
* char[23] // All zeroes
* "haproxy\x00" // username (null terminated string)
* "\x00" // filler (always 0x00)
* "\x01\x00\x00" // packet length
* "\x00" // packet number
* "\x01" // COM_QUIT command
* };
*/
if (*(args[2])) { if (*(args[2])) {
int cur_arg = 2; int cur_arg = 2;
@ -3900,6 +3917,35 @@ stats_error_parsing:
} }
mysqluser = args[cur_arg + 1]; mysqluser = args[cur_arg + 1];
userlen = strlen(mysqluser); userlen = strlen(mysqluser);
if (*(args[cur_arg+2])) {
if (!strcmp(args[cur_arg+2], "post-41")) {
packetlen = userlen + 7 + 27;
reqlen = packetlen + 9;
free(curproxy->check_req);
curproxy->check_req = (char *)calloc(1, reqlen);
curproxy->check_len = reqlen;
snprintf(curproxy->check_req, 4, "%c%c%c",
((unsigned char) packetlen & 0xff),
((unsigned char) (packetlen >> 8) & 0xff),
((unsigned char) (packetlen >> 16) & 0xff));
curproxy->check_req[3] = 1;
curproxy->check_req[5] = 130;
curproxy->check_req[11] = 1;
curproxy->check_req[12] = 33;
memcpy(&curproxy->check_req[36], mysqluser, userlen);
curproxy->check_req[36 + userlen + 1 + 1] = 1;
curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
cur_arg += 3;
} else {
Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
} else {
packetlen = userlen + 7; packetlen = userlen + 7;
reqlen = packetlen + 9; reqlen = packetlen + 9;
@ -3919,6 +3965,7 @@ stats_error_parsing:
curproxy->check_req[9 + userlen + 1 + 1] = 1; curproxy->check_req[9 + userlen + 1 + 1] = 1;
curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1; curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
cur_arg += 2; cur_arg += 2;
}
} else { } else {
/* unknown suboption - catchall */ /* unknown suboption - catchall */
Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n", Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",