mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Client attributes
This commit is contained in:
@ -1359,6 +1359,9 @@ sig_handler handle_sigint(int sig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
kill_mysql= mysql_init(kill_mysql);
|
kill_mysql= mysql_init(kill_mysql);
|
||||||
|
mysql_options(kill_mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(kill_mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysql");
|
||||||
if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password,
|
if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password,
|
||||||
"", opt_mysql_port, opt_mysql_unix_port,0))
|
"", opt_mysql_port, opt_mysql_unix_port,0))
|
||||||
{
|
{
|
||||||
@ -4606,6 +4609,9 @@ sql_real_connect(char *host,char *database,char *user,char *password,
|
|||||||
if (opt_default_auth && *opt_default_auth)
|
if (opt_default_auth && *opt_default_auth)
|
||||||
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||||
|
|
||||||
|
mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysql");
|
||||||
if (!mysql_real_connect(&mysql, host, user, password,
|
if (!mysql_real_connect(&mysql, host, user, password,
|
||||||
database, opt_mysql_port, opt_mysql_unix_port,
|
database, opt_mysql_port, opt_mysql_unix_port,
|
||||||
connect_flag | CLIENT_MULTI_STATEMENTS))
|
connect_flag | CLIENT_MULTI_STATEMENTS))
|
||||||
|
@ -370,6 +370,9 @@ int main(int argc,char *argv[])
|
|||||||
if (opt_default_auth && *opt_default_auth)
|
if (opt_default_auth && *opt_default_auth)
|
||||||
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||||
|
|
||||||
|
mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysqladmin");
|
||||||
if (sql_connect(&mysql, option_wait))
|
if (sql_connect(&mysql, option_wait))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -1745,6 +1745,9 @@ static Exit_status safe_connect()
|
|||||||
mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
|
mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
|
||||||
shared_memory_base_name);
|
shared_memory_base_name);
|
||||||
#endif
|
#endif
|
||||||
|
mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysqlbinlog");
|
||||||
if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0))
|
if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0))
|
||||||
{
|
{
|
||||||
error("Failed on connect: %s", mysql_error(mysql));
|
error("Failed on connect: %s", mysql_error(mysql));
|
||||||
|
@ -915,6 +915,9 @@ static int dbConnect(char *host, char *user, char *passwd)
|
|||||||
mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||||
|
|
||||||
mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
|
mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
|
||||||
|
mysql_options(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysqlcheck");
|
||||||
if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd,
|
if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd,
|
||||||
NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
|
NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
|
||||||
{
|
{
|
||||||
|
@ -1542,6 +1542,9 @@ static int connect_to_db(char *host, char *user,char *passwd)
|
|||||||
if (opt_default_auth && *opt_default_auth)
|
if (opt_default_auth && *opt_default_auth)
|
||||||
mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||||
|
|
||||||
|
mysql_options(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysqldump");
|
||||||
mysql= &mysql_connection; /* So we can mysql_close() it properly */
|
mysql= &mysql_connection; /* So we can mysql_close() it properly */
|
||||||
if (!mysql_real_connect(&mysql_connection,host,user,passwd,
|
if (!mysql_real_connect(&mysql_connection,host,user,passwd,
|
||||||
NULL,opt_mysql_port,opt_mysql_unix_port, 0))
|
NULL,opt_mysql_port,opt_mysql_unix_port, 0))
|
||||||
|
@ -456,6 +456,9 @@ static MYSQL *db_connect(char *host, char *database,
|
|||||||
mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||||
|
|
||||||
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
|
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
|
||||||
|
mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysqlimport");
|
||||||
if (!(mysql_real_connect(mysql,host,user,passwd,
|
if (!(mysql_real_connect(mysql,host,user,passwd,
|
||||||
database,opt_mysql_port,opt_mysql_unix_port,
|
database,opt_mysql_port,opt_mysql_unix_port,
|
||||||
0)))
|
0)))
|
||||||
|
@ -141,6 +141,9 @@ int main(int argc, char **argv)
|
|||||||
if (opt_default_auth && *opt_default_auth)
|
if (opt_default_auth && *opt_default_auth)
|
||||||
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||||
|
|
||||||
|
mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysqlshow");
|
||||||
if (!(mysql_real_connect(&mysql,host,user,opt_password,
|
if (!(mysql_real_connect(&mysql,host,user,opt_password,
|
||||||
(first_argument_uses_wildcards) ? "" :
|
(first_argument_uses_wildcards) ? "" :
|
||||||
argv[0],opt_mysql_port,opt_mysql_unix_port,
|
argv[0],opt_mysql_port,opt_mysql_unix_port,
|
||||||
|
@ -362,6 +362,9 @@ int main(int argc, char **argv)
|
|||||||
if (opt_default_auth && *opt_default_auth)
|
if (opt_default_auth && *opt_default_auth)
|
||||||
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||||
|
|
||||||
|
mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysqlslap");
|
||||||
if (!opt_only_print)
|
if (!opt_only_print)
|
||||||
{
|
{
|
||||||
if (!(mysql_real_connect(&mysql, host, user, opt_password,
|
if (!(mysql_real_connect(&mysql, host, user, opt_password,
|
||||||
|
@ -5648,6 +5648,10 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host,
|
|||||||
verbose_msg("Connecting to server %s:%d (socket %s) as '%s'"
|
verbose_msg("Connecting to server %s:%d (socket %s) as '%s'"
|
||||||
", connection '%s', attempt %d ...",
|
", connection '%s', attempt %d ...",
|
||||||
host, port, sock, user, name, failed_attempts);
|
host, port, sock, user, name, failed_attempts);
|
||||||
|
|
||||||
|
mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"program_name", "mysqltest");
|
||||||
while(!mysql_real_connect(mysql, host,user, pass, db, port, sock,
|
while(!mysql_real_connect(mysql, host,user, pass, db, port, sock,
|
||||||
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
|
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
|
||||||
{
|
{
|
||||||
@ -5748,7 +5752,9 @@ int connect_n_handle_errors(struct st_command *command,
|
|||||||
replace_dynstr_append(ds, command->query);
|
replace_dynstr_append(ds, command->query);
|
||||||
dynstr_append_mem(ds, ";\n", 2);
|
dynstr_append_mem(ds, ";\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mysql_options(con, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||||
|
mysql_options4(con, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysqltest");
|
||||||
while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
|
while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
|
||||||
CLIENT_MULTI_STATEMENTS))
|
CLIENT_MULTI_STATEMENTS))
|
||||||
{
|
{
|
||||||
|
@ -557,6 +557,8 @@ int STDCALL mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql,
|
|||||||
int status);
|
int status);
|
||||||
int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
|
int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
|
||||||
const void *arg);
|
const void *arg);
|
||||||
|
int STDCALL mysql_options4(MYSQL *mysql,enum mysql_option option,
|
||||||
|
const void *arg1, const void *arg2);
|
||||||
void STDCALL mysql_free_result(MYSQL_RES *result);
|
void STDCALL mysql_free_result(MYSQL_RES *result);
|
||||||
int STDCALL mysql_free_result_start(MYSQL_RES *result);
|
int STDCALL mysql_free_result_start(MYSQL_RES *result);
|
||||||
int STDCALL mysql_free_result_cont(MYSQL_RES *result, int status);
|
int STDCALL mysql_free_result_cont(MYSQL_RES *result, int status);
|
||||||
|
@ -552,6 +552,8 @@ int mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql,
|
|||||||
int status);
|
int status);
|
||||||
int mysql_options(MYSQL *mysql,enum mysql_option option,
|
int mysql_options(MYSQL *mysql,enum mysql_option option,
|
||||||
const void *arg);
|
const void *arg);
|
||||||
|
int mysql_options4(MYSQL *mysql,enum mysql_option option,
|
||||||
|
const void *arg1, const void *arg2);
|
||||||
void mysql_free_result(MYSQL_RES *result);
|
void mysql_free_result(MYSQL_RES *result);
|
||||||
int mysql_free_result_start(MYSQL_RES *result);
|
int mysql_free_result_start(MYSQL_RES *result);
|
||||||
int mysql_free_result_cont(MYSQL_RES *result, int status);
|
int mysql_free_result_cont(MYSQL_RES *result, int status);
|
||||||
|
@ -1921,6 +1921,7 @@ typedef struct PSI_digest_locker* (*digest_add_token_v1_t)
|
|||||||
typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length,
|
typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length,
|
||||||
const void *from_cs);
|
const void *from_cs);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Performance Schema Interface, version 1.
|
Performance Schema Interface, version 1.
|
||||||
@since PSI_VERSION_1
|
@since PSI_VERSION_1
|
||||||
|
@ -264,7 +264,8 @@ enum enum_server_command
|
|||||||
CLIENT_SSL_VERIFY_SERVER_CERT | \
|
CLIENT_SSL_VERIFY_SERVER_CERT | \
|
||||||
CLIENT_REMEMBER_OPTIONS | \
|
CLIENT_REMEMBER_OPTIONS | \
|
||||||
CLIENT_PROGRESS | \
|
CLIENT_PROGRESS | \
|
||||||
CLIENT_PLUGIN_AUTH)
|
CLIENT_PLUGIN_AUTH | \
|
||||||
|
CLIENT_CONNECT_ATTRS)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
To be added later:
|
To be added later:
|
||||||
|
@ -43,6 +43,8 @@ struct st_mysql_options_extention {
|
|||||||
const char *proc_info,
|
const char *proc_info,
|
||||||
uint proc_info_length);
|
uint proc_info_length);
|
||||||
struct mysql_async_context *async_context;
|
struct mysql_async_context *async_context;
|
||||||
|
HASH connection_attributes;
|
||||||
|
size_t connection_attributes_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct st_mysql_methods
|
typedef struct st_mysql_methods
|
||||||
@ -116,6 +118,7 @@ int mysql_client_plugin_init();
|
|||||||
void mysql_client_plugin_deinit();
|
void mysql_client_plugin_deinit();
|
||||||
struct st_mysql_client_plugin;
|
struct st_mysql_client_plugin;
|
||||||
extern struct st_mysql_client_plugin *mysql_client_builtins[];
|
extern struct st_mysql_client_plugin *mysql_client_builtins[];
|
||||||
|
uchar * send_client_connect_attrs(MYSQL *mysql, uchar *buf);
|
||||||
|
|
||||||
/* Non-blocking client API. */
|
/* Non-blocking client API. */
|
||||||
void my_context_install_suspend_resume_hook(struct mysql_async_context *b,
|
void my_context_install_suspend_resume_hook(struct mysql_async_context *b,
|
||||||
|
@ -34,7 +34,8 @@ extern char * mysql_unix_port;
|
|||||||
CLIENT_SECURE_CONNECTION | \
|
CLIENT_SECURE_CONNECTION | \
|
||||||
CLIENT_MULTI_RESULTS | \
|
CLIENT_MULTI_RESULTS | \
|
||||||
CLIENT_PS_MULTI_RESULTS | \
|
CLIENT_PS_MULTI_RESULTS | \
|
||||||
CLIENT_PLUGIN_AUTH)
|
CLIENT_PLUGIN_AUTH | \
|
||||||
|
CLIENT_CONNECT_ATTRS)
|
||||||
|
|
||||||
sig_handler my_pipe_sig_handler(int sig);
|
sig_handler my_pipe_sig_handler(int sig);
|
||||||
void read_user_name(char *name);
|
void read_user_name(char *name);
|
||||||
|
@ -638,7 +638,6 @@ void init_embedded_mysql(MYSQL *mysql, int client_flag)
|
|||||||
thd->mysql= mysql;
|
thd->mysql= mysql;
|
||||||
mysql->server_version= server_version;
|
mysql->server_version= server_version;
|
||||||
mysql->client_flag= client_flag;
|
mysql->client_flag= client_flag;
|
||||||
//mysql->server_capabilities= client_flag;
|
|
||||||
init_alloc_root(&mysql->field_alloc, 8192, 0, MYF(0));
|
init_alloc_root(&mysql->field_alloc, 8192, 0, MYF(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,12 +697,38 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
emb_transfer_connect_attrs(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_PSI_THREAD_INTERFACE
|
||||||
|
if (mysql->options.extension &&
|
||||||
|
mysql->options.extension->connection_attributes_length)
|
||||||
|
{
|
||||||
|
uchar *buf, *ptr;
|
||||||
|
THD *thd= (THD*)mysql->thd;
|
||||||
|
size_t length= mysql->options.extension->connection_attributes_length;
|
||||||
|
|
||||||
|
/* 9 = max length of the serialized length */
|
||||||
|
ptr= buf= (uchar *) my_alloca(length + 9);
|
||||||
|
send_client_connect_attrs(mysql, buf);
|
||||||
|
net_field_length_ll(&ptr);
|
||||||
|
PSI_THREAD_CALL(set_thread_connect_attrs)((char *) ptr, length, thd->charset());
|
||||||
|
my_afree(buf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef NO_EMBEDDED_ACCESS_CHECKS
|
#ifdef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
int check_embedded_connection(MYSQL *mysql, const char *db)
|
int check_embedded_connection(MYSQL *mysql, const char *db)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
LEX_STRING db_str = { (char*)db, db ? strlen(db) : 0 };
|
LEX_STRING db_str = { (char*)db, db ? strlen(db) : 0 };
|
||||||
THD *thd= (THD*)mysql->thd;
|
THD *thd= (THD*)mysql->thd;
|
||||||
|
|
||||||
|
/* the server does the same as the client */
|
||||||
|
mysql->server_capabilities= mysql->client_flag;
|
||||||
|
|
||||||
thd_init_client_charset(thd, mysql->charset->number);
|
thd_init_client_charset(thd, mysql->charset->number);
|
||||||
thd->update_charset();
|
thd->update_charset();
|
||||||
Security_context *sctx= thd->security_ctx;
|
Security_context *sctx= thd->security_ctx;
|
||||||
@ -713,6 +738,7 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
|
|||||||
sctx->user= my_strdup(mysql->user, MYF(0));
|
sctx->user= my_strdup(mysql->user, MYF(0));
|
||||||
sctx->proxy_user[0]= 0;
|
sctx->proxy_user[0]= 0;
|
||||||
sctx->master_access= GLOBAL_ACLS; // Full rights
|
sctx->master_access= GLOBAL_ACLS; // Full rights
|
||||||
|
emb_transfer_connect_attrs(mysql);
|
||||||
/* Change database if necessary */
|
/* Change database if necessary */
|
||||||
if (!(result= (db && db[0] && mysql_change_db(thd, &db_str, FALSE))))
|
if (!(result= (db && db[0] && mysql_change_db(thd, &db_str, FALSE))))
|
||||||
my_ok(thd);
|
my_ok(thd);
|
||||||
@ -728,11 +754,16 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
|
|||||||
we emulate a COM_CHANGE_USER user here,
|
we emulate a COM_CHANGE_USER user here,
|
||||||
it's easier than to emulate the complete 3-way handshake
|
it's easier than to emulate the complete 3-way handshake
|
||||||
*/
|
*/
|
||||||
char buf[USERNAME_LENGTH + SCRAMBLE_LENGTH + 1 + 2*NAME_LEN + 2], *end;
|
char *buf, *end;
|
||||||
NET *net= &mysql->net;
|
NET *net= &mysql->net;
|
||||||
THD *thd= (THD*)mysql->thd;
|
THD *thd= (THD*)mysql->thd;
|
||||||
Security_context *sctx= thd->security_ctx;
|
Security_context *sctx= thd->security_ctx;
|
||||||
|
size_t connect_attrs_len=
|
||||||
|
(mysql->options.extension) ?
|
||||||
|
mysql->options.extension->connection_attributes_length : 0;
|
||||||
|
|
||||||
|
buf= my_alloca(USERNAME_LENGTH + SCRAMBLE_LENGTH + 1 + 2*NAME_LEN + 2 +
|
||||||
|
connect_attrs_len + 2);
|
||||||
if (mysql->options.client_ip)
|
if (mysql->options.client_ip)
|
||||||
{
|
{
|
||||||
sctx->host= my_strdup(mysql->options.client_ip, MYF(0));
|
sctx->host= my_strdup(mysql->options.client_ip, MYF(0));
|
||||||
@ -766,6 +797,13 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
|
|||||||
int2store(end, (ushort) mysql->charset->number);
|
int2store(end, (ushort) mysql->charset->number);
|
||||||
end+= 2;
|
end+= 2;
|
||||||
|
|
||||||
|
end= strmake(end, "mysql_native_password", NAME_LEN) + 1;
|
||||||
|
|
||||||
|
/* the server does the same as the client */
|
||||||
|
mysql->server_capabilities= mysql->client_flag;
|
||||||
|
|
||||||
|
end= (char *) send_client_connect_attrs(mysql, (uchar *) end);
|
||||||
|
|
||||||
/* acl_authenticate() takes the data from thd->net->read_pos */
|
/* acl_authenticate() takes the data from thd->net->read_pos */
|
||||||
thd->net.read_pos= (uchar*)buf;
|
thd->net.read_pos= (uchar*)buf;
|
||||||
|
|
||||||
@ -774,6 +812,7 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
|
|||||||
my_free(thd->security_ctx->user);
|
my_free(thd->security_ctx->user);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
my_afree(buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -781,6 +820,7 @@ err:
|
|||||||
memcpy(net->sqlstate,
|
memcpy(net->sqlstate,
|
||||||
mysql_errno_to_sqlstate(thd->get_stmt_da()->sql_errno()),
|
mysql_errno_to_sqlstate(thd->get_stmt_da()->sql_errno()),
|
||||||
sizeof(net->sqlstate)-1);
|
sizeof(net->sqlstate)-1);
|
||||||
|
my_afree(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
52
mysql-test/suite/perfschema/r/connect_attrs.result
Normal file
52
mysql-test/suite/perfschema/r/connect_attrs.result
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# must return 0, 6
|
||||||
|
SELECT SUM(ISNULL(ATTR_VALUE)), COUNT(*)
|
||||||
|
FROM performance_schema.session_connect_attrs
|
||||||
|
WHERE ATTR_NAME IN ('_os', '_client_name', '_pid',
|
||||||
|
'_client_version', '_platform', 'program_name')
|
||||||
|
AND PROCESSLIST_ID = CONNECTION_ID();
|
||||||
|
SUM(ISNULL(ATTR_VALUE)) COUNT(*)
|
||||||
|
0 6
|
||||||
|
# must return 1
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_connect_attrs;
|
||||||
|
COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
1
|
||||||
|
# must return 0, 6
|
||||||
|
SELECT SUM(ISNULL(ATTR_VALUE)), COUNT(*)
|
||||||
|
FROM performance_schema.session_account_connect_attrs
|
||||||
|
WHERE ATTR_NAME IN ('_os', '_client_name', '_pid',
|
||||||
|
'_client_version', '_platform', 'program_name')
|
||||||
|
AND PROCESSLIST_ID = CONNECTION_ID();
|
||||||
|
SUM(ISNULL(ATTR_VALUE)) COUNT(*)
|
||||||
|
0 6
|
||||||
|
# must return 1
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_account_connect_attrs;
|
||||||
|
COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
1
|
||||||
|
CREATE USER wl5924@localhost;
|
||||||
|
# must return 1
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_account_connect_attrs;
|
||||||
|
COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
1
|
||||||
|
# must return 2
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_connect_attrs;
|
||||||
|
COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
2
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_account_connect_attrs;
|
||||||
|
ERROR 42000: SELECT command denied to user 'wl5924'@'localhost' for table 'session_account_connect_attrs'
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_connect_attrs;
|
||||||
|
ERROR 42000: SELECT command denied to user 'wl5924'@'localhost' for table 'session_connect_attrs'
|
||||||
|
grant select on performance_schema.* to wl5924@localhost;
|
||||||
|
SELECT SUM(ISNULL(ATTR_VALUE)), COUNT(*)
|
||||||
|
FROM performance_schema.session_account_connect_attrs
|
||||||
|
WHERE ATTR_NAME IN ('_os', '_client_name', '_pid',
|
||||||
|
'_client_version', '_platform', 'program_name')
|
||||||
|
AND PROCESSLIST_ID = CONNECTION_ID();
|
||||||
|
SUM(ISNULL(ATTR_VALUE)) COUNT(*)
|
||||||
|
0 6
|
||||||
|
DROP USER wl5924@localhost;
|
83
mysql-test/suite/perfschema/t/connect_attrs.test
Normal file
83
mysql-test/suite/perfschema/t/connect_attrs.test
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# Session connect attributes test
|
||||||
|
--source include/have_perfschema.inc
|
||||||
|
|
||||||
|
# although the connection attributes transfer code works
|
||||||
|
# with embedded P_S is not active, so the test won't run.
|
||||||
|
# TODO: remove this when P_S works with embedded.
|
||||||
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
|
# make sure we're alone
|
||||||
|
let $count_sessions= 1;
|
||||||
|
--source include/wait_until_count_sessions.inc
|
||||||
|
|
||||||
|
# basic performance_schema.session_connect_attrs tests
|
||||||
|
|
||||||
|
# check the presense of the pre-defined attributes
|
||||||
|
--echo # must return 0, 6
|
||||||
|
SELECT SUM(ISNULL(ATTR_VALUE)), COUNT(*)
|
||||||
|
FROM performance_schema.session_connect_attrs
|
||||||
|
WHERE ATTR_NAME IN ('_os', '_client_name', '_pid',
|
||||||
|
'_client_version', '_platform', 'program_name')
|
||||||
|
AND PROCESSLIST_ID = CONNECTION_ID();
|
||||||
|
|
||||||
|
# check the presense of the pre-defined attributes
|
||||||
|
--echo # must return 1
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_connect_attrs;
|
||||||
|
|
||||||
|
|
||||||
|
# basic performance_schema.session_account_connect_attrs tests
|
||||||
|
|
||||||
|
# check the presense of the pre-defined attributes
|
||||||
|
--echo # must return 0, 6
|
||||||
|
SELECT SUM(ISNULL(ATTR_VALUE)), COUNT(*)
|
||||||
|
FROM performance_schema.session_account_connect_attrs
|
||||||
|
WHERE ATTR_NAME IN ('_os', '_client_name', '_pid',
|
||||||
|
'_client_version', '_platform', 'program_name')
|
||||||
|
AND PROCESSLIST_ID = CONNECTION_ID();
|
||||||
|
|
||||||
|
# check the presense of the pre-defined attributes
|
||||||
|
--echo # must return 1
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_account_connect_attrs;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE USER wl5924@localhost;
|
||||||
|
|
||||||
|
connect(non_privileged_user,localhost,wl5924,,test);
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
--echo # must return 1
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_account_connect_attrs;
|
||||||
|
|
||||||
|
--echo # must return 2
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_connect_attrs;
|
||||||
|
|
||||||
|
connection non_privileged_user;
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_account_connect_attrs;
|
||||||
|
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
SELECT COUNT(DISTINCT PROCESSLIST_ID)
|
||||||
|
FROM performance_schema.session_connect_attrs;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
disconnect non_privileged_user;
|
||||||
|
|
||||||
|
grant select on performance_schema.* to wl5924@localhost;
|
||||||
|
change_user wl5924;
|
||||||
|
SELECT SUM(ISNULL(ATTR_VALUE)), COUNT(*)
|
||||||
|
FROM performance_schema.session_account_connect_attrs
|
||||||
|
WHERE ATTR_NAME IN ('_os', '_client_name', '_pid',
|
||||||
|
'_client_version', '_platform', 'program_name')
|
||||||
|
AND PROCESSLIST_ID = CONNECTION_ID();
|
||||||
|
change_user root,,test;
|
||||||
|
|
||||||
|
DROP USER wl5924@localhost;
|
||||||
|
|
||||||
|
# Wait till all disconnects are completed
|
||||||
|
--source include/wait_until_count_sessions.inc
|
@ -37,6 +37,7 @@
|
|||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
#include <my_default.h>
|
#include <my_default.h>
|
||||||
#include "mysql.h"
|
#include "mysql.h"
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
/* Remove client convenience wrappers */
|
/* Remove client convenience wrappers */
|
||||||
#undef max_allowed_packet
|
#undef max_allowed_packet
|
||||||
@ -1216,17 +1217,30 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EXTENSION_SET(OPTS, X, VAL) \
|
|
||||||
if (!(OPTS)->extension) \
|
#define ALLOCATE_EXTENSIONS(OPTS) \
|
||||||
(OPTS)->extension= (struct st_mysql_options_extention *) \
|
(OPTS)->extension= (struct st_mysql_options_extention *) \
|
||||||
my_malloc(sizeof(struct st_mysql_options_extention), \
|
my_malloc(sizeof(struct st_mysql_options_extention), \
|
||||||
MYF(MY_WME | MY_ZEROFILL)); \
|
MYF(MY_WME | MY_ZEROFILL)) \
|
||||||
(OPTS)->extension->X= (VAL);
|
|
||||||
|
|
||||||
|
#define ENSURE_EXTENSIONS_PRESENT(OPTS) \
|
||||||
|
do { \
|
||||||
|
if (!(OPTS)->extension) \
|
||||||
|
ALLOCATE_EXTENSIONS(OPTS); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#define EXTENSION_SET_STRING(OPTS, X, STR) \
|
#define EXTENSION_SET_STRING(OPTS, X, STR) \
|
||||||
if ((OPTS)->extension) \
|
do { \
|
||||||
my_free((OPTS)->extension->X); \
|
if ((OPTS)->extension) \
|
||||||
EXTENSION_SET(OPTS, X, (STR) ? my_strdup((STR), MYF(MY_WME)) : NULL);
|
my_free((OPTS)->extension->X); \
|
||||||
|
else \
|
||||||
|
ALLOCATE_EXTENSIONS(OPTS); \
|
||||||
|
(OPTS)->extension->X= ((STR) != NULL) ? \
|
||||||
|
my_strdup((STR), MYF(MY_WME)) : NULL; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
|
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
|
||||||
#define SET_SSL_OPTION(OPTS, opt_var, arg) \
|
#define SET_SSL_OPTION(OPTS, opt_var, arg) \
|
||||||
@ -2376,6 +2390,7 @@ static auth_plugin_t old_password_client_plugin=
|
|||||||
old_password_auth_client
|
old_password_auth_client
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct st_mysql_client_plugin *mysql_client_builtins[]=
|
struct st_mysql_client_plugin *mysql_client_builtins[]=
|
||||||
{
|
{
|
||||||
(struct st_mysql_client_plugin *)&native_password_client_plugin,
|
(struct st_mysql_client_plugin *)&native_password_client_plugin,
|
||||||
@ -2383,6 +2398,67 @@ struct st_mysql_client_plugin *mysql_client_builtins[]=
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static uchar *
|
||||||
|
write_length_encoded_string3(uchar *buf, char *string, size_t length)
|
||||||
|
{
|
||||||
|
buf= net_store_length(buf, length);
|
||||||
|
memcpy(buf, string, length);
|
||||||
|
buf+= length;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uchar *
|
||||||
|
send_client_connect_attrs(MYSQL *mysql, uchar *buf)
|
||||||
|
{
|
||||||
|
/* check if the server supports connection attributes */
|
||||||
|
if (mysql->server_capabilities & CLIENT_CONNECT_ATTRS)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Always store the length if the client supports it */
|
||||||
|
buf= net_store_length(buf,
|
||||||
|
mysql->options.extension ?
|
||||||
|
mysql->options.extension->connection_attributes_length :
|
||||||
|
0);
|
||||||
|
|
||||||
|
/* check if we have connection attributes */
|
||||||
|
if (mysql->options.extension &&
|
||||||
|
my_hash_inited(&mysql->options.extension->connection_attributes))
|
||||||
|
{
|
||||||
|
HASH *attrs= &mysql->options.extension->connection_attributes;
|
||||||
|
ulong idx;
|
||||||
|
|
||||||
|
/* loop over and dump the connection attributes */
|
||||||
|
for (idx= 0; idx < attrs->records; idx++)
|
||||||
|
{
|
||||||
|
LEX_STRING *attr= (LEX_STRING *) my_hash_element(attrs, idx);
|
||||||
|
LEX_STRING *key= attr, *value= attr + 1;
|
||||||
|
|
||||||
|
/* we can't have zero length keys */
|
||||||
|
DBUG_ASSERT(key->length);
|
||||||
|
|
||||||
|
buf= write_length_encoded_string3(buf, key->str, key->length);
|
||||||
|
buf= write_length_encoded_string3(buf, value->str, value->length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t get_length_store_length(size_t length)
|
||||||
|
{
|
||||||
|
/* as defined in net_store_length */
|
||||||
|
#define MAX_VARIABLE_STRING_LENGTH 9
|
||||||
|
uchar length_buffer[MAX_VARIABLE_STRING_LENGTH], *ptr;
|
||||||
|
|
||||||
|
ptr= net_store_length(length_buffer, length);
|
||||||
|
|
||||||
|
return ptr - &length_buffer[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* this is a "superset" of MYSQL_PLUGIN_VIO, in C++ I use inheritance */
|
/* this is a "superset" of MYSQL_PLUGIN_VIO, in C++ I use inheritance */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
|
int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
|
||||||
@ -2426,8 +2502,13 @@ static int send_change_user_packet(MCPVIO_EXT *mpvio,
|
|||||||
MYSQL *mysql= mpvio->mysql;
|
MYSQL *mysql= mpvio->mysql;
|
||||||
char *buff, *end;
|
char *buff, *end;
|
||||||
int res= 1;
|
int res= 1;
|
||||||
|
size_t connect_attrs_len=
|
||||||
|
(mysql->server_capabilities & CLIENT_CONNECT_ATTRS &&
|
||||||
|
mysql->options.extension) ?
|
||||||
|
mysql->options.extension->connection_attributes_length : 0;
|
||||||
|
|
||||||
buff= my_alloca(USERNAME_LENGTH+1 + data_len+1 + NAME_LEN+1 + 2 + NAME_LEN+1);
|
buff= my_alloca(USERNAME_LENGTH + data_len + 1 + NAME_LEN + 2 + NAME_LEN +
|
||||||
|
connect_attrs_len + 9 /* for the length of the attrs */);
|
||||||
|
|
||||||
end= strmake(buff, mysql->user, USERNAME_LENGTH) + 1;
|
end= strmake(buff, mysql->user, USERNAME_LENGTH) + 1;
|
||||||
|
|
||||||
@ -2464,6 +2545,8 @@ static int send_change_user_packet(MCPVIO_EXT *mpvio,
|
|||||||
if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
|
if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
|
||||||
end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
|
end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
|
||||||
|
|
||||||
|
end= (char *) send_client_connect_attrs(mysql, (uchar *) end);
|
||||||
|
|
||||||
res= simple_command(mysql, COM_CHANGE_USER,
|
res= simple_command(mysql, COM_CHANGE_USER,
|
||||||
(uchar*)buff, (ulong)(end-buff), 1);
|
(uchar*)buff, (ulong)(end-buff), 1);
|
||||||
|
|
||||||
@ -2472,6 +2555,7 @@ error:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_CONNECTION_ATTR_STORAGE_LENGTH 65536
|
||||||
|
|
||||||
/**
|
/**
|
||||||
sends a client authentication packet (second packet in the 3-way handshake)
|
sends a client authentication packet (second packet in the 3-way handshake)
|
||||||
@ -2509,10 +2593,21 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
|||||||
MYSQL *mysql= mpvio->mysql;
|
MYSQL *mysql= mpvio->mysql;
|
||||||
NET *net= &mysql->net;
|
NET *net= &mysql->net;
|
||||||
char *buff, *end;
|
char *buff, *end;
|
||||||
|
size_t buff_size;
|
||||||
|
size_t connect_attrs_len=
|
||||||
|
(mysql->server_capabilities & CLIENT_CONNECT_ATTRS &&
|
||||||
|
mysql->options.extension) ?
|
||||||
|
mysql->options.extension->connection_attributes_length : 0;
|
||||||
|
|
||||||
|
DBUG_ASSERT(connect_attrs_len < MAX_CONNECTION_ATTR_STORAGE_LENGTH);
|
||||||
|
|
||||||
|
/*
|
||||||
|
see end= buff+32 below, fixed size of the packet is 32 bytes.
|
||||||
|
+9 because data is a length encoded binary where meta data size is max 9.
|
||||||
|
*/
|
||||||
|
buff_size= 33 + USERNAME_LENGTH + data_len + 9 + NAME_LEN + NAME_LEN + connect_attrs_len + 9;
|
||||||
|
buff= my_alloca(buff_size);
|
||||||
|
|
||||||
/* see end= buff+32 below, fixed size of the packet is 32 bytes */
|
|
||||||
buff= my_alloca(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN);
|
|
||||||
|
|
||||||
mysql->client_flag|= mysql->options.client_flag;
|
mysql->client_flag|= mysql->options.client_flag;
|
||||||
mysql->client_flag|= CLIENT_CAPABILITIES;
|
mysql->client_flag|= CLIENT_CAPABILITIES;
|
||||||
|
|
||||||
@ -2665,6 +2760,8 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
|||||||
if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
|
if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
|
||||||
end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
|
end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
|
||||||
|
|
||||||
|
end= (char *) send_client_connect_attrs(mysql, (uchar *) end);
|
||||||
|
|
||||||
/* Write authentication package */
|
/* Write authentication package */
|
||||||
if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
|
if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
|
||||||
{
|
{
|
||||||
@ -3024,6 +3121,51 @@ connect_sync_or_async(MYSQL *mysql, NET *net, my_socket fd,
|
|||||||
return my_connect(fd, name, namelen, mysql->options.connect_timeout);
|
return my_connect(fd, name, namelen, mysql->options.connect_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** set some default attributes */
|
||||||
|
static int
|
||||||
|
set_connect_attributes(MYSQL *mysql, char *buff, size_t buf_len)
|
||||||
|
{
|
||||||
|
int rc= 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Clean up any values set by the client code. We want these options as
|
||||||
|
consistent as possible
|
||||||
|
*/
|
||||||
|
rc+= mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_client_name");
|
||||||
|
rc+= mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_os");
|
||||||
|
rc+= mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_platform");
|
||||||
|
rc+= mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_pid");
|
||||||
|
rc+= mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_thread");
|
||||||
|
rc+= mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_client_version");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Now let's set up some values
|
||||||
|
*/
|
||||||
|
rc+= mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"_client_name", "libmysql");
|
||||||
|
rc+= mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"_client_version", PACKAGE_VERSION);
|
||||||
|
rc+= mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"_os", SYSTEM_TYPE);
|
||||||
|
rc+= mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||||
|
"_platform", MACHINE_TYPE);
|
||||||
|
#ifdef __WIN__
|
||||||
|
snprintf(buff, buf_len, "%lu", (ulong) GetCurrentProcessId());
|
||||||
|
#else
|
||||||
|
snprintf(buff, buf_len, "%lu", (ulong) getpid());
|
||||||
|
#endif
|
||||||
|
rc+= mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_pid", buff);
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
snprintf(buff, buf_len, "%lu", (ulong) GetCurrentThreadId());
|
||||||
|
rc+= mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_thread", buff);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rc > 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MYSQL * STDCALL
|
MYSQL * STDCALL
|
||||||
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
||||||
const char *passwd, const char *db,
|
const char *passwd, const char *db,
|
||||||
@ -3057,6 +3199,9 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (set_connect_attributes(mysql, buff, sizeof(buff)))
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
mysql->methods= &client_methods;
|
mysql->methods= &client_methods;
|
||||||
net->vio = 0; /* If something goes wrong */
|
net->vio = 0; /* If something goes wrong */
|
||||||
mysql->client_flag=0; /* For handshake */
|
mysql->client_flag=0; /* For handshake */
|
||||||
@ -3757,6 +3902,7 @@ static void mysql_close_free_options(MYSQL *mysql)
|
|||||||
struct mysql_async_context *ctxt= mysql->options.extension->async_context;
|
struct mysql_async_context *ctxt= mysql->options.extension->async_context;
|
||||||
my_free(mysql->options.extension->plugin_dir);
|
my_free(mysql->options.extension->plugin_dir);
|
||||||
my_free(mysql->options.extension->default_auth);
|
my_free(mysql->options.extension->default_auth);
|
||||||
|
my_hash_free(&mysql->options.extension->connection_attributes);
|
||||||
if (ctxt)
|
if (ctxt)
|
||||||
{
|
{
|
||||||
my_context_destroy(&ctxt->async_context);
|
my_context_destroy(&ctxt->async_context);
|
||||||
@ -4320,7 +4466,8 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
|
|||||||
my_free(ctxt);
|
my_free(ctxt);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
EXTENSION_SET(&(mysql->options), async_context, ctxt)
|
ENSURE_EXTENSIONS_PRESENT(&(mysql->options));
|
||||||
|
mysql->options.extension->async_context= ctxt;
|
||||||
if (mysql->net.vio)
|
if (mysql->net.vio)
|
||||||
mysql->net.vio->async_context= ctxt;
|
mysql->net.vio->async_context= ctxt;
|
||||||
break;
|
break;
|
||||||
@ -4345,6 +4492,145 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
|
|||||||
case MYSQL_OPT_SSL_CRLPATH:
|
case MYSQL_OPT_SSL_CRLPATH:
|
||||||
EXTENSION_SET_SSL_STRING(&mysql->options, ssl_crlpath, arg);
|
EXTENSION_SET_SSL_STRING(&mysql->options, ssl_crlpath, arg);
|
||||||
break;
|
break;
|
||||||
|
case MYSQL_OPT_CONNECT_ATTR_RESET:
|
||||||
|
ENSURE_EXTENSIONS_PRESENT(&mysql->options);
|
||||||
|
if (my_hash_inited(&mysql->options.extension->connection_attributes))
|
||||||
|
{
|
||||||
|
my_hash_free(&mysql->options.extension->connection_attributes);
|
||||||
|
mysql->options.extension->connection_attributes_length= 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MYSQL_OPT_CONNECT_ATTR_DELETE:
|
||||||
|
ENSURE_EXTENSIONS_PRESENT(&mysql->options);
|
||||||
|
if (my_hash_inited(&mysql->options.extension->connection_attributes))
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uchar *elt;
|
||||||
|
|
||||||
|
len= arg ? strlen(arg) : 0;
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
elt= my_hash_search(&mysql->options.extension->connection_attributes,
|
||||||
|
arg, len);
|
||||||
|
if (elt)
|
||||||
|
{
|
||||||
|
LEX_STRING *attr= (LEX_STRING *) elt;
|
||||||
|
LEX_STRING *key= attr, *value= attr + 1;
|
||||||
|
|
||||||
|
mysql->options.extension->connection_attributes_length-=
|
||||||
|
get_length_store_length(key->length) + key->length +
|
||||||
|
get_length_store_length(value->length) + value->length;
|
||||||
|
|
||||||
|
my_hash_delete(&mysql->options.extension->connection_attributes,
|
||||||
|
elt);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
A function to return the key from a connection attribute
|
||||||
|
*/
|
||||||
|
uchar *
|
||||||
|
get_attr_key(LEX_STRING *part, size_t *length,
|
||||||
|
my_bool not_used __attribute__((unused)))
|
||||||
|
{
|
||||||
|
*length= part[0].length;
|
||||||
|
return (uchar *) part[0].str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int STDCALL
|
||||||
|
mysql_options4(MYSQL *mysql,enum mysql_option option,
|
||||||
|
const void *arg1, const void *arg2)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("mysql_option");
|
||||||
|
DBUG_PRINT("enter",("option: %d",(int) option));
|
||||||
|
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case MYSQL_OPT_CONNECT_ATTR_ADD:
|
||||||
|
{
|
||||||
|
LEX_STRING *elt;
|
||||||
|
char *key, *value;
|
||||||
|
size_t key_len= arg1 ? strlen(arg1) : 0,
|
||||||
|
value_len= arg2 ? strlen(arg2) : 0;
|
||||||
|
size_t attr_storage_length= key_len + value_len;
|
||||||
|
|
||||||
|
/* we can't have a zero length key */
|
||||||
|
if (!key_len)
|
||||||
|
{
|
||||||
|
set_mysql_error(mysql, CR_INVALID_PARAMETER_NO, unknown_sqlstate);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate the total storage length of the attribute */
|
||||||
|
attr_storage_length+= get_length_store_length(key_len);
|
||||||
|
attr_storage_length+= get_length_store_length(value_len);
|
||||||
|
|
||||||
|
ENSURE_EXTENSIONS_PRESENT(&mysql->options);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Throw and error if the maximum combined length of the attribute value
|
||||||
|
will be greater than the maximum that we can safely transmit.
|
||||||
|
*/
|
||||||
|
if (attr_storage_length +
|
||||||
|
mysql->options.extension->connection_attributes_length >
|
||||||
|
MAX_CONNECTION_ATTR_STORAGE_LENGTH)
|
||||||
|
{
|
||||||
|
set_mysql_error(mysql, CR_INVALID_PARAMETER_NO, unknown_sqlstate);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!my_hash_inited(&mysql->options.extension->connection_attributes))
|
||||||
|
{
|
||||||
|
if (my_hash_init(&mysql->options.extension->connection_attributes,
|
||||||
|
&my_charset_bin, 0, 0, 0, (my_hash_get_key) get_attr_key,
|
||||||
|
my_free, HASH_UNIQUE))
|
||||||
|
{
|
||||||
|
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!my_multi_malloc(MY_WME,
|
||||||
|
&elt, 2 * sizeof(LEX_STRING),
|
||||||
|
&key, key_len + 1,
|
||||||
|
&value, value_len + 1,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
elt[0].str= key; elt[0].length= key_len;
|
||||||
|
elt[1].str= value; elt[1].length= value_len;
|
||||||
|
if (key_len)
|
||||||
|
memcpy(key, arg1, key_len);
|
||||||
|
key[key_len]= 0;
|
||||||
|
if (value_len)
|
||||||
|
memcpy(value, arg2, value_len);
|
||||||
|
value[value_len]= 0;
|
||||||
|
if (my_hash_insert(&mysql->options.extension->connection_attributes,
|
||||||
|
(uchar *) elt))
|
||||||
|
{
|
||||||
|
/* can't insert the value */
|
||||||
|
my_free(elt);
|
||||||
|
set_mysql_error(mysql, CR_DUPLICATE_CONNECTION_ATTR,
|
||||||
|
unknown_sqlstate);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql->options.extension->connection_attributes_length+=
|
||||||
|
attr_storage_length;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,11 @@
|
|||||||
*/
|
*/
|
||||||
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \
|
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \
|
||||||
CLIENT_LONG_FLAG | \
|
CLIENT_LONG_FLAG | \
|
||||||
CLIENT_SECURE_CONNECTION | \
|
|
||||||
CLIENT_TRANSACTIONS | \
|
CLIENT_TRANSACTIONS | \
|
||||||
CLIENT_PROTOCOL_41 | \
|
CLIENT_PROTOCOL_41 | \
|
||||||
CLIENT_SECURE_CONNECTION | \
|
CLIENT_SECURE_CONNECTION | \
|
||||||
CLIENT_PLUGIN_AUTH)
|
CLIENT_PLUGIN_AUTH | \
|
||||||
|
CLIENT_CONNECT_ATTRS)
|
||||||
|
|
||||||
#define read_user_name(A) {}
|
#define read_user_name(A) {}
|
||||||
#undef _CUSTOMCONFIG_
|
#undef _CUSTOMCONFIG_
|
||||||
|
@ -8217,6 +8217,56 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio)
|
|||||||
mpvio->acl_user->plugin.str));
|
mpvio->acl_user->plugin.str));
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
read_client_connect_attrs(char **ptr, char *end,
|
||||||
|
const CHARSET_INFO *from_cs)
|
||||||
|
{
|
||||||
|
size_t length, length_length;
|
||||||
|
size_t max_bytes_available= end - *ptr;
|
||||||
|
/* not enough bytes to hold the length */
|
||||||
|
if ((*ptr) >= (end - 1))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* read the length */
|
||||||
|
if (max_bytes_available >= 9)
|
||||||
|
{
|
||||||
|
char *ptr_save= *ptr;
|
||||||
|
length= net_field_length_ll((uchar **) ptr);
|
||||||
|
length_length= *ptr - ptr_save;
|
||||||
|
DBUG_ASSERT(length_length <= 9);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* to avoid reading unallocated and uninitialized memory */
|
||||||
|
char buf[10]={'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',},
|
||||||
|
*len_ptr= buf;
|
||||||
|
memcpy(buf, *ptr, max_bytes_available);
|
||||||
|
length= net_field_length_ll((uchar **) &len_ptr);
|
||||||
|
length_length= len_ptr - buf;
|
||||||
|
*ptr+= length_length;
|
||||||
|
if (max_bytes_available < length_length)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
max_bytes_available-= length_length;
|
||||||
|
|
||||||
|
/* length says there're more data than can fit into the packet */
|
||||||
|
if (length > max_bytes_available)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* impose an artificial length limit of 64k */
|
||||||
|
if (length > 65535)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#ifdef HAVE_PSI_THREAD_INTERFACE
|
||||||
|
if (PSI_THREAD_CALL(set_thread_connect_attrs)(*ptr, length, from_cs) &&
|
||||||
|
current_thd->variables.log_warnings)
|
||||||
|
sql_print_warning("Connection attributes of length %lu were truncated",
|
||||||
|
(unsigned long) length);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* the packet format is described in send_change_user_packet() */
|
/* the packet format is described in send_change_user_packet() */
|
||||||
@ -8269,13 +8319,14 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
|
|||||||
|
|
||||||
uint db_len= strlen(db);
|
uint db_len= strlen(db);
|
||||||
|
|
||||||
char *ptr= db + db_len + 1;
|
char *next_field= db + db_len + 1;
|
||||||
|
|
||||||
if (ptr + 1 < end)
|
if (next_field + 1 < end)
|
||||||
{
|
{
|
||||||
if (thd_init_client_charset(thd, uint2korr(ptr)))
|
if (thd_init_client_charset(thd, uint2korr(next_field)))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
thd->update_charset();
|
thd->update_charset();
|
||||||
|
next_field+= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert database and user names to utf8 */
|
/* Convert database and user names to utf8 */
|
||||||
@ -8318,13 +8369,13 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
|
|||||||
char *client_plugin;
|
char *client_plugin;
|
||||||
if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
|
if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
|
||||||
{
|
{
|
||||||
client_plugin= ptr + 2;
|
if (next_field >= end)
|
||||||
if (client_plugin >= end)
|
|
||||||
{
|
{
|
||||||
my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
|
my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
client_plugin= fix_plugin_ptr(client_plugin);
|
client_plugin= fix_plugin_ptr(next_field);
|
||||||
|
next_field+= strlen(next_field) + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -8344,6 +8395,11 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mpvio->thd->client_capabilities & CLIENT_CONNECT_ATTRS) &&
|
||||||
|
read_client_connect_attrs(&next_field, end,
|
||||||
|
mpvio->thd->charset()))
|
||||||
|
return packet_error;
|
||||||
|
|
||||||
DBUG_PRINT("info", ("client_plugin=%s, restart", client_plugin));
|
DBUG_PRINT("info", ("client_plugin=%s, restart", client_plugin));
|
||||||
/*
|
/*
|
||||||
Remember the data part of the packet, to present it to plugin in
|
Remember the data part of the packet, to present it to plugin in
|
||||||
@ -8482,7 +8538,8 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
|
|||||||
/* strlen() can't be easily deleted without changing protocol */
|
/* strlen() can't be easily deleted without changing protocol */
|
||||||
db_len= db ? strlen(db) : 0;
|
db_len= db ? strlen(db) : 0;
|
||||||
|
|
||||||
char *client_plugin= passwd + passwd_len + (db ? db_len + 1 : 0);
|
char *next_field;
|
||||||
|
char *client_plugin= next_field= passwd + passwd_len + (db ? db_len + 1 : 0);
|
||||||
|
|
||||||
/* Since 4.1 all database names are stored in utf8 */
|
/* Since 4.1 all database names are stored in utf8 */
|
||||||
if (db)
|
if (db)
|
||||||
@ -8549,6 +8606,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
|
|||||||
(client_plugin < (char *)net->read_pos + pkt_len))
|
(client_plugin < (char *)net->read_pos + pkt_len))
|
||||||
{
|
{
|
||||||
client_plugin= fix_plugin_ptr(client_plugin);
|
client_plugin= fix_plugin_ptr(client_plugin);
|
||||||
|
next_field+= strlen(next_field) + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -8570,7 +8628,12 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
|
|||||||
mpvio->acl_user->plugin= old_password_plugin_name;
|
mpvio->acl_user->plugin= old_password_plugin_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) &&
|
||||||
|
read_client_connect_attrs(&next_field, ((char *)net->read_pos) + pkt_len,
|
||||||
|
mpvio->thd->charset()))
|
||||||
|
return packet_error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if the acl_user needs a different plugin to authenticate
|
if the acl_user needs a different plugin to authenticate
|
||||||
(specified in GRANT ... AUTHENTICATED VIA plugin_name ..)
|
(specified in GRANT ... AUTHENTICATED VIA plugin_name ..)
|
||||||
|
@ -54,6 +54,9 @@
|
|||||||
#ifndef PFS_STATEMENTS_STACK_SIZE
|
#ifndef PFS_STATEMENTS_STACK_SIZE
|
||||||
#define PFS_STATEMENTS_STACK_SIZE 10
|
#define PFS_STATEMENTS_STACK_SIZE 10
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef PFS_CONNECT_ATTRS_SIZE
|
||||||
|
#define PFS_SESSION_CONNECT_ATTRS_SIZE 2048
|
||||||
|
#endif
|
||||||
|
|
||||||
struct PFS_sizing_hints
|
struct PFS_sizing_hints
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user