Commit a2425837 authored by peter@mysql.com's avatar peter@mysql.com

SCRUM: Montymise code

       fix mysql_change_user() for old clients
parent 54ff0efe
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#define LOCAL_HOST "localhost" #define LOCAL_HOST "localhost"
#define LOCAL_HOST_NAMEDPIPE "." #define LOCAL_HOST_NAMEDPIPE "."
#if defined(__WIN__) && !defined( _CUSTOMCONFIG_) #if defined(__WIN__) && !defined( _CUSTOMCONFIG_)
#define MYSQL_NAMEDPIPE "MySQL" #define MYSQL_NAMEDPIPE "MySQL"
#define MYSQL_SERVICENAME "MySql" #define MYSQL_SERVICENAME "MySql"
...@@ -44,6 +45,11 @@ enum enum_server_command ...@@ -44,6 +45,11 @@ enum enum_server_command
COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT
}; };
#define SCRAMBLE_LENGTH 8
#define SCRAMBLE41_LENGTH 20
#define NOT_NULL_FLAG 1 /* Field can't be NULL */ #define NOT_NULL_FLAG 1 /* Field can't be NULL */
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */ #define PRI_KEY_FLAG 2 /* Field is part of a primary key */
#define UNIQUE_KEY_FLAG 4 /* Field is part of a unique key */ #define UNIQUE_KEY_FLAG 4 /* Field is part of a unique key */
......
...@@ -232,9 +232,9 @@ my_bool my_connect(my_socket s, const struct sockaddr *name, ...@@ -232,9 +232,9 @@ my_bool my_connect(my_socket s, const struct sockaddr *name,
FD_ZERO(&sfds); FD_ZERO(&sfds);
FD_SET(s, &sfds); FD_SET(s, &sfds);
/* /*
* select could be interrupted by a signal, and if it is, * select could be interrupted by a signal, and if it is,
* the timeout should be adjusted and the select restarted * the timeout should be adjusted and the select restarted
* to work around OSes that don't restart select and * to work around OSes that don't restart select and
* implementations of select that don't adjust tv upon * implementations of select that don't adjust tv upon
* failure to reflect the time remaining * failure to reflect the time remaining
*/ */
...@@ -346,23 +346,23 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, ...@@ -346,23 +346,23 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host,
} }
#endif #endif
/* /*
Create new shared memory connection, return handler of connection Create new shared memory connection, return handler of connection
SYNOPSIS SYNOPSIS
create_shared_memory() create_shared_memory()
mysql Pointer of mysql structure mysql Pointer of mysql structure
net Pointer of net structure net Pointer of net structure
connect_timeout Timeout of connection connect_timeout Timeout of connection
*/ */
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
{ {
ulong smem_buffer_length = shared_memory_buffer_length + 4; ulong smem_buffer_length = shared_memory_buffer_length + 4;
/* /*
event_connect_request is event object for start connection actions event_connect_request is event object for start connection actions
event_connect_answer is event object for confirm, that server put data event_connect_answer is event object for confirm, that server put data
handle_connect_file_map is file-mapping object, use for create shared memory handle_connect_file_map is file-mapping object, use for create shared memory
handle_connect_map is pointer on shared memory handle_connect_map is pointer on shared memory
handle_map is pointer on shared memory for client handle_map is pointer on shared memory for client
event_server_wrote, event_server_wrote,
...@@ -382,10 +382,10 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) ...@@ -382,10 +382,10 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
HANDLE event_client_wrote = NULL; HANDLE event_client_wrote = NULL;
HANDLE event_client_read = NULL; HANDLE event_client_read = NULL;
HANDLE handle_file_map = NULL; HANDLE handle_file_map = NULL;
ulong connect_number; ulong connect_number;
char connect_number_char[22], *p; char connect_number_char[22], *p;
char tmp[64]; char tmp[64];
char *suffix_pos; char *suffix_pos;
DWORD error_allow = 0; DWORD error_allow = 0;
DWORD error_code = 0; DWORD error_code = 0;
char *shared_memory_base_name = mysql->options.shared_memory_base_name; char *shared_memory_base_name = mysql->options.shared_memory_base_name;
...@@ -399,24 +399,24 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) ...@@ -399,24 +399,24 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
*/ */
suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS); suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS);
strmov(suffix_pos, "CONNECT_REQUEST"); strmov(suffix_pos, "CONNECT_REQUEST");
if ((event_connect_request = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) if ((event_connect_request = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
{ {
error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR; error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR;
goto err; goto err;
} }
strmov(suffix_pos, "CONNECT_ANSWER"); strmov(suffix_pos, "CONNECT_ANSWER");
if ((event_connect_answer = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) if ((event_connect_answer = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
{ {
error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR; error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR;
goto err; goto err;
} }
strmov(suffix_pos, "CONNECT_DATA"); strmov(suffix_pos, "CONNECT_DATA");
if ((handle_connect_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL) if ((handle_connect_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL)
{ {
error_allow = CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR; error_allow = CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR;
goto err; goto err;
} }
if ((handle_connect_map = MapViewOfFile(handle_connect_file_map,FILE_MAP_WRITE,0,0,sizeof(DWORD))) == NULL) if ((handle_connect_map = MapViewOfFile(handle_connect_file_map,FILE_MAP_WRITE,0,0,sizeof(DWORD))) == NULL)
{ {
error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR; error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR;
goto err; goto err;
...@@ -424,7 +424,7 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) ...@@ -424,7 +424,7 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
/* /*
Send to server request of connection Send to server request of connection
*/ */
if (!SetEvent(event_connect_request)) if (!SetEvent(event_connect_request))
{ {
error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR; error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR;
goto err; goto err;
...@@ -456,7 +456,7 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) ...@@ -456,7 +456,7 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL) if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL)
{ {
error_allow = CR_SHARED_MEMORY_FILE_MAP_ERROR; error_allow = CR_SHARED_MEMORY_FILE_MAP_ERROR;
goto err2; goto err2;
} }
if ((handle_map = MapViewOfFile(handle_file_map,FILE_MAP_WRITE,0,0,smem_buffer_length)) == NULL) if ((handle_map = MapViewOfFile(handle_file_map,FILE_MAP_WRITE,0,0,smem_buffer_length)) == NULL)
{ {
...@@ -496,13 +496,13 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) ...@@ -496,13 +496,13 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
*/ */
SetEvent(event_server_read); SetEvent(event_server_read);
err2: err2:
if (error_allow == 0) if (error_allow == 0)
{ {
net->vio = vio_new_win32shared_memory(net,handle_file_map,handle_map,event_server_wrote, net->vio = vio_new_win32shared_memory(net,handle_file_map,handle_map,event_server_wrote,
event_server_read,event_client_wrote,event_client_read); event_server_read,event_client_wrote,event_client_read);
} }
else else
{ {
error_code = GetLastError(); error_code = GetLastError();
if (event_server_read) CloseHandle(event_server_read); if (event_server_read) CloseHandle(event_server_read);
...@@ -518,7 +518,7 @@ err: ...@@ -518,7 +518,7 @@ err:
if (event_connect_answer) CloseHandle(event_connect_answer); if (event_connect_answer) CloseHandle(event_connect_answer);
if (handle_connect_map) UnmapViewOfFile(handle_connect_map); if (handle_connect_map) UnmapViewOfFile(handle_connect_map);
if (handle_connect_file_map) CloseHandle(handle_connect_file_map); if (handle_connect_file_map) CloseHandle(handle_connect_file_map);
if (error_allow) if (error_allow)
{ {
net->last_errno=error_allow; net->last_errno=error_allow;
if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR) if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR)
...@@ -526,7 +526,7 @@ err: ...@@ -526,7 +526,7 @@ err:
else else
sprintf(net->last_error,ER(net->last_errno),error_code); sprintf(net->last_error,ER(net->last_errno),error_code);
return(INVALID_HANDLE_VALUE); return(INVALID_HANDLE_VALUE);
} }
return(handle_map); return(handle_map);
}; };
#endif #endif
...@@ -554,7 +554,7 @@ net_safe_read(MYSQL *mysql) ...@@ -554,7 +554,7 @@ net_safe_read(MYSQL *mysql)
DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d",
vio_description(net->vio),len)); vio_description(net->vio),len));
end_server(mysql); end_server(mysql);
net->last_errno=(net->last_errno == ER_NET_PACKET_TOO_LARGE ? net->last_errno=(net->last_errno == ER_NET_PACKET_TOO_LARGE ?
CR_NET_PACKET_TOO_LARGE: CR_NET_PACKET_TOO_LARGE:
CR_SERVER_LOST); CR_SERVER_LOST);
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
...@@ -1095,7 +1095,7 @@ static void mysql_read_default_options(struct st_mysql_options *options, ...@@ -1095,7 +1095,7 @@ static void mysql_read_default_options(struct st_mysql_options *options,
my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME)); options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME));
#endif #endif
break; break;
default: default:
DBUG_PRINT("warning",("unknown option: %s",option[0])); DBUG_PRINT("warning",("unknown option: %s",option[0]));
} }
...@@ -1161,7 +1161,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, ...@@ -1161,7 +1161,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->name= strdup_root(alloc,(char*) row->data[1]); field->name= strdup_root(alloc,(char*) row->data[1]);
field->length= (uint) uint3korr(row->data[2]); field->length= (uint) uint3korr(row->data[2]);
field->type= (enum enum_field_types) (uchar) row->data[3][0]; field->type= (enum enum_field_types) (uchar) row->data[3][0];
if (server_capabilities & CLIENT_LONG_FLAG) if (server_capabilities & CLIENT_LONG_FLAG)
{ {
field->flags= uint2korr(row->data[4]); field->flags= uint2korr(row->data[4]);
...@@ -1346,7 +1346,7 @@ my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q, ...@@ -1346,7 +1346,7 @@ my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
} }
/* perform query on slave */ /* perform query on slave */
my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q, my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
unsigned long length) unsigned long length)
{ {
...@@ -1391,7 +1391,7 @@ void STDCALL mysql_disable_rpl_parse(MYSQL* mysql) ...@@ -1391,7 +1391,7 @@ void STDCALL mysql_disable_rpl_parse(MYSQL* mysql)
mysql->options.rpl_parse = 0; mysql->options.rpl_parse = 0;
} }
/* get the value of the parse flag */ /* get the value of the parse flag */
int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql) int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql)
{ {
return mysql->options.rpl_parse; return mysql->options.rpl_parse;
...@@ -1408,7 +1408,7 @@ void STDCALL mysql_disable_reads_from_master(MYSQL* mysql) ...@@ -1408,7 +1408,7 @@ void STDCALL mysql_disable_reads_from_master(MYSQL* mysql)
mysql->options.no_master_reads = 1; mysql->options.no_master_reads = 1;
} }
/* get the value of the master read flag */ /* get the value of the master read flag */
my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql) my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql)
{ {
return !(mysql->options.no_master_reads); return !(mysql->options.no_master_reads);
...@@ -1537,7 +1537,7 @@ my_bool STDCALL mysql_rpl_probe(MYSQL* mysql) ...@@ -1537,7 +1537,7 @@ my_bool STDCALL mysql_rpl_probe(MYSQL* mysql)
the most reliable way to do this is to run SHOW SLAVE STATUS and see the most reliable way to do this is to run SHOW SLAVE STATUS and see
if we have a non-empty master host. This is still not fool-proof - if we have a non-empty master host. This is still not fool-proof -
it is not a sin to have a master that has a dormant slave thread with it is not a sin to have a master that has a dormant slave thread with
a non-empty master host. However, it is more reliable to check a non-empty master host. However, it is more reliable to check
for empty master than whether the slave thread is actually running for empty master than whether the slave thread is actually running
*/ */
if (mysql_query(mysql, "SHOW SLAVE STATUS") || if (mysql_query(mysql, "SHOW SLAVE STATUS") ||
...@@ -1602,7 +1602,7 @@ STDCALL mysql_rpl_query_type(const char* q, int len) ...@@ -1602,7 +1602,7 @@ STDCALL mysql_rpl_query_type(const char* q, int len)
case 'a': /* alter */ case 'a': /* alter */
return MYSQL_RPL_MASTER; return MYSQL_RPL_MASTER;
case 'c': /* create or check */ case 'c': /* create or check */
return my_tolower(system_charset_info,q[1]) == 'h' ? MYSQL_RPL_ADMIN : return my_tolower(system_charset_info,q[1]) == 'h' ? MYSQL_RPL_ADMIN :
MYSQL_RPL_MASTER; MYSQL_RPL_MASTER;
case 's': /* select or show */ case 's': /* select or show */
return my_tolower(system_charset_info,q[1]) == 'h' ? MYSQL_RPL_ADMIN : return my_tolower(system_charset_info,q[1]) == 'h' ? MYSQL_RPL_ADMIN :
...@@ -1643,7 +1643,7 @@ mysql_init(MYSQL *mysql) ...@@ -1643,7 +1643,7 @@ mysql_init(MYSQL *mysql)
By default, we are a replication pivot. The caller must reset it By default, we are a replication pivot. The caller must reset it
after we return if this is not the case. after we return if this is not the case.
*/ */
mysql->rpl_pivot = 1; mysql->rpl_pivot = 1;
#if defined(SIGPIPE) && defined(THREAD) && !defined(__WIN__) #if defined(SIGPIPE) && defined(THREAD) && !defined(__WIN__)
if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE)) if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE))
(void) signal(SIGPIPE,pipe_sig_handler); (void) signal(SIGPIPE,pipe_sig_handler);
...@@ -1658,7 +1658,7 @@ mysql_init(MYSQL *mysql) ...@@ -1658,7 +1658,7 @@ mysql_init(MYSQL *mysql)
#endif #endif
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
mysql->options.shared_memory_base_name=(char*)def_shared_memory_base_name; mysql->options.shared_memory_base_name=(char*)def_shared_memory_base_name;
#endif #endif
return mysql; return mysql;
} }
...@@ -1716,9 +1716,9 @@ static void mysql_once_init() ...@@ -1716,9 +1716,9 @@ static void mysql_once_init()
my_bool STDCALL my_bool STDCALL
mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
const char *key __attribute__((unused)), const char *key __attribute__((unused)),
const char *cert __attribute__((unused)), const char *cert __attribute__((unused)),
const char *ca __attribute__((unused)), const char *ca __attribute__((unused)),
const char *capath __attribute__((unused)), const char *capath __attribute__((unused)),
const char *cipher __attribute__((unused))) const char *cipher __attribute__((unused)))
{ {
...@@ -1795,7 +1795,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -1795,7 +1795,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
{ {
char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16]; char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16];
char *end,*host_info,*charset_name; char *end,*host_info,*charset_name;
char password_hash[20]; /* Used for tmp storage of stage1 hash */ char password_hash[SCRAMBLE41_LENGTH]; /* tmp storage stage1 hash */
my_socket sock; my_socket sock;
uint32 ip_addr; uint32 ip_addr;
struct sockaddr_in sock_addr; struct sockaddr_in sock_addr;
...@@ -1861,7 +1861,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -1861,7 +1861,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)&& if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)&&
(!host || !strcmp(host,LOCAL_HOST))) (!host || !strcmp(host,LOCAL_HOST)))
{ {
if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) == if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) ==
INVALID_HANDLE_VALUE) INVALID_HANDLE_VALUE)
{ {
DBUG_PRINT("error", DBUG_PRINT("error",
...@@ -1871,11 +1871,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -1871,11 +1871,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
(int) mysql->options.shared_memory_base_name, (int) mysql->options.shared_memory_base_name,
(int) have_tcpip)); (int) have_tcpip));
if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)
goto error; goto error;
/* /*
Try also with PIPE or TCP/IP Try also with PIPE or TCP/IP
*/ */
} }
else else
{ {
mysql->options.protocol=MYSQL_PROTOCOL_MEMORY; mysql->options.protocol=MYSQL_PROTOCOL_MEMORY;
...@@ -1935,9 +1935,9 @@ Try also with PIPE or TCP/IP ...@@ -1935,9 +1935,9 @@ Try also with PIPE or TCP/IP
if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE || if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
(host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
(unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE)))
goto error; goto error;
/* /*
Try also with TCP/IP Try also with TCP/IP
*/ */
} }
else else
...@@ -2028,7 +2028,7 @@ Try also with PIPE or TCP/IP ...@@ -2028,7 +2028,7 @@ Try also with PIPE or TCP/IP
vio_poll_read(net->vio, mysql->options.connect_timeout)) vio_poll_read(net->vio, mysql->options.connect_timeout))
{ {
net->last_errno= CR_SERVER_LOST; net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
goto error; goto error;
} }
if ((pkt_length=net_safe_read(mysql)) == packet_error) if ((pkt_length=net_safe_read(mysql)) == packet_error)
...@@ -2100,7 +2100,7 @@ Try also with PIPE or TCP/IP ...@@ -2100,7 +2100,7 @@ Try also with PIPE or TCP/IP
} }
goto error; goto error;
} }
/* Save connection information */ /* Save connection information */
if (!user) user=""; if (!user) user="";
if (!passwd) passwd=""; if (!passwd) passwd="";
...@@ -2180,7 +2180,7 @@ Try also with PIPE or TCP/IP ...@@ -2180,7 +2180,7 @@ Try also with PIPE or TCP/IP
if (my_net_write(net,buff,(uint) (2)) || net_flush(net)) if (my_net_write(net,buff,(uint) (2)) || net_flush(net))
{ {
net->last_errno= CR_SERVER_LOST; net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
goto error; goto error;
} }
/* Do the SSL layering. */ /* Do the SSL layering. */
...@@ -2192,7 +2192,7 @@ Try also with PIPE or TCP/IP ...@@ -2192,7 +2192,7 @@ Try also with PIPE or TCP/IP
options->ssl_cipher))) options->ssl_cipher)))
{ {
net->last_errno= CR_SSL_CONNECTION_ERROR; net->last_errno= CR_SSL_CONNECTION_ERROR;
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
goto error; goto error;
} }
DBUG_PRINT("info", ("IO layer change in progress...")); DBUG_PRINT("info", ("IO layer change in progress..."));
...@@ -2201,7 +2201,7 @@ Try also with PIPE or TCP/IP ...@@ -2201,7 +2201,7 @@ Try also with PIPE or TCP/IP
{ {
net->last_errno= CR_SSL_CONNECTION_ERROR; net->last_errno= CR_SSL_CONNECTION_ERROR;
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
goto error; goto error;
} }
DBUG_PRINT("info", ("IO layer change done!")); DBUG_PRINT("info", ("IO layer change done!"));
} }
...@@ -2215,7 +2215,7 @@ Try also with PIPE or TCP/IP ...@@ -2215,7 +2215,7 @@ Try also with PIPE or TCP/IP
strmake(buff+5,user,32); /* Max user name */ strmake(buff+5,user,32); /* Max user name */
else else
read_user_name((char*) buff+5); read_user_name((char*) buff+5);
/* We have to handle different version of handshake here */ /* We have to handle different version of handshake here */
#ifdef _CUSTOMCONFIG_ #ifdef _CUSTOMCONFIG_
#include "_cust_libmysql.h"; #include "_cust_libmysql.h";
#endif #endif
...@@ -2232,7 +2232,7 @@ Try also with PIPE or TCP/IP ...@@ -2232,7 +2232,7 @@ Try also with PIPE or TCP/IP
end=scramble(strend(buff+5)+1, mysql->scramble_buff,"\1~MySQL#!\2", end=scramble(strend(buff+5)+1, mysql->scramble_buff,"\1~MySQL#!\2",
(my_bool) (mysql->protocol_version == 9)); (my_bool) (mysql->protocol_version == 9));
} }
else /* For empty password*/ else /* For empty password*/
{ {
end=strend(buff+5)+1; end=strend(buff+5)+1;
*end=0; /* Store zero length scramble */ *end=0; /* Store zero length scramble */
...@@ -2243,23 +2243,23 @@ Try also with PIPE or TCP/IP ...@@ -2243,23 +2243,23 @@ Try also with PIPE or TCP/IP
end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd, end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9)); (my_bool) (mysql->protocol_version == 9));
/* Add database if needed */ /* Add database if needed */
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{ {
end=strmake(end+1,db,NAME_LEN); end=strmake(end+1,db,NAME_LEN);
mysql->db=my_strdup(db,MYF(MY_WME)); mysql->db=my_strdup(db,MYF(MY_WME));
db=0; db=0;
} }
/* Write authentication package */ /* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
{ {
net->last_errno= CR_SERVER_LOST; net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
goto error; goto error;
} }
/* We shall only query sever if it expect us to do so */ /* We shall only query sever if it expect us to do so */
if ( (pkt_length=net_safe_read(mysql)) == packet_error) if ( (pkt_length=net_safe_read(mysql)) == packet_error)
goto error; goto error;
...@@ -2269,46 +2269,47 @@ Try also with PIPE or TCP/IP ...@@ -2269,46 +2269,47 @@ Try also with PIPE or TCP/IP
if (pkt_length==24) /* We have new hash back */ if (pkt_length==24) /* We have new hash back */
{ {
/* Old passwords will have zero at the first byte of hash */ /* Old passwords will have zero at the first byte of hash */
if (net->read_pos[0]) if (net->read_pos[0])
{ {
/* Build full password hash as it is required to decode scramble */ /* Build full password hash as it is required to decode scramble */
password_hash_stage1(buff, passwd); password_hash_stage1(buff, passwd);
/* Store copy as we'll need it later */ /* Store copy as we'll need it later */
memcpy(password_hash,buff,20); memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
/* Finally hash complete password using hash we got from server */ /* Finally hash complete password using hash we got from server */
password_hash_stage2(password_hash,net->read_pos); password_hash_stage2(password_hash,net->read_pos);
/* Decypt and store scramble 4 = hash for stage2 */ /* Decypt and store scramble 4 = hash for stage2 */
password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,20); password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,
mysql->scramble_buff[20]=0; SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Encode scramble with password. Recycle buffer */ /* Encode scramble with password. Recycle buffer */
password_crypt(mysql->scramble_buff,buff,buff,20); password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
} }
else else
{ {
/* Create password to decode scramble */ /* Create password to decode scramble */
create_key_from_old_password(passwd,password_hash); create_key_from_old_password(passwd,password_hash);
/* Decypt and store scramble 4 = hash for stage2 */ /* Decypt and store scramble 4 = hash for stage2 */
password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,20); password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,
mysql->scramble_buff[20]=0; SCRAMBLE41_LENGTH);
/* Finally scramble decoded scramble with password */ mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
scramble(buff, mysql->scramble_buff, passwd, /* Finally scramble decoded scramble with password */
(my_bool) (mysql->protocol_version == 9)); scramble(buff, mysql->scramble_buff, passwd,0);
} }
/* Write second package of authentication */ /* Write second package of authentication */
if (my_net_write(net,buff,20) || net_flush(net)) if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
{ {
net->last_errno= CR_SERVER_LOST; net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
goto error; goto error;
} }
/* Read What server thinks about out new auth message report */ /* Read What server thinks about out new auth message report */
if (net_safe_read(mysql) == packet_error) if (net_safe_read(mysql) == packet_error)
goto error; goto error;
} }
} }
/* End of authentication part of handshake */ /* End of authentication part of handshake */
if (client_flag & CLIENT_COMPRESS) /* We will use compression */ if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1; net->compress=1;
if (db && mysql_select_db(mysql,db)) if (db && mysql_select_db(mysql,db))
...@@ -2395,7 +2396,7 @@ static my_bool mysql_reconnect(MYSQL *mysql) ...@@ -2395,7 +2396,7 @@ static my_bool mysql_reconnect(MYSQL *mysql)
mysql->free_me=0; mysql->free_me=0;
mysql_close(mysql); mysql_close(mysql);
*mysql=tmp_mysql; *mysql=tmp_mysql;
mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */ mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */
net_clear(&mysql->net); net_clear(&mysql->net);
mysql->affected_rows= ~(my_ulonglong) 0; mysql->affected_rows= ~(my_ulonglong) 0;
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -2403,28 +2404,28 @@ static my_bool mysql_reconnect(MYSQL *mysql) ...@@ -2403,28 +2404,28 @@ static my_bool mysql_reconnect(MYSQL *mysql)
/************************************************************************** /**************************************************************************
Change user and database Change user and database
**************************************************************************/ **************************************************************************/
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db) const char *passwd, const char *db)
{ {
char buff[512],*end=buff; char buff[512],*end=buff;
ulong pkt_length; ulong pkt_length;
char password_hash[20]; /* Used for tmp storage of stage1 hash */ char password_hash[SCRAMBLE41_LENGTH]; /* Used for tmp storage of stage1 hash */
NET *net= &mysql->net; NET *net= &mysql->net;
DBUG_ENTER("mysql_change_user"); DBUG_ENTER("mysql_change_user");
if (!user) if (!user)
user=""; user="";
if (!passwd) if (!passwd)
passwd=""; passwd="";
/* Store user into the buffer */ /* Store user into the buffer */
end=strmov(end,user)+1; end=strmov(end,user)+1;
/* /*
We always start with old type handshake the only difference is message sent We always start with old type handshake the only difference is message sent
If server handles secure connection type we'll not send the real scramble If server handles secure connection type we'll not send the real scramble
*/ */
...@@ -2434,24 +2435,24 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, ...@@ -2434,24 +2435,24 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
{ {
/* Use something for not empty password not to match it against empty one */ /* Use something for not empty password not to match it against empty one */
end=scramble(end, mysql->scramble_buff,"\1~MySQL#!\2", end=scramble(end, mysql->scramble_buff,"\1~MySQL#!\2",
(my_bool) (mysql->protocol_version == 9)); (my_bool) (mysql->protocol_version == 9));
} }
else /* For empty password*/ else /* For empty password*/
*end=0; /* Store zero length scramble */ *end=0; /* Store zero length scramble */
} }
/* Real scramble is sent only for servers. This is to be blocked by option */ /* Real scramble is sent only for servers. This is to be blocked by option */
else else
end=scramble(end, mysql->scramble_buff, passwd, end=scramble(end, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9)); (my_bool) (mysql->protocol_version == 9));
/* Add database if needed */ /* Add database if needed */
end=strmov(end+1,db ? db : ""); end=strmov(end+1,db ? db : "");
/* Write authentication package */ /* Write authentication package */
simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1); simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1);
/* We shall only query sever if it expect us to do so */ /* We shall only query sever if it expect us to do so */
if ( (pkt_length=net_safe_read(mysql)) == packet_error) if ( (pkt_length=net_safe_read(mysql)) == packet_error)
goto error; goto error;
...@@ -2461,44 +2462,46 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, ...@@ -2461,44 +2462,46 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
if (pkt_length==24) /* We have new hash back */ if (pkt_length==24) /* We have new hash back */
{ {
/* Old passwords will have zero at the first byte of hash */ /* Old passwords will have zero at the first byte of hash */
if (net->read_pos[0]) if (net->read_pos[0])
{ {
/* Build full password hash as it is required to decode scramble */ /* Build full password hash as it is required to decode scramble */
password_hash_stage1(buff, passwd); password_hash_stage1(buff, passwd);
/* Store copy as we'll need it later */ /* Store copy as we'll need it later */
memcpy(password_hash,buff,20); memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
/* Finally hash complete password using hash we got from server */ /* Finally hash complete password using hash we got from server */
password_hash_stage2(password_hash,net->read_pos); password_hash_stage2(password_hash,net->read_pos);
/* Decypt and store scramble 4 = hash for stage2 */ /* Decypt and store scramble 4 = hash for stage2 */
password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,20); password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,
mysql->scramble_buff[20]=0; SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Encode scramble with password. Recycle buffer */ /* Encode scramble with password. Recycle buffer */
password_crypt(mysql->scramble_buff,buff,buff,20); password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
} }
else else
{ {
/* Create password to decode scramble */ /* Create password to decode scramble */
create_key_from_old_password(passwd,password_hash); create_key_from_old_password(passwd,password_hash);
/* Decypt and store scramble 4 = hash for stage2 */ /* Decypt and store scramble 4 = hash for stage2 */
password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,20); password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,
mysql->scramble_buff[20]=0; SCRAMBLE41_LENGTH);
/* Finally scramble decoded scramble with password */ mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Finally scramble decoded scramble with password */
scramble(buff, mysql->scramble_buff, passwd, scramble(buff, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9)); (my_bool) (mysql->protocol_version == 9));
} }
/* Write second package of authentication */ /* Write second package of authentication */
if (my_net_write(net,buff,20) || net_flush(net)) if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
{ {
net->last_errno= CR_SERVER_LOST; net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
goto error; goto error;
} }
/* Read What server thinks about out new auth message report */ /* Read What server thinks about out new auth message report */
if (net_safe_read(mysql) == packet_error) if (net_safe_read(mysql) == packet_error)
goto error; goto error;
} }
} }
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
...@@ -2507,10 +2510,10 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, ...@@ -2507,10 +2510,10 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
mysql->passwd=my_strdup(passwd,MYF(MY_WME)); mysql->passwd=my_strdup(passwd,MYF(MY_WME));
mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0; mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0;
DBUG_RETURN(0); DBUG_RETURN(0);
error: error:
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -2598,7 +2601,7 @@ mysql_close(MYSQL *mysql) ...@@ -2598,7 +2601,7 @@ mysql_close(MYSQL *mysql)
{ {
next_element= element->next; next_element= element->next;
stmt_close((MYSQL_STMT *)element->data, 0); stmt_close((MYSQL_STMT *)element->data, 0);
} }
} }
if (mysql != mysql->master) if (mysql != mysql->master)
mysql_close(mysql->master); mysql_close(mysql->master);
...@@ -2686,7 +2689,7 @@ STDCALL mysql_add_slave(MYSQL* mysql, const char* host, ...@@ -2686,7 +2689,7 @@ STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
Send the query and return so we can do something else. Send the query and return so we can do something else.
Needs to be followed by mysql_read_query_result() when we want to Needs to be followed by mysql_read_query_result() when we want to
finish processing it. finish processing it.
*/ */
int STDCALL int STDCALL
mysql_send_query(MYSQL* mysql, const char* query, ulong length) mysql_send_query(MYSQL* mysql, const char* query, ulong length)
...@@ -4024,12 +4027,12 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param) ...@@ -4024,12 +4027,12 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
DBUG_ENTER("store_param"); DBUG_ENTER("store_param");
DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %d", param->buffer_type, DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %d", param->buffer_type,
param->buffer ? param->buffer : "0", *param->length)); param->buffer ? param->buffer : "0", *param->length));
if (param->is_null || param->buffer_type == MYSQL_TYPE_NULL) if (param->is_null || param->buffer_type == MYSQL_TYPE_NULL)
store_param_null(net, param); store_param_null(net, param);
else else
{ {
/* Allocate for worst case (long string) */ /* Allocate for worst case (long string) */
if ((my_realloc_str(net, 9 + *param->length))) if ((my_realloc_str(net, 9 + *param->length)))
DBUG_RETURN(1); DBUG_RETURN(1);
(*param->store_param_func)(net, param); (*param->store_param_func)(net, param);
...@@ -4205,14 +4208,14 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind) ...@@ -4205,14 +4208,14 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
param->param_number); param->param_number);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
/* /*
If param->length is not given, change it to point to bind_length. If param->length is not given, change it to point to bind_length.
This way we can always use *param->length to get the length of data This way we can always use *param->length to get the length of data
*/ */
if (!param->length) if (!param->length)
param->length= &param->bind_length; param->length= &param->bind_length;
/* Setup data copy functions for the different supported types */ /* Setup data copy functions for the different supported types */
switch (param->buffer_type) { switch (param->buffer_type) {
case MYSQL_TYPE_NULL: case MYSQL_TYPE_NULL:
...@@ -4358,7 +4361,7 @@ static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row) ...@@ -4358,7 +4361,7 @@ static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row)
static void fetch_result_short(MYSQL_BIND *param, uchar **row) static void fetch_result_short(MYSQL_BIND *param, uchar **row)
{ {
short value= *(short *)row; short value= *(short *)row;
int2store(param->buffer, value); int2store(param->buffer, value);
*row+=2; *row+=2;
} }
...@@ -4462,7 +4465,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) ...@@ -4462,7 +4465,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
sprintf(stmt->last_error, ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE), sprintf(stmt->last_error, ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
param->buffer_type, param->param_number); param->buffer_type, param->param_number);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (!param->length) if (!param->length)
param->length= &param->bind_length; param->length= &param->bind_length;
} }
...@@ -4479,10 +4482,10 @@ stmt_fetch_row(MYSQL_STMT *stmt, uchar **row) ...@@ -4479,10 +4482,10 @@ stmt_fetch_row(MYSQL_STMT *stmt, uchar **row)
{ {
MYSQL_BIND *bind, *end; MYSQL_BIND *bind, *end;
uchar *null_ptr= (uchar*) *row, bit; uchar *null_ptr= (uchar*) *row, bit;
*row+= (stmt->field_count+7)/8; *row+= (stmt->field_count+7)/8;
bit=1; bit=1;
/* Copy complete row to application buffers */ /* Copy complete row to application buffers */
for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count; for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count;
bind < end; bind < end;
...@@ -4505,7 +4508,7 @@ stmt_fetch_row(MYSQL_STMT *stmt, uchar **row) ...@@ -4505,7 +4508,7 @@ stmt_fetch_row(MYSQL_STMT *stmt, uchar **row)
} }
static int read_binary_data(MYSQL *mysql) static int read_binary_data(MYSQL *mysql)
{ {
if (packet_error == net_safe_read(mysql)) if (packet_error == net_safe_read(mysql))
return -1; return -1;
if (mysql->net.read_pos[0]) if (mysql->net.read_pos[0])
...@@ -4532,9 +4535,9 @@ int STDCALL mysql_fetch(MYSQL_STMT *stmt) ...@@ -4532,9 +4535,9 @@ int STDCALL mysql_fetch(MYSQL_STMT *stmt)
DBUG_RETURN((int) stmt_fetch_row(stmt,(uchar **) &mysql->net.read_pos+1)); DBUG_RETURN((int) stmt_fetch_row(stmt,(uchar **) &mysql->net.read_pos+1));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
DBUG_PRINT("info", ("end of data")); DBUG_PRINT("info", ("end of data"));
mysql->status= MYSQL_STATUS_READY; mysql->status= MYSQL_STATUS_READY;
if (res < 0) /* Network error */ if (res < 0) /* Network error */
{ {
set_stmt_errmsg(stmt,(char *)mysql->net.last_error, set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
......
...@@ -170,12 +170,20 @@ fi ...@@ -170,12 +170,20 @@ fi
@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA @bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
alter table user alter table user
change password password char(45) not null,
add max_questions int(11) NOT NULL AFTER x509_subject, add max_questions int(11) NOT NULL AFTER x509_subject,
add max_updates int(11) unsigned NOT NULL AFTER max_questions, add max_updates int(11) unsigned NOT NULL AFTER max_questions,
add max_connections int(11) unsigned NOT NULL AFTER max_updates; add max_connections int(11) unsigned NOT NULL AFTER max_updates;
END_OF_DATA END_OF_DATA
# Increase password length to handle new passwords
@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
alter table user
change password password char(45) not null;
END_OF_DATA
# #
# Add Create_tmp_table_priv and Lock_tables_priv to db and host # Add Create_tmp_table_priv and Lock_tables_priv to db and host
# #
......
...@@ -490,7 +490,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -490,7 +490,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
uint net_read_timeout) uint net_read_timeout)
{ {
char buff[NAME_LEN+USERNAME_LENGTH+100],*end,*host_info; char buff[NAME_LEN+USERNAME_LENGTH+100],*end,*host_info;
char password_hash[20]; char password_hash[SCRAMBLE41_LENGTH];
my_socket sock; my_socket sock;
ulong ip_addr; ulong ip_addr;
struct sockaddr_in sock_addr; struct sockaddr_in sock_addr;
...@@ -856,28 +856,29 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -856,28 +856,29 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
/* Build full password hash as it is required to decode scramble */ /* Build full password hash as it is required to decode scramble */
password_hash_stage1(buff, passwd); password_hash_stage1(buff, passwd);
/* Store copy as we'll need it later */ /* Store copy as we'll need it later */
memcpy(password_hash,buff,20); memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
/* Finally hash complete password using hash we got from server */ /* Finally hash complete password using hash we got from server */
password_hash_stage2(password_hash,(char*)net->read_pos); password_hash_stage2(password_hash,(char*)net->read_pos);
/* Decypt and store scramble 4 = hash for stage2 */ /* Decypt and store scramble 4 = hash for stage2 */
password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash,20); password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash,
mysql->scramble_buff[20]=0; SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Encode scramble with password. Recycle buffer */ /* Encode scramble with password. Recycle buffer */
password_crypt(mysql->scramble_buff,buff,buff,20); password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
} }
else else
{ {
/* Create password to decode scramble */ /* Create password to decode scramble */
create_key_from_old_password(passwd,password_hash); create_key_from_old_password(passwd,password_hash);
/* Decypt and store scramble 4 = hash for stage2 */ /* Decypt and store scramble 4 = hash for stage2 */
password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash,20); password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash,
mysql->scramble_buff[20]=0; SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Finally scramble decoded scramble with password */ /* Finally scramble decoded scramble with password */
scramble(buff, mysql->scramble_buff, passwd, scramble(buff, mysql->scramble_buff, passwd,0);
(my_bool) (mysql->protocol_version == 9));
} }
/* Write second package of authentication */ /* Write second package of authentication */
if (my_net_write(net,buff,20) || net_flush(net)) if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
{ {
net->last_errno= CR_SERVER_LOST; net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
......
...@@ -2496,6 +2496,9 @@ static void create_new_thread(THD *thd) ...@@ -2496,6 +2496,9 @@ static void create_new_thread(THD *thd)
for (uint i=0; i < 8 ; i++) // Generate password teststring for (uint i=0; i < 8 ; i++) // Generate password teststring
thd->scramble[i]= (char) (rnd(&sql_rand)*94+33); thd->scramble[i]= (char) (rnd(&sql_rand)*94+33);
thd->scramble[8]=0; thd->scramble[8]=0;
// Back it up as old clients may need it
memcpy(thd->old_scramble,thd->scramble,9);
thd->real_id=pthread_self(); // Keep purify happy thd->real_id=pthread_self(); // Keep purify happy
......
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
#define PVERSION41_CHAR '*' #define PVERSION41_CHAR '*'
/* Scramble length for new password version */ /* Scramble length for new password version */
#define SCRAMBLE41_LENGTH 20
/* /*
...@@ -175,17 +174,12 @@ void create_random_string(int length,struct rand_struct *rand_st,char* target) ...@@ -175,17 +174,12 @@ void create_random_string(int length,struct rand_struct *rand_st,char* target)
none none
*/ */
inline void password_crypt(const char* from,char* to, const char* password,int length) void password_crypt(const char* from,char* to, const char* password,int length)
{ {
const char *from_end=from+length; const char *from_end=from+length;
while(from<from_end) while (from < from_end)
{ *to++= *(from++) ^* (password++);
*to=*from^*password;
from++;
to++;
password++;
}
} }
...@@ -286,7 +280,9 @@ void password_hash_stage2(char *to,const char *salt) ...@@ -286,7 +280,9 @@ void password_hash_stage2(char *to,const char *salt)
none none
*/ */
void make_scrambled_password(char *to,const char *password,my_bool force_old_scramble,struct rand_struct *rand_st) void make_scrambled_password(char *to,const char *password,
my_bool force_old_scramble,
struct rand_struct *rand_st)
{ {
ulong hash_res[2]; /* Used for pre 4.1 password hashing */ ulong hash_res[2]; /* Used for pre 4.1 password hashing */
unsigned short salt; /* Salt for 4.1 version password */ unsigned short salt; /* Salt for 4.1 version password */
...@@ -336,7 +332,6 @@ void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt) ...@@ -336,7 +332,6 @@ void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt)
unsigned char* password_end=password+SCRAMBLE41_LENGTH; unsigned char* password_end=password+SCRAMBLE41_LENGTH;
*res=salt; *res=salt;
res++; res++;
bzero(res,5*sizeof(res[0]));
/* Process password of known length*/ /* Process password of known length*/
while (password<password_end) while (password<password_end)
...@@ -364,12 +359,14 @@ void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt) ...@@ -364,12 +359,14 @@ void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt)
!0 for invalid password !0 for invalid password
*/ */
my_bool validate_password(const char* password, const char* message, ulong* salt) my_bool validate_password(const char* password, const char* message,
ulong* salt)
{ {
char buffer[SCRAMBLE41_LENGTH]; /* Used for password validation */ char buffer[SCRAMBLE41_LENGTH]; /* Used for password validation */
char tmpsalt[8]; /* Temporary value to convert salt to string form */ char tmpsalt[8]; /* Temporary value to convert salt to string form */
int i;
ulong salt_candidate[6]; /* Computed candidate salt */ ulong salt_candidate[6]; /* Computed candidate salt */
ulong* sc=salt_candidate; /* we need to be able to increment */
ulong* salt_end;
/* Now we shall get stage1 encrypted password in buffer*/ /* Now we shall get stage1 encrypted password in buffer*/
password_crypt(password,buffer,message,SCRAMBLE41_LENGTH); password_crypt(password,buffer,message,SCRAMBLE41_LENGTH);
...@@ -381,9 +378,11 @@ my_bool validate_password(const char* password, const char* message, ulong* salt ...@@ -381,9 +378,11 @@ my_bool validate_password(const char* password, const char* message, ulong* salt
/* Convert password to salt to compare */ /* Convert password to salt to compare */
get_salt_from_bin_password(salt_candidate,buffer,salt[0]); get_salt_from_bin_password(salt_candidate,buffer,salt[0]);
/* Now we shall get exactly the same password as we have stored for user */ /* Now we shall get exactly the same password as we have stored for user */
for(i=1;i<6;i++) for (salt_end=salt+5 ; salt < salt_end; )
if (salt[i]!=salt_candidate[i]) return 1; if (*++salt != *++sc)
return 1;
/* Or password correct*/ /* Or password correct*/
return 0; return 0;
} }
...@@ -400,11 +399,9 @@ my_bool validate_password(const char* password, const char* message, ulong* salt ...@@ -400,11 +399,9 @@ my_bool validate_password(const char* password, const char* message, ulong* salt
password length >0 password length >0
*/ */
inline int get_password_length(my_bool force_old_scramble) int get_password_length(my_bool force_old_scramble)
{ {
if (force_old_scramble) return (force_old_scramble) ? 16 : SHA1_HASH_SIZE*2+4+1;
return 16;
else return SHA1_HASH_SIZE*2+4+1;
} }
...@@ -420,9 +417,9 @@ inline int get_password_length(my_bool force_old_scramble) ...@@ -420,9 +417,9 @@ inline int get_password_length(my_bool force_old_scramble)
!0 password version char for newer passwords !0 password version char for newer passwords
*/ */
inline char get_password_version(const char* password) char get_password_version(const char* password)
{ {
if (password==NULL) return 0; if (password==NULL) return 0;
if (password[0]==PVERSION41_CHAR) return PVERSION41_CHAR; if (password[0]==PVERSION41_CHAR) return PVERSION41_CHAR;
return 0; return 0;
} }
...@@ -467,7 +464,6 @@ inline uint char_val(char X) ...@@ -467,7 +464,6 @@ inline uint char_val(char X)
void get_salt_from_password(ulong *res,const char *password) void get_salt_from_password(ulong *res,const char *password)
{ {
bzero(res,6*sizeof(res[0]));
if (password) /* zero salt corresponds to empty password */ if (password) /* zero salt corresponds to empty password */
{ {
if (password[0]==PVERSION41_CHAR) /* if new password */ if (password[0]==PVERSION41_CHAR) /* if new password */
...@@ -553,19 +549,17 @@ void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned cha ...@@ -553,19 +549,17 @@ void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned cha
if (pversion) /* New password version assumed */ if (pversion) /* New password version assumed */
{ {
salt_end=salt+6; salt_end=salt+5;
sprintf(hash,"%04x",(unsigned short)salt[0]); sprintf(hash,"%04x",(unsigned short)salt[0]);
salt++; /* position to the second element */
while (salt<salt_end) /* Iterate over these elements*/ while (salt<salt_end) /* Iterate over these elements*/
{ {
val=*salt; val=*(++salt);
for(t=3;t>=0;t--) for (t=3; t>=0; t--)
{ {
bin_password[t]=val%256; bin_password[t]=val%256;
val>>=8; /* Scroll 8 bits to get next part*/ val>>=8; /* Scroll 8 bits to get next part*/
} }
bin_password+=4; /* Get to next 4 chars*/ bin_password+=4; /* Get to next 4 chars*/
salt++;
} }
} }
else else
...@@ -611,7 +605,7 @@ void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned cha ...@@ -611,7 +605,7 @@ void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned cha
void create_key_from_old_password(const char* passwd, char* key) void create_key_from_old_password(const char* passwd, char* key)
{ {
char buffer[20]; /* Buffer for various needs */ char buffer[SCRAMBLE41_LENGTH]; /* Buffer for various needs */
ulong salt[6]; /* Salt (large for safety) */ ulong salt[6]; /* Salt (large for safety) */
/* At first hash password to the string stored in password */ /* At first hash password to the string stored in password */
make_scrambled_password(buffer,passwd,1,(struct rand_struct *)NULL); make_scrambled_password(buffer,passwd,1,(struct rand_struct *)NULL);
......
...@@ -102,10 +102,10 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ...@@ -102,10 +102,10 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
if (dont_read_acl_tables) if (dont_read_acl_tables)
{ {
DBUG_RETURN(0); /* purecov: tested */ DBUG_RETURN(0); /* purecov: tested */
} }
priv_version++; /* Priveleges updated */ priv_version++; /* Priveleges updated */
/* /*
To be able to run this from boot, we allocate a temporary THD To be able to run this from boot, we allocate a temporary THD
*/ */
...@@ -205,7 +205,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ...@@ -205,7 +205,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
continue; /* purecov: tested */ continue; /* purecov: tested */
} }
} }
get_salt_from_password(user.salt,user.password); get_salt_from_password(user.salt,user.password);
user.access=get_access(table,3) & GLOBAL_ACLS; user.access=get_access(table,3) & GLOBAL_ACLS;
user.sort=get_sort(2,user.host.hostname,user.user); user.sort=get_sort(2,user.host.hostname,user.user);
user.hostname_length= (user.host.hostname ? user.hostname_length= (user.host.hostname ?
...@@ -263,7 +263,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ...@@ -263,7 +263,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
sizeof(ACL_USER),(qsort_cmp) acl_compare); sizeof(ACL_USER),(qsort_cmp) acl_compare);
end_read_record(&read_record_info); end_read_record(&read_record_info);
freeze_size(&acl_users); freeze_size(&acl_users);
init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0); init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0);
VOID(my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100)); VOID(my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100));
while (!(read_record_info.read_record(&read_record_info))) while (!(read_record_info.read_record(&read_record_info)))
...@@ -452,17 +452,17 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b) ...@@ -452,17 +452,17 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
Prepare crypted scramble to be sent to the client Prepare crypted scramble to be sent to the client
*/ */
void prepare_scramble(THD* thd, ACL_USER *acl_user,char* prepared_scramble) void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
{ {
/* Binary password format to be used for generation*/ /* Binary password format to be used for generation*/
char bin_password[20]; char bin_password[SCRAMBLE41_LENGTH];
/* Generate new long scramble for the thread */ /* Generate new long scramble for the thread */
create_random_string(20,&thd->rand,thd->scramble); create_random_string(SCRAMBLE41_LENGTH,&thd->rand,thd->scramble);
thd->scramble[20]=0; thd->scramble[SCRAMBLE41_LENGTH]=0;
/* Get binary form, First 4 bytes of prepared scramble is salt */ /* Get binary form, First 4 bytes of prepared scramble is salt */
get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,(unsigned char*)bin_password); get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,(unsigned char*)bin_password);
/* Finally encrypt password to get prepared scramble */ /* Finally encrypt password to get prepared scramble */
password_crypt(thd->scramble,prepared_scramble+4,bin_password,20); password_crypt(thd->scramble,prepared_scramble+4,bin_password,SCRAMBLE41_LENGTH);
} }
...@@ -472,11 +472,11 @@ void prepare_scramble(THD* thd, ACL_USER *acl_user,char* prepared_scramble) ...@@ -472,11 +472,11 @@ void prepare_scramble(THD* thd, ACL_USER *acl_user,char* prepared_scramble)
/* /*
Get master privilges for user (priviliges for all tables). Get master privilges for user (priviliges for all tables).
Required before connecting to MySQL Required before connecting to MySQL
as we have 2 stage handshake now we cache user not to lookup as we have 2 stage handshake now we cache user not to lookup
it second time. At the second stage we do not lookup user in case it second time. At the second stage we do not lookup user in case
we already know it; we already know it;
*/ */
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
...@@ -488,7 +488,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -488,7 +488,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
*priv_user=(char*) user; *priv_user=(char*) user;
bool password_correct=0; bool password_correct=0;
ACL_USER *acl_user=NULL; ACL_USER *acl_user=NULL;
DBUG_ENTER("acl_getroot"); DBUG_ENTER("acl_getroot");
bzero(mqh,sizeof(USER_RESOURCES)); bzero(mqh,sizeof(USER_RESOURCES));
...@@ -498,18 +498,18 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -498,18 +498,18 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
DBUG_RETURN((ulong) ~NO_ACCESS); /* purecov: tested */ DBUG_RETURN((ulong) ~NO_ACCESS); /* purecov: tested */
} }
VOID(pthread_mutex_lock(&acl_cache->lock)); VOID(pthread_mutex_lock(&acl_cache->lock));
/* /*
Get possible access from user_list. This is or'ed to others not Get possible access from user_list. This is or'ed to others not
fully specified fully specified
If we have cached user use it, in other case look it up. If we have cached user use it, in other case look it up.
*/ */
if (stage && (*cur_priv_version==priv_version)) if (stage && (*cur_priv_version==priv_version))
acl_user=*hint_user; acl_user=*hint_user;
else else
for (uint i=0 ; i < acl_users.elements ; i++) for (uint i=0 ; i < acl_users.elements ; i++)
{ {
ACL_USER *acl_user_search=dynamic_element(&acl_users,i,ACL_USER*); ACL_USER *acl_user_search=dynamic_element(&acl_users,i,ACL_USER*);
...@@ -517,30 +517,30 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -517,30 +517,30 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
{ {
if (compare_hostname(&acl_user_search->host,host,ip)) if (compare_hostname(&acl_user_search->host,host,ip))
{ {
/* Found mathing user */ /* Found mathing user */
acl_user=acl_user_search; acl_user=acl_user_search;
/* Store it as a cache */ /* Store it as a cache */
*hint_user=acl_user; *hint_user=acl_user;
*cur_priv_version=priv_version; *cur_priv_version=priv_version;
break; break;
} }
} }
} }
/* Now we have acl_user found and may start our checks */ /* Now we have acl_user found and may start our checks */
if (acl_user) if (acl_user)
{ {
/* Password should present for both or absend for both */ /* Password should present for both or absend for both */
if (!acl_user->password && !*password || if (!acl_user->password && !*password ||
(acl_user->password && *password)) (acl_user->password && *password))
{ {
/* Quick check and accept for empty passwords*/ /* Quick check and accept for empty passwords*/
if (!acl_user->password && !*password) if (!acl_user->password && !*password)
password_correct=1; password_correct=1;
else /* Normal password presents */ else /* Normal password presents */
{ {
/* New version password is checked differently */ /* New version password is checked differently */
if (acl_user->pversion) if (acl_user->pversion)
{ {
...@@ -548,40 +548,40 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -548,40 +548,40 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
{ {
if (!validate_password(password,message,acl_user->salt)) if (!validate_password(password,message,acl_user->salt))
password_correct=1; password_correct=1;
} }
else /* First stage - just prepare scramble */ else /* First stage - just prepare scramble */
prepare_scramble(thd,acl_user,prepared_scramble); prepare_scramble(thd,acl_user,prepared_scramble);
} }
/* Old way to check password */ /* Old way to check password */
else else
{ {
/* Checking the scramble at any stage. First - old clients */ /* Checking the scramble at any stage. First - old clients */
if (!check_scramble(password,message,acl_user->salt, if (!check_scramble(password,message,acl_user->salt,
(my_bool) old_ver)) (my_bool) old_ver))
password_correct=1; password_correct=1;
else /* Password incorrect */ else /* Password incorrect */
/* At the first stage - prepare scramble */ /* At the first stage - prepare scramble */
if (!stage) if (!stage)
prepare_scramble(thd,acl_user,prepared_scramble); prepare_scramble(thd,acl_user,prepared_scramble);
} }
} }
} }
} }
/* If user not found password_correct will also be zero */ /* If user not found password_correct will also be zero */
if (!password_correct) if (!password_correct)
goto unlock_and_exit; goto unlock_and_exit;
/* OK. User found and password checked continue validation */ /* OK. User found and password checked continue validation */
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
Vio *vio=thd->net.vio; Vio *vio=thd->net.vio;
/* /*
In this point we know that user is allowed to connect In this point we know that user is allowed to connect
from given host by given username/password pair. Now from given host by given username/password pair. Now
we check if SSL is required, if user is using SSL and we check if SSL is required, if user is using SSL and
if X509 certificate attributes are OK if X509 certificate attributes are OK
*/ */
switch (acl_user->ssl_type) { switch (acl_user->ssl_type) {
case SSL_TYPE_NOT_SPECIFIED: // Impossible case SSL_TYPE_NOT_SPECIFIED: // Impossible
...@@ -594,8 +594,8 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -594,8 +594,8 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
break; break;
case SSL_TYPE_X509: /* Client should have any valid certificate. */ case SSL_TYPE_X509: /* Client should have any valid certificate. */
/* /*
Connections with non-valid certificates are dropped already Connections with non-valid certificates are dropped already
in sslaccept() anyway, so we do not check validity here. in sslaccept() anyway, so we do not check validity here.
*/ */
if (SSL_get_peer_certificate(vio->ssl_)) if (SSL_get_peer_certificate(vio->ssl_))
user_access=acl_user->access; user_access=acl_user->access;
...@@ -624,7 +624,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -624,7 +624,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
X509* cert=SSL_get_peer_certificate(vio->ssl_); X509* cert=SSL_get_peer_certificate(vio->ssl_);
DBUG_PRINT("info",("checkpoint 2")); DBUG_PRINT("info",("checkpoint 2"));
/* If X509 issuer is speified, we check it... */ /* If X509 issuer is speified, we check it... */
if (acl_user->x509_issuer) if (acl_user->x509_issuer)
{ {
DBUG_PRINT("info",("checkpoint 3")); DBUG_PRINT("info",("checkpoint 3"));
char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
...@@ -660,7 +660,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -660,7 +660,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
*mqh=acl_user->user_resource; *mqh=acl_user->user_resource;
if (!acl_user->user) if (!acl_user->user)
*priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */ *priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
unlock_and_exit: unlock_and_exit:
VOID(pthread_mutex_unlock(&acl_cache->lock)); VOID(pthread_mutex_unlock(&acl_cache->lock));
DBUG_RETURN(user_access); DBUG_RETURN(user_access);
...@@ -675,12 +675,12 @@ static byte* check_get_key(ACL_USER *buff,uint *length, ...@@ -675,12 +675,12 @@ static byte* check_get_key(ACL_USER *buff,uint *length,
} }
static void acl_update_user(const char *user, const char *host, static void acl_update_user(const char *user, const char *host,
const char *password, const char *password,
enum SSL_type ssl_type, enum SSL_type ssl_type,
const char *ssl_cipher, const char *ssl_cipher,
const char *x509_issuer, const char *x509_issuer,
const char *x509_subject, const char *x509_subject,
USER_RESOURCES *mqh, USER_RESOURCES *mqh,
ulong privileges) ulong privileges)
{ {
for (uint i=0 ; i < acl_users.elements ; i++) for (uint i=0 ; i < acl_users.elements ; i++)
...@@ -716,8 +716,8 @@ static void acl_update_user(const char *user, const char *host, ...@@ -716,8 +716,8 @@ static void acl_update_user(const char *user, const char *host,
if (!password[0]) /* If password is empty set it to null */ if (!password[0]) /* If password is empty set it to null */
{ {
acl_user->password=0; acl_user->password=0;
acl_user->pversion=0; // just initialize acl_user->pversion=0; // just initialize
} }
else else
{ {
acl_user->password=(char*) ""; // Just point at something acl_user->password=(char*) ""; // Just point at something
...@@ -733,7 +733,7 @@ static void acl_update_user(const char *user, const char *host, ...@@ -733,7 +733,7 @@ static void acl_update_user(const char *user, const char *host,
static void acl_insert_user(const char *user, const char *host, static void acl_insert_user(const char *user, const char *host,
const char *password, const char *password,
enum SSL_type ssl_type, enum SSL_type ssl_type,
const char *ssl_cipher, const char *ssl_cipher,
const char *x509_issuer, const char *x509_issuer,
...@@ -926,7 +926,7 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr) ...@@ -926,7 +926,7 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
{ {
if (*wildstr == wild_prefix && wildstr[1]) if (*wildstr == wild_prefix && wildstr[1])
wildstr++; wildstr++;
if (my_toupper(cs, *wildstr++) != if (my_toupper(cs, *wildstr++) !=
my_toupper(cs, *str++)) DBUG_RETURN(1); my_toupper(cs, *str++)) DBUG_RETURN(1);
} }
if (! *wildstr ) DBUG_RETURN (*str != 0); if (! *wildstr ) DBUG_RETURN (*str != 0);
...@@ -1091,7 +1091,7 @@ bool check_change_password(THD *thd, const char *host, const char *user) ...@@ -1091,7 +1091,7 @@ bool check_change_password(THD *thd, const char *host, const char *user)
RETURN VALUES RETURN VALUES
0 ok 0 ok
1 ERROR; In this case the error is sent to the client. 1 ERROR; In this case the error is sent to the client.
*/ */
bool change_password(THD *thd, const char *host, const char *user, bool change_password(THD *thd, const char *host, const char *user,
char *new_password) char *new_password)
...@@ -1107,7 +1107,7 @@ bool change_password(THD *thd, const char *host, const char *user, ...@@ -1107,7 +1107,7 @@ bool change_password(THD *thd, const char *host, const char *user,
/* password should always be 0,16 or 45 chars; simple hack to avoid cracking */ /* password should always be 0,16 or 45 chars; simple hack to avoid cracking */
length=(uint) strlen(new_password); length=(uint) strlen(new_password);
if (length!=45) if (length!=45)
new_password[length & 16]=0; new_password[length & 16]=0;
...@@ -1133,8 +1133,8 @@ bool change_password(THD *thd, const char *host, const char *user, ...@@ -1133,8 +1133,8 @@ bool change_password(THD *thd, const char *host, const char *user,
if (!new_password[0]) if (!new_password[0])
acl_user->password=0; acl_user->password=0;
else else
acl_user->password=(char*) ""; // Point at something acl_user->password=(char*) ""; // Point at something
acl_cache->clear(1); // Clear locked hostname cache acl_cache->clear(1); // Clear locked hostname cache
VOID(pthread_mutex_unlock(&acl_cache->lock)); VOID(pthread_mutex_unlock(&acl_cache->lock));
...@@ -1321,7 +1321,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, ...@@ -1321,7 +1321,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
if (combo.password.str && combo.password.str[0]) if (combo.password.str && combo.password.str[0])
{ {
if ((combo.password.length != HASH_PASSWORD_LENGTH) if ((combo.password.length != HASH_PASSWORD_LENGTH)
&& combo.password.length != HASH_OLD_PASSWORD_LENGTH) && combo.password.length != HASH_OLD_PASSWORD_LENGTH)
{ {
my_error(ER_PASSWORD_NO_MATCH,MYF(0)); my_error(ER_PASSWORD_NO_MATCH,MYF(0));
...@@ -1329,7 +1329,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, ...@@ -1329,7 +1329,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
} }
password=combo.password.str; password=combo.password.str;
} }
table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
table->field[1]->store(combo.user.str,combo.user.length, system_charset_info); table->field[1]->store(combo.user.str,combo.user.length, system_charset_info);
table->file->index_init(0); table->file->index_init(0);
...@@ -1742,9 +1742,9 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip, ...@@ -1742,9 +1742,9 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip,
} }
else else
{ {
if ((host && !wild_case_compare(system_charset_info, if ((host && !wild_case_compare(system_charset_info,
host,grant_table->host)) || host,grant_table->host)) ||
(ip && !wild_case_compare(system_charset_info, (ip && !wild_case_compare(system_charset_info,
ip,grant_table->host))) ip,grant_table->host)))
found=grant_table; // Host ok found=grant_table; // Host ok
} }
...@@ -2676,9 +2676,9 @@ bool check_grant_db(THD *thd,const char *db) ...@@ -2676,9 +2676,9 @@ bool check_grant_db(THD *thd,const char *db)
GRANT_TABLE *grant_table = (GRANT_TABLE*) hash_element(&hash_tables,idx); GRANT_TABLE *grant_table = (GRANT_TABLE*) hash_element(&hash_tables,idx);
if (len < grant_table->key_length && if (len < grant_table->key_length &&
!memcmp(grant_table->hash_key,helping,len) && !memcmp(grant_table->hash_key,helping,len) &&
(thd->host && !wild_case_compare(system_charset_info, (thd->host && !wild_case_compare(system_charset_info,
thd->host,grant_table->host) || thd->host,grant_table->host) ||
(thd->ip && !wild_case_compare(system_charset_info, (thd->ip && !wild_case_compare(system_charset_info,
thd->ip,grant_table->host)))) thd->ip,grant_table->host))))
{ {
error=0; // Found match error=0; // Found match
...@@ -2764,7 +2764,7 @@ static uint command_lengths[]= ...@@ -2764,7 +2764,7 @@ static uint command_lengths[]=
}; };
int mysql_show_grants(THD *thd,LEX_USER *lex_user) int mysql_show_grants(THD *thd,LEX_USER *lex_user)
{ {
ulong want_access; ulong want_access;
uint counter,index; uint counter,index;
...@@ -2803,7 +2803,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2803,7 +2803,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
!my_strcasecmp(system_charset_info, lex_user->host.str, host)) !my_strcasecmp(system_charset_info, lex_user->host.str, host))
break; break;
} }
if (counter == acl_users.elements) if (counter == acl_users.elements)
{ {
my_printf_error(ER_NONEXISTING_GRANT,ER(ER_NONEXISTING_GRANT), my_printf_error(ER_NONEXISTING_GRANT,ER(ER_NONEXISTING_GRANT),
MYF(0),lex_user->user.str,lex_user->host.str); MYF(0),lex_user->user.str,lex_user->host.str);
...@@ -2836,13 +2836,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2836,13 +2836,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append("ALL PRIVILEGES",14); global.append("ALL PRIVILEGES",14);
else if (!(want_access & ~GRANT_ACL)) else if (!(want_access & ~GRANT_ACL))
global.append("USAGE",5); global.append("USAGE",5);
else else
{ {
bool found=0; bool found=0;
ulong j,test_access= want_access & ~GRANT_ACL; ulong j,test_access= want_access & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= GLOBAL_ACLS;counter++,j <<= 1) for (counter=0, j = SELECT_ACL;j <= GLOBAL_ACLS;counter++,j <<= 1)
{ {
if (test_access & j) if (test_access & j)
{ {
if (found) if (found)
global.append(", ",2); global.append(", ",2);
...@@ -2852,7 +2852,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2852,7 +2852,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
} }
} }
global.append (" ON *.* TO '",12); global.append (" ON *.* TO '",12);
global.append(lex_user->user.str,lex_user->user.length); global.append(lex_user->user.str,lex_user->user.length);
global.append ("'@'",3); global.append ("'@'",3);
global.append(lex_user->host.str,lex_user->host.length); global.append(lex_user->host.str,lex_user->host.length);
global.append ('\''); global.append ('\'');
...@@ -2901,9 +2901,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2901,9 +2901,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
(acl_user->user_resource.questions | acl_user->user_resource.updates | (acl_user->user_resource.questions | acl_user->user_resource.updates |
acl_user->user_resource.connections)) acl_user->user_resource.connections))
{ {
global.append(" WITH",5); global.append(" WITH",5);
if (want_access & GRANT_ACL) if (want_access & GRANT_ACL)
global.append(" GRANT OPTION",13); global.append(" GRANT OPTION",13);
if (acl_user->user_resource.questions) if (acl_user->user_resource.questions)
{ {
char buff[22], *p; // just as in int2str char buff[22], *p; // just as in int2str
...@@ -2950,7 +2950,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2950,7 +2950,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
!my_strcasecmp(system_charset_info, lex_user->host.str, host)) !my_strcasecmp(system_charset_info, lex_user->host.str, host))
{ {
want_access=acl_db->access; want_access=acl_db->access;
if (want_access) if (want_access)
{ {
String db(buff,sizeof(buff),system_charset_info); String db(buff,sizeof(buff),system_charset_info);
db.length(0); db.length(0);
...@@ -2976,10 +2976,10 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2976,10 +2976,10 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
db.append (" ON `",5); db.append (" ON `",5);
db.append(acl_db->db); db.append(acl_db->db);
db.append ("`.* TO '",8); db.append ("`.* TO '",8);
db.append(lex_user->user.str,lex_user->user.length); db.append(lex_user->user.str,lex_user->user.length);
db.append ("'@'",3); db.append ("'@'",3);
db.append(lex_user->host.str, lex_user->host.length); db.append(lex_user->host.str, lex_user->host.length);
db.append ('\''); db.append ('\'');
if (want_access & GRANT_ACL) if (want_access & GRANT_ACL)
db.append(" WITH GRANT OPTION",18); db.append(" WITH GRANT OPTION",18);
thd->packet.length(0); thd->packet.length(0);
...@@ -2998,7 +2998,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2998,7 +2998,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
for (index=0 ; index < hash_tables.records ; index++) for (index=0 ; index < hash_tables.records ; index++)
{ {
const char *user,*host; const char *user,*host;
GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&hash_tables,index); GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&hash_tables,index);
if (!(user=grant_table->user)) if (!(user=grant_table->user))
user=""; user="";
...@@ -3017,21 +3017,21 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -3017,21 +3017,21 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (test_all_bits(grant_table->privs,(TABLE_ACLS & ~GRANT_ACL))) if (test_all_bits(grant_table->privs,(TABLE_ACLS & ~GRANT_ACL)))
global.append("ALL PRIVILEGES",14); global.append("ALL PRIVILEGES",14);
else else
{ {
int found=0; int found=0;
ulong j,test_access= (want_access | grant_table->cols) & ~GRANT_ACL; ulong j,test_access= (want_access | grant_table->cols) & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= TABLE_ACLS; counter++,j <<= 1) for (counter=0, j = SELECT_ACL;j <= TABLE_ACLS; counter++,j <<= 1)
{ {
if (test_access & j) if (test_access & j)
{ {
if (found) if (found)
global.append(", ",2); global.append(", ",2);
found = 1; found = 1;
global.append(command_array[counter],command_lengths[counter]); global.append(command_array[counter],command_lengths[counter]);
if (grant_table->cols) if (grant_table->cols)
{ {
uint found_col=0; uint found_col=0;
for (uint col_index=0 ; for (uint col_index=0 ;
...@@ -3040,9 +3040,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -3040,9 +3040,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
{ {
GRANT_COLUMN *grant_column = (GRANT_COLUMN*) GRANT_COLUMN *grant_column = (GRANT_COLUMN*)
hash_element(&grant_table->hash_columns,col_index); hash_element(&grant_table->hash_columns,col_index);
if (grant_column->rights & j) if (grant_column->rights & j)
{ {
if (!found_col) if (!found_col)
{ {
global.append(" (",2); global.append(" (",2);
found_col=1; found_col=1;
...@@ -3064,12 +3064,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -3064,12 +3064,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(".",1); global.append(".",1);
global.append(grant_table->tname); global.append(grant_table->tname);
global.append(" TO '",5); global.append(" TO '",5);
global.append(lex_user->user.str,lex_user->user.length); global.append(lex_user->user.str,lex_user->user.length);
global.append("'@'",3); global.append("'@'",3);
global.append(lex_user->host.str,lex_user->host.length); global.append(lex_user->host.str,lex_user->host.length);
global.append('\''); global.append('\'');
if (want_access & GRANT_ACL) if (want_access & GRANT_ACL)
global.append(" WITH GRANT OPTION",18); global.append(" WITH GRANT OPTION",18);
thd->packet.length(0); thd->packet.length(0);
net_store_data(&thd->packet,global.ptr(),global.length()); net_store_data(&thd->packet,global.ptr(),global.length());
if (my_net_write(&thd->net,(char*) thd->packet.ptr(), if (my_net_write(&thd->net,(char*) thd->packet.ptr(),
......
...@@ -499,7 +499,10 @@ public: ...@@ -499,7 +499,10 @@ public:
uint check_loops_counter; //last id used to check loops uint check_loops_counter; //last id used to check loops
/* variables.transaction_isolation is reset to this after each commit */ /* variables.transaction_isolation is reset to this after each commit */
enum_tx_isolation session_tx_isolation; enum_tx_isolation session_tx_isolation;
char scramble[21]; // extend scramble to handle new auth // extend scramble to handle new auth
char scramble[SCRAMBLE41_LENGTH+1];
// old scramble is needed to handle old clients
char old_scramble[SCRAMBLE_LENGTH+1];
uint8 query_cache_type; // type of query cache processing uint8 query_cache_type; // type of query cache processing
bool slave_thread; bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted; bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
......
...@@ -44,8 +44,6 @@ ...@@ -44,8 +44,6 @@
#else #else
#define MIN_HANDSHAKE_SIZE 6 #define MIN_HANDSHAKE_SIZE 6
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
#define SCRAMBLE_LENGTH 8
#define SCRAMBLE41_LENGTH 20
#define MEM_ROOT_BLOCK_SIZE 8192 #define MEM_ROOT_BLOCK_SIZE 8192
#define MEM_ROOT_PREALLOC 8192 #define MEM_ROOT_PREALLOC 8192
...@@ -129,7 +127,7 @@ extern pthread_mutex_t LOCK_user_conn; ...@@ -129,7 +127,7 @@ extern pthread_mutex_t LOCK_user_conn;
static int get_or_create_user_conn(THD *thd, const char *user, static int get_or_create_user_conn(THD *thd, const char *user,
const char *host, const char *host,
USER_RESOURCES *mqh) USER_RESOURCES *mqh)
{ {
int return_val=0; int return_val=0;
uint temp_len, user_len, host_len; uint temp_len, user_len, host_len;
...@@ -163,7 +161,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, ...@@ -163,7 +161,7 @@ static int get_or_create_user_conn(THD *thd, const char *user,
uc->connections = 1; uc->connections = 1;
uc->questions=uc->updates=uc->conn_per_hour=0; uc->questions=uc->updates=uc->conn_per_hour=0;
uc->user_resources=*mqh; uc->user_resources=*mqh;
if (max_user_connections && mqh->connections > max_user_connections) if (max_user_connections && mqh->connections > max_user_connections)
uc->user_resources.connections = max_user_connections; uc->user_resources.connections = max_user_connections;
uc->intime=thd->thr_create_time; uc->intime=thd->thr_create_time;
if (hash_insert(&hash_user_connections, (byte*) uc)) if (hash_insert(&hash_user_connections, (byte*) uc))
...@@ -178,7 +176,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, ...@@ -178,7 +176,7 @@ static int get_or_create_user_conn(THD *thd, const char *user,
end: end:
(void) pthread_mutex_unlock(&LOCK_user_conn); (void) pthread_mutex_unlock(&LOCK_user_conn);
return return_val; return return_val;
} }
...@@ -189,16 +187,16 @@ end: ...@@ -189,16 +187,16 @@ end:
*/ */
static int check_user(THD *thd,enum_server_command command, const char *user, static int check_user(THD *thd,enum_server_command command, const char *user,
const char *passwd, const char *db, bool check_count, const char *passwd, const char *db, bool check_count,
bool do_send_error, char* crypted_scramble,int stage, bool do_send_error, char* crypted_scramble,int stage,
bool had_password,uint *cur_priv_version, bool had_password,uint *cur_priv_version,
ACL_USER** hint_user) ACL_USER** hint_user)
{ {
thd->db=0; thd->db=0;
thd->db_length=0; thd->db_length=0;
USER_RESOURCES ur; USER_RESOURCES ur;
/* We shall avoid dupplicate user allocations here */ /* We shall avoid dupplicate user allocations here */
if (!(thd->user)) if (!(thd->user))
if (!(thd->user = my_strdup(user, MYF(0)))) if (!(thd->user = my_strdup(user, MYF(0))))
{ {
...@@ -211,15 +209,15 @@ static int check_user(THD *thd,enum_server_command command, const char *user, ...@@ -211,15 +209,15 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
!(thd->client_capabilities & !(thd->client_capabilities &
CLIENT_LONG_PASSWORD),&ur,crypted_scramble, CLIENT_LONG_PASSWORD),&ur,crypted_scramble,
stage,cur_priv_version,hint_user); stage,cur_priv_version,hint_user);
DBUG_PRINT("info", DBUG_PRINT("info",
("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'", ("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
thd->client_capabilities, thd->max_client_packet_length, thd->client_capabilities, thd->max_client_packet_length,
thd->host_or_ip, thd->priv_user, thd->host_or_ip, thd->priv_user,
had_password ? "yes": "no", had_password ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*")); thd->master_access, thd->db ? thd->db : "*none*"));
/* in case we're going to retry we should not send error message at this point */ /* in case we're going to retry we should not send error message at this point */
if (thd->master_access & NO_ACCESS) if (thd->master_access & NO_ACCESS)
{ {
if (do_send_error) if (do_send_error)
...@@ -233,11 +231,11 @@ static int check_user(THD *thd,enum_server_command command, const char *user, ...@@ -233,11 +231,11 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
thd->host_or_ip, thd->host_or_ip,
had_password ? ER(ER_YES) : ER(ER_NO)); had_password ? ER(ER_YES) : ER(ER_NO));
return(1); // Error already given return(1); // Error already given
} }
else else
return(-1); // do not report error in special handshake return(-1); // do not report error in special handshake
} }
if (check_count) if (check_count)
{ {
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
...@@ -262,16 +260,16 @@ static int check_user(THD *thd,enum_server_command command, const char *user, ...@@ -262,16 +260,16 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
if ((ur.questions || ur.updates || ur.connections) && if ((ur.questions || ur.updates || ur.connections) &&
get_or_create_user_conn(thd,user,thd->host_or_ip,&ur)) get_or_create_user_conn(thd,user,thd->host_or_ip,&ur))
return -1; return -1;
if (thd->user_connect && thd->user_connect->user_resources.connections && if (thd->user_connect && thd->user_connect->user_resources.connections &&
check_for_max_user_connections(thd, thd->user_connect)) check_for_max_user_connections(thd, thd->user_connect))
return -1; return -1;
if (db && db[0]) if (db && db[0])
{ {
bool error=test(mysql_change_db(thd,db)); bool error=test(mysql_change_db(thd,db));
if (error && thd->user_connect) if (error && thd->user_connect)
decrease_user_connections(thd->user_connect); decrease_user_connections(thd->user_connect);
return error; return error;
} }
else else
send_ok(thd); // Ready to handle questions send_ok(thd); // Ready to handle questions
...@@ -296,7 +294,7 @@ extern "C" void free_user(struct user_conn *uc) ...@@ -296,7 +294,7 @@ extern "C" void free_user(struct user_conn *uc)
my_free((char*) uc,MYF(0)); my_free((char*) uc,MYF(0));
} }
void init_max_user_conn(void) void init_max_user_conn(void)
{ {
(void) hash_init(&hash_user_connections,system_charset_info,max_connections, (void) hash_init(&hash_user_connections,system_charset_info,max_connections,
0,0, 0,0,
...@@ -309,7 +307,7 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) ...@@ -309,7 +307,7 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{ {
int error=0; int error=0;
DBUG_ENTER("check_for_max_user_connections"); DBUG_ENTER("check_for_max_user_connections");
if (max_user_connections && if (max_user_connections &&
(max_user_connections <= (uint) uc->connections)) (max_user_connections <= (uint) uc->connections))
{ {
...@@ -317,7 +315,7 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) ...@@ -317,7 +315,7 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
error=1; error=1;
goto end; goto end;
} }
uc->connections++; uc->connections++;
if (uc->user_resources.connections && if (uc->user_resources.connections &&
uc->conn_per_hour++ >= uc->user_resources.connections) uc->conn_per_hour++ >= uc->user_resources.connections)
{ {
...@@ -441,7 +439,7 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them=false) ...@@ -441,7 +439,7 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them=false)
{ {
(void) pthread_mutex_lock(&LOCK_user_conn); (void) pthread_mutex_lock(&LOCK_user_conn);
if (lu) // for GRANT if (lu) // for GRANT
{ {
USER_CONN *uc; USER_CONN *uc;
uint temp_len=lu->user.length+lu->host.length+2; uint temp_len=lu->user.length+lu->host.length+2;
...@@ -530,9 +528,9 @@ check_connections(THD *thd) ...@@ -530,9 +528,9 @@ check_connections(THD *thd)
ulong pkt_len=0; ulong pkt_len=0;
{ {
/* buff[] needs to big enough to hold the server_version variable */ /* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + char buff[SERVER_VERSION_LENGTH +
SCRAMBLE_LENGTH+64],*end; SCRAMBLE_LENGTH+64],*end;
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION; CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION;
if (opt_using_transactions) if (opt_using_transactions)
...@@ -555,7 +553,7 @@ check_connections(THD *thd) ...@@ -555,7 +553,7 @@ check_connections(THD *thd)
int2store(end+3,thd->server_status); int2store(end+3,thd->server_status);
bzero(end+5,13); bzero(end+5,13);
end+=18; end+=18;
// At this point we write connection message and read reply // At this point we write connection message and read reply
if (net_write_command(net,(uchar) protocol_version, "", 0, buff, if (net_write_command(net,(uchar) protocol_version, "", 0, buff,
(uint) (end-buff)) || (uint) (end-buff)) ||
...@@ -588,7 +586,7 @@ check_connections(THD *thd) ...@@ -588,7 +586,7 @@ check_connections(THD *thd)
DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)", DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
pkt_len)); pkt_len));
inc_host_errors(&thd->remote.sin_addr); inc_host_errors(&thd->remote.sin_addr);
return(ER_HANDSHAKE_ERROR); return(ER_HANDSHAKE_ERROR);
} }
DBUG_PRINT("info", ("Reading user information over SSL layer")); DBUG_PRINT("info", ("Reading user information over SSL layer"));
if ((pkt_len=my_net_read(net)) == packet_error || if ((pkt_len=my_net_read(net)) == packet_error ||
...@@ -615,81 +613,73 @@ check_connections(THD *thd) ...@@ -615,81 +613,73 @@ check_connections(THD *thd)
char *user= (char*) net->read_pos+5; char *user= (char*) net->read_pos+5;
char *passwd= strend(user)+1; char *passwd= strend(user)+1;
char *db=0; char *db=0;
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB) if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
db=strend(passwd)+1; db=strend(passwd)+1;
/* We can get only old hash at this point */ /* We can get only old hash at this point */
if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH) if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH)
return ER_HANDSHAKE_ERROR; return ER_HANDSHAKE_ERROR;
if (thd->client_capabilities & CLIENT_INTERACTIVE) if (thd->client_capabilities & CLIENT_INTERACTIVE)
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout; thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) && if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions) opt_using_transactions)
thd->net.return_status= &thd->server_status; thd->net.return_status= &thd->server_status;
net->read_timeout=(uint) thd->variables.net_read_timeout; net->read_timeout=(uint) thd->variables.net_read_timeout;
char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble and hash */ char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble and hash */
ACL_USER* cached_user; ACL_USER* cached_user;
uint cur_priv_version; uint cur_priv_version;
/* Simple connect only for old clients. New clients always use secure auth */ /* Simple connect only for old clients. New clients always use secure auth */
bool simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION)); bool simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION));
/* Store information if we used password. passwd will be dammaged */ /* Store information if we used password. passwd will be dammaged */
bool using_password=test(passwd[0]); bool using_password=test(passwd[0]);
/* Check user permissions. If password failure we'll get scramble back */ /* Check user permissions. If password failure we'll get scramble back */
if (check_user(thd,COM_CONNECT, user, passwd, db, 1, simple_connect, if (check_user(thd,COM_CONNECT, user, passwd, db, 1, simple_connect,
prepared_scramble,0,using_password,&cur_priv_version,&cached_user)<0) prepared_scramble,0,using_password,&cur_priv_version,&cached_user)<0)
{ {
/* If The client is old we just have to return error */ /* If The client is old we just have to return error */
if (simple_connect) if (simple_connect)
return -1; return -1;
/* Store current used and database as they are erased with next packet */ /* Store current used and database as they are erased with next packet */
char tmp_user[USERNAME_LENGTH+1]; char tmp_user[USERNAME_LENGTH+1];
char tmp_db[NAME_LEN+1]; char tmp_db[NAME_LEN+1];
tmp_user[0]=0;
if (user) if (user)
{ strmake(tmp_user,user,USERNAME_LENGTH);
strncpy(tmp_user,user,USERNAME_LENGTH+1);
/* Extra safety if we have too long data */ tmp_db[0]=0;
tmp_user[USERNAME_LENGTH]=0;
}
else
tmp_user[0]=0;
if (db) if (db)
{ strmake(tmp_db,db,NAME_LEN);
strncpy(tmp_db,db,NAME_LEN+1);
tmp_db[NAME_LEN]=0;
}
else
tmp_db[0]=0;
/* Write hash and encrypted scramble to client */ /* Write hash and encrypted scramble to client */
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4)
|| net_flush(net)) || net_flush(net))
{ {
inc_host_errors(&thd->remote.sin_addr); inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR; return ER_HANDSHAKE_ERROR;
} }
/* Reading packet back */ /* Reading packet back */
if ((pkt_len=my_net_read(net)) == packet_error) if ((pkt_len=my_net_read(net)) == packet_error)
{ {
inc_host_errors(&thd->remote.sin_addr); inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR; return ER_HANDSHAKE_ERROR;
} }
/* We have to get very specific packet size */ /* We have to get very specific packet size */
if (pkt_len!=SCRAMBLE41_LENGTH) if (pkt_len!=SCRAMBLE41_LENGTH)
{ {
inc_host_errors(&thd->remote.sin_addr); inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR; return ER_HANDSHAKE_ERROR;
} }
/* Final attempt to check the user based on reply */ /* Final attempt to check the user based on reply */
if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos, if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
tmp_db, 1, 1,prepared_scramble,1,using_password,&cur_priv_version, tmp_db, 1, 1,prepared_scramble,1,using_password,&cur_priv_version,
&cached_user)) &cached_user))
return -1; return -1;
...@@ -796,7 +786,7 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -796,7 +786,7 @@ pthread_handler_decl(handle_one_connection,arg)
send_error(thd,net->last_errno,NullS); send_error(thd,net->last_errno,NullS);
statistic_increment(aborted_threads,&LOCK_status); statistic_increment(aborted_threads,&LOCK_status);
} }
end_thread: end_thread:
close_connection(net); close_connection(net);
end_thread(thd,1); end_thread(thd,1);
...@@ -854,7 +844,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) ...@@ -854,7 +844,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
while (fgets(buff, thd->net.max_packet, file)) while (fgets(buff, thd->net.max_packet, file))
{ {
uint length=(uint) strlen(buff); uint length=(uint) strlen(buff);
while (length && (my_isspace(system_charset_info, buff[length-1]) || while (length && (my_isspace(system_charset_info, buff[length-1]) ||
buff[length-1] == ';')) buff[length-1] == ';'))
length--; length--;
buff[length]=0; buff[length]=0;
...@@ -1043,7 +1033,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1043,7 +1033,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
char *user= (char*) packet; char *user= (char*) packet;
char *passwd= strend(user)+1; char *passwd= strend(user)+1;
char *db= strend(passwd)+1; char *db= strend(passwd)+1;
/* Save user and privileges */ /* Save user and privileges */
uint save_master_access=thd->master_access; uint save_master_access=thd->master_access;
uint save_db_access= thd->db_access; uint save_db_access= thd->db_access;
...@@ -1055,43 +1045,46 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1055,43 +1045,46 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
USER_CONN *save_uc= thd->user_connect; USER_CONN *save_uc= thd->user_connect;
bool simple_connect; bool simple_connect;
bool using_password; bool using_password;
ulong pkt_len=0; /* Length of reply packet */ ulong pkt_len=0; /* Length of reply packet */
/* Small check for incomming packet */ /* Small check for incomming packet */
if ((uint) ((uchar*) db - net->read_pos) > packet_length) if ((uint) ((uchar*) db - net->read_pos) > packet_length)
goto restore_user_err; goto restore_user_err;
/* Now we shall basically perform authentication again */ /* Now we shall basically perform authentication again */
/* We can get only old hash at this point */ /* We can get only old hash at this point */
if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH) if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH)
goto restore_user_err; goto restore_user_err;
char prepared_scramble[SCRAMBLE41_LENGTH+4];/* Buffer for scramble,hash */ char prepared_scramble[SCRAMBLE41_LENGTH+4];/* Buffer for scramble,hash */
ACL_USER* cached_user; /* Cached user */ ACL_USER* cached_user; /* Cached user */
uint cur_priv_version; /* Cached grant version */ uint cur_priv_version; /* Cached grant version */
/* Simple connect only for old clients. New clients always use sec. auth*/ /* Simple connect only for old clients. New clients always use sec. auth*/
simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION)); simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION));
/* Store information if we used password. passwd will be dammaged */ /* Store information if we used password. passwd will be dammaged */
using_password=test(passwd[0]); using_password=test(passwd[0]);
/* if (simple_connect) /* Restore scramble for old clients */
Check user permissions. If password failure we'll get scramble back memcpy(thd->scramble,thd->old_scramble,9);
Do not retry if we already have sent error (result>0)
*/ /*
Check user permissions. If password failure we'll get scramble back
Do not retry if we already have sent error (result>0)
*/
if (check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, simple_connect, if (check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, simple_connect,
prepared_scramble,0,using_password,&cur_priv_version,&cached_user)<0) prepared_scramble,0,using_password,&cur_priv_version,&cached_user)<0)
{ {
/* If The client is old we just have to have auth failure */ /* If The client is old we just have to have auth failure */
if (simple_connect) if (simple_connect)
goto restore_user; /* Error is already reported */ goto restore_user; /* Error is already reported */
/* Store current used and database as they are erased with next packet */ /* Store current used and database as they are erased with next packet */
char tmp_user[USERNAME_LENGTH+1]; char tmp_user[USERNAME_LENGTH+1];
char tmp_db[NAME_LEN+1]; char tmp_db[NAME_LEN+1];
...@@ -1099,33 +1092,33 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1099,33 +1092,33 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{ {
strncpy(tmp_user,user,USERNAME_LENGTH+1); strncpy(tmp_user,user,USERNAME_LENGTH+1);
/* Extra safety if we have too long data */ /* Extra safety if we have too long data */
tmp_user[USERNAME_LENGTH]=0; tmp_user[USERNAME_LENGTH]=0;
} }
else else
tmp_user[0]=0; tmp_user[0]=0;
if (db) if (db)
{ {
strncpy(tmp_db,db,NAME_LEN+1); strncpy(tmp_db,db,NAME_LEN+1);
tmp_db[NAME_LEN]=0; tmp_db[NAME_LEN]=0;
} }
else else
tmp_db[0]=0; tmp_db[0]=0;
/* Write hash and encrypted scramble to client */ /* Write hash and encrypted scramble to client */
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4)
|| net_flush(net)) || net_flush(net))
goto restore_user_err;
/* Reading packet back */
if ((pkt_len=my_net_read(net)) == packet_error)
goto restore_user_err; goto restore_user_err;
/* We have to get very specific packet size */ /* Reading packet back */
if (pkt_len!=SCRAMBLE41_LENGTH) if ((pkt_len=my_net_read(net)) == packet_error)
goto restore_user_err;
/* We have to get very specific packet size */
if (pkt_len!=SCRAMBLE41_LENGTH)
goto restore_user; goto restore_user;
/* Final attempt to check the user based on reply */ /* Final attempt to check the user based on reply */
if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos, if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
tmp_db, 0, 1,prepared_scramble,1,using_password,&cur_priv_version, tmp_db, 0, 1,prepared_scramble,1,using_password,&cur_priv_version,
&cached_user)) &cached_user))
goto restore_user; goto restore_user;
...@@ -1137,11 +1130,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1137,11 +1130,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
x_free((gptr) save_user); x_free((gptr) save_user);
thd->password=using_password; thd->password=using_password;
break; break;
/* Bad luck we shall restore old user */ /* Bad luck we shall restore old user */
restore_user_err: restore_user_err:
send_error(thd, ER_UNKNOWN_COM_ERROR); send_error(thd, ER_UNKNOWN_COM_ERROR);
restore_user: restore_user:
x_free(thd->user); x_free(thd->user);
x_free(thd->db); x_free(thd->db);
...@@ -1150,10 +1143,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1150,10 +1143,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->db=save_db; thd->db=save_db;
thd->db_length=save_db_length; thd->db_length=save_db_length;
thd->user=save_user; thd->user=save_user;
thd->priv_user=save_priv_user; thd->priv_user=save_priv_user;
break; break;
} }
case COM_EXECUTE: case COM_EXECUTE:
{ {
mysql_stmt_execute(thd, packet); mysql_stmt_execute(thd, packet);
...@@ -1444,7 +1437,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length) ...@@ -1444,7 +1437,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
packet_length--; packet_length--;
} }
char *pos=packet+packet_length; // Point at end null char *pos=packet+packet_length; // Point at end null
while (packet_length > 0 && while (packet_length > 0 &&
(pos[-1] == ';' || my_isspace(system_charset_info,pos[-1]))) (pos[-1] == ';' || my_isspace(system_charset_info,pos[-1])))
{ {
pos--; pos--;
...@@ -1496,7 +1489,7 @@ mysql_execute_command(THD *thd) ...@@ -1496,7 +1489,7 @@ mysql_execute_command(THD *thd)
if (thd->slave_thread) if (thd->slave_thread)
{ {
/* /*
Skip if we are in the slave thread, some table rules have been Skip if we are in the slave thread, some table rules have been
given and the table list says the query should not be replicated given and the table list says the query should not be replicated
*/ */
...@@ -1515,7 +1508,7 @@ mysql_execute_command(THD *thd) ...@@ -1515,7 +1508,7 @@ mysql_execute_command(THD *thd)
} }
#endif #endif
} }
/* /*
TODO: make derived tables processing 'inside' SELECT processing. TODO: make derived tables processing 'inside' SELECT processing.
TODO: solve problem with depended derived tables in subselects TODO: solve problem with depended derived tables in subselects
...@@ -1532,13 +1525,13 @@ mysql_execute_command(THD *thd) ...@@ -1532,13 +1525,13 @@ mysql_execute_command(THD *thd)
(SELECT_LEX_UNIT *) (SELECT_LEX_UNIT *)
cursor->derived, cursor->derived,
cursor))) cursor)))
{ {
if (res < 0 || thd->net.report_error) if (res < 0 || thd->net.report_error)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
} }
if ((&lex->select_lex != lex->all_selects_list && if ((&lex->select_lex != lex->all_selects_list &&
lex->unit.create_total_list(thd, lex, &tables)) || lex->unit.create_total_list(thd, lex, &tables)) ||
(table_rules_on && tables && thd->slave_thread && (table_rules_on && tables && thd->slave_thread &&
!tables_ok(thd,tables))) !tables_ok(thd,tables)))
...@@ -1568,7 +1561,7 @@ mysql_execute_command(THD *thd) ...@@ -1568,7 +1561,7 @@ mysql_execute_command(THD *thd)
unit->offset_limit_cnt= (ha_rows) unit->global_parameters->offset_limit; unit->offset_limit_cnt= (ha_rows) unit->global_parameters->offset_limit;
unit->select_limit_cnt= (ha_rows) (unit->global_parameters->select_limit+ unit->select_limit_cnt= (ha_rows) (unit->global_parameters->select_limit+
unit->global_parameters->offset_limit); unit->global_parameters->offset_limit);
if (unit->select_limit_cnt < if (unit->select_limit_cnt <
(ha_rows) unit->global_parameters->select_limit) (ha_rows) unit->global_parameters->select_limit)
unit->select_limit_cnt= HA_POS_ERROR; // no limit unit->select_limit_cnt= HA_POS_ERROR; // no limit
if (unit->select_limit_cnt == HA_POS_ERROR) if (unit->select_limit_cnt == HA_POS_ERROR)
...@@ -1714,7 +1707,7 @@ mysql_execute_command(THD *thd) ...@@ -1714,7 +1707,7 @@ mysql_execute_command(THD *thd)
res = show_binlog_info(thd); res = show_binlog_info(thd);
break; break;
} }
case SQLCOM_LOAD_MASTER_DATA: // sync with master case SQLCOM_LOAD_MASTER_DATA: // sync with master
if (check_global_access(thd, SUPER_ACL)) if (check_global_access(thd, SUPER_ACL))
goto error; goto error;
...@@ -1723,7 +1716,7 @@ mysql_execute_command(THD *thd) ...@@ -1723,7 +1716,7 @@ mysql_execute_command(THD *thd)
else else
res = load_master_data(thd); res = load_master_data(thd);
break; break;
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
case SQLCOM_SHOW_INNODB_STATUS: case SQLCOM_SHOW_INNODB_STATUS:
{ {
...@@ -1899,7 +1892,7 @@ mysql_execute_command(THD *thd) ...@@ -1899,7 +1892,7 @@ mysql_execute_command(THD *thd)
select_lex->db=tables->db; select_lex->db=tables->db;
if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege) || if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege) ||
check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv) || check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv) ||
check_merge_table_access(thd, tables->db, check_merge_table_access(thd, tables->db,
(TABLE_LIST *) (TABLE_LIST *)
lex->create_info.merge_list.first)) lex->create_info.merge_list.first))
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
...@@ -1981,7 +1974,7 @@ mysql_execute_command(THD *thd) ...@@ -1981,7 +1974,7 @@ mysql_execute_command(THD *thd)
res = show_binlogs(thd); res = show_binlogs(thd);
break; break;
} }
#endif #endif
case SQLCOM_SHOW_CREATE: case SQLCOM_SHOW_CREATE:
#ifdef DONT_ALLOW_SHOW_COMMANDS #ifdef DONT_ALLOW_SHOW_COMMANDS
send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
...@@ -2611,7 +2604,7 @@ mysql_execute_command(THD *thd) ...@@ -2611,7 +2604,7 @@ mysql_execute_command(THD *thd)
if (user->password.str && if (user->password.str &&
(strcmp(thd->user,user->user.str) || (strcmp(thd->user,user->user.str) ||
user->host.str && user->host.str &&
my_strcasecmp(system_charset_info, my_strcasecmp(system_charset_info,
user->host.str, thd->host_or_ip))) user->host.str, thd->host_or_ip)))
{ {
if (check_access(thd, UPDATE_ACL, "mysql",0,1)) if (check_access(thd, UPDATE_ACL, "mysql",0,1))
...@@ -3012,7 +3005,7 @@ mysql_init_query(THD *thd) ...@@ -3012,7 +3005,7 @@ mysql_init_query(THD *thd)
lex->select_lex.init_query(); lex->select_lex.init_query();
lex->value_list.empty(); lex->value_list.empty();
lex->param_list.empty(); lex->param_list.empty();
lex->unit.global_parameters= lex->unit.slave= lex->current_select= lex->unit.global_parameters= lex->unit.slave= lex->current_select=
lex->all_selects_list= &lex->select_lex; lex->all_selects_list= &lex->select_lex;
lex->select_lex.master= &lex->unit; lex->select_lex.master= &lex->unit;
lex->select_lex.prev= &lex->unit.slave; lex->select_lex.prev= &lex->unit.slave;
...@@ -3020,7 +3013,7 @@ mysql_init_query(THD *thd) ...@@ -3020,7 +3013,7 @@ mysql_init_query(THD *thd)
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list); lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
lex->olap=lex->describe=0; lex->olap=lex->describe=0;
lex->derived_tables= false; lex->derived_tables= false;
thd->check_loops_counter= thd->select_number= thd->check_loops_counter= thd->select_number=
lex->select_lex.select_number= 1; lex->select_lex.select_number= 1;
thd->free_list= 0; thd->free_list= 0;
thd->total_warn_count=0; // Warnings for this query thd->total_warn_count=0; // Warnings for this query
...@@ -3037,7 +3030,7 @@ mysql_init_select(LEX *lex) ...@@ -3037,7 +3030,7 @@ mysql_init_select(LEX *lex)
SELECT_LEX *select_lex= lex->current_select->select_lex(); SELECT_LEX *select_lex= lex->current_select->select_lex();
DBUG_ASSERT(select_lex->linkage != GLOBAL_OPTIONS_TYPE); DBUG_ASSERT(select_lex->linkage != GLOBAL_OPTIONS_TYPE);
select_lex->init_select(); select_lex->init_select();
select_lex->master_unit()->select_limit= select_lex->select_limit= select_lex->master_unit()->select_limit= select_lex->select_limit=
lex->thd->variables.select_limit; lex->thd->variables.select_limit;
lex->exchange= 0; lex->exchange= 0;
lex->result= 0; lex->result= 0;
...@@ -3067,7 +3060,7 @@ mysql_new_select(LEX *lex, bool move_down) ...@@ -3067,7 +3060,7 @@ mysql_new_select(LEX *lex, bool move_down)
} }
else else
select_lex->include_neighbour(lex->current_select); select_lex->include_neighbour(lex->current_select);
select_lex->master_unit()->global_parameters= select_lex; select_lex->master_unit()->global_parameters= select_lex;
DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE); DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list); select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
...@@ -3577,10 +3570,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table, ...@@ -3577,10 +3570,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table,
if (!alias) /* Alias is case sensitive */ if (!alias) /* Alias is case sensitive */
if (!(alias_str=thd->memdup(alias_str,table->table.length+1))) if (!(alias_str=thd->memdup(alias_str,table->table.length+1)))
DBUG_RETURN(0); DBUG_RETURN(0);
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(0); /* purecov: inspected */ DBUG_RETURN(0); /* purecov: inspected */
if (table->db.str) if (table->db.str)
{ {
ptr->db= table->db.str; ptr->db= table->db.str;
ptr->db_length= table->db.length; ptr->db_length= table->db.length;
...@@ -3596,7 +3589,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table, ...@@ -3596,7 +3589,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table,
ptr->db= empty_c_string; ptr->db= empty_c_string;
ptr->db_length= 0; ptr->db_length= 0;
} }
ptr->alias= alias_str; ptr->alias= alias_str;
if (lower_case_table_names) if (lower_case_table_names)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment