Description:
Starting from MySQL 5.1.57, I couldn't connect to mysqld from
older MySQL clients including MySQL 4.0 and client bindings built from 4.0 libmysqlclient.
How to repeat:
Get 4.0 mysql binary
$ mysql(4.0) -hmysql_5.1.57_host -pxxx
ERROR 1043: Bad handshake
Suggested fix:
I briefly checked with debugger and the error was raised here.
sql/sql_connect.cc check_connection(THD *thd)
...
else
{
/*
Old passwords are zero terminated strings.
*/
passwd= get_null_terminated_string(&end, &bytes_remaining_in_packet,
&passwd_len);
}
if (passwd == NULL)
{
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
return 1;
}
get_null_terminated_string() returned 0x0, and ER_HANDSHAKE_ERROR was returned.
As far as I checked, MySQL 4.0 client does not send null-terminated password to MySQL. The below was I captured on MySQL server.
0x0000: 0016 364c a9d1 0024 3817 fc00 0800 4508 ..6L...$8.....E.
0x0010: 004a bfd3 4000 3e06 5cde 0a09 09eb 0a11 .J..@.>.\.......
0x0020: 01f0 d357 0cea 800d 1a4a ccac d2a0 8018 ...W.....J......
0x0030: 05b4 6be7 0000 0101 080a a3c2 a588 2f24 ..k.........../$
0x0040: 9864 1200 0001 8524 0000 0072 6f6f 7400 .d.....$...root.
0x0050: 5b5f 434b 5654 4a4e [_CKVTJN
It's not ended with 0x0.
----
char *get_null_terminated_string(char **buffer,
size_t *max_bytes_available,
size_t *string_length)
{
char *str= (char *)memchr(*buffer, '\0', *max_bytes_available);
if (str == NULL)
return NULL;
----
*string_length was 8, but 0x0 was not between (*buffer)[0] and (*buffer)[7]. So NULL was returned.