Commit acf89934 authored by monty@mashka.mysql.fi's avatar monty@mashka.mysql.fi

Fixed problem when connecting to user without a password.

Fixed problem with LIKE and BINARY
parent 3695c641
...@@ -597,3 +597,4 @@ vio/test-sslclient ...@@ -597,3 +597,4 @@ vio/test-sslclient
vio/test-sslserver vio/test-sslserver
vio/viotest-ssl vio/viotest-ssl
scripts/fill_help_tables.sql scripts/fill_help_tables.sql
scripts/fill_help_tables
...@@ -991,7 +991,8 @@ int do_sync_with_master2(const char* p) ...@@ -991,7 +991,8 @@ int do_sync_with_master2(const char* p)
mysql_errno(mysql), mysql_error(mysql)); mysql_errno(mysql), mysql_error(mysql));
if (!(last_result = res = mysql_store_result(mysql))) if (!(last_result = res = mysql_store_result(mysql)))
die("line %u: mysql_store_result() returned NULL", start_lineno); die("line %u: mysql_store_result() returned NULL for '%s'", start_lineno,
query_buf);
if (!(row = mysql_fetch_row(res))) if (!(row = mysql_fetch_row(res)))
die("line %u: empty result in %s", start_lineno, query_buf); die("line %u: empty result in %s", start_lineno, query_buf);
if (!row[0]) if (!row[0])
...@@ -1021,17 +1022,19 @@ int do_save_master_pos() ...@@ -1021,17 +1022,19 @@ int do_save_master_pos()
MYSQL_RES* res; MYSQL_RES* res;
MYSQL_ROW row; MYSQL_ROW row;
MYSQL* mysql = &cur_con->mysql; MYSQL* mysql = &cur_con->mysql;
const char *query;
int rpl_parse; int rpl_parse;
rpl_parse = mysql_rpl_parse_enabled(mysql); rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql); mysql_disable_rpl_parse(mysql);
if (mysql_query(mysql, "show master status")) if (mysql_query(mysql, query= "show master status"))
die("At line %u: failed in show master status: %d: %s", start_lineno, die("At line %u: failed in show master status: %d: %s", start_lineno,
mysql_errno(mysql), mysql_error(mysql)); mysql_errno(mysql), mysql_error(mysql));
if (!(last_result =res = mysql_store_result(mysql))) if (!(last_result =res = mysql_store_result(mysql)))
die("line %u: mysql_store_result() retuned NULL", start_lineno); die("line %u: mysql_store_result() retuned NULL for '%s'", start_lineno,
query);
if (!(row = mysql_fetch_row(res))) if (!(row = mysql_fetch_row(res)))
die("line %u: empty result in show master status", start_lineno); die("line %u: empty result in show master status", start_lineno);
strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1); strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
......
...@@ -215,30 +215,31 @@ my_bool my_connect(my_socket s, const struct sockaddr *name, ...@@ -215,30 +215,31 @@ my_bool my_connect(my_socket s, const struct sockaddr *name,
if (res == 0) /* Connected quickly! */ if (res == 0) /* Connected quickly! */
return(0); return(0);
/* Otherwise, our connection is "in progress." We can use /*
* the select() call to wait up to a specified period of time Otherwise, our connection is "in progress." We can use
* for the connection to suceed. If select() returns 0 the select() call to wait up to a specified period of time
* (after waiting howevermany seconds), our socket never became for the connection to succeed. If select() returns 0
* writable (host is probably unreachable.) Otherwise, if (after waiting howevermany seconds), our socket never became
* select() returns 1, then one of two conditions exist: writable (host is probably unreachable.) Otherwise, if
* select() returns 1, then one of two conditions exist:
* 1. An error occured. We use getsockopt() to check for this.
* 2. The connection was set up sucessfully: getsockopt() will 1. An error occured. We use getsockopt() to check for this.
* return 0 as an error. 2. The connection was set up sucessfully: getsockopt() will
* return 0 as an error.
* Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
* who posted this method of timing out a connect() in Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
* comp.unix.programmer on August 15th, 1997. who posted this method of timing out a connect() in
comp.unix.programmer on August 15th, 1997.
*/ */
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
*/ */
start_time = time(NULL); start_time = time(NULL);
for (;;) for (;;)
...@@ -258,9 +259,10 @@ my_bool my_connect(my_socket s, const struct sockaddr *name, ...@@ -258,9 +259,10 @@ my_bool my_connect(my_socket s, const struct sockaddr *name,
return 1; return 1;
} }
/* select() returned something more interesting than zero, let's /*
* see if we have any errors. If the next two statements pass, select() returned something more interesting than zero, let's
* we've got an open socket! see if we have any errors. If the next two statements pass,
we've got an open socket!
*/ */
s_err=0; s_err=0;
...@@ -276,6 +278,7 @@ my_bool my_connect(my_socket s, const struct sockaddr *name, ...@@ -276,6 +278,7 @@ my_bool my_connect(my_socket s, const struct sockaddr *name,
#endif #endif
} }
/* /*
Create a named pipe connection Create a named pipe connection
*/ */
...@@ -348,6 +351,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, ...@@ -348,6 +351,7 @@ 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
...@@ -357,6 +361,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, ...@@ -357,6 +361,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host,
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)
{ {
...@@ -401,58 +406,60 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) ...@@ -401,58 +406,60 @@ 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)))
{ {
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)))
{ {
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)))
{ {
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))))
{ {
error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR; error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR;
goto err; goto err;
} }
/* /*
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;
} }
/* /*
Wait of answer from server Wait of answer from server
*/ */
if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) != WAIT_OBJECT_0) if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) !=
WAIT_OBJECT_0)
{ {
error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR; error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR;
goto err; goto err;
} }
/* /*
Get number of connection Get number of connection
*/ */
connect_number = uint4korr(handle_connect_map);/*WAX2*/ connect_number = uint4korr(handle_connect_map);/*WAX2*/
p = int2str(connect_number, connect_number_char, 10); p= int2str(connect_number, connect_number_char, 10);
/* /*
The name of event and file-mapping events create agree next rule: The name of event and file-mapping events create agree next rule:
shared_memory_base_name+unique_part+number_of_connection shared_memory_base_name+unique_part+number_of_connection
Where: Where:
shared_memory_base_name is uniquel value for each server shared_memory_base_name is uniquel value for each server
unique_part is uniquel value for each object (events and file-mapping) unique_part is uniquel value for each object (events and file-mapping)
number_of_connection is number of connection between server and client number_of_connection is number of connection between server and client
*/ */
suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char, suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
"_",NullS); "_",NullS);
strmov(suffix_pos, "DATA"); strmov(suffix_pos, "DATA");
...@@ -495,33 +502,46 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) ...@@ -495,33 +502,46 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
error_allow = CR_SHARED_MEMORY_EVENT_ERROR; error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
goto err2; goto err2;
} }
/* /*
Set event that server should send data Set event that server should send data
*/ */
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_read,event_client_wrote,event_client_read); event_server_wrote,
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)
if (event_server_wrote) CloseHandle(event_server_wrote); CloseHandle(event_server_read);
if (event_client_read) CloseHandle(event_client_read); if (event_server_wrote)
if (event_client_wrote) CloseHandle(event_client_wrote); CloseHandle(event_server_wrote);
if (handle_map) UnmapViewOfFile(handle_map); if (event_client_read)
if (handle_file_map) CloseHandle(handle_file_map); CloseHandle(event_client_read);
if (event_client_wrote)
CloseHandle(event_client_wrote);
if (handle_map)
UnmapViewOfFile(handle_map);
if (handle_file_map)
CloseHandle(handle_file_map);
} }
err: err:
if (error_allow) error_code = GetLastError(); if (error_allow)
if (event_connect_request) CloseHandle(event_connect_request); error_code = GetLastError();
if (event_connect_answer) CloseHandle(event_connect_answer); if (event_connect_request)
if (handle_connect_map) UnmapViewOfFile(handle_connect_map); CloseHandle(event_connect_request);
if (handle_connect_file_map) CloseHandle(handle_connect_file_map); if (event_connect_answer)
CloseHandle(event_connect_answer);
if (handle_connect_map)
UnmapViewOfFile(handle_connect_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;
...@@ -532,11 +552,12 @@ err: ...@@ -532,11 +552,12 @@ err:
return(INVALID_HANDLE_VALUE); return(INVALID_HANDLE_VALUE);
} }
return(handle_map); return(handle_map);
}; }
#endif #endif
/***************************************************************************** /*****************************************************************************
read a packet from server. Give error message if socket was down Read a packet from server. Give error message if socket was down
or packet is an error message or packet is an error message
*****************************************************************************/ *****************************************************************************/
...@@ -1796,10 +1817,11 @@ void STDCALL mysql_once_init(void) ...@@ -1796,10 +1817,11 @@ void STDCALL mysql_once_init(void)
#endif #endif
} }
/**************************************************************************
/*
Fill in SSL part of MYSQL structure and set 'use_ssl' flag. Fill in SSL part of MYSQL structure and set 'use_ssl' flag.
NB! Errors are not reported until you do mysql_real_connect. NB! Errors are not reported until you do mysql_real_connect.
**************************************************************************/ */
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME)) #define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
...@@ -1822,10 +1844,10 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , ...@@ -1822,10 +1844,10 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
} }
/************************************************************************** /*
Free strings in the SSL structure and clear 'use_ssl' flag. Free strings in the SSL structure and clear 'use_ssl' flag.
NB! Errors are not reported until you do mysql_real_connect. NB! Errors are not reported until you do mysql_real_connect.
**************************************************************************/ */
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
static void static void
...@@ -1847,6 +1869,75 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) ...@@ -1847,6 +1869,75 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
} }
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
/*
Handle password authentication
*/
static my_bool mysql_autenticate(MYSQL *mysql, const char *passwd)
{
ulong pkt_length;
NET *net= &mysql->net;
char buff[SCRAMBLE41_LENGTH];
char password_hash[SCRAMBLE41_LENGTH]; /* Used for storage of stage1 hash */
/* We shall only query server if it expect us to do so */
if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
/*
This should always happen with new server unless empty password
OK/Error packets have zero as the first char
*/
if (pkt_length == 24 && net->read_pos[0])
{
/* Old passwords will have '*' at the first byte of hash */
if (net->read_pos[0] != '*')
{
/* Build full password hash as it is required to decode scramble */
password_hash_stage1(buff, passwd);
/* Store copy as we'll need it later */
memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
/* Finally hash complete password using hash we got from server */
password_hash_stage2(password_hash,(const char*) net->read_pos);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
password_hash, SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Encode scramble with password. Recycle buffer */
password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
}
else
{
/* Create password to decode scramble */
create_key_from_old_password(passwd,password_hash);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
password_hash, SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Finally scramble decoded scramble with password */
scramble(buff, mysql->scramble_buff, passwd,0);
}
/* Write second package of authentication */
if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Read what server thinks about out new auth message report */
if (net_safe_read(mysql) == packet_error)
goto error;
}
}
return 0;
error:
return 1;
}
/************************************************************************** /**************************************************************************
Connect to sql server Connect to sql server
If host == 0 then use localhost If host == 0 then use localhost
...@@ -1884,7 +1975,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -1884,7 +1975,6 @@ 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[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;
...@@ -1930,7 +2020,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -1930,7 +2020,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
passwd=mysql->options.password; passwd=mysql->options.password;
#ifndef DONT_USE_MYSQL_PWD #ifndef DONT_USE_MYSQL_PWD
if (!passwd) if (!passwd)
passwd=getenv("MYSQL_PWD"); /* get it from environment (haneke) */ passwd=getenv("MYSQL_PWD"); /* get it from environment */
#endif #endif
} }
if (!db || !db[0]) if (!db || !db[0])
...@@ -1944,10 +2034,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -1944,10 +2034,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
mysql->server_status=SERVER_STATUS_AUTOCOMMIT; mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
/* /*
** Grab a socket and connect it to the server Grab a socket and connect it to the server
*/ */
#if defined(HAVE_SMEM) #if defined(HAVE_SMEM)
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)) ==
...@@ -1961,9 +2052,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -1961,9 +2052,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
(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
{ {
...@@ -1974,10 +2063,12 @@ Try also with PIPE or TCP/IP ...@@ -1974,10 +2063,12 @@ Try also with PIPE or TCP/IP
host_info=(char*) ER(CR_SHARED_MEMORY_CONNECTION); host_info=(char*) ER(CR_SHARED_MEMORY_CONNECTION);
} }
} else } else
#endif //HAVE_SMEM #endif /* HAVE_SMEM */
#if defined(HAVE_SYS_UN_H) #if defined(HAVE_SYS_UN_H)
if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_SOCKET)&& if ((!mysql->options.protocol ||
(!host || !strcmp(host,LOCAL_HOST)) && (unix_socket || mysql_unix_port)) mysql->options.protocol == MYSQL_PROTOCOL_SOCKET)&&
(!host || !strcmp(host,LOCAL_HOST)) &&
(unix_socket || mysql_unix_port))
{ {
host=LOCAL_HOST; host=LOCAL_HOST;
if (!unix_socket) if (!unix_socket)
...@@ -1997,7 +2088,8 @@ Try also with PIPE or TCP/IP ...@@ -1997,7 +2088,8 @@ Try also with PIPE or TCP/IP
if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
mysql->options.connect_timeout)) mysql->options.connect_timeout))
{ {
DBUG_PRINT("error",("Got error %d on connect to local server",socket_errno)); DBUG_PRINT("error",("Got error %d on connect to local server",
socket_errno));
net->last_errno=CR_CONNECTION_ERROR; net->last_errno=CR_CONNECTION_ERROR;
sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno);
goto error; goto error;
...@@ -2007,9 +2099,12 @@ Try also with PIPE or TCP/IP ...@@ -2007,9 +2099,12 @@ Try also with PIPE or TCP/IP
} }
else else
#elif defined(__WIN__) #elif defined(__WIN__)
if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_PIPE)&& {
if ((!mysql->options.protocol ||
mysql->options.protocol == MYSQL_PROTOCOL_PIPE)&&
((unix_socket || !host && is_NT() || ((unix_socket || !host && is_NT() ||
host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||!have_tcpip))&&(!net->vio)) host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||! have_tcpip))&&
(!net->vio))
{ {
sock=0; sock=0;
if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout,
...@@ -2025,9 +2120,7 @@ Try also with PIPE or TCP/IP ...@@ -2025,9 +2120,7 @@ Try also with PIPE or TCP/IP
(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
{ {
...@@ -2036,8 +2129,10 @@ Try also with PIPE or TCP/IP ...@@ -2036,8 +2129,10 @@ Try also with PIPE or TCP/IP
unix_socket); unix_socket);
} }
} }
}
#endif #endif
if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_TCP)&&(!net->vio)) if ((!mysql->options.protocol ||
mysql->options.protocol == MYSQL_PROTOCOL_TCP)&&(!net->vio))
{ {
unix_socket=0; /* This is not used */ unix_socket=0; /* This is not used */
if (!port) if (!port)
...@@ -2058,7 +2153,7 @@ Try also with PIPE or TCP/IP ...@@ -2058,7 +2153,7 @@ Try also with PIPE or TCP/IP
sock_addr.sin_family = AF_INET; sock_addr.sin_family = AF_INET;
/* /*
** The server name may be a host name or IP address The server name may be a host name or IP address
*/ */
if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE)
...@@ -2086,20 +2181,20 @@ Try also with PIPE or TCP/IP ...@@ -2086,20 +2181,20 @@ Try also with PIPE or TCP/IP
if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
mysql->options.connect_timeout)) mysql->options.connect_timeout))
{ {
DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,host)); DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,
host));
net->last_errno= CR_CONN_HOST_ERROR; net->last_errno= CR_CONN_HOST_ERROR;
sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno); sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno);
goto error; goto error;
} }
} }
else else if (!net->vio)
if (!net->vio)
{ {
DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol)); DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol));
net->last_errno= CR_CONN_UNKNOW_PROTOCOL; net->last_errno= CR_CONN_UNKNOW_PROTOCOL;
sprintf(net->last_error ,ER(CR_CONN_UNKNOW_PROTOCOL)); sprintf(net->last_error ,ER(CR_CONN_UNKNOW_PROTOCOL));
goto error; goto error;
}; }
if (!net->vio || my_net_init(net, net->vio)) if (!net->vio || my_net_init(net, net->vio))
{ {
...@@ -2167,7 +2262,6 @@ Try also with PIPE or TCP/IP ...@@ -2167,7 +2262,6 @@ Try also with PIPE or TCP/IP
if (!(mysql->charset = if (!(mysql->charset =
get_charset((uint8) mysql->server_language, MYF(0)))) get_charset((uint8) mysql->server_language, MYF(0))))
mysql->charset = default_charset_info; /* shouldn't be fatal */ mysql->charset = default_charset_info; /* shouldn't be fatal */
} }
else else
mysql->charset=default_charset_info; mysql->charset=default_charset_info;
...@@ -2349,59 +2443,9 @@ Try also with PIPE or TCP/IP ...@@ -2349,59 +2443,9 @@ Try also with PIPE or TCP/IP
goto error; goto error;
} }
/* We shall only query sever if it expect us to do so */ if (mysql_autenticate(mysql, passwd))
if ( (pkt_length=net_safe_read(mysql)) == packet_error)
goto error; goto error;
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
/* This should always happen with new server unless empty password */
if (pkt_length==24 && net->read_pos[0])
/* OK/Error packets have zero as the first char */
{
/* Old passwords will have '*' at the first byte of hash */
if (net->read_pos[0] != '*')
{
/* Build full password hash as it is required to decode scramble */
password_hash_stage1(buff, passwd);
/* Store copy as we'll need it later */
memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
/* Finally hash complete password using hash we got from server */
password_hash_stage2(password_hash,(const char*) net->read_pos);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
password_hash, SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Encode scramble with password. Recycle buffer */
password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
}
else
{
/* Create password to decode scramble */
create_key_from_old_password(passwd,password_hash);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
password_hash, SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Finally scramble decoded scramble with password */
scramble(buff, mysql->scramble_buff, passwd,0);
}
/* Write second package of authentication */
if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Read What server thinks about out new auth message report */
if (net_safe_read(mysql) == packet_error)
goto error;
}
}
/* 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 (mysql->options.max_allowed_packet) if (mysql->options.max_allowed_packet)
...@@ -2521,10 +2565,6 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, ...@@ -2521,10 +2565,6 @@ 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;
char password_hash[SCRAMBLE41_LENGTH]; /* Used for tmp storage of stage1 hash */
NET *net= &mysql->net;
DBUG_ENTER("mysql_change_user"); DBUG_ENTER("mysql_change_user");
if (!user) if (!user)
...@@ -2553,83 +2593,36 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, ...@@ -2553,83 +2593,36 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
*end=0; /* Store zero length scramble */ *end=0; /* Store zero length scramble */
} }
else else
{
/* /*
Real scramble is only sent to old servers. This can be blocked Real scramble is only sent to old servers. This can be blocked
by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
*/ */
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 */ if (mysql_autenticate(mysql, passwd))
if ( (pkt_length=net_safe_read(mysql)) == packet_error)
goto error; goto error;
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) /* Free old connect information */
{
/* This should always happen with new server unless empty password */
if (pkt_length==24 && net->read_pos[0])
/* Err/OK messages has first character=0 */
{
/* Old passwords will have zero at the first byte of hash */
if (net->read_pos[0] != '*')
{
/* Build full password hash as it is required to decode scramble */
password_hash_stage1(buff, passwd);
/* Store copy as we'll need it later */
memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
/* Finally hash complete password using hash we got from server */
password_hash_stage2(password_hash, (const char*) net->read_pos);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((const char*) net->read_pos+4, mysql->scramble_buff,
password_hash, SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Encode scramble with password. Recycle buffer */
password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
}
else
{
/* Create password to decode scramble */
create_key_from_old_password(passwd,password_hash);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
password_hash, SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Finally scramble decoded scramble with password */
scramble(buff, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
}
/* Write second package of authentication */
if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Read What server thinks about out new auth message report */
if (net_safe_read(mysql) == packet_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));
/* alloc new connect information */
mysql->user= my_strdup(user,MYF(MY_WME)); mysql->user= my_strdup(user,MYF(MY_WME));
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);
} }
...@@ -5102,6 +5095,7 @@ static void fetch_result_datetime(MYSQL_BIND *param, uchar **row) ...@@ -5102,6 +5095,7 @@ static void fetch_result_datetime(MYSQL_BIND *param, uchar **row)
*row+= read_binary_datetime(tm, row); *row+= read_binary_datetime(tm, row);
} }
static void fetch_result_str(MYSQL_BIND *param, uchar **row) static void fetch_result_str(MYSQL_BIND *param, uchar **row)
{ {
ulong length= net_field_length(row); ulong length= net_field_length(row);
...@@ -5110,7 +5104,7 @@ static void fetch_result_str(MYSQL_BIND *param, uchar **row) ...@@ -5110,7 +5104,7 @@ static void fetch_result_str(MYSQL_BIND *param, uchar **row)
/* Add an end null if there is room in the buffer */ /* Add an end null if there is room in the buffer */
if (copy_length != param->buffer_length) if (copy_length != param->buffer_length)
*(param->buffer+copy_length)= '\0'; *(param->buffer+copy_length)= '\0';
*param->length= length; // return total length *param->length= length; /* return total length */
*row+= length; *row+= length;
} }
......
...@@ -373,12 +373,21 @@ bool Protocol::send_fields(List<Item> *list, uint flag) ...@@ -373,12 +373,21 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
Send_field server_field; Send_field server_field;
item->make_field(&server_field); item->make_field(&server_field);
client_field->db= strdup_root(alloc, server_field.db_name);
client_field->table= strdup_root(alloc, server_field.table_name); client_field->table= strdup_root(alloc, server_field.table_name);
client_field->name= strdup_root(alloc,server_field.col_name); client_field->name= strdup_root(alloc, server_field.col_name);
client_field->org_table= strdup_root(alloc, server_field.org_table_name);
client_field->org_name= strdup_root(alloc, server_field.org_col_name);
client_field->length= server_field.length; client_field->length= server_field.length;
client_field->type= server_field.type; client_field->type= server_field.type;
client_field->flags= server_field.flags; client_field->flags= server_field.flags;
client_field->decimals= server_field.decimals; client_field->decimals= server_field.decimals;
client_field->db_length= strlen(client_field->db);
client_field->table_length= strlen(client_field->table);
client_field->name_length= strlen(client_field->name);
client_field->org_name_length= strlen(client_field->org_name);
client_field->org_table_length= strlen(client_field->org_table);
client_field->charsetnr= server_field.charsetnr;
if (INTERNAL_NUM_FIELD(client_field)) if (INTERNAL_NUM_FIELD(client_field))
client_field->flags|= NUM_FLAG; client_field->flags|= NUM_FLAG;
......
...@@ -4,9 +4,6 @@ reset master; ...@@ -4,9 +4,6 @@ reset master;
reset slave; reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave; start slave;
stop slave;
reset master;
drop table if exists t1;
create table t1(n char(30)); create table t1(n char(30));
set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1; set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1;
set @s1:='This is a test', @r1:=12.5, @r2:=-12.5; set @s1:='This is a test', @r1:=12.5, @r2:=-12.5;
...@@ -23,7 +20,6 @@ set @q:='abc'; ...@@ -23,7 +20,6 @@ set @q:='abc';
insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2')); insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'));
set @a:=5; set @a:=5;
insert into t1 values (@a),(@a); insert into t1 values (@a),(@a);
start slave;
select * from t1; select * from t1;
n n
12345678901234 12345678901234
...@@ -59,20 +55,20 @@ slave-bin.000001 396 User var 2 396 @r1=12.5 ...@@ -59,20 +55,20 @@ slave-bin.000001 396 User var 2 396 @r1=12.5
slave-bin.000001 439 User var 2 439 @r2=-12.5 slave-bin.000001 439 User var 2 439 @r2=-12.5
slave-bin.000001 482 Query 1 482 use `test`; insert into t1 values (@r1), (@r2) slave-bin.000001 482 Query 1 482 use `test`; insert into t1 values (@r1), (@r2)
slave-bin.000001 551 User var 2 551 @s1='This is a test' slave-bin.000001 551 User var 2 551 @s1='This is a test'
slave-bin.000001 601 User var 2 601 @s2='' slave-bin.000001 600 User var 2 600 @s2=''
slave-bin.000001 637 User var 2 637 @s3='abc'def' slave-bin.000001 635 User var 2 635 @s3='abc'def'
slave-bin.000001 680 User var 2 680 @s4='abc\def' slave-bin.000001 677 User var 2 677 @s4='abc\def'
slave-bin.000001 723 User var 2 723 @s5='abc'def' slave-bin.000001 719 User var 2 719 @s5='abc'def'
slave-bin.000001 766 Query 1 766 use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5) slave-bin.000001 761 Query 1 761 use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5)
slave-bin.000001 856 User var 2 856 @n1=NULL slave-bin.000001 851 User var 2 851 @n1=NULL
slave-bin.000001 882 Query 1 882 use `test`; insert into t1 values (@n1) slave-bin.000001 877 Query 1 877 use `test`; insert into t1 values (@n1)
slave-bin.000001 944 Query 1 944 use `test`; insert into t1 values (@n2) slave-bin.000001 939 Query 1 939 use `test`; insert into t1 values (@n2)
slave-bin.000001 1006 Query 1 1006 use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1) slave-bin.000001 1001 Query 1 1001 use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1)
slave-bin.000001 1094 User var 2 1094 @a='2' slave-bin.000001 1089 User var 2 1089 @a='2'
slave-bin.000001 1130 Query 1 1130 use `test`; insert into t1 values (@a+(@b:=@a+1)) slave-bin.000001 1124 Query 1 1124 use `test`; insert into t1 values (@a+(@b:=@a+1))
slave-bin.000001 1202 User var 2 1202 @q='abc' slave-bin.000001 1196 User var 2 1196 @q='abc'
slave-bin.000001 1240 Query 1 1240 use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2')) slave-bin.000001 1233 Query 1 1233 use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'))
slave-bin.000001 1344 User var 2 1344 @a=5 slave-bin.000001 1337 User var 2 1337 @a=5
slave-bin.000001 1386 Query 1 1386 use `test`; insert into t1 values (@a),(@a) slave-bin.000001 1379 Query 1 1379 use `test`; insert into t1 values (@a),(@a)
drop table t1; drop table t1;
stop slave; stop slave;
...@@ -130,6 +130,10 @@ select d from t1 having d like "%HELLO%"; ...@@ -130,6 +130,10 @@ select d from t1 having d like "%HELLO%";
d d
HELLO HELLO
HELLO MY HELLO MY
select d from t1 having d like "%HE%LLO%";
d
HELLO
HELLO MY
select t from t1 order by t; select t from t1 order by t;
t t
NULL NULL
......
#
# Test of replicating user variables
#
source include/master-slave.inc; source include/master-slave.inc;
connection master;
save_master_pos;
connection slave;
sync_with_master;
stop slave;
reset master;
connection master;
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1(n char(30)); create table t1(n char(30));
set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1; set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1;
set @s1:='This is a test', @r1:=12.5, @r2:=-12.5; set @s1:='This is a test', @r1:=12.5, @r2:=-12.5;
...@@ -27,7 +21,6 @@ set @a:=5; ...@@ -27,7 +21,6 @@ set @a:=5;
insert into t1 values (@a),(@a); insert into t1 values (@a),(@a);
save_master_pos; save_master_pos;
connection slave; connection slave;
start slave;
sync_with_master; sync_with_master;
select * from t1; select * from t1;
show binlog events from 141; show binlog events from 141;
......
...@@ -87,6 +87,7 @@ select b from t1 where b like "%HELLO%"; ...@@ -87,6 +87,7 @@ select b from t1 where b like "%HELLO%";
select d from t1 where d like "%HELLO%"; select d from t1 where d like "%HELLO%";
select c from t1 having c like "%HELLO%"; select c from t1 having c like "%HELLO%";
select d from t1 having d like "%HELLO%"; select d from t1 having d like "%HELLO%";
select d from t1 having d like "%HE%LLO%";
select t from t1 order by t; select t from t1 order by t;
select c from t1 order by c; select c from t1 order by c;
select b from t1 order by b; select b from t1 order by b;
......
...@@ -1203,18 +1203,22 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1203,18 +1203,22 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
max_length= (*ref)->max_length; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals; decimals= (*ref)->decimals;
set_charset((*ref)->charset());
fixed= 1; fixed= 1;
if (ref && (*ref)->check_cols(1)) if (ref && (*ref)->check_cols(1))
return 1; return 1;
return 0; return 0;
} }
bool Item_default_value::eq(const Item *item, bool binary_cmp) const bool Item_default_value::eq(const Item *item, bool binary_cmp) const
{ {
return item->type() == DEFAULT_VALUE_ITEM && return item->type() == DEFAULT_VALUE_ITEM &&
((Item_default_value *)item)->arg->eq(arg, binary_cmp); ((Item_default_value *)item)->arg->eq(arg, binary_cmp);
} }
bool Item_default_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items) bool Item_default_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items)
{ {
if (!arg) if (!arg)
......
...@@ -1129,11 +1129,16 @@ void in_string::set(uint pos,Item *item) ...@@ -1129,11 +1129,16 @@ void in_string::set(uint pos,Item *item)
String *res=item->val_str(str); String *res=item->val_str(str);
if (res && res != str) if (res && res != str)
*str= *res; *str= *res;
// BAR TODO: I'm not sure this is absolutely correct
if (!str->charset()) if (!str->charset())
str->set_charset(default_charset_info); {
CHARSET_INFO *cs;
if (!(cs= item->charset()))
cs= default_charset_info; // Should never happen for STR items
str->set_charset(cs);
}
} }
byte *in_string::get_value(Item *item) byte *in_string::get_value(Item *item)
{ {
return (byte*) item->val_str(&tmp); return (byte*) item->val_str(&tmp);
...@@ -1692,6 +1697,7 @@ longlong Item_func_isnull::val_int() ...@@ -1692,6 +1697,7 @@ longlong Item_func_isnull::val_int()
return args[0]->is_null() ? 1: 0; return args[0]->is_null() ? 1: 0;
} }
longlong Item_func_isnotnull::val_int() longlong Item_func_isnotnull::val_int()
{ {
return args[0]->is_null() ? 0 : 1; return args[0]->is_null() ? 0 : 1;
...@@ -1713,9 +1719,6 @@ longlong Item_func_like::val_int() ...@@ -1713,9 +1719,6 @@ longlong Item_func_like::val_int()
return 0; return 0;
} }
null_value=0; null_value=0;
if ((res->charset()->state & MY_CS_BINSORT) ||
(res2->charset()->state & MY_CS_BINSORT))
set_charset(&my_charset_bin);
if (canDoTurboBM) if (canDoTurboBM)
return turboBM_matches(res->ptr(), res->length()) ? 1 : 0; return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
return my_wildcmp(charset(), return my_wildcmp(charset(),
...@@ -1748,10 +1751,19 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) ...@@ -1748,10 +1751,19 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
return 1; return 1;
/* /*
TODO--we could do it for non-const, but we'd have to Comparision is by default done according to character set of LIKE
recompute the tables for each row--probably not worth it. */
if (binary_cmp)
set_charset(&my_charset_bin);
else
set_charset(args[1]->charset());
/*
We could also do boyer-more for non-const items, but as we would have to
recompute the tables for each row it's not worth it.
*/ */
if (args[1]->const_item() && !(specialflag & SPECIAL_NO_NEW_FUNC)) if (args[1]->const_item() && !use_strnxfrm(charset()) &&
!(specialflag & SPECIAL_NO_NEW_FUNC))
{ {
String* res2 = args[1]->val_str(&tmp_value2); String* res2 = args[1]->val_str(&tmp_value2);
if (!res2) if (!res2)
......
...@@ -2083,7 +2083,8 @@ longlong ...@@ -2083,7 +2083,8 @@ longlong
Item_func_set_user_var::val_int() Item_func_set_user_var::val_int()
{ {
longlong value=args[0]->val_int(); longlong value=args[0]->val_int();
update_hash((void*) &value,sizeof(longlong),INT_RESULT, default_charset_info); update_hash((void*) &value, sizeof(longlong), INT_RESULT,
default_charset_info);
return value; return value;
} }
...@@ -2092,9 +2093,10 @@ Item_func_set_user_var::val_str(String *str) ...@@ -2092,9 +2093,10 @@ Item_func_set_user_var::val_str(String *str)
{ {
String *res=args[0]->val_str(str); String *res=args[0]->val_str(str);
if (!res) // Null value if (!res) // Null value
update_hash((void*) 0, 0, STRING_RESULT, default_charset_info); update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin);
else else
update_hash(res->c_ptr(),res->length()+1,STRING_RESULT,res->charset()); update_hash((void*) res->ptr(), res->length(), STRING_RESULT,
res->charset());
return res; return res;
} }
...@@ -2129,13 +2131,13 @@ Item_func_get_user_var::val_str(String *str) ...@@ -2129,13 +2131,13 @@ Item_func_get_user_var::val_str(String *str)
return NULL; return NULL;
switch (entry->type) { switch (entry->type) {
case REAL_RESULT: case REAL_RESULT:
str->set(*(double*) entry->value,decimals,thd_charset()); str->set(*(double*) entry->value,decimals, &my_charset_bin);
break; break;
case INT_RESULT: case INT_RESULT:
str->set(*(longlong*) entry->value,thd_charset()); str->set(*(longlong*) entry->value, &my_charset_bin);
break; break;
case STRING_RESULT: case STRING_RESULT:
if (str->copy(entry->value, entry->length-1, entry->var_charset)) if (str->copy(entry->value, entry->length, entry->var_charset))
{ {
null_value=1; null_value=1;
return NULL; return NULL;
...@@ -2191,8 +2193,6 @@ longlong Item_func_get_user_var::val_int() ...@@ -2191,8 +2193,6 @@ longlong Item_func_get_user_var::val_int()
return LL(0); // Impossible return LL(0); // Impossible
} }
/* From sql_parse.cc */
extern bool is_update_query(enum enum_sql_command command);
void Item_func_get_user_var::fix_length_and_dec() void Item_func_get_user_var::fix_length_and_dec()
{ {
...@@ -2207,13 +2207,15 @@ void Item_func_get_user_var::fix_length_and_dec() ...@@ -2207,13 +2207,15 @@ void Item_func_get_user_var::fix_length_and_dec()
if (opt_bin_log && is_update_query(thd->lex.sql_command) && if (opt_bin_log && is_update_query(thd->lex.sql_command) &&
var_entry->used_query_id != thd->query_id) var_entry->used_query_id != thd->query_id)
{ {
uint size;
/* /*
First we need to store value of var_entry, when the next situation appers: First we need to store value of var_entry, when the next situation
appers:
> set @a:=1; > set @a:=1;
> insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1); > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
We have to write to binlog value @a= 1; We have to write to binlog value @a= 1;
*/ */
uint size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length; size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size))) if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size)))
goto err; goto err;
...@@ -2240,6 +2242,7 @@ void Item_func_get_user_var::fix_length_and_dec() ...@@ -2240,6 +2242,7 @@ void Item_func_get_user_var::fix_length_and_dec()
} }
} }
return; return;
err: err:
thd->fatal_error(); thd->fatal_error();
return; return;
...@@ -2247,7 +2250,9 @@ err: ...@@ -2247,7 +2250,9 @@ err:
bool Item_func_get_user_var::const_item() const bool Item_func_get_user_var::const_item() const
{ return var_entry && current_thd->query_id != var_entry->update_query_id; } {
return var_entry && current_thd->query_id != var_entry->update_query_id;
}
enum Item_result Item_func_get_user_var::result_type() const enum Item_result Item_func_get_user_var::result_type() const
...@@ -2275,14 +2280,9 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const ...@@ -2275,14 +2280,9 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
if (this == item) if (this == item)
return 1; // Same item is same. return 1; // Same item is same.
/* Check if other type is also a get_user_var() object */ /* Check if other type is also a get_user_var() object */
#ifdef FIX_THIS
if (item->eq == &Item_func_get_user_var::eq)
return 0;
#else
if (item->type() != FUNC_ITEM || if (item->type() != FUNC_ITEM ||
((Item_func*) item)->func_name() != func_name()) ((Item_func*) item)->func_name() != func_name())
return 0; return 0;
#endif
Item_func_get_user_var *other=(Item_func_get_user_var*) item; Item_func_get_user_var *other=(Item_func_get_user_var*) item;
return (name.length == other->name.length && return (name.length == other->name.length &&
!memcmp(name.str, other->name.str, name.length)); !memcmp(name.str, other->name.str, name.length));
......
...@@ -1899,19 +1899,10 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -1899,19 +1899,10 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
#endif #endif
/***************************************************************************** /****************************************************************************
*****************************************************************************
Rand_log_event methods Rand_log_event methods
****************************************************************************/
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Rand_log_event::pack_info()
****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Rand_log_event::pack_info(Protocol *protocol) void Rand_log_event::pack_info(Protocol *protocol)
{ {
...@@ -1924,11 +1915,7 @@ void Rand_log_event::pack_info(Protocol *protocol) ...@@ -1924,11 +1915,7 @@ void Rand_log_event::pack_info(Protocol *protocol)
} }
#endif #endif
/*****************************************************************************
Rand_log_event::Rand_log_event()
****************************************************************************/
Rand_log_event::Rand_log_event(const char* buf, bool old_format) Rand_log_event::Rand_log_event(const char* buf, bool old_format)
:Log_event(buf, old_format) :Log_event(buf, old_format)
{ {
...@@ -1937,11 +1924,7 @@ Rand_log_event::Rand_log_event(const char* buf, bool old_format) ...@@ -1937,11 +1924,7 @@ Rand_log_event::Rand_log_event(const char* buf, bool old_format)
seed2 = uint8korr(buf+RAND_SEED2_OFFSET); seed2 = uint8korr(buf+RAND_SEED2_OFFSET);
} }
/*****************************************************************************
Rand_log_event::write_data()
****************************************************************************/
int Rand_log_event::write_data(IO_CACHE* file) int Rand_log_event::write_data(IO_CACHE* file)
{ {
char buf[16]; char buf[16];
...@@ -1950,11 +1933,7 @@ int Rand_log_event::write_data(IO_CACHE* file) ...@@ -1950,11 +1933,7 @@ int Rand_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, (byte*) buf, sizeof(buf)); return my_b_safe_write(file, (byte*) buf, sizeof(buf));
} }
/*****************************************************************************
Rand_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT #ifdef MYSQL_CLIENT
void Rand_log_event::print(FILE* file, bool short_form, char* last_db) void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
{ {
...@@ -1970,11 +1949,7 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db) ...@@ -1970,11 +1949,7 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
} }
#endif // MYSQL_CLIENT #endif // MYSQL_CLIENT
/*****************************************************************************
Rand_log_event::exec_event()
****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Rand_log_event::exec_event(struct st_relay_log_info* rli) int Rand_log_event::exec_event(struct st_relay_log_info* rli)
{ {
...@@ -1986,19 +1961,10 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -1986,19 +1961,10 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
/***************************************************************************** /***************************************************************************
*****************************************************************************
User_var_log_event methods User_var_log_event methods
***************************************************************************/
*****************************************************************************
****************************************************************************/
/*****************************************************************************
User_var_log_event::pack_info()
****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void User_var_log_event::pack_info(Protocol* protocol) void User_var_log_event::pack_info(Protocol* protocol)
{ {
...@@ -2019,7 +1985,7 @@ void User_var_log_event::pack_info(Protocol* protocol) ...@@ -2019,7 +1985,7 @@ void User_var_log_event::pack_info(Protocol* protocol)
double real_val; double real_val;
float8get(real_val, val); float8get(real_val, val);
buf= my_malloc(val_offset + FLOATING_POINT_BUFFER, MYF(MY_WME)); buf= my_malloc(val_offset + FLOATING_POINT_BUFFER, MYF(MY_WME));
event_len += my_sprintf(buf + val_offset, event_len+= my_sprintf(buf + val_offset,
(buf + val_offset, "%.14g", real_val)); (buf + val_offset, "%.14g", real_val));
break; break;
case INT_RESULT: case INT_RESULT:
...@@ -2032,11 +1998,11 @@ void User_var_log_event::pack_info(Protocol* protocol) ...@@ -2032,11 +1998,11 @@ void User_var_log_event::pack_info(Protocol* protocol)
only. But be carefull this is may be incorrect in other cases as only. But be carefull this is may be incorrect in other cases as
string may contain \ and '. string may contain \ and '.
*/ */
buf= my_malloc(val_offset + 2 + val_len, MYF(MY_WME)); event_len= val_offset + 2 + val_len;
buf= my_malloc(event_len, MYF(MY_WME));
buf[val_offset]= '\''; buf[val_offset]= '\'';
memcpy(buf + val_offset + 1, val, val_len); memcpy(buf + val_offset + 1, val, val_len);
buf[val_offset + val_len]= '\''; buf[val_offset + val_len + 1]= '\'';
event_len= val_offset + 1 + val_len;
break; break;
case ROW_RESULT: case ROW_RESULT:
DBUG_ASSERT(1); DBUG_ASSERT(1);
...@@ -2050,18 +2016,16 @@ void User_var_log_event::pack_info(Protocol* protocol) ...@@ -2050,18 +2016,16 @@ void User_var_log_event::pack_info(Protocol* protocol)
my_free(buf, MYF(MY_ALLOW_ZERO_PTR)); my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
/*****************************************************************************
User_var_log_event::User_var_log_event()
****************************************************************************/
User_var_log_event::User_var_log_event(const char* buf, bool old_format) User_var_log_event::User_var_log_event(const char* buf, bool old_format)
:Log_event(buf, old_format) :Log_event(buf, old_format)
{ {
buf+= (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; buf+= (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
name_len= uint4korr(buf); name_len= uint4korr(buf);
name= (char *) buf + UV_NAME_LEN_SIZE; name= (char *) buf + UV_NAME_LEN_SIZE;
is_null= buf[UV_NAME_LEN_SIZE + name_len]; buf+= UV_NAME_LEN_SIZE + name_len;
is_null= (bool) *buf;
if (is_null) if (is_null)
{ {
type= STRING_RESULT; type= STRING_RESULT;
...@@ -2070,22 +2034,16 @@ User_var_log_event::User_var_log_event(const char* buf, bool old_format) ...@@ -2070,22 +2034,16 @@ User_var_log_event::User_var_log_event(const char* buf, bool old_format)
} }
else else
{ {
type= (Item_result) buf[UV_VAL_IS_NULL + UV_NAME_LEN_SIZE + name_len]; type= (Item_result) buf[UV_VAL_IS_NULL];
charset_number= uint4korr(buf + UV_NAME_LEN_SIZE + name_len + charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE); val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
val_len= uint4korr(buf + UV_NAME_LEN_SIZE + name_len +
UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
UV_CHARSET_NUMBER_SIZE); UV_CHARSET_NUMBER_SIZE);
val= (char *) buf + UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL + val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE; UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE);
} }
} }
/*****************************************************************************
User_var_log_event::write_data()
****************************************************************************/
int User_var_log_event::write_data(IO_CACHE* file) int User_var_log_event::write_data(IO_CACHE* file)
{ {
char buf[UV_NAME_LEN_SIZE]; char buf[UV_NAME_LEN_SIZE];
...@@ -2224,19 +2182,9 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -2224,19 +2182,9 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
/***************************************************************************** /****************************************************************************
*****************************************************************************
Slave_log_event methods Slave_log_event methods
****************************************************************************/
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Slave_log_event::pack_info()
****************************************************************************/
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
...@@ -2255,11 +2203,7 @@ void Slave_log_event::pack_info(Protocol *protocol) ...@@ -2255,11 +2203,7 @@ void Slave_log_event::pack_info(Protocol *protocol)
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
/*****************************************************************************
Slave_log_event::Slave_log_event()
****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
Slave_log_event::Slave_log_event(THD* thd_arg, Slave_log_event::Slave_log_event(THD* thd_arg,
struct st_relay_log_info* rli) struct st_relay_log_info* rli)
...@@ -2296,21 +2240,13 @@ Slave_log_event::Slave_log_event(THD* thd_arg, ...@@ -2296,21 +2240,13 @@ Slave_log_event::Slave_log_event(THD* thd_arg,
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
/*****************************************************************************
Slave_log_event dtor
****************************************************************************/
Slave_log_event::~Slave_log_event() Slave_log_event::~Slave_log_event()
{ {
my_free(mem_pool, MYF(MY_ALLOW_ZERO_PTR)); my_free(mem_pool, MYF(MY_ALLOW_ZERO_PTR));
} }
/*****************************************************************************
Slave_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT #ifdef MYSQL_CLIENT
void Slave_log_event::print(FILE* file, bool short_form, char* last_db) void Slave_log_event::print(FILE* file, bool short_form, char* last_db)
{ {
...@@ -2325,21 +2261,13 @@ master_log: '%s' master_pos: %s\n", ...@@ -2325,21 +2261,13 @@ master_log: '%s' master_pos: %s\n",
} }
#endif // MYSQL_CLIENT #endif // MYSQL_CLIENT
/*****************************************************************************
Slave_log_event::get_data_size()
****************************************************************************/
int Slave_log_event::get_data_size() int Slave_log_event::get_data_size()
{ {
return master_host_len + master_log_len + 1 + SL_MASTER_HOST_OFFSET; return master_host_len + master_log_len + 1 + SL_MASTER_HOST_OFFSET;
} }
/*****************************************************************************
Slave_log_event::write_data()
****************************************************************************/
int Slave_log_event::write_data(IO_CACHE* file) int Slave_log_event::write_data(IO_CACHE* file)
{ {
int8store(mem_pool + SL_MASTER_POS_OFFSET, master_pos); int8store(mem_pool + SL_MASTER_POS_OFFSET, master_pos);
...@@ -2348,11 +2276,7 @@ int Slave_log_event::write_data(IO_CACHE* file) ...@@ -2348,11 +2276,7 @@ int Slave_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, (byte*)mem_pool, get_data_size()); return my_b_safe_write(file, (byte*)mem_pool, get_data_size());
} }
/*****************************************************************************
Slave_log_event::init_from_mem_pool()
****************************************************************************/
void Slave_log_event::init_from_mem_pool(int data_size) void Slave_log_event::init_from_mem_pool(int data_size)
{ {
master_pos = uint8korr(mem_pool + SL_MASTER_POS_OFFSET); master_pos = uint8korr(mem_pool + SL_MASTER_POS_OFFSET);
...@@ -2369,11 +2293,7 @@ void Slave_log_event::init_from_mem_pool(int data_size) ...@@ -2369,11 +2293,7 @@ void Slave_log_event::init_from_mem_pool(int data_size)
master_log_len = strlen(master_log); master_log_len = strlen(master_log);
} }
/*****************************************************************************
Slave_log_event::Slave_log_event()
****************************************************************************/
Slave_log_event::Slave_log_event(const char* buf, int event_len) Slave_log_event::Slave_log_event(const char* buf, int event_len)
:Log_event(buf,0),mem_pool(0),master_host(0) :Log_event(buf,0),mem_pool(0),master_host(0)
{ {
...@@ -2387,11 +2307,7 @@ Slave_log_event::Slave_log_event(const char* buf, int event_len) ...@@ -2387,11 +2307,7 @@ Slave_log_event::Slave_log_event(const char* buf, int event_len)
init_from_mem_pool(event_len); init_from_mem_pool(event_len);
} }
/*****************************************************************************
Slave_log_event::exec_event()
****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
int Slave_log_event::exec_event(struct st_relay_log_info* rli) int Slave_log_event::exec_event(struct st_relay_log_info* rli)
{ {
......
...@@ -635,7 +635,7 @@ public: ...@@ -635,7 +635,7 @@ public:
ulong val_len; ulong val_len;
Item_result type; Item_result type;
uint charset_number; uint charset_number;
byte is_null; bool is_null;
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg, User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
char *val_arg, ulong val_len_arg, Item_result type_arg, char *val_arg, ulong val_len_arg, Item_result type_arg,
......
...@@ -830,6 +830,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -830,6 +830,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
} }
} }
else else
{
/* /*
Real scramble is only sent to old servers. This can be blocked Real scramble is only sent to old servers. This can be blocked
by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
...@@ -837,6 +838,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -837,6 +838,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
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))
{ {
......
...@@ -346,6 +346,7 @@ int quick_rm_table(enum db_type base,const char *db, ...@@ -346,6 +346,7 @@ int quick_rm_table(enum db_type base,const char *db,
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
bool mysql_change_db(THD *thd,const char *name); bool mysql_change_db(THD *thd,const char *name);
void mysql_parse(THD *thd,char *inBuf,uint length); void mysql_parse(THD *thd,char *inBuf,uint length);
bool is_update_query(enum enum_sql_command command);
void free_items(Item *item); void free_items(Item *item);
bool alloc_query(THD *thd, char *packet, ulong packet_length); bool alloc_query(THD *thd, char *packet, ulong packet_length);
void mysql_init_select(LEX *lex); void mysql_init_select(LEX *lex);
......
...@@ -295,11 +295,12 @@ void ...@@ -295,11 +295,12 @@ void
send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
{ {
NET *net= &thd->net; NET *net= &thd->net;
if (net->no_send_ok || !net->vio) // hack for re-parsing queries
return;
char buff[MYSQL_ERRMSG_SIZE+10],*pos; char buff[MYSQL_ERRMSG_SIZE+10],*pos;
DBUG_ENTER("send_ok"); DBUG_ENTER("send_ok");
if (net->no_send_ok || !net->vio) // hack for re-parsing queries
DBUG_VOID_RETURN;
buff[0]=0; // No fields buff[0]=0; // No fields
pos=net_store_length(buff+1,(ulonglong) affected_rows); pos=net_store_length(buff+1,(ulonglong) affected_rows);
pos=net_store_length(pos, (ulonglong) id); pos=net_store_length(pos, (ulonglong) id);
......
...@@ -485,7 +485,7 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble) ...@@ -485,7 +485,7 @@ 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;
...@@ -494,14 +494,13 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble) ...@@ -494,14 +494,13 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
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,
const char *password,const char *message,char **priv_user, const char *password,const char *message,char **priv_user,
bool old_ver, USER_RESOURCES *mqh, char *prepared_scramble, bool old_ver, USER_RESOURCES *mqh, char *prepared_scramble,
uint *cur_priv_version,ACL_USER** hint_user) uint *cur_priv_version, ACL_USER **cached_user)
{ {
ulong user_access=NO_ACCESS; ulong user_access=NO_ACCESS;
*priv_user= (char*) user; *priv_user= (char*) user;
bool password_correct= 0; bool password_correct= 0;
int stage= (*hint_user != NULL); /* NULL passed as first stage */ int stage= (*cached_user != NULL); /* NULL passed as first stage */
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));
...@@ -512,7 +511,6 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -512,7 +511,6 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
} }
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
...@@ -520,9 +518,10 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -520,9 +518,10 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
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= *cached_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*);
...@@ -531,28 +530,28 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -531,28 +530,28 @@ 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; *cached_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 ||
(acl_user->password && *password))
{
/* 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 if (!acl_user->password || !*password)
{
*cached_user= 0; // Impossible to connect
}
else
{ {
/* New version password is checked differently */ /* New version password is checked differently */
if (acl_user->pversion) if (acl_user->pversion)
...@@ -580,7 +579,6 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ...@@ -580,7 +579,6 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
} }
} }
} }
}
/* 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)
...@@ -1120,7 +1118,10 @@ bool change_password(THD *thd, const char *host, const char *user, ...@@ -1120,7 +1118,10 @@ bool change_password(THD *thd, const char *host, const char *user,
if (check_change_password(thd, host, user)) if (check_change_password(thd, host, user))
DBUG_RETURN(1); DBUG_RETURN(1);
/* 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)
......
...@@ -225,7 +225,7 @@ public: ...@@ -225,7 +225,7 @@ public:
return (void*) sql_calloc((uint) size); return (void*) sql_calloc((uint) size);
} }
static void operator delete(void *ptr,size_t size) {} static void operator delete(void *ptr,size_t size) {}
st_select_lex_node() {} st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {}
virtual ~st_select_lex_node() {} virtual ~st_select_lex_node() {}
inline st_select_lex_node* get_master() { return master; } inline st_select_lex_node* get_master() { return master; }
virtual void init_query(); virtual void init_query();
......
...@@ -181,32 +181,57 @@ end: ...@@ -181,32 +181,57 @@ end:
/* /*
Check if user is ok Check if user is ok
Updates:
thd->user, thd->master_access, thd->priv_user, thd->db, thd->db_access SYNOPSIS
check_user()
thd Thread handle
command Command for connection (for log)
user Name of user trying to connect
passwd Scrambled password sent from client
db Database to connect to
check_count If set to 1, don't allow too many connection
simple_connect If 1 then client is of old type and we should connect
using the old method (no challange)
do_send_error Set to 1 if we should send error to user
prepared_scramble Buffer to store hash password of new connection
had_password Set to 1 if the user gave a password
cur_priv_version Check flag to know if someone flushed the privileges
since last code
hint_user Pointer used by acl_getroot() to remmeber user for
next call
RETURN
0 ok
thd->user, thd->master_access, thd->priv_user, thd->db and
thd->db_access are updated
1 Access denied; Error sent to client
-1 If do_send_error == 1: Failed connect, error sent to client
If do_send_error == 0: Prepare for stage of connect
*/ */
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 simple_connect, bool do_send_error, bool simple_connect, bool do_send_error,
char *crypted_scramble, bool had_password, char *prepared_scramble, bool had_password,
uint *cur_priv_version, ACL_USER** hint_user) uint *cur_priv_version, ACL_USER** hint_user)
{ {
thd->db=0; thd->db=0;
thd->db_length=0; thd->db_length=0;
USER_RESOURCES ur; USER_RESOURCES ur;
DBUG_ENTER("check_user");
/* We shall avoid dupplicate user allocations here */ /* We shall avoid dupplicate user allocations here */
if (!thd->user && !(thd->user = my_strdup(user, MYF(0)))) if (!thd->user && !(thd->user = my_strdup(user, MYF(0))))
{ {
send_error(thd,ER_OUT_OF_RESOURCES); send_error(thd,ER_OUT_OF_RESOURCES);
return 1; DBUG_RETURN(1);
} }
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user, thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
passwd, thd->scramble, &thd->priv_user, passwd, thd->scramble, &thd->priv_user,
(protocol_version == 9 || (protocol_version == 9 ||
!(thd->client_capabilities & !(thd->client_capabilities &
CLIENT_LONG_PASSWORD)), CLIENT_LONG_PASSWORD)),
&ur,crypted_scramble, &ur,prepared_scramble,
cur_priv_version,hint_user); cur_priv_version,hint_user);
DBUG_PRINT("info", DBUG_PRINT("info",
...@@ -222,8 +247,9 @@ static int check_user(THD *thd,enum_server_command command, const char *user, ...@@ -222,8 +247,9 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
*/ */
if (thd->master_access & NO_ACCESS) if (thd->master_access & NO_ACCESS)
{ {
if (do_send_error) if (do_send_error || !had_password || !*hint_user)
{ {
DBUG_PRINT("info",("Access denied"));
/* /*
Old client should get nicer error message if password version is Old client should get nicer error message if password version is
not supported not supported
...@@ -244,10 +270,10 @@ static int check_user(THD *thd,enum_server_command command, const char *user, ...@@ -244,10 +270,10 @@ 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 DBUG_RETURN(1); // Error already given
} }
else DBUG_PRINT("info",("Prepare for second part of handshake"));
return(-1); // do not report error in special handshake DBUG_RETURN(-1); // no report error in special handshake
} }
if (check_count) if (check_count)
...@@ -259,7 +285,7 @@ static int check_user(THD *thd,enum_server_command command, const char *user, ...@@ -259,7 +285,7 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
if (tmp) if (tmp)
{ // Too many connections { // Too many connections
send_error(thd, ER_CON_COUNT_ERROR); send_error(thd, ER_CON_COUNT_ERROR);
return(1); DBUG_RETURN(1);
} }
} }
mysql_log.write(thd,command, mysql_log.write(thd,command,
...@@ -273,21 +299,20 @@ static int check_user(THD *thd,enum_server_command command, const char *user, ...@@ -273,21 +299,20 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
/* Don't allow user to connect if he has done too many queries */ /* Don't allow user to connect if he has done too many queries */
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; DBUG_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; DBUG_RETURN(1);
if (db && db[0]) if (db && db[0])
{ {
bool error=test(mysql_change_db(thd,db)); int 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; DBUG_RETURN(error);
} }
else
send_ok(thd); // Ready to handle questions send_ok(thd); // Ready to handle questions
return 0; // ok DBUG_RETURN(0); // ok
} }
...@@ -492,24 +517,35 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) ...@@ -492,24 +517,35 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
/* /*
Check connnetion and get priviliges Check connnectionn and get priviliges
Returns 0 on ok, -1 < if error is given > 0 on error.
SYNOPSIS
check_connections
thd Thread handle
RETURN
0 ok
-1 Error, which is sent to user
> 0 Error code (not sent to user)
*/ */
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
static int static int
check_connections(THD *thd) check_connections(THD *thd)
{ {
int res;
uint connect_errors=0; uint connect_errors=0;
uint cur_priv_version;
bool using_password;
NET *net= &thd->net; NET *net= &thd->net;
char *end, *user, *passwd, *db; char *end, *user, *passwd, *db;
char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */ char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */
ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */ ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */
uint cur_priv_version;
DBUG_PRINT("info",("New connection received on %s", DBUG_PRINT("info",("New connection received on %s",
vio_description(net->vio))); vio_description(net->vio)));
/* Remove warning from valgrind. TODO: Fix it in password.c */ /* Remove warning from valgrind. TODO: Fix it in password.c */
bzero((char*) prepared_scramble, sizeof(prepared_scramble)); bzero((char*) &prepared_scramble[0], sizeof(prepared_scramble));
if (!thd->host) // If TCP/IP connection if (!thd->host) // If TCP/IP connection
{ {
char ip[30]; char ip[30];
...@@ -648,11 +684,12 @@ check_connections(THD *thd) ...@@ -648,11 +684,12 @@ check_connections(THD *thd)
user= end; user= end;
passwd= strend(user)+1; passwd= strend(user)+1;
db=0; db=0;
using_password= test(passwd[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 (using_password && strlen(passwd) != SCRAMBLE_LENGTH)
return ER_HANDSHAKE_ERROR; return ER_HANDSHAKE_ERROR;
if (thd->client_capabilities & CLIENT_INTERACTIVE) if (thd->client_capabilities & CLIENT_INTERACTIVE)
...@@ -665,24 +702,23 @@ check_connections(THD *thd) ...@@ -665,24 +702,23 @@ check_connections(THD *thd)
/* 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 */
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 ((res=check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect,
simple_connect, prepared_scramble, using_password, simple_connect, prepared_scramble, using_password,
&cur_priv_version, &cur_priv_version,
&cached_user)<0) &cached_user)) < 0)
{ {
/* 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]= tmp_db[0]= 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;
DBUG_PRINT("info",("password challenge"));
tmp_user[0]= tmp_db[0]= 0;
if (user) if (user)
strmake(tmp_user,user,USERNAME_LENGTH); strmake(tmp_user,user,USERNAME_LENGTH);
if (db) if (db)
...@@ -714,10 +750,13 @@ check_connections(THD *thd) ...@@ -714,10 +750,13 @@ check_connections(THD *thd)
&cached_user)) &cached_user))
return -1; return -1;
} }
else if (res)
return -1; // Error sent from check_user()
thd->password=using_password; thd->password=using_password;
return 0; return 0;
} }
pthread_handler_decl(handle_one_connection,arg) pthread_handler_decl(handle_one_connection,arg)
{ {
THD *thd=(THD*) arg; THD *thd=(THD*) arg;
...@@ -1014,14 +1053,15 @@ bool do_command(THD *thd) ...@@ -1014,14 +1053,15 @@ bool do_command(THD *thd)
net->read_timeout=old_timeout; // restore it net->read_timeout=old_timeout; // restore it
DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length)); DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
} }
#endif /* EMBEDDED_LIBRARY */ #endif /* EMBEDDED_LIBRARY */
bool dispatch_command(enum enum_server_command command, THD *thd, bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length) char* packet, uint packet_length)
{ {
int res;
NET *net= &thd->net; NET *net= &thd->net;
bool error=0; bool error= 0;
/* /*
Commands which will always take a long time should be marked with Commands which will always take a long time should be marked with
this so that they will not get logged to the slow query log this so that they will not get logged to the slow query log
...@@ -1098,6 +1138,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1098,6 +1138,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
uint cur_priv_version; /* Cached grant version */ uint cur_priv_version; /* Cached grant version */
ulong pkt_len=0; /* Length of reply packet */ ulong pkt_len=0; /* Length of reply packet */
bzero((char*) prepared_scramble, sizeof(prepared_scramble));
/* 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)
...@@ -1124,11 +1165,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1124,11 +1165,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
Check user permissions. If password failure we'll get scramble back Check user permissions. If password failure we'll get scramble back
Do not retry if we already have sent error (result>0) 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 ((res=check_user(thd,COM_CHANGE_USER, user, passwd, db, 0,
simple_connect, prepared_scramble, using_password, &cur_priv_version, simple_connect, simple_connect, prepared_scramble,
&cached_user) < 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 */
...@@ -1149,16 +1190,18 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1149,16 +1190,18 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
goto restore_user_err; goto restore_user_err;
/* 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)
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_CHANGE_USER, tmp_user, (char*) net->read_pos, if (check_user(thd,COM_CHANGE_USER, tmp_user, (char*) net->read_pos,
tmp_db, 0, 0, 1, prepared_scramble, using_password, tmp_db, 0, 0, 1, prepared_scramble, using_password,
&cur_priv_version, &cur_priv_version, &cached_user))
&cached_user))
goto restore_user; goto restore_user;
} }
else if (res)
goto restore_user;
/* Finally we've authenticated new user */ /* Finally we've authenticated new user */
if (max_connections && save_uc) if (max_connections && save_uc)
decrease_user_connections(save_uc); decrease_user_connections(save_uc);
...@@ -1168,10 +1211,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1168,10 +1211,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
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);
thd->master_access=save_master_access; thd->master_access=save_master_access;
thd->db_access=save_db_access; thd->db_access=save_db_access;
......
...@@ -639,9 +639,11 @@ bool str_to_time(const char *str,uint length,TIME *l_time) ...@@ -639,9 +639,11 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
value=value*10L + (long) (*str - '0'); value=value*10L + (long) (*str - '0');
if (*str == ' ') /* Move to last space */
if (str != end && *str == ' ')
{ {
while (++str != end && str[0] == ' ') ; while (++str != end && str[0] == ' ')
{}
str--; str--;
} }
......
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