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