1
0
mirror of https://github.com/MariaDB/server.git synced 2026-01-06 05:22:24 +03:00

5.5-merge

This commit is contained in:
Sergei Golubchik
2011-07-02 22:08:51 +02:00
3220 changed files with 94894 additions and 422456 deletions

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2000-2003 MySQL AB
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,7 +24,6 @@
mysql_real_connect()
- Support for reading local file with LOAD DATA LOCAL
- SHARED memory handling
- Protection against sigpipe
- Prepared statements
- Things that only works for the server
@@ -70,9 +69,9 @@ my_bool net_flush(NET *net);
#include "mysqld_error.h"
#include "errmsg.h"
#include <violite.h>
#if defined(THREAD) && !defined(__WIN__)
#if !defined(__WIN__)
#include <my_pthread.h> /* because of signal() */
#endif /* defined(THREAD) && !defined(__WIN__) */
#endif /* !defined(__WIN__) */
#include <sys/stat.h>
#include <signal.h>
@@ -287,7 +286,7 @@ static int wait_for_data(my_socket fd, uint timeout)
{
tv.tv_sec = (long) timeout;
tv.tv_usec = 0;
#if defined(HPUX10) && defined(THREAD)
#if defined(HPUX10)
if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
break;
#else
@@ -731,13 +730,9 @@ cli_safe_read(MYSQL *mysql)
{
NET *net= &mysql->net;
ulong len=0;
init_sigpipe_variables
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
if (net->vio != 0)
len=my_net_read(net);
reset_sigpipe(mysql);
if (len == packet_error || len == 0)
{
@@ -817,13 +812,9 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
{
NET *net= &mysql->net;
my_bool result= 1;
init_sigpipe_variables
my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE;
DBUG_ENTER("cli_advanced_command");
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
if (mysql->net.vio == 0)
{ /* Do reconnect if possible */
if (mysql_reconnect(mysql) || stmt_skip)
@@ -872,7 +863,6 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
result= ((mysql->packet_length=cli_safe_read(mysql)) == packet_error ?
1 : 0);
end:
reset_sigpipe(mysql);
DBUG_PRINT("exit",("result: %d", result));
DBUG_RETURN(result);
}
@@ -1089,14 +1079,11 @@ void end_server(MYSQL *mysql)
DBUG_ENTER("end_server");
if (mysql->net.vio != 0)
{
init_sigpipe_variables
DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio)));
#ifdef MYSQL_SERVER
slave_io_thread_detach_vio();
#endif
set_sigpipe(mysql);
vio_delete(mysql->net.vio);
reset_sigpipe(mysql);
mysql->net.vio= 0; /* Marker */
mysql_prune_stmt_list(mysql);
}
@@ -1161,6 +1148,7 @@ enum option_id {
OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name,
OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth,
OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth,
OPT_keep_this_one_last
};
static TYPELIB option_types={array_elements(default_options)-1,
@@ -1192,7 +1180,7 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd)
return 0;
}
#define extension_set_string(OPTS, X, STR) \
#define EXTENSION_SET_STRING(OPTS, X, STR) \
if ((OPTS)->extension) \
my_free((OPTS)->extension->X); \
else \
@@ -1210,6 +1198,9 @@ void mysql_read_default_options(struct st_mysql_options *options,
DBUG_ENTER("mysql_read_default_options");
DBUG_PRINT("enter",("file: %s group: %s",filename,group ? group :"NULL"));
compile_time_assert(OPT_keep_this_one_last ==
array_elements(default_options));
argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
@@ -1219,7 +1210,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
char **option=argv;
while (*++option)
{
if (option[0] == args_separator) /* skip arguments separator */
if (my_getopt_is_args_separator(option[0])) /* skip arguments separator */
continue;
/* DBUG_PRINT("info",("option: %s",option[0])); */
if (option[0][0] == '-' && option[0][1] == '-')
@@ -1234,7 +1225,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
/* Change all '_' in variable name to '-' */
for (end= *option ; *(end= strcend(end,'_')) ; )
*end= '-';
switch (find_type(*option+2,&option_types,2)) {
switch (find_type(*option + 2, &option_types, FIND_TYPE_BASIC)) {
case OPT_port:
if (opt_arg)
options->port=atoi(opt_arg);
@@ -1250,7 +1241,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
options->compress=1;
options->client_flag|= CLIENT_COMPRESS;
break;
case OPT_password:
case OPT_password:
if (opt_arg)
{
my_free(options->password);
@@ -1296,7 +1287,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_return_found_rows:
options->client_flag|=CLIENT_FOUND_ROWS;
break;
#ifdef HAVE_OPENSSL
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
case OPT_ssl_key:
my_free(options->ssl_key);
options->ssl_key = my_strdup(opt_arg, MYF(MY_WME));
@@ -1324,8 +1315,8 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_ssl_capath:
case OPT_ssl_cipher:
break;
#endif /* HAVE_OPENSSL */
case OPT_character_sets_dir:
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
case OPT_character_sets_dir:
my_free(options->charset_dir);
options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
break;
@@ -1350,8 +1341,8 @@ void mysql_read_default_options(struct st_mysql_options *options,
options->max_allowed_packet= atoi(opt_arg);
break;
case OPT_protocol:
if ((options->protocol= find_type(opt_arg,
&sql_protocol_typelib,0)) <= 0)
if ((options->protocol= find_type(opt_arg, &sql_protocol_typelib,
FIND_TYPE_BASIC)) <= 0)
{
fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
exit(1);
@@ -1378,10 +1369,22 @@ void mysql_read_default_options(struct st_mysql_options *options,
options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
break;
case OPT_plugin_dir:
extension_set_string(options, plugin_dir, opt_arg);
{
char buff[FN_REFLEN], buff2[FN_REFLEN];
if (strlen(opt_arg) >= FN_REFLEN)
opt_arg[FN_REFLEN]= '\0';
if (my_realpath(buff, opt_arg, 0))
{
DBUG_PRINT("warning",("failed to normalize the plugin path: %s",
opt_arg));
break;
}
convert_dirname(buff, buff2, NULL);
EXTENSION_SET_STRING(options, plugin_dir, buff2);
}
break;
case OPT_default_auth:
extension_set_string(options, default_auth, opt_arg);
EXTENSION_SET_STRING(options, default_auth, opt_arg);
break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
@@ -1842,6 +1845,8 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
ssl_verify_server_cert()
vio pointer to a SSL connected vio
server_hostname name of the server that we connected to
errptr if we fail, we'll return (a pointer to a string
describing) the reason here
RETURN VALUES
0 Success
@@ -1851,7 +1856,7 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const char **errptr)
{
SSL *ssl;
X509 *server_cert;
@@ -1862,19 +1867,19 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
if (!(ssl= (SSL*)vio->ssl_arg))
{
DBUG_PRINT("error", ("No SSL pointer found"));
*errptr= "No SSL pointer found";
DBUG_RETURN(1);
}
if (!server_hostname)
{
DBUG_PRINT("error", ("No server hostname supplied"));
*errptr= "No server hostname supplied";
DBUG_RETURN(1);
}
if (!(server_cert= SSL_get_peer_certificate(ssl)))
{
DBUG_PRINT("error", ("Could not get server certificate"));
*errptr= "Could not get server certificate";
DBUG_RETURN(1);
}
@@ -1903,7 +1908,7 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
DBUG_RETURN(0);
}
}
DBUG_PRINT("error", ("SSL certificate validation failure"));
*errptr= "SSL certificate validation failure";
DBUG_RETURN(1);
}
@@ -2266,6 +2271,7 @@ typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, int);
static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
static int clear_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
static auth_plugin_t native_password_client_plugin=
{
@@ -2275,6 +2281,9 @@ static auth_plugin_t native_password_client_plugin=
"R.J.Silk, Sergei Golubchik",
"Native MySQL authentication",
{1, 0, 0},
"GPL",
NULL,
NULL,
NULL,
NULL,
native_password_auth_client
@@ -2288,15 +2297,42 @@ static auth_plugin_t old_password_client_plugin=
"R.J.Silk, Sergei Golubchik",
"Old MySQL-3.23 authentication",
{1, 0, 0},
"GPL",
NULL,
NULL,
NULL,
NULL,
old_password_auth_client
};
static auth_plugin_t clear_password_client_plugin=
{
MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
"mysql_clear_password",
"Georgi Kodinov",
"Clear password authentication plugin",
{0,1,0},
"GPL",
NULL,
NULL,
NULL,
NULL,
clear_password_auth_client
};
#ifdef AUTHENTICATION_WIN
extern auth_plugin_t win_auth_client_plugin;
#endif
struct st_mysql_client_plugin *mysql_client_builtins[]=
{
(struct st_mysql_client_plugin *)&native_password_client_plugin,
(struct st_mysql_client_plugin *)&old_password_client_plugin,
(struct st_mysql_client_plugin *)&clear_password_client_plugin,
#ifdef AUTHENTICATION_WIN
(struct st_mysql_client_plugin *)&win_auth_client_plugin,
#endif
0
};
@@ -2309,15 +2345,15 @@ typedef struct {
void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
/* -= end of MYSQL_PLUGIN_VIO =- */
MYSQL *mysql;
auth_plugin_t *plugin; /**< what plugin we're under */
auth_plugin_t *plugin; /**< what plugin we're under */
const char *db;
struct {
uchar *pkt; /**< pointer into NET::buff */
uchar *pkt; /**< pointer into NET::buff */
uint pkt_len;
} cached_server_reply;
uint packets_read, packets_written; /**< counters for send/received packets */
my_bool mysql_change_user; /**< if it's mysql_change_user() */
int last_read_packet_len; /**< the length of the last *read* packet */
int packets_read, packets_written; /**< counters for send/received packets */
int mysql_change_user; /**< if it's mysql_change_user() */
int last_read_packet_len; /**< the length of the last *read* packet */
} MCPVIO_EXT;
/**
@@ -2339,7 +2375,6 @@ typedef struct {
@retval 0 ok
@retval 1 error
*/
static int send_change_user_packet(MCPVIO_EXT *mpvio,
const uchar *data, int data_len)
{
@@ -2423,7 +2458,6 @@ error:
@retval 0 ok
@retval 1 error
*/
static int send_client_reply_packet(MCPVIO_EXT *mpvio,
const uchar *data, int data_len)
{
@@ -2481,7 +2515,9 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
/* Do the SSL layering. */
struct st_mysql_options *options= &mysql->options;
struct st_VioSSLFd *ssl_fd;
char error_string[1024];
enum enum_ssl_init_error ssl_init_error;
const char *cert_error;
unsigned long ssl_error;
/*
Send mysql->client_flag, max_packet_size - unencrypted otherwise
@@ -2501,32 +2537,36 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
options->ssl_cert,
options->ssl_ca,
options->ssl_capath,
options->ssl_cipher)))
options->ssl_cipher,
&ssl_init_error)))
{
set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
ER(CR_SSL_CONNECTION_ERROR), sslGetErrString(ssl_init_error));
goto error;
}
mysql->connector_fd= (void*)ssl_fd;
mysql->connector_fd= (unsigned char *) ssl_fd;
/* Connect to the server */
DBUG_PRINT("info", ("IO layer change in progress..."));
if (sslconnect(ssl_fd, net->vio,
(long) (mysql->options.connect_timeout),
error_string))
{
set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR,
unknown_sqlstate, "SSL error: %s",
error_string[0] ? error_string :
ER(CR_SSL_CONNECTION_ERROR));
(long) (mysql->options.connect_timeout), &ssl_error))
{
char buf[512];
ERR_error_string_n(ssl_error, buf, 512);
buf[511]= 0;
set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
ER(CR_SSL_CONNECTION_ERROR),
buf);
goto error;
}
DBUG_PRINT("info", ("IO layer change done!"));
/* Verify server cert */
if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
ssl_verify_server_cert(net->vio, mysql->host))
ssl_verify_server_cert(net->vio, mysql->host, &cert_error))
{
set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
ER(CR_SSL_CONNECTION_ERROR), cert_error);
goto error;
}
}
@@ -2599,7 +2639,6 @@ error:
This function is called by a client authentication plugin, when it wants
to read data from the server.
*/
static int client_mpvio_read_packet(struct st_plugin_vio *mpv, uchar **buf)
{
MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
@@ -2662,7 +2701,6 @@ static int client_mpvio_read_packet(struct st_plugin_vio *mpv, uchar **buf)
It transparently wraps the data into a change user or authentication
handshake packet, if neccessary.
*/
static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
const uchar *pkt, int pkt_len)
{
@@ -2698,7 +2736,6 @@ static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
fills MYSQL_PLUGIN_VIO_INFO structure with the information about the
connection
*/
void mpvio_info(Vio *vio, MYSQL_PLUGIN_VIO_INFO *info)
{
bzero(info, sizeof(*info));
@@ -2729,7 +2766,9 @@ void mpvio_info(Vio *vio, MYSQL_PLUGIN_VIO_INFO *info)
return;
case VIO_TYPE_SHARED_MEMORY:
info->protocol= MYSQL_VIO_MEMORY;
#ifdef HAVE_SMEM
info->handle= vio->handle_file_map; /* or what ? */
#endif
return;
#endif
default: DBUG_ASSERT(0);
@@ -2761,7 +2800,6 @@ static void client_mpvio_info(MYSQL_PLUGIN_VIO *vio,
@retval 0 ok
@retval 1 error
*/
int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
const char *data_plugin, const char *db)
{
@@ -2771,6 +2809,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
ulong pkt_length;
int res;
DBUG_ENTER ("run_plugin_auth");
/* determine the default/initial plugin to use */
if (mysql->options.extension && mysql->options.extension->default_auth &&
mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
@@ -2778,7 +2817,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
auth_plugin_name= mysql->options.extension->default_auth;
if (!(auth_plugin= (auth_plugin_t*) mysql_client_find_plugin(mysql,
auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
return 1; /* oops, not found */
DBUG_RETURN (1); /* oops, not found */
}
else
{
@@ -2787,6 +2826,8 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
auth_plugin_name= auth_plugin->name;
}
DBUG_PRINT ("info", ("using plugin %s", auth_plugin_name));
mysql->net.last_errno= 0; /* just in case */
if (data_plugin && strcmp(data_plugin, auth_plugin_name))
@@ -2808,6 +2849,11 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
mpvio.plugin= auth_plugin;
res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
DBUG_PRINT ("info", ("authenticate_user returned %s",
res == CR_OK ? "CR_OK" :
res == CR_ERROR ? "CR_ERROR" :
res == CR_OK_HANDSHAKE_COMPLETE ?
"CR_OK_HANDSHAKE_COMPLETE" : "error"));
compile_time_assert(CR_OK == -1);
compile_time_assert(CR_ERROR == 0);
@@ -2818,12 +2864,13 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
unless the error code is CR_ERROR and mysql->net.last_errno
is already set (the plugin has done it)
*/
DBUG_PRINT ("info", ("res=%d", res));
if (res > CR_ERROR)
set_mysql_error(mysql, res, unknown_sqlstate);
else
if (!mysql->net.last_errno)
set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
return 1;
DBUG_RETURN (1);
}
/* read the OK packet (or use the cached value in mysql->net.read_pos */
@@ -2832,6 +2879,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
else /* res == CR_OK_HANDSHAKE_COMPLETE */
pkt_length= mpvio.last_read_packet_len;
DBUG_PRINT ("info", ("OK packet length=%lu", pkt_length));
if (pkt_length == packet_error)
{
if (mysql->net.last_errno == CR_SERVER_LOST)
@@ -2839,7 +2887,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
ER(CR_SERVER_LOST_EXTENDED),
"reading authorization packet",
errno);
return 1;
DBUG_RETURN (1);
}
if (mysql->net.read_pos[0] == 254)
@@ -2848,6 +2896,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
if (pkt_length == 1)
{
/* old "use short scramble" packet */
DBUG_PRINT ("info", ("old use short scramble packet from server"));
auth_plugin_name= old_password_plugin_name;
mpvio.cached_server_reply.pkt= (uchar*)mysql->scramble;
mpvio.cached_server_reply.pkt_len= SCRAMBLE_LENGTH + 1;
@@ -2860,15 +2909,22 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
len= strlen(auth_plugin_name); /* safe as my_net_read always appends \0 */
mpvio.cached_server_reply.pkt_len= pkt_length - len - 2;
mpvio.cached_server_reply.pkt= mysql->net.read_pos + len + 2;
DBUG_PRINT ("info", ("change plugin packet from server for plugin %s",
auth_plugin_name));
}
if (!(auth_plugin= (auth_plugin_t *) mysql_client_find_plugin(mysql,
auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
return 1;
DBUG_RETURN (1);
mpvio.plugin= auth_plugin;
res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
DBUG_PRINT ("info", ("second authenticate_user returned %s",
res == CR_OK ? "CR_OK" :
res == CR_ERROR ? "CR_ERROR" :
res == CR_OK_HANDSHAKE_COMPLETE ?
"CR_OK_HANDSHAKE_COMPLETE" : "error"));
if (res > CR_OK)
{
if (res > CR_ERROR)
@@ -2876,7 +2932,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
else
if (!mysql->net.last_errno)
set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
return 1;
DBUG_RETURN (1);
}
if (res != CR_OK_HANDSHAKE_COMPLETE)
@@ -2889,7 +2945,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
ER(CR_SERVER_LOST_EXTENDED),
"reading final connect information",
errno);
return 1;
DBUG_RETURN (1);
}
}
}
@@ -2897,7 +2953,7 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
net->read_pos[0] should always be 0 here if the server implements
the protocol correctly
*/
return mysql->net.read_pos[0] != 0;
DBUG_RETURN (mysql->net.read_pos[0] != 0);
}
@@ -2907,8 +2963,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
uint port, const char *unix_socket,ulong client_flag)
{
char buff[NAME_LEN+USERNAME_LENGTH+100];
int scramble_data_len, pkt_scramble_len;
char *end, *host_info=0, *server_version_end, *pkt_end;
int scramble_data_len, pkt_scramble_len= 0;
char *end,*host_info= 0, *server_version_end, *pkt_end;
char *scramble_data;
const char *scramble_plugin;
ulong pkt_length;
@@ -2923,7 +2979,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
#ifdef HAVE_SYS_UN_H
struct sockaddr_un UNIXaddr;
#endif
init_sigpipe_variables
DBUG_ENTER("mysql_real_connect");
LINT_INIT(pkt_scramble_len);
@@ -2939,8 +2994,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
DBUG_RETURN(0);
}
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
mysql->methods= &client_methods;
net->vio = 0; /* If something goes wrong */
mysql->client_flag=0; /* For handshake */
@@ -3451,11 +3504,9 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
#endif
DBUG_PRINT("exit", ("Mysql handler: 0x%lx", (long) mysql));
reset_sigpipe(mysql);
DBUG_RETURN(mysql);
error:
reset_sigpipe(mysql);
DBUG_PRINT("error",("message: %u/%s (%s)",
net->last_errno,
net->sqlstate,
@@ -4076,10 +4127,10 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
break;
case MYSQL_PLUGIN_DIR:
extension_set_string(&mysql->options, plugin_dir, arg);
EXTENSION_SET_STRING(&mysql->options, plugin_dir, arg);
break;
case MYSQL_DEFAULT_AUTH:
extension_set_string(&mysql->options, default_auth, arg);
EXTENSION_SET_STRING(&mysql->options, default_auth, arg);
break;
default:
DBUG_RETURN(1);
@@ -4188,6 +4239,123 @@ int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
return mysql->net.last_errno;
}
/**
client authentication plugin that does native MySQL authentication
using a 20-byte (4.1+) scramble
*/
static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
int pkt_len;
uchar *pkt;
DBUG_ENTER("native_password_auth_client");
if (((MCPVIO_EXT *)vio)->mysql_change_user)
{
/*
in mysql_change_user() the client sends the first packet.
we use the old scramble.
*/
pkt= (uchar*)mysql->scramble;
pkt_len= SCRAMBLE_LENGTH + 1;
}
else
{
/* read the scramble */
if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
DBUG_RETURN(CR_ERROR);
if (pkt_len != SCRAMBLE_LENGTH + 1)
DBUG_RETURN(CR_SERVER_HANDSHAKE_ERR);
/* save it in MYSQL */
memcpy(mysql->scramble, pkt, SCRAMBLE_LENGTH);
mysql->scramble[SCRAMBLE_LENGTH] = 0;
}
if (mysql->passwd[0])
{
char scrambled[SCRAMBLE_LENGTH + 1];
DBUG_PRINT("info", ("sending scramble"));
scramble(scrambled, (char*)pkt, mysql->passwd);
if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH))
DBUG_RETURN(CR_ERROR);
}
else
{
DBUG_PRINT("info", ("no password"));
if (vio->write_packet(vio, 0, 0)) /* no password */
DBUG_RETURN(CR_ERROR);
}
DBUG_RETURN(CR_OK);
}
/**
client authentication plugin that does old MySQL authentication
using an 8-byte (4.0-) scramble
*/
static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
uchar *pkt;
int pkt_len;
DBUG_ENTER("old_password_auth_client");
if (((MCPVIO_EXT *)vio)->mysql_change_user)
{
/*
in mysql_change_user() the client sends the first packet.
we use the old scramble.
*/
pkt= (uchar*)mysql->scramble;
pkt_len= SCRAMBLE_LENGTH_323 + 1;
}
else
{
/* read the scramble */
if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
DBUG_RETURN(CR_ERROR);
if (pkt_len != SCRAMBLE_LENGTH_323 + 1 &&
pkt_len != SCRAMBLE_LENGTH + 1)
DBUG_RETURN(CR_SERVER_HANDSHAKE_ERR);
/* save it in MYSQL */
memcpy(mysql->scramble, pkt, pkt_len);
mysql->scramble[pkt_len] = 0;
}
if (mysql->passwd[0])
{
char scrambled[SCRAMBLE_LENGTH_323 + 1];
scramble_323(scrambled, (char*)pkt, mysql->passwd);
if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH_323 + 1))
DBUG_RETURN(CR_ERROR);
}
else
if (vio->write_packet(vio, 0, 0)) /* no password */
DBUG_RETURN(CR_ERROR);
DBUG_RETURN(CR_OK);
}
/**
The main function of the mysql_clear_password authentication plugin.
*/
static int clear_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
int res;
/* send password in clear text */
res= vio->write_packet(vio, (const unsigned char *) mysql->passwd,
strlen(mysql->passwd) + 1);
return res ? CR_ERROR : CR_OK;
}
/**
client authentication plugin that does native MySQL authentication