From 5fca34186f1cef71a25e0ec5833c0cee341f380b Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Fri, 20 Nov 2015 18:34:35 +0100 Subject: [PATCH] Initial implementation for MDEV-9117: 10.2 protocol changes - exchanging mariadb specific client/server capabilities during handshake --- include/mysql.h | 19 ++++++++++--------- include/mysql_com.h | 12 ++++++++++-- libmariadb/libmariadb.c | 15 ++++++++++++--- plugins/auth/my_auth.c | 13 ++++++++++++- 4 files changed, 44 insertions(+), 15 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index b61eb84f..d2a5c7e3 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -276,17 +276,18 @@ struct st_mysql_options { my_ulonglong extra_info; /* Used by mysqlshow */ unsigned long thread_id; /* Id for connection in server */ unsigned long packet_length; - unsigned int port; - unsigned long client_flag,server_capabilities; /* changed from int to long in 4.1 protocol */ - unsigned int protocol_version; - unsigned int field_count; - unsigned int server_status; - unsigned int server_language; - unsigned int warning_count; /* warning count, added in 4.1 protocol */ + unsigned int port; + unsigned long long client_flag; + unsigned long long server_capabilities; /* changed from long to longlong in 10.2 protocol */ + unsigned int protocol_version; + unsigned int field_count; + unsigned int server_status; + unsigned int server_language; + unsigned int warning_count; /* warning count, added in 4.1 protocol */ struct st_mysql_options options; enum mysql_status status; - my_bool free_me; /* If free in mysql_close */ - my_bool reconnect; /* set to 1 if automatic reconnect */ + my_bool free_me; /* If free in mysql_close */ + my_bool reconnect; /* set to 1 if automatic reconnect */ char scramble_buff[20+ 1]; /* madded after 3.23.58 */ my_bool unused_1; diff --git a/include/mysql_com.h b/include/mysql_com.h index f1d4eb69..eba227fb 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -154,7 +154,15 @@ enum enum_server_command #define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) #define CLIENT_REMEMBER_OPTIONS (1UL << 31) -#define CLIENT_SUPPORTED_FLAGS (CLIENT_LONG_PASSWORD | \ +/* MariaDB specific capabilities */ +#define MARIADB_CLIENT_FLAGS 0xFFFFFFFF00000000ULL +#define MARIADB_CLIENT_PROGRESS (1ULL << 32) +#define MARIADB_CLIENT_EXTENDED_PROTOCOL (1ULL << 63) + +#define MARIADB_CLIENT_SUPPORTED_FLAGS (MARIADB_CLIENT_PROGRESS |\ + MARIADB_CLIENT_EXTENDED_PROTOCOL) + +#define CLIENT_SUPPORTED_FLAGS (CLIENT_LONG_PASSWORD |\ CLIENT_FOUND_ROWS |\ CLIENT_LONG_FLAG |\ CLIENT_CONNECT_WITH_DB |\ @@ -178,7 +186,7 @@ enum enum_server_command CLIENT_PLUGIN_AUTH |\ CLIENT_CONNECT_ATTRS) -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD |\ +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \ CLIENT_LONG_FLAG |\ CLIENT_TRANSACTIONS |\ CLIENT_SECURE_CONNECTION |\ diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 1590df17..1a5e62b4 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -70,6 +70,7 @@ #include #define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15) +#define MA_RPL_VERSION_HACK "5.5.5-" #undef max_allowed_packet #undef net_buffer_length @@ -1308,6 +1309,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, MA_PVIO_CINFO cinfo= {NULL, NULL, 0, -1, NULL}; MARIADB_PVIO *pvio= NULL; char *scramble_data; + my_bool is_maria= 0; const char *scramble_plugin; uint pkt_length, scramble_len, pkt_scramble_len= 0; NET *net= &mysql->net; @@ -1532,13 +1534,14 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, mysql->port=port; client_flag|=mysql->options.client_flag; - if (strncmp(end, "5.5.5-", 6) == 0) + if (strncmp(end, MA_RPL_VERSION_HACK, sizeof(MA_RPL_VERSION_HACK)) == 0) { - if (!(mysql->server_version= my_strdup(end + 6, 0))) + if (!(mysql->server_version= my_strdup(end + sizeof(MA_RPL_VERSION_HACK), 0))) { SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); goto error; } + is_maria= 1; } else { @@ -1575,7 +1578,14 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, mysql->server_status= uint2korr(end + 3); mysql->server_capabilities|= uint2korr(end + 5) << 16; pkt_scramble_len= uint1korr(end + 7); + + /* check if MariaD2B specific capabilities are available */ + if (is_maria && !(mysql->server_capabilities & CLIENT_LONG_PASSWORD)) + { + mysql->server_capabilities|= (ulonglong) uint4korr(end + 14) << 32; + } } + /* pad 2 */ end+= 18; @@ -1605,7 +1615,6 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, } } - /* Set character set */ if (mysql->options.charset_name) mysql->charset= mysql_find_charset_name(mysql->options.charset_name); diff --git a/plugins/auth/my_auth.c b/plugins/auth/my_auth.c index 08505685..e1a8b95c 100644 --- a/plugins/auth/my_auth.c +++ b/plugins/auth/my_auth.c @@ -169,6 +169,12 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, if (mysql->client_flag & CLIENT_MULTI_STATEMENTS) mysql->client_flag|= CLIENT_MULTI_RESULTS; + /* if server supports extended MariaDB extended protocol, we will unset + CLIENT_LONG_PASSWORD and send extended client capabilities in last + four of 23 unused bytes */ + if (mysql->server_capabilities & MARIADB_CLIENT_EXTENDED_PROTOCOL) + mysql->client_flag &= ~CLIENT_LONG_PASSWORD; + #if defined(HAVE_SSL) && !defined(EMBEDDED_LIBRARY) if (mysql->options.ssl_key || mysql->options.ssl_cert || mysql->options.ssl_ca || mysql->options.ssl_capath || @@ -211,7 +217,12 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, int4store(buff,mysql->client_flag); int4store(buff+4, net->max_packet_size); buff[8]= (char) mysql->charset->nr; - bzero(buff+9, 32-9); + bzero(buff + 9, 32-9); + if (!(mysql->server_capabilities & MARIADB_CLIENT_EXTENDED_PROTOCOL)) + { + mysql->client_flag |= MARIADB_CLIENT_SUPPORTED_FLAGS; + int4store(buff + 28, mysql->client_flag << 32); + } end= buff+32; } else